예제 #1
0
        /// <summary>
        /// Analyze thr MemberAcessExpressionSyntax Nodes
        /// </summary>
        /// <param name="memberAccessExpressions"></param>
        /// <param name="cryslData"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public ValidEvents AnalyzeMemAccessExprSyntax(IdentifierNameSyntax identifier, IEnumerable <CryptoSignature> cryptoMethods, Methods methods, CryslJsonModel cryslData, SyntaxNodeAnalysisContext context, IMethodSymbol identifierSymbolInfo, TextSpan nodeSPan)
        {
            ValidEvents validEvents = new ValidEvents();

            // Check for valid event only if Identifier is of Spec type in Crysl.
            if (identifierSymbolInfo.ReturnType.ToString().Equals(cryslData.Spec_Section.Class_Name))
            {
                List <MethodSignatureModel> methodSignatureModelsList = new List <MethodSignatureModel>();
                foreach (var method in cryptoMethods)
                {
                    ICommonUtilities commonUtilities = serviceProvider.GetService <ICommonUtilities>();
                    //Check if the Event is Valid
                    bool isValidEvent = commonUtilities.IsMethodInEvents(method, identifierSymbolInfo, cryslData.Object_Section.Objects_Declaration);
                    if (isValidEvent)
                    {
                        MethodSignatureModel currentValidEvent = new MethodSignatureModel
                        {
                            MethodName = identifierSymbolInfo.Name,
                            Parameters = method.Argument_types,
                        };
                        methodSignatureModelsList.Add(currentValidEvent);
                        //Go to the Containing Method Declaration Node
                        var containingMethodDeclarationNode = identifier.FirstAncestorOrSelf <MethodDeclarationSyntax>();
                        var invExprSyntaxWalker             = new InvocationExpressionSyntaxWalker(cryslData, context, nodeSPan);
                        //Walk through the current method to find all invocations of the given type
                        invExprSyntaxWalker.Visit(containingMethodDeclarationNode);
                        Dictionary <string, List <MethodSignatureModel> > validEventsDict = invExprSyntaxWalker.GetMethodsList();
                        if (!validEventsDict.ContainsKey(method.Event_Var_Name))
                        {
                            validEventsDict.Add(method.Event_Var_Name, methodSignatureModelsList);
                        }
                        //If there are two events of same type
                        else if (validEventsDict.ContainsKey(method.Event_Var_Name))
                        {
                            foreach (var methodSig in validEventsDict.Values)
                            {
                                methodSignatureModelsList.AddRange(methodSig);
                            }
                            validEventsDict[method.Event_Var_Name] = methodSignatureModelsList;
                        }
                        //Check if the Aggregator Condition Satisfies
                        bool isAggregatorCondition = commonUtilities.CheckAggregator(validEventsDict, methods.Aggregator.Aggregators);
                        if (isAggregatorCondition)
                        {
                            validEvents.IsValidEvent    = true;
                            validEvents.ValidEventsDict = validEventsDict;
                            validEvents.AggregatorName  = methods.Aggregator.Aggregator_Name;
                        }
                        else
                        {
                            validEvents.IsValidEvent = false;
                        }

                        return(validEvents);
                    }
                }
            }
            validEvents.IsValidEvent = false;
            return(validEvents);
        }
