private IEnumerable <Microsoft.CodeAnalysis.CodeActions.CodeIssue> GetIssuesInternal(IEnumerable <ClousotOutput> results, CompilationUnitSyntax compilationUnitDeclaration)
        {
            IEnumerator <ClousotOutput> enumerator;

            try
            {
                enumerator = results.GetEnumerator();
            }
            catch
            {
                yield break;
            }

            bool hasNext;

            try
            {
                hasNext = enumerator.MoveNext();
            }
            catch
            {
                yield break;
            }

            while (hasNext)
            {
                var result = enumerator.Current;

                //foreach (var result in results )
                {
                    var msg    = result.Message;
                    var span   = result.Span;
                    var action = result.action;
                    if (span.IsEmpty)
                    {
                        msg  = "Unknown location: " + msg;
                        span = compilationUnitDeclaration.GetFirstToken().Span;
                    }
                    if (action == null)
                    {
                        yield return(new Microsoft.CodeAnalysis.CodeActions.CodeIssue(Microsoft.CodeAnalysis.CodeActions.CodeIssueKind.Warning, span, msg));
                    }
                    else
                    {
                        yield return(new Microsoft.CodeAnalysis.CodeActions.CodeIssue(Microsoft.CodeAnalysis.CodeActions.CodeIssueKind.Warning, span, msg, action));
                    }
                }
                try
                {
                    hasNext = enumerator.MoveNext();
                }
                catch
                {
                    yield break;
                }
            }
        }
示例#2
0
        public static CompilationUnitSyntax AddUsingDirectives(
            this CompilationUnitSyntax root,
            IList <UsingDirectiveSyntax> usingDirectives,
            bool placeSystemNamespaceFirst,
            params SyntaxAnnotation[] annotations)
        {
            if (!usingDirectives.Any())
            {
                return(root);
            }

            var specialCaseSystem = placeSystemNamespaceFirst;
            var comparer          = specialCaseSystem
                ? UsingsAndExternAliasesDirectiveComparer.SystemFirstInstance
                : UsingsAndExternAliasesDirectiveComparer.NormalInstance;

            var usings = new List <UsingDirectiveSyntax>();

            usings.AddRange(root.Usings);
            usings.AddRange(usingDirectives);

            // If the user likes to have their Usings statements unsorted, allow them to
            if (root.Usings.IsSorted(comparer))
            {
                usings.Sort(comparer);
            }

            // If any using we added was moved to the first location, then take the trivia from
            // the start of the first token and add it to the using we added.  This way things
            // like #define's and #r's will stay above the using.
            var firstUsingChanged = root.Usings.Count == 0 || usings[0] != root.Usings[0];

            if (firstUsingChanged && root.Externs.Count == 0)
            {
                var firstToken = root.GetFirstToken();

                // Move the leading directives from the first directive to the new using.
                var firstUsing = usings[0].WithLeadingTrivia(firstToken.LeadingTrivia.Where(t => !t.IsDocComment() && !t.IsElastic()));

                // Remove the leading directives from the first token.
                var newFirstToken = firstToken.WithLeadingTrivia(firstToken.LeadingTrivia.Where(t => t.IsDocComment() || t.IsElastic()));

                // Remove the leading trivia from the first token from the tree.
                root = root.ReplaceToken(firstToken, newFirstToken);

                // Create the new list of usings.
                var finalUsings = new List <UsingDirectiveSyntax>();
                finalUsings.Add(firstUsing);
                finalUsings.AddRange(root.Usings);
                finalUsings.AddRange(usingDirectives.Except(new[] { usings[0] }));
                finalUsings.Sort(comparer);
                usings = finalUsings;
            }

            usings = usings.Select(u => u.WithAdditionalAnnotations(annotations)).ToList();
            return(root.WithUsings(usings.ToSyntaxList()));
        }
示例#3
0
        public override void Open()
        {
            base.Open();

            tree = (CSharpSyntaxTree)CSharpSyntaxTree.ParseText(Source, CSharpParseOptions.Default);

            CompilationUnitSyntax   root        = (CompilationUnitSyntax)tree.GetRoot();
            MemberDeclarationSyntax firstMember = root.Members [0];

            Console.WriteLine(firstMember.GetType().FullName);

            SyntaxToken tok = root.GetFirstToken();

            while (tok.Value != null)
            {
                Console.Write(tok.Text);
                tok = tok.GetNextToken(true, true);
            }
            Console.Out.Flush();
        }
