提交 4ff68fb1 编写于 作者: J jmarolf

finished implementing generate-from-useage and add imports/usings for ?.

Most of the changes were handing MemberBindingExpressions and how they change the shape of the tree.

Stylecop was turned off for CSharpGenerateVariableService.cs, CSharpGenerateMethodService.cs, and CSharpSyntaxFactsService.cs to enable the use of ?.

Modified CodeActionsUnitTestGenerator.cs so reflection would not fail to locate CodeAction object. (changeset 1380526)
上级 1eb4d631
......@@ -215,7 +215,9 @@
<Compile Include="LanguageServices\CSharpCompilationFactoryService.cs" />
<Compile Include="LanguageServices\CSharpSemanticFactsService.cs" />
<Compile Include="LanguageServices\CSharpSymbolDeclarationService.cs" />
<Compile Include="LanguageServices\CSharpSyntaxFactsService.cs" />
<Compile Include="LanguageServices\CSharpSyntaxFactsService.cs">
<ExcludeFromStyleCop>true</ExcludeFromStyleCop>
</Compile>
<Compile Include="LanguageServices\CSharpSyntaxTreeFactory.PathSyntaxReference.cs" />
<Compile Include="LanguageServices\CSharpSyntaxTreeFactoryService.cs" />
<Compile Include="LanguageServices\CSharpSyntaxTreeFactoryService.NullSyntaxReference.cs" />
......
......@@ -137,7 +137,8 @@ public static bool IsQualifiedCrefName(this ExpressionSyntax expression)
public static bool IsMemberAccessExpressionName(this ExpressionSyntax expression)
{
return expression.IsParentKind(SyntaxKind.SimpleMemberAccessExpression) && ((MemberAccessExpressionSyntax)expression.Parent).Name == expression;
return (expression.IsParentKind(SyntaxKind.SimpleMemberAccessExpression) && ((MemberAccessExpressionSyntax)expression.Parent).Name == expression) ||
(expression.IsParentKind(SyntaxKind.MemberBindingExpression) && expression.Parent.Parent.IsParentKind(SyntaxKind.ConditionalAccessExpression) && ((MemberBindingExpressionSyntax)expression.Parent).Name == expression);
}
public static bool IsAnyMemberAccessExpressionName(this ExpressionSyntax expression)
......@@ -485,6 +486,7 @@ private static bool CanReplace(ISymbol symbol)
expression.IsParentKind(SyntaxKind.EqualsValueClause) ||
expression.IsParentKind(SyntaxKind.ArrayInitializerExpression) ||
expression.IsParentKind(SyntaxKind.CollectionInitializerExpression) ||
expression.IsParentKind(SyntaxKind.ConditionalAccessExpression) ||
expression.IsParentKind(SyntaxKind.Argument) ||
expression.IsParentKind(SyntaxKind.AttributeArgument) ||
expression.IsParentKind(SyntaxKind.AnonymousObjectMemberDeclarator) ||
......@@ -2208,6 +2210,12 @@ public static NameSyntax GetRightmostName(this ExpressionSyntax node)
return simple;
}
var conditional = node as ConditionalAccessExpressionSyntax;
if (conditional != null)
{
return conditional.WhenNotNull.GetRightmostName();
}
return null;
}
......
......@@ -269,40 +269,40 @@ private PredefinedType GetPredefinedType(SyntaxToken token)
{
switch ((SyntaxKind)token.RawKind)
{
case SyntaxKind.BoolKeyword:
return PredefinedType.Boolean;
case SyntaxKind.ByteKeyword:
return PredefinedType.Byte;
case SyntaxKind.SByteKeyword:
return PredefinedType.SByte;
case SyntaxKind.IntKeyword:
return PredefinedType.Int32;
case SyntaxKind.UIntKeyword:
return PredefinedType.UInt32;
case SyntaxKind.ShortKeyword:
return PredefinedType.Int16;
case SyntaxKind.UShortKeyword:
return PredefinedType.UInt16;
case SyntaxKind.LongKeyword:
return PredefinedType.Int64;
case SyntaxKind.ULongKeyword:
return PredefinedType.UInt64;
case SyntaxKind.FloatKeyword:
return PredefinedType.Single;
case SyntaxKind.DoubleKeyword:
return PredefinedType.Double;
case SyntaxKind.DecimalKeyword:
return PredefinedType.Decimal;
case SyntaxKind.StringKeyword:
return PredefinedType.String;
case SyntaxKind.CharKeyword:
return PredefinedType.Char;
case SyntaxKind.ObjectKeyword:
return PredefinedType.Object;
case SyntaxKind.VoidKeyword:
return PredefinedType.Void;
default:
return PredefinedType.None;
case SyntaxKind.BoolKeyword:
return PredefinedType.Boolean;
case SyntaxKind.ByteKeyword:
return PredefinedType.Byte;
case SyntaxKind.SByteKeyword:
return PredefinedType.SByte;
case SyntaxKind.IntKeyword:
return PredefinedType.Int32;
case SyntaxKind.UIntKeyword:
return PredefinedType.UInt32;
case SyntaxKind.ShortKeyword:
return PredefinedType.Int16;
case SyntaxKind.UShortKeyword:
return PredefinedType.UInt16;
case SyntaxKind.LongKeyword:
return PredefinedType.Int64;
case SyntaxKind.ULongKeyword:
return PredefinedType.UInt64;
case SyntaxKind.FloatKeyword:
return PredefinedType.Single;
case SyntaxKind.DoubleKeyword:
return PredefinedType.Double;
case SyntaxKind.DecimalKeyword:
return PredefinedType.Decimal;
case SyntaxKind.StringKeyword:
return PredefinedType.String;
case SyntaxKind.CharKeyword:
return PredefinedType.Char;
case SyntaxKind.ObjectKeyword:
return PredefinedType.Object;
case SyntaxKind.VoidKeyword:
return PredefinedType.Void;
default:
return PredefinedType.None;
}
}
......@@ -328,70 +328,70 @@ private PredefinedOperator GetPredefinedOperator(SyntaxToken token)
{
switch ((SyntaxKind)token.RawKind)
{
case SyntaxKind.PlusToken:
case SyntaxKind.PlusEqualsToken:
return PredefinedOperator.Addition;
case SyntaxKind.PlusToken:
case SyntaxKind.PlusEqualsToken:
return PredefinedOperator.Addition;
case SyntaxKind.MinusToken:
case SyntaxKind.MinusEqualsToken:
return PredefinedOperator.Subtraction;
case SyntaxKind.MinusToken:
case SyntaxKind.MinusEqualsToken:
return PredefinedOperator.Subtraction;
case SyntaxKind.AmpersandToken:
case SyntaxKind.AmpersandEqualsToken:
return PredefinedOperator.BitwiseAnd;
case SyntaxKind.AmpersandToken:
case SyntaxKind.AmpersandEqualsToken:
return PredefinedOperator.BitwiseAnd;
case SyntaxKind.BarToken:
case SyntaxKind.BarEqualsToken:
return PredefinedOperator.BitwiseOr;
case SyntaxKind.BarToken:
case SyntaxKind.BarEqualsToken:
return PredefinedOperator.BitwiseOr;
case SyntaxKind.MinusMinusToken:
return PredefinedOperator.Decrement;
case SyntaxKind.MinusMinusToken:
return PredefinedOperator.Decrement;
case SyntaxKind.PlusPlusToken:
return PredefinedOperator.Increment;
case SyntaxKind.PlusPlusToken:
return PredefinedOperator.Increment;
case SyntaxKind.SlashToken:
case SyntaxKind.SlashEqualsToken:
return PredefinedOperator.Division;
case SyntaxKind.SlashToken:
case SyntaxKind.SlashEqualsToken:
return PredefinedOperator.Division;
case SyntaxKind.EqualsEqualsToken:
return PredefinedOperator.Equality;
case SyntaxKind.EqualsEqualsToken:
return PredefinedOperator.Equality;
case SyntaxKind.CaretToken:
case SyntaxKind.CaretEqualsToken:
return PredefinedOperator.ExclusiveOr;
case SyntaxKind.CaretToken:
case SyntaxKind.CaretEqualsToken:
return PredefinedOperator.ExclusiveOr;
case SyntaxKind.GreaterThanToken:
return PredefinedOperator.GreaterThan;
case SyntaxKind.GreaterThanToken:
return PredefinedOperator.GreaterThan;
case SyntaxKind.GreaterThanEqualsToken:
return PredefinedOperator.GreaterThanOrEqual;
case SyntaxKind.GreaterThanEqualsToken:
return PredefinedOperator.GreaterThanOrEqual;
case SyntaxKind.ExclamationEqualsToken:
return PredefinedOperator.Inequality;
case SyntaxKind.ExclamationEqualsToken:
return PredefinedOperator.Inequality;
case SyntaxKind.LessThanLessThanToken:
case SyntaxKind.LessThanLessThanEqualsToken:
return PredefinedOperator.LeftShift;
case SyntaxKind.LessThanLessThanToken:
case SyntaxKind.LessThanLessThanEqualsToken:
return PredefinedOperator.LeftShift;
case SyntaxKind.LessThanEqualsToken:
return PredefinedOperator.LessThanOrEqual;
case SyntaxKind.LessThanEqualsToken:
return PredefinedOperator.LessThanOrEqual;
case SyntaxKind.AsteriskToken:
case SyntaxKind.AsteriskEqualsToken:
return PredefinedOperator.Multiplication;
case SyntaxKind.AsteriskToken:
case SyntaxKind.AsteriskEqualsToken:
return PredefinedOperator.Multiplication;
case SyntaxKind.PercentToken:
case SyntaxKind.PercentEqualsToken:
return PredefinedOperator.Modulus;
case SyntaxKind.PercentToken:
case SyntaxKind.PercentEqualsToken:
return PredefinedOperator.Modulus;
case SyntaxKind.ExclamationToken:
case SyntaxKind.TildeToken:
return PredefinedOperator.Complement;
case SyntaxKind.ExclamationToken:
case SyntaxKind.TildeToken:
return PredefinedOperator.Complement;
case SyntaxKind.GreaterThanGreaterThanToken:
case SyntaxKind.GreaterThanGreaterThanEqualsToken:
return PredefinedOperator.RightShift;
case SyntaxKind.GreaterThanGreaterThanToken:
case SyntaxKind.GreaterThanGreaterThanEqualsToken:
return PredefinedOperator.RightShift;
}
return PredefinedOperator.None;
......@@ -443,13 +443,13 @@ public bool IsLiteral(SyntaxToken token)
{
switch (token.CSharpKind())
{
case SyntaxKind.NumericLiteralToken:
case SyntaxKind.CharacterLiteralToken:
case SyntaxKind.StringLiteralToken:
case SyntaxKind.NullKeyword:
case SyntaxKind.TrueKeyword:
case SyntaxKind.FalseKeyword:
return true;
case SyntaxKind.NumericLiteralToken:
case SyntaxKind.CharacterLiteralToken:
case SyntaxKind.StringLiteralToken:
case SyntaxKind.NullKeyword:
case SyntaxKind.TrueKeyword:
case SyntaxKind.FalseKeyword:
return true;
}
return false;
......@@ -506,9 +506,9 @@ public bool IsBindableToken(SyntaxToken token)
{
switch ((SyntaxKind)token.RawKind)
{
case SyntaxKind.DelegateKeyword:
case SyntaxKind.VoidKeyword:
return false;
case SyntaxKind.DelegateKeyword:
case SyntaxKind.VoidKeyword:
return false;
}
return true;
......@@ -523,6 +523,11 @@ public bool IsMemberAccessExpression(SyntaxNode node)
((MemberAccessExpressionSyntax)node).CSharpKind() == SyntaxKind.SimpleMemberAccessExpression;
}
public bool IsConditionalMemberAccessExpression(SyntaxNode node)
{
return node is ConditionalAccessExpressionSyntax;
}
public bool IsPointerMemberAccessExpression(SyntaxNode node)
{
return node is MemberAccessExpressionSyntax &&
......@@ -544,7 +549,25 @@ public void GetNameAndArityOfSimpleName(SyntaxNode node, out string name, out in
public SyntaxNode GetExpressionOfMemberAccessExpression(SyntaxNode node)
{
return ((MemberAccessExpressionSyntax)node).Expression;
if (node.IsKind(SyntaxKind.MemberBindingExpression))
{
if (node.IsParentKind(SyntaxKind.ConditionalAccessExpression))
{
return GetExpressionOfConditionalMemberAccessExpression(node.Parent);
}
if (node.IsParentKind(SyntaxKind.InvocationExpression) &&
node.Parent.IsParentKind(SyntaxKind.ConditionalAccessExpression))
{
return GetExpressionOfConditionalMemberAccessExpression(node.Parent.Parent);
}
}
return (node as MemberAccessExpressionSyntax)?.Expression;
}
public SyntaxNode GetExpressionOfConditionalMemberAccessExpression(SyntaxNode node)
{
return (node as ConditionalAccessExpressionSyntax)?.Expression;
}
public bool IsInStaticContext(SyntaxNode node)
......
......@@ -187,6 +187,11 @@ private IEnumerable<ITypeSymbol> InferTypesWorker(ExpressionSyntax expression)
expression = expression.WalkUpParentheses();
var parent = expression.Parent;
if (parent is ConditionalAccessExpressionSyntax)
{
parent = parent.Parent;
}
return parent.TypeSwitch(
(AnonymousObjectMemberDeclaratorSyntax memberDeclarator) => InferTypeInMemberDeclarator(memberDeclarator),
(ArgumentSyntax argument) => InferTypeInArgument(argument),
......
......@@ -53,7 +53,9 @@ internal interface ISyntaxFactsService : ILanguageService
bool IsSkippedTokensTrivia(SyntaxNode node);
SyntaxNode GetExpressionOfMemberAccessExpression(SyntaxNode node);
SyntaxNode GetExpressionOfConditionalMemberAccessExpression(SyntaxNode node);
SyntaxNode GetExpressionOfArgument(SyntaxNode node);
bool IsConditionalMemberAccessExpression(SyntaxNode node);
SyntaxNode GetNameOfAttribute(SyntaxNode node);
SyntaxToken GetIdentifierOfGenericName(SyntaxNode node);
RefKind GetRefKindOfArgument(SyntaxNode node);
......
......@@ -42,12 +42,27 @@ public static IList<INamedTypeSymbol> GetAllInterfacesIncludingThis(this ITypeSy
public static bool IsAbstractClass(this ITypeSymbol symbol)
{
return symbol != null && symbol.TypeKind == TypeKind.Class && symbol.IsAbstract;
return symbol?.TypeKind == TypeKind.Class && symbol.IsAbstract;
}
public static bool IsSystemVoid(this ITypeSymbol symbol)
{
return symbol != null && symbol.SpecialType == SpecialType.System_Void;
return symbol?.SpecialType == SpecialType.System_Void;
}
public static bool IsNullable(this ITypeSymbol symbol)
{
return symbol?.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T;
}
public static ITypeSymbol RemoveNullableIfPresent(this ITypeSymbol symbol)
{
if (symbol.IsNullable())
{
return symbol.GetTypeArguments().Single();
}
return symbol;
}
/// <summary>
......
......@@ -668,7 +668,9 @@
<Compile Include="Shared\Extensions\ITypeSymbolExtensions.AnonymousTypeRemover.cs" />
<Compile Include="Shared\Extensions\ITypeSymbolExtensions.CollectTypeParameterSymbolsVisitor.cs" />
<Compile Include="Shared\Extensions\ITypeSymbolExtensions.CompilationTypeGenerator.cs" />
<Compile Include="Shared\Extensions\ITypeSymbolExtensions.cs" />
<Compile Include="Shared\Extensions\ITypeSymbolExtensions.cs">
<ExcludeFromStyleCop>true</ExcludeFromStyleCop>
</Compile>
<Compile Include="Shared\Extensions\ITypeSymbolExtensions.MinimalAccessibilityVisitor.cs" />
<Compile Include="Shared\Extensions\ITypeSymbolExtensions.SubstituteTypesVisitor.cs" />
<Compile Include="Shared\Extensions\ITypeSymbolExtensions.UnavailableTypeParameterRemover.cs" />
......
......@@ -288,6 +288,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery
targetToken.IsChildToken(Of CallStatementSyntax)(Function(callStatementSyntax) callStatementSyntax.CallKeyword) OrElse
targetToken.IsChildToken(Of CatchFilterClauseSyntax)(Function(catchFilterClauseSyntax) catchFilterClauseSyntax.WhenKeyword) OrElse
targetToken.IsChildToken(Of CaseStatementSyntax)(Function(caseStatement) caseStatement.CaseKeyword) OrElse
targetToken.IsChildToken(Of ConditionalAccessExpressionSyntax)(Function(conditionalAccessExpressionSyntax) conditionalAccessExpressionSyntax.QuestionMarkToken) OrElse
targetToken.IsChildSeparatorToken(Of CaseStatementSyntax, CaseClauseSyntax)(Function(caseStatement) caseStatement.Cases) OrElse
targetToken.IsChildToken(Of RangeCaseClauseSyntax)(Function(rangeCaseClause) rangeCaseClause.ToKeyword) OrElse
targetToken.IsChildToken(Of RelationalCaseClauseSyntax)(Function(relationalCaseClause) relationalCaseClause.OperatorToken) OrElse
......
......@@ -573,7 +573,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions
expression.IsParentKind(SyntaxKind.WhileStatement) OrElse
expression.IsParentKind(SyntaxKind.ElseIfStatement) OrElse
expression.IsParentKind(SyntaxKind.ForEachStatement) OrElse
expression.IsParentKind(SyntaxKind.ForStatement) Then
expression.IsParentKind(SyntaxKind.ForStatement) OrElse
expression.IsParentKind(SyntaxKind.ConditionalAccessExpression) Then
Return True
End If
......
......@@ -128,6 +128,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return vbNode IsNot Nothing AndAlso vbNode.IsMemberAccessExpressionName()
End Function
Public Function IsConditionalMemberAccessExpression(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsConditionalMemberAccessExpression
Return TypeOf node Is ConditionalAccessExpressionSyntax
End Function
Public Function IsInvocationExpression(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsInvocationExpression
Return TypeOf node Is InvocationExpressionSyntax
End Function
......@@ -415,6 +419,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return DirectCast(node, MemberAccessExpressionSyntax).GetExpressionOfMemberAccessExpression()
End Function
Public Function GetExpressionOfConditionalMemberAccessExpression(node As SyntaxNode) As SyntaxNode Implements ISyntaxFactsService.GetExpressionOfConditionalMemberAccessExpression
Return TryCast(node, ConditionalAccessExpressionSyntax)?.Expression
End Function
Public Function IsInNamespaceOrTypeContext(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsInNamespaceOrTypeContext
Return SyntaxFacts.IsInNamespaceOrTypeContext(node)
End Function
......
......@@ -74,8 +74,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Private Function InferTypesWorker(expression As ExpressionSyntax) As IEnumerable(Of ITypeSymbol)
expression = expression.WalkUpParentheses()
Dim parent = expression.Parent
If TypeOf parent Is ConditionalAccessExpressionSyntax Then
parent = parent.Parent
End If
Return expression.Parent.TypeSwitch(
Return parent.TypeSwitch(
Function(addRemoveHandlerStatement As AddRemoveHandlerStatementSyntax) InferTypeInAddRemoveHandlerStatementSyntax(addRemoveHandlerStatement, expression),
Function(argument As ArgumentSyntax) InferTypeInArgumentList(TryCast(argument.Parent, ArgumentListSyntax), argument),
Function(arrayCreationExpression As ArrayCreationExpressionSyntax) InferTypeInArrayCreationExpression(arrayCreationExpression),
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册