/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/VisualStudio/CSharp/Impl/CodeModel/CSharpCodeModelService.NodeLocator.cs
1 341 строка
55 KB
Cyrus Najmabadi
Use file scoped namespaces. (#77854)
27 мар 2025, 09:55
Не верифицирован
27 мар 2025, 09:55
98d41b8
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #nullable disable using System; using System.Diagnostics; using System.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Editor.Shared.Utilities; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Text; using Microsoft.VisualStudio.LanguageServices.Implementation.Utilities; namespace Microsoft.VisualStudio.LanguageServices.CSharp.CodeModel; internal sealed partial class CSharpCodeModelService { protected override AbstractNodeLocator CreateNodeLocator() => new NodeLocator(); private sealed class NodeLocator : AbstractNodeLocator { protected override string LanguageName => LanguageNames.CSharp; protected override EnvDTE.vsCMPart DefaultPart => EnvDTE.vsCMPart.vsCMPartWholeWithAttributes; protected override VirtualTreePoint? GetStartPoint(SourceText text, LineFormattingOptions options, SyntaxNode node, EnvDTE.vsCMPart part) { switch (node.Kind()) { case SyntaxKind.ArrowExpressionClause: return GetStartPoint(text, (ArrowExpressionClauseSyntax)node, part); case SyntaxKind.Attribute: return GetStartPoint(text, (AttributeSyntax)node, part); case SyntaxKind.AttributeArgument: return GetStartPoint(text, (AttributeArgumentSyntax)node, part); case SyntaxKind.ClassDeclaration: case SyntaxKind.RecordDeclaration: case SyntaxKind.InterfaceDeclaration: case SyntaxKind.StructDeclaration: case SyntaxKind.RecordStructDeclaration: case SyntaxKind.EnumDeclaration: return GetStartPoint(text, (BaseTypeDeclarationSyntax)node, part); case SyntaxKind.MethodDeclaration: case SyntaxKind.ConstructorDeclaration: case SyntaxKind.DestructorDeclaration: case SyntaxKind.OperatorDeclaration: case SyntaxKind.ConversionOperatorDeclaration: return GetStartPoint(text, options, (BaseMethodDeclarationSyntax)node, part); case SyntaxKind.PropertyDeclaration: case SyntaxKind.IndexerDeclaration: case SyntaxKind.EventDeclaration: return GetStartPoint(text, options, (BasePropertyDeclarationSyntax)node, part); case SyntaxKind.GetAccessorDeclaration: case SyntaxKind.SetAccessorDeclaration: case SyntaxKind.AddAccessorDeclaration: case SyntaxKind.RemoveAccessorDeclaration: return GetStartPoint(text, options, (AccessorDeclarationSyntax)node, part); case SyntaxKind.DelegateDeclaration: return GetStartPoint(text, (DelegateDeclarationSyntax)node, part); case SyntaxKind.NamespaceDeclaration: case SyntaxKind.FileScopedNamespaceDeclaration: return GetStartPoint(text, (BaseNamespaceDeclarationSyntax)node, part); case SyntaxKind.UsingDirective: return GetStartPoint(text, (UsingDirectiveSyntax)node, part); case SyntaxKind.EnumMemberDeclaration: return GetStartPoint(text, (EnumMemberDeclarationSyntax)node, part); case SyntaxKind.VariableDeclarator: return GetStartPoint(text, (VariableDeclaratorSyntax)node, part); case SyntaxKind.Parameter: return GetStartPoint(text, (ParameterSyntax)node, part); default: Debug.Fail("Unsupported node kind: " + node.Kind()); throw new NotSupportedException(); } } protected override VirtualTreePoint? GetEndPoint(SourceText text, LineFormattingOptions options, SyntaxNode node, EnvDTE.vsCMPart part) { switch (node.Kind()) { case SyntaxKind.ArrowExpressionClause: return GetEndPoint(text, (ArrowExpressionClauseSyntax)node, part); case SyntaxKind.Attribute: return GetEndPoint(text, (AttributeSyntax)node, part); case SyntaxKind.AttributeArgument: return GetEndPoint(text, (AttributeArgumentSyntax)node, part); case SyntaxKind.ClassDeclaration: case SyntaxKind.RecordDeclaration: case SyntaxKind.InterfaceDeclaration: case SyntaxKind.StructDeclaration: case SyntaxKind.RecordStructDeclaration: case SyntaxKind.EnumDeclaration: return GetEndPoint(text, (BaseTypeDeclarationSyntax)node, part); case SyntaxKind.MethodDeclaration: case SyntaxKind.ConstructorDeclaration: case SyntaxKind.DestructorDeclaration: case SyntaxKind.OperatorDeclaration: case SyntaxKind.ConversionOperatorDeclaration: return GetEndPoint(text, (BaseMethodDeclarationSyntax)node, part); case SyntaxKind.PropertyDeclaration: case SyntaxKind.IndexerDeclaration: case SyntaxKind.EventDeclaration: return GetEndPoint(text, (BasePropertyDeclarationSyntax)node, part); case SyntaxKind.GetAccessorDeclaration: case SyntaxKind.SetAccessorDeclaration: case SyntaxKind.AddAccessorDeclaration: case SyntaxKind.RemoveAccessorDeclaration: return GetEndPoint(text, (AccessorDeclarationSyntax)node, part); case SyntaxKind.DelegateDeclaration: return GetEndPoint(text, (DelegateDeclarationSyntax)node, part); case SyntaxKind.NamespaceDeclaration: case SyntaxKind.FileScopedNamespaceDeclaration: return GetEndPoint(text, (BaseNamespaceDeclarationSyntax)node, part); case SyntaxKind.UsingDirective: return GetEndPoint(text, (UsingDirectiveSyntax)node, part); case SyntaxKind.EnumMemberDeclaration: return GetEndPoint(text, (EnumMemberDeclarationSyntax)node, part); case SyntaxKind.VariableDeclarator: return GetEndPoint(text, (VariableDeclaratorSyntax)node, part); case SyntaxKind.Parameter: return GetEndPoint(text, (ParameterSyntax)node, part); default: Debug.Fail("Unsupported node kind: " + node.Kind()); throw new NotSupportedException(); } } private static VirtualTreePoint GetBodyStartPoint(SourceText text, SyntaxToken openBrace) { Debug.Assert(!openBrace.IsMissing); var openBraceLine = text.Lines.GetLineFromPosition(openBrace.Span.End); var textAfterBrace = text.ToString(TextSpan.FromBounds(openBrace.Span.End, openBraceLine.End)); return string.IsNullOrWhiteSpace(textAfterBrace) ? new VirtualTreePoint(openBrace.SyntaxTree, text, text.Lines[openBraceLine.LineNumber + 1].Start) : new VirtualTreePoint(openBrace.SyntaxTree, text, openBrace.Span.End); } private static VirtualTreePoint GetBodyStartPoint(SourceText text, LineFormattingOptions options, SyntaxToken openBrace, SyntaxToken closeBrace, int memberStartColumn) { Debug.Assert(!openBrace.IsMissing); Debug.Assert(!closeBrace.IsMissing); Debug.Assert(memberStartColumn >= 0); var openBraceLine = text.Lines.GetLineFromPosition(openBrace.SpanStart); var closeBraceLine = text.Lines.GetLineFromPosition(closeBrace.SpanStart); var tokenAfterOpenBrace = openBrace.GetNextToken(); var nextPosition = tokenAfterOpenBrace.SpanStart; // We need to check if there is any significant trivia trailing this token or leading // to the next token. This accounts for the fact that comments were included in the token // stream in Dev10. var significantTrivia = openBrace.GetAllTrailingTrivia() .Where(t => t is not SyntaxTrivia(SyntaxKind.WhitespaceTrivia or SyntaxKind.EndOfLineTrivia)) .FirstOrDefault(); if (significantTrivia.Kind() != SyntaxKind.None) { nextPosition = significantTrivia.SpanStart; } // If the opening and closing curlies are at least two lines apart then place the cursor // on the next line provided that there isn't any token on the line with the open curly. if (openBraceLine.LineNumber + 1 < closeBraceLine.LineNumber && openBraceLine.LineNumber < text.Lines.IndexOf(tokenAfterOpenBrace.SpanStart)) { var lineAfterOpenBrace = text.Lines[openBraceLine.LineNumber + 1]; var firstNonWhitespaceOffset = lineAfterOpenBrace.GetFirstNonWhitespaceOffset() ?? -1; // If the line contains any text, we return the start of the first non-whitespace character. if (firstNonWhitespaceOffset >= 0) { return new VirtualTreePoint(openBrace.SyntaxTree, text, lineAfterOpenBrace.Start + firstNonWhitespaceOffset); } // If the line is all whitespace then place the caret at the first indent after the start // of the member. var indentSize = options.TabSize; var lineText = lineAfterOpenBrace.ToString(); var lineEndColumn = lineText.GetColumnFromLineOffset(lineText.Length, indentSize); var indentColumn = memberStartColumn + indentSize; var virtualSpaces = indentColumn - lineEndColumn; return new VirtualTreePoint(openBrace.SyntaxTree, text, lineAfterOpenBrace.End, virtualSpaces); } else { // If the body is empty then place it after the open brace; otherwise, place // at the start of the first token after the open curly. if (closeBrace.SpanStart == nextPosition) { return new VirtualTreePoint(openBrace.SyntaxTree, text, openBrace.Span.End); } else { return new VirtualTreePoint(openBrace.SyntaxTree, text, nextPosition); } } } private static VirtualTreePoint GetBodyEndPoint(SourceText text, SyntaxToken closeBrace) { var closeBraceLine = text.Lines.GetLineFromPosition(closeBrace.SpanStart); var textBeforeBrace = text.ToString(TextSpan.FromBounds(closeBraceLine.Start, closeBrace.SpanStart)); return string.IsNullOrWhiteSpace(textBeforeBrace) ? new VirtualTreePoint(closeBrace.SyntaxTree, text, closeBraceLine.Start) : new VirtualTreePoint(closeBrace.SyntaxTree, text, closeBrace.SpanStart); } private static VirtualTreePoint GetStartPoint(SourceText text, ArrowExpressionClauseSyntax node, EnvDTE.vsCMPart part) { int startPosition; switch (part) { case EnvDTE.vsCMPart.vsCMPartWhole: startPosition = node.SpanStart; break; case EnvDTE.vsCMPart.vsCMPartBody: startPosition = node.Expression.SpanStart; break; default: throw Exceptions.ThrowENotImpl(); } return new VirtualTreePoint(node.SyntaxTree, text, startPosition); } private static VirtualTreePoint GetStartPoint(SourceText text, AttributeSyntax node, EnvDTE.vsCMPart part) { int startPosition; switch (part) { case EnvDTE.vsCMPart.vsCMPartName: case EnvDTE.vsCMPart.vsCMPartAttributes: case EnvDTE.vsCMPart.vsCMPartHeader: case EnvDTE.vsCMPart.vsCMPartWhole: case EnvDTE.vsCMPart.vsCMPartBodyWithDelimiter: case EnvDTE.vsCMPart.vsCMPartHeaderWithAttributes: throw Exceptions.ThrowENotImpl(); case EnvDTE.vsCMPart.vsCMPartAttributesWithDelimiter: case EnvDTE.vsCMPart.vsCMPartBody: throw Exceptions.ThrowEFail(); case EnvDTE.vsCMPart.vsCMPartWholeWithAttributes: startPosition = node.GetFirstToken().SpanStart; break; case EnvDTE.vsCMPart.vsCMPartNavigate: startPosition = node.Name.SpanStart; break; default: throw Exceptions.ThrowEInvalidArg(); } return new VirtualTreePoint(node.SyntaxTree, text, startPosition); } private static VirtualTreePoint GetStartPoint(SourceText text, AttributeArgumentSyntax node, EnvDTE.vsCMPart part) { int startPosition; switch (part) { case EnvDTE.vsCMPart.vsCMPartName: case EnvDTE.vsCMPart.vsCMPartAttributes: case EnvDTE.vsCMPart.vsCMPartHeader: case EnvDTE.vsCMPart.vsCMPartWhole: case EnvDTE.vsCMPart.vsCMPartBodyWithDelimiter: case EnvDTE.vsCMPart.vsCMPartHeaderWithAttributes: throw Exceptions.ThrowENotImpl(); case EnvDTE.vsCMPart.vsCMPartAttributesWithDelimiter: case EnvDTE.vsCMPart.vsCMPartBody: case EnvDTE.vsCMPart.vsCMPartNavigate: throw Exceptions.ThrowEFail(); case EnvDTE.vsCMPart.vsCMPartWholeWithAttributes: startPosition = node.SpanStart; break; default: throw Exceptions.ThrowEInvalidArg(); } return new VirtualTreePoint(node.SyntaxTree, text, startPosition); } private static VirtualTreePoint GetStartPoint(SourceText text, BaseTypeDeclarationSyntax node, EnvDTE.vsCMPart part) { int startPosition; switch (part) { case EnvDTE.vsCMPart.vsCMPartName: case EnvDTE.vsCMPart.vsCMPartAttributes: case EnvDTE.vsCMPart.vsCMPartWhole: case EnvDTE.vsCMPart.vsCMPartBodyWithDelimiter: case EnvDTE.vsCMPart.vsCMPartHeaderWithAttributes: throw Exceptions.ThrowENotImpl(); case EnvDTE.vsCMPart.vsCMPartHeader: startPosition = node.GetFirstTokenAfterAttributes().SpanStart; break; case EnvDTE.vsCMPart.vsCMPartAttributesWithDelimiter: if (node.AttributeLists.Count == 0) { throw Exceptions.ThrowEFail(); } goto case EnvDTE.vsCMPart.vsCMPartWholeWithAttributes; case EnvDTE.vsCMPart.vsCMPartWholeWithAttributes: startPosition = node.GetFirstToken().SpanStart; break; case EnvDTE.vsCMPart.vsCMPartNavigate: startPosition = node.Identifier.SpanStart; break; case EnvDTE.vsCMPart.vsCMPartBody: if (node.OpenBraceToken.IsMissing || node.CloseBraceToken.IsMissing) { throw Exceptions.ThrowEFail(); } return GetBodyStartPoint(text, node.OpenBraceToken); default: throw Exceptions.ThrowEInvalidArg(); } return new VirtualTreePoint(node.SyntaxTree, text, startPosition); } private static VirtualTreePoint GetStartPoint(SourceText text, LineFormattingOptions options, BaseMethodDeclarationSyntax node, EnvDTE.vsCMPart part) { int startPosition; switch (part) { case EnvDTE.vsCMPart.vsCMPartName: case EnvDTE.vsCMPart.vsCMPartAttributes: case EnvDTE.vsCMPart.vsCMPartWhole: case EnvDTE.vsCMPart.vsCMPartBodyWithDelimiter: case EnvDTE.vsCMPart.vsCMPartHeaderWithAttributes: throw Exceptions.ThrowENotImpl(); case EnvDTE.vsCMPart.vsCMPartHeader: startPosition = node.GetFirstTokenAfterAttributes().SpanStart; break; case EnvDTE.vsCMPart.vsCMPartAttributesWithDelimiter: if (node.AttributeLists.Count == 0) { throw Exceptions.ThrowEFail(); } goto case EnvDTE.vsCMPart.vsCMPartWholeWithAttributes; case EnvDTE.vsCMPart.vsCMPartWholeWithAttributes: startPosition = node.GetFirstToken().SpanStart; break; case EnvDTE.vsCMPart.vsCMPartNavigate: if (node.Body != null && !node.Body.OpenBraceToken.IsMissing) { var line = text.Lines.GetLineFromPosition(node.SpanStart); var indentation = line.GetColumnOfFirstNonWhitespaceCharacterOrEndOfLine(options.TabSize); return GetBodyStartPoint(text, options, node.Body.OpenBraceToken, node.Body.CloseBraceToken, indentation); } else { switch (node.Kind()) { case SyntaxKind.MethodDeclaration: startPosition = ((MethodDeclarationSyntax)node).Identifier.SpanStart; break; case SyntaxKind.ConstructorDeclaration: startPosition = ((ConstructorDeclarationSyntax)node).Identifier.SpanStart; break; case SyntaxKind.DestructorDeclaration: startPosition = ((DestructorDeclarationSyntax)node).Identifier.SpanStart; break; case SyntaxKind.ConversionOperatorDeclaration: startPosition = ((ConversionOperatorDeclarationSyntax)node).ImplicitOrExplicitKeyword.SpanStart; break; case SyntaxKind.OperatorDeclaration: startPosition = ((OperatorDeclarationSyntax)node).OperatorToken.SpanStart; break; default: startPosition = node.GetFirstTokenAfterAttributes().SpanStart; break; } } break; case EnvDTE.vsCMPart.vsCMPartBody: if (node.Body == null || node.Body.OpenBraceToken.IsMissing || node.Body.CloseBraceToken.IsMissing) { throw Exceptions.ThrowEFail(); } return GetBodyStartPoint(text, node.Body.OpenBraceToken); default: throw Exceptions.ThrowEInvalidArg(); } return new VirtualTreePoint(node.SyntaxTree, text, startPosition); } private static AccessorDeclarationSyntax FindFirstAccessorNode(BasePropertyDeclarationSyntax node) { if (node.AccessorList == null) { return null; } return node.AccessorList.Accessors.FirstOrDefault(); } private static VirtualTreePoint GetStartPoint(SourceText text, LineFormattingOptions options, BasePropertyDeclarationSyntax node, EnvDTE.vsCMPart part) { int startPosition; switch (part) { case EnvDTE.vsCMPart.vsCMPartName: case EnvDTE.vsCMPart.vsCMPartAttributes: case EnvDTE.vsCMPart.vsCMPartHeader: case EnvDTE.vsCMPart.vsCMPartWhole: case EnvDTE.vsCMPart.vsCMPartBodyWithDelimiter: case EnvDTE.vsCMPart.vsCMPartHeaderWithAttributes: throw Exceptions.ThrowENotImpl(); case EnvDTE.vsCMPart.vsCMPartAttributesWithDelimiter: if (node.AttributeLists.Count == 0) { throw Exceptions.ThrowEFail(); } goto case EnvDTE.vsCMPart.vsCMPartWholeWithAttributes; case EnvDTE.vsCMPart.vsCMPartWholeWithAttributes: startPosition = node.SpanStart; break; case EnvDTE.vsCMPart.vsCMPartNavigate: var firstAccessorNode = FindFirstAccessorNode(node); if (firstAccessorNode != null) { var line = text.Lines.GetLineFromPosition(firstAccessorNode.SpanStart); var indentation = line.GetColumnOfFirstNonWhitespaceCharacterOrEndOfLine(options.TabSize); if (firstAccessorNode.Body != null) { return GetBodyStartPoint(text, options, firstAccessorNode.Body.OpenBraceToken, firstAccessorNode.Body.CloseBraceToken, indentation); } else if (!firstAccessorNode.SemicolonToken.IsMissing) { // This is total weirdness from the old C# code model with auto props. // If there isn't a body, the semi-colon is used return GetBodyStartPoint(text, options, firstAccessorNode.SemicolonToken, firstAccessorNode.SemicolonToken, indentation); } } throw Exceptions.ThrowEFail(); case EnvDTE.vsCMPart.vsCMPartBody: if (node.AccessorList != null && !node.AccessorList.OpenBraceToken.IsMissing) { var line = text.Lines.GetLineFromPosition(node.SpanStart); var indentation = line.GetColumnOfFirstNonWhitespaceCharacterOrEndOfLine(options.TabSize); return GetBodyStartPoint(text, options, node.AccessorList.OpenBraceToken, node.AccessorList.CloseBraceToken, indentation); } throw Exceptions.ThrowEFail(); default: throw Exceptions.ThrowEInvalidArg(); } return new VirtualTreePoint(node.SyntaxTree, text, startPosition); } private static VirtualTreePoint GetStartPoint(SourceText text, LineFormattingOptions options, AccessorDeclarationSyntax node, EnvDTE.vsCMPart part) { int startPosition; switch (part) { case EnvDTE.vsCMPart.vsCMPartName: case EnvDTE.vsCMPart.vsCMPartAttributes: case EnvDTE.vsCMPart.vsCMPartHeader: case EnvDTE.vsCMPart.vsCMPartWhole: case EnvDTE.vsCMPart.vsCMPartBodyWithDelimiter: case EnvDTE.vsCMPart.vsCMPartHeaderWithAttributes: throw Exceptions.ThrowENotImpl(); case EnvDTE.vsCMPart.vsCMPartAttributesWithDelimiter: throw Exceptions.ThrowEFail(); case EnvDTE.vsCMPart.vsCMPartWholeWithAttributes: startPosition = node.SpanStart; break; case EnvDTE.vsCMPart.vsCMPartNavigate: if (node.Body != null && !node.Body.OpenBraceToken.IsMissing) { var line = text.Lines.GetLineFromPosition(node.SpanStart); var indentation = line.GetColumnOfFirstNonWhitespaceCharacterOrEndOfLine(options.TabSize); return GetBodyStartPoint(text, options, node.Body.OpenBraceToken, node.Body.CloseBraceToken, indentation); } throw Exceptions.ThrowEFail(); case EnvDTE.vsCMPart.vsCMPartBody: if (node.Body == null || node.Body.OpenBraceToken.IsMissing || node.Body.CloseBraceToken.IsMissing) { throw Exceptions.ThrowEFail(); } return GetBodyStartPoint(text, node.Body.OpenBraceToken); default: throw Exceptions.ThrowEInvalidArg(); } return new VirtualTreePoint(node.SyntaxTree, text, startPosition); } private static VirtualTreePoint GetStartPoint(SourceText text, BaseNamespaceDeclarationSyntax node, EnvDTE.vsCMPart part) { int startPosition; switch (part) { case EnvDTE.vsCMPart.vsCMPartName: case EnvDTE.vsCMPart.vsCMPartAttributes: case EnvDTE.vsCMPart.vsCMPartHeader: case EnvDTE.vsCMPart.vsCMPartWhole: case EnvDTE.vsCMPart.vsCMPartBodyWithDelimiter: case EnvDTE.vsCMPart.vsCMPartHeaderWithAttributes: throw Exceptions.ThrowENotImpl(); case EnvDTE.vsCMPart.vsCMPartAttributesWithDelimiter: throw Exceptions.ThrowEFail(); case EnvDTE.vsCMPart.vsCMPartWholeWithAttributes: startPosition = node.GetFirstToken().SpanStart; break; case EnvDTE.vsCMPart.vsCMPartNavigate: startPosition = node.Name.SpanStart; break; case EnvDTE.vsCMPart.vsCMPartBody: if (node is NamespaceDeclarationSyntax namespaceDeclaration) { if (namespaceDeclaration.OpenBraceToken.IsMissing || namespaceDeclaration.CloseBraceToken.IsMissing) throw Exceptions.ThrowEFail(); return GetBodyStartPoint(text, namespaceDeclaration.OpenBraceToken); } else if (node is FileScopedNamespaceDeclarationSyntax fileScopedNamespace) { return GetBodyStartPoint(text, fileScopedNamespace.SemicolonToken); } else { throw Exceptions.ThrowEFail(); } default: throw Exceptions.ThrowEInvalidArg(); } return new VirtualTreePoint(node.SyntaxTree, text, startPosition); } private static VirtualTreePoint GetStartPoint(SourceText text, DelegateDeclarationSyntax node, EnvDTE.vsCMPart part) { int startPosition; switch (part) { case EnvDTE.vsCMPart.vsCMPartName: case EnvDTE.vsCMPart.vsCMPartAttributes: case EnvDTE.vsCMPart.vsCMPartHeader: case EnvDTE.vsCMPart.vsCMPartWhole: case EnvDTE.vsCMPart.vsCMPartBodyWithDelimiter: case EnvDTE.vsCMPart.vsCMPartHeaderWithAttributes: throw Exceptions.ThrowENotImpl(); case EnvDTE.vsCMPart.vsCMPartAttributesWithDelimiter: if (node.AttributeLists.Count == 0) { throw Exceptions.ThrowEFail(); } goto case EnvDTE.vsCMPart.vsCMPartWholeWithAttributes; case EnvDTE.vsCMPart.vsCMPartWholeWithAttributes: startPosition = node.GetFirstToken().SpanStart; break; case EnvDTE.vsCMPart.vsCMPartNavigate: startPosition = node.Identifier.SpanStart; break; case EnvDTE.vsCMPart.vsCMPartBody: throw Exceptions.ThrowEFail(); default: throw Exceptions.ThrowEInvalidArg(); } return new VirtualTreePoint(node.SyntaxTree, text, startPosition); } private static VirtualTreePoint GetStartPoint(SourceText text, UsingDirectiveSyntax node, EnvDTE.vsCMPart part) { int startPosition; switch (part) { case EnvDTE.vsCMPart.vsCMPartName: case EnvDTE.vsCMPart.vsCMPartAttributes: case EnvDTE.vsCMPart.vsCMPartHeader: case EnvDTE.vsCMPart.vsCMPartWhole: case EnvDTE.vsCMPart.vsCMPartBodyWithDelimiter: case EnvDTE.vsCMPart.vsCMPartHeaderWithAttributes: throw Exceptions.ThrowENotImpl(); case EnvDTE.vsCMPart.vsCMPartAttributesWithDelimiter: case EnvDTE.vsCMPart.vsCMPartBody: throw Exceptions.ThrowEFail(); case EnvDTE.vsCMPart.vsCMPartWholeWithAttributes: startPosition = node.SpanStart; break; case EnvDTE.vsCMPart.vsCMPartNavigate: startPosition = node.Name.SpanStart; break; default: throw Exceptions.ThrowEInvalidArg(); } return new VirtualTreePoint(node.SyntaxTree, text, startPosition); } private static VirtualTreePoint GetStartPoint(SourceText text, VariableDeclaratorSyntax node, EnvDTE.vsCMPart part) { var field = node.FirstAncestorOrSelf<BaseFieldDeclarationSyntax>(); int startPosition; switch (part) { case EnvDTE.vsCMPart.vsCMPartName: case EnvDTE.vsCMPart.vsCMPartAttributes: case EnvDTE.vsCMPart.vsCMPartHeader: case EnvDTE.vsCMPart.vsCMPartWhole: case EnvDTE.vsCMPart.vsCMPartBodyWithDelimiter: case EnvDTE.vsCMPart.vsCMPartHeaderWithAttributes: throw Exceptions.ThrowENotImpl(); case EnvDTE.vsCMPart.vsCMPartAttributesWithDelimiter: if (field.AttributeLists.Count == 0) { throw Exceptions.ThrowEFail(); } goto case EnvDTE.vsCMPart.vsCMPartWholeWithAttributes; case EnvDTE.vsCMPart.vsCMPartWholeWithAttributes: startPosition = field.SpanStart; break; case EnvDTE.vsCMPart.vsCMPartBody: throw Exceptions.ThrowEFail(); case EnvDTE.vsCMPart.vsCMPartNavigate: startPosition = node.Identifier.SpanStart; break; default: throw Exceptions.ThrowEInvalidArg(); } return new VirtualTreePoint(node.SyntaxTree, text, startPosition); } private static VirtualTreePoint GetStartPoint(SourceText text, EnumMemberDeclarationSyntax node, EnvDTE.vsCMPart part) { int startPosition; switch (part) { case EnvDTE.vsCMPart.vsCMPartName: case EnvDTE.vsCMPart.vsCMPartAttributes: case EnvDTE.vsCMPart.vsCMPartHeader: case EnvDTE.vsCMPart.vsCMPartWhole: case EnvDTE.vsCMPart.vsCMPartBodyWithDelimiter: case EnvDTE.vsCMPart.vsCMPartHeaderWithAttributes: throw Exceptions.ThrowENotImpl(); case EnvDTE.vsCMPart.vsCMPartAttributesWithDelimiter: if (node.AttributeLists.Count == 0) { throw Exceptions.ThrowEFail(); } goto case EnvDTE.vsCMPart.vsCMPartWholeWithAttributes; case EnvDTE.vsCMPart.vsCMPartWholeWithAttributes: startPosition = node.SpanStart; break; case EnvDTE.vsCMPart.vsCMPartBody: throw Exceptions.ThrowEFail(); case EnvDTE.vsCMPart.vsCMPartNavigate: startPosition = node.Identifier.SpanStart; break; default: throw Exceptions.ThrowEInvalidArg(); } return new VirtualTreePoint(node.SyntaxTree, text, startPosition); } private static VirtualTreePoint GetStartPoint(SourceText text, ParameterSyntax node, EnvDTE.vsCMPart part) { int startPosition; switch (part) { case EnvDTE.vsCMPart.vsCMPartName: case EnvDTE.vsCMPart.vsCMPartAttributes: case EnvDTE.vsCMPart.vsCMPartHeader: case EnvDTE.vsCMPart.vsCMPartWhole: case EnvDTE.vsCMPart.vsCMPartBodyWithDelimiter: case EnvDTE.vsCMPart.vsCMPartHeaderWithAttributes: throw Exceptions.ThrowENotImpl(); case EnvDTE.vsCMPart.vsCMPartAttributesWithDelimiter: if (node.AttributeLists.Count == 0) { throw Exceptions.ThrowEFail(); } goto case EnvDTE.vsCMPart.vsCMPartWholeWithAttributes; case EnvDTE.vsCMPart.vsCMPartWholeWithAttributes: startPosition = node.SpanStart; break; case EnvDTE.vsCMPart.vsCMPartBody: throw Exceptions.ThrowEFail(); case EnvDTE.vsCMPart.vsCMPartNavigate: startPosition = node.Identifier.SpanStart; break; default: throw Exceptions.ThrowEInvalidArg(); } return new VirtualTreePoint(node.SyntaxTree, text, startPosition); } private static VirtualTreePoint GetEndPoint(SourceText text, ArrowExpressionClauseSyntax node, EnvDTE.vsCMPart part) { int endPosition; switch (part) { case EnvDTE.vsCMPart.vsCMPartWhole: case EnvDTE.vsCMPart.vsCMPartBody: endPosition = node.Span.End; break; default: throw Exceptions.ThrowENotImpl(); } return new VirtualTreePoint(node.SyntaxTree, text, endPosition); } private static VirtualTreePoint GetEndPoint(SourceText text, AttributeSyntax node, EnvDTE.vsCMPart part) { int endPosition; switch (part) { case EnvDTE.vsCMPart.vsCMPartName: case EnvDTE.vsCMPart.vsCMPartAttributes: case EnvDTE.vsCMPart.vsCMPartHeader: case EnvDTE.vsCMPart.vsCMPartWhole: case EnvDTE.vsCMPart.vsCMPartBodyWithDelimiter: case EnvDTE.vsCMPart.vsCMPartHeaderWithAttributes: throw Exceptions.ThrowENotImpl(); case EnvDTE.vsCMPart.vsCMPartAttributesWithDelimiter: case EnvDTE.vsCMPart.vsCMPartBody: throw Exceptions.ThrowEFail(); case EnvDTE.vsCMPart.vsCMPartWholeWithAttributes: endPosition = node.Span.End; break; case EnvDTE.vsCMPart.vsCMPartNavigate: endPosition = node.Name.Span.End; break; default: throw Exceptions.ThrowEInvalidArg(); } return new VirtualTreePoint(node.SyntaxTree, text, endPosition); } private static VirtualTreePoint GetEndPoint(SourceText text, AttributeArgumentSyntax node, EnvDTE.vsCMPart part) { int endPosition; switch (part) { case EnvDTE.vsCMPart.vsCMPartName: case EnvDTE.vsCMPart.vsCMPartAttributes: case EnvDTE.vsCMPart.vsCMPartHeader: case EnvDTE.vsCMPart.vsCMPartWhole: case EnvDTE.vsCMPart.vsCMPartBodyWithDelimiter: case EnvDTE.vsCMPart.vsCMPartHeaderWithAttributes: throw Exceptions.ThrowENotImpl(); case EnvDTE.vsCMPart.vsCMPartAttributesWithDelimiter: case EnvDTE.vsCMPart.vsCMPartBody: case EnvDTE.vsCMPart.vsCMPartNavigate: throw Exceptions.ThrowEFail(); case EnvDTE.vsCMPart.vsCMPartWholeWithAttributes: endPosition = node.Span.End; break; default: throw Exceptions.ThrowEInvalidArg(); } return new VirtualTreePoint(node.SyntaxTree, text, endPosition); } private static VirtualTreePoint GetEndPoint(SourceText text, BaseTypeDeclarationSyntax node, EnvDTE.vsCMPart part) { int endPosition; switch (part) { case EnvDTE.vsCMPart.vsCMPartName: case EnvDTE.vsCMPart.vsCMPartAttributes: case EnvDTE.vsCMPart.vsCMPartHeader: case EnvDTE.vsCMPart.vsCMPartWhole: case EnvDTE.vsCMPart.vsCMPartBodyWithDelimiter: case EnvDTE.vsCMPart.vsCMPartHeaderWithAttributes: throw Exceptions.ThrowENotImpl(); case EnvDTE.vsCMPart.vsCMPartAttributesWithDelimiter: if (node.AttributeLists.Count == 0) { throw Exceptions.ThrowEFail(); } endPosition = node.AttributeLists.Last().GetLastToken().Span.End; break; case EnvDTE.vsCMPart.vsCMPartWholeWithAttributes: endPosition = node.Span.End; break; case EnvDTE.vsCMPart.vsCMPartNavigate: endPosition = node.Identifier.Span.End; break; case EnvDTE.vsCMPart.vsCMPartBody: return GetBodyEndPoint(text, node.CloseBraceToken); default: throw Exceptions.ThrowEInvalidArg(); } return new VirtualTreePoint(node.SyntaxTree, text, endPosition); } private static VirtualTreePoint GetEndPoint(SourceText text, BaseMethodDeclarationSyntax node, EnvDTE.vsCMPart part) { int endPosition; switch (part) { case EnvDTE.vsCMPart.vsCMPartName: case EnvDTE.vsCMPart.vsCMPartAttributes: case EnvDTE.vsCMPart.vsCMPartHeader: case EnvDTE.vsCMPart.vsCMPartWhole: case EnvDTE.vsCMPart.vsCMPartBodyWithDelimiter: case EnvDTE.vsCMPart.vsCMPartHeaderWithAttributes: throw Exceptions.ThrowENotImpl(); case EnvDTE.vsCMPart.vsCMPartAttributesWithDelimiter: if (node.AttributeLists.Count == 0) { throw Exceptions.ThrowEFail(); } endPosition = node.AttributeLists.Last().GetLastToken().Span.End; break; case EnvDTE.vsCMPart.vsCMPartWholeWithAttributes: endPosition = node.Span.End; break; case EnvDTE.vsCMPart.vsCMPartNavigate: if (node.Body != null && !node.Body.CloseBraceToken.IsMissing) { return GetBodyEndPoint(text, node.Body.CloseBraceToken); } else { switch (node.Kind()) { case SyntaxKind.MethodDeclaration: endPosition = ((MethodDeclarationSyntax)node).Identifier.Span.End; break; case SyntaxKind.ConstructorDeclaration: endPosition = ((ConstructorDeclarationSyntax)node).Identifier.Span.End; break; case SyntaxKind.DestructorDeclaration: endPosition = ((DestructorDeclarationSyntax)node).Identifier.Span.End; break; case SyntaxKind.ConversionOperatorDeclaration: endPosition = ((ConversionOperatorDeclarationSyntax)node).ImplicitOrExplicitKeyword.Span.End; break; case SyntaxKind.OperatorDeclaration: endPosition = ((OperatorDeclarationSyntax)node).OperatorToken.Span.End; break; default: endPosition = node.GetFirstTokenAfterAttributes().Span.End; break; } } break; case EnvDTE.vsCMPart.vsCMPartBody: if (node.Body == null || node.Body.OpenBraceToken.IsMissing || node.Body.CloseBraceToken.IsMissing) { throw Exceptions.ThrowEFail(); } return GetBodyEndPoint(text, node.Body.CloseBraceToken); default: throw Exceptions.ThrowEInvalidArg(); } return new VirtualTreePoint(node.SyntaxTree, text, endPosition); } private static VirtualTreePoint GetEndPoint(SourceText text, BasePropertyDeclarationSyntax node, EnvDTE.vsCMPart part) { int endPosition; switch (part) { case EnvDTE.vsCMPart.vsCMPartName: case EnvDTE.vsCMPart.vsCMPartAttributes: case EnvDTE.vsCMPart.vsCMPartHeader: case EnvDTE.vsCMPart.vsCMPartWhole: case EnvDTE.vsCMPart.vsCMPartBodyWithDelimiter: case EnvDTE.vsCMPart.vsCMPartHeaderWithAttributes: throw Exceptions.ThrowENotImpl(); case EnvDTE.vsCMPart.vsCMPartAttributesWithDelimiter: if (node.AttributeLists.Count == 0) { throw Exceptions.ThrowEFail(); } endPosition = node.AttributeLists.Last().Span.End; break; case EnvDTE.vsCMPart.vsCMPartWholeWithAttributes: endPosition = node.Span.End; break; case EnvDTE.vsCMPart.vsCMPartNavigate: var firstAccessorNode = FindFirstAccessorNode(node); if (firstAccessorNode != null) { if (firstAccessorNode.Body != null) { return GetBodyEndPoint(text, firstAccessorNode.Body.CloseBraceToken); } else { // This is total weirdness from the old C# code model with auto props. // If there isn't a body, the semi-colon is used return GetBodyEndPoint(text, firstAccessorNode.SemicolonToken); } } throw Exceptions.ThrowEFail(); case EnvDTE.vsCMPart.vsCMPartBody: if (node.AccessorList != null && !node.AccessorList.CloseBraceToken.IsMissing) { return GetBodyEndPoint(text, node.AccessorList.CloseBraceToken); } throw Exceptions.ThrowEFail(); default: throw Exceptions.ThrowEInvalidArg(); } return new VirtualTreePoint(node.SyntaxTree, text, endPosition); } private static VirtualTreePoint GetEndPoint(SourceText text, AccessorDeclarationSyntax node, EnvDTE.vsCMPart part) { int endPosition; switch (part) { case EnvDTE.vsCMPart.vsCMPartName: case EnvDTE.vsCMPart.vsCMPartAttributes: case EnvDTE.vsCMPart.vsCMPartHeader: case EnvDTE.vsCMPart.vsCMPartWhole: case EnvDTE.vsCMPart.vsCMPartBodyWithDelimiter: case EnvDTE.vsCMPart.vsCMPartHeaderWithAttributes: throw Exceptions.ThrowENotImpl(); case EnvDTE.vsCMPart.vsCMPartAttributesWithDelimiter: throw Exceptions.ThrowEFail(); case EnvDTE.vsCMPart.vsCMPartWholeWithAttributes: endPosition = node.Span.End; break; case EnvDTE.vsCMPart.vsCMPartBody: case EnvDTE.vsCMPart.vsCMPartNavigate: if (node.Body == null || node.Body.OpenBraceToken.IsMissing || node.Body.CloseBraceToken.IsMissing) { throw Exceptions.ThrowEFail(); } return GetBodyEndPoint(text, node.Body.CloseBraceToken); default: throw Exceptions.ThrowEInvalidArg(); } return new VirtualTreePoint(node.SyntaxTree, text, endPosition); } private static VirtualTreePoint GetEndPoint(SourceText text, DelegateDeclarationSyntax node, EnvDTE.vsCMPart part) { int endPosition; switch (part) { case EnvDTE.vsCMPart.vsCMPartName: case EnvDTE.vsCMPart.vsCMPartAttributes: case EnvDTE.vsCMPart.vsCMPartHeader: case EnvDTE.vsCMPart.vsCMPartWhole: case EnvDTE.vsCMPart.vsCMPartBodyWithDelimiter: case EnvDTE.vsCMPart.vsCMPartHeaderWithAttributes: throw Exceptions.ThrowENotImpl(); case EnvDTE.vsCMPart.vsCMPartAttributesWithDelimiter: if (node.AttributeLists.Count == 0) { throw Exceptions.ThrowEFail(); } endPosition = node.AttributeLists.Last().Span.End; break; case EnvDTE.vsCMPart.vsCMPartWholeWithAttributes: endPosition = node.Span.End; break; case EnvDTE.vsCMPart.vsCMPartNavigate: endPosition = node.Identifier.Span.End; break; case EnvDTE.vsCMPart.vsCMPartBody: throw Exceptions.ThrowEFail(); default: throw Exceptions.ThrowEInvalidArg(); } return new VirtualTreePoint(node.SyntaxTree, text, endPosition); } private static VirtualTreePoint GetEndPoint(SourceText text, BaseNamespaceDeclarationSyntax node, EnvDTE.vsCMPart part) { int endPosition; switch (part) { case EnvDTE.vsCMPart.vsCMPartName: case EnvDTE.vsCMPart.vsCMPartAttributes: case EnvDTE.vsCMPart.vsCMPartHeader: case EnvDTE.vsCMPart.vsCMPartWhole: case EnvDTE.vsCMPart.vsCMPartBodyWithDelimiter: case EnvDTE.vsCMPart.vsCMPartHeaderWithAttributes: throw Exceptions.ThrowENotImpl(); case EnvDTE.vsCMPart.vsCMPartAttributesWithDelimiter: throw Exceptions.ThrowEFail(); case EnvDTE.vsCMPart.vsCMPartWholeWithAttributes: endPosition = node.Span.End; break; case EnvDTE.vsCMPart.vsCMPartNavigate: endPosition = node.Name.Span.End; break; case EnvDTE.vsCMPart.vsCMPartBody: if (node is NamespaceDeclarationSyntax namespaceDeclaration) { if (namespaceDeclaration.OpenBraceToken.IsMissing || namespaceDeclaration.CloseBraceToken.IsMissing) throw Exceptions.ThrowEFail(); return GetBodyEndPoint(text, namespaceDeclaration.CloseBraceToken); } else if (node is FileScopedNamespaceDeclarationSyntax fileScopedNamespace) { return new VirtualTreePoint(fileScopedNamespace.SyntaxTree, text, fileScopedNamespace.Parent.Span.End); } else { throw Exceptions.ThrowEFail(); } default: throw Exceptions.ThrowEInvalidArg(); } return new VirtualTreePoint(node.SyntaxTree, text, endPosition); } private static VirtualTreePoint GetEndPoint(SourceText text, UsingDirectiveSyntax node, EnvDTE.vsCMPart part) { int endPosition; switch (part) { case EnvDTE.vsCMPart.vsCMPartName: case EnvDTE.vsCMPart.vsCMPartAttributes: case EnvDTE.vsCMPart.vsCMPartHeader: case EnvDTE.vsCMPart.vsCMPartWhole: case EnvDTE.vsCMPart.vsCMPartBodyWithDelimiter: case EnvDTE.vsCMPart.vsCMPartHeaderWithAttributes: throw Exceptions.ThrowENotImpl(); case EnvDTE.vsCMPart.vsCMPartAttributesWithDelimiter: case EnvDTE.vsCMPart.vsCMPartBody: throw Exceptions.ThrowEFail(); case EnvDTE.vsCMPart.vsCMPartWholeWithAttributes: endPosition = node.Span.End; break; case EnvDTE.vsCMPart.vsCMPartNavigate: endPosition = node.Name.Span.End; break; default: throw Exceptions.ThrowEInvalidArg(); } return new VirtualTreePoint(node.SyntaxTree, text, endPosition); } private static VirtualTreePoint GetEndPoint(SourceText text, EnumMemberDeclarationSyntax node, EnvDTE.vsCMPart part) { int endPosition; switch (part) { case EnvDTE.vsCMPart.vsCMPartName: case EnvDTE.vsCMPart.vsCMPartAttributes: case EnvDTE.vsCMPart.vsCMPartHeader: case EnvDTE.vsCMPart.vsCMPartWhole: case EnvDTE.vsCMPart.vsCMPartBodyWithDelimiter: case EnvDTE.vsCMPart.vsCMPartHeaderWithAttributes: throw Exceptions.ThrowENotImpl(); case EnvDTE.vsCMPart.vsCMPartAttributesWithDelimiter: if (node.AttributeLists.Count == 0) { throw Exceptions.ThrowEFail(); } endPosition = node.AttributeLists.Last().GetLastToken().Span.End; break; case EnvDTE.vsCMPart.vsCMPartWholeWithAttributes: endPosition = node.Span.End; break; case EnvDTE.vsCMPart.vsCMPartBody: throw Exceptions.ThrowEFail(); case EnvDTE.vsCMPart.vsCMPartNavigate: endPosition = node.Identifier.Span.End; break; default: throw Exceptions.ThrowEInvalidArg(); } return new VirtualTreePoint(node.SyntaxTree, text, endPosition); } private static VirtualTreePoint GetEndPoint(SourceText text, VariableDeclaratorSyntax node, EnvDTE.vsCMPart part) { var field = node.FirstAncestorOrSelf<BaseFieldDeclarationSyntax>(); int endPosition; switch (part) { case EnvDTE.vsCMPart.vsCMPartName: case EnvDTE.vsCMPart.vsCMPartAttributes: case EnvDTE.vsCMPart.vsCMPartHeader: case EnvDTE.vsCMPart.vsCMPartWhole: case EnvDTE.vsCMPart.vsCMPartBodyWithDelimiter: case EnvDTE.vsCMPart.vsCMPartHeaderWithAttributes: throw Exceptions.ThrowENotImpl(); case EnvDTE.vsCMPart.vsCMPartAttributesWithDelimiter: if (field.AttributeLists.Count == 0) { throw Exceptions.ThrowEFail(); } endPosition = field.AttributeLists.Last().GetLastToken().Span.End; break; case EnvDTE.vsCMPart.vsCMPartWholeWithAttributes: endPosition = field.Span.End; break; case EnvDTE.vsCMPart.vsCMPartBody: throw Exceptions.ThrowEFail(); case EnvDTE.vsCMPart.vsCMPartNavigate: endPosition = node.Identifier.Span.End; break; default: throw Exceptions.ThrowEInvalidArg(); } return new VirtualTreePoint(node.SyntaxTree, text, endPosition); } private static VirtualTreePoint GetEndPoint(SourceText text, ParameterSyntax node, EnvDTE.vsCMPart part) { int endPosition; switch (part) { case EnvDTE.vsCMPart.vsCMPartName: case EnvDTE.vsCMPart.vsCMPartAttributes: case EnvDTE.vsCMPart.vsCMPartHeader: case EnvDTE.vsCMPart.vsCMPartWhole: case EnvDTE.vsCMPart.vsCMPartBodyWithDelimiter: case EnvDTE.vsCMPart.vsCMPartHeaderWithAttributes: throw Exceptions.ThrowENotImpl(); case EnvDTE.vsCMPart.vsCMPartAttributesWithDelimiter: if (node.AttributeLists.Count == 0) { throw Exceptions.ThrowEFail(); } endPosition = node.AttributeLists.Last().GetLastToken().Span.End; break; case EnvDTE.vsCMPart.vsCMPartWholeWithAttributes: endPosition = node.Span.End; break; case EnvDTE.vsCMPart.vsCMPartBody: throw Exceptions.ThrowEFail(); case EnvDTE.vsCMPart.vsCMPartNavigate: endPosition = node.Identifier.Span.End; break; default: throw Exceptions.ThrowEInvalidArg(); } return new VirtualTreePoint(node.SyntaxTree, text, endPosition); } } }