private async Task <Document> MakeParameterAsync(Document document, VariableDeclaratorSyntax typeDecl, CancellationToken cancellationToken)
        {
            var root = await document.GetSyntaxRootAsync(cancellationToken);

            string varKeyword = string.Empty, varName = string.Empty;

            //Predefined variable type (string, int, etc...)
            var preDefType = typeDecl.Parent.ChildNodes().OfType <PredefinedTypeSyntax>().FirstOrDefault();

            if (preDefType != null)
            {
                varKeyword = preDefType.Keyword.ToString();
                var varDecl = typeDecl.Parent.ChildNodes().OfType <VariableDeclaratorSyntax>().FirstOrDefault();
                varName = varDecl?.Identifier.ToString();
            }
            else             //var
            {
                var identName = typeDecl.Parent.ChildNodes().OfType <IdentifierNameSyntax>().FirstOrDefault();

                //Access the semantic model to determine actual type
                var model = document.GetSemanticModelAsync().Result;
                var type  = model.GetTypeInfo(identName).Type;
                varKeyword = type.ToMinimalDisplayString(model, typeDecl.SpanStart);

                var varDecl = typeDecl.Parent.ChildNodes().OfType <VariableDeclaratorSyntax>().FirstOrDefault();
                varName = varDecl?.Identifier.ToString();
            }

            MethodDeclarationSyntax mds = typeDecl.Ancestors().OfType <MethodDeclarationSyntax>().FirstOrDefault();

            //Add the existing and new parameters
            ParameterSyntax ps      = SyntaxFactory.Parameter(SyntaxFactory.Identifier(string.Concat(varKeyword, " ", varName)));
            var             newList = SyntaxFactory.ParameterList(SyntaxFactory.SeparatedList <ParameterSyntax>().AddRange(
                                                                      mds.ParameterList.ChildNodes().OfType <ParameterSyntax>()).Add(ps));

            var methodNode         = typeDecl.Ancestors().OfType <MethodDeclarationSyntax>().FirstOrDefault();
            var variableNode       = typeDecl.Parent.Parent;
            var variableParentNode = typeDecl.Parent.Parent.Parent;

            //Track the nodes we'll be using
            var newRoot = root.TrackNodes(methodNode, variableNode, variableParentNode);

            //Remode/replace the variable declaration
            var trackedVariableParentNode = newRoot.GetCurrentNode(variableParentNode);
            var trackedVariableNode       = newRoot.GetCurrentNode(variableNode);
            var newVariableParentNode     = trackedVariableParentNode.RemoveNode(trackedVariableNode, SyntaxRemoveOptions.KeepNoTrivia);

            newRoot = newRoot.ReplaceNode(trackedVariableParentNode, newVariableParentNode);

            //Replace the method parameters
            var trackedMethodNode = newRoot.GetCurrentNode(methodNode);
            var newMethodNode     = trackedMethodNode.ReplaceNode(trackedMethodNode.ParameterList, newList);

            newRoot = newRoot.ReplaceNode(trackedMethodNode, newMethodNode);

            return(document.WithSyntaxRoot(newRoot));
        }
