in src/Bicep.LangServer/Handlers/BicepDefinitionHandler.cs [107:175]
private LocationOrLocationLinks HandleUnboundSymbolLocation(DefinitionParams request, CompilationContext context)
{
int offset = PositionHelper.GetOffset(context.LineStarts, request.Position);
var matchingNodes = SyntaxMatcher.FindNodesMatchingOffset(context.Compilation.SourceFileGrouping.EntryPoint.ProgramSyntax, offset);
{ // Definition handler for a non symbol bound to implement module path goto.
// try to resolve module path syntax from given offset using tail matching.
if (SyntaxMatcher.IsTailMatch<ModuleDeclarationSyntax, StringSyntax, Token>(
matchingNodes,
(moduleSyntax, stringSyntax, token) => moduleSyntax.Path == stringSyntax && token.Type == TokenType.StringComplete)
&& matchingNodes[^3] is ModuleDeclarationSyntax moduleDeclarationSyntax
&& matchingNodes[^2] is StringSyntax stringToken
&& context.Compilation.SourceFileGrouping.TryGetSourceFile(moduleDeclarationSyntax).IsSuccess(out var sourceFile)
&& this.moduleDispatcher.TryGetArtifactReference(context.Compilation.SourceFileGrouping.EntryPoint, moduleDeclarationSyntax).IsSuccess(out var moduleReference))
{
return HandleModuleReference(context, stringToken, sourceFile, moduleReference);
}
}
{ // Definition handler for a non symbol bound to implement import path goto.
// try to resolve import path syntax from given offset using tail matching.
if (SyntaxMatcher.IsTailMatch<CompileTimeImportDeclarationSyntax, CompileTimeImportFromClauseSyntax, StringSyntax, Token>(
matchingNodes,
(_, fromClauseSyntax, stringSyntax, token) => fromClauseSyntax.Path == stringSyntax && token.Type == TokenType.StringComplete)
&& matchingNodes[^4] is CompileTimeImportDeclarationSyntax importDeclarationSyntax
&& matchingNodes[^2] is StringSyntax stringToken
&& context.Compilation.SourceFileGrouping.TryGetSourceFile(importDeclarationSyntax).IsSuccess(out var sourceFile)
&& this.moduleDispatcher.TryGetArtifactReference(context.Compilation.SourceFileGrouping.EntryPoint, importDeclarationSyntax).IsSuccess(out var moduleReference))
{
// goto beginning of the module file.
return GetFileDefinitionLocation(
GetModuleSourceLinkUri(sourceFile, moduleReference),
stringToken,
context,
new() { Start = new(0, 0), End = new(0, 0) });
}
}
{ // Definition handler for a non symbol bound to implement load* functions file argument path goto.
if (SyntaxMatcher.IsTailMatch<StringSyntax, Token>(
matchingNodes,
(stringSyntax, token) => !stringSyntax.IsInterpolated() && token.Type == TokenType.StringComplete)
&& matchingNodes[^2] is StringSyntax stringToken
&& context.Compilation.GetEntrypointSemanticModel().GetDeclaredType(stringToken) is { } stringType
&& stringType.ValidationFlags.HasFlag(TypeSymbolValidationFlags.IsStringFilePath)
&& stringToken.TryGetLiteralValue() is { } stringTokenValue
&& RelativePath.TryCreate(stringTokenValue).Transform(context.Compilation.SourceFileGrouping.EntryPoint.FileHandle.TryGetRelativeFile).IsSuccess(out var relativeFile)
&& relativeFile.Exists())
{
return GetFileDefinitionLocation(
relativeFile.Uri.ToUri(),
stringToken,
context,
new() { Start = new(0, 0), End = new(0, 0) });
}
}
{
if (SyntaxMatcher.GetTailMatch<UsingDeclarationSyntax, StringSyntax, Token>(matchingNodes) is (var @using, var path, _) &&
@using.Path == path &&
context.Compilation.SourceFileGrouping.TryGetSourceFile(@using).IsSuccess(out var sourceFile))
{
return GetFileDefinitionLocation(
sourceFile.Uri,
path,
context,
new() { Start = new(0, 0), End = new(0, 0) });
}
}
// all other unbound syntax nodes return no
return new();
}