private static void AddExplicitSymbolStates(ImmutableDictionary <string, Tristate> .Builder symbolStates, IEnumerable <string> symbols, Tristate explicitState)
            {
                if (symbols == null)
                {
                    return;
                }

                foreach (var symbol in symbols)
                {
                    Tristate state;
                    if (symbolStates.TryGetValue(symbol, out state))
                    {
                        if (state == explicitState)
                        {
                            throw new ArgumentException(
                                      string.Format("Symbol '{0}' appears in the {1} list multiple times",
                                                    symbol, GetStateString(explicitState)));
                        }
                        else
                        {
                            throw new ArgumentException(
                                      string.Format("Symbol '{0}' cannot be both {1} and {2}",
                                                    symbol, GetStateString(state), GetStateString(explicitState)));
                        }
                    }
                    else
                    {
                        symbolStates[symbol] = explicitState;
                    }
                }
            }
Пример #2
0
        public Tristate EvaluateExpression(CSharpSyntaxNode expression)
        {
            var it = _expressionEvaluators.GetEnumerator();

            if (!it.MoveNext())
            {
                Debug.Assert(false, "We should have at least one expression evaluator");
            }

            Tristate result = expression.Accept(it.Current);

            if (result == Tristate.Varying)
            {
                return(Tristate.Varying);
            }

            while (it.MoveNext())
            {
                if (expression.Accept(it.Current) != result)
                {
                    return(Tristate.Varying);
                }
            }

            return(result);
        }
            internal Options(
                IEnumerable <Project> projects    = null,
                IEnumerable <string> projectPaths = null,
                IEnumerable <string> sourcePaths  = null,
                IEnumerable <IEnumerable <string> > symbolConfigurations = null,
                IEnumerable <string> alwaysIgnoredSymbols  = null,
                IEnumerable <string> alwaysDefinedSymbols  = null,
                IEnumerable <string> alwaysDisabledSymbols = null,
                Tristate undefinedSymbolValue = default(Tristate),
                IAnalysisLogger logger        = null)
            {
                if (projectPaths != null)
                {
                    List <Project> projectsToAdd = new List <Project>();
                    projectPaths.ToList().ForEach(filePath =>
                    {
                        AnalyzerManager analyzerManager = new AnalyzerManager();
                        ProjectAnalyzer analyzer        = analyzerManager.GetProject(filePath);
                        projectsToAdd.AddRange(analyzerManager.GetWorkspace().CurrentSolution.Projects);
                    });
                    projects = projectsToAdd.AsEnumerable();
                }
                if (projects != null)
                {
                    Documents = GetSharedDocuments(projects);
                }

                if (projects == null && sourcePaths != null)
                {
                    var projectId = ProjectId.CreateNewId("AnalysisProject");
                    var solution  = new AdhocWorkspace()
                                    .CurrentSolution
                                    .AddProject(projectId, "AnalysisProject", "AnalysisProject", LanguageNames.CSharp);

                    foreach (var path in sourcePaths)
                    {
                        var documentId = DocumentId.CreateNewId(projectId);
                        solution = solution.AddDocument(
                            documentId,
                            Path.GetFileName(path),
                            new FileTextLoader(path, defaultEncoding: Encoding.UTF8));
                    }

                    Documents = solution.Projects.Single().Documents.ToImmutableArray();
                }

                _symbolConfigurations = CalculateSymbolConfigurations(
                    alwaysDisabledSymbols,
                    alwaysDefinedSymbols,
                    alwaysIgnoredSymbols,
                    symbolConfigurations);

                _undefinedSymbolValue = undefinedSymbolValue;

                Logger = logger ?? new ConsoleAnalysisLogger();
            }
        public ConditionalRegion(DirectiveTriviaSyntax startDirective, DirectiveTriviaSyntax endDirective, Tristate state)
        {
            Debug.Assert(startDirective.SyntaxTree.FilePath == endDirective.SyntaxTree.FilePath);

            StartDirective = startDirective;
            EndDirective   = endDirective;

            SpanStart = CalculateSpanStart(startDirective);
            SpanEnd   = endDirective.FullSpan.End;
            Location  = Location.Create(startDirective.SyntaxTree, new TextSpan(SpanStart, SpanEnd - SpanStart));
            State     = state;
        }
 private static string GetStateString(Tristate state)
 {
     if (state == Tristate.False)
     {
         return("always disabled");
     }
     else if (state == Tristate.True)
     {
         return("always enabled");
     }
     else
     {
         return("ignore");
     }
 }
        public static async Task <AnalysisEngine> FromFilePaths(
            IEnumerable <string> filePaths,
            IEnumerable <IEnumerable <string> > symbolConfigurations = null,
            IEnumerable <string> alwaysIgnoredSymbols  = null,
            IEnumerable <string> alwaysDefinedSymbols  = null,
            IEnumerable <string> alwaysDisabledSymbols = null,
            Tristate undefinedSymbolValue       = default(Tristate),
            CancellationToken cancellationToken = default(CancellationToken))
        {
            if (filePaths == null || !filePaths.Any())
            {
                throw new ArgumentException("Must specify at least one file path");
            }

            IEnumerable <string> sourcePaths = null;
            List <Project>       projects    = new List <Project>();

            var firstFileExt = Path.GetExtension(filePaths.First());

            if (firstFileExt.EndsWith("proj", StringComparison.OrdinalIgnoreCase))
            {
                filePaths.ToList().ForEach(filePath =>
                {
                    AnalyzerManager manager  = new AnalyzerManager();
                    ProjectAnalyzer analyzer = manager.GetProject(filePath);
                    projects.AddRange(manager.GetWorkspace().CurrentSolution.Projects);
                });
            }
            else
            {
                sourcePaths = filePaths;
            }

            var options = new Options(
                projects: projects,
                sourcePaths: sourcePaths,
                symbolConfigurations: symbolConfigurations,
                alwaysIgnoredSymbols: alwaysIgnoredSymbols,
                alwaysDefinedSymbols: alwaysDefinedSymbols,
                alwaysDisabledSymbols: alwaysDisabledSymbols,
                undefinedSymbolValue: undefinedSymbolValue);

            return(new AnalysisEngine(options));
        }
        private Tristate EvaluateDirectiveExpression(DirectiveTriviaSyntax directive, Tristate previousRegionState)
        {
            switch (directive.Kind())
            {
            case SyntaxKind.IfDirectiveTrivia:
                return(EvaluateExpression(((IfDirectiveTriviaSyntax)directive).Condition));

            case SyntaxKind.ElifDirectiveTrivia:
                Tristate result = EvaluateExpression(((ElifDirectiveTriviaSyntax)directive).Condition);
                return(!previousRegionState & result);

            case SyntaxKind.ElseDirectiveTrivia:
                return(!previousRegionState);

            default:
                Debug.Assert(false);
                return(Tristate.Varying);
            }
        }
        private ImmutableArray <ConditionalRegion> ParseConditionalRegionChain(IList <DirectiveTriviaSyntax> directives, HashSet <DirectiveTriviaSyntax> visitedDirectives)
        {
            DirectiveTriviaSyntax previousDirective = null;
            Tristate previousRegionState            = Tristate.False;
            bool     hasEnabledRegion = false;
            var      chain            = ImmutableArray.CreateBuilder <ConditionalRegion>();

            for (int i = 0; i < directives.Count; i++)
            {
                var directive = directives[i];

                if (visitedDirectives.Contains(directive))
                {
                    // We've already visited this chain of linked directives
                    return(default(ImmutableArray <ConditionalRegion>));
                }

                if (previousDirective != null)
                {
                    var regionState = EvaluateDirectiveExpression(previousDirective, previousRegionState);
                    previousRegionState = regionState;

                    if (regionState == Tristate.True)
                    {
                        // There can only be one always enabled region per chain
                        regionState      = hasEnabledRegion ? Tristate.False : Tristate.True;
                        hasEnabledRegion = true;
                    }

                    var region = new ConditionalRegion(previousDirective, directive, regionState);
                    chain.Add(region);
                }

                previousDirective = directive;
                visitedDirectives.Add(directive);
            }

            return(chain.ToImmutable());
        }
        public static AnalysisEngine FromProjects(
            IEnumerable <Project> projects,
            IEnumerable <IEnumerable <string> > symbolConfigurations = null,
            IEnumerable <string> alwaysIgnoredSymbols  = null,
            IEnumerable <string> alwaysDefinedSymbols  = null,
            IEnumerable <string> alwaysDisabledSymbols = null,
            Tristate undefinedSymbolValue = default(Tristate))
        {
            if (projects != null && !projects.Any())
            {
                throw new ArgumentException("Must specify at least one project");
            }

            var options = new Options(
                projects: projects,
                symbolConfigurations: symbolConfigurations,
                alwaysIgnoredSymbols: alwaysIgnoredSymbols,
                alwaysDefinedSymbols: alwaysDefinedSymbols,
                alwaysDisabledSymbols: alwaysDisabledSymbols,
                undefinedSymbolValue: undefinedSymbolValue);

            return(new AnalysisEngine(options));
        }
