Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bring back naive implementation of FAR for target-typed new #43645

Merged
merged 4 commits into from
May 11, 2020
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 @@ -497,6 +497,25 @@ internal static ImmutableArray<T> Concat<T>(this ImmutableArray<T> first, Immuta
return first.AddRange(second);
}

internal static ImmutableArray<T> Concat<T>(this ImmutableArray<T> first, ImmutableArray<T> second, ImmutableArray<T> third)
{
var builder = ArrayBuilder<T>.GetInstance(first.Length + second.Length + third.Length);
builder.AddRange(first);
builder.AddRange(second);
builder.AddRange(third);
return builder.ToImmutableAndFree();
}

internal static ImmutableArray<T> Concat<T>(this ImmutableArray<T> first, ImmutableArray<T> second, ImmutableArray<T> third, ImmutableArray<T> fourth)
{
var builder = ArrayBuilder<T>.GetInstance(first.Length + second.Length + third.Length + fourth.Length);
builder.AddRange(first);
builder.AddRange(second);
builder.AddRange(third);
builder.AddRange(fourth);
return builder.ToImmutableAndFree();
}

internal static ImmutableArray<T> Concat<T>(this ImmutableArray<T> first, T second)
{
return first.Add(second);
Expand Down
39 changes: 39 additions & 0 deletions src/EditorFeatures/CSharpTest/ChangeSignature/AddParameterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1222,5 +1222,44 @@ static void M(string[] args)

await TestChangeSignatureViaCommandAsync(LanguageNames.CSharp, markup, updatedSignature: permutation, expectedUpdatedInvocationDocumentCode: updatedCode);
}

[WpfFact, Trait(Traits.Feature, Traits.Features.ChangeSignature)]
[WorkItem(44126, "https://github.com/dotnet/roslyn/issues/44126")]
public async Task AddAndReorderImplicitObjectCreationParameter()
{
var markup = @"
using System;
class C
{
$$C(int x, string y)
{
}

public void M()
{
_ = new(1, 2);
}
}";
var permutation = new[] {
new AddedParameterOrExistingIndex(1),
new AddedParameterOrExistingIndex(new AddedParameter(null, "byte", "b", "34"), "byte"),
new AddedParameterOrExistingIndex(0)};
var updatedCode = @"
using System;
class C
{
C(string y, byte b, int x)
{
}

public void M()
{
_ = new(1, 2);
}
}";
// Expect: _ = new(2, 34, 1);
// Tracked by https://github.com/dotnet/roslyn/issues/44126
await TestChangeSignatureViaCommandAsync(LanguageNames.CSharp, markup, updatedSignature: permutation, expectedUpdatedInvocationDocumentCode: updatedCode);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,6 @@ internal static class DefinitionItemExtensions

var properties = GetProperties(definition, isPrimary);

var displayableProperties = AbstractReferenceFinder.GetAdditionalFindUsagesProperties(definition);

// If it's a namespace, don't create any normal location. Namespaces
// come from many different sources, but we'll only show a single
// root definition node for it. That node won't be navigable.
Expand Down Expand Up @@ -162,6 +160,8 @@ internal static class DefinitionItemExtensions
properties, displayIfNoReferences);
}

var displayableProperties = AbstractReferenceFinder.GetAdditionalFindUsagesProperties(definition);

return DefinitionItem.Create(
tags, displayParts, sourceLocations.ToImmutable(),
nameDisplayParts, properties, displayableProperties, displayIfNoReferences);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -815,6 +815,81 @@ public class A
}
</Document>
</Project>
</Workspace>
Await TestAPIAndFeature(input, kind, host)
End Function

<WpfTheory, CombinatorialData, Trait(Traits.Feature, Traits.Features.FindReferences)>
Public Async Function TestConstructor_TargetTypedNew_Local(kind As TestKind, host As TestHost) As Task
Dim input =
<Workspace>
<Project Language="C#" CommonReferences="true">
<Document>
class D
{
public {|Definition:$$D|}() { }
}
</Document>
<Document>
class C
{
void M()
{
D d = [|new|]();
D d2 = [|new|]();
}
}
</Document>
</Project>
</Workspace>
Await TestAPIAndFeature(input, kind, host)
End Function

