提交 8d8423c2 编写于 作者: S Sam Harwell

Merge CyrusNajmabadi/convertForToForEach into preview3-rollup

......@@ -1567,16 +1567,16 @@ class C
public static void Main()
{
void Local()
{
{|Warning:{
{|Rename:NewMethod|}();
}
}|}
Local();
}
private static void NewMethod()
{
{|Warning:int x = 0;
x++;|}
int x = 0;
x++;
}
}");
}
......@@ -1616,7 +1616,7 @@ static void Main(string[] args)
private static int NewMethod(int v, int i)
{
{|Warning:v = v + i|};
{|Warning:v = v + i;|}
return v;
}
}");
......@@ -1650,14 +1650,14 @@ static void Main(string[] args)
int v = 0;
for(int i=0 ; i<5; i++)
{
v = {|Rename:NewMethod|}(v, i);
{|Warning:v = {|Rename:NewMethod|}(v, i)|};
}
}
}
private static int NewMethod(int v, int i)
{
{|Warning:return v + i|};
return v + i;
}
}");
}
......@@ -1690,14 +1690,14 @@ static void Main(string[] args)
int v = 0;
for(int i=0 ; i<5; i++)
{
i = {|Rename:NewMethod|}(ref v, i);
{|Warning:i = {|Rename:NewMethod|}(ref v, i)|};
}
}
}
private static int NewMethod(ref int v, int i)
{
{|Warning:return v = v + i;|}
return v = v + i;
}
}");
}
......
......@@ -421,24 +421,15 @@ public TestParameters WithFixProviderData(object fixProviderData)
void TestAnnotations(ImmutableArray<TextSpan> expectedSpans, string annotationKind)
{
var annotatedTokens = fixedRoot.GetAnnotatedNodesAndTokens(annotationKind).Select(n => (SyntaxToken)n).ToList();
var annotatedItems = fixedRoot.GetAnnotatedNodesAndTokens(annotationKind).OrderBy(s => s.SpanStart).ToList();
Assert.Equal(expectedSpans.Length, annotatedTokens.Count);
Assert.Equal(expectedSpans.Length, annotatedItems.Count);
if (expectedSpans.Length > 0)
for (var i = 0; i < Math.Min(expectedSpans.Length, annotatedItems.Count); i++)
{
var expectedTokens = TokenUtilities.GetTokens(TokenUtilities.GetSyntaxRoot(expectedText, GetLanguage(), parseOptions));
var actualTokens = TokenUtilities.GetTokens(fixedRoot);
for (var i = 0; i < Math.Min(expectedTokens.Count, actualTokens.Count); i++)
{
var expectedToken = expectedTokens[i];
var actualToken = actualTokens[i];
var actualIsConflict = annotatedTokens.Contains(actualToken);
var expectedIsConflict = expectedSpans.Contains(expectedToken.Span);
Assert.Equal(expectedIsConflict, actualIsConflict);
}
var actual = annotatedItems[i].Span;
var expected = expectedSpans[i];
Assert.Equal(expected, actual);
}
}
}
......
......@@ -3574,7 +3574,7 @@ Module M
Sub Main()
With ""
Dim x = .Equals("", "", StringComparison.InvariantCulture) ' Inline x
Dim y = New List(Of String) With {.Capacity = CBool({|Conflict:.Equals("", "", StringComparison.InvariantCulture)|}).GetHashCode}
Dim y = New List(Of String) With {.Capacity = {|Conflict:CBool(.Equals("", "", StringComparison.InvariantCulture))|}.GetHashCode}
End With
End Sub
End Module
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports Microsoft.CodeAnalysis.CodeRefactorings
Imports Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.CodeRefactorings
Imports Microsoft.CodeAnalysis.VisualBasic.ConvertForToForEach
Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.ConvertForToForEach
Public Class ConvertForToForEachTests
Inherits AbstractVisualBasicCodeActionTest
Protected Overrides Function CreateCodeRefactoringProvider(workspace As Workspace, parameters As TestParameters) As CodeRefactoringProvider
Return New VisualBasicConvertForToForEachCodeRefactoringProvider()
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertForToForEach)>
Public Async Function TestArray1() As Task
Await TestInRegularAndScript1Async(
"imports System
class C
sub Test(array as string())
[||]For i = 0 to array.Length - 1
Console.WriteLine(array(i))
next
end sub
end class",
"imports System
class C
sub Test(array as string())
For Each {|Rename:v|} In array
Console.WriteLine(v)
next
end sub
end class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertForToForEach)>
Public Async Function TestForSelected() As Task
Await TestInRegularAndScript1Async(
"imports System
class C
sub Test(array as string())
[|For|] i = 0 to array.Length - 1
Console.WriteLine(array(i))
next
end sub
end class",
"imports System
class C
sub Test(array as string())
For Each {|Rename:v|} In array
Console.WriteLine(v)
next
end sub
end class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertForToForEach)>
Public Async Function TestAtEndOfFor() As Task
Await TestInRegularAndScript1Async(
"imports System
class C
sub Test(array as string())
For i = 0 to array.Length - 1[||]
Console.WriteLine(array(i))
next
end sub
end class",
"imports System
class C
sub Test(array as string())
For Each {|Rename:v|} In array
Console.WriteLine(v)
next
end sub
end class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertForToForEach)>
Public Async Function TestMissingBeforeFor() As Task
Await TestMissingInRegularAndScriptAsync(
"imports System
class C
sub Test(array as string())
[||] For i = 0 to array.Length - 1
Console.WriteLine(array(i))
next
end sub
end class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertForToForEach)>
Public Async Function TestMissingAfterFor() As Task
Await TestMissingInRegularAndScriptAsync(
"imports System
class C
sub Test(array as string())
For [||]i = 0 to array.Length - 1
Console.WriteLine(array(i))
next
end sub
end class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertForToForEach)>
Public Async Function TestArrayPlusStep1() As Task
Await TestInRegularAndScript1Async(
"imports System
class C
sub Test(array as string())
[||]For i = 0 to array.Length - 1 step 1
Console.WriteLine(array(i))
next
end sub
end class",
"imports System
class C
sub Test(array as string())
For Each {|Rename:v|} In array
Console.WriteLine(v)
next
end sub
end class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertForToForEach)>
Public Async Function TestMissingWithWrongStep() As Task
Await TestMissingInRegularAndScriptAsync(
"imports System
class C
sub Test(array as string())
[||]For i = 0 to array.Length - 1 step 2
Console.WriteLine(array(i))
next
end sub
end class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertForToForEach)>
Public Async Function TestMissingIfReferencingNotDeclaringVariable() As Task
Await TestMissingInRegularAndScriptAsync(
"imports System
class C
sub Test(array as string())
dim i as integer
[||]For i = 0 to array.Length - 1 step 2
Console.WriteLine(array(i))
next
end sub
end class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertForToForEach)>
Public Async Function TestMissingWithIncorrectCondition1() As Task
Await TestMissingInRegularAndScriptAsync(
"imports System
class C
sub Test(array as string())
[||]For i = 0 to array.Length
{
Console.WriteLine(array(i))
next
end sub
end class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertForToForEach)>
Public Async Function TestMissingWithIncorrectCondition2() As Task
Await TestMissingInRegularAndScriptAsync(
"imports System
class C
sub Test(array as string())
[||]For i = 0 to GetLength(array) - 1
{
Console.WriteLine(array(i))
next
end sub
end class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertForToForEach)>
Public Async Function TestMissingWithIncorrectCondition3() As Task
Await TestMissingInRegularAndScriptAsync(
"imports System
class C
sub Test(array as string())
[||]For i = 0 to array.Length - 2
{
Console.WriteLine(array(i))
next
end sub
end class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertForToForEach)>
Public Async Function TestNotStartingAtZero() As Task
Await TestMissingInRegularAndScriptAsync(
"imports System
class C
sub Test(array as string())
[||]For i = 1 to array.Length - 1
{
Console.WriteLine(array(i))
next
end sub
end class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertForToForEach)>
Public Async Function TestList1() As Task
Await TestInRegularAndScript1Async(
"imports System
imports System.Collections.Generic
class C
sub Test(list as IList(of string))
[||]For i = 0 to list.Count - 1
Console.WriteLine(list(i))
next
end sub
end class",
"imports System
imports System.Collections.Generic
class C
sub Test(list as IList(of string))
For Each {|Rename:v|} In list
Console.WriteLine(v)
next
end sub
end class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertForToForEach)>
Public Async Function TestChooseNameFromDeclarationStatement() As Task
Await TestInRegularAndScript1Async(
"imports System
imports System.Collections.Generic
class C
sub Test(list as IList(of string))
[||]For i = 0 to list.Count - 1
dim val = list(i)
Console.WriteLine(list(i))
next
end sub
end class",
"imports System
imports System.Collections.Generic
class C
sub Test(list as IList(of string))
For Each val In list
Console.WriteLine(val)
next
end sub
end class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertForToForEach)>
Public Async Function TestChooseNameAndTypeFromDeclarationStatement() As Task
Await TestInRegularAndScript1Async(
"imports System
imports System.Collections.Generic
class C
sub Test(list as IList(of string))
[||]For i = 0 to list.Count - 1
dim val As Object = list(i)
Console.WriteLine(list(i))
next
end sub
end class",
"imports System
imports System.Collections.Generic
class C
sub Test(list as IList(of string))
For Each val As Object In list
Console.WriteLine(val)
next
end sub
end class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertForToForEach)>
Public Async Function TestChooseNameFromDeclarationStatement_PreserveComments() As Task
Await TestInRegularAndScript1Async(
"imports System
imports System.Collections.Generic
class C
sub Test(list as IList(of string))
[||]For i = 0 to list.Count - 1
' loop comment
dim val = list(i)
Console.WriteLine(list(i))
next
end sub
end class",
"imports System
imports System.Collections.Generic
class C
sub Test(list as IList(of string))
For Each val In list
' loop comment
Console.WriteLine(val)
next
end sub
end class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertForToForEach)>
Public Async Function TestChooseNameFromDeclarationStatement_PreserveDirectives() As Task
Await TestInRegularAndScript1Async(
"imports System
imports System.Collections.Generic
class C
sub Test(list as IList(of string))
[||]For i = 0 to list.Count - 1
#if true
dim val = list(i)
Console.WriteLine(list(i))
#end if
next
end sub
end class",
"imports System
imports System.Collections.Generic
class C
sub Test(list as IList(of string))
For Each val In list
#if true
Console.WriteLine(val)
#end if
next
end sub
end class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertForToForEach)>
Public Async Function TestMissingIfVariableUsedNotForIndexing() As Task
Await TestMissingInRegularAndScriptAsync(
"imports System
class C
sub Test(array as string())
[||]For i = 0 to array.Length - 1
Console.WriteLine(i)
next
end sub
end class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertForToForEach)>
Public Async Function TestMissingIfVariableUsedForIndexingNonCollection() As Task
Await TestMissingInRegularAndScriptAsync(
"imports System
class C
sub Test(array as string())
[||]For i = 0 to array.Length - 1
Console.WriteLine(other(i))
next
end sub
end class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertForToForEach)>
Public Async Function TestWarningIfCollectionWrittenTo() As Task
Await TestInRegularAndScript1Async(
"imports System
class C
sub Test(array as string())
[||]For i = 0 to array.Length - 1
array(i) = 1
next
end sub
end class",
"imports System
class C
sub Test(array as string())
For Each {|Rename:v|} In array
{|Warning:v|} = 1
next
end sub
end class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertForToForEach)>
Public Async Function TestDifferentIndexerAndEnumeratorType() As Task
Await TestInRegularAndScriptAsync(
"imports System
class MyList
default public readonly property Item(i as integer) as string
public function GetEnumerator() as Enumerator
end function
public structure Enumerator
public readonly property Current as object
end structure
end class
class C
sub Test(list as MyList)
' need to use 'string' here to preserve original index semantics.
[||]For i = 0 to list.Length - 1
Console.WriteLine(list(i))
next
end sub
end class",
"imports System
class MyList
default public readonly property Item(i as integer) as string
public function GetEnumerator() as Enumerator
end function
public structure Enumerator
public readonly property Current as object
end structure
end class
class C
sub Test(list as MyList)
' need to use 'string' here to preserve original index semantics.
For Each {|Rename:v|} As String In list
Console.WriteLine(v)
next
end sub
end class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertForToForEach)>
Public Async Function TestSameIndexerAndEnumeratorType() As Task
Await TestInRegularAndScriptAsync(
"imports System
class MyList
default public readonly property Item(i as integer) as object
public function GetEnumerator() as Enumerator
end function
public structure Enumerator
public readonly property Current as object
end structure
end class
class C
sub Test(list as MyList)
' can omit type here since the type stayed the same.
[||]For i = 0 to list.Count - 1
Console.WriteLine(list(i))
next
end sub
end class",
"imports System
class MyList
default public readonly property Item(i as integer) as object
public function GetEnumerator() as Enumerator
end function
public structure Enumerator
public readonly property Current as object
end structure
end class
class C
sub Test(list as MyList)
' can omit type here since the type stayed the same.
For Each {|Rename:v|} In list
Console.WriteLine(v)
next
end sub
end class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsConvertForToForEach)>
Public Async Function TestTrivia() As Task
Await TestInRegularAndScript1Async(
"imports System
class C
sub Test(array as string())
' trivia 1
[||]For i = 0 to array.Length - 1 ' trivia 2
Console.WriteLine(array(i))
next ' trivia 3
end sub
end class",
"imports System
class C
sub Test(array as string())
' trivia 1
For Each {|Rename:v|} In array ' trivia 2
Console.WriteLine(v)
next ' trivia 3
end sub
end class")
End Function
End Class
End Namespace
......@@ -287,6 +287,15 @@ internal class CSharpFeaturesResources {
}
}
/// <summary>
/// Looks up a localized string similar to Convert &apos;for&apos; to &apos;foreach&apos;.
/// </summary>
internal static string Convert_for_to_foreach {
get {
return ResourceManager.GetString("Convert_for_to_foreach", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Convert &apos;if&apos; to &apos;switch&apos;.
/// </summary>
......@@ -467,15 +476,6 @@ internal class CSharpFeaturesResources {
}
}
/// <summary>
/// Looks up a localized string similar to &lt;implicit array creation&gt;.
/// </summary>
internal static string implicit_array_creation {
get {
return ResourceManager.GetString("implicit_array_creation", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to indexer.
/// </summary>
......
......@@ -521,4 +521,7 @@
<data name="Add_parentheses_around_conditional_expression_in_interpolated_string" xml:space="preserve">
<value>Add parentheses</value>
</data>
<data name="Convert_for_to_foreach" xml:space="preserve">
<value>Convert 'for' to 'foreach'</value>
</data>
</root>
\ No newline at end of file
// 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.Composition;
using System.Threading;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.ConvertForToForEach;
using Microsoft.CodeAnalysis.CSharp.CodeGeneration;
using Microsoft.CodeAnalysis.CSharp.CodeStyle.TypeStyle;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.CodeAnalysis.CSharp.ConvertForToForEach
{
[ExportCodeRefactoringProvider(LanguageNames.CSharp, Name = nameof(CSharpConvertForToForEachCodeRefactoringProvider)), Shared]
internal class CSharpConvertForToForEachCodeRefactoringProvider :
AbstractConvertForToForEachCodeRefactoringProvider<
StatementSyntax,
ForStatementSyntax,
ExpressionSyntax,
MemberAccessExpressionSyntax,
TypeSyntax,
VariableDeclaratorSyntax>
{
protected override string GetTitle()
=> CSharpFeaturesResources.Convert_for_to_foreach;
protected override bool IsValidCursorPosition(ForStatementSyntax forStatement, int cursorPos)
{
// If there isn't a selection, then we allow the refactoring from the start of
// 'for' to the start of the open paren, or in the trailing trivia of the c
// close paren.
var startSpan = TextSpan.FromBounds(forStatement.ForKeyword.SpanStart, forStatement.OpenParenToken.SpanStart);
var endSpan = TextSpan.FromBounds(forStatement.CloseParenToken.Span.End, forStatement.CloseParenToken.FullSpan.End);
return startSpan.IntersectsWith(cursorPos) || endSpan.IntersectsWith(cursorPos);
}
protected override SyntaxList<StatementSyntax> GetBodyStatements(ForStatementSyntax forStatement)
=> forStatement.Statement is BlockSyntax block
? block.Statements
: SyntaxFactory.SingletonList(forStatement.Statement);
protected override bool TryGetForStatementComponents(
ForStatementSyntax forStatement,
out SyntaxToken iterationVariable, out ExpressionSyntax initializer,
out MemberAccessExpressionSyntax memberAccess,
out ExpressionSyntax stepValueExpressionOpt,
CancellationToken cancellationToken)
{
// Look for very specific forms. Basically, only minor variations around:
// for (var i = 0; i < expr.Lenth; i++)
if (forStatement.Declaration != null &&
forStatement.Condition.IsKind(SyntaxKind.LessThanExpression) &&
forStatement.Incrementors.Count == 1)
{
var declaration = forStatement.Declaration;
if (declaration.Variables.Count == 1)
{
var declarator = declaration.Variables[0];
if (declarator.Initializer != null)
{
iterationVariable = declarator.Identifier;
initializer = declarator.Initializer.Value;
var binaryExpression = (BinaryExpressionSyntax)forStatement.Condition;
// Look for: i < expr.Length
if (binaryExpression.Left is IdentifierNameSyntax identifierName &&
identifierName.Identifier.ValueText == iterationVariable.ValueText &&
binaryExpression.Right is MemberAccessExpressionSyntax)
{
memberAccess = (MemberAccessExpressionSyntax)binaryExpression.Right;
var incrementor = forStatement.Incrementors[0];
return TryGetStepValue(
iterationVariable, incrementor, out stepValueExpressionOpt, cancellationToken);
}
}
}
}
iterationVariable = default;
memberAccess = default;
initializer = default;
stepValueExpressionOpt = default;
return false;
}
private static bool TryGetStepValue(
SyntaxToken iterationVariable, ExpressionSyntax incrementor,
out ExpressionSyntax stepValue, CancellationToken cancellationToken)
{
// support
// x++
// ++x
// x += constant_1
ExpressionSyntax operand;
switch (incrementor.Kind())
{
case SyntaxKind.PostIncrementExpression:
operand = ((PostfixUnaryExpressionSyntax)incrementor).Operand;
stepValue = default;
break;
case SyntaxKind.PreIncrementExpression:
operand = ((PrefixUnaryExpressionSyntax)incrementor).Operand;
stepValue = default;
break;
case SyntaxKind.AddAssignmentExpression:
var assignment = (AssignmentExpressionSyntax)incrementor;
operand = assignment.Left;
stepValue = assignment.Right;
break;
default:
stepValue = null;
return false;
}
return operand is IdentifierNameSyntax identifierName &&
identifierName.Identifier.ValueText == iterationVariable.ValueText;
}
protected override SyntaxNode ConvertForNode(
ForStatementSyntax forStatement, TypeSyntax typeNode,
SyntaxToken foreachIdentifier, ExpressionSyntax collectionExpression,
ITypeSymbol iterationVariableType, OptionSet optionSet)
{
if (typeNode == null)
{
// types are not apparent in foreach statements.
var isBuiltInTypeContext = TypeStyleHelper.IsBuiltInType(iterationVariableType);
if (TypeStyleHelper.IsImplicitStylePreferred(
optionSet, isBuiltInTypeContext, isTypeApparentContext: false))
{
typeNode = SyntaxFactory.IdentifierName("var");
}
else
{
typeNode = (TypeSyntax)CSharpSyntaxGenerator.Instance.TypeExpression(iterationVariableType);
}
}
return SyntaxFactory.ForEachStatement(
SyntaxFactory.Token(SyntaxKind.ForEachKeyword).WithTriviaFrom(forStatement.ForKeyword),
forStatement.OpenParenToken,
typeNode,
foreachIdentifier,
SyntaxFactory.Token(SyntaxKind.InKeyword),
collectionExpression,
forStatement.CloseParenToken,
forStatement.Statement);
}
// C# has no special variable declarator forms that would cause us to not be able to convert.
protected override bool IsValidVariableDeclarator(VariableDeclaratorSyntax firstVariable)
=> true;
}
}
......@@ -27,8 +27,8 @@ private static bool IsAnyQueryClause(SyntaxNode node)
var oldOutermostQuery = expression.GetAncestorsOrThis<QueryExpressionSyntax>().LastOrDefault();
var newLocalNameToken = GenerateUniqueLocalName(
document, expression, isConstant: false,
container: oldOutermostQuery, cancellationToken: cancellationToken);
document, expression, isConstant: false,
containerOpt: oldOutermostQuery, cancellationToken: cancellationToken);
var newLocalName = SyntaxFactory.IdentifierName(newLocalNameToken);
var letClause = SyntaxFactory.LetClause(
......
......@@ -632,6 +632,11 @@
<target state="new">Add parentheses</target>
<note />
</trans-unit>
<trans-unit id="Convert_for_to_foreach">
<source>Convert 'for' to 'foreach'</source>
<target state="new">Convert 'for' to 'foreach'</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -632,6 +632,11 @@
<target state="new">Add parentheses</target>
<note />
</trans-unit>
<trans-unit id="Convert_for_to_foreach">
<source>Convert 'for' to 'foreach'</source>
<target state="new">Convert 'for' to 'foreach'</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -632,6 +632,11 @@
<target state="new">Add parentheses</target>
<note />
</trans-unit>
<trans-unit id="Convert_for_to_foreach">
<source>Convert 'for' to 'foreach'</source>
<target state="new">Convert 'for' to 'foreach'</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -632,6 +632,11 @@
<target state="new">Add parentheses</target>
<note />
</trans-unit>
<trans-unit id="Convert_for_to_foreach">
<source>Convert 'for' to 'foreach'</source>
<target state="new">Convert 'for' to 'foreach'</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -632,6 +632,11 @@
<target state="new">Add parentheses</target>
<note />
</trans-unit>
<trans-unit id="Convert_for_to_foreach">
<source>Convert 'for' to 'foreach'</source>
<target state="new">Convert 'for' to 'foreach'</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -632,6 +632,11 @@
<target state="new">Add parentheses</target>
<note />
</trans-unit>
<trans-unit id="Convert_for_to_foreach">
<source>Convert 'for' to 'foreach'</source>
<target state="new">Convert 'for' to 'foreach'</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -632,6 +632,11 @@
<target state="new">Add parentheses</target>
<note />
</trans-unit>
<trans-unit id="Convert_for_to_foreach">
<source>Convert 'for' to 'foreach'</source>
<target state="new">Convert 'for' to 'foreach'</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -632,6 +632,11 @@
<target state="new">Add parentheses</target>
<note />
</trans-unit>
<trans-unit id="Convert_for_to_foreach">
<source>Convert 'for' to 'foreach'</source>
<target state="new">Convert 'for' to 'foreach'</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -632,6 +632,11 @@
<target state="new">Add parentheses</target>
<note />
</trans-unit>
<trans-unit id="Convert_for_to_foreach">
<source>Convert 'for' to 'foreach'</source>
<target state="new">Convert 'for' to 'foreach'</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -632,6 +632,11 @@
<target state="new">Add parentheses</target>
<note />
</trans-unit>
<trans-unit id="Convert_for_to_foreach">
<source>Convert 'for' to 'foreach'</source>
<target state="new">Convert 'for' to 'foreach'</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -632,6 +632,11 @@
<target state="new">Add parentheses</target>
<note />
</trans-unit>
<trans-unit id="Convert_for_to_foreach">
<source>Convert 'for' to 'foreach'</source>
<target state="new">Convert 'for' to 'foreach'</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -632,6 +632,11 @@
<target state="new">Add parentheses</target>
<note />
</trans-unit>
<trans-unit id="Convert_for_to_foreach">
<source>Convert 'for' to 'foreach'</source>
<target state="new">Convert 'for' to 'foreach'</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -632,6 +632,11 @@
<target state="new">Add parentheses</target>
<note />
</trans-unit>
<trans-unit id="Convert_for_to_foreach">
<source>Convert 'for' to 'foreach'</source>
<target state="new">Convert 'for' to 'foreach'</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -428,6 +428,15 @@ internal class FeaturesResources {
}
}
/// <summary>
/// Looks up a localized string similar to Alias ambiguous type &apos;{0}&apos;.
/// </summary>
internal static string Alias_ambiguous_type_0 {
get {
return ResourceManager.GetString("Alias_ambiguous_type_0", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to All lowercase.
/// </summary>
......@@ -3635,15 +3644,6 @@ internal class FeaturesResources {
}
}
/// <summary>
/// Looks up a localized string similar to Variable declaration can be deconstructed.
/// </summary>
internal static string Variable_declaration_can_be_deconstructed {
get {
return ResourceManager.GetString("Variable_declaration_can_be_deconstructed", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Using readonly references will prevent the debug session from continuing..
/// </summary>
......@@ -3671,6 +3671,15 @@ internal class FeaturesResources {
}
}
/// <summary>
/// Looks up a localized string similar to Variable declaration can be deconstructed.
/// </summary>
internal static string Variable_declaration_can_be_deconstructed {
get {
return ResourceManager.GetString("Variable_declaration_can_be_deconstructed", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Variable declaration can be inlined.
/// </summary>
......@@ -3689,6 +3698,24 @@ internal class FeaturesResources {
}
}
/// <summary>
/// Looks up a localized string similar to Warning: Collection may be modified during iteration..
/// </summary>
internal static string Warning_colon_Collection_may_be_modified_during_iteration {
get {
return ResourceManager.GetString("Warning_colon_Collection_may_be_modified_during_iteration", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Warning: Collection was modified during iteration..
/// </summary>
internal static string Warning_colon_Collection_was_modified_during_iteration {
get {
return ResourceManager.GetString("Warning_colon_Collection_was_modified_during_iteration", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Warning: Declaration changes scope and may change meaning..
/// </summary>
......@@ -3698,6 +3725,15 @@ internal class FeaturesResources {
}
}
/// <summary>
/// Looks up a localized string similar to Warning: Iteration variable crossed function boundary..
/// </summary>
internal static string Warning_colon_Iteration_variable_crossed_function_boundary {
get {
return ResourceManager.GetString("Warning_colon_Iteration_variable_crossed_function_boundary", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Warning: Method overrides symbol from metadata.
/// </summary>
......
......@@ -1334,4 +1334,16 @@ This version used in: {2}</value>
<data name="indexer_" xml:space="preserve">
<value>indexer</value>
</data>
</root>
<data name="Alias_ambiguous_type_0" xml:space="preserve">
<value>Alias ambiguous type '{0}'</value>
</data>
<data name="Warning_colon_Collection_was_modified_during_iteration" xml:space="preserve">
<value>Warning: Collection was modified during iteration.</value>
</data>
<data name="Warning_colon_Iteration_variable_crossed_function_boundary" xml:space="preserve">
<value>Warning: Iteration variable crossed function boundary.</value>
</data>
<data name="Warning_colon_Collection_may_be_modified_during_iteration" xml:space="preserve">
<value>Warning: Collection may be modified during iteration.</value>
</data>
</root>
\ No newline at end of file
......@@ -218,23 +218,17 @@ private CodeAction CreateAction(State state, bool allOccurrences, bool isConstan
SemanticDocument document,
TExpressionSyntax expression,
bool isConstant,
SyntaxNode container,
SyntaxNode containerOpt,
CancellationToken cancellationToken)
{
var syntaxFacts = document.Document.GetLanguageService<ISyntaxFactsService>();
var semanticFacts = document.Document.GetLanguageService<ISemanticFactsService>();
var semanticModel = document.SemanticModel;
var existingSymbols = semanticModel.GetExistingSymbols(container, cancellationToken);
var semanticFacts = document.Document.GetLanguageService<ISemanticFactsService>();
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));
return syntaxFacts.ToIdentifierToken(
NameGenerator.EnsureUniqueness(baseName, reservedNames, syntaxFacts.IsCaseSensitive));
return semanticFacts.GenerateUniqueName(
semanticModel, expression, containerOpt, baseName, cancellationToken);
}
protected ISet<TExpressionSyntax> FindMatches(
......@@ -277,7 +271,7 @@ where NodeMatchesExpression(originalSemanticModel, currentSemanticModel, syntaxF
if (allOccurrences &&
this.CanReplace(nodeInCurrent))
{
return SemanticEquivalence.AreSemanticallyEquivalent(
return SemanticEquivalence.AreEquivalent(
originalSemanticModel, currentSemanticModel, expressionInOriginal, nodeInCurrent);
}
}
......
......@@ -1985,6 +1985,26 @@ Tato verze se používá zde: {2}.</target>
<target state="translated">indexer</target>
<note />
</trans-unit>
<trans-unit id="Alias_ambiguous_type_0">
<source>Alias ambiguous type '{0}'</source>
<target state="new">Alias ambiguous type '{0}'</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Collection_was_modified_during_iteration">
<source>Warning: Collection was modified during iteration.</source>
<target state="new">Warning: Collection was modified during iteration.</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Iteration_variable_crossed_function_boundary">
<source>Warning: Iteration variable crossed function boundary.</source>
<target state="new">Warning: Iteration variable crossed function boundary.</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Collection_may_be_modified_during_iteration">
<source>Warning: Collection may be modified during iteration.</source>
<target state="new">Warning: Collection may be modified during iteration.</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -1985,6 +1985,26 @@ Diese Version wird verwendet in: {2}</target>
<target state="translated">Indexer</target>
<note />
</trans-unit>
<trans-unit id="Alias_ambiguous_type_0">
<source>Alias ambiguous type '{0}'</source>
<target state="new">Alias ambiguous type '{0}'</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Collection_was_modified_during_iteration">
<source>Warning: Collection was modified during iteration.</source>
<target state="new">Warning: Collection was modified during iteration.</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Iteration_variable_crossed_function_boundary">
<source>Warning: Iteration variable crossed function boundary.</source>
<target state="new">Warning: Iteration variable crossed function boundary.</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Collection_may_be_modified_during_iteration">
<source>Warning: Collection may be modified during iteration.</source>
<target state="new">Warning: Collection may be modified during iteration.</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -1985,6 +1985,26 @@ Esta versión se utiliza en: {2}</target>
<target state="translated">indizador</target>
<note />
</trans-unit>
<trans-unit id="Alias_ambiguous_type_0">
<source>Alias ambiguous type '{0}'</source>
<target state="new">Alias ambiguous type '{0}'</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Collection_was_modified_during_iteration">
<source>Warning: Collection was modified during iteration.</source>
<target state="new">Warning: Collection was modified during iteration.</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Iteration_variable_crossed_function_boundary">
<source>Warning: Iteration variable crossed function boundary.</source>
<target state="new">Warning: Iteration variable crossed function boundary.</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Collection_may_be_modified_during_iteration">
<source>Warning: Collection may be modified during iteration.</source>
<target state="new">Warning: Collection may be modified during iteration.</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -1985,6 +1985,26 @@ Version utilisée dans : {2}</target>
<target state="translated">indexeur</target>
<note />
</trans-unit>
<trans-unit id="Alias_ambiguous_type_0">
<source>Alias ambiguous type '{0}'</source>
<target state="new">Alias ambiguous type '{0}'</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Collection_was_modified_during_iteration">
<source>Warning: Collection was modified during iteration.</source>
<target state="new">Warning: Collection was modified during iteration.</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Iteration_variable_crossed_function_boundary">
<source>Warning: Iteration variable crossed function boundary.</source>
<target state="new">Warning: Iteration variable crossed function boundary.</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Collection_may_be_modified_during_iteration">
<source>Warning: Collection may be modified during iteration.</source>
<target state="new">Warning: Collection may be modified during iteration.</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -1985,6 +1985,26 @@ Questa versione è usata {2}</target>
<target state="translated">indicizzatore</target>
<note />
</trans-unit>
<trans-unit id="Alias_ambiguous_type_0">
<source>Alias ambiguous type '{0}'</source>
<target state="new">Alias ambiguous type '{0}'</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Collection_was_modified_during_iteration">
<source>Warning: Collection was modified during iteration.</source>
<target state="new">Warning: Collection was modified during iteration.</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Iteration_variable_crossed_function_boundary">
<source>Warning: Iteration variable crossed function boundary.</source>
<target state="new">Warning: Iteration variable crossed function boundary.</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Collection_may_be_modified_during_iteration">
<source>Warning: Collection may be modified during iteration.</source>
<target state="new">Warning: Collection may be modified during iteration.</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -1985,6 +1985,26 @@ This version used in: {2}</source>
<target state="translated">インデクサー</target>
<note />
</trans-unit>
<trans-unit id="Alias_ambiguous_type_0">
<source>Alias ambiguous type '{0}'</source>
<target state="new">Alias ambiguous type '{0}'</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Collection_was_modified_during_iteration">
<source>Warning: Collection was modified during iteration.</source>
<target state="new">Warning: Collection was modified during iteration.</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Iteration_variable_crossed_function_boundary">
<source>Warning: Iteration variable crossed function boundary.</source>
<target state="new">Warning: Iteration variable crossed function boundary.</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Collection_may_be_modified_during_iteration">
<source>Warning: Collection may be modified during iteration.</source>
<target state="new">Warning: Collection may be modified during iteration.</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -1985,6 +1985,26 @@ This version used in: {2}</source>
<target state="translated">인덱서</target>
<note />
</trans-unit>
<trans-unit id="Alias_ambiguous_type_0">
<source>Alias ambiguous type '{0}'</source>
<target state="new">Alias ambiguous type '{0}'</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Collection_was_modified_during_iteration">
<source>Warning: Collection was modified during iteration.</source>
<target state="new">Warning: Collection was modified during iteration.</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Iteration_variable_crossed_function_boundary">
<source>Warning: Iteration variable crossed function boundary.</source>
<target state="new">Warning: Iteration variable crossed function boundary.</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Collection_may_be_modified_during_iteration">
<source>Warning: Collection may be modified during iteration.</source>
<target state="new">Warning: Collection may be modified during iteration.</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -1985,6 +1985,26 @@ Ta wersja jest używana wersja: {2}</target>
<target state="translated">indeksator</target>
<note />
</trans-unit>
<trans-unit id="Alias_ambiguous_type_0">
<source>Alias ambiguous type '{0}'</source>
<target state="new">Alias ambiguous type '{0}'</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Collection_was_modified_during_iteration">
<source>Warning: Collection was modified during iteration.</source>
<target state="new">Warning: Collection was modified during iteration.</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Iteration_variable_crossed_function_boundary">
<source>Warning: Iteration variable crossed function boundary.</source>
<target state="new">Warning: Iteration variable crossed function boundary.</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Collection_may_be_modified_during_iteration">
<source>Warning: Collection may be modified during iteration.</source>
<target state="new">Warning: Collection may be modified during iteration.</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -1985,6 +1985,26 @@ Essa versão é usada no: {2}</target>
<target state="translated">indexador</target>
<note />
</trans-unit>
<trans-unit id="Alias_ambiguous_type_0">
<source>Alias ambiguous type '{0}'</source>
<target state="new">Alias ambiguous type '{0}'</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Collection_was_modified_during_iteration">
<source>Warning: Collection was modified during iteration.</source>
<target state="new">Warning: Collection was modified during iteration.</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Iteration_variable_crossed_function_boundary">
<source>Warning: Iteration variable crossed function boundary.</source>
<target state="new">Warning: Iteration variable crossed function boundary.</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Collection_may_be_modified_during_iteration">
<source>Warning: Collection may be modified during iteration.</source>
<target state="new">Warning: Collection may be modified during iteration.</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -1985,6 +1985,26 @@ This version used in: {2}</source>
<target state="translated">индексатор</target>
<note />
</trans-unit>
<trans-unit id="Alias_ambiguous_type_0">
<source>Alias ambiguous type '{0}'</source>
<target state="new">Alias ambiguous type '{0}'</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Collection_was_modified_during_iteration">
<source>Warning: Collection was modified during iteration.</source>
<target state="new">Warning: Collection was modified during iteration.</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Iteration_variable_crossed_function_boundary">
<source>Warning: Iteration variable crossed function boundary.</source>
<target state="new">Warning: Iteration variable crossed function boundary.</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Collection_may_be_modified_during_iteration">
<source>Warning: Collection may be modified during iteration.</source>
<target state="new">Warning: Collection may be modified during iteration.</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -1985,6 +1985,26 @@ Bu sürüm şurada kullanılır: {2}</target>
<target state="translated">dizin oluşturucu</target>
<note />
</trans-unit>
<trans-unit id="Alias_ambiguous_type_0">
<source>Alias ambiguous type '{0}'</source>
<target state="new">Alias ambiguous type '{0}'</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Collection_was_modified_during_iteration">
<source>Warning: Collection was modified during iteration.</source>
<target state="new">Warning: Collection was modified during iteration.</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Iteration_variable_crossed_function_boundary">
<source>Warning: Iteration variable crossed function boundary.</source>
<target state="new">Warning: Iteration variable crossed function boundary.</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Collection_may_be_modified_during_iteration">
<source>Warning: Collection may be modified during iteration.</source>
<target state="new">Warning: Collection may be modified during iteration.</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -1985,6 +1985,26 @@ This version used in: {2}</source>
<target state="translated">索引器</target>
<note />
</trans-unit>
<trans-unit id="Alias_ambiguous_type_0">
<source>Alias ambiguous type '{0}'</source>
<target state="new">Alias ambiguous type '{0}'</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Collection_was_modified_during_iteration">
<source>Warning: Collection was modified during iteration.</source>
<target state="new">Warning: Collection was modified during iteration.</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Iteration_variable_crossed_function_boundary">
<source>Warning: Iteration variable crossed function boundary.</source>
<target state="new">Warning: Iteration variable crossed function boundary.</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Collection_may_be_modified_during_iteration">
<source>Warning: Collection may be modified during iteration.</source>
<target state="new">Warning: Collection may be modified during iteration.</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -1985,6 +1985,26 @@ This version used in: {2}</source>
<target state="translated">索引子</target>
<note />
</trans-unit>
<trans-unit id="Alias_ambiguous_type_0">
<source>Alias ambiguous type '{0}'</source>
<target state="new">Alias ambiguous type '{0}'</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Collection_was_modified_during_iteration">
<source>Warning: Collection was modified during iteration.</source>
<target state="new">Warning: Collection was modified during iteration.</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Iteration_variable_crossed_function_boundary">
<source>Warning: Iteration variable crossed function boundary.</source>
<target state="new">Warning: Iteration variable crossed function boundary.</target>
<note />
</trans-unit>
<trans-unit id="Warning_colon_Collection_may_be_modified_during_iteration">
<source>Warning: Collection may be modified during iteration.</source>
<target state="new">Warning: Collection may be modified during iteration.</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Composition
Imports System.Threading
Imports Microsoft.CodeAnalysis.CodeRefactorings
Imports Microsoft.CodeAnalysis.ConvertForToForEach
Imports Microsoft.CodeAnalysis.Options
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic.ConvertForToForEach
<ExportCodeRefactoringProvider(LanguageNames.VisualBasic, Name:=NameOf(VisualBasicConvertForToForEachCodeRefactoringProvider)), [Shared]>
Friend Class VisualBasicConvertForToForEachCodeRefactoringProvider
Inherits AbstractConvertForToForEachCodeRefactoringProvider(Of
StatementSyntax,
ForBlockSyntax,
ExpressionSyntax,
MemberAccessExpressionSyntax,
TypeSyntax,
VariableDeclaratorSyntax)
Protected Overrides Function GetTitle() As String
Return VBFeaturesResources.Convert_For_to_For_Each
End Function
Protected Overrides Function IsValidCursorPosition(forBlock As ForBlockSyntax, cursorPos As Integer) As Boolean
' If there isn't a selection, then we allow the refactoring in the 'for' keyword, or at the end
' of hte for-statement signature.
Dim forStatement = forBlock.ForStatement
Dim startSpan = forStatement.ForKeyword.Span
Dim endSpan = TextSpan.FromBounds(forStatement.Span.End, forStatement.FullSpan.End)
Return startSpan.IntersectsWith(cursorPos) OrElse endSpan.IntersectsWith(cursorPos)
End Function
Protected Overrides Function GetBodyStatements(forStatement As ForBlockSyntax) As SyntaxList(Of StatementSyntax)
Return forStatement.Statements
End Function
Protected Overrides Function IsValidVariableDeclarator(firstVariable As VariableDeclaratorSyntax) As Boolean
' we only support local declarations in vb that have a single identifier. i.e.
' dim x = list(i)
Return firstVariable.Names.Count = 1
End Function
Protected Overrides Function TryGetForStatementComponents(
forBlock As ForBlockSyntax,
ByRef iterationVariable As SyntaxToken,
ByRef initializer As ExpressionSyntax,
ByRef memberAccess As MemberAccessExpressionSyntax,
ByRef stepValueExpressionOpt As ExpressionSyntax,
cancellationToken As CancellationToken) As Boolean
Dim forStatement As ForStatementSyntax = forBlock.ForStatement
Dim identifierName = TryCast(forStatement.ControlVariable, IdentifierNameSyntax)
If identifierName IsNot Nothing Then
iterationVariable = identifierName.Identifier
If forStatement.FromValue IsNot Nothing Then
initializer = forStatement.FromValue
Dim subtraction = TryCast(forStatement.ToValue, BinaryExpressionSyntax)
If subtraction?.Kind() = SyntaxKind.SubtractExpression Then
Dim subtractionRight = TryCast(subtraction.Right, LiteralExpressionSyntax)
If TypeOf subtractionRight.Token.Value Is Integer AndAlso
DirectCast(subtractionRight.Token.Value, Integer) = 1 Then
memberAccess = TryCast(subtraction.Left, MemberAccessExpressionSyntax)
If memberAccess IsNot Nothing Then
stepValueExpressionOpt = forStatement.StepClause?.StepValue
Return True
End If
End If
End If
End If
End If
Return False
End Function
Protected Overrides Function ConvertForNode(
currentFor As ForBlockSyntax, typeNode As TypeSyntax,
foreachIdentifier As SyntaxToken, collectionExpression As ExpressionSyntax, iterationVariableType As ITypeSymbol, options As OptionSet) As SyntaxNode
Dim forStatement = currentFor.ForStatement
Return SyntaxFactory.ForEachBlock(
SyntaxFactory.ForEachStatement(
forStatement.ForKeyword,
SyntaxFactory.Token(SyntaxKind.EachKeyword),
SyntaxFactory.VariableDeclarator(
SyntaxFactory.SingletonSeparatedList(SyntaxFactory.ModifiedIdentifier(foreachIdentifier)),
If(typeNode IsNot Nothing, SyntaxFactory.SimpleAsClause(typeNode), Nothing),
Nothing),
SyntaxFactory.Token(SyntaxKind.InKeyword),
collectionExpression).WithTriviaFrom(forStatement),
currentFor.Statements,
currentFor.NextStatement)
End Function
End Class
End Namespace
......@@ -23,7 +23,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.IntroduceVariable
Nothing)
Dim newNameToken = GenerateUniqueLocalName(
document, expression, isConstant, container:=Nothing,
document, expression, isConstant, containerOpt:=Nothing,
cancellationToken:=cancellationToken)
Dim newQualifiedName = SyntaxFactory.SimpleMemberAccessExpression(
......
......@@ -18,7 +18,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.IntroduceVariable
Dim newLocalNameToken = GenerateUniqueLocalName(
document, expression, isConstant:=False,
container:=oldOutermostQuery, cancellationToken:=cancellationToken)
containerOpt:=oldOutermostQuery, cancellationToken:=cancellationToken)
Dim newLocalName = SyntaxFactory.IdentifierName(newLocalNameToken)
Dim letClause = SyntaxFactory.LetClause(
......
......@@ -476,6 +476,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.VBFeaturesResources
End Get
End Property
'''<summary>
''' Looks up a localized string similar to Convert &apos;For&apos; to &apos;For Each&apos;.
'''</summary>
Friend ReadOnly Property Convert_For_to_For_Each() As String
Get
Return ResourceManager.GetString("Convert_For_to_For_Each", resourceCulture)
End Get
End Property
'''<summary>
''' Looks up a localized string similar to Convert &apos;If&apos; to &apos;Select Case&apos;.
'''</summary>
......@@ -3353,7 +3362,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.VBFeaturesResources
Return ResourceManager.GetString("Using_statement", resourceCulture)
End Get
End Property
'''<summary>
''' Looks up a localized string similar to When a run-time error occurs, execution transfers to the statement following the statement or procedure call that resulted in the error..
'''</summary>
......
......@@ -1247,4 +1247,7 @@ Sub(&lt;parameterList&gt;) &lt;statement&gt;</value>
<data name="Use_IsNot_Nothing_check" xml:space="preserve">
<value>Use 'IsNot Nothing' check</value>
</data>
<data name="Convert_For_to_For_Each" xml:space="preserve">
<value>Convert 'For' to 'For Each'</value>
</data>
</root>
\ No newline at end of file
......@@ -1817,6 +1817,11 @@ Sub(&lt;seznam_parametrů&gt;) &lt;výraz&gt;</target>
<target state="translated">Použít kontrolu „IsNot Nothing“</target>
<note />
</trans-unit>
<trans-unit id="Convert_For_to_For_Each">
<source>Convert 'For' to 'For Each'</source>
<target state="new">Convert 'For' to 'For Each'</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -1817,6 +1817,11 @@ Sub(&lt;Parameterliste&gt;) &lt;Ausdruck&gt;</target>
<target state="translated">Prüfung "IsNot Nothing" verwenden</target>
<note />
</trans-unit>
<trans-unit id="Convert_For_to_For_Each">
<source>Convert 'For' to 'For Each'</source>
<target state="new">Convert 'For' to 'For Each'</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -1817,6 +1817,11 @@ Sub(&lt;listaDeParámetros&gt;) &lt;instrucción&gt;</target>
<target state="translated">Usar comprobación "IsNot Nothing"</target>
<note />
</trans-unit>
<trans-unit id="Convert_For_to_For_Each">
<source>Convert 'For' to 'For Each'</source>
<target state="new">Convert 'For' to 'For Each'</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -1817,6 +1817,11 @@ Sub(&lt;parameterList&gt;) &lt;statement&gt;</target>
<target state="translated">Utiliser la vérification 'IsNot Nothing'</target>
<note />
</trans-unit>
<trans-unit id="Convert_For_to_For_Each">
<source>Convert 'For' to 'For Each'</source>
<target state="new">Convert 'For' to 'For Each'</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -1817,6 +1817,11 @@ Sub(&lt;elencoParametri&gt;) &lt;istruzione&gt;</target>
<target state="translated">Usa controllo 'IsNot Nothing'</target>
<note />
</trans-unit>
<trans-unit id="Convert_For_to_For_Each">
<source>Convert 'For' to 'For Each'</source>
<target state="new">Convert 'For' to 'For Each'</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -1816,6 +1816,11 @@ Sub(&lt;parameterList&gt;) &lt;statement&gt;</target>
<target state="translated">IsNot Nothing' チェックを使用します</target>
<note />
</trans-unit>
<trans-unit id="Convert_For_to_For_Each">
<source>Convert 'For' to 'For Each'</source>
<target state="new">Convert 'For' to 'For Each'</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -1817,6 +1817,11 @@ Sub(&lt;parameterList&gt;) &lt;statement&gt;</target>
<target state="translated">IsNot Nothing' 검사 사용</target>
<note />
</trans-unit>
<trans-unit id="Convert_For_to_For_Each">
<source>Convert 'For' to 'For Each'</source>
<target state="new">Convert 'For' to 'For Each'</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -1817,6 +1817,11 @@ Sub(&lt;listaParametrów&gt;) &lt;instrukcja&gt;</target>
<target state="translated">Użyj sprawdzania „IsNot Nothing”</target>
<note />
</trans-unit>
<trans-unit id="Convert_For_to_For_Each">
<source>Convert 'For' to 'For Each'</source>
<target state="new">Convert 'For' to 'For Each'</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -1817,6 +1817,11 @@ Sub(&lt;parameterList&gt;) &lt;statement&gt;</target>
<target state="translated">Usar a verificação 'IsNot Nothing'</target>
<note />
</trans-unit>
<trans-unit id="Convert_For_to_For_Each">
<source>Convert 'For' to 'For Each'</source>
<target state="new">Convert 'For' to 'For Each'</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -1817,6 +1817,11 @@ Sub(&lt;parameterList&gt;) &lt;statement&gt;</target>
<target state="translated">Использовать флажок "IsNot Nothing"</target>
<note />
</trans-unit>
<trans-unit id="Convert_For_to_For_Each">
<source>Convert 'For' to 'For Each'</source>
<target state="new">Convert 'For' to 'For Each'</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -1817,6 +1817,11 @@ Sub(&lt;parameterList&gt;) &lt;statement&gt;</target>
<target state="translated">IsNot Nothing' denetimi kullan</target>
<note />
</trans-unit>
<trans-unit id="Convert_For_to_For_Each">
<source>Convert 'For' to 'For Each'</source>
<target state="new">Convert 'For' to 'For Each'</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -1817,6 +1817,11 @@ Sub(&lt;parameterList&gt;) &lt;statement&gt;</target>
<target state="translated">使用 "IsNot Nothing" 检查</target>
<note />
</trans-unit>
<trans-unit id="Convert_For_to_For_Each">
<source>Convert 'For' to 'For Each'</source>
<target state="new">Convert 'For' to 'For Each'</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -1817,6 +1817,11 @@ Sub(&lt;parameterList&gt;) &lt;statement&gt;</target>
<target state="translated">使用 'IsNot Nothing' 檢查</target>
<note />
</trans-unit>
<trans-unit id="Convert_For_to_For_Each">
<source>Convert 'For' to 'For Each'</source>
<target state="new">Convert 'For' to 'For Each'</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
\ No newline at end of file
......@@ -49,6 +49,7 @@ public static class Features
public const string CodeActionsConvertNumericLiteral = "CodeActions.ConvertNumericLiteral";
public const string CodeActionsConvertToInterpolatedString = "CodeActions.ConvertToInterpolatedString";
public const string CodeActionsConvertToIterator = "CodeActions.ConvertToIterator";
public const string CodeActionsConvertForToForEach = "CodeActions.ConvertForToForEach";
public const string CodeActionsConvertIfToSwitch = "CodeActions.ConvertIfToSwitch";
public const string CodeActionsCorrectExitContinue = "CodeActions.CorrectExitContinue";
public const string CodeActionsCorrectFunctionReturnType = "CodeActions.CorrectFunctionReturnType";
......
......@@ -46,13 +46,23 @@ internal static class TypeStyleHelper
ExpressionSyntax initializerExpression,
SemanticModel semanticModel,
CancellationToken cancellationToken) =>
semanticModel.GetTypeInfo(initializerExpression, cancellationToken).Type?.IsSpecialType() == true;
IsBuiltInType(semanticModel.GetTypeInfo(initializerExpression, cancellationToken).Type);
private static bool IsImplicitStylePreferred(TypeStylePreference stylePreferences,
bool isBuiltInTypeContext,
bool isTypeApparentContext)
public static bool IsBuiltInType(ITypeSymbol type)
=> type?.IsSpecialType() == true;
public static bool IsImplicitStylePreferred(
OptionSet optionSet, bool isBuiltInTypeContext, bool isTypeApparentContext)
{
return IsImplicitStylePreferred(
GetCurrentTypeStylePreferences(optionSet),
isBuiltInTypeContext,
isTypeApparentContext);
}
private static bool IsImplicitStylePreferred(
TypeStylePreference stylePreferences, bool isBuiltInTypeContext, bool isTypeApparentContext)
{
return isBuiltInTypeContext
? stylePreferences.HasFlag(TypeStylePreference.ImplicitTypeForIntrinsicTypes)
: isTypeApparentContext
......
......@@ -8,6 +8,7 @@
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Extensions.ContextQuery;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Shared.Extensions;
......@@ -15,10 +16,12 @@
namespace Microsoft.CodeAnalysis.CSharp
{
internal class CSharpSemanticFactsService : ISemanticFactsService
internal class CSharpSemanticFactsService : AbstractSemanticFactsService, ISemanticFactsService
{
internal static readonly CSharpSemanticFactsService Instance = new CSharpSemanticFactsService();
protected override ISyntaxFactsService SyntaxFactsService => CSharpSyntaxFactsService.Instance;
private CSharpSemanticFactsService()
{
}
......
......@@ -691,10 +691,14 @@ public SyntaxNode GetExpressionOfArgument(SyntaxNode node)
public RefKind GetRefKindOfArgument(SyntaxNode node)
=> (node as ArgumentSyntax).GetRefKind();
public bool IsArgument(SyntaxNode node)
=> node.Kind() == SyntaxKind.Argument;
public bool IsSimpleArgument(SyntaxNode node)
{
var argument = (ArgumentSyntax)node;
return argument.RefOrOutKeyword.Kind() == SyntaxKind.None &&
var argument = node as ArgumentSyntax;
return argument != null &&
argument.RefOrOutKeyword.Kind() == SyntaxKind.None &&
argument.NameColon == null;
}
......@@ -1402,7 +1406,7 @@ public SeparatedSyntaxList<SyntaxNode> GetArgumentsOfObjectCreationExpression(Sy
=> GetArgumentsOfArgumentList((invocationExpression as ObjectCreationExpressionSyntax)?.ArgumentList);
public SeparatedSyntaxList<SyntaxNode> GetArgumentsOfArgumentList(SyntaxNode argumentList)
=> (argumentList as ArgumentListSyntax)?.Arguments ?? default(SeparatedSyntaxList<SyntaxNode>);
=> (argumentList as BaseArgumentListSyntax)?.Arguments ?? default(SeparatedSyntaxList<SyntaxNode>);
public bool IsRegularComment(SyntaxTrivia trivia)
=> trivia.IsRegularComment();
......@@ -1528,22 +1532,19 @@ public void GetPartsOfMemberAccessExpression(SyntaxNode node, out SyntaxNode exp
}
public SyntaxToken GetIdentifierOfSimpleName(SyntaxNode node)
{
return ((SimpleNameSyntax)node).Identifier;
}
=> ((SimpleNameSyntax)node).Identifier;
public SyntaxToken GetIdentifierOfVariableDeclarator(SyntaxNode node)
{
return ((VariableDeclaratorSyntax)node).Identifier;
}
=> ((VariableDeclaratorSyntax)node).Identifier;
public bool IsIdentifierName(SyntaxNode node)
=> node.IsKind(SyntaxKind.IdentifierName);
public bool IsLocalDeclarationStatement(SyntaxNode node)
{
return node.IsKind(SyntaxKind.LocalDeclarationStatement);
}
=> node.IsKind(SyntaxKind.LocalDeclarationStatement);
public bool IsLocalFunctionStatement(SyntaxNode node)
=> node.IsKind(SyntaxKind.LocalFunctionStatement);
public bool IsDeclaratorOfLocalDeclarationStatement(SyntaxNode declarator, SyntaxNode localDeclarationStatement)
{
......@@ -1808,8 +1809,11 @@ public SeparatedSyntaxList<SyntaxNode> GetVariablesOfLocalDeclarationStatement(S
public SyntaxNode GetInitializerOfVariableDeclarator(SyntaxNode node)
=> ((VariableDeclaratorSyntax)node).Initializer;
public SyntaxNode GetTypeOfVariableDeclarator(SyntaxNode node)
=> ((VariableDeclarationSyntax)((VariableDeclaratorSyntax)node).Parent).Type;
public SyntaxNode GetValueOfEqualsValueClause(SyntaxNode node)
=> ((EqualsValueClauseSyntax)node).Value;
=> ((EqualsValueClauseSyntax)node)?.Value;
public bool IsExecutableBlock(SyntaxNode node)
=> node.IsKind(SyntaxKind.Block);
......
// 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.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.Utilities;
namespace Microsoft.CodeAnalysis.LanguageServices
{
internal abstract class AbstractSemanticFactsService
{
protected abstract ISyntaxFactsService SyntaxFactsService { get; }
public SyntaxToken GenerateUniqueName(
SemanticModel semanticModel, SyntaxNode location, SyntaxNode containerOpt,
string baseName, CancellationToken cancellationToken)
{
var syntaxFacts = this.SyntaxFactsService;
var container = containerOpt ?? location.AncestorsAndSelf().FirstOrDefault(
a => syntaxFacts.IsExecutableBlock(a) || syntaxFacts.IsMethodBody(a));
var existingSymbols = semanticModel.GetExistingSymbols(container, cancellationToken);
var reservedNames = semanticModel.LookupSymbols(location.SpanStart)
.Select(s => s.Name)
.Concat(existingSymbols.Select(s => s.Name));
return syntaxFacts.ToIdentifierToken(
NameGenerator.EnsureUniqueness(baseName, reservedNames, syntaxFacts.IsCaseSensitive));
}
}
}
......@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.Host;
......@@ -101,5 +102,9 @@ internal interface ISemanticFactsService : ILanguageService
IEnumerable<ISymbol> GetDeclaredSymbols(SemanticModel semanticModel, SyntaxNode memberDeclaration, CancellationToken cancellationToken);
SymbolInfo GetSymbolInfo(SemanticModel semanticModel, SyntaxNode node, SyntaxToken token, CancellationToken cancellationToken);
SyntaxToken GenerateUniqueName(
SemanticModel semanticModel, SyntaxNode location,
SyntaxNode containerOpt, string baseName, CancellationToken cancellationToken);
}
}
......@@ -159,12 +159,14 @@ internal interface ISyntaxFactsService : ILanguageService
SyntaxToken GetIdentifierOfGenericName(SyntaxNode node);
SyntaxToken GetIdentifierOfSimpleName(SyntaxNode node);
SyntaxToken GetIdentifierOfVariableDeclarator(SyntaxNode node);
SyntaxNode GetTypeOfVariableDeclarator(SyntaxNode node);
/// <summary>
/// True if this is an argument with just an expression and nothing else (i.e. no ref/out,
/// no named params, no omitted args).
/// </summary>
bool IsSimpleArgument(SyntaxNode node);
bool IsArgument(SyntaxNode node);
RefKind GetRefKindOfArgument(SyntaxNode node);
void GetNameAndArityOfSimpleName(SyntaxNode node, out string name, out int arity);
......@@ -215,6 +217,8 @@ internal interface ISyntaxFactsService : ILanguageService
SyntaxNode GetExpressionOfReturnStatement(SyntaxNode node);
bool IsLocalDeclarationStatement(SyntaxNode node);
bool IsLocalFunctionStatement(SyntaxNode node);
bool IsDeclaratorOfLocalDeclarationStatement(SyntaxNode declarator, SyntaxNode localDeclarationStatement);
SeparatedSyntaxList<SyntaxNode> GetVariablesOfLocalDeclarationStatement(SyntaxNode node);
SyntaxNode GetInitializerOfVariableDeclarator(SyntaxNode node);
......
......@@ -9,7 +9,10 @@ namespace Microsoft.CodeAnalysis.Shared.Extensions
{
internal static class SemanticEquivalence
{
public static bool AreSemanticallyEquivalent(
public static bool AreEquivalent(SemanticModel semanticModel, SyntaxNode node1, SyntaxNode node2)
=> AreEquivalent(semanticModel, semanticModel, node1, node2);
public static bool AreEquivalent(
SemanticModel semanticModel1,
SemanticModel semanticModel2,
SyntaxNode node1,
......
......@@ -21,10 +21,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Class
Friend Class VisualBasicSemanticFactsService
Inherits AbstractSemanticFactsService
Implements ISemanticFactsService
Public Shared ReadOnly Instance As New VisualBasicSemanticFactsService()
Protected Overrides ReadOnly Property SyntaxFactsService As ISyntaxFactsService = VisualBasicSyntaxFactsService.Instance
Private Sub New()
End Sub
......@@ -294,5 +297,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Public Function GetSymbolInfo(semanticModel As SemanticModel, node As SyntaxNode, token As SyntaxToken, cancellationToken As CancellationToken) As SymbolInfo Implements ISemanticFactsService.GetSymbolInfo
Return semanticModel.GetSymbolInfo(node, cancellationToken)
End Function
Private Function ISemanticFactsService_GenerateUniqueName(semanticModel As SemanticModel, location As SyntaxNode, containerOpt As SyntaxNode, baseName As String, cancellationToken As CancellationToken) As SyntaxToken Implements ISemanticFactsService.GenerateUniqueName
Return MyBase.GenerateUniqueName(semanticModel, location, containerOpt, baseName, cancellationToken)
End Function
End Class
End Namespace
......@@ -633,9 +633,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return RefKind.None
End Function
Public Function IsArgument(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsArgument
Return TypeOf node Is ArgumentSyntax
End Function
Public Function IsSimpleArgument(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsSimpleArgument
Dim argument = DirectCast(node, ArgumentSyntax)
Return Not argument.IsNamed AndAlso Not argument.IsOmitted
Dim argument = TryCast(node, ArgumentSyntax)
Return argument IsNot Nothing AndAlso Not argument.IsNamed AndAlso Not argument.IsOmitted
End Function
Public Function IsInConstantContext(node As Microsoft.CodeAnalysis.SyntaxNode) As Boolean Implements ISyntaxFactsService.IsInConstantContext
......@@ -1473,6 +1477,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return node.IsKind(SyntaxKind.LocalDeclarationStatement)
End Function
Public Function IsLocalFunctionStatement(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsLocalFunctionStatement
' VB does not have local funtions
Return False
End Function
Public Function IsDeclaratorOfLocalDeclarationStatement(declarator As SyntaxNode, localDeclarationStatement As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsDeclaratorOfLocalDeclarationStatement
Return DirectCast(localDeclarationStatement, LocalDeclarationStatementSyntax).Declarators.
Contains(DirectCast(declarator, VariableDeclaratorSyntax))
......@@ -1715,6 +1724,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return DirectCast(node, VariableDeclaratorSyntax).Initializer
End Function
Public Function GetTypeOfVariableDeclarator(node As SyntaxNode) As SyntaxNode Implements ISyntaxFactsService.GetTypeOfVariableDeclarator
Dim declarator = DirectCast(node, VariableDeclaratorSyntax)
Return TryCast(declarator.AsClause, SimpleAsClauseSyntax)?.Type
End Function
Public Function GetValueOfEqualsValueClause(node As SyntaxNode) As SyntaxNode Implements ISyntaxFactsService.GetValueOfEqualsValueClause
Return DirectCast(node, EqualsValueSyntax).Value
End Function
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册