|
// 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 partial class CSharpCodeModelService
{
protected override AbstractNodeLocator CreateNodeLocator()
=> new NodeLocator();
private 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);
}
}
}
}
|