<WpfTheory, CombinatorialData, Trait(Traits.Feature, Traits.Features.FindReferences)>
Public Async Function TestConstructor_TargetTypedNew_Local_WithArguments(kind As TestKind, host As TestHost) As Task
Dim input =
<Workspace>
<Project Language="C#" CommonReferences="true">
<Document>
class D
{
public {|Definition:$$D|}(int i, int j) { }
}
</Document>
<Document>
class C
{
void M()
{
D d = [|new|](1, 2);
D d2 = [|new|](3, 4);
}
}
</Document>
</Project>
</Workspace>
Await TestAPIAndFeature(input, kind, host)
End Function

<WpfTheory, CombinatorialData, Trait(Traits.Feature, Traits.Features.FindReferences)>
Public Async Function TestConstructor_TargetTypedNew_Field(kind As TestKind, host As TestHost) As Task
Dim input =
<Workspace>
<Project Language="C#" CommonReferences="true">
<Document>
class D
{
public {|Definition:$$D|}() { }
}
</Document>
<Document>
class C
{
D d = [|new|]();
D d2 = [|new|]();
}
</Document>
</Project>
</Workspace>
Await TestAPIAndFeature(input, kind, host)
End Function
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,6 @@ protected static async Task<ImmutableArray<SyntaxToken>> GetIdentifierOrGlobalNa
var location = token.GetLocation();
var symbolUsageInfo = GetSymbolUsageInfo(token.Parent, semanticModel, syntaxFacts, semanticFacts, cancellationToken);

var isWrittenTo = symbolUsageInfo.IsWrittenTo();
locations.Add(new FinderLocation(token.Parent, new ReferenceLocation(
document, alias, location, isImplicit: false,
symbolUsageInfo, GetAdditionalFindUsagesProperties(token.Parent, semanticModel, syntaxFacts), candidateReason: reason)));
Expand Down Expand Up @@ -433,6 +432,9 @@ protected Task<ImmutableArray<Document>> FindDocumentsWithDeconstructionAsync(Pr
protected Task<ImmutableArray<Document>> FindDocumentsWithAwaitExpressionAsync(Project project, IImmutableSet<Document> documents, CancellationToken cancellationToken)
=> FindDocumentsWithPredicateAsync(project, documents, predicate: sti => sti.ContainsAwait, cancellationToken);

protected Task<ImmutableArray<Document>> FindDocumentsWithImplicitObjectCreationExpressionAsync(Project project, IImmutableSet<Document> documents, CancellationToken cancellationToken)
=> FindDocumentsWithPredicateAsync(project, documents, predicate: sti => sti.ContainsImplicitObjectCreation, cancellationToken);

/// <summary>
/// If the `node` implicitly matches the `symbol`, then it will be added to `locations`.
/// </summary>
Expand Down Expand Up @@ -564,6 +566,33 @@ static bool IsRelevantDocument(SyntaxTreeIndex syntaxTreeInfo)
}
}

protected Task<ImmutableArray<FinderLocation>> FindReferencesInImplicitObjectCreationExpressionAsync(
ISymbol symbol,
Document document,
SemanticModel semanticModel,
CancellationToken cancellationToken)
{
return FindReferencesInDocumentAsync(symbol, document, IsRelevantDocument, CollectMatchingReferences, cancellationToken);

static bool IsRelevantDocument(SyntaxTreeIndex syntaxTreeInfo)
=> syntaxTreeInfo.ContainsImplicitObjectCreation;

void CollectMatchingReferences(ISymbol originalUnreducedSymbolDefinition, SyntaxNode node,
ISyntaxFactsService syntaxFacts, ISemanticFactsService semanticFacts, ArrayBuilder<FinderLocation> locations)
{
var constructor = semanticModel.GetSymbolInfo(node).Symbol;

if (Matches(constructor, originalUnreducedSymbolDefinition))
{
var location = node.GetFirstToken().GetLocation();
var symbolUsageInfo = GetSymbolUsageInfo(node, semanticModel, syntaxFacts, semanticFacts, cancellationToken);

locations.Add(new FinderLocation(node, new ReferenceLocation(
document, alias: null, location, isImplicit: true, symbolUsageInfo, GetAdditionalFindUsagesProperties(node, semanticModel, syntaxFacts), CandidateReason.None)));
CyrusNajmabadi marked this conversation as resolved.
Show resolved Hide resolved
}
}
}

