コード例 #1
0
        public override LookupResult Lookup(SimpleNameSyntax name, Package fromPackage)
        {
            return name.Match().Returning<LookupResult>()
                .With<IdentifierNameSyntax>(identifierName =>
                {
                    var identifier = identifierName.Identifier.ValueText;
                    var members = symbols.SelectMany(r => r.GetMembers(identifier)).ToList();

                    // TODO this looks like a duplicate of the Resolve method on ContainerBinder
                    if(members.Count == 0)
                        return Empty;

                    var visible = members.Where(m => m.IsVisibleFrom(fromPackage)).ToList();
                    if(visible.Count == 1)
                        return Good(visible.Single());

                    var visibleInPackage = visible.Where(r => r.IsIn(fromPackage)).ToList();
                    if(visibleInPackage.Count == 1)
                        return Good(visibleInPackage.Single()); // TODO issue warning that we have chosen the one in the current package

                    if(visibleInPackage.Count > 1 || visible.Count > 1)
                        return Ambiguous(visible);

                    // Nothing visible in package
                    if(members.Count > 0)
                        return NotAccessible(members);

                    return NotDefined();
                })
                .Exhaustive();
        }
コード例 #2
0
        // returns true if the idenfitier meets requirements
        // for adding the 'this' keyword prefix
        private bool IsCandidateForThis(SimpleNameSyntax node, ISymbol symbol)
        {
            if (symbol == null || symbol.ContainingType == null || symbol.IsStatic)
                return false;

            if (node.Parent.Kind == SyntaxKind.MemberAccessExpression)
            {
                var memberAcc = node.Parent as MemberAccessExpressionSyntax;
                if (memberAcc.Expression != node)
                    return false;
            }

            switch (symbol.Kind)
            {
                case CommonSymbolKind.Field:
                case CommonSymbolKind.Property:
                case CommonSymbolKind.Event:
                    return true;

                case CommonSymbolKind.Method:
                    if (((IMethodSymbol)symbol).MethodKind != CommonMethodKind.Constructor)
                        return true;
                    else break;
            }

            return false;
        }
コード例 #3
0
        // get the symbol for from the identifier
        private ISymbol GetSymbol(SimpleNameSyntax node)
        {
            var info = Semantics.GetSymbolInfo(node);
            if (info.Symbol != null)
                return info.Symbol;

            if (info.CandidateSymbols.Count == 1)
                return info.CandidateSymbols[0];

            return null;
        }
コード例 #4
0
        // return true the the physical container matches the specified symbol
        private bool ContainingTypeMatches(SimpleNameSyntax node, INamedTypeSymbol symbol)
        {
            TypeDeclarationSyntax value = null;
            var parent = node.Parent;

            while (parent != null)
            {
                value = parent as TypeDeclarationSyntax;
                if (value != null) break;

                parent = parent.Parent;
            }

            if (value == null)
                return false;

            return Semantics.GetDeclaredSymbol(value).Equals(symbol);
        }
コード例 #5
0
        // carries out the actual rewrite process, if required
        private SyntaxNode RewriteSyntax(SimpleNameSyntax node)
        {
            var symbol = GetSymbol(node);
            if (symbol == null)
                return node;

            if (IsCandidateForThis(node, symbol) &&
                ContainingTypeMatches(node, symbol.ContainingType))
            {
                // rewrite the syntax to include 'this' keyword
                return Syntax.MemberAccessExpression(
                    SyntaxKind.MemberAccessExpression,
                    Syntax.ThisExpression(
                        Syntax.Token(SyntaxKind.ThisKeyword)),
                    Syntax.Token(SyntaxKind.DotToken),
                    Syntax.IdentifierName(node.Identifier.ValueText));
            }

            return node;
        }
コード例 #6
0
        public static SyntaxNode MethodInvocation(string name, MethodBase methodInfo, SyntaxNode instance, List <ArgumentSyntax> argumentList, TypeArgumentListSyntax typeArgumentList)
        {
            var sepList = SyntaxFactory.SeparatedList(argumentList);

            if (methodInfo == null)
            {
                return(SyntaxFactory.EmptyStatement());
            }

            var  propertyInfos = methodInfo.DeclaringType?.GetProperties();
            var  isSetAccessor = propertyInfos?.FirstOrDefault(prop => prop.GetSetMethod() == methodInfo);
            var  isGetAccessor = propertyInfos?.FirstOrDefault(prop => prop.GetGetMethod() == methodInfo);
            bool isProperty    = isSetAccessor != null || isGetAccessor != null;
            var  methodName    = methodInfo.Name;

            if (isProperty)
            {
                methodName = name.Substring(4);
            }

            bool             isGenericMethod        = methodInfo.IsGenericMethod;
            ExpressionSyntax finalExpressionSyntax  = null;
            ExpressionSyntax memberAccessExpression = instance == null?SyntaxFactory.IdentifierName(methodInfo.DeclaringType?.Name) : instance as ExpressionSyntax;

            if (!isProperty)
            {
                if (methodInfo.IsConstructor)
                {
                    finalExpressionSyntax = SyntaxFactory.ObjectCreationExpression(
                        TypeSystem.BuildTypeSyntax(methodInfo.DeclaringType))
                                            .WithArgumentList(SyntaxFactory.ArgumentList(sepList));
                }
                else
                {
                    SimpleNameSyntax genericName = isGenericMethod
                        ? (SimpleNameSyntax)SyntaxFactory.GenericName(
                        SyntaxFactory.Identifier(methodName))
                                                   .WithTypeArgumentList(typeArgumentList)
                        : SyntaxFactory.IdentifierName(methodName);

                    InvocationExpressionSyntax invocation = SyntaxFactory.InvocationExpression(
                        SyntaxFactory.MemberAccessExpression(
                            SyntaxKind.SimpleMemberAccessExpression,
                            memberAccessExpression,
                            genericName
                            ));
                    finalExpressionSyntax = invocation
                                            .WithArgumentList(SyntaxFactory.ArgumentList(sepList));
                }
            }
            else
            {
                if (isGetAccessor != null)
                {
                    if (isGetAccessor.GetIndexParameters().Length > 0)
                    {
                        finalExpressionSyntax = SyntaxFactory.ElementAccessExpression(
                            memberAccessExpression,
                            SyntaxFactory.BracketedArgumentList(sepList));
                    }
                    else
                    {
                        finalExpressionSyntax = SyntaxFactory.MemberAccessExpression(
                            SyntaxKind.SimpleMemberAccessExpression,
                            memberAccessExpression,
                            SyntaxFactory.IdentifierName(methodName));
                    }
                }
                else if (isSetAccessor != null)
                {
                    ExpressionSyntax left;
                    if (isSetAccessor.GetIndexParameters().Length > 0)
                    {
                        left = SyntaxFactory.ElementAccessExpression(memberAccessExpression, SyntaxFactory.BracketedArgumentList(
                                                                         SyntaxFactory.SeparatedList(argumentList.Take(argumentList.Count - 1))
                                                                         ));
                    }
                    else
                    {
                        left = SyntaxFactory.MemberAccessExpression(
                            SyntaxKind.SimpleMemberAccessExpression,
                            memberAccessExpression,
                            SyntaxFactory.IdentifierName(methodName));
                    }

                    finalExpressionSyntax = SyntaxFactory.AssignmentExpression(
                        SyntaxKind.SimpleAssignmentExpression,
                        left,
                        argumentList.Last().Expression);
                }
            }

            return(finalExpressionSyntax);
        }
コード例 #7
0
 private static bool IsQualified(SimpleNameSyntax identifierName)
 {
     return(identifierName.IsParentKind(SyntaxKind.SimpleMemberAccessExpression));
 }
