Example #1
0
 public Rule(string id, SyntaxQuery query, RuleSeverity severity, string message)
 {
     Id       = id;
     Query    = query;
     Severity = severity;
     Message  = message;
 }
        private bool MatchesIgnoringAxis(SyntaxNodeOrToken nodeOrToken, SyntaxQuery query)
        {
            var node = nodeOrToken.AsNode();

            if (node is ExpressionStatementSyntax statement && node.Kind() == ExpressionStatement)
            {
                return(MatchesIgnoringAxis(statement.Expression, query));
            }

            if (node is SwitchSectionSyntax switchSection)
            {
                foreach (var label in switchSection.Labels)
                {
                    if (MatchesSyntaxKindAndFilter(switchSection, label.Kind(), query))
                    {
                        return(true);
                    }
                }
            }

            if (node is PredefinedTypeSyntax predefinedType)
            {
                return(MatchesSyntaxKindAndFilter(predefinedType, predefinedType.Keyword.Kind(), query));
            }

            return(MatchesSyntaxKindAndFilter(nodeOrToken, nodeOrToken.Kind(), query));
        }
        public IEnumerable <SyntaxNodeOrToken> QueryAll(CSharpSyntaxNode current, SyntaxQuery query)
        {
            if (current is CompilationUnitSyntax)
            {
                return(current.ChildNodes().SelectMany(c => QueryAll((CSharpSyntaxNode)c, query)));
            }

            switch (query.Axis)
            {
            case SyntaxQueryAxis.Self:
                if (MatchesIgnoringAxis(current, query))
                {
                    return(Enumerable.Repeat((SyntaxNodeOrToken)current, 1));
                }
                return(Enumerable.Empty <SyntaxNodeOrToken>());

            case SyntaxQueryAxis.Child:
                return(QueryAllChildrenOrDescendants(current, query, descendants: false));

            case SyntaxQueryAxis.Descendant:
                return(QueryAllChildrenOrDescendants(current, query, descendants: true));

            case SyntaxQueryAxis.Parent:
                if (MatchesIgnoringAxis(current.Parent, query))
                {
                    return(Enumerable.Repeat((SyntaxNodeOrToken)current.Parent, 1));
                }
                return(Enumerable.Empty <SyntaxNodeOrToken>());

            default:
                throw new ArgumentException($"Unsupported query axis: {query.Axis}.", nameof(query));
            }
        }
Example #4
0
 private static HashSet <SyntaxKind> GetSyntaxKinds(SyntaxQuery query)
 {
     if (!SyntaxKindsByKeyword.TryGetValue(query.Keyword, out var kinds))
     {
         throw new NotSupportedException($"Unsupported query keyword: {query.Keyword}.");
     }
     return(kinds);
 }
 private static HashSet <NodeType> GetNodeTypes(SyntaxQuery query)
 {
     if (!NodeTypesByKeyword.TryGetValue(query.Keyword, out var types))
     {
         throw new NotSupportedException($"Unsupported query keyword: {query.Keyword}.");
     }
     return(types);
 }
Example #6
0
 private IEnumerable <SyntaxNodeOrToken> Search(SyntaxQuery query, Compilation compilation)
 {
     foreach (var tree in compilation.SyntaxTrees)
     {
         foreach (var match in _executor.QueryAll((CSharpSyntaxNode)tree.GetRoot(), query))
         {
             yield return(match);
         }
     }
 }