private static bool Matches(ISymbol symbol1, ISymbol notNulloriginalUnreducedSymbol2)
{
return symbol1 != null && SymbolEquivalenceComparer.Instance.Equals(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@ protected override bool CanFind(IMethodSymbol symbol)
? await FindDocumentsAsync(project, documents, cancellationToken, simpleName).ConfigureAwait(false)
: SpecializedCollections.EmptyEnumerable<Document>();

return documentsWithName.Concat(documentsWithType)
var documentsWithImplicitObjectCreations = symbol.MethodKind == MethodKind.Constructor
? await FindDocumentsWithImplicitObjectCreationExpressionAsync(project, documents, cancellationToken).ConfigureAwait(false)
: ImmutableArray<Document>.Empty;

return documentsWithName.Concat(documentsWithType, documentsWithImplicitObjectCreations)
.Concat(documentsWithAttribute)
.Distinct()
.ToImmutableArray();
Expand Down Expand Up @@ -96,8 +100,9 @@ protected override bool CanFind(IMethodSymbol symbol)
var ordinaryRefs = await FindOrdinaryReferencesAsync(symbol, document, semanticModel, findParentNode, cancellationToken).ConfigureAwait(false);
var attributeRefs = await FindAttributeReferencesAsync(symbol, document, semanticModel, cancellationToken).ConfigureAwait(false);
var predefinedTypeRefs = await FindPredefinedTypeReferencesAsync(symbol, document, semanticModel, cancellationToken).ConfigureAwait(false);
var implicitObjectCreationMatches = await FindReferencesInImplicitObjectCreationExpressionAsync(symbol, document, semanticModel, cancellationToken).ConfigureAwait(false);

return ordinaryRefs.Concat(attributeRefs).Concat(predefinedTypeRefs);
return ordinaryRefs.Concat(attributeRefs, predefinedTypeRefs, implicitObjectCreationMatches);
}

private Task<ImmutableArray<FinderLocation>> FindOrdinaryReferencesAsync(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ internal partial class SyntaxTreeIndex
bool containsIndexerMemberCref,
bool containsDeconstruction,
bool containsAwait,
bool containsTupleExpressionOrTupleType)
bool containsTupleExpressionOrTupleType,
bool containsImplicitObjectCreation)
: this(predefinedTypes, predefinedOperators,
ConvertToContainingNodeFlag(
containsForEachStatement,
Expand All @@ -42,7 +43,8 @@ internal partial class SyntaxTreeIndex
containsIndexerMemberCref,
containsDeconstruction,
containsAwait,
containsTupleExpressionOrTupleType))
containsTupleExpressionOrTupleType,
containsImplicitObjectCreation))
{
}