示例#4
0
        public IEnumerable <Tuple <string, TextSpan> > AnalyzeMeAUnit(
            Microsoft.CodeAnalysis.Document document,
            CompilationUnitSyntax compilationUnitDeclaration,
            CancellationToken cancellationToken)
        {
            var semanticModel = document.GetSemanticModel(cancellationToken);
            var semanticNode  = semanticModel.GetDeclaredSymbol(compilationUnitDeclaration);

            this.sourceLocationProvider = new SourceLocationProvider();
            string             exceptionMessage = null;
            IAssemblyReference ar = null;

            try {
                // Constructs a full metadata model for the assembly the semantic model is from
                var transformer = new NodeVisitor(this.host, semanticModel, sourceLocationProvider);

                // Constructs the method bodies all of the methods in the compilation unit
                var tree  = document.GetSyntaxTree(cancellationToken);
                var tree2 = transformer.Visit(compilationUnitDeclaration);
                ar = tree2 as IAssemblyReference;
            } catch (ConverterException e) {
                exceptionMessage = e.Message;
            }
            if (exceptionMessage != null)
            {
                yield return(Tuple.Create(exceptionMessage, compilationUnitDeclaration.GetFirstToken().Span));

                yield break;
            }
            var unit = ar;

            this.host.RegisterUnit(unit.ResolvedUnit);
            this.cciProvider.MetaDataDecoder.RegisterSourceLocationProvider(unit, sourceLocationProvider);

            this.methodAnalyzer.AnalyzeAssembly(ar);

            foreach (var result in this.analysisResults)
            {
                yield return(result);
            }
        }
