feat(adminui): tag-path completion inside ctx.GetTag/SetVirtualTag literals
This commit is contained in:
@@ -29,8 +29,13 @@ public sealed class ScriptAnalysisService
|
||||
OutputKind.DynamicallyLinkedLibrary, optimizationLevel: OptimizationLevel.Release,
|
||||
allowUnsafe: false, warningLevel: 4, nullableContextOptions: NullableContextOptions.Enable);
|
||||
|
||||
private readonly IScriptTagCatalog? _catalog;
|
||||
private readonly ILogger<ScriptAnalysisService>? _logger;
|
||||
public ScriptAnalysisService(ILogger<ScriptAnalysisService>? logger = null) => _logger = logger;
|
||||
public ScriptAnalysisService(IScriptTagCatalog? catalog = null, ILogger<ScriptAnalysisService>? logger = null)
|
||||
{
|
||||
_catalog = catalog;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
// Mirrors ScriptEvaluator's wrapper EXACTLY (usings from the sandbox + the
|
||||
// Run(ScriptGlobals<VirtualTagContext>) shape), except the analysis return type is
|
||||
@@ -154,7 +159,12 @@ public sealed class ScriptAnalysisService
|
||||
// position is the offset just AFTER the caret; -1 finds the token the caret sits at/just-after (e.g. the dot in "ctx.").
|
||||
var token = root.FindToken(Math.Max(0, position - 1));
|
||||
|
||||
// Task 6 inserts tag-path string-literal completion here (inside ctx.GetTag("…")/ctx.SetVirtualTag("…")).
|
||||
if (_catalog != null && TryGetTagPathLiteral(token, out var pathPrefix))
|
||||
{
|
||||
var paths = await _catalog.GetPathsAsync(pathPrefix, CancellationToken.None);
|
||||
return new CompletionsResponse(
|
||||
paths.Select(p => new CompletionItem(p, p, "tag path", "Field")).ToList());
|
||||
}
|
||||
|
||||
var dot = TryGetDotMembers(token, model);
|
||||
if (dot != null) return new CompletionsResponse(dot);
|
||||
@@ -188,6 +198,24 @@ public sealed class ScriptAnalysisService
|
||||
.Select(ToCompletionItem).Take(200).ToList();
|
||||
}
|
||||
|
||||
private static bool TryGetTagPathLiteral(SyntaxToken token, out string prefix)
|
||||
{
|
||||
prefix = "";
|
||||
var literal = token.Parent as LiteralExpressionSyntax
|
||||
?? token.GetPreviousToken().Parent as LiteralExpressionSyntax;
|
||||
if (literal is null || !literal.IsKind(SyntaxKind.StringLiteralExpression)) return false;
|
||||
if (literal.Parent is not ArgumentSyntax arg) return false;
|
||||
if (arg.Parent is not ArgumentListSyntax argList) return false;
|
||||
if (argList.Parent is not InvocationExpressionSyntax inv) return false;
|
||||
if (inv.Expression is not MemberAccessExpressionSyntax ma) return false;
|
||||
var method = ma.Name.Identifier.ValueText;
|
||||
if (method is not ("GetTag" or "SetVirtualTag")) return false;
|
||||
// only the FIRST argument is the path
|
||||
if (argList.Arguments.Count > 0 && argList.Arguments[0] != arg) return false;
|
||||
prefix = literal.Token.ValueText ?? "";
|
||||
return true;
|
||||
}
|
||||
|
||||
private static CompletionItem ToCompletionItem(ISymbol symbol)
|
||||
{
|
||||
var kind = symbol.Kind switch
|
||||
|
||||
Reference in New Issue
Block a user