コード例 #2
0
        public override void VisitVariableDeclarator(VariableDeclaratorSyntax node)
        {
            if (node.Ancestors().Any(x => x is FunctionDefinitionSyntax))
                CreateTag(node.Identifier, _classificationService.LocalVariableIdentifier);
            else if (node.Ancestors().Any(x => x is TypeDefinitionSyntax))
                CreateTag(node.Identifier, _classificationService.FieldIdentifier);
            else
                CreateTag(node.Identifier, _classificationService.GlobalVariableIdentifier);

            base.VisitVariableDeclarator(node);
        }
		private async Task<Document> MakeParameterAsync(Document document, VariableDeclaratorSyntax typeDecl, CancellationToken cancellationToken)
		{
			var root = await document.GetSyntaxRootAsync(cancellationToken);
			string varKeyword = string.Empty, varName = string.Empty;

			//Predefined variable type (string, int, etc...)
			var preDefType = typeDecl.Parent.ChildNodes().OfType<PredefinedTypeSyntax>().FirstOrDefault();
			if (preDefType != null)
			{
				varKeyword = preDefType.Keyword.ToString();
				var varDecl = typeDecl.Parent.ChildNodes().OfType<VariableDeclaratorSyntax>().FirstOrDefault();
				varName = varDecl?.Identifier.ToString();
			}
			else //var
			{
				var identName = typeDecl.Parent.ChildNodes().OfType<IdentifierNameSyntax>().FirstOrDefault();

				//Access the semantic model to determine actual type
				var model = document.GetSemanticModelAsync().Result;
                var type = model.GetTypeInfo(identName).Type;
				varKeyword = type.ToMinimalDisplayString(model, typeDecl.SpanStart);

				var varDecl = typeDecl.Parent.ChildNodes().OfType<VariableDeclaratorSyntax>().FirstOrDefault();
				varName = varDecl?.Identifier.ToString();
			}

			MethodDeclarationSyntax mds = typeDecl.Ancestors().OfType<MethodDeclarationSyntax>().FirstOrDefault();

			//Add the existing and new parameters
			ParameterSyntax ps = SyntaxFactory.Parameter(SyntaxFactory.Identifier(string.Concat(varKeyword, " ", varName)));
			var newList = SyntaxFactory.ParameterList(SyntaxFactory.SeparatedList<ParameterSyntax>().AddRange(
				mds.ParameterList.ChildNodes().OfType<ParameterSyntax>()).Add(ps));

			var methodNode = typeDecl.Ancestors().OfType<MethodDeclarationSyntax>().FirstOrDefault();
			var variableNode = typeDecl.Parent.Parent;
			var variableParentNode = typeDecl.Parent.Parent.Parent;

			//Track the nodes we'll be using 
			var newRoot = root.TrackNodes(methodNode, variableNode, variableParentNode);

			//Remode/replace the variable declaration
			var trackedVariableParentNode = newRoot.GetCurrentNode(variableParentNode);
			var trackedVariableNode = newRoot.GetCurrentNode(variableNode);
			var newVariableParentNode = trackedVariableParentNode.RemoveNode(trackedVariableNode, SyntaxRemoveOptions.KeepNoTrivia);
			newRoot = newRoot.ReplaceNode(trackedVariableParentNode, newVariableParentNode);

			//Replace the method parameters
			var trackedMethodNode = newRoot.GetCurrentNode(methodNode);
			var newMethodNode = trackedMethodNode.ReplaceNode(trackedMethodNode.ParameterList, newList);
			newRoot = newRoot.ReplaceNode(trackedMethodNode, newMethodNode);

			return document.WithSyntaxRoot(newRoot);
		}
コード例 #4
0
        private static bool HasMutableUsagesInMethod(VariableDeclaratorSyntax parameter, ISymbol parameterSymbol,
                                                     SemanticModel semanticModel)
        {
            var methodSyntax = parameter?.Ancestors()?.FirstOrDefault(IsMethodLike);

            if (methodSyntax == null)
            {
                return(false);
            }

            return(methodSyntax
                   .DescendantNodes()
                   .OfType <IdentifierNameSyntax>()
                   .Where(MatchesIdentifier)
                   .Any(IsMutatingUse));

            bool IsMethodLike(SyntaxNode arg) =>
            arg is BaseMethodDeclarationSyntax ||
            arg is IndexerDeclarationSyntax ||
            arg is AccessorDeclarationSyntax;

            bool MatchesIdentifier(IdentifierNameSyntax id)
            {
                var symbol = semanticModel.GetSymbolInfo(id).Symbol;

                return(Equals(parameterSymbol, symbol));
            }
        }