コード例 #8
0
        private static bool IsSelectingADifferentMethod(IEnumerable <SyntaxNode> childNodes, SimpleNameSyntax methodName, SyntaxTree tree, IMethodSymbol methodSymbol, StatementSyntax invocationStatement, Compilation compilation)
        {
            var parameterExpressions   = CallExtensionMethodAsExtensionCodeFixProvider.GetParameterExpressions(childNodes);
            var firstArgument          = parameterExpressions.FirstOrDefault();
            var argumentList           = CallExtensionMethodAsExtensionCodeFixProvider.CreateArgumentListSyntaxFrom(parameterExpressions.Skip(1));
            var newInvocationStatement = SyntaxFactory.ExpressionStatement(
                CallExtensionMethodAsExtensionCodeFixProvider.CreateInvocationExpression(
                    firstArgument, methodName, argumentList)).WithAdditionalAnnotations(introduceExtensionMethodAnnotation);
            var extensionMethodNamespaceUsingDirective = SyntaxFactory.UsingDirective(methodSymbol.ContainingNamespace.ToNameSyntax());
            var speculativeRootWithExtensionMethod     = tree.GetCompilationUnitRoot()
                                                         .ReplaceNode(invocationStatement, newInvocationStatement)
                                                         .AddUsings(extensionMethodNamespaceUsingDirective);
            var speculativeModel = compilation.ReplaceSyntaxTree(tree, speculativeRootWithExtensionMethod.SyntaxTree)
                                   .GetSemanticModel(speculativeRootWithExtensionMethod.SyntaxTree);
            var speculativeInvocationStatement               = speculativeRootWithExtensionMethod.SyntaxTree.GetCompilationUnitRoot().GetAnnotatedNodes(introduceExtensionMethodAnnotation).Single() as ExpressionStatementSyntax;
            var speculativeExtensionMethodSymbol             = speculativeModel.GetSymbolInfo(speculativeInvocationStatement.Expression).Symbol as IMethodSymbol;
            var speculativeNonExtensionFormOfTheMethodSymbol = speculativeExtensionMethodSymbol?.GetConstructedReducedFrom();

            return(speculativeNonExtensionFormOfTheMethodSymbol == null || !speculativeNonExtensionFormOfTheMethodSymbol.Equals(methodSymbol));
        }
        private static async Task ComputeCodeFixAsync(CodeFixContext context, Diagnostic diagnostic, ExpressionSyntax expression, SimpleNameSyntax simpleName)
        {
            switch (simpleName.Identifier.ValueText)
            {
            case "Count":
            {
                SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                ComputeCodeFix(context, diagnostic, expression, simpleName, semanticModel, "Count", "Length");
                break;
            }

            case "Length":
            {
                SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                ComputeCodeFix(context, diagnostic, expression, simpleName, semanticModel, "Length", "Count");
                break;
            }
            }
        }