Пример #10
0
        public override SyntaxNode VisitBinaryExpression(BinaryExpressionSyntax node)
        {
            Tristate leftState  = _expressionEvaluator.EvaluateExpression(node.Left);
            Tristate rightState = _expressionEvaluator.EvaluateExpression(node.Right);

            var left  = (ExpressionSyntax)node.Left.Accept(this);
            var right = (ExpressionSyntax)node.Right.Accept(this);

            if (node.Left != left)
            {
                node = node.WithLeft(left);
            }

            if (node.Right != right)
            {
                node = node.WithRight(right);
            }

            if (leftState != Tristate.Varying && rightState != Tristate.Varying)
            {
                return(node);
            }

            ExpressionSyntax newExpression = null;

            if (node.Kind() == SyntaxKind.LogicalAndExpression)
            {
                if (leftState == Tristate.True)
                {
                    // true && varying == varying
                    newExpression = right;
                }
                else if (rightState == Tristate.True)
                {
                    // varying && true == varying
                    newExpression = left;
                }
            }
            else if (node.Kind() == SyntaxKind.LogicalOrExpression)
            {
                if (leftState == Tristate.False)
                {
                    // false || varying == varying
                    newExpression = right;
                }
                else if (rightState == Tristate.False)
                {
                    // varying || false == varying
                    newExpression = left;
                }
            }

            if (newExpression != null)
            {
                return(newExpression
                       .WithLeadingTrivia(node.GetLeadingTrivia())
                       .WithTrailingTrivia(node.GetTrailingTrivia()));
            }

            return(node);
        }