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)); } }
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); }
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); } } }
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)); }
protected override bool MatchesNodeType(SyntaxNodeOrToken nodeOrToken, SyntaxQuery query) { return(GetSyntaxKinds(query).Contains(nodeOrToken.Kind())); }
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); } }