示例#5
0
        public static CompilationUnitSyntax AddUsingDirectives(
            this CompilationUnitSyntax root,
            IList <UsingDirectiveSyntax> usingDirectives,
            bool placeSystemNamespaceFirst,
            params SyntaxAnnotation[] annotations)
        {
            if (usingDirectives.Count == 0)
            {
                return(root);
            }

            var comparer = placeSystemNamespaceFirst
                ? UsingsAndExternAliasesDirectiveComparer.SystemFirstInstance
                : UsingsAndExternAliasesDirectiveComparer.NormalInstance;

            var usings = AddUsingDirectives(root, usingDirectives);

            // Keep usings sorted if they were originally sorted.
            if (root.Usings.IsSorted(comparer))
            {
                usings.Sort(comparer);
            }

            if (root.Externs.Count == 0)
            {
                if (root.Usings.Count == 0)
                {
                    // We don't have any existing usings. Move any trivia on the first token
                    // of the file to the first using.
                    //
                    // Don't do this for doc comments, as they belong to the first element
                    // already in the file (like a class) and we don't want it to move to
                    // the using.
                    var firstToken = root.GetFirstToken();

                    // Remove the leading directives from the first token.
                    var newFirstToken = firstToken.WithLeadingTrivia(
                        firstToken.LeadingTrivia.Where(t => IsDocCommentOrElastic(t)));

                    root = root.ReplaceToken(firstToken, newFirstToken);

                    // Move the leading trivia from the first token to the first using.
                    var newFirstUsing = usings[0].WithLeadingTrivia(
                        firstToken.LeadingTrivia.Where(t => !IsDocCommentOrElastic(t)));
                    usings[0] = newFirstUsing;
                }
                else
                {
                    var originalFirstUsing = root.Usings[0];
                    if (usings[0] != originalFirstUsing)
                    {
                        // We added a new first-using.  Take the trivia on the existing first using
                        // And move it to the new using.
                        var originalFirstUsingCurrentIndex = usings.IndexOf(originalFirstUsing);

                        var newFirstUsing = usings[0].WithLeadingTrivia(originalFirstUsing.GetLeadingTrivia())
                                            .WithAppendedTrailingTrivia(SyntaxFactory.ElasticCarriageReturnLineFeed);

                        usings[0] = newFirstUsing;
                        usings[originalFirstUsingCurrentIndex] = originalFirstUsing.WithoutLeadingTrivia();
                    }
                }
            }

            return(root.WithUsings(
                       usings.Select(u => u.WithAdditionalAnnotations(annotations)).ToSyntaxList()));
        }
        public static CompilationUnitSyntax Visit(CompilationUnitSyntax code)
        {
            var    modifications = new Dictionary <SyntaxToken, SyntaxToken>();
            var    token         = code.GetFirstToken();
            Action modifyPrevEol = () => { };
            var    addAtPrevEol  = new List <(string errorCode, bool isRestore)>();
            var    addAtNextEol  = new List <(string errorCode, bool isRestore)>();

            while (!token.IsKind(SyntaxKind.None))
            {
                token = token.GetNextToken();
                var localToken    = token;
                var leadingTrivia = token.GetAllTrivia().TakeWhile(x => x.SpanStart < token.SpanStart).ToList();
                HandleEol(leadingTrivia, t => t.WithLeadingTrivia);
                var warnings = token.GetAnnotations(PragmaWarnings.AnnotationKind);
                if (warnings.Any())
                {
                    var errorCodes = warnings.Select(x => x.Data).ToList();
                    addAtPrevEol.AddRange(errorCodes.Select(x => (x, false)));
                    addAtNextEol.AddRange(errorCodes.Select(x => (x, true)));
                }
                var trailingTrivia = token.GetAllTrivia().SkipWhile(x => x.SpanStart < token.SpanStart).ToList();
                HandleEol(trailingTrivia, t => t.WithTrailingTrivia);

                void HandleEol(IReadOnlyList <SyntaxTrivia> trivia, Func <SyntaxToken, Func <IEnumerable <SyntaxTrivia>, SyntaxToken> > mod)
                {
                    if (trivia.Any(ContainsEol))
                    {
                        modifyPrevEol();
                        addAtPrevEol  = addAtNextEol;
                        addAtNextEol  = new List <(string errorCode, bool isRestore)>();
                        modifyPrevEol = () =>
                        {
                            if (!addAtPrevEol.Any())
                            {
                                return;
                            }
                            var disables0 = addAtPrevEol.Where(x => !x.isRestore).Select(x => x.errorCode).Distinct().ToList();
                            var restores0 = addAtPrevEol.Where(x => x.isRestore).Select(x => x.errorCode).Distinct().ToList();
                            var disables  = disables0.Except(restores0).ToList();
                            var restores  = restores0.Except(disables0).ToList();
                            if (!disables.Any() && !restores.Any())
                            {
                                return;
                            }
                            var preEol         = trivia.TakeWhile(x => !ContainsEol(x)).ToList();
                            var postEol        = Enumerable.Reverse(trivia).TakeWhile(x => !ContainsEol(x)).Reverse().ToList();
                            var midEol         = trivia.Skip(preEol.Count).Take(trivia.Count - preEol.Count - postEol.Count);
                            var modifiedTrivia = preEol
                                                 .Concat(restores.Any() ?
                                                         new[] { WhitespaceFormatterNewLine.NewLine, PragmaWarningRestore(restores.ToArray()) } :
                                                         Enumerable.Empty <SyntaxTrivia>())
                                                 .Concat(midEol)
                                                 .Concat(disables.Any() ?
                                                         new[] { PragmaWarningDisable(disables.ToArray()), WhitespaceFormatterNewLine.NewLine } :
                                                         Enumerable.Empty <SyntaxTrivia>())
                                                 .Concat(postEol);
                            var existingToken = modifications.TryGetValue(localToken, out var modifiedToken) ? modifiedToken : localToken;
                            modifications[localToken] = mod(existingToken)(modifiedTrivia);
                        };
                    }

                    bool ContainsEol(SyntaxTrivia st)
                    {
                        if (st.IsKind(SyntaxKind.EndOfLineTrivia))
                        {
                            return(true);
                        }
                        var structure = st.GetStructure();

                        if (structure is object)
                        {
                            if (structure.DescendantNodesAndTokensAndSelf().Any(nt => nt.GetLeadingTrivia().Concat(nt.GetTrailingTrivia()).Any(ContainsEol)))
                            {
                                return(true);
                            }
                        }
                        return(false);
                    }
                }
            }
            modifyPrevEol();
            code = code.ReplaceTokens(modifications.Keys, (orgtoken, _) => modifications[orgtoken]);
            code = (CompilationUnitSyntax) new PragmaVisitor().Visit(code);
            return(code);
        }