예제 #2
0
        public override void VisitIdentifierName(IdentifierNameSyntax node)
        {
            // See if we're part of a qualified name
            var qname      = node.FirstAncestorOrSelf <QualifiedNameSyntax>();
            var syntaxNode = qname == null ? (SyntaxNode)node : qname;

            // Get the symbol
            var symbolInfo = _semanticModel.GetSymbolInfo(syntaxNode, _cancellationToken);

            if (symbolInfo.Symbol == null)
            {
                _logger.LogWarning(node.GetLocation(), "Failed to resolve symbol for: {Syntax}", syntaxNode.ToString());
            }
            else if (symbolInfo.Symbol is INamedTypeSymbol namedTypeSymbol && namedTypeSymbol.TypeKind == TypeKind.Class)
            {
                _logger.LogTrace(node.GetLocation(), "Referenced symbol: {Kind}::{Name}", symbolInfo.Symbol.Kind, symbolInfo.Symbol.Name);
                _builder.Snapshot.ReferenceSymbol(symbolInfo.Symbol, node.GetLocation());
            }
예제 #3
0
        public override void VisitIdentifierName(IdentifierNameSyntax node)
        {
            if (symbols.FirstOrDefault(x => node.NameIs(x.Name) && x.Equals(semanticModel.GetSymbolInfo(node).Symbol)) is { } symbol)
            {
                isMuted = IsInTupleAssignmentTarget() || IsUsedInLocalFunction(symbol) || IsInUnsupportedExpression();
                InspectTryCatch(node);
            }
            base.VisitIdentifierName(node);

            bool IsInTupleAssignmentTarget() =>
            node.Parent is ArgumentSyntax argument && argument.IsInTupleAssignmentTarget();

            bool IsUsedInLocalFunction(ISymbol symbol) =>
            // We don't mute it if it's declared and used in local function
            !(symbol.ContainingSymbol is IMethodSymbol containingSymbol && containingSymbol.MethodKind == MethodKindEx.LocalFunction) &&
            HasAncestor(node, SyntaxKindEx.LocalFunctionStatement);

            bool IsInUnsupportedExpression() =>
            node.FirstAncestorOrSelf <SyntaxNode>(x => x.IsAnyKind(SyntaxKindEx.IndexExpression, SyntaxKindEx.RangeExpression)) != null;
        }
            public override SyntaxNode VisitIdentifierName(IdentifierNameSyntax node)
            {
                // Get related symbol
                ISymbol symbol = this.model.GetSymbolInfo(node).Symbol;

                // Check does the symbol refer to stored parameter
                if (symbol != null && symbol.Equals(this.parameterSymbol))
                {
                    // Create reference to temporary variable
                    IdentifierNameSyntax tempVariableReference = Syntax.IdentifierName(this.variableName)
                                                                 .WithLeadingTrivia(node.GetLeadingTrivia())
                                                                 .WithTrailingTrivia(node.GetTrailingTrivia());

                    // Check is the IdentifierNameExpression on the left side of binary expression
                    if (node.Parent != null && node.Parent is BinaryExpressionSyntax)
                    {
                        BinaryExpressionSyntax binaryExpression = (BinaryExpressionSyntax)node.Parent;
                        if (IsComplexAssignment(binaryExpression) && binaryExpression.Left != null && binaryExpression.Left.Equals(node))
                        {
                            // Assignment operation is rewritten to utilize new temporary variable
                            return(tempVariableReference);
                        }
                    }

                    // Verify has the parameter symbol been already assigned new value
                    // If not, then no replacement should take place (we can still read the original value directly from parameter)
                    StatementSyntax parentStatement = node.FirstAncestorOrSelf <StatementSyntax>();

                    if (IsInConditionExpression(parentStatement, this.parameterSymbol))
                    {
                        return(tempVariableReference);
                    }

                    if (IsAlreadyAssignedNewValue(parentStatement, this.parameterSymbol))
                    {
                        return(tempVariableReference);
                    }
                }

                return(base.VisitIdentifierName(node));
            }
예제 #5
0
            public void HandleIdentifierNameSyntax(SyntaxNodeAnalysisContext context, StyleCopSettings settings)
            {
                IdentifierNameSyntax identifierNameSyntax = (IdentifierNameSyntax)context.Node;

                if (identifierNameSyntax.IsVar)
                {
                    return;
                }

                if (identifierNameSyntax.Identifier.IsMissing)
                {
                    return;
                }

                switch (identifierNameSyntax.Identifier.ValueText)
                {
                case "bool":
                case "byte":
                case "char":
                case "decimal":
                case "double":
                case "short":
                case "int":
                case "long":
                case "object":
                case "sbyte":
                case "float":
                case "string":
                case "ushort":
                case "uint":
                case "ulong":
                    return;

                default:
                    break;
                }

                if (identifierNameSyntax.FirstAncestorOrSelf <UsingDirectiveSyntax>() != null &&
                    identifierNameSyntax.FirstAncestorOrSelf <TypeArgumentListSyntax>() == null)
                {
                    return;
                }

                // Most source files will not have any using alias directives. Then we don't have to use semantics
                // if the identifier name doesn't match the name of a special type
                if (settings.ReadabilityRules.AllowBuiltInTypeAliases ||
                    !identifierNameSyntax.SyntaxTree.ContainsUsingAlias(this.usingAliasCache))
                {
                    switch (identifierNameSyntax.Identifier.ValueText)
                    {
                    case nameof(Boolean):
                    case nameof(Byte):
                    case nameof(Char):
                    case nameof(Decimal):
                    case nameof(Double):
                    case nameof(Int16):
                    case nameof(Int32):
                    case nameof(Int64):
                    case nameof(Object):
                    case nameof(SByte):
                    case nameof(Single):
                    case nameof(String):
                    case nameof(UInt16):
                    case nameof(UInt32):
                    case nameof(UInt64):
                        break;

                    default:
                        return;
                    }
                }

                SemanticModel semanticModel = context.SemanticModel;

                // We go straight to the symbol here. We don't need to check alias information because aliases will fall
                // into one of two categories:
                //
                // 1. The alias to a built-in type matches the name of a built-in type (e.g. using Int32 = Int32;). In
                //    this case, a diagnostic is reported even if allowBuiltInTypeAliases=true.
                // 2. The alias to a built-in type is a different name. In this case, if allowBuiltInTypeAliases is true
                //    then the above code would have already returned due to the renamed symbol not being in the set of
                //    strings checked by the analyzer above.
                INamedTypeSymbol symbol = semanticModel.GetSymbolInfo(identifierNameSyntax, context.CancellationToken).Symbol as INamedTypeSymbol;

                switch (symbol?.SpecialType)
                {
                case SpecialType.System_Boolean:
                case SpecialType.System_Byte:
                case SpecialType.System_Char:
                case SpecialType.System_Decimal:
                case SpecialType.System_Double:
                case SpecialType.System_Int16:
                case SpecialType.System_Int32:
                case SpecialType.System_Int64:
                case SpecialType.System_Object:
                case SpecialType.System_SByte:
                case SpecialType.System_Single:
                case SpecialType.System_String:
                case SpecialType.System_UInt16:
                case SpecialType.System_UInt32:
                case SpecialType.System_UInt64:
                    break;

                default:
                    return;
                }

                SyntaxNode locationNode = identifierNameSyntax;

                if (identifierNameSyntax.Parent is QualifiedNameSyntax)
                {
                    locationNode = identifierNameSyntax.Parent;
                }
                else if ((identifierNameSyntax.Parent as MemberAccessExpressionSyntax)?.Name == identifierNameSyntax)
                {
                    // this "weird" syntax appears for qualified references within a nameof expression
                    locationNode = identifierNameSyntax.Parent;
                }
                else if (identifierNameSyntax.Parent is NameMemberCrefSyntax && identifierNameSyntax.Parent.Parent is QualifiedCrefSyntax)
                {
                    locationNode = identifierNameSyntax.Parent.Parent;
                }

                // Allow nameof
                if (IsNameInNameOfExpression(identifierNameSyntax))
                {
                    return;
                }

                // Use built-in type alias
                context.ReportDiagnostic(Diagnostic.Create(Descriptor, locationNode.GetLocation()));
            }
        private void HandleIdentifierNameSyntax(SyntaxNodeAnalysisContext context)
        {
            IdentifierNameSyntax identifierNameSyntax = context.Node as IdentifierNameSyntax;

            if (identifierNameSyntax == null || identifierNameSyntax.IsVar)
            {
                return;
            }

            if (identifierNameSyntax.Identifier.IsMissing)
            {
                return;
            }

            switch (identifierNameSyntax.Identifier.Text)
            {
            case "bool":
            case "byte":
            case "char":
            case "decimal":
            case "double":
            case "short":
            case "int":
            case "long":
            case "object":
            case "sbyte":
            case "float":
            case "string":
            case "ushort":
            case "uint":
            case "ulong":
                return;

            default:
                break;
            }

            if (identifierNameSyntax.FirstAncestorOrSelf <UsingDirectiveSyntax>() != null)
            {
                return;
            }

            SemanticModel    semanticModel = context.SemanticModel;
            INamedTypeSymbol symbol        = semanticModel.GetSymbolInfo(identifierNameSyntax, context.CancellationToken).Symbol as INamedTypeSymbol;

            switch (symbol?.SpecialType)
            {
            case SpecialType.System_Boolean:
            case SpecialType.System_Byte:
            case SpecialType.System_Char:
            case SpecialType.System_Decimal:
            case SpecialType.System_Double:
            case SpecialType.System_Int16:
            case SpecialType.System_Int32:
            case SpecialType.System_Int64:
            case SpecialType.System_Object:
            case SpecialType.System_SByte:
            case SpecialType.System_Single:
            case SpecialType.System_String:
            case SpecialType.System_UInt16:
            case SpecialType.System_UInt32:
            case SpecialType.System_UInt64:
                break;

            default:
                return;
            }

            SyntaxNode locationNode = identifierNameSyntax;

            if (identifierNameSyntax.Parent is QualifiedNameSyntax)
            {
                locationNode = identifierNameSyntax.Parent;
            }
            else if ((identifierNameSyntax.Parent as MemberAccessExpressionSyntax)?.Name == identifierNameSyntax)
            {
                // this "weird" syntax appears for qualified references within a nameof expression
                locationNode = identifierNameSyntax.Parent;
            }
            else if (identifierNameSyntax.Parent is NameMemberCrefSyntax && identifierNameSyntax.Parent.Parent is QualifiedCrefSyntax)
            {
                locationNode = identifierNameSyntax.Parent.Parent;
            }

            // Allow nameof
            if (this.IsNameInNameOfExpression(identifierNameSyntax))
            {
                return;
            }

            // Use built-in type alias
            context.ReportDiagnostic(Diagnostic.Create(Descriptor, locationNode.GetLocation()));
        }
        private static void HandleIdentifierNameSyntax(SyntaxNodeAnalysisContext context)
        {
            IdentifierNameSyntax identifierNameSyntax = (IdentifierNameSyntax)context.Node;

            if (identifierNameSyntax.IsVar)
            {
                return;
            }

            if (identifierNameSyntax.Identifier.IsMissing)
            {
                return;
            }

            switch (identifierNameSyntax.Identifier.ValueText)
            {
            case "bool":
            case "byte":
            case "char":
            case "decimal":
            case "double":
            case "short":
            case "int":
            case "long":
            case "object":
            case "sbyte":
            case "float":
            case "string":
            case "ushort":
            case "uint":
            case "ulong":
                return;

            default:
                break;
            }

            if (identifierNameSyntax.FirstAncestorOrSelf <UsingDirectiveSyntax>() != null &&
                identifierNameSyntax.FirstAncestorOrSelf <TypeArgumentListSyntax>() == null)
            {
                return;
            }

            // Most source files will not have any using alias directives. Then we don't have to use semantics
            // if the identifier name doesn't match the name of a special type
            if (!identifierNameSyntax.SyntaxTree.ContainsUsingAlias())
            {
                switch (identifierNameSyntax.Identifier.ValueText)
                {
                case nameof(Boolean):
                case nameof(Byte):
                case nameof(Char):
                case nameof(Decimal):
                case nameof(Double):
                case nameof(Int16):
                case nameof(Int32):
                case nameof(Int64):
                case nameof(Object):
                case nameof(SByte):
                case nameof(Single):
                case nameof(String):
                case nameof(UInt16):
                case nameof(UInt32):
                case nameof(UInt64):
                    break;

                default:
                    return;
                }
            }

            SemanticModel    semanticModel = context.SemanticModel;
            INamedTypeSymbol symbol        = semanticModel.GetSymbolInfo(identifierNameSyntax, context.CancellationToken).Symbol as INamedTypeSymbol;

            switch (symbol?.SpecialType)
            {
            case SpecialType.System_Boolean:
            case SpecialType.System_Byte:
            case SpecialType.System_Char:
            case SpecialType.System_Decimal:
            case SpecialType.System_Double:
            case SpecialType.System_Int16:
            case SpecialType.System_Int32:
            case SpecialType.System_Int64:
            case SpecialType.System_Object:
            case SpecialType.System_SByte:
            case SpecialType.System_Single:
            case SpecialType.System_String:
            case SpecialType.System_UInt16:
            case SpecialType.System_UInt32:
            case SpecialType.System_UInt64:
                break;

            default:
                return;
            }

            SyntaxNode locationNode = identifierNameSyntax;

            if (identifierNameSyntax.Parent is QualifiedNameSyntax)
            {
                locationNode = identifierNameSyntax.Parent;
            }
            else if ((identifierNameSyntax.Parent as MemberAccessExpressionSyntax)?.Name == identifierNameSyntax)
            {
                // this "weird" syntax appears for qualified references within a nameof expression
                locationNode = identifierNameSyntax.Parent;
            }
            else if (identifierNameSyntax.Parent is NameMemberCrefSyntax && identifierNameSyntax.Parent.Parent is QualifiedCrefSyntax)
            {
                locationNode = identifierNameSyntax.Parent.Parent;
            }

            // Allow nameof
            if (IsNameInNameOfExpression(identifierNameSyntax))
            {
                return;
            }

            // Use built-in type alias
            context.ReportDiagnostic(Diagnostic.Create(Descriptor, locationNode.GetLocation()));
        }
 private static Location GetSquigglesLocation(IdentifierNameSyntax identifier)
 => identifier.FirstAncestorOrSelf <MemberAccessExpressionSyntax>().GetLocation();
        public CodeRefactoring GetRefactoring(IDocument document, TextSpan textSpan, CancellationToken cancellationToken)
        {
            SyntaxNode  root  = (SyntaxNode)document.GetSyntaxRoot(cancellationToken);
            SyntaxToken token = root.FindToken(textSpan.Start, findInsideTrivia: true);

            SyntaxNode parentNode = token.Parent;

            if (parentNode == null)
            {
                return(null);
            }

            // Verify is the selected token an identifier of a method
            if (token.Kind == SyntaxKind.IdentifierToken && parentNode.Kind == SyntaxKind.IdentifierName && token.Span.Start <= textSpan.End && textSpan.End <= token.Span.End)
            {
                IdentifierNameSyntax identifier = (IdentifierNameSyntax)parentNode;

                InvocationExpressionSyntax invocationExpression = identifier.FirstAncestorOrSelf <InvocationExpressionSyntax>();
                if (invocationExpression == null || invocationExpression.HasDiagnostics)
                {
                    return(null);
                }

                ISemanticModel model = document.GetSemanticModel(cancellationToken);

                ISymbol methodSymbol = model.GetSymbolInfo(invocationExpression.Expression, cancellationToken).Symbol;
                if (methodSymbol == null)
                {
                    return(null);
                }

                // Check is the method defined in source, so that its body can be read and inlined
                CommonLocation methodDeclarationLocation = methodSymbol.Locations.First();
                if (methodDeclarationLocation == null || !methodDeclarationLocation.IsInSource)
                {
                    return(null);
                }

                // Get method declaration based on location
                int position = methodDeclarationLocation.SourceSpan.Start;
                MethodDeclarationSyntax methodDeclaration = methodDeclarationLocation.SourceTree.GetRoot().FindToken(position).Parent.FirstAncestorOrSelf <MethodDeclarationSyntax>();
                if (methodDeclaration == null)
                {
                    return(null);
                }

                BlockSyntax methodBody = methodDeclaration.Body;

                // Method can be inlined only if it has only one statement, which is return statement
                if (methodBody.Statements.Count != 1 || methodBody.Statements[0].Kind != SyntaxKind.ReturnStatement)
                {
                    return(null);
                }

                ReturnStatementSyntax returnStatement = (ReturnStatementSyntax)methodBody.Statements[0];
                if (returnStatement == null || returnStatement.Expression == null)
                {
                    return(null);
                }

                // If inlined method's invocation expression is the only expression in statement (so its direct parent is ExpressionStatement)
                // then the expression in ReturnStatement should be one of: invocation, object creation, increment, decrement, assignment (or complex assignment).
                if (invocationExpression.Parent != null && invocationExpression.Parent.Kind == SyntaxKind.ExpressionStatement)
                {
                    if (!IsIndependentExpression(returnStatement.Expression))
                    {
                        return(null);
                    }
                }

                // If method is polymorphic, then it should not be inlined. Late binding does not take place.
                MethodSymbol declaredMethodSymbol = (MethodSymbol)model.GetDeclaredSymbol(methodDeclaration);
                if (declaredMethodSymbol.OverriddenMethod != null ||
                    declaredMethodSymbol.MethodKind == MethodKind.ExplicitInterfaceImplementation ||
                    declaredMethodSymbol.IsVirtual ||
                    declaredMethodSymbol.IsOverride)
                {
                    return(null);
                }

                var analysis = model.AnalyzeStatementDataFlow(returnStatement);

                // If parameter is assigned value, it must be either `out' or `ref' to preserve semantics when method is inlined
                // That is, if parameter is modified, the change is reflected before inlining and after inlining

                foreach (var parameter in methodDeclaration.ParameterList.Parameters)
                {
                    ISymbol parameterSymbol = model.GetDeclaredSymbol(parameter, cancellationToken);

                    // Check is the parameter changed in method's body
                    if (analysis.WrittenInside.Contains(parameterSymbol))
                    {
                        // Verify if the modified parameter defined with either `ref' or `out' keyword
                        if (!parameter.Modifiers.Any(n => n.Kind == SyntaxKind.OutKeyword || n.Kind == SyntaxKind.RefKeyword))
                        {
                            return(null);
                        }
                    }
                }

                return(new CodeRefactoring(
                           new[] { new InlineMethodAction(document, invocationExpression, methodDeclaration, returnStatement.Expression) }
                           , invocationExpression.Span));
            }

            return(null);
        }