コード例 #5
0
        public override void VisitVariableDeclarator(VariableDeclaratorSyntax node)
        {
            if (node.Ancestors().Any(x => x is FunctionDefinitionSyntax))
            {
                CreateTag(node.Identifier, _classificationService.LocalVariableIdentifier);
            }
            else if (node.Ancestors().Any(x => x is TypeDefinitionSyntax))
            {
                CreateTag(node.Identifier, _classificationService.FieldIdentifier);
            }
            else
            {
                CreateTag(node.Identifier, _classificationService.GlobalVariableIdentifier);
            }

            base.VisitVariableDeclarator(node);
        }
コード例 #6
0
            private static Diag GetDiagnostic(VariableDeclaratorSyntax syntax, ContractCategory contractCategory)
            {
                var fieldDeclarationSyntax = syntax?.Ancestors().OfType <FieldDeclarationSyntax>().FirstOrDefault();

                if (fieldDeclarationSyntax?.AttributeLists.ContainsNotNullAttribute() != false)
                {
                    return(null);
                }

                return(new Diag(fieldDeclarationSyntax.GetLocation(), syntax.ToString(), contractCategory));
            }
コード例 #7
0
        private static bool HasMutableUsagesInMethod(VariableDeclaratorSyntax variable, ISymbol variableSymbol, SemanticModel semanticModel)
        {
            var methodSyntax = variable?.Ancestors()?.FirstOrDefault(IsMethodLike);

            if (methodSyntax == null)
            {
                return(false);
            }

            return(methodSyntax
                   .DescendantNodes()
                   .OfType <IdentifierNameSyntax>()
                   .Where(MatchesIdentifier)
                   .Any(IsMutatingUse));
        private static CompilationUnitSyntax AddInvariant(CompilationUnitSyntax root, SemanticModel semanticModel, [NotNull] VariableDeclaratorSyntax variableSyntax)
        {
            var classDeclaration = variableSyntax.Ancestors().OfType <ClassDeclarationSyntax>().FirstOrDefault();

            var invariantMethod = classDeclaration?.ChildNodes()
                                  .OfType <MethodDeclarationSyntax>()
                                  .FirstOrDefault(m => m.AttributeLists.ContainsAttribute("ContractInvariantMethod"));

            if (invariantMethod == null)
            {
                return(root);
            }

            var statements = new [] { SyntaxFactory.ParseStatement($"            Contract.Invariant({variableSyntax.Identifier.Text} != null);\r\n") };

            return(root.ReplaceNode(invariantMethod, invariantMethod.AddBodyStatements(statements)));
        }
コード例 #9
0
        public override SyntaxNode VisitVariableDeclarator(VariableDeclaratorSyntax node)
        {
            var id = node.Identifier.ValueText;

            if (node.Ancestors().Any(anc => anc is FieldDeclarationSyntax))
            {
                return(base.VisitVariableDeclarator(node));
            }

            if (!identities.ContainsKey(id))
            {
                identities[id] = 1;
                return(base.VisitVariableDeclarator(node));
            }

            ++identities[id];
            return(base.VisitVariableDeclarator(node.WithIdentifier(Identifier(id))));
        }
コード例 #10
0
        private static IEnumerable <ConstructorDeclarationSyntax> GetConstructors(VariableDeclaratorSyntax fieldVariable)
        {
            var classDeclaration = fieldVariable.Ancestors().OfType <ClassDeclarationSyntax>().SingleOrDefault();

            if (classDeclaration == null)
            {
                return(new List <ConstructorDeclarationSyntax>());
            }

            var constructors = classDeclaration.DescendantNodes().OfType <ConstructorDeclarationSyntax>();

            var relevantConstructors = constructors.Where(x =>
                                                          x.Body
                                                          .DescendantNodes()
                                                          .OfType <IdentifierNameSyntax>()
                                                          .All(identifier => identifier.Identifier.Text != fieldVariable.Identifier.Text));

            return(relevantConstructors);
        }
コード例 #11
0
        private void Analyze(SyntaxNodeAnalysisContext context)
        {
            if (!IsCaseWeUnderstand(context.Node))
            {
                return;
            }

            // Collect some items we'll use repeatedly
            if (context.Node.Parent != null)
            {
                VariableDeclaratorSyntax variableDeclaratorSyntax = context.Node.Parent.Parent as VariableDeclaratorSyntax;
                if (variableDeclaratorSyntax != null)
                {
                    BlockSyntax blockOfInterest = variableDeclaratorSyntax.Ancestors().OfType <BlockSyntax>().First();
                    var         model           = context.SemanticModel;
                    ISymbol     ourSymbol       = model.GetDeclaredSymbol(variableDeclaratorSyntax);

                    //  Identify where y is first used (ie., MemberAccessExpression)
                    IdentifierNameSyntax identifierNameSyntax = GetFirstMemberAccess(ourSymbol, model, blockOfInterest);
                    if (identifierNameSyntax == null)
                    {
                        return;
                    }
                    if (!SameBlock(blockOfInterest, identifierNameSyntax))
                    {
                        return;
                    }

                    //  Evaluate the code between (ie after) "y = x as yType" and "y.Foo" (ie before) to see if y is read (ie checked for null) or written to (ie rendering our check moot)
                    (StatementSyntax firstStatementOfAnalysis, int firstStatementOfAnalysisIndex) = GetStatement(blockOfInterest, variableDeclaratorSyntax, offset: 1);
                    (StatementSyntax lastStatementOfAnalysis, int lastStatementOfAnalysisIndex)   = GetStatement(blockOfInterest, identifierNameSyntax, offset: -1);

                    if (lastStatementOfAnalysisIndex < firstStatementOfAnalysisIndex)
                    {
                        // There's nothing to analyze; they immediately used the symbol after the 'as'

                        // Before reporting an error, note common possibility that the situation could be:
                        // string y = obj as string;
                        // if (y != null && y.ToString() == @"")
                        // Ie there's nothing to analyze between the statements, but within the statement exists a check
                        if (firstStatementOfAnalysis is IfStatementSyntax ifStatementSyntax)
                        {
                            if (ifStatementSyntax.Condition.ToString().Contains(@"null"))
                            {
                                // There's an "if" statement with a likely null check of some kind in some order.  Don't be too picky, just let it go to minimize risk of a false positive
                                return;
                            }
                        }
                        if (firstStatementOfAnalysis is WhileStatementSyntax whileStatementSyntax)
                        {
                            if (whileStatementSyntax.Condition.ToString().Contains(@"null"))
                            {
                                // There's an "if" statement with a likely null check of some kind in some order.  Don't be too picky, just let it go to minimize risk of a false positive
                                return;
                            }
                        }


                        Report(context, identifierNameSyntax);
                        return;
                    }

                    bool             ourSymbolIsReadOrWritten = false;
                    DataFlowAnalysis result = model.AnalyzeDataFlow(firstStatementOfAnalysis, lastStatementOfAnalysis);
                    if (result != null)
                    {
                        foreach (ISymbol assignedValue in result.ReadInside)
                        {
                            if (SymbolEqualityComparer.Default.Equals(assignedValue, ourSymbol))
                            {
                                // We shouldn't just be checking that we read our symbol; we should really see if it's checked for null
                                ourSymbolIsReadOrWritten = true;
                                break;
                            }
                        }

                        foreach (ISymbol assignedValue in result.WrittenInside)
                        {
                            if (SymbolEqualityComparer.Default.Equals(assignedValue, ourSymbol))
                            {
                                ourSymbolIsReadOrWritten = true;
                                break;
                            }
                        }
                    }

                    if (!ourSymbolIsReadOrWritten)
                    {
                        Report(context, identifierNameSyntax);
                        return;
                    }
                }
            }
        }