提交 e02548c6 编写于 作者: C CyrusNajmabadi 提交者: GitHub

Merge pull request #19334 from CyrusNajmabadi/generateBetterNames

Generate better names for expressions used as parameters.
......@@ -8,7 +8,6 @@
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Editor.UnitTests;
using Microsoft.CodeAnalysis.Options;
using Roslyn.Test.Utilities;
using Xunit;
......@@ -556,7 +555,7 @@ public class @class
{
}
public static void Add(object t)
public static void Add(object @class)
{
}
}
......@@ -574,7 +573,7 @@ public class @class
{
}
public static void Add(object t)
public static void Add(object @class)
{
}
}
......@@ -600,7 +599,7 @@ public class @class
{
}
public static void Add(object t)
public static void Add(object @class)
{
}
}
......@@ -618,7 +617,7 @@ public class @class
{
}
public static void Add(object t)
public static void Add(object @class)
{
}
}
......@@ -643,7 +642,7 @@ public class @class
{
}
public static void Add(object t)
public static void Add(object @class)
{
}
......@@ -658,7 +657,7 @@ public class @class
{
}
public static void Add(object t)
public static void Add(object @class)
{
}
......@@ -681,7 +680,7 @@ public class @class
{
}
public static void Add(object t)
public static void Add(object @class)
{
}
......@@ -696,7 +695,7 @@ public class @class
{
}
public static void Add(object t)
public static void Add(object @class)
{
}
......@@ -2180,8 +2179,8 @@ int Main(int i)
switch (1)
{
case 0:
const int {|Rename:V|} = 1 + 1;
var f = Main(V);
const int {|Rename:I|} = 1 + 1;
var f = Main(I);
Console.WriteLine(f);
}
}
......@@ -2432,8 +2431,8 @@ class C
static void Main(string[] args)
{
var set = new HashSet<string>();
var {|Rename:v|} = set.ToString();
set.Add(v);
var {|Rename:item|} = set.ToString();
set.Add(item);
}
}",
options: ImplicitTypingEverywhere());
......@@ -2530,8 +2529,8 @@ class Program
static void Main(string[] args)
{
var d = new Dictionary<string, Exception>();
var {|Rename:exception|} = new Exception();
d.Add(""a"", exception);
var {|Rename:value|} = new Exception();
d.Add(""a"", value);
}
}",
ignoreTrivia: false, options: ImplicitTypingEverywhere());
......@@ -3091,8 +3090,8 @@ class Complex
int real; int imaginary;
public static Complex operator +(Complex a, Complex b)
{
var {|Rename:v|} = b.real + 1;
return a.Add(v);
var {|Rename:b1|} = b.real + 1;
return a.Add(b1);
}
private Complex Add(int b)
......@@ -3161,7 +3160,7 @@ public struct DBBool
@"using System;
public struct DBBool
{
private const int {|Rename:V|} = 1;
private const int {|Rename:Value|} = 1;
public static readonly DBBool dbFalse = new DBBool(-1);
int value;
......@@ -3170,7 +3169,7 @@ public struct DBBool
this.value = value;
}
public static implicit operator DBBool(bool x) => x ? new DBBool(V) : dbFalse;
public static implicit operator DBBool(bool x) => x ? new DBBool(Value) : dbFalse;
}";
await TestInRegularAndScriptAsync(code, expected, ignoreTrivia: false);
......@@ -3574,8 +3573,8 @@ class TestClass
{
static void Test(string[] args)
{
var {|Rename:v|} = $""{DateTime.Now.ToString()}Text{args[0]}"";
Console.WriteLine(v);
var {|Rename:value|} = $""{DateTime.Now.ToString()}Text{args[0]}"";
Console.WriteLine(value);
}
}";
......@@ -3603,9 +3602,9 @@ class TestClass
{
static void Test(string[] args)
{
var {|Rename:v|} = $""Text{{s}}"";
Console.WriteLine(v);
Console.WriteLine(v);
var {|Rename:value|} = $""Text{{s}}"";
Console.WriteLine(value);
Console.WriteLine(value);
}
}";
......@@ -3773,8 +3772,8 @@ class C
{
public async Task M()
{
FormattableString {|Rename:v|} = $"""";
var f = FormattableString.Invariant(v);
FormattableString {|Rename:formattable|} = $"""";
var f = FormattableString.Invariant(formattable);
}
}
}";
......@@ -4254,5 +4253,81 @@ void M()
await TestInRegularAndScriptAsync(code, expected, index: 1, ignoreTrivia: false);
}
[WorkItem(2423, "https://github.com/dotnet/roslyn/issues/2423")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsIntroduceVariable)]
public async Task TestPickNameBasedOnArgument1()
{
await TestInRegularAndScriptAsync(
@"class C
{
public C(string a, string b)
{
new TextSpan([|int.Parse(a)|], int.Parse(b));
}
}
struct TextSpan
{
public TextSpan(int start, int length)
{
}
}",
@"class C
{
public C(string a, string b)
{
int {|Rename:start|} = int.Parse(a);
new TextSpan(start, int.Parse(b));
}
}
struct TextSpan
{
public TextSpan(int start, int length)
{
}
}");
}
[WorkItem(2423, "https://github.com/dotnet/roslyn/issues/2423")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsIntroduceVariable)]
public async Task TestPickNameBasedOnArgument2()
{
await TestInRegularAndScriptAsync(
@"class C
{
public C(string a, string b)
{
new TextSpan(int.Parse(a), [|int.Parse(b)|]);
}
}
struct TextSpan
{
public TextSpan(int start, int length)
{
}
}",
@"class C
{
public C(string a, string b)
{
int {|Rename:length|} = int.Parse(b);
new TextSpan(int.Parse(a), length);
}
}
struct TextSpan
{
public TextSpan(int start, int length)
{
}
}");
}
}
}
\ No newline at end of file
......@@ -168,8 +168,8 @@ public static void Main()
{
for (int i = 0; i < 10; i++)
{
int {|Rename:v|} = i + 1;
Console.WriteLine(v);
int {|Rename:value|} = i + 1;
Console.WriteLine(value);
}
}
}
......
......@@ -28,8 +28,8 @@ Imports System.Collections.Generic
Imports System.Linq
Module Program
Sub Main(args As String())
Const {|Rename:V|} As Integer = 1 + 1
Console.WriteLine(V)
Const {|Rename:Value|} As Integer = 1 + 1
Console.WriteLine(Value)
End Sub
End Module",
index:=2)
......@@ -51,8 +51,8 @@ Imports System.Collections.Generic
Imports System.Linq
Module Program
Sub Main(args As String())
Const {|Rename:V|} As Integer = 1 + 1
Console.WriteLine(V)
Const {|Rename:Value|} As Integer = 1 + 1
Console.WriteLine(Value)
End Sub
End Module",
index:=3)
......@@ -826,9 +826,9 @@ End Class")
End Sub
End Class",
"Class Foo
Private Const {|Rename:V|} As Integer = 42
Private Const {|Rename:X|} As Integer = 42
Sub New()
MyClass.New(V)
MyClass.New(X)
End Sub
Sub New(x As Integer)
End Sub
......@@ -1158,8 +1158,8 @@ Module Program
If True Then
If True Then
Const {|Rename:V|} As Integer = 1
Console.WriteLine(V)
Const {|Rename:Value|} As Integer = 1
Console.WriteLine(Value)
Else
Console.WriteLine(2)
End If
......@@ -1198,8 +1198,8 @@ Module Program
If True Then
Console.WriteLine(1)
Else
Const {|Rename:V|} As Integer = 2
Console.WriteLine(V)
Const {|Rename:Value|} As Integer = 2
Console.WriteLine(Value)
End If
Else
Console.WriteLine(3)
......@@ -1234,8 +1234,8 @@ Module Program
If True Then
If True Then Console.WriteLine(1) Else Console.WriteLine(2)
Else
Const {|Rename:V|} As Integer = 3
Console.WriteLine(V)
Const {|Rename:Value|} As Integer = 3
Console.WriteLine(Value)
End If
End Sub
End Module
......@@ -1258,8 +1258,8 @@ End Module",
Module Program
Sub Main
Dim a = Sub(x As Integer)
Dim {|Rename:v|} As Integer = x + 1
Console.WriteLine(v) ' Introduce local
Dim {|Rename:value|} As Integer = x + 1
Console.WriteLine(value) ' Introduce local
End Sub
End Sub
End Module")
......@@ -1280,8 +1280,8 @@ Module Program
Sub Main
Dim a = Sub(x As Integer)
If True Then
Dim {|Rename:v|} As Integer = x + 1
Console.WriteLine(v)
Dim {|Rename:value|} As Integer = x + 1
Console.WriteLine(value)
Else
Console.WriteLine()
End If
......@@ -1307,8 +1307,8 @@ Module Program
If True Then
Console.WriteLine()
Else
Dim {|Rename:v|} As Integer = x + 1
Console.WriteLine(v)
Dim {|Rename:value|} As Integer = x + 1
Console.WriteLine(value)
End If
End Sub
End Sub
......@@ -1329,8 +1329,8 @@ End Module",
Module Program
Sub Main
Dim a = Sub(x As Integer)
Dim {|Rename:v|} As Integer = x + 1
If True Then Console.WriteLine(v) Else Console.WriteLine(v)
Dim {|Rename:value|} As Integer = x + 1
If True Then Console.WriteLine(value) Else Console.WriteLine(value)
End Sub
End Sub
End Module",
......@@ -1351,10 +1351,10 @@ End Module",
"Module Program
Sub Main(args As String())
Dim query = Sub(a)
Dim {|Rename:v|} As Object = a Or a
Dim {|Rename:arg1|} As Object = a Or a
a = New With {Key .Key = Function(ByVal arg As Integer) As Integer
Return arg
End Function}.Key.Invoke(v)
End Function}.Key.Invoke(arg1)
End Sub
End Sub
End Module")
......@@ -2093,8 +2093,8 @@ End Class",
Class C
Private Shared Sub Main(args As String())
Dim hSet = New HashSet(Of String)()
Dim {|Rename:v|} As String = hSet.ToString()
hSet.Add(v)
Dim {|Rename:item|} As String = hSet.ToString()
hSet.Add(item)
End Sub
End Class")
End Function
......@@ -2175,8 +2175,8 @@ Imports System.Collections.Generic
Imports System.Linq
Module Program
Sub Main()
Dim {|Rename:enumerable1|} As IEnumerable(Of Char) = From x In """"
[Take](enumerable1)
Dim {|Rename:x1|} As IEnumerable(Of Char) = From x In """"
[Take](x1)
End Sub
Sub Take(x)
End Sub
......@@ -2621,8 +2621,8 @@ Imports System
Namespace N
Class C
Public Sub M()
Dim {|Rename:v|} As FormattableString = $""""
Dim f = FormattableString.Invariant(v)
Dim {|Rename:formattable|} As FormattableString = $""""
Dim f = FormattableString.Invariant(formattable)
End Sub
End Class
End Namespace"
......@@ -2889,5 +2889,58 @@ End Class
Await TestInRegularAndScriptAsync(code, expected, ignoreTrivia:=False)
End Function
<WorkItem(2423, "https://github.com/dotnet/roslyn/issues/2423")>
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsIntroduceVariable)>
Public Async Function TestPickNameBasedOnArgument1() As Task
Await TestInRegularAndScriptAsync(
"class C
public sub new(a as string, b as string)
dim c = new TextSpan([|integer.Parse(a)|], integer.Parse(b))
end sub
end class
structure TextSpan
public sub new(start as integer, length as integer)
end sub
end structure",
"class C
public sub new(a as string, b as string)
Dim {|Rename:start|} As Integer = integer.Parse(a)
dim c = new TextSpan(start, integer.Parse(b))
end sub
end class
structure TextSpan
public sub new(start as integer, length as integer)
end sub
end structure")
End Function
<WorkItem(2423, "https://github.com/dotnet/roslyn/issues/2423")>
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsIntroduceVariable)>
Public Async Function TestPickNameBasedOnArgument2() As Task
Await TestInRegularAndScriptAsync(
"class C
public sub new(a as string, b as string)
dim c = new TextSpan(integer.Parse(a), [|integer.Parse(b)|])
end sub
end class
structure TextSpan
public sub new(start as integer, length as integer)
end sub
end structure",
"class C
public sub new(a as string, b as string)
Dim {|Rename:length|} As Integer = integer.Parse(b)
dim c = new TextSpan(integer.Parse(a), length)
end sub
end class
structure TextSpan
public sub new(start as integer, length as integer)
end sub
end structure")
End Function
End Class
End Namespace
End Namespace
\ No newline at end of file
......@@ -166,24 +166,18 @@ protected override bool IsClassDeclarationGeneration(SemanticDocument document,
}
protected override ImmutableArray<ParameterName> GenerateParameterNames(
SemanticModel semanticModel, IEnumerable<ArgumentSyntax> arguments, IList<string> reservedNames)
=> semanticModel.GenerateParameterNames(arguments, reservedNames);
SemanticModel semanticModel, IEnumerable<ArgumentSyntax> arguments, IList<string> reservedNames, CancellationToken cancellationToken)
=> semanticModel.GenerateParameterNames(arguments, reservedNames, cancellationToken);
protected override ImmutableArray<ParameterName> GenerateParameterNames(
SemanticModel semanticModel, IEnumerable<AttributeArgumentSyntax> arguments, IList<string> reservedNames)
=> semanticModel.GenerateParameterNames(arguments, reservedNames).ToImmutableArray();
SemanticModel semanticModel, IEnumerable<AttributeArgumentSyntax> arguments, IList<string> reservedNames, CancellationToken cancellationToken)
=> semanticModel.GenerateParameterNames(arguments, reservedNames, cancellationToken).ToImmutableArray();
protected override string GenerateNameForArgument(
SemanticModel semanticModel, ArgumentSyntax argument)
{
return semanticModel.GenerateNameForArgument(argument);
}
protected override string GenerateNameForArgument(SemanticModel semanticModel, ArgumentSyntax argument, CancellationToken cancellationToken)
=> semanticModel.GenerateNameForArgument(argument, cancellationToken);
protected override string GenerateNameForArgument(
SemanticModel semanticModel, AttributeArgumentSyntax argument)
{
return semanticModel.GenerateNameForArgument(argument);
}
protected override string GenerateNameForArgument(SemanticModel semanticModel, AttributeArgumentSyntax argument, CancellationToken cancellationToken)
=> semanticModel.GenerateNameForArgument(argument, cancellationToken);
protected override RefKind GetRefKind(ArgumentSyntax argument)
{
......
......@@ -34,7 +34,7 @@ public InvocationExpressionInfo(SemanticDocument document, State state)
protected override ImmutableArray<ParameterName> DetermineParameterNames(CancellationToken cancellationToken)
{
return this.Document.SemanticModel.GenerateParameterNames(
_invocationExpression.ArgumentList);
_invocationExpression.ArgumentList, cancellationToken);
}
protected override bool DetermineReturnsByRef(CancellationToken cancellationToken)
......
......@@ -526,9 +526,9 @@ protected override bool TryGetArgumentList(ObjectCreationExpressionSyntax object
}
protected override IList<ParameterName> GenerateParameterNames(
SemanticModel semanticModel, IList<ArgumentSyntax> arguments)
SemanticModel semanticModel, IList<ArgumentSyntax> arguments, CancellationToken cancellationToken)
{
return semanticModel.GenerateParameterNames(arguments);
return semanticModel.GenerateParameterNames(arguments, reservedNames: null, cancellationToken: cancellationToken);
}
public override string GetRootNamespace(CompilationOptions options)
......
......@@ -185,7 +185,8 @@ private int NonParamsParameterCount(IMethodSymbol method)
var newMethodDeclaration = GetNewMethodDeclaration(
method, argument, argumentList, generator, methodDeclaration,
semanticFacts, argumentName, expression, semanticModel, parameterType);
semanticFacts, argumentName, expression, semanticModel,
parameterType, cancellationToken);
var root = methodDeclaration.SyntaxTree.GetRoot(cancellationToken);
var newRoot = root.ReplaceNode(methodDeclaration, newMethodDeclaration);
......@@ -206,7 +207,8 @@ private int NonParamsParameterCount(IMethodSymbol method)
string argumentName,
SyntaxNode expression,
SemanticModel semanticModel,
ITypeSymbol parameterType)
ITypeSymbol parameterType,
CancellationToken cancellationToken)
{
if (!string.IsNullOrWhiteSpace(argumentName))
{
......@@ -222,7 +224,8 @@ private int NonParamsParameterCount(IMethodSymbol method)
}
else
{
var name = semanticFacts.GenerateNameForExpression(semanticModel, expression);
var name = semanticFacts.GenerateNameForExpression(
semanticModel, expression, capitalize: false, cancellationToken: cancellationToken);
var uniqueName = NameGenerator.EnsureUniqueness(name, method.Parameters.Select(p => p.Name));
var newParameterSymbol = CodeGenerationSymbolFactory.CreateParameterSymbol(
......
......@@ -188,7 +188,8 @@ private async Task<Document> GenerateDelegatedConstructorAsync()
// delegating.
var remainingParameterNames = _service.GenerateParameterNames(
_document.SemanticModel, remainingArguments,
delegatedConstructor.Parameters.Select(p => p.Name).ToList());
delegatedConstructor.Parameters.Select(p => p.Name).ToList(),
_cancellationToken);
// Can't generate the constructor if the parameter names we're copying over forcibly
// conflict with any names we generated.
......@@ -275,8 +276,8 @@ private async Task<Document> GenerateFieldDelegatingConstructorAsync()
ImmutableArray<TArgumentSyntax> arguments, ImmutableArray<string> typeParametersNames)
{
return _state.AttributeArguments != null
? _service.GenerateParameterNames(_document.SemanticModel, _state.AttributeArguments, typeParametersNames)
: _service.GenerateParameterNames(_document.SemanticModel, arguments, typeParametersNames);
? _service.GenerateParameterNames(_document.SemanticModel, _state.AttributeArguments, typeParametersNames, _cancellationToken)
: _service.GenerateParameterNames(_document.SemanticModel, arguments, typeParametersNames, _cancellationToken);
}
private void GetParameters(
......@@ -364,8 +365,8 @@ private async Task<Document> GenerateFieldDelegatingConstructorAsync()
// use so we can assign to that.
var newFieldName = NameGenerator.EnsureUniqueness(
attributeArguments != null
? _service.GenerateNameForArgument(_document.SemanticModel, attributeArguments.Value[index])
: _service.GenerateNameForArgument(_document.SemanticModel, arguments[index]),
? _service.GenerateNameForArgument(_document.SemanticModel, attributeArguments.Value[index], _cancellationToken)
: _service.GenerateNameForArgument(_document.SemanticModel, arguments[index], _cancellationToken),
GetUnavailableMemberNames().Concat(parameterToNewFieldMap.Values));
if (isFixed)
......
......@@ -30,12 +30,12 @@ protected AbstractGenerateConstructorService()
protected abstract bool TryInitializeClassDeclarationGenerationState(SemanticDocument document, SyntaxNode classDeclaration, CancellationToken cancellationToken, out SyntaxToken token, out IMethodSymbol constructor, out INamedTypeSymbol typeToGenerateIn);
protected abstract bool TryInitializeConstructorInitializerGeneration(SemanticDocument document, SyntaxNode constructorInitializer, CancellationToken cancellationToken, out SyntaxToken token, out ImmutableArray<TArgumentSyntax> arguments, out INamedTypeSymbol typeToGenerateIn);
protected abstract bool TryInitializeSimpleAttributeNameGenerationState(SemanticDocument document, SyntaxNode simpleName, CancellationToken cancellationToken, out SyntaxToken token, out ImmutableArray<TArgumentSyntax> arguments, out ImmutableArray<TAttributeArgumentSyntax> attributeArguments, out INamedTypeSymbol typeToGenerateIn);
protected abstract ImmutableArray<ParameterName> GenerateParameterNames(SemanticModel semanticModel, IEnumerable<TArgumentSyntax> arguments, IList<string> reservedNames = null);
protected virtual ImmutableArray<ParameterName> GenerateParameterNames(SemanticModel semanticModel, IEnumerable<TAttributeArgumentSyntax> arguments, IList<string> reservedNames = null)
protected abstract ImmutableArray<ParameterName> GenerateParameterNames(SemanticModel semanticModel, IEnumerable<TArgumentSyntax> arguments, IList<string> reservedNames, CancellationToken cancellationToken);
protected virtual ImmutableArray<ParameterName> GenerateParameterNames(SemanticModel semanticModel, IEnumerable<TAttributeArgumentSyntax> arguments, IList<string> reservedNames, CancellationToken cancellationToken)
=> default(ImmutableArray<ParameterName>);
protected abstract string GenerateNameForArgument(SemanticModel semanticModel, TArgumentSyntax argument);
protected virtual string GenerateNameForArgument(SemanticModel semanticModel, TAttributeArgumentSyntax argument) { return null; }
protected abstract string GenerateNameForArgument(SemanticModel semanticModel, TArgumentSyntax argument, CancellationToken cancellationToken);
protected virtual string GenerateNameForArgument(SemanticModel semanticModel, TAttributeArgumentSyntax argument, CancellationToken cancellationToken) { return null; }
protected abstract RefKind GetRefKind(TArgumentSyntax argument);
protected abstract bool IsNamedArgument(TArgumentSyntax argument);
protected abstract ITypeSymbol GetArgumentType(SemanticModel semanticModel, TArgumentSyntax argument, CancellationToken cancellationToken);
......
......@@ -206,7 +206,7 @@ private void AddProperties(ArrayBuilder<ISymbol> members)
var availableTypeParameters = _service.GetAvailableTypeParameters(_state, _document.SemanticModel, _intoNamespace, _cancellationToken);
var parameterTypes = GetArgumentTypes(argumentList);
var parameterNames = _service.GenerateParameterNames(_document.SemanticModel, argumentList);
var parameterNames = _service.GenerateParameterNames(_document.SemanticModel, argumentList, _cancellationToken);
var parameters = ArrayBuilder<IParameterSymbol>.GetInstance();
var parameterToExistingFieldMap = new Dictionary<string, ISymbol>();
......
......@@ -39,7 +39,7 @@ protected AbstractGenerateTypeService()
protected abstract string DefaultFileExtension { get; }
protected abstract ImmutableArray<ITypeParameterSymbol> GetTypeParameters(State state, SemanticModel semanticModel, CancellationToken cancellationToken);
protected abstract Accessibility GetAccessibility(State state, SemanticModel semanticModel, bool intoNamespace, CancellationToken cancellationToken);
protected abstract IList<ParameterName> GenerateParameterNames(SemanticModel semanticModel, IList<TArgumentSyntax> arguments);
protected abstract IList<ParameterName> GenerateParameterNames(SemanticModel semanticModel, IList<TArgumentSyntax> arguments, CancellationToken cancellationToken);
protected abstract INamedTypeSymbol DetermineTypeToGenerateIn(SemanticModel semanticModel, TSimpleNameSyntax simpleName, CancellationToken cancellationToken);
protected abstract ITypeSymbol DetermineArgumentType(SemanticModel semanticModel, TArgumentSyntax argument, CancellationToken cancellationToken);
......
......@@ -199,11 +199,12 @@ private CodeAction CreateAction(State state, bool allOccurrences, bool isConstan
bool isConstant,
CancellationToken cancellationToken)
{
var syntaxFacts = document.Project.LanguageServices.GetService<ISyntaxFactsService>();
var semanticFacts = document.Project.LanguageServices.GetService<ISemanticFactsService>();
var syntaxFacts = document.Document.GetLanguageService<ISyntaxFactsService>();
var semanticFacts = document.Document.GetLanguageService<ISemanticFactsService>();
var semanticModel = document.SemanticModel;
var baseName = semanticFacts.GenerateNameForExpression(semanticModel, expression, isConstant);
var baseName = semanticFacts.GenerateNameForExpression(
semanticModel, expression, isConstant, cancellationToken);
// A field can't conflict with any existing member names.
var declaringType = semanticModel.GetEnclosingNamedType(expression.SpanStart, cancellationToken);
......@@ -226,7 +227,8 @@ private CodeAction CreateAction(State state, bool allOccurrences, bool isConstan
var semanticModel = document.SemanticModel;
var existingSymbols = GetExistingSymbols(semanticModel, container, cancellationToken);
var baseName = semanticFacts.GenerateNameForExpression(semanticModel, expression, capitalize: isConstant);
var baseName = semanticFacts.GenerateNameForExpression(
semanticModel, expression, capitalize: isConstant, cancellationToken: cancellationToken);
var reservedNames = semanticModel.LookupSymbols(expression.SpanStart)
.Select(s => s.Name)
.Concat(existingSymbols.Select(s => s.Name));
......
......@@ -14,15 +14,16 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.GenerateConstructor
Partial Friend Class VisualBasicGenerateConstructorService
Inherits AbstractGenerateConstructorService(Of VisualBasicGenerateConstructorService, ArgumentSyntax, AttributeSyntax)
Protected Overrides Function GenerateNameForArgument(semanticModel As SemanticModel, argument As ArgumentSyntax) As String
Return semanticModel.GenerateNameForArgument(argument)
Protected Overrides Function GenerateNameForArgument(semanticModel As SemanticModel, argument As ArgumentSyntax, cancellationToken As CancellationToken) As String
Return semanticModel.GenerateNameForArgument(argument, cancellationToken)
End Function
Protected Overrides Function GenerateParameterNames(
semanticModel As SemanticModel,
arguments As IEnumerable(Of ArgumentSyntax),
Optional reservedNames As IList(Of String) = Nothing) As ImmutableArray(Of ParameterName)
Return semanticModel.GenerateParameterNames(arguments?.ToList(), reservedNames)
reservedNames As IList(Of String),
cancellationToken As CancellationToken) As ImmutableArray(Of ParameterName)
Return semanticModel.GenerateParameterNames(arguments?.ToList(), reservedNames, cancellationToken)
End Function
Protected Overrides Function GetArgumentType(
......
......@@ -28,7 +28,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.GenerateMember.GenerateMethod
Protected Overrides Function DetermineParameterNames(cancellationToken As CancellationToken) As ImmutableArray(Of ParameterName)
Dim typeParametersNames = Me.DetermineTypeParameters(cancellationToken).SelectAsArray(Function(t) t.Name)
Return Me.Document.SemanticModel.GenerateParameterNames(
Me.InvocationExpression.ArgumentList, reservedNames:=typeParametersNames)
Me.InvocationExpression.ArgumentList, reservedNames:=typeParametersNames, cancellationToken:=cancellationToken)
End Function
Protected Overrides Function DetermineReturnsByRef(cancellationToken As CancellationToken) As Boolean
......
......@@ -31,8 +31,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.GenerateType
End Get
End Property
Protected Overrides Function GenerateParameterNames(semanticModel As SemanticModel, arguments As IList(Of ArgumentSyntax)) As IList(Of ParameterName)
Return semanticModel.GenerateParameterNames(arguments)
Protected Overrides Function GenerateParameterNames(semanticModel As SemanticModel, arguments As IList(Of ArgumentSyntax), cancellationToken As CancellationToken) As IList(Of ParameterName)
Return semanticModel.GenerateParameterNames(arguments, reservedNames:=Nothing, cancellationToken:=cancellationToken)
End Function
Protected Overrides Function GetLeftSideOfDot(simpleName As SimpleNameSyntax) As ExpressionSyntax
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
......@@ -170,7 +171,7 @@ private static bool CanBindToken(SyntaxToken token)
/// argument.
/// </summary>
public static string GenerateNameForArgument(
this SemanticModel semanticModel, ArgumentSyntax argument)
this SemanticModel semanticModel, ArgumentSyntax argument, CancellationToken cancellationToken)
{
// If it named argument then we use the name provided.
if (argument.NameColon != null)
......@@ -178,11 +179,12 @@ private static bool CanBindToken(SyntaxToken token)
return argument.NameColon.Name.Identifier.ValueText;
}
return semanticModel.GenerateNameForExpression(argument.Expression);
return semanticModel.GenerateNameForExpression(
argument.Expression, capitalize: false, cancellationToken: cancellationToken);
}
public static string GenerateNameForArgument(
this SemanticModel semanticModel, AttributeArgumentSyntax argument)
this SemanticModel semanticModel, AttributeArgumentSyntax argument, CancellationToken cancellationToken)
{
// If it named argument then we use the name provided.
if (argument.NameEquals != null)
......@@ -190,7 +192,8 @@ private static bool CanBindToken(SyntaxToken token)
return argument.NameEquals.Name.Identifier.ValueText;
}
return semanticModel.GenerateNameForExpression(argument.Expression);
return semanticModel.GenerateNameForExpression(
argument.Expression, capitalize: false, cancellationToken: cancellationToken);
}
/// <summary>
......@@ -198,7 +201,8 @@ private static bool CanBindToken(SyntaxToken token)
/// that expression.
/// </summary>
public static string GenerateNameForExpression(
this SemanticModel semanticModel, ExpressionSyntax expression, bool capitalize = false)
this SemanticModel semanticModel, ExpressionSyntax expression,
bool capitalize, CancellationToken cancellationToken)
{
// Try to find a usable name node that we can use to name the
// parameter. If we have an expression that has a name as part of it
......@@ -244,32 +248,78 @@ private static bool CanBindToken(SyntaxToken token)
}
}
// there was nothing in the expression to signify a name. If we're in an argument
// location, then try to choose a name based on the argument name.
var argumentName = TryGenerateNameForArgumentExpression(
semanticModel, expression, cancellationToken);
if (argumentName != null)
{
return capitalize ? argumentName.ToPascalCase() : argumentName.ToCamelCase();
}
// Otherwise, figure out the type of the expression and generate a name from that
// instead.
var info = semanticModel.GetTypeInfo(expression);
var info = semanticModel.GetTypeInfo(expression, cancellationToken);
// If we can't determine the type, then fallback to some placeholders.
var type = info.Type;
return type.CreateParameterName(capitalize);
}
private static string TryGenerateNameForArgumentExpression(
SemanticModel semanticModel, ExpressionSyntax expression, CancellationToken cancellationToken)
{
var topExpression = expression.WalkUpParentheses();
if (topExpression.IsParentKind(SyntaxKind.Argument))
{
var argument = (ArgumentSyntax)topExpression.Parent;
if (argument.NameColon != null)
{
return argument.NameColon.Name.Identifier.ValueText;
}
var argumentList = argument.Parent as BaseArgumentListSyntax;
if (argumentList != null)
{
var index = argumentList.Arguments.IndexOf(argument);
var member = semanticModel.GetSymbolInfo(argumentList.Parent, cancellationToken).Symbol as IMethodSymbol;
if (member != null && index < member.Parameters.Length)
{
var parameter = member.Parameters[index];
if (parameter.Type.OriginalDefinition.TypeKind != TypeKind.TypeParameter)
{
return parameter.Name;
}
}
}
}
return null;
}
public static ImmutableArray<ParameterName> GenerateParameterNames(
this SemanticModel semanticModel, ArgumentListSyntax argumentList)
this SemanticModel semanticModel,
ArgumentListSyntax argumentList,
CancellationToken cancellationToken)
{
return semanticModel.GenerateParameterNames(argumentList.Arguments);
return semanticModel.GenerateParameterNames(
argumentList.Arguments, reservedNames: null, cancellationToken: cancellationToken);
}
public static IList<ParameterName> GenerateParameterNames(
this SemanticModel semanticModel,
AttributeArgumentListSyntax argumentList)
AttributeArgumentListSyntax argumentList,
CancellationToken cancellationToken)
{
return semanticModel.GenerateParameterNames(argumentList.Arguments);
return semanticModel.GenerateParameterNames(
argumentList.Arguments, reservedNames: null, cancellationToken: cancellationToken);
}
public static ImmutableArray<ParameterName> GenerateParameterNames(
this SemanticModel semanticModel,
IEnumerable<ArgumentSyntax> arguments,
IList<string> reservedNames = null)
IList<string> reservedNames,
CancellationToken cancellationToken)
{
reservedNames = reservedNames ?? SpecializedCollections.EmptyList<string>();
......@@ -278,7 +328,7 @@ private static bool CanBindToken(SyntaxToken token)
arguments.Select(a => a.NameColon != null)).ToList();
var parameterNames = reservedNames.Concat(
arguments.Select(semanticModel.GenerateNameForArgument)).ToList();
arguments.Select(a => semanticModel.GenerateNameForArgument(a, cancellationToken))).ToList();
return GenerateNames(reservedNames, isFixed, parameterNames);
}
......@@ -293,7 +343,8 @@ private static ImmutableArray<ParameterName> GenerateNames(IList<string> reserve
public static IList<ParameterName> GenerateParameterNames(
this SemanticModel semanticModel,
IEnumerable<AttributeArgumentSyntax> arguments,
IList<string> reservedNames = null)
IList<string> reservedNames,
CancellationToken cancellationToken)
{
reservedNames = reservedNames ?? SpecializedCollections.EmptyList<string>();
......@@ -302,7 +353,7 @@ private static ImmutableArray<ParameterName> GenerateNames(IList<string> reserve
arguments.Select(a => a.NameEquals != null)).ToList();
var parameterNames = reservedNames.Concat(
arguments.Select(a => semanticModel.GenerateNameForArgument(a))).ToList();
arguments.Select(a => semanticModel.GenerateNameForArgument(a, cancellationToken))).ToList();
return GenerateNames(reservedNames, isFixed, parameterNames);
}
......
......@@ -108,10 +108,8 @@ public bool CanReplaceWithRValue(SemanticModel semanticModel, SyntaxNode express
return (expression as ExpressionSyntax).CanReplaceWithRValue(semanticModel, cancellationToken);
}
public string GenerateNameForExpression(SemanticModel semanticModel, SyntaxNode expression, bool capitalize = false)
{
return semanticModel.GenerateNameForExpression((ExpressionSyntax)expression, capitalize);
}
public string GenerateNameForExpression(SemanticModel semanticModel, SyntaxNode expression, bool capitalize, CancellationToken cancellationToken)
=> semanticModel.GenerateNameForExpression((ExpressionSyntax)expression, capitalize, cancellationToken);
public ISymbol GetDeclaredSymbol(SemanticModel semanticModel, SyntaxToken token, CancellationToken cancellationToken)
{
......
......@@ -71,7 +71,7 @@ internal interface ISemanticFactsService : ILanguageService
bool CanReplaceWithRValue(SemanticModel semanticModel, SyntaxNode expression, CancellationToken cancellationToken);
string GenerateNameForExpression(SemanticModel semanticModel, SyntaxNode expression, bool capitalize = false);
string GenerateNameForExpression(SemanticModel semanticModel, SyntaxNode expression, bool capitalize, CancellationToken cancellationToken);
ISymbol GetDeclaredSymbol(SemanticModel semanticModel, SyntaxToken token, CancellationToken cancellationToken);
......
......@@ -80,17 +80,20 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions
<Extension()>
Public Function GenerateNameForArgument(semanticModel As SemanticModel,
argument As ArgumentSyntax) As String
Dim result = GenerateNameForArgumentWorker(semanticModel, argument)
argument As ArgumentSyntax,
cancellationToken As CancellationToken) As String
Dim result = GenerateNameForArgumentWorker(semanticModel, argument, cancellationToken)
Return If(String.IsNullOrWhiteSpace(result), s_defaultParameterName, result)
End Function
Private Function GenerateNameForArgumentWorker(semanticModel As SemanticModel,
argument As ArgumentSyntax) As String
argument As ArgumentSyntax,
cancellationToken As CancellationToken) As String
If argument.IsNamed Then
Return DirectCast(argument, SimpleArgumentSyntax).NameColonEquals.Name.Identifier.ValueText
ElseIf Not argument.IsOmitted Then
Return semanticModel.GenerateNameForExpression(argument.GetExpression())
Return semanticModel.GenerateNameForExpression(
argument.GetExpression(), capitalize:=False, cancellationToken:=cancellationToken)
Else
Return s_defaultParameterName
End If
......@@ -103,7 +106,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions
<Extension()>
Public Function GenerateNameForExpression(semanticModel As SemanticModel,
expression As ExpressionSyntax,
Optional capitalize As Boolean = False) As String
capitalize As Boolean,
cancellationToken As CancellationToken) As String
' Try to find a usable name node that we can use to name the
' parameter. If we have an expression that has a name as part of it
' then we try to use that part.
......@@ -122,40 +126,80 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions
End If
End While
' there was nothing in the expression to signify a name. If we're in an argument
' location, then try to choose a name based on the argument name.
Dim argumentName = TryGenerateNameForArgumentExpression(
semanticModel, expression, cancellationToken)
If argumentName IsNot Nothing Then
Return If(capitalize, argumentName.ToPascalCase(), argumentName.ToCamelCase())
End If
' Otherwise, figure out the type of the expression and generate a name from that
' instead.
Dim info = semanticModel.GetTypeInfo(expression)
Dim info = semanticModel.GetTypeInfo(expression, cancellationToken)
' If we can't determine the type, then fallback to some placeholders.
Dim [type] = info.Type
Return [type].CreateParameterName(capitalize)
End Function
Private Function TryGenerateNameForArgumentExpression(semanticModel As SemanticModel, expression As ExpressionSyntax, cancellationToken As CancellationToken) As String
Dim topExpression = expression.WalkUpParentheses()
If TypeOf topExpression.Parent Is ArgumentSyntax Then
Dim argument = DirectCast(topExpression.Parent, ArgumentSyntax)
Dim simpleArgument = TryCast(argument, SimpleArgumentSyntax)
If simpleArgument?.NameColonEquals IsNot Nothing Then
Return simpleArgument.NameColonEquals.Name.Identifier.ValueText
End If
Dim argumentList = TryCast(argument.Parent, ArgumentListSyntax)
If argumentList IsNot Nothing Then
Dim index = argumentList.Arguments.IndexOf(argument)
Dim member = TryCast(semanticModel.GetSymbolInfo(argumentList.Parent, cancellationToken).Symbol, IMethodSymbol)
If member IsNot Nothing AndAlso index < member.Parameters.Length Then
Dim parameter = member.Parameters(index)
If parameter.Type.TypeKind <> TypeKind.TypeParameter Then
Return parameter.Name
End If
End If
End If
End If
Return Nothing
End Function
<Extension()>
Public Function GenerateParameterNames(semanticModel As SemanticModel,
arguments As ArgumentListSyntax,
Optional reservedNames As IEnumerable(Of String) = Nothing) As ImmutableArray(Of ParameterName)
reservedNames As IEnumerable(Of String),
cancellationToken As CancellationToken) As ImmutableArray(Of ParameterName)
If arguments Is Nothing Then
Return ImmutableArray(Of ParameterName).Empty
End If
Return GenerateParameterNames(semanticModel, arguments.Arguments.ToList(), reservedNames)
Return GenerateParameterNames(
semanticModel, arguments.Arguments.ToList(),
reservedNames, cancellationToken)
End Function
<Extension()>
Public Function GenerateParameterNames(semanticModel As SemanticModel,
arguments As IList(Of ArgumentSyntax),
Optional reservedNames As IEnumerable(Of String) = Nothing) As ImmutableArray(Of ParameterName)
reservedNames As IEnumerable(Of String),
cancellationToken As CancellationToken) As ImmutableArray(Of ParameterName)
reservedNames = If(reservedNames, SpecializedCollections.EmptyEnumerable(Of String))
Return semanticModel.GenerateParameterNames(
arguments,
Function(s) Not reservedNames.Any(Function(n) CaseInsensitiveComparison.Equals(s, n)))
Function(s) Not reservedNames.Any(Function(n) CaseInsensitiveComparison.Equals(s, n)),
cancellationToken)
End Function
<Extension()>
Public Function GenerateParameterNames(semanticModel As SemanticModel,
arguments As IList(Of ArgumentSyntax),
canUse As Func(Of String, Boolean)) As ImmutableArray(Of ParameterName)
canUse As Func(Of String, Boolean),
cancellationToken As CancellationToken) As ImmutableArray(Of ParameterName)
If arguments.Count = 0 Then
Return ImmutableArray(Of ParameterName).Empty
End If
......@@ -166,7 +210,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions
Select arg IsNot Nothing AndAlso arg.NameColonEquals IsNot Nothing
Into ToList()
Dim parameterNames = arguments.Select(Function(a) semanticModel.GenerateNameForArgument(a)).ToList()
Dim parameterNames = arguments.Select(Function(a) semanticModel.GenerateNameForArgument(a, cancellationToken)).ToList()
Return NameGenerator.EnsureUniqueness(parameterNames, isFixed, canUse).
Select(Function(name, index) New ParameterName(name, isFixed(index))).
ToImmutableArray()
......
......@@ -124,8 +124,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Public Function GenerateNameForExpression(semanticModel As SemanticModel,
expression As SyntaxNode,
Optional capitalize As Boolean = False) As String Implements ISemanticFactsService.GenerateNameForExpression
Return semanticModel.GenerateNameForExpression(DirectCast(expression, ExpressionSyntax), capitalize)
capitalize As Boolean,
cancellationToken As CancellationToken) As String Implements ISemanticFactsService.GenerateNameForExpression
Return semanticModel.GenerateNameForExpression(
DirectCast(expression, ExpressionSyntax), capitalize, cancellationToken)
End Function
Public Function GetDeclaredSymbol(semanticModel As SemanticModel, token As SyntaxToken, cancellationToken As CancellationToken) As ISymbol Implements ISemanticFactsService.GetDeclaredSymbol
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册