示例#7
0
        /// <summary>
        /// Checks the <paramref name="compilationUnitDeclaration"/> for syntax and semantic
        /// errors and returns an empty enumerable if any are found.
        /// </summary>
        public IEnumerable <ClousotOutput> AnalyzeMeAUnit(
            Microsoft.CodeAnalysis.Document document,
            CompilationUnitSyntax compilationUnitDeclaration,
            CancellationToken cancellationToken,
            ClousotOptions options,
            string[] extraOptions,
            bool showOnlyAnswersToAskClousot = false
            )
        {
            if (options == null)
            {
                options = new ClousotOptions();
            }

            // Don't do anything if there are syntactic errors.
            if (compilationUnitDeclaration.ContainsDiagnostics)
            {
                yield break;
            }

            var semanticModel = document.GetSemanticModel(cancellationToken);

            // Don't do anything if there are semantic errors.
            var diagnostics = semanticModel.GetDiagnostics(cancellationToken);

            if (diagnostics.Any(d => d.Info.Severity == DiagnosticSeverity.Error || d.Info.IsWarningAsError))
            {
                yield break;
            }

            this.host = new ClousotGlueHost((document.Project).MetadataReferences);

            this.sourceLocationProvider = new SourceLocationProvider();
            string             exceptionMessage = null;
            IAssemblyReference ar = null;

            try {
                // Constructs a full metadata model for the assembly the semantic model is from
                var transformer = new NodeVisitor(this.host, semanticModel, sourceLocationProvider);

                // Constructs the method bodies all of the methods in the compilation unit
                // var tree = document.GetSyntaxTree(cancellationToken);
                var tree2 = transformer.Visit(compilationUnitDeclaration);
                ar = tree2 as IAssemblyReference;
            } catch (ConverterException e) {
                exceptionMessage = e.Message;
            } catch (OperationCanceledException) {
                // just return nothing
                yield break;
            }
            if (exceptionMessage != null)
            {
                yield return(new ClousotOutput(null, exceptionMessage, compilationUnitDeclaration.GetFirstToken().Span, null, (ICodeAction)null, ClousotOutput.ExtraInfo.None));

                yield break;
            }

            var spanToMethodMap = MethodSpanFinder.GetMethodSpans(compilationUnitDeclaration);

            lock (this) { // Clousot is single-threaded
                var cciProvider = Microsoft.Cci.Analysis.CciILCodeProvider.CreateCodeProvider(host);
                var unit        = ar;
                this.host.RegisterUnit(unit.ResolvedUnit);
                cciProvider.MetaDataDecoder.RegisterSourceLocationProvider(unit, sourceLocationProvider);
                var metadataDecoder = cciProvider.MetaDataDecoder;
                var contractDecoder = cciProvider.ContractDecoder;

                var defaultargs = new string[] {
                    "-nonnull",
                    "-bounds",
                    "-arithmetic",
                    "-sortwarns:-",
                    //"-arrays",
                    "-cache",
                    //"-suggest=methodensures",
                    "-suggest=propertyensures",
                    "-suggest=objectinvariants",
                    //"-infer=requires",
                    //"-infer=objectinvariants",
                    //"-clearcache",
                    //"-prefrompost"
                };
                var codefixesargs = new string[] {
                    "-nonnull",
                    "-bounds",
                    "-arithmetic",
                    "-suggest=codefixes",
                    "-cache",
                    "-libpaths:\"c:\\program files (x86)\\Microsoft\\Contracts\\Contracts\\.NetFramework\\v4.0\"",
                    //"-suggest=methodensures",
                    "-suggest=objectinvariants",
                    "-infer=objectinvariants",
                    "-suggest=assumes",
                    "-premode=backwards",
                };
                var args = codefixesargs;
                if (extraOptions != null)
                {
                    args = args.Concat(extraOptions).ToArray();
                }

                var w = (options == null || String.IsNullOrWhiteSpace(options.WarningLevel))
          ? "low"
          : options.WarningLevel;

                var warninglevel = String.Format("-warninglevel={0}", w);
                var x            = new string[] { warninglevel, };
                args = args.Concat(x).ToArray();

                if (options != null)
                {
                    var otherOptions = options.OtherOptions;
                    if (!String.IsNullOrWhiteSpace(otherOptions))
                    {
                        var otherOpts = otherOptions.Split(' ');
                        args = args.Concat(otherOpts).ToArray();
                    }
                }

                this.analysisResults = new List <ClousotOutput>();
                var output         = new RoslynOutput(showOnlyAnswersToAskClousot, this.analysisResults, document, spanToMethodMap, null);
                var methodAnalyzer = Clousot.GetIndividualMethodAnalyzer(metadataDecoder, contractDecoder, args, output,
                                                                         new[] { this.cacheFactory });
                foreach (var path in methodAnalyzer.Options.libPaths)
                {
                    host.AddLibPath(path);
                }
                methodAnalyzer.AnalyzeAssembly(ar);
            }

            foreach (var result in this.analysisResults)
            {
                yield return(result);
            }
        }