Skip to content

Commit

Permalink
Provide a declared type for imported variable accesses to enable comp…
Browse files Browse the repository at this point in the history
…letions (#12050)

Resolves #12049

The CompletionProvider always queries the *declared* type (rather than
the assigned type) of expressions when supplying completions. Since we
supply a declared type for variable accesses (even though variables have
no type declaration), it makes sense to do so for imported variables as
well.
###### Microsoft Reviewers: [Open in
CodeFlow](https://microsoft.github.io/open-pr/?codeflow=https://github.com/Azure/bicep/pull/12050)
  • Loading branch information
jeskew authored Oct 4, 2023
1 parent eb7ab40 commit 3b5f245
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 3 deletions.
8 changes: 5 additions & 3 deletions src/Bicep.Core/TypeSystem/DeclaredTypeManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -964,9 +964,11 @@ private DeclaredTypeAssignment GetTestType(TestDeclarationSyntax syntax)
var variableType = this.typeManager.GetTypeInfo(variableSymbol.DeclaringVariable.Value);
return new DeclaredTypeAssignment(variableType, variableSymbol.DeclaringVariable);

case WildcardImportSymbol wildcardImportSymbol when IsCycleFree(wildcardImportSymbol):
var wildcardImportType = this.typeManager.GetTypeInfo(wildcardImportSymbol.DeclaringSyntax);
return new DeclaredTypeAssignment(wildcardImportType, declaringSyntax: null);
case ImportedSymbol importedSymbol when importedSymbol.Kind == SymbolKind.Variable:
return new DeclaredTypeAssignment(importedSymbol.Type, declaringSyntax: null);

case WildcardImportSymbol wildcardImportSymbol:
return new DeclaredTypeAssignment(wildcardImportSymbol.Type, declaringSyntax: null);

case DeclaredSymbol declaredSymbol when IsCycleFree(declaredSymbol):
// the syntax node is referencing a declared symbol
Expand Down
60 changes: 60 additions & 0 deletions src/Bicep.LangServer.IntegrationTests/CompletionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4443,5 +4443,65 @@ [new Uri("file:///mod2.bicep")] = mod2Content,
completions.Should().Contain(c => c.Label == "mod2.buzz");
}
}

[TestMethod]
public async Task Compile_time_imports_offer_imported_symbol_property_completions()
{
var modContent = """
@export()
var foo = {
bar: 'bar'
baz: 'baz'
}
""";

var mod2Content = """
@export()
var fizz = {
buzz: 'buzz'
pop: 'pop'
}
""";

var mainContent = """
import {foo} from 'mod.bicep'
import {fizz} from 'mod2.bicep'

output obj object = {
bar: foo.|
pop: fizz.|
}
""";

var (text, cursors) = ParserHelper.GetFileWithCursors(mainContent, '|');
Uri mainUri = new Uri("file:///main.bicep");
var files = new Dictionary<Uri, string>
{
[new Uri("file:///mod.bicep")] = modContent,
[new Uri("file:///mod2.bicep")] = mod2Content,
[mainUri] = text
};

var bicepFile = SourceFileFactory.CreateBicepFile(mainUri, text);
using var helper = await LanguageServerHelper.StartServerWithText(
this.TestContext,
files,
bicepFile.FileUri,
services => services.WithFeatureOverrides(new(CompileTimeImportsEnabled: true)));

var file = new FileRequestHelper(helper.Client, bicepFile);

var completions = await file.RequestCompletion(cursors[0]);
completions.Should().Contain(c => c.Label == "bar");
completions.Should().Contain(c => c.Label == "baz");
completions.Should().NotContain(c => c.Label == "buzz");
completions.Should().NotContain(c => c.Label == "pop");

completions = await file.RequestCompletion(cursors[1]);
completions.Should().Contain(c => c.Label == "buzz");
completions.Should().Contain(c => c.Label == "pop");
completions.Should().NotContain(c => c.Label == "bar");
completions.Should().NotContain(c => c.Label == "baz");
}
}
}

0 comments on commit 3b5f245

Please sign in to comment.