public override void VisitList(SyntaxNodeOrTokenList list) { foreach (var nodeOrToken in list) { if (nodeOrToken.IsToken) { var token = nodeOrToken.AsToken(); if (token.Kind == TokenKind.IdentifierToken) { AddToken(token, _scheme.Identifier); } else if (SyntaxFacts.IsBracket(token.Kind)) { AddToken(token, _scheme.Bracket); } else { AddToken(token, _scheme.Punctuation); } } else { Visit(nodeOrToken.AsNode()); } } }
private async Task <Solution> CreateTestCategoryAttribute(Document document, Diagnostic diagnostic, MethodDeclarationSyntax methodDeclaration, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken); var frameworkAnalyzerUsed = FrameworkAnalyzers.FirstOrDefault(analyzer => analyzer.GetType().FullName == diagnostic.Properties[nameof(IFrameworkAnalyzer)]); string testCategoryAttribute = frameworkAnalyzerUsed.TestCategoryAttribute; SyntaxNodeOrTokenList attributeArguments = frameworkAnalyzerUsed.GetTestCategoryAttributeArguments(); var currentIndent = methodDeclaration.GetLeadingTrivia().Where(t => t.IsKind(SyntaxKind.WhitespaceTrivia)); var attributes = methodDeclaration.AttributeLists.Add( SyntaxFactory.AttributeList( SyntaxFactory.SingletonSeparatedList( SyntaxFactory.Attribute( SyntaxFactory.IdentifierName(testCategoryAttribute)) .WithArgumentList(SyntaxFactory .AttributeArgumentList(SyntaxFactory .SeparatedList <AttributeArgumentSyntax>(attributeArguments))) )).NormalizeWhitespace() .WithLeadingTrivia(currentIndent) .WithTrailingTrivia(SyntaxFactory.Whitespace(Environment.NewLine))); document = document.WithSyntaxRoot( root.ReplaceNode( methodDeclaration, methodDeclaration.WithAttributeLists(attributes) )); return(document.Project.Solution); }
public SeparatedSyntaxListBuilder<TNode> AddRange(SeparatedSyntaxList<TNode> nodes) { CheckExpectedElement(); SyntaxNodeOrTokenList list = nodes.GetWithSeparators(); _builder.AddRange(list); _expectedSeparator = ((_builder.Count & 1) != 0); return this; }
public SeparatedSyntaxListBuilder<TNode> AddRange(SeparatedSyntaxList<TNode> nodes, int count) { CheckExpectedElement(); SyntaxNodeOrTokenList list = nodes.GetWithSeparators(); _builder.AddRange(list, this.Count, Math.Min(count << 1, list.Count)); _expectedSeparator = ((_builder.Count & 1) != 0); return this; }
protected override SyntaxToken FromNodesOrTokens(SyntaxNodeOrTokenList nodesOrTokens) { if (nodesOrTokens.Count != 1) { throw new ArgumentException("expected singleton list", nameof(nodesOrTokens)); } return(nodesOrTokens[0].GetToken()); }
public void Add(SyntaxNodeOrTokenList list, int offset, int length) { if (nodes == null || count + length > nodes.Length) { this.Grow(count + length); } list.CopyTo(offset, nodes, count, length); count += length; }
public void Add(SyntaxNodeOrTokenList list, int offset, int length) { if (_nodes == null || _count + length > _nodes.Length) { this.Grow(_count + length); } list.CopyTo(offset, _nodes, _count, length); _count += length; }
internal static bool TryGetAtIndex(this SyntaxNodeOrTokenList source, int index, out SyntaxNodeOrToken result) { result = default(SyntaxNodeOrToken); if (source.Count <= index) { return(false); } result = source[index]; return(true); }
private static SyntaxNodeOrTokenList OmitTrailingComma(SyntaxNodeOrTokenList list) { // Trailing comma is allowed in initializer list, but disallowed in method calls. if (list.Count == 0 || list.Count % 2 == 1) { // The list is either empty, or does not end with a trailing comma. return(list); } return(list.Replace( list[^ 2],
/// <summary> /// Try getting the first element in <paramref name="source"/> /// </summary> /// <param name="source">The source collection, can be null.</param> /// <param name="result">The first element, can be null.</param> /// <returns>True if an element was found.</returns> internal static bool TryFirst(this SyntaxNodeOrTokenList source, out SyntaxNodeOrToken result) { result = default(SyntaxNodeOrToken); if (source.Count == 0) { return(false); } result = source[0]; return(true); }
private static bool NodesAreCorrectType <TNode>(SyntaxNodeOrTokenList list) { for (int i = 0, n = list.Count; i < n; i++) { var element = list[i]; if (element.IsNode && !(element.AsNode() is TNode)) { return(false); } } return(true); }
private static bool HasSeparatedNodeTokenPattern(SyntaxNodeOrTokenList list) { for (int i = 0, n = list.Count; i < n; i++) { var element = list[i]; if (element.IsToken == ((i & 1) == 0)) { return(false); } } return(true); }
/// <summary> /// Try getting the first element in <paramref name="source"/> matching <paramref name="predicate"/> /// </summary> /// <param name="source">The source collection, can be null.</param> /// <param name="predicate">The predicate.</param> /// <param name="result">The first element matching the predicate, can be null.</param> /// <returns>True if an element was found.</returns> internal static bool TryFirst(this SyntaxNodeOrTokenList source, Func <SyntaxNodeOrToken, bool> predicate, out SyntaxNodeOrToken result) { result = default(SyntaxNodeOrToken); foreach (var item in source) { if (predicate(item)) { result = item; return(true); } } return(false); }
internal static bool TryGetSingle(this SyntaxNodeOrTokenList source, Func <SyntaxNodeOrToken, bool> selector, out SyntaxNodeOrToken result) { result = default(SyntaxNodeOrToken); foreach (var item in source) { if (selector(item)) { result = item; return(true); } } return(false); }
/// <summary> /// Creates a separated list from a <see cref="SyntaxNodeOrTokenList"/>, where the list elements start with a node and then alternate between /// additional nodes and separator tokens. /// </summary> /// <typeparam name="TNode">The specific type of the element nodes.</typeparam> /// <param name="nodesAndTokens">The list of nodes and tokens.</param> public virtual SeparatedSyntaxList <TNode> SeparatedList <TNode>(SyntaxNodeOrTokenList nodesAndTokens) where TNode : SyntaxNode { if (!HasSeparatedNodeTokenPattern(nodesAndTokens)) { throw new ArgumentException(CodeAnalysisResources.NodeOrTokenOutOfSequence); } if (!NodesAreCorrectType <TNode>(nodesAndTokens)) { throw new ArgumentException(CodeAnalysisResources.UnexpectedTypeOfNodeInList); } return(new SeparatedSyntaxList <TNode>(nodesAndTokens)); }
internal static bool TryGetLast(this SyntaxNodeOrTokenList source, Func <SyntaxNodeOrToken, bool> selector, out SyntaxNodeOrToken result) { result = default(SyntaxNodeOrToken); for (var i = source.Count - 1; i >= 0; i--) { var item = source[i]; if (selector(item)) { result = item; return(true); } } return(false); }
private static void Validate(SyntaxNodeOrTokenList list) { for (int i = 0; i < list.Count; i++) { var item = list[i]; if ((i & 1) == 0) { Debug.Assert(item.IsNode, "Node missing in separated list."); } else { Debug.Assert(item.IsToken, "Separator token missing in separated list."); } } }
internal SeparatedSyntaxList(SyntaxNodeOrTokenList list) : this() { Validate(list); // calculating counts is very cheap when list interleaves nodes and tokens // so lets just do it here. int allCount = list.Count; this.count = (allCount + 1) >> 1; this.separatorCount = allCount >> 1; this.list = list; }
private static async Task <Document> SortEnumMembersAsync( Document document, EnumDeclarationSyntax enumDeclaration, CancellationToken cancellationToken) { SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); SpecialType enumSpecialType = semanticModel.GetDeclaredSymbol(enumDeclaration).EnumUnderlyingType.SpecialType; SeparatedSyntaxList <EnumMemberDeclarationSyntax> members = enumDeclaration.Members; SeparatedSyntaxList <EnumMemberDeclarationSyntax> newMembers = members .OrderBy(f => GetConstantValue(f, semanticModel, cancellationToken), EnumValueComparer.GetInstance(enumSpecialType)) .ToSeparatedSyntaxList(); if (AreSeparatedWithEmptyLine(members)) { for (int i = 0; i < newMembers.Count; i++) { newMembers = newMembers.ReplaceAt(i, newMembers[i].TrimLeadingTrivia()); } for (int i = 0; i < newMembers.Count - 1; i++) { SyntaxToken separator = newMembers.GetSeparator(i); newMembers = newMembers.ReplaceSeparator( separator, separator.TrimTrailingTrivia().AppendToTrailingTrivia(new SyntaxTrivia[] { NewLine(), NewLine() })); } } if (newMembers.SeparatorCount == members.SeparatorCount - 1) { SyntaxNodeOrTokenList newMembersWithSeparators = newMembers.GetWithSeparators(); newMembersWithSeparators = newMembersWithSeparators.Add(CommaToken()); newMembers = newMembersWithSeparators.ToSeparatedSyntaxList <EnumMemberDeclarationSyntax>(); } MemberDeclarationSyntax newNode = enumDeclaration .WithMembers(newMembers) .WithFormatterAnnotation(); return(await document.ReplaceNodeAsync(enumDeclaration, newNode, cancellationToken).ConfigureAwait(false)); }
private void DoTestAddInsertRemoveReplaceOnEmptyList(SyntaxNodeOrTokenList list) { Assert.Equal(0, list.Count); SyntaxNodeOrToken tokenD = SyntaxFactory.ParseToken("D "); SyntaxNodeOrToken nodeE = SyntaxFactory.ParseExpression("E "); var newList = list.Add(tokenD); Assert.Equal(1, newList.Count); Assert.Equal("D ", newList.ToFullString()); newList = list.AddRange(new[] { tokenD, nodeE }); Assert.Equal(2, newList.Count); Assert.Equal("D E ", newList.ToFullString()); newList = list.Insert(0, tokenD); Assert.Equal(1, newList.Count); Assert.Equal("D ", newList.ToFullString()); newList = list.InsertRange(0, new[] { tokenD, nodeE }); Assert.Equal(2, newList.Count); Assert.Equal("D E ", newList.ToFullString()); newList = list.Remove(tokenD); Assert.Equal(0, newList.Count); Assert.Equal(-1, list.IndexOf(tokenD)); Assert.Throws <ArgumentOutOfRangeException>(() => list.RemoveAt(0)); Assert.Throws <ArgumentOutOfRangeException>(() => list.Insert(1, tokenD)); Assert.Throws <ArgumentOutOfRangeException>(() => list.Insert(-1, tokenD)); Assert.Throws <ArgumentOutOfRangeException>(() => list.InsertRange(1, new[] { tokenD })); Assert.Throws <ArgumentOutOfRangeException>( () => list.InsertRange(-1, new[] { tokenD }) ); Assert.Throws <ArgumentOutOfRangeException>(() => list.Add(default(SyntaxNodeOrToken))); Assert.Throws <ArgumentOutOfRangeException>( () => list.Insert(0, default(SyntaxNodeOrToken)) ); Assert.Throws <ArgumentNullException>( () => list.AddRange((IEnumerable <SyntaxNodeOrToken>)null) ); Assert.Throws <ArgumentNullException>( () => list.InsertRange(0, (IEnumerable <SyntaxNodeOrToken>)null) ); }
public void AddRange(SyntaxNodeOrTokenList list, int offset, int count) { if (nodes == null || this.Count + count > nodes.Length) { this.Grow(Count + count); } var dst = this.Count; for (int i = offset, limit = offset + count; i < limit; i++) { this.nodes[dst].Value = list[i].UnderlyingNode; dst++; } int start = Count; Count += count; Validate(start, Count); }
public static TypeArgumentListSyntax AsList(params TypeSyntax[] types) { SyntaxNodeOrTokenList list = new SyntaxNodeOrTokenList(); var last = types.Length > 0 ? types.Last() : null; foreach (var type in types) { list = list.Add(type); if (!type.Equals(last)) { list = list.Add(Token.Comma); } } return SyntaxFactory.TypeArgumentList(SyntaxFactory.SeparatedList<TypeSyntax>(list)) .WithLessThanToken(Token.LessThan) .WithGreaterThanToken(Token.GreaterThan); }
public static void GetSeparatorInfo( SyntaxNodeOrTokenList nodesAndSeparators, int nodeIndex, int endOfLineKind, out bool nextTokenIsSeparator, out bool nextSeparatorBelongsToNode ) { // remove preceding separator if any, except for the case where // the following separator immediately touches the item in the list // and is followed by a newline. // // In that case, we consider the next token to be more closely // associated with the item, and it should be removed. // // For example, if you have: // // Goo(a, // a stuff // b, // b stuff // c); // // If we're removing 'b', we should remove the comma after it. // // If there is no next comma, or the next comma is not on the // same line, then just remove the preceding comma if there is // one. If there is no next or previous comma there's nothing // in the list that needs to be fixed up. var node = nodesAndSeparators[nodeIndex].AsNode(); Debug.Assert(node is object); nextTokenIsSeparator = nodeIndex + 1 < nodesAndSeparators.Count && nodesAndSeparators[nodeIndex + 1].IsToken; nextSeparatorBelongsToNode = nextTokenIsSeparator && nodesAndSeparators[nodeIndex + 1].AsToken() is var nextSeparator && !nextSeparator.HasLeadingTrivia && !ContainsEndOfLine(node.GetTrailingTrivia(), endOfLineKind) && ContainsEndOfLine(nextSeparator.TrailingTrivia, endOfLineKind); }
/// <summary> /// Returns this list as a <see cref="Microsoft.CodeAnalysis.SeparatedSyntaxList<TNode>"/>. /// </summary> /// <typeparam name="TOther">The type of the list elements in the separated list.</typeparam> /// <returns></returns> internal static SeparatedSyntaxList <TOther> AsSeparatedList <TOther>(this SyntaxNodeOrTokenList list) where TOther : SyntaxNode { var builder = SeparatedSyntaxListBuilder <TOther> .Create(); foreach (var i in list) { var node = i.AsNode(); if (node != null) { builder.Add((TOther)node); } else { builder.AddSeparator(i.AsToken()); } } return(builder.ToList()); }
public static ArgumentListSyntax AsList(params ArgumentSyntax[] arguments) { SyntaxNodeOrTokenList list = new SyntaxNodeOrTokenList(); var last = arguments.Length > 0 ? arguments.Last() : null; foreach (var argument in arguments) { list = list.Add(argument); if (!argument.Equals(last)) { list = list.Add(Token.Comma); } } return SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList<ArgumentSyntax>(list)) .WithOpenParenToken(Token.OpenParen) .WithCloseParenToken(Token.CloseParen); }
/** * start a new procedure/function */ private static MethodDeclarationSyntax StartFunction([NotNull] FunctionDeclaration functionDeclaration) { var method = SyntaxFactory.MethodDeclaration(GetTypeName(functionDeclaration.ReturnType), functionDeclaration.Name); if (!functionDeclaration.Block.Declarations.Any(x => x is ProcedureParameterDeclaration)) { return(method); } var list = new SyntaxNodeOrTokenList(); bool first = true; foreach (var declaration in functionDeclaration.Block.Declarations.OfType <ProcedureParameterDeclaration>()) { if (!first) { list = list.Add(SyntaxFactory.Token(SyntaxKind.CommaToken)); } first = false; var param = SyntaxFactory.Parameter(MapIdentifier(declaration.Name)) .WithType(AddTypeSyntaxSpecification(declaration)); if (declaration.IsVar) { param = param.WithModifiers(SyntaxFactory.TokenList( SyntaxFactory.Token(SyntaxKind.RefKeyword))); } list = list.Add(param); } if (list.Any()) { method = method.WithParameterList(SyntaxFactory.ParameterList( SyntaxFactory.SeparatedList <ParameterSyntax>(list))); } return(method); }
/// <summary> /// Try getting the single element in <paramref name="source"/> matching <paramref name="predicate"/> /// </summary> /// <param name="source">The source collection, can be null.</param> /// <param name="predicate">The predicate.</param> /// <param name="result">The single element matching the predicate, can be null.</param> /// <returns>True if an element was found.</returns> internal static bool TrySingle(this SyntaxNodeOrTokenList source, Func <SyntaxNodeOrToken, bool> predicate, out SyntaxNodeOrToken result) { result = default(SyntaxNodeOrToken); for (var i = 0; i < source.Count; i++) { var item = source[i]; if (predicate(item)) { result = item; for (var j = i + 1; j < source.Count; j++) { if (predicate(source[j])) { return(false); } } return(true); } } return(false); }
private static void CheckIfCommasAreAtTheSameLineAsThePreviousParameter(SyntaxNodeAnalysisContext context, SyntaxNodeOrTokenList nodeOrTokenList) { SyntaxNode previousNode = null; // If index is even we expecting parameter syntax node, otherwise we expecting comma token. for (int index = 0, count = nodeOrTokenList.Count; index < count; ++index) { SyntaxNodeOrToken nodeOrToken = nodeOrTokenList[index]; if (index % 2 == 0) { // We expecting node here if (nodeOrToken.IsToken) { return; } previousNode = nodeOrToken.AsNode(); } else { // We expecting token here if (nodeOrToken.IsNode) { return; } if (previousNode.GetEndLine() < nodeOrToken.GetLineSpan().StartLinePosition.Line) { var properties = TokenSpacingProperties.RemovePrecedingPreserveLayout; context.ReportDiagnostic(Diagnostic.Create(Descriptor, nodeOrToken.GetLocation(), properties)); } } } }
public void ThrowIfUnderlyingNodeIsNullForList() { var list = new SyntaxNodeOrTokenList(); Assert.Equal(list.Count, 0); foreach (var index in new int[] { -1, 0, 23 }) { bool exceptionThrown = false; try { var unused = list[0]; } catch (ArgumentOutOfRangeException) { exceptionThrown = true; } Assert.True(exceptionThrown); } }
private static void CheckIfCommasAreAtTheSameLineAsThePreviousParameter(SyntaxNodeAnalysisContext context, SyntaxNodeOrTokenList nodeOrTokenList) { SyntaxNode previousNode = null; // If index is even we expecting parameter syntax node, otherwise we expecting comma token. for (int index = 0, count = nodeOrTokenList.Count; index < count; ++index) { SyntaxNodeOrToken nodeOrToken = nodeOrTokenList[index]; if (index % 2 == 0) { // We expecting node here if (nodeOrToken.IsToken) { return; } previousNode = nodeOrToken.AsNode(); } else { // We expecting token here if (nodeOrToken.IsNode) { return; } if (previousNode.GetEndLine() < nodeOrToken.GetLineSpan().StartLinePosition.Line) { var properties = new Dictionary <string, string> { [OpenCloseSpacingCodeFixProvider.LocationKey] = OpenCloseSpacingCodeFixProvider.LocationPreceding, [OpenCloseSpacingCodeFixProvider.ActionKey] = OpenCloseSpacingCodeFixProvider.ActionRemove, [OpenCloseSpacingCodeFixProvider.LayoutKey] = OpenCloseSpacingCodeFixProvider.LayoutPreserve }; context.ReportDiagnostic(Diagnostic.Create(Descriptor, nodeOrToken.GetLocation(), properties.ToImmutableDictionary())); } } } }
public void AddRange(SyntaxNodeOrTokenList list) { this.AddRange(list, 0, list.Count); }
public void Add(SyntaxNodeOrTokenList list) { this.Add(list, 0, list.Count); }
private void DoTestAddInsertRemoveReplaceOnEmptyList(SyntaxNodeOrTokenList list) { Assert.Equal(0, list.Count); SyntaxNodeOrToken tokenD = SyntaxFactory.ParseToken("D "); SyntaxNodeOrToken nodeE = SyntaxFactory.ParseExpression("E "); var newList = list.Add(tokenD); Assert.Equal(1, newList.Count); Assert.Equal("D ", newList.ToFullString()); newList = list.AddRange(new[] { tokenD, nodeE }); Assert.Equal(2, newList.Count); Assert.Equal("D E ", newList.ToFullString()); newList = list.Insert(0, tokenD); Assert.Equal(1, newList.Count); Assert.Equal("D ", newList.ToFullString()); newList = list.InsertRange(0, new[] { tokenD, nodeE }); Assert.Equal(2, newList.Count); Assert.Equal("D E ", newList.ToFullString()); newList = list.Remove(tokenD); Assert.Equal(0, newList.Count); Assert.Equal(-1, list.IndexOf(tokenD)); Assert.Throws<ArgumentOutOfRangeException>(() => list.RemoveAt(0)); Assert.Throws<ArgumentOutOfRangeException>(() => list.Insert(1, tokenD)); Assert.Throws<ArgumentOutOfRangeException>(() => list.Insert(-1, tokenD)); Assert.Throws<ArgumentOutOfRangeException>(() => list.InsertRange(1, new[] { tokenD })); Assert.Throws<ArgumentOutOfRangeException>(() => list.InsertRange(-1, new[] { tokenD })); Assert.Throws<ArgumentException>(() => list.Add(default(SyntaxNodeOrToken))); Assert.Throws<ArgumentException>(() => list.Insert(0, default(SyntaxNodeOrToken))); Assert.Throws<ArgumentNullException>(() => list.AddRange((IEnumerable<SyntaxNodeOrToken>)null)); Assert.Throws<ArgumentNullException>(() => list.InsertRange(0, (IEnumerable<SyntaxNodeOrToken>)null)); }
private static void CheckIfCommasAreAtTheSameLineAsThePreviousParameter(SyntaxNodeAnalysisContext context, SyntaxNodeOrTokenList nodeOrTokenList) { SyntaxNode previousNode = null; // If index is even we expecting parameter syntax node, otherwise we expecting comma token. for (int index = 0, count = nodeOrTokenList.Count; index < count; ++index) { SyntaxNodeOrToken nodeOrToken = nodeOrTokenList[index]; if (index % 2 == 0) { // We expecting node here if (nodeOrToken.IsToken) { return; } previousNode = nodeOrToken.AsNode(); } else { // We expecting token here if (nodeOrToken.IsNode) { return; } if (previousNode.GetEndLine() < nodeOrToken.GetLineSpan().StartLinePosition.Line) { var properties = new Dictionary<string, string> { [OpenCloseSpacingCodeFixProvider.LocationKey] = OpenCloseSpacingCodeFixProvider.LocationPreceding, [OpenCloseSpacingCodeFixProvider.ActionKey] = OpenCloseSpacingCodeFixProvider.ActionRemove, [OpenCloseSpacingCodeFixProvider.LayoutKey] = OpenCloseSpacingCodeFixProvider.LayoutPreserve }; context.ReportDiagnostic(Diagnostic.Create(Descriptor, nodeOrToken.GetLocation(), properties.ToImmutableDictionary())); } } } }
private SyntaxNodeOrTokenList CreateArguments(SyntaxNodeOrTokenList list) => new SyntaxNodeOrTokenList(list.Select(CreateArgumentOrComma));
public virtual void VisitList(SyntaxNodeOrTokenList list) { DefaultVisit(list); }