Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -90,17 +90,17 @@ private async Task<bool> TryInitializeAsync(
{
if (_service.IsConstructorInitializerGeneration(_document, node, cancellationToken))
{
if (!TryInitializeConstructorInitializerGeneration(node, cancellationToken))
if (!(await TryInitializeConstructorInitializerGenerationAsync(node, cancellationToken).ConfigureAwait(false)))
return false;
}
else if (_service.IsSimpleNameGeneration(_document, node, cancellationToken))
{
if (!TryInitializeSimpleNameGeneration(node, cancellationToken))
if (!(await TryInitializeSimpleNameGenerationAsync(node, cancellationToken).ConfigureAwait(false)))
return false;
}
else if (_service.IsImplicitObjectCreation(_document, node, cancellationToken))
{
if (!TryInitializeImplicitObjectCreation(node, cancellationToken))
if (!(await TryInitializeImplicitObjectCreationAsync(node, cancellationToken).ConfigureAwait(false)))
return false;
}
else
Expand Down Expand Up @@ -296,7 +296,7 @@ private static ITypeSymbol FixType(ITypeSymbol typeSymbol, SemanticModel semanti
.RemoveUnnamedErrorTypes(compilation);
}

private bool TryInitializeConstructorInitializerGeneration(
private async ValueTask<bool> TryInitializeConstructorInitializerGenerationAsync(
SyntaxNode constructorInitializer, CancellationToken cancellationToken)
{
if (_service.TryInitializeConstructorInitializerGeneration(
Expand All @@ -309,13 +309,13 @@ private bool TryInitializeConstructorInitializerGeneration(

var semanticInfo = _document.SemanticModel.GetSymbolInfo(constructorInitializer, cancellationToken);
if (semanticInfo.Symbol == null)
return TryDetermineTypeToGenerateIn(typeToGenerateIn, cancellationToken);
return await TryDetermineTypeToGenerateInAsync(typeToGenerateIn, cancellationToken).ConfigureAwait(false);
}

return false;
}

private bool TryInitializeImplicitObjectCreation(SyntaxNode implicitObjectCreation, CancellationToken cancellationToken)
private async ValueTask<bool> TryInitializeImplicitObjectCreationAsync(SyntaxNode implicitObjectCreation, CancellationToken cancellationToken)
{
if (_service.TryInitializeImplicitObjectCreation(
_document, implicitObjectCreation, cancellationToken,
Expand All @@ -326,13 +326,13 @@ private bool TryInitializeImplicitObjectCreation(SyntaxNode implicitObjectCreati

var semanticInfo = _document.SemanticModel.GetSymbolInfo(implicitObjectCreation, cancellationToken);
if (semanticInfo.Symbol == null)
return TryDetermineTypeToGenerateIn(typeToGenerateIn, cancellationToken);
return await TryDetermineTypeToGenerateInAsync(typeToGenerateIn, cancellationToken).ConfigureAwait(false);
}

return false;
}

private bool TryInitializeSimpleNameGeneration(
private async ValueTask<bool> TryInitializeSimpleNameGenerationAsync(
SyntaxNode simpleName,
CancellationToken cancellationToken)
{
Expand All @@ -359,7 +359,7 @@ private bool TryInitializeSimpleNameGeneration(

cancellationToken.ThrowIfCancellationRequested();

return TryDetermineTypeToGenerateIn(typeToGenerateIn, cancellationToken);
return await TryDetermineTypeToGenerateInAsync(typeToGenerateIn, cancellationToken).ConfigureAwait(false);
}

private static bool IsValidAttributeParameterType(ITypeSymbol type)
Expand Down Expand Up @@ -397,10 +397,10 @@ private static bool IsValidAttributeParameterType(ITypeSymbol type)
}
}

private bool TryDetermineTypeToGenerateIn(
private async ValueTask<bool> TryDetermineTypeToGenerateInAsync(
INamedTypeSymbol original, CancellationToken cancellationToken)
{
var definition = SymbolFinderInternal.FindSourceDefinition(original, _document.Project.Solution, cancellationToken);
var definition = await SymbolFinderInternal.FindSourceDefinitionAsync(original, _document.Project.Solution, cancellationToken).ConfigureAwait(false);
TypeToGenerateIn = definition as INamedTypeSymbol;

return TypeToGenerateIn?.TypeKind is (TypeKind?)TypeKind.Class or (TypeKind?)TypeKind.Struct;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeGeneration;
using Microsoft.CodeAnalysis.FindSymbols;
using Microsoft.CodeAnalysis.LanguageService;
Expand All @@ -23,17 +24,17 @@ private sealed partial class State
public TSimpleNameSyntax SimpleName { get; private set; } = null!;
public TExpressionSyntax SimpleNameOrMemberAccessExpression { get; private set; } = null!;

public static State? Generate(
public static async Task<State?> GenerateAsync(
TService service,
SemanticDocument document,
SyntaxNode node,
CancellationToken cancellationToken)
{
var state = new State();
return state.TryInitialize(service, document, node, cancellationToken) ? state : null;
return await state.TryInitializeAsync(service, document, node, cancellationToken).ConfigureAwait(false) ? state : null;
}

private bool TryInitialize(
private async ValueTask<bool> TryInitializeAsync(
TService service,
SemanticDocument document,
SyntaxNode node,
Expand Down Expand Up @@ -63,7 +64,7 @@ private bool TryInitialize(
}

cancellationToken.ThrowIfCancellationRequested();
var sourceType = SymbolFinderInternal.FindSourceDefinition(TypeToGenerateIn, document.Project.Solution, cancellationToken) as INamedTypeSymbol;
var sourceType = (await SymbolFinderInternal.FindSourceDefinitionAsync(TypeToGenerateIn, document.Project.Solution, cancellationToken).ConfigureAwait(false)) as INamedTypeSymbol;
if (!ValidateTypeToGenerateIn(sourceType, true, EnumType))
return false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public async Task<ImmutableArray<CodeAction>> GenerateEnumMemberAsync(Document d
using (Logger.LogBlock(FunctionId.Refactoring_GenerateMember_GenerateEnumMember, cancellationToken))
{
var semanticDocument = await SemanticDocument.CreateAsync(document, cancellationToken).ConfigureAwait(false);
var state = State.Generate((TService)this, semanticDocument, node, cancellationToken);
var state = await State.GenerateAsync((TService)this, semanticDocument, node, cancellationToken).ConfigureAwait(false);
if (state == null)
{
return [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public Location Location
protected async Task<bool> TryFinishInitializingStateAsync(TService service, SemanticDocument document, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
TypeToGenerateIn = SymbolFinderInternal.FindSourceDefinition(TypeToGenerateIn, document.Project.Solution, cancellationToken) as INamedTypeSymbol;
TypeToGenerateIn = await SymbolFinderInternal.FindSourceDefinitionAsync(TypeToGenerateIn, document.Project.Solution, cancellationToken).ConfigureAwait(false) as INamedTypeSymbol;
if (TypeToGenerateIn.IsErrorType())
{
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeGeneration;
using Microsoft.CodeAnalysis.FindSymbols;
Expand Down Expand Up @@ -69,14 +70,14 @@ private State(
_document = document;
}

public static State Generate(
public static async ValueTask<State> GenerateAsync(
TService service,
SemanticDocument document,
SyntaxNode interfaceNode,
CancellationToken cancellationToken)
{
var state = new State(service, document);
return state.TryInitialize(interfaceNode, cancellationToken) ? state : null;
return await state.TryInitializeAsync(interfaceNode, cancellationToken).ConfigureAwait(false) ? state : null;
}

public Accessibility DetermineMaximalAccessibility()
Expand All @@ -102,7 +103,7 @@ public Accessibility DetermineMaximalAccessibility()
return accessibility;
}

private bool TryInitialize(
private async ValueTask<bool> TryInitializeAsync(
SyntaxNode node, CancellationToken cancellationToken)
{
if (_service.IsIdentifierNameGeneration(node))
Expand Down Expand Up @@ -148,8 +149,8 @@ private bool TryInitialize(
return false;
}

TypeToGenerateIn = SymbolFinderInternal.FindSourceDefinition(
TypeToGenerateIn, _document.Project.Solution, cancellationToken) as INamedTypeSymbol;
TypeToGenerateIn = await SymbolFinder.FindSourceDefinitionAsync(
TypeToGenerateIn, _document.Project.Solution, cancellationToken).ConfigureAwait(false) as INamedTypeSymbol;

if (!ValidateTypeToGenerateIn(TypeToGenerateIn, IsStatic, ClassInterfaceModuleStructTypes))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public async Task<ImmutableArray<CodeAction>> GenerateVariableAsync(
{
var semanticDocument = await SemanticDocument.CreateAsync(document, cancellationToken).ConfigureAwait(false);

var state = State.Generate((TService)this, semanticDocument, node, cancellationToken);
var state = await State.GenerateAsync((TService)this, semanticDocument, node, cancellationToken).ConfigureAwait(false);
if (state == null)
return [];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
if (semanticModel.GetSymbolInfo(node, cancellationToken).Symbol is INamedTypeSymbol type &&
type.TypeKind == TypeKind.Class && type.IsSealed && !type.IsStatic)
{
var definition = SymbolFinderInternal.FindSourceDefinition(
type, document.Project.Solution, cancellationToken);
var definition = await SymbolFinderInternal.FindSourceDefinitionAsync(
type, document.Project.Solution, cancellationToken).ConfigureAwait(false);
if (definition is not null && definition.DeclaringSyntaxReferences.Length > 0)
{
var title = string.Format(TitleFormat, type.Name);
Expand Down
4 changes: 2 additions & 2 deletions src/EditorFeatures/Core.Wpf/Peek/PeekableItemFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ public async Task<IEnumerable<IPeekableItem>> GetPeekableItemsAsync(
throw new ArgumentNullException(nameof(peekResultFactory));

var solution = project.Solution;
symbol = SymbolFinder.FindSourceDefinition(symbol, solution, cancellationToken) ?? symbol;
symbol = GoToDefinitionFeatureHelpers.TryGetPreferredSymbol(solution, symbol, cancellationToken);
symbol = await SymbolFinder.FindSourceDefinitionAsync(symbol, solution, cancellationToken).ConfigureAwait(false) ?? symbol;
symbol = await GoToDefinitionFeatureHelpers.TryGetPreferredSymbolAsync(solution, symbol, cancellationToken).ConfigureAwait(false);
if (symbol is null)
return [];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ private async Task<TriggerIdentifierKind> DetermineIfRenamableIdentifierAsync(Sn
// This is a reference from a nameof expression. Allow the rename but set the RenameOverloads option
ForceRenameOverloads = true;

return DetermineIfRenamableSymbols(renameSymbolInfo.Symbols, document);
return await DetermineIfRenamableSymbolsAsync(renameSymbolInfo.Symbols, document).ConfigureAwait(false);
}
else
{
Expand All @@ -208,20 +208,20 @@ private async Task<TriggerIdentifierKind> DetermineIfRenamableIdentifierAsync(Sn
return TriggerIdentifierKind.NotRenamable;
}

return DetermineIfRenamableSymbol(renameSymbolInfo.Symbols.Single(), document, token);
return await DetermineIfRenamableSymbolAsync(renameSymbolInfo.Symbols.Single(), document, token).ConfigureAwait(false);
}
}
}

return TriggerIdentifierKind.NotRenamable;
}

private TriggerIdentifierKind DetermineIfRenamableSymbols(IEnumerable<ISymbol> symbols, Document document)
private async ValueTask<TriggerIdentifierKind> DetermineIfRenamableSymbolsAsync(IEnumerable<ISymbol> symbols, Document document)
{
foreach (var symbol in symbols)
{
// Get the source symbol if possible
var sourceSymbol = SymbolFinder.FindSourceDefinition(symbol, document.Project.Solution, _cancellationToken) ?? symbol;
var sourceSymbol = await SymbolFinder.FindSourceDefinitionAsync(symbol, document.Project.Solution, _cancellationToken).ConfigureAwait(false) ?? symbol;

if (!sourceSymbol.IsFromSource())
{
Expand All @@ -232,10 +232,10 @@ private TriggerIdentifierKind DetermineIfRenamableSymbols(IEnumerable<ISymbol> s
return TriggerIdentifierKind.RenamableReference;
}

private TriggerIdentifierKind DetermineIfRenamableSymbol(ISymbol symbol, Document document, SyntaxToken token)
private async ValueTask<TriggerIdentifierKind> DetermineIfRenamableSymbolAsync(ISymbol symbol, Document document, SyntaxToken token)
{
// Get the source symbol if possible
var sourceSymbol = SymbolFinder.FindSourceDefinition(symbol, document.Project.Solution, _cancellationToken) ?? symbol;
var sourceSymbol = await SymbolFinder.FindSourceDefinitionAsync(symbol, document.Project.Solution, _cancellationToken).ConfigureAwait(false) ?? symbol;

if (sourceSymbol is IFieldSymbol { ContainingType.IsTupleType: true, IsImplicitlyDeclared: true })
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -796,4 +796,90 @@ public interface I
// verify that we don't crash here.
var implementedMembers = await SymbolFinder.FindImplementedInterfaceMembersArrayAsync(namespaceSymbol, solution, CancellationToken.None);
}

[Theory, CombinatorialData]
public async Task FindSourceDefinition_CrossAssembly(TestHost host)
{
using var workspace = CreateWorkspace(host);
var solution = workspace.CurrentSolution;

// Create a source assembly with a class in Visual Basic
solution = AddProjectWithMetadataReferences(solution, "ReferencedProject", LanguageNames.VisualBasic, @"
Namespace N
Public Class ReferencedClass
End Class
End Namespace
", Net40.References.mscorlib);

var referencedProjectId = solution.Projects.Single(p => p.Name == "ReferencedProject").Id;

// Create a project that uses the class from the other assembly in C#
solution = AddProjectWithMetadataReferences(solution, "SourceProject", LanguageNames.CSharp, "", Net40.References.mscorlib, referencedProjectId);

// Get the symbol for ReferencedClass from the using project's compilation
var sourceCompilation = await solution.Projects.Single(p => p.Name == "SourceProject").GetCompilationAsync();
var classInSource = sourceCompilation.GetTypeByMetadataName("N.ReferencedClass");

// It should be a metadata symbol (from assembly reference)
Assert.True(classInSource.Locations.Any(loc => loc.IsInMetadata));

// Find the source definition
var sourceDefinition = await SymbolFinder.FindSourceDefinitionAsync(classInSource, solution, CancellationToken.None);

// Verify we found the source definition
Assert.NotNull(sourceDefinition);
Assert.True(sourceDefinition.Locations.Any(loc => loc.IsInSource));

// Verify it comes from the VB project
var document = solution.GetDocument(sourceDefinition.Locations.First(loc => loc.IsInSource).SourceTree);
Assert.Equal(referencedProjectId, document.Project.Id);
}

[Theory, CombinatorialData, WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems/edit/2443981")]
public async Task FindSourceDefinition_CrossAssembly_WithFrozen(TestHost host)
{
using var workspace = CreateWorkspace(host);
var solution = workspace.CurrentSolution;

var code = @"
Namespace N
Public Class ReferencedClass
Public Sub M()
Dim x As Integer = 0
End Sub
End Class
End Namespace
";

// Create a source assembly with a class in Visual Basic
solution = AddProjectWithMetadataReferences(solution, "ReferencedProject", LanguageNames.VisualBasic, code, Net40.References.mscorlib);

var referencedProjectId = solution.Projects.Single(p => p.Name == "ReferencedProject").Id;

// Create a project that uses the class from the other assembly in C#
solution = AddProjectWithMetadataReferences(solution, "SourceProject", LanguageNames.CSharp, "", Net40.References.mscorlib, referencedProjectId);

// Fetch the C# compilation to ensure we produce all compilations, and then make a change to the VB project and freeze it.
// At this point we won't create more skeleton references for the VB reference, but we also won't have an up-to-date compilation.
await solution.Projects.Single(p => p.Name == "SourceProject").GetCompilationAsync();
solution = solution.GetProject(referencedProjectId).Documents.Single().WithText(SourceText.From(code.Replace('0', '1')))
.Project.Solution.WithFrozenPartialCompilations(CancellationToken.None);

var sourceCompilation = await solution.Projects.Single(p => p.Name == "SourceProject").GetCompilationAsync();
var classInSource = sourceCompilation.GetTypeByMetadataName("N.ReferencedClass");

// It should be a metadata symbol (from assembly reference)
Assert.True(classInSource.Locations.Any(loc => loc.IsInMetadata));

// Find the source definition
var sourceDefinition = await SymbolFinder.FindSourceDefinitionAsync(classInSource, solution, CancellationToken.None);

// Verify we found the source definition
Assert.NotNull(sourceDefinition);
Assert.True(sourceDefinition.Locations.Any(loc => loc.IsInSource));

// Verify it comes from the VB project
var document = solution.GetDocument(sourceDefinition.Locations.First(loc => loc.IsInSource).SourceTree);
Assert.Equal(referencedProjectId, document.Project.Id);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -890,7 +890,7 @@ public override async Task<ImmutableArray<ISymbol>> DetermineCascadedSymbolsFrom

if (convertedType != null)
{
convertedType = SymbolFinder.FindSourceDefinition(convertedType, document.Project.Solution, cancellationToken)
convertedType = await SymbolFinder.FindSourceDefinitionAsync(convertedType, document.Project.Solution, cancellationToken).ConfigureAwait(false)
?? convertedType;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ internal async Task<ChangeSignatureAnalyzedContext> GetChangeSignatureContextAsy
document, position, restrictToDeclarations, cancellationToken).ConfigureAwait(false);

// Cross-language symbols will show as metadata, so map it to source if possible.
symbol = SymbolFinder.FindSourceDefinition(symbol, document.Project.Solution, cancellationToken) ?? symbol;
symbol = await SymbolFinder.FindSourceDefinitionAsync(symbol, document.Project.Solution, cancellationToken).ConfigureAwait(false) ?? symbol;
if (symbol == null)
return new CannotChangeSignatureAnalyzedContext(ChangeSignatureFailureKind.IncorrectKind);

Expand Down
Loading
Loading