in src/Bicep.LangServer/Handlers/BicepDefinitionHandler.cs [378:473]
private static LocationOrLocationLinks HandleImportedSymbolLocation(SymbolResolutionResult result, CompilationContext context, ImportedSymbol imported)
=> HandleImportedSymbolLocation(result.Origin.ToRange(context.LineStarts), context, imported.SourceModel, imported.OriginalSymbolName, imported.EnclosingDeclaration);
private static LocationOrLocationLinks HandleWildcardImportInstanceFunctionLocation(SymbolResolutionResult result, CompilationContext context, WildcardImportInstanceFunctionSymbol symbol)
=> HandleImportedSymbolLocation(result.Origin.ToRange(context.LineStarts), context, symbol.BaseSymbol.SourceModel, symbol.Name, symbol.BaseSymbol.EnclosingDeclaration);
private static LocationOrLocationLinks HandleImportedSymbolLocation(Range originSelectionRange, CompilationContext context, ISemanticModel sourceModel, string? originalSymbolName, IArtifactReferenceSyntax enclosingDeclaration)
{
if (sourceModel is SemanticModel bicepModel &&
bicepModel.Root.Declarations.Where(type => LanguageConstants.IdentifierComparer.Equals(type.Name, originalSymbolName)).FirstOrDefault() is { } originalDeclaration)
{
// entire span of the declaredSymbol
var targetRange = PositionHelper.GetNameRange(bicepModel.SourceFile.LineStarts, originalDeclaration.DeclaringSyntax);
return new(new LocationOrLocationLink(new LocationLink
{
OriginSelectionRange = originSelectionRange,
TargetUri = bicepModel.SourceFile.Uri,
TargetRange = targetRange,
TargetSelectionRange = targetRange,
}));
}
var (armTemplate, armTemplateUri) = GetArmSourceTemplateInfo(context, enclosingDeclaration);
if (armTemplateUri is not null && originalSymbolName is string nonNullName && sourceModel.Exports.TryGetValue(nonNullName, out var exportMetadata))
{
if (exportMetadata.Kind == ExportMetadataKind.Type &&
armTemplate?.Definitions?.TryGetValue(nonNullName, out var originalTypeDefinition) is true &&
ToRange(originalTypeDefinition) is Range typeDefinitionRange)
{
return new(new LocationOrLocationLink(new LocationLink
{
OriginSelectionRange = originSelectionRange,
TargetUri = armTemplateUri,
TargetRange = typeDefinitionRange,
TargetSelectionRange = typeDefinitionRange,
}));
}
if (exportMetadata.Kind == ExportMetadataKind.Variable)
{
if (armTemplate?.Variables?.TryGetValue(nonNullName, out var variableDeclaration) is true && ToRange(variableDeclaration) is Range variableDefinitionRange)
{
return new(new LocationOrLocationLink(new LocationLink
{
OriginSelectionRange = originSelectionRange,
TargetUri = armTemplateUri,
TargetRange = variableDefinitionRange,
TargetSelectionRange = variableDefinitionRange,
}));
}
if (armTemplate?.Variables?.TryGetValue("copy", out var copyVariablesDeclaration) is true &&
copyVariablesDeclaration.Value is JArray copyVariablesArray &&
copyVariablesArray.Where(e => e is JObject objectElement &&
objectElement.TryGetValue("name", StringComparison.OrdinalIgnoreCase, out var nameToken) &&
nameToken is JValue { Value: string nameString } &&
StringComparer.OrdinalIgnoreCase.Equals(nameString, nonNullName))
.FirstOrDefault() is JToken copyVariableToken &&
ToRange(copyVariableToken) is Range copyVariableDefinitionRange)
{
return new(new LocationOrLocationLink(new LocationLink
{
OriginSelectionRange = originSelectionRange,
TargetUri = armTemplateUri,
TargetRange = copyVariableDefinitionRange,
TargetSelectionRange = copyVariableDefinitionRange,
}));
}
}
if (exportMetadata.Kind == ExportMetadataKind.Function)
{
var fullyQualifiedFunctionName = nonNullName.Contains('.')
? nonNullName
: $"{EmitConstants.UserDefinedFunctionsNamespace}.{nonNullName}";
if (armTemplate?.GetFunctionDefinitions()
.Where(fd => StringComparer.OrdinalIgnoreCase.Equals(fd.Key, fullyQualifiedFunctionName))
.FirstOrDefault() is FunctionDefinition functionDefinition &&
ToRange(functionDefinition.Function) is Range functionDefinitionRange)
{
return new(new LocationOrLocationLink(new LocationLink
{
OriginSelectionRange = originSelectionRange,
TargetUri = armTemplateUri,
TargetRange = functionDefinitionRange,
TargetSelectionRange = functionDefinitionRange,
}));
}
}
}
return new();
}