Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: .dev.vars #298

Merged
merged 1 commit into from
Jan 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Compiler/Commands/BuildCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,15 @@

config.Validate();

using var host = CompilerHost.CompilerHostBuilder.Create()
using var host = CompilerHost.CompilerHostBuilder.Create(config.WorkingDirectory)
.WithDefaults()
#if !WASI_WASM_BUILD
.WithExtensions(config.Extensions)
#endif
.Build();

var compiler = new BebopCompiler(host);
Helpers.WriteHostInfo(host);
BebopSchema schema = default;
string? tempFilePath = null;
try
Expand All @@ -50,7 +51,7 @@
#if !WASI_WASM_BUILD
await standardInput.CopyToAsync(fs, cancellationToken);
#else
standardInput.CopyTo(fs);

Check warning on line 54 in Compiler/Commands/BuildCommand.cs

View workflow job for this annotation

GitHub Actions / build-compiler (ubuntu-22.04)

CopyTo synchronously blocks. Await CopyToAsync instead. (https://github.com/Microsoft/vs-threading/blob/master/doc/analyzers/VSTHRD103.md)
#endif

fs.Seek(0, SeekOrigin.Begin);
Expand Down
9 changes: 3 additions & 6 deletions Compiler/Commands/LanguageServerCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,13 @@
SetAction(HandleCommandAsync);
}

private async Task<int> HandleCommandAsync(ParseResult result, CancellationToken token)

Check warning on line 21 in Compiler/Commands/LanguageServerCommand.cs

View workflow job for this annotation