コード例 #10
0
        public static void AnalyzeInvocationExpression(SyntaxNodeAnalysisContext context)
        {
            var invocation = (InvocationExpressionSyntax)context.Node;

            ExpressionSyntax expression = invocation.Expression;

            if (expression?.IsKind(SyntaxKind.SimpleMemberAccessExpression) == true)
            {
                var memberAccess = (MemberAccessExpressionSyntax)expression;

                ArgumentListSyntax argumentList = invocation.ArgumentList;

                if (argumentList != null)
                {
                    SeparatedSyntaxList <ArgumentSyntax> arguments = argumentList.Arguments;

                    if (arguments.Any())
                    {
                        SimpleNameSyntax name = memberAccess.Name;

                        if (name?.Identifier.ValueText == "Join")
                        {
                            SemanticModel     semanticModel     = context.SemanticModel;
                            CancellationToken cancellationToken = context.CancellationToken;

                            if (semanticModel.TryGetMethodInfo(invocation, out MethodInfo info, cancellationToken) &&
                                info.IsName("Join") &&
                                info.IsContainingType(SpecialType.System_String) &&
                                info.IsPublic &&
                                info.IsStatic &&
                                info.IsReturnType(SpecialType.System_String) &&
                                !info.IsGenericMethod &&
                                !info.IsExtensionMethod)
                            {
                                ImmutableArray <IParameterSymbol> parameters = info.Parameters;

                                if (parameters.Length == 2 &&
                                    parameters[0].Type.IsString())
                                {
                                    IParameterSymbol parameter = parameters[1];

                                    if (parameter.IsParamsOf(SpecialType.System_String, SpecialType.System_Object) ||
                                        parameter.Type.IsConstructedFromIEnumerableOfT())
                                    {
                                        ArgumentSyntax   firstArgument      = arguments.First();
                                        ExpressionSyntax argumentExpression = firstArgument.Expression;

                                        if (argumentExpression != null &&
                                            CSharpUtility.IsEmptyString(argumentExpression, semanticModel, cancellationToken) &&
                                            !invocation.ContainsDirectives(TextSpan.FromBounds(invocation.SpanStart, firstArgument.Span.End)))
                                        {
                                            context.ReportDiagnostic(
                                                DiagnosticDescriptors.CallStringConcatInsteadOfStringJoin,
                                                name);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
コード例 #11
0
 public abstract LookupResult Lookup(SimpleNameSyntax name, Package fromPackage);
コード例 #12
0
        private static bool IsSelectingADifferentMethod(IEnumerable <SyntaxNode> childNodes, SimpleNameSyntax methodName, SyntaxTree tree, IMethodSymbol methodSymbol, ExpressionSyntax invocationExpression, Compilation compilation)
        {
            var parameterExpressions   = GetParameterExpressions(childNodes);
            var firstArgument          = parameterExpressions.FirstOrDefault();
            var argumentList           = CreateArgumentListSyntaxFrom(parameterExpressions.Skip(1));
            var newInvocationStatement = CreateInvocationExpression(firstArgument, methodName, argumentList)
                                         .WithAdditionalAnnotations(introduceExtensionMethodAnnotation);
            var extensionMethodNamespaceUsingDirective = SyntaxFactory.UsingDirective(methodSymbol.ContainingNamespace.ToNameSyntax());
            var speculativeRootWithExtensionMethod     = tree.GetCompilationUnitRoot()
                                                         .ReplaceNode(invocationExpression, newInvocationStatement)
                                                         .AddUsings(extensionMethodNamespaceUsingDirective);
            var speculativeTree        = speculativeRootWithExtensionMethod.SyntaxTree;
            var speculativeTreeOptions = (CSharpParseOptions)speculativeTree.Options;
            var speculativeTreeWithCorrectLanguageVersion = speculativeTree.WithRootAndOptions(speculativeRootWithExtensionMethod, speculativeTreeOptions.WithLanguageVersion(((CSharpParseOptions)tree.Options).LanguageVersion));
            var speculativeModel = compilation.ReplaceSyntaxTree(tree, speculativeTreeWithCorrectLanguageVersion)
                                   .GetSemanticModel(speculativeTreeWithCorrectLanguageVersion);
            var speculativeInvocationStatement               = speculativeTreeWithCorrectLanguageVersion.GetCompilationUnitRoot().GetAnnotatedNodes(introduceExtensionMethodAnnotation).Single() as InvocationExpressionSyntax;
            var speculativeExtensionMethodSymbol             = speculativeModel.GetSymbolInfo(speculativeInvocationStatement.Expression).Symbol as IMethodSymbol;
            var speculativeNonExtensionFormOfTheMethodSymbol = speculativeExtensionMethodSymbol?.GetConstructedReducedFrom();

            return(speculativeNonExtensionFormOfTheMethodSymbol == null || speculativeNonExtensionFormOfTheMethodSymbol.ToString() != methodSymbol.ToString());//can't compare equality, as speculative symbol might be different
        }
コード例 #13
0
        // return true the the physical container matches the specified symbol
        private bool ContainingTypeMatches(SimpleNameSyntax node, INamedTypeSymbol symbol)
        {
            TypeDeclarationSyntax value = null;
            var parent = node.Parent;

            while (parent != null)
            {
                value = parent as TypeDeclarationSyntax;
                if (value != null) break;

                parent = parent.Parent;
            }

            if (value == null)
                return false;

            var typeSym = Semantics.GetDeclaredSymbol(value) as INamedTypeSymbol;

            // the symbol can match any type in the inheritance chain
            while (typeSym != null)
            {
                if (typeSym.Equals(symbol))
                    return true;

                typeSym = typeSym.BaseType;
            }

            return false;
        }
コード例 #14
0
        private ExpressionNode BindMemberAccess(SyntaxNode node, ExpressionNode left, SimpleNameSyntax right, bool invoked)
        {
            Debug.Assert(node != null);
            Debug.Assert(left != null);
            Debug.Assert(right != null);
            Debug.Assert(node != null);

            // A member-access consists of a primary-expression, a predefined-type, or a 
            // qualified-alias-member, followed by a "." token, followed by an identifier, 
            // optionally followed by a type-argument-list.

            // A member-access is either of the form E.I or of the form E.I<A1, ..., AK>, 
            // where E is a primary-expression, I is a single identifier and <A1, ..., AK> 
            // is an optional type-argument-list. When no type-argument-list is specified,
            // consider K to be zero. 

            // UNDONE: A member-access with a primary-expression of type dynamic is dynamically bound. 
            // UNDONE: In this case the compiler classifies the member access as a property access of 
            // UNDONE: type dynamic. The rules below to determine the meaning of the member-access are 
            // UNDONE: then applied at run-time, using the run-time type instead of the compile-time 
            // UNDONE: type of the primary-expression. If this run-time classification leads to a method 
            // UNDONE: group, then the member access must be the primary-expression of an invocation-expression.

            // The member-access is evaluated and classified as follows:

            string rightName = right.PlainName;
            int rightArity = right.Arity;
            LookupResult lookupResult = new LookupResult();

            if (left.Kind == NodeKind.NamespaceExpression)
            {
                // If K is zero and E is a namespace and E contains a nested namespace with name I, 
                // then the result is that namespace.

                var ns = ((NamespaceExpression)left).NamespaceSymbol;
                lookupResult = MemberLookupInNamespace(ns, rightName, rightArity);

                // UNDONE: Report errors if more than one, or none.

                if (lookupResult.IsViable) {
                    Symbol sym = lookupResult.Symbols.First();
                    if (sym.Kind == SymbolKind.Namespace)
                        return new NamespaceExpression(node, (NamespaceSymbol)sym);
                    else {
                        Debug.Assert(sym.Kind == SymbolKind.NamedType);
                        return new TypeExpression(node, (NamedTypeSymbol)sym);
                    }
                }
                else {
                    return null;
                }
#if SLOW
                if (node.Right.Arity == 0)
                {
                    var childnamespaces = ns.GetMembers(node.Right.Identifier.ValueText).OfType<NamespaceSymbol>();
                    var childnamespace = childnamespaces.SingleOrDefault();
                    if (childnamespace != null)
                    {
                        return new NamespaceExpression(node, childnamespace);
                    }
                }

                // Otherwise, if E is a namespace and E contains an accessible type having name I and K type
                // parameters, then the result is that type constructed with the given type arguments.

                var childTypes = ns.GetMembers(node.Right.Identifier.Text).OfType<NamedTypeSymbol>().Where(s => s.Arity == node.Right.Arity && IsMemberAccessible(s));
                var childType = childTypes.SingleOrDefault();
                if (childType != null)
                {
                    // UNDONE: Construct the child type if it is generic!
                    return new TypeExpression(node, childType);
                }
#endif
            }

            // If E is a predefined-type or a primary-expression classified as a type, if E is not a 
            // type parameter, and if a member lookup of I in E with K type parameters produces a 
            // match, then E.I is evaluated and classified as follows:
            else if (left.Kind == NodeKind.TypeExpression)
            {
                var type = ((TypeExpression)left).Type;
                if (!(type is TypeParameterSymbol))
                {
                    lookupResult = MemberLookup(type, rightName, rightArity, invoked);
                    if (lookupResult.IsViable)
                    {
                        return BindStaticMemberOfType(node, left, right, lookupResult);
                    }
                }
            }
            // If E is a property access, indexer access, variable, or value, the type of which is T, 
            // and a member lookup of I in T with K type arguments produces a match, then E.I 
            // is evaluated and classified as follows:

            // UNDONE: Classify E as prop access, indexer access, variable or value
            else {
                var type = ((ValueNode)left).Type;
                lookupResult = MemberLookup(type, rightName, rightArity, invoked);
                if (lookupResult.IsViable)
                {
                    return BindInstanceMemberOfType(node, type, left, right, lookupResult);
                }
            }

            // UNDONE: Otherwise, an attempt is made to process E.I as an extension method invocation. 

            // UNDONE: If this fails, E.I is an invalid member reference, and a binding-time error occurs.

            return null;
        }
コード例 #15
0
        private ExpressionNode BindInstanceMemberOfType(SyntaxNode node, TypeSymbol type,
                                                        ExpressionNode left, SimpleNameSyntax right, LookupResult lookupResult)
        {
            Debug.Assert(left != null);
            Debug.Assert(right != null);
            Debug.Assert(node != null);
            Debug.Assert(lookupResult.IsViable);
            Debug.Assert(lookupResult.Symbols.Any());

            // UNDONE: First, if E is a property or indexer access, then the value of the property or indexer access is obtained (§7.1.1) and E is reclassified as a value.

            SymbolOrMethodGroup symbolOrMethods = GetSymbolOrMethodGroup(lookupResult);

            if (symbolOrMethods.IsMethodGroup)
            {
                // If I identifies one or more methods, then the result is a method group with an associated
                // instance expression of E. If a type argument list was specified, it is used in calling 
                // a generic method.

                // UNDONE: Construct the type argument list if there is one.
                return new MethodGroup(right, null, left, symbolOrMethods.MethodGroup);
            }

            // UNDONE: If I identifies an instance property, then the result is a property access with an associated instance expression of E. 
            // UNDONE: If T is a class-type and I identifies an instance field of that class-type:
            // UNDONE:   If the value of E is null, then a System.NullReferenceException is thrown.
            // UNDONE:   Otherwise, if the field is readonly and the reference occurs outside an instance constructor of the class in which the field is declared, then the result is a value, namely the value of the field I in the object referenced by E.
            // UNDONE:   Otherwise, the result is a variable, namely the field I in the object referenced by E.
            // UNDONE: If T is a struct-type and I identifies an instance field of that struct-type:
            // UNDONE:   If E is a value, or if the field is readonly and the reference occurs outside an instance constructor of the struct in which the field is declared, then the result is a value, namely the value of the field I in the struct instance given by E.
            // UNDONE:   Otherwise, the result is a variable, namely the field I in the struct instance given by E.
            // UNDONE: If I identifies an instance event:
            // UNDONE:   If the reference occurs within the class or struct in which the event is declared, and the event was declared without event-accessor-declarations (§10.8), then E.I is processed exactly as if I was an instance field.
            // UNDONE:   Otherwise, the result is an event access with an associated instance expression of E.

            return null;
        }
コード例 #16
0
 private static string GetMessage(SimpleNameSyntax identifier) =>
 IsArgumentOfConstructorInitializer(identifier)
         ? string.Format(Constructor, identifier.Identifier.ValueText)
         : string.Format(Method, identifier.Identifier.ValueText);
コード例 #17
0
        private static IMethodSymbol GetCallerMethodSymbol(SemanticModel semanticModel, SimpleNameSyntax name, int argumentsCount)
        {
            var symbolInfo = semanticModel.GetSymbolInfo(name);

            return(symbolInfo.Symbol as IMethodSymbol ??
                   symbolInfo
                   .CandidateSymbols
                   .OfType <IMethodSymbol>()
                   .FirstOrDefault(s => s.Parameters.Length == argumentsCount + 1));
        }
コード例 #18
0
            private MethodDeclarationSyntax CreateKeyValueMethod(MetaField field, IdentifierNameSyntax methodName, SimpleNameSyntax collectionMutationMethodName)
            {
                var paramsArrayMethod = CreateMethodStarter(methodName.Identifier, field)
                                        .WithParameterList(SyntaxFactory.ParameterList(SyntaxFactory.SeparatedList(
                                                                                           new ParameterSyntax[] {
                    SyntaxFactory.Parameter(KeyParameterName.Identifier).WithType(GetFullyQualifiedSymbolName(field.ElementKeyType)),
                    SyntaxFactory.Parameter(ValueParameterName.Identifier).WithType(GetFullyQualifiedSymbolName(field.ElementValueType)),
                })));

                paramsArrayMethod = this.AddMethodBody(
                    paramsArrayMethod,
                    field,
                    receiver => SyntaxFactory.InvocationExpression(
                        SyntaxFactory.MemberAccessExpression(
                            SyntaxKind.SimpleMemberAccessExpression,
                            receiver,
                            collectionMutationMethodName),
                        SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList(new ArgumentSyntax[] {
                    SyntaxFactory.Argument(KeyParameterName),
                    SyntaxFactory.Argument(ValueParameterName),
                }))));

                return(paramsArrayMethod);
            }
コード例 #19
0
        private static void AnalyzeBinaryExpression(SyntaxNodeAnalysisContext context)
        {
            var binaryExpression = (BinaryExpressionSyntax)context.Node;

            BinaryExpressionInfo binaryExpressionInfo = SyntaxInfo.BinaryExpressionInfo(binaryExpression);

            if (!binaryExpressionInfo.Success)
            {
                return;
            }

            if (binaryExpressionInfo.Right.Kind() != SyntaxKind.TrueLiteralExpression)
            {
                return;
            }

            ExpressionSyntax left = binaryExpressionInfo.Left;

            if (left.Kind() != SyntaxKind.ConditionalAccessExpression)
            {
                return;
            }

            var conditionalAccess = (ConditionalAccessExpressionSyntax)left;

            ExpressionSyntax whenNotNull = conditionalAccess.WhenNotNull;

            if (whenNotNull.Kind() != SyntaxKind.InvocationExpression)
            {
                return;
            }

            var invocationExpression = (InvocationExpressionSyntax)whenNotNull;

            if (invocationExpression.ArgumentList.Arguments.Count != 1)
            {
                return;
            }

            ExpressionSyntax expression = invocationExpression.Expression;

            if (expression.Kind() != SyntaxKind.MemberBindingExpression)
            {
                return;
            }

            var memberBindingExpression = (MemberBindingExpressionSyntax)expression;

            SimpleNameSyntax name = memberBindingExpression.Name;

            if (name.Kind() != SyntaxKind.IdentifierName)
            {
                return;
            }

            var identifierName = (IdentifierNameSyntax)name;

            if (!string.Equals(identifierName.Identifier.ValueText, "IsKind", StringComparison.Ordinal))
            {
                return;
            }

            ISymbol symbol = context.SemanticModel.GetSymbol(invocationExpression, context.CancellationToken);

            if (symbol?.Kind != SymbolKind.Method)
            {
                return;
            }

            var methodSymbol = (IMethodSymbol)symbol;

            if (methodSymbol.MethodKind != MethodKind.ReducedExtension)
            {
                return;
            }

            if (methodSymbol.ReturnType.SpecialType != SpecialType.System_Boolean)
            {
                return;
            }

            if (methodSymbol.ContainingType?.HasMetadataName(RoslynMetadataNames.Microsoft_CodeAnalysis_CSharpExtensions) != true)
            {
                return;
            }

            ImmutableArray <IParameterSymbol> parameters = methodSymbol
                                                           .ReducedFrom
                                                           .Parameters;

            if (parameters.Length != 2)
            {
                return;
            }

            if (!parameters[0].Type.HasMetadataName(RoslynMetadataNames.Microsoft_CodeAnalysis_SyntaxNode))
            {
                return;
            }

            if (!parameters[1].Type.HasMetadataName(CSharpMetadataNames.Microsoft_CodeAnalysis_CSharp_SyntaxKind))
            {
                return;
            }

            DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.UnnecessaryConditionalAccess, conditionalAccess.OperatorToken);
            DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.UnnecessaryConditionalAccessFadeOut, binaryExpression.Right);
        }
コード例 #20
0
        async Task <Solution> PerformAction(Document document, SemanticModel model, SyntaxNode root, TypeDeclarationSyntax enclosingTypeDeclaration, INamedTypeSymbol declaringTypeSymbol, MethodDeclarationSyntax methodDeclaration, IMethodSymbol methodSymbol, CancellationToken cancellationToken)
        {
            // Collect all invocations of changed method
            var methodReferencesVisitor = new MethodReferencesVisitor(document.Project.Solution, methodSymbol, methodDeclaration, cancellationToken);
            await methodReferencesVisitor.Collect();

            // Collect all references to type members and "this" expressions inside of changed method
            var memberReferencesVisitor = new MemberReferencesVisitor(model, declaringTypeSymbol.GetMembers().Where(m => m != methodSymbol), cancellationToken);

            memberReferencesVisitor.Collect(methodDeclaration.Body);

            Solution solution = document.Project.Solution;

            List <SyntaxNode> trackedNodesInMainDoc = new List <SyntaxNode>();

            trackedNodesInMainDoc.Add(methodDeclaration);
            var methodReferencesInMainDocument = methodReferencesVisitor.NodesToChange.FirstOrDefault(n => n.Document.Id == document.Id);

            if (methodReferencesInMainDocument != null)
            {
                trackedNodesInMainDoc.AddRange(methodReferencesInMainDocument.References.Select(r => r.InvocationExpression));
            }
            trackedNodesInMainDoc.AddRange(memberReferencesVisitor.NodesToChange);

            var newMainRoot = root.TrackNodes(trackedNodesInMainDoc);

            foreach (var invocationsInDocument in methodReferencesVisitor.NodesToChange)
            {
                SyntaxNode thisDocRoot    = null;
                var        thisDocumentId = invocationsInDocument.Document.Id;
                if (document.Id == thisDocumentId)
                {
                    // We are in same document as changed method declaration, reuse new root from outside
                    thisDocRoot = newMainRoot;
                }
                else
                {
                    thisDocRoot = await invocationsInDocument.Document.GetSyntaxRootAsync();

                    if (thisDocRoot == null)
                    {
                        continue;
                    }
                    thisDocRoot = thisDocRoot.TrackNodes(invocationsInDocument.References.Select(r => r.InvocationExpression));
                }

                foreach (var referencingInvocation in invocationsInDocument.References)
                {
                    // Change this method invocation to invocation of a static method with instance parameter
                    var thisInvocation = thisDocRoot.GetCurrentNode(referencingInvocation.InvocationExpression);

                    ExpressionSyntax invocationExpressionPart = null;
                    SimpleNameSyntax methodName = null;
                    var memberAccessExpr        = thisInvocation.Expression as MemberAccessExpressionSyntax;
                    if (memberAccessExpr != null)
                    {
                        invocationExpressionPart = memberAccessExpr.Expression;
                        methodName = memberAccessExpr.Name;
                    }

                    if (invocationExpressionPart == null)
                    {
                        var identifier = thisInvocation.Expression as IdentifierNameSyntax;
                        if (identifier != null)
                        {
                            // If changed method references itself, use "instance" as additional parameter! In other methods of affected class, use "this"!
                            if (referencingInvocation.IsInChangedMethod)
                            {
                                invocationExpressionPart = SyntaxFactory.IdentifierName("instance").WithLeadingTrivia(identifier.GetLeadingTrivia());
                            }
                            else
                            {
                                invocationExpressionPart = SyntaxFactory.ThisExpression().WithLeadingTrivia(identifier.GetLeadingTrivia());
                            }
                            methodName = identifier;
                        }
                    }

                    if (invocationExpressionPart == null)
                    {
                        continue;
                    }

                    List <ArgumentSyntax> invocationArguments = new List <ArgumentSyntax>();
                    invocationArguments.Add(SyntaxFactory.Argument(invocationExpressionPart.WithoutLeadingTrivia()));
                    invocationArguments.AddRange(referencingInvocation.InvocationExpression.ArgumentList.Arguments);

                    thisDocRoot = thisDocRoot.ReplaceNode(
                        thisInvocation,
                        SyntaxFactory.InvocationExpression(
                            SyntaxFactory.MemberAccessExpression(
                                SyntaxKind.SimpleMemberAccessExpression,
                                SyntaxFactory.IdentifierName(enclosingTypeDeclaration.Identifier.WithoutTrivia()).WithLeadingTrivia(invocationExpressionPart.GetLeadingTrivia()),
                                methodName.WithoutLeadingTrivia()
                                ),
                            SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList(invocationArguments)).WithAdditionalAnnotations(Formatter.Annotation)
                            ));
                }


                if (document.Id == thisDocumentId)
                {
                    // Write new root back to outside
                    newMainRoot = thisDocRoot;
                }
                else
                {
                    // Another document, replace it with modified version in solution
                    solution = solution.WithDocumentSyntaxRoot(thisDocumentId, thisDocRoot);
                }
            }

            foreach (var changedNode in memberReferencesVisitor.NodesToChange)
            {
                var trackedNode = newMainRoot.GetCurrentNode(changedNode);

                var thisExpression = trackedNode as ThisExpressionSyntax;
                if (thisExpression != null)
                {
                    // Replace "this" with instance parameter name
                    newMainRoot = newMainRoot.ReplaceNode(
                        thisExpression,
                        SyntaxFactory.IdentifierName("instance").WithLeadingTrivia(thisExpression.GetLeadingTrivia())
                        );
                }

                var memberIdentifier = trackedNode as IdentifierNameSyntax;
                if (memberIdentifier != null)
                {
                    newMainRoot = newMainRoot.ReplaceNode(
                        memberIdentifier,
                        SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                             SyntaxFactory.IdentifierName("instance").WithLeadingTrivia(memberIdentifier.GetLeadingTrivia()),
                                                             memberIdentifier.WithoutLeadingTrivia())
                        );
                }
            }

            List <ParameterSyntax> parameters = new List <ParameterSyntax>();

            parameters.Add(SyntaxFactory.Parameter(
                               SyntaxFactory.List <AttributeListSyntax>(),
                               SyntaxFactory.TokenList(),
                               SyntaxFactory.ParseTypeName(enclosingTypeDeclaration.Identifier.ValueText),
                               SyntaxFactory.Identifier("instance"), null)
                           .WithAdditionalAnnotations(Formatter.Annotation));
            parameters.AddRange(methodDeclaration.ParameterList.Parameters);

            var staticModifierLeadingTrivia =
                methodDeclaration.Modifiers.Any() ? SyntaxFactory.TriviaList() : methodDeclaration.GetLeadingTrivia();
            var methodDeclarationLeadingTrivia =
                methodDeclaration.Modifiers.Any() ? methodDeclaration.GetLeadingTrivia() : SyntaxFactory.TriviaList();

            var trackedMethodDeclaration = newMainRoot.GetCurrentNode(methodDeclaration);

            newMainRoot = newMainRoot.ReplaceNode((SyntaxNode)trackedMethodDeclaration, trackedMethodDeclaration
                                                  .WithLeadingTrivia(methodDeclarationLeadingTrivia)
                                                  .WithModifiers(trackedMethodDeclaration.Modifiers.Add(SyntaxFactory.Token(SyntaxKind.StaticKeyword).WithLeadingTrivia(staticModifierLeadingTrivia).WithTrailingTrivia(SyntaxFactory.TriviaList(SyntaxFactory.Whitespace(" ")))))
                                                  .WithParameterList(SyntaxFactory.ParameterList(SyntaxFactory.SeparatedList(parameters)).WithTrailingTrivia(trackedMethodDeclaration.ParameterList.GetTrailingTrivia())));
            return(solution.WithDocumentSyntaxRoot(document.Id, newMainRoot));
        }
コード例 #21
0
        private ExpressionNode BindStaticMemberOfType(SyntaxNode node, ExpressionNode left, SimpleNameSyntax right, LookupResult lookupResult)
        {
            Debug.Assert(node != null);
            Debug.Assert(left != null);
            Debug.Assert(right != null);
            Debug.Assert(lookupResult.IsViable);
            Debug.Assert(lookupResult.Symbols.Any());

            SymbolOrMethodGroup symbolOrMethods = GetSymbolOrMethodGroup(lookupResult);

            if (symbolOrMethods.IsMethodGroup) {
                // If I identifies one or more methods, then the result is a method group with no 
                // associated instance expression. If a type argument list was specified, it is used 
                // in calling a generic method.
                // UNDONE: Construct the type argument list if there is one.
                return new MethodGroup(right, null, left, symbolOrMethods.MethodGroup);
            }
            else {
                Symbol symbol = symbolOrMethods.NonMethod;

                switch (symbol.Kind) {
                    case SymbolKind.NamedType:
                    case SymbolKind.ErrorType:
                        // If I identifies a type, then the result is that type constructed with the given type arguments.
                        // UNDONE: Construct the child type if it is generic!
                        return new TypeExpression(node, (TypeSymbol)symbol);

                    case SymbolKind.Property:
                        // If I identifies a static property, then the result is a property access with no
                        // associated instance expression.
                        // UNDONE: give error if not static.
                        return null;

                    case SymbolKind.Field:
                        // If I identifies a static field:
                        // UNDONE: If the field is readonly and the reference occurs outside the static constructor of 
                        // UNDONE: the class or struct in which the field is declared, then the result is a value, namely
                        // UNDONE: the value of the static field I in E.
                        // UNDONE: Otherwise, the result is a variable, namely the static field I in E.

                        // UNDONE: Need a way to mark an expression node as "I am a variable, not a value".

                        // UNDONE: Give error for non-static.
                        return null;

                    default:
                        Debug.Fail("Unexpected symbol kind");
                        return null;
                }
            }
        }
コード例 #22
0
        private static bool IsValidGetter(ArgumentSyntax argument, SemanticModel semanticModel, INamedTypeSymbol containingType, out IPropertySymbol propertySymbol, out SimpleNameSyntax nameSyntax)
        {
            propertySymbol = null;
            nameSyntax     = null;

            var expression = argument.GetExpression();

            if (!(expression is SingleLineLambdaExpressionSyntax lambdaExpression))
            {
                return(false);
            }

            if (!(lambdaExpression.Body is MemberAccessExpressionSyntax memberAccessExpression))
            {
                return(false);
            }

            if (!memberAccessExpression.IsKind(SyntaxKind.SimpleMemberAccessExpression))
            {
                return(false);
            }

            if (!(semanticModel.GetSymbolInfo(memberAccessExpression).Symbol is IPropertySymbol result))
            {
                return(false);
            }

            if (result.ContainingType != containingType)
            {
                return(false);
            }

            if (result.SetMethod == null)
            {
                return(false);
            }

            propertySymbol = result;
            nameSyntax     = memberAccessExpression.Name;
            return(true);
        }
コード例 #23
0
        /// <summary>
        /// Tries to get the list of candidate methods that can
        /// override the specified virtual call.
        /// </summary>
        /// <param name="overriders">List of overrider methods</param>
        /// <param name="virtualCall">Virtual call</param>
        /// <param name="node">IDataFlowNode</param>
        /// <returns>Boolean</returns>
        private static bool TryGetCandidateMethodOverriders(out HashSet <MethodDeclarationSyntax> overriders,
                                                            InvocationExpressionSyntax virtualCall, IDataFlowNode node)
        {
            overriders = new HashSet <MethodDeclarationSyntax>();

            ISymbol          calleeSymbol = null;
            SimpleNameSyntax callee       = null;
            bool             isThis       = false;

            if (virtualCall.Expression is MemberAccessExpressionSyntax)
            {
                var expr       = virtualCall.Expression as MemberAccessExpressionSyntax;
                var identifier = expr.Expression.DescendantNodesAndSelf().
                                 OfType <IdentifierNameSyntax>().Last();
                calleeSymbol = node.Summary.SemanticModel.GetSymbolInfo(identifier).Symbol;

                if (expr.Expression is ThisExpressionSyntax)
                {
                    callee = expr.Name;
                    isThis = true;
                }
            }
            else
            {
                callee = virtualCall.Expression as IdentifierNameSyntax;
                isThis = true;
            }

            if (isThis)
            {
                var typeDeclaration = node.Summary.Method.FirstAncestorOrSelf <TypeDeclarationSyntax>();
                if (typeDeclaration != null)
                {
                    foreach (var method in typeDeclaration.Members.OfType <MethodDeclarationSyntax>())
                    {
                        if (method.Identifier.ToString().Equals(callee.Identifier.ToString()))
                        {
                            overriders.Add(method);
                            return(true);
                        }
                    }
                }

                return(false);
            }

            var calleeDefinitions = node.DataFlowInfo.ResolveOutputAliases(calleeSymbol);
            var calleeTypes       = calleeDefinitions.SelectMany(def => def.CandidateTypes);

            if (!calleeTypes.Any())
            {
                return(false);
            }

            foreach (var calleeType in calleeTypes)
            {
                MethodDeclarationSyntax method = null;
                if (MethodSummaryResolver.TryGetMethodDeclarationFromType(
                        out method, calleeType, virtualCall, node))
                {
                    overriders.Add(method);
                }
            }

            return(true);
        }
コード例 #24
0
 public static MemberAccessExpressionSyntax MemberAccessExpression(ExpressionSyntax expression, SimpleNameSyntax name)
 => SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, expression, name);
コード例 #25
0
 private static string GetSimpleTypeName(SimpleNameSyntax name)
 => name.Identifier.ValueText;
コード例 #26
0
 public static InvocationExpressionSyntax InvocationExpression(string identifier, SimpleNameSyntax name, params ArgumentSyntax[] arguments)
 => InvocationExpression(IdentifierName(identifier), name, arguments);
コード例 #27
0
ファイル: Syntax.cs プロジェクト: jpobst/Mokii
 public static QualifiedNameSyntax QualifiedName(NameSyntax left, SyntaxToken dotToken, SimpleNameSyntax right)
 {
     return new QualifiedNameSyntax (left, dotToken, right);
 }
コード例 #28
0
 public static InvocationExpressionSyntax InvocationExpression(ExpressionSyntax expression, SimpleNameSyntax name, params ArgumentSyntax[] arguments)
 => InvocationExpression(MemberAccessExpression(expression, name), (IEnumerable <ArgumentSyntax>)arguments);
コード例 #29
0
 public MemberInvocationExpressionWithSingleParameter(ExpressionSyntax expression, SimpleNameSyntax name, ArgumentSyntax argument)
 {
     Expression = expression;
     Name       = name;
     Argument   = argument;
 }
コード例 #30
0
        public static bool ParseInvocation(InvocationExpressionSyntax invocation, out ContractInvocationInfo invocationInfo)
        {
            if (invocation.ArgumentList.Arguments.Count >= 1 && invocation.ArgumentList.Arguments.Count <= 3 &&
                invocation.Expression is MemberAccessExpressionSyntax memberAccess &&
                memberAccess.Name is SimpleNameSyntax methodNameSyntax)
            {
                SimpleNameSyntax className = memberAccess.Expression as SimpleNameSyntax;
                if (className == null && memberAccess.Expression is MemberAccessExpressionSyntax classMemberAccess)
                {
                    className = classMemberAccess.Name as SimpleNameSyntax;
                }

                if (className != null && ValidContractClasses.Contains(className.Identifier.ValueText))
                {
                    SimpleNameSyntax methodName           = methodNameSyntax;
                    NameSyntax       genericExceptionType = null;
                    if (methodNameSyntax is GenericNameSyntax genericName && genericName.TypeArgumentList.Arguments.Count == 1)
                    {
                        genericExceptionType = genericName.TypeArgumentList.Arguments[0] as NameSyntax;
                    }


                    ExpressionSyntax condition       = invocation.ArgumentList.Arguments[0].Expression;
                    ExpressionSyntax message         = null;
                    ExpressionSyntax conditionString = null;
                    if (invocation.ArgumentList.Arguments.Count >= 2)
                    {
                        if (invocation.ArgumentList.Arguments[1].NameColon != null)
                        {
                            if (invocation.ArgumentList.Arguments[1].NameColon.Name.Identifier.ValueText == "conditionString")
                            {
                                conditionString = invocation.ArgumentList.Arguments[1].Expression;
                            }
                            else
                            {
                                message = invocation.ArgumentList.Arguments[1].Expression;
                            }
                        }
                        else
                        {
                            message = invocation.ArgumentList.Arguments[1].Expression;
                        }
                    }

                    if (invocation.ArgumentList.Arguments.Count == 3)
                    {
                        if (invocation.ArgumentList.Arguments[2].NameColon != null)
                        {
                            if (invocation.ArgumentList.Arguments[2].NameColon.Name.Identifier.ValueText == "message" ||
                                invocation.ArgumentList.Arguments[2].NameColon.Name.Identifier.ValueText == "userMessage")
                            {
                                message = invocation.ArgumentList.Arguments[2].Expression;
                            }
                            else
                            {
                                conditionString = invocation.ArgumentList.Arguments[2].Expression;
                            }
                        }
                        else
                        {
                            conditionString = invocation.ArgumentList.Arguments[2].Expression;
                        }
                    }

                    if (className != null && methodName != null && condition != null)
                    {
                        invocationInfo = new ContractInvocationInfo(className, methodName, genericExceptionType, condition, message, conditionString, invocation.ArgumentList);
                        return(true);
                    }
                }
            }


            invocationInfo = null;
            return(false);
        }
コード例 #31
0
#pragma warning disable AvoidAsyncSuffix // Avoid Async suffix
        internal static MemberAccessExpressionSyntax MemberAccess(IReadOnlyList <string> qualifiers, SimpleNameSyntax simpleName)
        {
            if (qualifiers == null)
            {
                throw new ArgumentNullException(nameof(qualifiers));
            }

            if (simpleName == null)
            {
                throw new ArgumentNullException(nameof(simpleName));
            }

            if (qualifiers.Count == 0)
            {
                throw new ArgumentException("At least one qualifier required.");
            }

            ExpressionSyntax result = SyntaxFactory.IdentifierName(qualifiers[0]);

            for (int i = 1; i < qualifiers.Count; i++)
            {
                var rightSide = SyntaxFactory.IdentifierName(qualifiers[i]);
                result = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, result, rightSide);
            }

            return(SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, result, simpleName));
        }
コード例 #32
0
        public static ExpressionSyntax CreateExpressionWithNewName(InvocationExpressionSyntax invocation, SimpleNameSyntax nameToCheck)
        {
            var otherExpression = invocation.Expression.IsKind(SyntaxKind.MemberBindingExpression)
                ? (ExpressionSyntax)((MemberBindingExpressionSyntax)invocation.Expression).WithName(nameToCheck).WithAdditionalAnnotations(speculativeAnnotation)
                                  //avoid this, already checked before: if (invocation.Expression.IsKind(SyntaxKind.SimpleMemberAccessExpression)):
                : ((MemberAccessExpressionSyntax)invocation.Expression).WithName(nameToCheck).WithAdditionalAnnotations(speculativeAnnotation);

            return(otherExpression);
        }
コード例 #33
0
            protected override async Task <Solution> GetChangedSolutionAsync(CancellationToken cancellationToken)
            {
                var document = this.document;
                var root     = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

                // Find the synchronously blocking call member,
                // and bookmark it so we can find it again after some mutations have taken place.
                var syncAccessBookmark          = new SyntaxAnnotation();
                SimpleNameSyntax syncMethodName = (SimpleNameSyntax)root.FindNode(this.diagnostic.Location.SourceSpan);

                if (syncMethodName == null)
                {
                    var syncMemberAccess = root.FindNode(this.diagnostic.Location.SourceSpan).FirstAncestorOrSelf <MemberAccessExpressionSyntax>();
                    syncMethodName = syncMemberAccess.Name;
                }

                // When we give the Document a modified SyntaxRoot, yet another is created. So we first assign it to the Document,
                // then we query for the SyntaxRoot from the Document.
                document = document.WithSyntaxRoot(
                    root.ReplaceNode(syncMethodName, syncMethodName.WithAdditionalAnnotations(syncAccessBookmark)));
                root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

                syncMethodName = (SimpleNameSyntax)root.GetAnnotatedNodes(syncAccessBookmark).Single();

                // We'll need the semantic model later. But because we've annotated a node, that changes the SyntaxRoot
                // and that renders the default semantic model broken (even though we've already updated the document's SyntaxRoot?!).
                // So after acquiring the semantic model, update it with the new method body.
                var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

                var originalAnonymousMethodContainerIfApplicable = syncMethodName.FirstAncestorOrSelf <AnonymousFunctionExpressionSyntax>();
                var originalMethodDeclaration = syncMethodName.FirstAncestorOrSelf <MethodDeclarationSyntax>();

                // Ensure that the method or anonymous delegate is using the async keyword.
                MethodDeclarationSyntax updatedMethod;

                if (originalAnonymousMethodContainerIfApplicable != null)
                {
                    updatedMethod = originalMethodDeclaration.ReplaceNode(
                        originalAnonymousMethodContainerIfApplicable,
                        originalAnonymousMethodContainerIfApplicable.MakeMethodAsync(semanticModel, cancellationToken));
                }
                else
                {
                    (document, updatedMethod) = await originalMethodDeclaration.MakeMethodAsync(document, cancellationToken).ConfigureAwait(false);

                    semanticModel = null; // out-dated
                }

                if (updatedMethod != originalMethodDeclaration)
                {
                    // Re-discover our synchronously blocking member.
                    syncMethodName = (SimpleNameSyntax)updatedMethod.GetAnnotatedNodes(syncAccessBookmark).Single();
                }

                var syncExpression = (ExpressionSyntax)syncMethodName.FirstAncestorOrSelf <InvocationExpressionSyntax>() ?? syncMethodName.FirstAncestorOrSelf <MemberAccessExpressionSyntax>();

                ExpressionSyntax awaitExpression;

                if (this.AlternativeAsyncMethod != string.Empty)
                {
                    // Replace the member being called and await the invocation expression.
                    var asyncMethodName = syncMethodName.WithIdentifier(SyntaxFactory.Identifier(this.diagnostic.Properties[AsyncMethodKeyName]));
                    awaitExpression = SyntaxFactory.AwaitExpression(syncExpression.ReplaceNode(syncMethodName, asyncMethodName));
                    if (!(syncExpression.Parent is ExpressionStatementSyntax))
                    {
                        awaitExpression = SyntaxFactory.ParenthesizedExpression(awaitExpression)
                                          .WithAdditionalAnnotations(Simplifier.Annotation);
                    }
                }
                else
                {
                    // Remove the member being accessed that causes a synchronous block and simply await the object.
                    var syncMemberAccess             = syncMethodName.FirstAncestorOrSelf <MemberAccessExpressionSyntax>();
                    var syncMemberStrippedExpression = syncMemberAccess.Expression;

                    // Special case a common pattern of calling task.GetAwaiter().GetResult() and remove both method calls.
                    var expressionMethodCall = (syncMemberStrippedExpression as InvocationExpressionSyntax)?.Expression as MemberAccessExpressionSyntax;
                    if (expressionMethodCall?.Name.Identifier.Text == nameof(Task.GetAwaiter))
                    {
                        syncMemberStrippedExpression = expressionMethodCall.Expression;
                    }

                    awaitExpression = SyntaxFactory.AwaitExpression(syncMemberStrippedExpression);
                }

                updatedMethod = updatedMethod
                                .ReplaceNode(syncExpression, awaitExpression);

                var newRoot     = root.ReplaceNode(originalMethodDeclaration, updatedMethod);
                var newDocument = document.WithSyntaxRoot(newRoot);

                return(newDocument.Project.Solution);
            }
        private static CompilationUnitSyntax ReplaceStaticCallWithExtionMethodCall(CompilationUnitSyntax root, InvocationExpressionSyntax staticInvocationExpression, ExpressionSyntax sourceExpression, SimpleNameSyntax methodName, ArgumentListSyntax argumentList)
        {
            var extensionInvocationExpression = CreateInvocationExpression(sourceExpression, methodName, argumentList)
                                                .WithLeadingTrivia(staticInvocationExpression.GetLeadingTrivia());

            return(root.ReplaceNode(staticInvocationExpression, extensionInvocationExpression));
        }
コード例 #35
0
 public static InvocationExpressionSyntax CreateInvocationExpression(ExpressionSyntax sourceExpression, SimpleNameSyntax methodName, ArgumentListSyntax argumentList) =>
 SyntaxFactory.InvocationExpression(
     SyntaxFactory.MemberAccessExpression(
         SyntaxKind.SimpleMemberAccessExpression,
         sourceExpression,
         methodName),
     argumentList);
コード例 #36
0
 protected AbstractFunctionDataReference(TData data, ReferenceLocation referenceLocation, SimpleNameSyntax referenceNameNode,
                                         IMethodSymbol referenceSymbol, FunctionData referenceFunctionData, bool insideMethodBody)
     : base(data, referenceLocation, referenceNameNode, referenceSymbol, referenceFunctionData)
 {
     ReferenceFunctionData = referenceFunctionData;
     InsideMethodBody      = insideMethodBody;
 }
コード例 #37
0
 /// <summary>
 /// Updates the given SimpleNameSyntax node with the given identifier token.
 /// This function is a wrapper that calls WithIdentifier on derived syntax nodes.
 /// </summary>
 /// <param name="simpleName"></param>
 /// <param name="identifier"></param>
 /// <returns>The given simple name updated with the given identifier.</returns>
 public static SimpleNameSyntax WithIdentifier(this SimpleNameSyntax simpleName, SyntaxToken identifier)
 {
     return(simpleName.Kind == SyntaxKind.IdentifierName
         ? (SimpleNameSyntax)((IdentifierNameSyntax)simpleName).WithIdentifier(identifier)
         : (SimpleNameSyntax)((GenericNameSyntax)simpleName).WithIdentifier(identifier));
 }
コード例 #38
0
        private static Expression Create(ExpressionNodeInfo info, ExpressionSyntax expression, SimpleNameSyntax name)
        {
            if (IsDynamic(info.Context, expression))
            {
                var expr = new MemberAccess(info.SetKind(ExprKind.DYNAMIC_MEMBER_ACCESS), expression, null);
                info.Context.TrapWriter.Writer.dynamic_member_name(expr, name.Identifier.Text);
                return(expr);
            }

            var target = info.SymbolInfo;

            if (target.CandidateReason == CandidateReason.OverloadResolutionFailure)
            {
                // Roslyn workaround. Even if we can't resolve a method, we know it's a method.
                return(Create(info.Context, expression, info.Parent, info.Child));
            }

            var symbol = target.Symbol ?? info.Context.GetSymbolInfo(name).Symbol;

            if (symbol is null && target.CandidateSymbols.Length >= 1)
            {
                // Pick the first symbol. This could occur for something like `nameof(Foo.Bar)`
                // where `Bar` is a method group. Technically, we don't know which symbol is accessed.
                symbol = target.CandidateSymbols[0];
            }

            if (symbol is null)
            {
                info.Context.ModelError(info.Node, "Failed to determine symbol for member access");
                // Default to property access - this can still give useful results but
                // the target of the expression should be checked in QL.
                return(new MemberAccess(info.SetKind(ExprKind.PROPERTY_ACCESS), expression, symbol));
            }

            ExprKind kind;

            switch (symbol.Kind)
            {
            case SymbolKind.Property:
                kind = ExprKind.PROPERTY_ACCESS;
                break;

            case SymbolKind.Method:
                kind = ExprKind.METHOD_ACCESS;
                break;

            case SymbolKind.Field:
                kind = ExprKind.FIELD_ACCESS;
                break;

            case SymbolKind.NamedType:
                return(TypeAccess.Create(info));

            case SymbolKind.Event:
                kind = ExprKind.EVENT_ACCESS;
                break;

            case SymbolKind.Namespace:
                kind = ExprKind.NAMESPACE_ACCESS;
                break;

            default:
                info.Context.ModelError(info.Node, "Unhandled symbol for member access");
                kind = ExprKind.UNKNOWN;
                break;
            }
            return(new MemberAccess(info.SetKind(kind), expression, symbol));
        }
コード例 #39
0
        private static async Task <Document> GenerateInterfaceImplementationAsync(Document document, SimpleBaseTypeSyntax baseTypeSyntax, CancellationToken cancellationToken)
        {
            var semanticModel = await document.GetSemanticModelAsync(cancellationToken);

            SimpleNameSyntax sns = (baseTypeSyntax.Type as SimpleNameSyntax) ?? (baseTypeSyntax.Type as QualifiedNameSyntax).Right;
            var interfaceSymbol  = semanticModel.GetSymbolInfo(sns).Symbol as INamedTypeSymbol;

            if (interfaceSymbol == null || interfaceSymbol.TypeKind != TypeKind.Interface)
            {
                return(document);
            }

            var originalClassDefinitionSyntax = (ClassDeclarationSyntax)baseTypeSyntax.Parent.Parent;
            ClassDeclarationSyntax modifiedClassDefinitionSyntax = null;

            if (interfaceSymbol.Name == "IObjectMapper" && interfaceSymbol.TypeArguments.Length == 1)
            {
                var sourceClassSymbol = semanticModel.GetDeclaredSymbol(originalClassDefinitionSyntax);
                var targetClassSymbol = interfaceSymbol.TypeArguments[0].OriginalDefinition as INamedTypeSymbol;
                if (sourceClassSymbol == null || targetClassSymbol == null)
                {
                    return(document);
                }

                var matchedProperties = RetrieveMatchedProperties(sourceClassSymbol, targetClassSymbol);

                var updatedMethods = new Dictionary <MethodDeclarationSyntax, MethodDeclarationSyntax>();
                var addedMethods   = new List <MethodDeclarationSyntax>();

                foreach (IMethodSymbol member in interfaceSymbol.GetMembers().Where(x => x.Kind == SymbolKind.Method))
                {
                    var method = sourceClassSymbol.FindImplementationForInterfaceMember(member) as IMethodSymbol;
                    MethodDeclarationSyntax methodSyntax = null;
                    if (method != null)
                    {
                        methodSyntax = await method.DeclaringSyntaxReferences[0].GetSyntaxAsync(cancellationToken) as MethodDeclarationSyntax;
                        var newMethodSyntax = methodSyntax.WithBody(GenerateMethodBody(member, matchedProperties, semanticModel, originalClassDefinitionSyntax.Span.End - 1));
                        updatedMethods.Add(methodSyntax, newMethodSyntax);
                    }
                    else
                    {
                        methodSyntax = GenerateMethodImplementation(member, semanticModel, originalClassDefinitionSyntax.Span.End - 1).
                                       WithBody(GenerateMethodBody(member, matchedProperties, semanticModel, originalClassDefinitionSyntax.Span.End - 1));
                        addedMethods.Add(methodSyntax);
                    }
                }

                modifiedClassDefinitionSyntax = originalClassDefinitionSyntax.ReplaceNodes(updatedMethods.Keys.AsEnumerable(), (n1, n2) => updatedMethods[n1]).AddMembers(addedMethods.ToArray());
            }
            else if (interfaceSymbol.Name == "IObjectMapperAdapter" && interfaceSymbol.TypeArguments.Length == 2)
            {
                var adapterClassSymbol = semanticModel.GetDeclaredSymbol(originalClassDefinitionSyntax);
                var sourceClassSymbol  = interfaceSymbol.TypeArguments[0].OriginalDefinition as INamedTypeSymbol;
                var targetClassSymbol  = interfaceSymbol.TypeArguments[1].OriginalDefinition as INamedTypeSymbol;
                if (sourceClassSymbol == null || targetClassSymbol == null)
                {
                    return(document);
                }

                var matchedProperties = RetrieveMatchedProperties(sourceClassSymbol, targetClassSymbol);

                var updatedMethods = new Dictionary <MethodDeclarationSyntax, MethodDeclarationSyntax>();
                var addedMethods   = new List <MethodDeclarationSyntax>();

                foreach (IMethodSymbol member in interfaceSymbol.GetMembers().Where(x => x.Kind == SymbolKind.Method))
                {
                    var matchingPropertyList = matchedProperties;
                    // check if we have to switch matched properties
                    if (member.Parameters.Length == 2 && !interfaceSymbol.TypeArguments[0].Equals(member.Parameters[0].Type))
                    {
                        matchingPropertyList = matchingPropertyList.Select(x => new MatchedPropertySymbols {
                            Source = x.Target, Target = x.Source
                        });
                    }

                    var method = adapterClassSymbol.FindImplementationForInterfaceMember(member) as IMethodSymbol;
                    MethodDeclarationSyntax methodSyntax = null;
                    if (method != null)
                    {
                        methodSyntax = await method.DeclaringSyntaxReferences[0].GetSyntaxAsync(cancellationToken) as MethodDeclarationSyntax;
                        var newMethodSyntax = methodSyntax.WithBody(GenerateMethodBody(member, matchingPropertyList, semanticModel, originalClassDefinitionSyntax.Span.End - 1));
                        updatedMethods.Add(methodSyntax, newMethodSyntax);
                    }
                    else
                    {
                        methodSyntax = GenerateMethodImplementation(member, semanticModel, originalClassDefinitionSyntax.Span.End - 1).
                                       WithBody(GenerateMethodBody(member, matchingPropertyList, semanticModel, originalClassDefinitionSyntax.Span.End - 1));
                        addedMethods.Add(methodSyntax);
                    }
                }

                modifiedClassDefinitionSyntax = originalClassDefinitionSyntax.ReplaceNodes(updatedMethods.Keys.AsEnumerable(), (n1, n2) => updatedMethods[n1]).AddMembers(addedMethods.ToArray());
            }

            if (modifiedClassDefinitionSyntax == null)
            {
                return(document);
            }

            // replace root and return modified document
            var root = await document.GetSyntaxRootAsync(cancellationToken);

            var newRoot     = root.ReplaceNode(originalClassDefinitionSyntax, modifiedClassDefinitionSyntax);
            var newDocument = document.WithSyntaxRoot(newRoot);

            return(newDocument);
        }
コード例 #40
0
        private static void AnalyzeSimpleMemberAccessExpression(SyntaxNodeAnalysisContext context)
        {
            var memberAccessExpression = (MemberAccessExpressionSyntax)context.Node;

            SimpleNameSyntax name = memberAccessExpression.Name;

            switch (name)
            {
            case IdentifierNameSyntax identifierName:
            {
                switch (identifierName.Identifier.ValueText)
                {
                case "Start":
                {
                    ExpressionSyntax expression = memberAccessExpression.Expression;

                    if (!expression.IsKind(SyntaxKind.SimpleMemberAccessExpression))
                    {
                        break;
                    }

                    ISymbol symbol = context.SemanticModel.GetSymbol(memberAccessExpression, context.CancellationToken);

                    if (symbol == null)
                    {
                        break;
                    }

                    if (!symbol.ContainingType.HasMetadataName(RoslynMetadataNames.Microsoft_CodeAnalysis_Text_TextSpan))
                    {
                        break;
                    }

                    var memberAccess2 = (MemberAccessExpressionSyntax)expression;

                    SimpleNameSyntax name2 = memberAccess2.Name;

                    if (!(name2 is IdentifierNameSyntax identifierName2))
                    {
                        break;
                    }

                    if (!string.Equals(identifierName2.Identifier.ValueText, "Span", StringComparison.Ordinal))
                    {
                        break;
                    }

                    ISymbol symbol2 = context.SemanticModel.GetSymbol(expression, context.CancellationToken);

                    if (symbol2 == null)
                    {
                        break;
                    }

                    if (!symbol2.ContainingType.HasMetadataName(RoslynMetadataNames.Microsoft_CodeAnalysis_SyntaxNode))
                    {
                        break;
                    }

                    DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.UsePropertySyntaxNodeSpanStart, memberAccessExpression);
                    break;
                }

                case "Count":
                {
                    CallAnyInsteadOfUsingCount();
                    break;
                }
                }

                break;
            }
            }

            void CallAnyInsteadOfUsingCount()
            {
                SyntaxNode expression = memberAccessExpression.WalkUpParentheses();

                SyntaxNode parent = expression.Parent;

                if (!parent.IsKind(SyntaxKind.EqualsExpression, SyntaxKind.NotEqualsExpression, SyntaxKind.GreaterThanExpression))
                {
                    return;
                }

                BinaryExpressionInfo binaryExpressionInfo = SyntaxInfo.BinaryExpressionInfo((BinaryExpressionSyntax)parent);

                if (!binaryExpressionInfo.Success)
                {
                    return;
                }

                ExpressionSyntax otherExpression = (expression == binaryExpressionInfo.Left)
                    ? binaryExpressionInfo.Right
                    : binaryExpressionInfo.Left;

                if (!otherExpression.IsKind(SyntaxKind.NumericLiteralExpression))
                {
                    return;
                }

                var numericLiteralExpression = (LiteralExpressionSyntax)otherExpression;

                if (numericLiteralExpression.Token.ValueText != "0")
                {
                    return;
                }

                ISymbol symbol = context.SemanticModel.GetSymbol(memberAccessExpression, context.CancellationToken);

                if (symbol?.Kind != SymbolKind.Property ||
                    symbol.IsStatic ||
                    symbol.DeclaredAccessibility != Accessibility.Public ||
                    !RoslynSymbolUtility.IsList(symbol.ContainingType.OriginalDefinition))
                {
                    return;
                }

                TextSpan span = (memberAccessExpression == binaryExpressionInfo.Left)
                    ? TextSpan.FromBounds(name.SpanStart, numericLiteralExpression.Span.End)
                    : TextSpan.FromBounds(numericLiteralExpression.SpanStart, name.Span.End);

                DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.CallAnyInsteadOfAccessingCount, Location.Create(memberAccessExpression.SyntaxTree, span));
            }
        }
 public override LookupResult Lookup(SimpleNameSyntax name, Package fromPackage)
 {
     throw new NotImplementedException();
 }
コード例 #42
0
 internal static MemberAccessExpressionSyntax QualifyWithThis(this SimpleNameSyntax simpleName, bool simplifiable = true)
 {
     return(SimpleMemberAccessExpression(ThisExpression(), simpleName).WithSimplifierAnnotationIf(simplifiable));
 }