Example #7
0
        public SyntaxRuleConfiguration Load(string content)
        {
            var lines = content.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
            var rules = new List <SyntaxRule>();

            string             ruleId       = null;
            SyntaxQuery        ruleQuery    = null;
            SyntaxRuleSeverity?ruleSeverity = null;
            string             ruleMessage  = null;

            foreach (var line in lines)
            {
                if (Char.IsWhiteSpace(line[0]))
                {
                    // TODO: don't allocate
                    var trimmed = line.TrimStart();
                    if (ruleId == null)
                    {
                        continue; // TODO: error
                    }
                    if (ruleQuery == null)
                    {
                        ruleQuery = _parser.Parse(trimmed);
                        continue;
                    }
                    // TODO: don't allocate
                    var parts = trimmed.Split(new[] { ':' }, 2);
                    ruleSeverity = parts[0] == "error" ? SyntaxRuleSeverity.Error : SyntaxRuleSeverity.Warning;
                    ruleMessage  = parts[1].Trim(); // TODO: don't allocate (if possible)
                }
                else
                {
                    if (ruleId != null && ruleQuery != null)
                    {
                        rules.Add(new SyntaxRule(ruleId, ruleQuery, ruleSeverity ?? SyntaxRuleSeverity.Error, ruleMessage));
                    }
                    ruleId       = line;
                    ruleQuery    = null;
                    ruleSeverity = null;
                    ruleMessage  = null;
                }
            }
            if (ruleId != null && ruleQuery != null)
            {
                rules.Add(new SyntaxRule(ruleId, ruleQuery, ruleSeverity ?? SyntaxRuleSeverity.Error, ruleMessage));
            }
            return(new SyntaxRuleConfiguration(rules));
        }
Example #8
0
 protected override bool MatchesNodeType(SyntaxNodeOrToken nodeOrToken, SyntaxQuery query)
 {
     return(GetSyntaxKinds(query).Contains(nodeOrToken.Kind()));
 }
Example #9
0
 public IEnumerable <SyntaxKind> GetRootSyntaxKinds(SyntaxQuery query)
 {
     return(GetSyntaxKinds(query));
 }
 private bool MatchesSyntaxKindAndFilter(SyntaxNodeOrToken nodeOrToken, SyntaxKind syntaxKind, SyntaxQuery query)
 {
     return(GetSyntaxKinds(query).Contains(syntaxKind) &&
            MatchesFilter(nodeOrToken, query.Filter));
 }
        private IEnumerable <SyntaxNodeOrToken> QueryAllChildrenOrDescendants(SyntaxNode node, SyntaxQuery query, bool descendants)
        {
            foreach (var child in node.ChildNodesAndTokens())
            {
                if (MatchesIgnoringAxis(child, query))
                {
                    yield return(child);

                    continue;
                }

                if (descendants && child.IsNode)
                {
                    foreach (var descendant in QueryAllChildrenOrDescendants(child.AsNode(), query, descendants: true))
                    {
                        yield return(descendant);
                    }
                }
            }
        }
        protected override bool MatchesNodeType(ITreeNode node, SyntaxQuery query)
        {
            switch (query.Keyword)
            {
            case Add: return(IsAccessorWithName("add"));

            case Get: return(IsAccessorWithName("get"));

            case Remove: return(IsAccessorWithName("remove"));

            case Set: return(IsAccessorWithName("set"));

            case Base: if (IsConstructorInitializer(ConstructorInitializerKind.BASE))
                {
                    return(true);
                }
                break;

            case This: if (IsConstructorInitializer(ConstructorInitializerKind.THIS))
                {
                    return(true);
                }
                break;

            case Event: {
                if (node is IMultipleEventDeclaration events && events.Children().OfType <IEventDeclaration>().Count() == 1)
                {
                    return(true);
                }
                break;
            }

            case Default: if (IsCaseLabel(isDefault: true))
                {
                    return(true);
                }
                break;

            case Case: if (IsCaseLabel(isDefault: false))
                {
                    return(true);
                }
                break;

            case Global: return(node is IIdentifier identifier && identifier.Name == "global");
            }

            return(GetNodeTypes(query).Contains(node.NodeType));

            bool IsAccessorWithName(string name)
            {
                return(node is IAccessorDeclaration accessor &&
                       accessor.NameIdentifier.Name == name);
            }

            bool IsConstructorInitializer(ConstructorInitializerKind kind)
            {
                return(node is IConstructorInitializer initializer &&
                       initializer.Kind == kind);
            }

            bool IsCaseLabel(bool isDefault)
            {
                return(node is ISwitchCaseLabel caseLabel &&
                       caseLabel.IsDefault == isDefault);
            }
        }