Expand All @@ -64,7 +66,8 @@ private ContextInfo(int predefinedTypes, int predefinedOperators, ContainingNode
bool containsIndexerMemberCref,
bool containsDeconstruction,
bool containsAwait,
bool containsTupleExpressionOrTupleType)
bool containsTupleExpressionOrTupleType,
bool containsImplicitObjectCreation)
{
var containingNodes = ContainingNodes.None;

Expand All @@ -79,6 +82,7 @@ private ContextInfo(int predefinedTypes, int predefinedOperators, ContainingNode
containingNodes |= containsDeconstruction ? ContainingNodes.ContainsDeconstruction : 0;
containingNodes |= containsAwait ? ContainingNodes.ContainsAwait : 0;
containingNodes |= containsTupleExpressionOrTupleType ? ContainingNodes.ContainsTupleExpressionOrTupleType : 0;
containingNodes |= containsImplicitObjectCreation ? ContainingNodes.ContainsImplicitObjectCreation : 0;

return containingNodes;
}
Expand All @@ -98,6 +102,9 @@ public bool ContainsDeconstruction
public bool ContainsAwait
=> (_containingNodes & ContainingNodes.ContainsAwait) == ContainingNodes.ContainsAwait;

public bool ContainsImplicitObjectCreation
=> (_containingNodes & ContainingNodes.ContainsImplicitObjectCreation) == ContainingNodes.ContainsImplicitObjectCreation;

public bool ContainsLockStatement
=> (_containingNodes & ContainingNodes.ContainsLockStatement) == ContainingNodes.ContainsLockStatement;

Expand Down Expand Up @@ -161,6 +168,7 @@ private enum ContainingNodes
ContainsDeconstruction = 1 << 8,
ContainsAwait = 1 << 9,
ContainsTupleExpressionOrTupleType = 1 << 10,
ContainsImplicitObjectCreation = 1 << 11,
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ internal sealed partial class SyntaxTreeIndex
var containsDeconstruction = false;
var containsAwait = false;
var containsTupleExpressionOrTupleType = false;
var containsImplicitObjectCreation = false;

var predefinedTypes = (int)PredefinedType.None;
var predefinedOperators = (int)PredefinedOperator.None;
Expand Down Expand Up @@ -116,6 +117,7 @@ internal sealed partial class SyntaxTreeIndex
containsAwait = containsAwait || syntaxFacts.IsAwaitExpression(node);
containsTupleExpressionOrTupleType = containsTupleExpressionOrTupleType ||
syntaxFacts.IsTupleExpression(node) || syntaxFacts.IsTupleType(node);
containsImplicitObjectCreation = containsImplicitObjectCreation || syntaxFacts.IsImplicitObjectCreationExpression(node);

if (syntaxFacts.IsUsingAliasDirective(node) && infoFactory.TryGetAliasesFromUsingDirective(node, out var aliases))
{
Expand Down Expand Up @@ -263,7 +265,8 @@ internal sealed partial class SyntaxTreeIndex
containsIndexerMemberCref,
containsDeconstruction,
containsAwait,
containsTupleExpressionOrTupleType),
containsTupleExpressionOrTupleType,
containsImplicitObjectCreation),
new DeclarationInfo(
declaredSymbolInfos.ToImmutable()),
new ExtensionMethodInfo(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public ImmutableArray<int> ComplexExtensionMethodInfo
public bool ContainsForEachStatement => _contextInfo.ContainsForEachStatement;
public bool ContainsDeconstruction => _contextInfo.ContainsDeconstruction;
public bool ContainsAwait => _contextInfo.ContainsAwait;
public bool ContainsImplicitObjectCreation => _contextInfo.ContainsImplicitObjectCreation;
public bool ContainsLockStatement => _contextInfo.ContainsLockStatement;
public bool ContainsUsingStatement => _contextInfo.ContainsUsingStatement;
public bool ContainsQueryExpression => _contextInfo.ContainsQueryExpression;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace Microsoft.CodeAnalysis.FindSymbols
internal sealed partial class SyntaxTreeIndex : IObjectWritable
{
private const string PersistenceName = "<SyntaxTreeIndex>";
private static readonly Checksum SerializationFormatChecksum = Checksum.Create("17");
private static readonly Checksum SerializationFormatChecksum = Checksum.Create("18");

public readonly Checksum Checksum;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ internal static class SyntaxKindEx
{
// The code style layer does not currently need access to any syntax defined in newer versions of Roslyn. This
// type is included as an example should this change in future updates.
public const SyntaxKind ImplicitObjectCreationExpression = (SyntaxKind)8659;
public const SyntaxKind RelationalPattern = (SyntaxKind)9029;
public const SyntaxKind ParenthesizedPattern = (SyntaxKind)9028;
public const SyntaxKind AndPattern = (SyntaxKind)9032;
Expand All @@ -26,12 +27,14 @@ internal static class SyntaxKindEx
public const SyntaxKind OrKeyword = (SyntaxKind)8438;

#if !CODE_STYLE
private const uint ImplicitObjectCreationExpressionAssertion = -(ImplicitObjectCreationExpression - SyntaxKind.ImplicitObjectCreationExpression);

/// <summary>
/// This will only compile if <see cref="RelationalPattern"/> and <see cref="SyntaxKind.RelationalPattern"/> have the same
/// value.
/// </summary>
/// <remarks>
/// <para>The subtraction will overflow if <see cref="SyntaxKind.DotDotToken"/> is greater, and the conversion
/// <para>The subtraction will overflow if <see cref="SyntaxKind.RelationalPattern"/> is greater, and the conversion
/// to an unsigned value after negation will overflow if <see cref="RelationalPattern"/> is greater.</para>
/// </remarks>
private const uint RelationalPatternValueAssertion = -(RelationalPattern - SyntaxKind.RelationalPattern);
Expand Down
Loading