GitHub Actions / build-compiler (ubuntu-22.04)

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
{
#if !WASI_WASM_BUILD
Dictionary<string, string> extensions = [];
var config = result.GetValue<BebopConfig>(CliStrings.ConfigFlag);
if (config is not null)
{
extensions = config.Extensions;
}
using var host = CompilerHost.CompilerHostBuilder.Create().WithDefaultDecorators().WithExtensions(extensions).Build();
var config = result.GetValue<BebopConfig>(CliStrings.ConfigFlag)!;
extensions = config.Extensions;
using var host = CompilerHost.CompilerHostBuilder.Create(config.WorkingDirectory).WithDefaultDecorators().WithExtensions(extensions).Build();
await BebopLangServer.RunAsync(host, token);
#endif
return BebopCompiler.Ok;
Expand Down
3 changes: 2 additions & 1 deletion Compiler/Commands/WatchCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@ private async Task<int> HandleCommandAsync(ParseResult result, CancellationToken
{
var config = result.GetValue<BebopConfig>(CliStrings.ConfigFlag)!;
config.Validate();
using var host = CompilerHost.CompilerHostBuilder.Create()
using var host = CompilerHost.CompilerHostBuilder.Create(config.WorkingDirectory)
.WithDefaults()
#if !WASI_WASM_BUILD
.WithExtensions(config.Extensions)
#endif
.Build();

Helpers.WriteHostInfo(host);
var compiler = new BebopCompiler(host);
var watcher = new SchemaWatcher(config.WorkingDirectory, config, compiler);
return await watcher.StartAsync(token);
Expand Down
27 changes: 27 additions & 0 deletions Compiler/Helpers.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
using System;
using System.CommandLine;
using System.IO;
using System.Linq;
using Core;

#if WASI_WASM_BUILD
using Core.Exceptions;
#endif
using Core.Generators;
using Core.Logging;
using Core.Meta;
using Spectre.Console;

namespace Compiler;

Expand Down Expand Up @@ -84,6 +89,28 @@ public static void MergeConfig(ParseResult parseResults, BebopConfig config)
}
}

public static void WriteHostInfo(CompilerHost host)
{
if (host.Extensions.Any())
{
DiagnosticLogger.Instance.Error.MarkupLine("[yellow]Using extensions defined in bebop.json[/]");
DiagnosticLogger.Instance.Error.MarkupLine("[blue]- Extensions:[/]");
foreach (var extension in host.Extensions)
{
DiagnosticLogger.Instance.Error.MarkupLine($" - [white]{extension.Name}[/]: [green]{extension.Version}[/]");
}
}
if (host.EnvironmentVariableStore.DevVarsCount > 0)
{
DiagnosticLogger.Instance.Error.MarkupLine("[yellow]Using vars defined in .dev.vars[/]");
DiagnosticLogger.Instance.Error.MarkupLine("[blue]- Vars:[/]");
foreach (var name in host.EnvironmentVariableStore.DevVarNames)
{
DiagnosticLogger.Instance.Error.MarkupLine($" - [white]{name}[/]: [green](hidden)[/]");
}
}
}

public static int ProcessId
{
get
Expand Down
2 changes: 1 addition & 1 deletion Compiler/LangServer/Handlers/SemanticTokenHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public SemanticTokenHandler(

_tokenTypes = new Dictionary<TokenKind, SemanticTokenType>
{
{ TokenKind.ReadOnly, SemanticTokenType.Modifier },
{ TokenKind.Mut, SemanticTokenType.Keyword },
{ TokenKind.Array, SemanticTokenType.Keyword },
{ TokenKind.Enum, SemanticTokenType.Keyword },
{ TokenKind.Map, SemanticTokenType.Keyword },
Expand Down
17 changes: 12 additions & 5 deletions Core/CompilerHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@ public class CompilerHost : IDisposable
private readonly FrozenDictionary<string, DecoratorDefinition> _decorators;
private readonly FrozenDictionary<string, BaseGenerator> _generators;
private readonly ExtensionRuntime? _extensionRuntime;
private CompilerHost(FrozenDictionary<string, DecoratorDefinition> decorators, FrozenDictionary<string, BaseGenerator> generators, ExtensionRuntime? extensionRuntime)
private readonly EnvironmentVariableStore _environmentVariableStore;
private CompilerHost(FrozenDictionary<string, DecoratorDefinition> decorators, FrozenDictionary<string, BaseGenerator> generators, EnvironmentVariableStore environmentVariableStore, ExtensionRuntime? extensionRuntime)
{
_decorators = decorators;
_generators = generators;
_extensionRuntime = extensionRuntime;
_environmentVariableStore = environmentVariableStore;
}

public bool TryGetDecorator(string identifier, [NotNullWhen(true)] out DecoratorDefinition? decorator)
Expand All @@ -40,6 +42,8 @@ public bool TryGetGenerator(string alias, [NotNullWhen(true)] out BaseGenerator?
return _generators.TryGetValue(alias, out generator);
}

public EnvironmentVariableStore EnvironmentVariableStore => _environmentVariableStore;

public IEnumerable<(string Alias, string Name)> Generators
{
get
Expand Down Expand Up @@ -87,16 +91,19 @@ public class CompilerHostBuilder
private ExtensionRuntime? _extensionRuntime;
private readonly Dictionary<string, DecoratorDefinition> _decorators;
private readonly Dictionary<string, BaseGenerator> _generators;
private readonly EnvironmentVariableStore _environmentVariableStore;

private CompilerHostBuilder()
private CompilerHostBuilder(string workingDirectory)
{

_decorators = [];
_generators = [];
_environmentVariableStore = new EnvironmentVariableStore(workingDirectory);
}

public static CompilerHostBuilder Create()
public static CompilerHostBuilder Create(string workingDirectory)
{
return new CompilerHostBuilder();
return new CompilerHostBuilder(workingDirectory);
}

public CompilerHost Build()
Expand All @@ -106,7 +113,7 @@ public CompilerHost Build()
throw new CompilerException("A compiler host has already been built.");
}
_isBuilt = true;
return new CompilerHost(_decorators.ToFrozenDictionary(), _generators.ToFrozenDictionary(), _extensionRuntime);
return new CompilerHost(_decorators.ToFrozenDictionary(), _generators.ToFrozenDictionary(), _environmentVariableStore, _extensionRuntime);
}

public CompilerHostBuilder WithDefaults()
Expand Down
69 changes: 69 additions & 0 deletions Core/EnvironmentVariableStore.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using System;
using System.Collections.Frozen;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security;
using System.Text.RegularExpressions;
using Core.Exceptions;
using Core.Lexer.Tokenization.Models;
namespace Core;
public sealed partial class EnvironmentVariableStore
{
private readonly FrozenDictionary<string, string> _devVariables;

public EnvironmentVariableStore(string workingDirectory)
{
var devEnvFilePath = Path.Combine(workingDirectory, ".dev.vars");
if (File.Exists(devEnvFilePath))
{
_devVariables = File.ReadAllLines(devEnvFilePath)
.Select(line => line.Split('=', 2))
.Where(parts => parts.Length == 2)
.ToDictionary(parts => parts[0], parts => parts[1])
.ToFrozenDictionary();
}
else
{
_devVariables = FrozenDictionary<string, string>.Empty;
}
}
public int DevVarsCount => _devVariables.Count;
public IEnumerable<string> DevVarNames => _devVariables.Keys;

public string Replace(string input, List<SpanException> errors, Span span)
{
return TemplateRegex().Replace(input, match =>
{
string varName = match.Groups[1].Value;
string? envVar = null;
try
{
envVar = Get(varName);
if (string.IsNullOrEmpty(envVar))
{
errors.Add(new EnvironmentVariableNotFoundException(span, $"String substitution failed: environment variable '{varName}' was not found."));
return string.Empty;
}
return envVar.Trim();
}
catch (SecurityException)
{
errors.Add(new EnvironmentVariableNotFoundException(span, $"String substitution failed: environment variable '{varName}' was not found."));
return string.Empty;
}
});
}

public string? Get(string variableName)
{
if (_devVariables.TryGetValue(variableName, out var value))
{
return value.Trim();
}
return Environment.GetEnvironmentVariable(variableName)?.Trim();
}

[GeneratedRegex(@"\$\{([^\}]+)\}")]
private static partial Regex TemplateRegex();
}
15 changes: 7 additions & 8 deletions Core/Exceptions/Exceptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,13 @@ public MissingValueForArgumentException(string identifier, string paramName, Spa
: base($"Decorator '{identifier}' is missing a value for parameter '{paramName}'.", span, 146, hint)
{ }
}
[Serializable]
public class EnvironmentVariableNotFoundException : SpanException
{
public EnvironmentVariableNotFoundException(Span span, string reason)
: base(reason, span, 147, severity: Severity.Error)
{ }
}



Expand All @@ -426,12 +433,4 @@ public DeprecatedFeatureWarning(Span span, string reason)
{ }
}

[Serializable]
public class EnvironmentVariableNotFoundException : SpanException
{
public EnvironmentVariableNotFoundException(Span span, string reason)
: base(reason, span, 202, severity: Severity.Warning)
{ }
}

}
40 changes: 0 additions & 40 deletions Core/Internal/EnvironmentVariableReplacer.cs

This file was deleted.

5 changes: 3 additions & 2 deletions Core/Parser/SchemaParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -486,10 +486,11 @@ private bool EatEnvironmentVariable([NotNullWhen(true)] out string? envValue)
Expect(TokenKind.CloseBrace);
try
{
envValue = EnvironmentVariableHelper.Get(envVar);
envValue = _compilerHost.EnvironmentVariableStore.Get(envVar);
if (string.IsNullOrEmpty(envValue))
{
_errors.Add(new EnvironmentVariableNotFoundException(Span.Combine(startSpan, CurrentToken.Span), $"String substitution failed: environment variable '{envVar}' was not found."));
envValue = string.Empty;
}
return true;
}
Expand Down Expand Up @@ -539,7 +540,7 @@ private Literal ParseLiteral(TypeBase type)
// the string has possible template variables
if (str.Contains('$'))
{
str = EnvironmentVariableHelper.Replace(str, _errors, token.Span);
str = _compilerHost.EnvironmentVariableStore.Replace(str, _errors, token.Span);
}
return new StringLiteral(st, token.Span, str);
case ScalarType st when st.BaseType == BaseType.Guid:
Expand Down
Loading