Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
d6aed247
R
roslyn
项目概览
lwm1986
/
roslyn
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
roslyn
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
d6aed247
编写于
6月 16, 2017
作者:
C
CyrusNajmabadi
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Break out code for index building into its own service.
上级
55c8d481
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
1952 addition
and
1936 deletion
+1952
-1936
src/Workspaces/CSharp/Portable/LanguageServices/CSharpSyntaxFactsService.cs
...arp/Portable/LanguageServices/CSharpSyntaxFactsService.cs
+927
-925
src/Workspaces/Core/Portable/FindSymbols/SyntaxTree/SyntaxTreeIndex_Create.cs
...Portable/FindSymbols/SyntaxTree/SyntaxTreeIndex_Create.cs
+9
-1
src/Workspaces/Core/Portable/LanguageServices/SyntaxFactsService/AbstractSyntaxFactsService.cs
...Services/SyntaxFactsService/AbstractSyntaxFactsService.cs
+51
-45
src/Workspaces/Core/Portable/LanguageServices/SyntaxFactsService/ISyntaxFactsService.cs
...anguageServices/SyntaxFactsService/ISyntaxFactsService.cs
+0
-3
src/Workspaces/VisualBasic/Portable/LanguageServices/VisualBasicSyntaxFactsService.vb
...ortable/LanguageServices/VisualBasicSyntaxFactsService.vb
+965
-962
未找到文件。
src/Workspaces/CSharp/Portable/LanguageServices/CSharpSyntaxFactsService.cs
浏览文件 @
d6aed247
...
...
@@ -3,6 +3,7 @@
using
System
;
using
System.Collections.Generic
;
using
System.Collections.Immutable
;
using
System.Composition
;
using
System.Diagnostics
;
using
System.Linq
;
using
System.Text
;
...
...
@@ -13,6 +14,7 @@
using
Microsoft.CodeAnalysis.CSharp.Syntax
;
using
Microsoft.CodeAnalysis.FindSymbols
;
using
Microsoft.CodeAnalysis.Formatting
;
using
Microsoft.CodeAnalysis.Host.Mef
;
using
Microsoft.CodeAnalysis.LanguageServices
;
using
Microsoft.CodeAnalysis.Shared.Extensions
;
using
Microsoft.CodeAnalysis.Text
;
...
...
@@ -20,1221 +22,1221 @@
namespace
Microsoft.CodeAnalysis.CSharp
{
internal
class
CSharpSyntaxFactsService
:
AbstractSyntaxFactsService
,
ISyntaxFactsService
[
ExportLanguageService
(
typeof
(
IDeclaredSymbolInfoFactoryService
),
LanguageNames
.
CSharp
),
Shared
]
internal
class
CSharpDeclaredSymbolInfoFactoryService
:
AbstractDeclaredSymbolInfoFactoryService
{
internal
static
readonly
CSharpSyntaxFactsService
Instance
=
new
CSharpSyntaxFactsService
();
private
CSharpSyntaxFactsService
()
{
}
public
bool
IsCaseSensitive
=>
true
;
public
StringComparer
StringComparer
{
get
;
}
=
StringComparer
.
Ordinal
;
protected
override
IDocumentationCommentService
DocumentationCommentService
=>
CSharpDocumentationCommentService
.
Instance
;
public
bool
SupportsIndexingInitializer
(
ParseOptions
options
)
=>
((
CSharpParseOptions
)
options
).
LanguageVersion
>=
LanguageVersion
.
CSharp6
;
public
bool
SupportsThrowExpression
(
ParseOptions
options
)
=>
((
CSharpParseOptions
)
options
).
LanguageVersion
>=
LanguageVersion
.
CSharp7
;
public
bool
IsAwaitKeyword
(
SyntaxToken
token
)
{
return
token
.
IsKind
(
SyntaxKind
.
AwaitKeyword
);
}
public
bool
IsIdentifier
(
SyntaxToken
token
)
{
return
token
.
IsKind
(
SyntaxKind
.
IdentifierToken
);
}
public
bool
IsGlobalNamespaceKeyword
(
SyntaxToken
token
)
{
return
token
.
IsKind
(
SyntaxKind
.
GlobalKeyword
);
}
public
bool
IsVerbatimIdentifier
(
SyntaxToken
token
)
{
return
token
.
IsVerbatimIdentifier
();
}
public
bool
IsOperator
(
SyntaxToken
token
)
{
var
kind
=
token
.
Kind
();
return
(
SyntaxFacts
.
IsAnyUnaryExpression
(
kind
)
&&
(
token
.
Parent
is
PrefixUnaryExpressionSyntax
||
token
.
Parent
is
PostfixUnaryExpressionSyntax
||
token
.
Parent
is
OperatorDeclarationSyntax
))
||
(
SyntaxFacts
.
IsBinaryExpression
(
kind
)
&&
(
token
.
Parent
is
BinaryExpressionSyntax
||
token
.
Parent
is
OperatorDeclarationSyntax
))
||
(
SyntaxFacts
.
IsAssignmentExpressionOperatorToken
(
kind
)
&&
token
.
Parent
is
AssignmentExpressionSyntax
);
}
public
bool
IsKeyword
(
SyntaxToken
token
)
{
var
kind
=
(
SyntaxKind
)
token
.
RawKind
;
return
SyntaxFacts
.
IsKeywordKind
(
kind
);
// both contextual and reserved keywords
}
public
bool
IsContextualKeyword
(
SyntaxToken
token
)
{
var
kind
=
(
SyntaxKind
)
token
.
RawKind
;
return
SyntaxFacts
.
IsContextualKeyword
(
kind
);
}
public
bool
IsPreprocessorKeyword
(
SyntaxToken
token
)
{
var
kind
=
(
SyntaxKind
)
token
.
RawKind
;
return
SyntaxFacts
.
IsPreprocessorKeyword
(
kind
);
}
public
bool
IsHashToken
(
SyntaxToken
token
)
{
return
(
SyntaxKind
)
token
.
RawKind
==
SyntaxKind
.
HashToken
;
}
public
bool
IsInInactiveRegion
(
SyntaxTree
syntaxTree
,
int
position
,
CancellationToken
cancellationToken
)
private
ImmutableArray
<
string
>
GetInheritanceNames
(
Project
project
,
BaseListSyntax
baseList
)
{
var
csharpTree
=
syntaxTree
as
SyntaxTree
;
if
(
csharpTree
==
null
)
if
(
baseList
==
null
)
{
return
false
;
return
ImmutableArray
<
string
>.
Empty
;
}
return
csharpTree
.
IsInInactiveRegion
(
position
,
cancellationToken
);
}
var
builder
=
ArrayBuilder
<
string
>.
GetInstance
(
baseList
.
Types
.
Count
);
public
bool
IsInNonUserCode
(
SyntaxTree
syntaxTree
,
int
position
,
CancellationToken
cancellationToken
)
{
var
csharpTree
=
syntaxTree
as
SyntaxTree
;
if
(
csharpTree
==
null
)
// It's not sufficient to just store the textual names we see in the inheritance list
// of a type. For example if we have:
//
// using Y = X;
// ...
// using Z = Y;
// ...
// class C : Z
//
// It's insufficient to just state that 'C' derives from 'Z'. If we search for derived
// types from 'B' we won't examine 'C'. To solve this, we keep track of the aliasing
// that occurs in containing scopes. Then, when we're adding an inheritance name we
// walk the alias maps and we also add any names that these names alias to. In the
// above example we'd put Z, Y, and X in the inheritance names list for 'C'.
// Each dictionary in this list is a mapping from alias name to the name of the thing
// it aliases. Then, each scope with alias mapping gets its own entry in this list.
// For the above example, we would produce: [{Z => Y}, {Y => X}]
var
aliasMaps
=
AllocateAliasMapList
();
try
{
return
false
;
}
AddAliasMaps
(
baseList
,
aliasMaps
);
return
csharpTree
.
IsInNonUserCode
(
position
,
cancellationToken
);
}
foreach
(
var
baseType
in
baseList
.
Types
)
{
AddInheritanceName
(
builder
,
baseType
.
Type
,
aliasMaps
);
}
public
bool
IsEntirelyWithinStringOrCharOrNumericLiteral
(
SyntaxTree
syntaxTree
,
int
position
,
CancellationToken
cancellationToken
)
{
var
csharpTree
=
syntaxTree
as
SyntaxTree
;
if
(
csharpTree
==
null
)
DeclaredSymbolInfo
.
Intern
(
project
,
builder
);
return
builder
.
ToImmutableAndFree
();
}
finally
{
return
false
;
FreeAliasMapList
(
aliasMaps
)
;
}
return
csharpTree
.
IsEntirelyWithinStringOrCharLiteral
(
position
,
cancellationToken
);
}
public
bool
IsDirective
(
SyntaxNode
node
)
{
return
node
is
DirectiveTriviaSyntax
;
}
p
ublic
bool
TryGetExternalSourceInfo
(
SyntaxNode
node
,
out
ExternalSourceInfo
info
)
p
rivate
void
AddAliasMaps
(
SyntaxNode
node
,
List
<
Dictionary
<
string
,
string
>>
aliasMaps
)
{
var
lineDirective
=
node
as
LineDirectiveTriviaSyntax
;
if
(
lineDirective
!=
null
)
for
(
var
current
=
node
;
current
!=
null
;
current
=
current
.
Parent
)
{
if
(
lineDirective
.
Line
.
Kind
()
==
SyntaxKind
.
DefaultKeyword
)
if
(
current
.
IsKind
(
SyntaxKind
.
NamespaceDeclaration
)
)
{
info
=
new
ExternalSourceInfo
(
null
,
ends
:
true
);
return
true
;
ProcessUsings
(
aliasMaps
,
((
NamespaceDeclarationSyntax
)
current
).
Usings
);
}
else
if
(
lineDirective
.
Line
.
Kind
()
==
SyntaxKind
.
NumericLiteralToken
&&
lineDirective
.
Line
.
Value
is
int
)
else
if
(
current
.
IsKind
(
SyntaxKind
.
CompilationUnit
))
{
info
=
new
ExternalSourceInfo
((
int
)
lineDirective
.
Line
.
Value
,
false
);
return
true
;
ProcessUsings
(
aliasMaps
,
((
CompilationUnitSyntax
)
current
).
Usings
);
}
}
info
=
default
(
ExternalSourceInfo
);
return
false
;
}
public
bool
IsRightSideOfQualifiedName
(
SyntaxNode
node
)
{
var
name
=
node
as
SimpleNameSyntax
;
return
name
.
IsRightSideOfQualifiedName
();
}
public
bool
IsNameOfMemberAccessExpression
(
SyntaxNode
node
)
{
var
name
=
node
as
SimpleNameSyntax
;
return
name
.
IsMemberAccessExpressionName
();
}
public
bool
IsObjectCreationExpressionType
(
SyntaxNode
node
)
{
return
node
.
IsParentKind
(
SyntaxKind
.
ObjectCreationExpression
)
&&
((
ObjectCreationExpressionSyntax
)
node
.
Parent
).
Type
==
node
;
}
public
bool
IsAttributeName
(
SyntaxNode
node
)
private
void
ProcessUsings
(
List
<
Dictionary
<
string
,
string
>>
aliasMaps
,
SyntaxList
<
UsingDirectiveSyntax
>
usings
)
{
return
SyntaxFacts
.
IsAttributeName
(
node
);
}
Dictionary
<
string
,
string
>
aliasMap
=
null
;
public
bool
IsInvocationExpression
(
SyntaxNode
node
)
{
return
node
is
InvocationExpressionSyntax
;
}
foreach
(
var
usingDecl
in
usings
)
{
if
(
usingDecl
.
Alias
!=
null
)
{
var
mappedName
=
GetTypeName
(
usingDecl
.
Name
);
if
(
mappedName
!=
null
)
{
aliasMap
=
aliasMap
??
AllocateAliasMap
();
public
bool
IsAnonymousFunction
(
SyntaxNode
node
)
{
return
node
is
ParenthesizedLambdaExpressionSyntax
||
node
is
SimpleLambdaExpressionSyntax
||
node
is
AnonymousMethodExpressionSyntax
;
}
// If we have: using X = Foo, then we store a mapping from X -> Foo
// here. That way if we see a class that inherits from X we also state
// that it inherits from Foo as well.
aliasMap
[
usingDecl
.
Alias
.
Name
.
Identifier
.
ValueText
]
=
mappedName
;
}
}
}
public
bool
IsGenericName
(
SyntaxNode
node
)
{
return
node
is
GenericNameSyntax
;
if
(
aliasMap
!=
null
)
{
aliasMaps
.
Add
(
aliasMap
);
}
}
public
bool
IsNamedParameter
(
SyntaxNode
node
)
=>
node
.
CheckParent
<
NameColonSyntax
>(
p
=>
p
.
Name
==
node
);
public
SyntaxNode
GetDefaultOfParameter
(
SyntaxNode
node
)
=>
(
node
as
ParameterSyntax
)?.
Default
;
public
bool
IsSkippedTokensTrivia
(
SyntaxNode
node
)
private
void
AddInheritanceName
(
ArrayBuilder
<
string
>
builder
,
TypeSyntax
type
,
List
<
Dictionary
<
string
,
string
>>
aliasMaps
)
{
return
node
is
SkippedTokensTriviaSyntax
;
}
var
name
=
GetTypeName
(
type
);
if
(
name
!=
null
)
{
// First, add the name that the typename that the type directly says it inherits from.
builder
.
Add
(
name
);
public
bool
HasIncompleteParentMember
(
SyntaxNode
node
)
{
return
node
.
IsParentKind
(
SyntaxKind
.
IncompleteMember
);
}
// Now, walk the alias chain and add any names this alias may eventually map to.
var
currentName
=
name
;
foreach
(
var
aliasMap
in
aliasMaps
)
{
if
(
aliasMap
.
TryGetValue
(
currentName
,
out
var
mappedName
))
{
// Looks like this could be an alias. Also include the name the alias points to
builder
.
Add
(
mappedName
);
public
SyntaxToken
GetIdentifierOfGenericName
(
SyntaxNode
genericName
)
{
var
csharpGenericName
=
genericName
as
GenericNameSyntax
;
return
csharpGenericName
!=
null
?
csharpGenericName
.
Identifier
:
default
(
SyntaxToken
);
// Keep on searching. An alias in an inner namespcae can refer to an
// alias in an outer namespace.
currentName
=
mappedName
;
}
}
}
}
public
bool
IsUsingDirectiveName
(
SyntaxNode
node
)
public
override
bool
TryGetDeclaredSymbolInfo
(
Project
project
,
SyntaxNode
node
,
out
DeclaredSymbolInfo
declaredSymbolInfo
)
{
return
node
.
IsParentKind
(
SyntaxKind
.
UsingDirective
)
&&
((
UsingDirectiveSyntax
)
node
.
Parent
).
Name
==
node
;
}
switch
(
node
.
Kind
())
{
case
SyntaxKind
.
ClassDeclaration
:
var
classDecl
=
(
ClassDeclarationSyntax
)
node
;
declaredSymbolInfo
=
new
DeclaredSymbolInfo
(
project
,
classDecl
.
Identifier
.
ValueText
,
GetTypeParameterSuffix
(
classDecl
.
TypeParameterList
),
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
DeclaredSymbolInfoKind
.
Class
,
GetAccessibility
(
classDecl
,
classDecl
.
Modifiers
),
classDecl
.
Identifier
.
Span
,
GetInheritanceNames
(
project
,
classDecl
.
BaseList
));
return
true
;
case
SyntaxKind
.
ConstructorDeclaration
:
var
ctorDecl
=
(
ConstructorDeclarationSyntax
)
node
;
declaredSymbolInfo
=
new
DeclaredSymbolInfo
(
project
,
ctorDecl
.
Identifier
.
ValueText
,
GetConstructorSuffix
(
ctorDecl
),
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
DeclaredSymbolInfoKind
.
Constructor
,
GetAccessibility
(
ctorDecl
,
ctorDecl
.
Modifiers
),
ctorDecl
.
Identifier
.
Span
,
inheritanceNames
:
ImmutableArray
<
string
>.
Empty
,
parameterCount
:
ctorDecl
.
ParameterList
?.
Parameters
.
Count
??
0
);
return
true
;
case
SyntaxKind
.
DelegateDeclaration
:
var
delegateDecl
=
(
DelegateDeclarationSyntax
)
node
;
declaredSymbolInfo
=
new
DeclaredSymbolInfo
(
project
,
delegateDecl
.
Identifier
.
ValueText
,
GetTypeParameterSuffix
(
delegateDecl
.
TypeParameterList
),
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
DeclaredSymbolInfoKind
.
Delegate
,
GetAccessibility
(
delegateDecl
,
delegateDecl
.
Modifiers
),
delegateDecl
.
Identifier
.
Span
,
inheritanceNames
:
ImmutableArray
<
string
>.
Empty
);
return
true
;
case
SyntaxKind
.
EnumDeclaration
:
var
enumDecl
=
(
EnumDeclarationSyntax
)
node
;
declaredSymbolInfo
=
new
DeclaredSymbolInfo
(
project
,
enumDecl
.
Identifier
.
ValueText
,
null
,
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
DeclaredSymbolInfoKind
.
Enum
,
GetAccessibility
(
enumDecl
,
enumDecl
.
Modifiers
),
enumDecl
.
Identifier
.
Span
,
inheritanceNames
:
ImmutableArray
<
string
>.
Empty
);
return
true
;
case
SyntaxKind
.
EnumMemberDeclaration
:
var
enumMember
=
(
EnumMemberDeclarationSyntax
)
node
;
declaredSymbolInfo
=
new
DeclaredSymbolInfo
(
project
,
enumMember
.
Identifier
.
ValueText
,
null
,
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
DeclaredSymbolInfoKind
.
EnumMember
,
Accessibility
.
Public
,
enumMember
.
Identifier
.
Span
,
inheritanceNames
:
ImmutableArray
<
string
>.
Empty
);
return
true
;
case
SyntaxKind
.
EventDeclaration
:
var
eventDecl
=
(
EventDeclarationSyntax
)
node
;
declaredSymbolInfo
=
new
DeclaredSymbolInfo
(
project
,
eventDecl
.
Identifier
.
ValueText
,
null
,
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
DeclaredSymbolInfoKind
.
Event
,
GetAccessibility
(
eventDecl
,
eventDecl
.
Modifiers
),
eventDecl
.
Identifier
.
Span
,
inheritanceNames
:
ImmutableArray
<
string
>.
Empty
);
return
true
;
case
SyntaxKind
.
IndexerDeclaration
:
var
indexerDecl
=
(
IndexerDeclarationSyntax
)
node
;
declaredSymbolInfo
=
new
DeclaredSymbolInfo
(
project
,
"this"
,
GetIndexerSuffix
(
indexerDecl
),
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
DeclaredSymbolInfoKind
.
Indexer
,
GetAccessibility
(
indexerDecl
,
indexerDecl
.
Modifiers
),
indexerDecl
.
ThisKeyword
.
Span
,
inheritanceNames
:
ImmutableArray
<
string
>.
Empty
);
return
true
;
case
SyntaxKind
.
InterfaceDeclaration
:
var
interfaceDecl
=
(
InterfaceDeclarationSyntax
)
node
;
declaredSymbolInfo
=
new
DeclaredSymbolInfo
(
project
,
interfaceDecl
.
Identifier
.
ValueText
,
GetTypeParameterSuffix
(
interfaceDecl
.
TypeParameterList
),
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
DeclaredSymbolInfoKind
.
Interface
,
GetAccessibility
(
interfaceDecl
,
interfaceDecl
.
Modifiers
),
interfaceDecl
.
Identifier
.
Span
,
GetInheritanceNames
(
project
,
interfaceDecl
.
BaseList
));
return
true
;
case
SyntaxKind
.
MethodDeclaration
:
var
method
=
(
MethodDeclarationSyntax
)
node
;
declaredSymbolInfo
=
new
DeclaredSymbolInfo
(
project
,
method
.
Identifier
.
ValueText
,
GetMethodSuffix
(
method
),
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
IsExtensionMethod
(
method
)
?
DeclaredSymbolInfoKind
.
ExtensionMethod
:
DeclaredSymbolInfoKind
.
Method
,
GetAccessibility
(
method
,
method
.
Modifiers
),
method
.
Identifier
.
Span
,
inheritanceNames
:
ImmutableArray
<
string
>.
Empty
,
parameterCount
:
method
.
ParameterList
?.
Parameters
.
Count
??
0
,
typeParameterCount
:
method
.
TypeParameterList
?.
Parameters
.
Count
??
0
);
return
true
;
case
SyntaxKind
.
PropertyDeclaration
:
var
property
=
(
PropertyDeclarationSyntax
)
node
;
declaredSymbolInfo
=
new
DeclaredSymbolInfo
(
project
,
property
.
Identifier
.
ValueText
,
null
,
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
DeclaredSymbolInfoKind
.
Property
,
GetAccessibility
(
property
,
property
.
Modifiers
),
property
.
Identifier
.
Span
,
inheritanceNames
:
ImmutableArray
<
string
>.
Empty
);
return
true
;
case
SyntaxKind
.
StructDeclaration
:
var
structDecl
=
(
StructDeclarationSyntax
)
node
;
declaredSymbolInfo
=
new
DeclaredSymbolInfo
(
project
,
structDecl
.
Identifier
.
ValueText
,
GetTypeParameterSuffix
(
structDecl
.
TypeParameterList
),
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
DeclaredSymbolInfoKind
.
Struct
,
GetAccessibility
(
structDecl
,
structDecl
.
Modifiers
),
structDecl
.
Identifier
.
Span
,
GetInheritanceNames
(
project
,
structDecl
.
BaseList
));
return
true
;
case
SyntaxKind
.
VariableDeclarator
:
// could either be part of a field declaration or an event field declaration
var
variableDeclarator
=
(
VariableDeclaratorSyntax
)
node
;
var
variableDeclaration
=
variableDeclarator
.
Parent
as
VariableDeclarationSyntax
;
var
fieldDeclaration
=
variableDeclaration
?.
Parent
as
BaseFieldDeclarationSyntax
;
if
(
fieldDeclaration
!=
null
)
{
var
kind
=
fieldDeclaration
is
EventFieldDeclarationSyntax
?
DeclaredSymbolInfoKind
.
Event
:
fieldDeclaration
.
Modifiers
.
Any
(
m
=>
m
.
Kind
()
==
SyntaxKind
.
ConstKeyword
)
?
DeclaredSymbolInfoKind
.
Constant
:
DeclaredSymbolInfoKind
.
Field
;
public
bool
IsForEachStatement
(
SyntaxNode
node
)
{
return
node
is
ForEachStatementSyntax
;
}
declaredSymbolInfo
=
new
DeclaredSymbolInfo
(
project
,
variableDeclarator
.
Identifier
.
ValueText
,
null
,
GetContainerDisplayName
(
fieldDeclaration
.
Parent
),
GetFullyQualifiedContainerName
(
fieldDeclaration
.
Parent
),
kind
,
GetAccessibility
(
fieldDeclaration
,
fieldDeclaration
.
Modifiers
),
variableDeclarator
.
Identifier
.
Span
,
inheritanceNames
:
ImmutableArray
<
string
>.
Empty
);
return
true
;
}
public
bool
IsLockStatement
(
SyntaxNode
node
)
{
return
node
is
LockStatementSyntax
;
break
;
}
declaredSymbolInfo
=
default
(
DeclaredSymbolInfo
);
return
false
;
}
public
bool
IsUsingStatement
(
SyntaxNode
node
)
=>
node
.
Kind
()
==
SyntaxKind
.
UsingStatement
;
private
string
GetConstructorSuffix
(
ConstructorDeclarationSyntax
constructor
)
=>
constructor
.
Modifiers
.
Any
(
SyntaxKind
.
StaticKeyword
)
?
".static "
+
constructor
.
Identifier
+
"()"
:
GetSuffix
(
'('
,
')'
,
constructor
.
ParameterList
.
Parameters
);
public
bool
IsReturnStatement
(
SyntaxNode
node
)
=>
node
.
Kind
()
==
SyntaxKind
.
ReturnStatement
;
private
string
GetMethodSuffix
(
MethodDeclarationSyntax
method
)
=>
GetTypeParameterSuffix
(
method
.
TypeParameterList
)
+
GetSuffix
(
'('
,
')'
,
method
.
ParameterList
.
Parameters
);
p
ublic
SyntaxNode
GetExpressionOfReturnStatement
(
SyntaxNode
node
)
=>
(
node
as
ReturnStatementSyntax
)?.
Expression
;
p
rivate
string
GetIndexerSuffix
(
IndexerDeclarationSyntax
indexer
)
=>
GetSuffix
(
'['
,
']'
,
indexer
.
ParameterList
.
Parameters
)
;
p
ublic
bool
IsThisConstructorInitializer
(
SyntaxToken
token
)
p
rivate
string
GetTypeParameterSuffix
(
TypeParameterListSyntax
typeParameterList
)
{
return
token
.
Parent
.
IsKind
(
SyntaxKind
.
ThisConstructorInitializer
)
&&
((
ConstructorInitializerSyntax
)
token
.
Parent
).
ThisOrBaseKeyword
==
token
;
}
if
(
typeParameterList
==
null
)
{
return
null
;
}
public
bool
IsBaseConstructorInitializer
(
SyntaxToken
token
)
{
return
token
.
Parent
.
IsKind
(
SyntaxKind
.
BaseConstructorInitializer
)
&&
((
ConstructorInitializerSyntax
)
token
.
Parent
).
ThisOrBaseKeyword
==
token
;
}
var
pooledBuilder
=
PooledStringBuilder
.
GetInstance
();
public
bool
IsQueryExpression
(
SyntaxNode
node
)
=>
node
.
Kind
()
==
SyntaxKind
.
QueryExpression
;
var
builder
=
pooledBuilder
.
Builder
;
builder
.
Append
(
'<'
)
;
public
bool
IsThrowExpression
(
SyntaxNode
node
)
=>
node
.
Kind
()
==
SyntaxKind
.
ThrowExpression
;
var
first
=
true
;
foreach
(
var
parameter
in
typeParameterList
.
Parameters
)
{
if
(!
first
)
{
builder
.
Append
(
", "
);
}
public
bool
IsPredefinedType
(
SyntaxToken
token
)
=>
TryGetPredefinedType
(
token
,
out
var
actualType
)
&&
actualType
!=
PredefinedType
.
None
;
builder
.
Append
(
parameter
.
Identifier
.
Text
);
}
public
bool
IsPredefinedType
(
SyntaxToken
token
,
PredefinedType
type
)
=>
TryGetPredefinedType
(
token
,
out
var
actualType
)
&&
actualType
==
type
;
builder
.
Append
(
'>'
);
public
bool
TryGetPredefinedType
(
SyntaxToken
token
,
out
PredefinedType
type
)
return
pooledBuilder
.
ToStringAndFree
();
}
/// <summary>
/// Builds up the suffix to show for something with parameters in navigate-to.
/// While it would be nice to just use the compiler SymbolDisplay API for this,
/// it would be too expensive as it requires going back to Symbols (which requires
/// creating compilations, etc.) in a perf sensitive area.
///
/// So, instead, we just build a reasonable suffix using the pure syntax that a
/// user provided. That means that if they wrote "Method(System.Int32 i)" we'll
/// show that as "Method(System.Int32)" not "Method(int)". Given that this is
/// actually what the user wrote, and it saves us from ever having to go back to
/// symbols/compilations, this is well worth it, even if it does mean we have to
/// create our own 'symbol display' logic here.
/// </summary>
private
string
GetSuffix
(
char
openBrace
,
char
closeBrace
,
SeparatedSyntaxList
<
ParameterSyntax
>
parameters
)
{
type
=
GetPredefinedType
(
token
);
return
type
!=
PredefinedType
.
None
;
var
pooledBuilder
=
PooledStringBuilder
.
GetInstance
();
var
builder
=
pooledBuilder
.
Builder
;
builder
.
Append
(
openBrace
);
AppendParameters
(
parameters
,
builder
);
builder
.
Append
(
closeBrace
);
return
pooledBuilder
.
ToStringAndFree
();
}
private
PredefinedType
GetPredefinedType
(
SyntaxToken
token
)
private
void
AppendParameters
(
SeparatedSyntaxList
<
ParameterSyntax
>
parameters
,
StringBuilder
builder
)
{
switch
((
SyntaxKind
)
token
.
RawKind
)
var
first
=
true
;
foreach
(
var
parameter
in
parameters
)
{
case
SyntaxKind
.
BoolKeyword
:
return
PredefinedType
.
Boolean
;
case
SyntaxKind
.
ByteKeyword
:
return
PredefinedType
.
Byte
;
case
SyntaxKind
.
SByteKeyword
:
return
PredefinedType
.
SByte
;
case
SyntaxKind
.
IntKeyword
:
return
PredefinedType
.
Int32
;
case
SyntaxKind
.
UIntKeyword
:
return
PredefinedType
.
UInt32
;
case
SyntaxKind
.
ShortKeyword
:
return
PredefinedType
.
Int16
;
case
SyntaxKind
.
UShortKeyword
:
return
PredefinedType
.
UInt16
;
case
SyntaxKind
.
LongKeyword
:
return
PredefinedType
.
Int64
;
case
SyntaxKind
.
ULongKeyword
:
return
PredefinedType
.
UInt64
;
case
SyntaxKind
.
FloatKeyword
:
return
PredefinedType
.
Single
;
case
SyntaxKind
.
DoubleKeyword
:
return
PredefinedType
.
Double
;
case
SyntaxKind
.
DecimalKeyword
:
return
PredefinedType
.
Decimal
;
case
SyntaxKind
.
StringKeyword
:
return
PredefinedType
.
String
;
case
SyntaxKind
.
CharKeyword
:
return
PredefinedType
.
Char
;
case
SyntaxKind
.
ObjectKeyword
:
return
PredefinedType
.
Object
;
case
SyntaxKind
.
VoidKeyword
:
return
PredefinedType
.
Void
;
default
:
return
PredefinedType
.
None
;
}
}
if
(!
first
)
{
builder
.
Append
(
", "
);
}
foreach
(
var
modifier
in
parameter
.
Modifiers
)
{
builder
.
Append
(
modifier
.
Text
);
builder
.
Append
(
' '
);
}
public
bool
IsPredefinedOperator
(
SyntaxToken
token
)
{
return
TryGetPredefinedOperator
(
token
,
out
var
actualOperator
)
&&
actualOperator
!=
PredefinedOperator
.
None
;
}
if
(
parameter
.
Type
!=
null
)
{
AppendTokens
(
parameter
.
Type
,
builder
);
}
else
{
builder
.
Append
(
parameter
.
Identifier
.
Text
);
}
public
bool
IsPredefinedOperator
(
SyntaxToken
token
,
PredefinedOperator
op
)
{
return
TryGetPredefinedOperator
(
token
,
out
var
actualOperator
)
&&
actualOperator
==
op
;
first
=
false
;
}
}
public
bool
TryGetPredefinedOperator
(
SyntaxToken
token
,
out
PredefinedOperator
op
)
{
op
=
GetPredefinedOperator
(
token
);
return
op
!=
PredefinedOperator
.
None
;
}
private
string
GetContainerDisplayName
(
SyntaxNode
node
)
=>
CSharpSyntaxFactsService
.
Instance
.
GetDisplayName
(
node
,
DisplayNameOptions
.
IncludeTypeParameters
);
private
PredefinedOperator
GetPredefinedOperator
(
SyntaxToken
token
)
private
string
GetFullyQualifiedContainerName
(
SyntaxNode
node
)
=>
CSharpSyntaxFactsService
.
Instance
.
GetDisplayName
(
node
,
DisplayNameOptions
.
IncludeNamespaces
);
private
Accessibility
GetAccessibility
(
SyntaxNode
node
,
SyntaxTokenList
modifiers
)
{
switch
((
SyntaxKind
)
token
.
RawKind
)
var
sawInternal
=
false
;
foreach
(
var
modifier
in
modifiers
)
{
case
SyntaxKind
.
PlusToken
:
case
SyntaxKind
.
PlusEqualsToken
:
return
PredefinedOperator
.
Addition
;
case
SyntaxKind
.
MinusToken
:
case
SyntaxKind
.
MinusEqualsToken
:
return
PredefinedOperator
.
Subtraction
;
case
SyntaxKind
.
AmpersandToken
:
case
SyntaxKind
.
AmpersandEqualsToken
:
return
PredefinedOperator
.
BitwiseAnd
;
switch
(
modifier
.
Kind
())
{
case
SyntaxKind
.
PublicKeyword
:
return
Accessibility
.
Public
;
case
SyntaxKind
.
PrivateKeyword
:
return
Accessibility
.
Private
;
case
SyntaxKind
.
ProtectedKeyword
:
return
Accessibility
.
Protected
;
case
SyntaxKind
.
InternalKeyword
:
sawInternal
=
true
;
continue
;
}
}
case
SyntaxKind
.
BarToken
:
case
SyntaxKind
.
BarEqualsToken
:
return
PredefinedOperator
.
BitwiseOr
;
if
(
sawInternal
)
{
return
Accessibility
.
Internal
;
}
case
SyntaxKind
.
MinusMinusToken
:
return
PredefinedOperator
.
Decrement
;
// No accessibility modifiers:
switch
(
node
.
Parent
.
Kind
())
{
case
SyntaxKind
.
ClassDeclaration
:
case
SyntaxKind
.
StructDeclaration
:
// Anything without modifiers is private if it's in a class/struct declaration.
return
Accessibility
.
Private
;
case
SyntaxKind
.
InterfaceDeclaration
:
// Anything without modifiers is public if it's in an interface declaration.
return
Accessibility
.
Public
;
case
SyntaxKind
.
CompilationUnit
:
// Things are private by default in script
if
(((
CSharpParseOptions
)
node
.
SyntaxTree
.
Options
).
Kind
==
SourceCodeKind
.
Script
)
{
return
Accessibility
.
Private
;
}
case
SyntaxKind
.
PlusPlusToken
:
return
PredefinedOperator
.
Increment
;
return
Accessibility
.
Internal
;
case
SyntaxKind
.
SlashToken
:
case
SyntaxKind
.
SlashEqualsToken
:
return
PredefinedOperator
.
Division
;
default
:
// Otherwise it's internal
return
Accessibility
.
Internal
;
}
}
case
SyntaxKind
.
EqualsEqualsToken
:
return
PredefinedOperator
.
Equality
;
private
string
GetTypeName
(
TypeSyntax
type
)
{
if
(
type
is
SimpleNameSyntax
simpleName
)
{
return
GetSimpleTypeName
(
simpleName
);
}
else
if
(
type
is
QualifiedNameSyntax
qualifiedName
)
{
return
GetSimpleTypeName
(
qualifiedName
.
Right
);
}
else
if
(
type
is
AliasQualifiedNameSyntax
aliasName
)
{
return
GetSimpleTypeName
(
aliasName
.
Name
);
}
case
SyntaxKind
.
CaretToken
:
case
SyntaxKind
.
CaretEqualsToken
:
return
PredefinedOperator
.
ExclusiveOr
;
return
null
;
}
case
SyntaxKind
.
GreaterThanToken
:
return
PredefinedOperator
.
GreaterThan
;
private
static
string
GetSimpleTypeName
(
SimpleNameSyntax
name
)
=>
name
.
Identifier
.
ValueText
;
case
SyntaxKind
.
GreaterThanEqualsToken
:
return
PredefinedOperator
.
GreaterThanOrEqual
;
private
bool
IsExtensionMethod
(
MethodDeclarationSyntax
method
)
=>
method
.
ParameterList
.
Parameters
.
Count
>
0
&&
method
.
ParameterList
.
Parameters
[
0
].
Modifiers
.
Any
(
SyntaxKind
.
ThisKeyword
);
}
case
SyntaxKind
.
ExclamationEqualsToken
:
return
PredefinedOperator
.
Inequality
;
internal
class
CSharpSyntaxFactsService
:
AbstractSyntaxFactsService
,
ISyntaxFactsService
{
internal
static
readonly
CSharpSyntaxFactsService
Instance
=
new
CSharpSyntaxFactsService
();
case
SyntaxKind
.
LessThanLessThanToken
:
case
SyntaxKind
.
LessThanLessThanEqualsToken
:
return
PredefinedOperator
.
LeftShift
;
private
CSharpSyntaxFactsService
()
{
}
case
SyntaxKind
.
LessThanEqualsToken
:
return
PredefinedOperator
.
LessThanOrEqual
;
public
bool
IsCaseSensitive
=>
true
;
case
SyntaxKind
.
AsteriskToken
:
case
SyntaxKind
.
AsteriskEqualsToken
:
return
PredefinedOperator
.
Multiplication
;
public
StringComparer
StringComparer
{
get
;
}
=
StringComparer
.
Ordinal
;
case
SyntaxKind
.
PercentToken
:
case
SyntaxKind
.
PercentEqualsToken
:
return
PredefinedOperator
.
Modulus
;
protected
override
IDocumentationCommentService
DocumentationCommentService
=>
CSharpDocumentationCommentService
.
Instance
;
case
SyntaxKind
.
ExclamationToken
:
case
SyntaxKind
.
TildeToken
:
return
PredefinedOperator
.
Complement
;
public
bool
SupportsIndexingInitializer
(
ParseOptions
options
)
=>
((
CSharpParseOptions
)
options
).
LanguageVersion
>=
LanguageVersion
.
CSharp6
;
case
SyntaxKind
.
GreaterThanGreaterThanToken
:
case
SyntaxKind
.
GreaterThanGreaterThanEqualsToken
:
return
PredefinedOperator
.
RightShift
;
}
public
bool
SupportsThrowExpression
(
ParseOptions
options
)
=>
((
CSharpParseOptions
)
options
).
LanguageVersion
>=
LanguageVersion
.
CSharp7
;
return
PredefinedOperator
.
None
;
public
bool
IsAwaitKeyword
(
SyntaxToken
token
)
{
return
token
.
IsKind
(
SyntaxKind
.
AwaitKeyword
);
}
public
string
GetText
(
int
kind
)
public
bool
IsIdentifier
(
SyntaxToken
token
)
{
return
SyntaxFacts
.
GetText
((
SyntaxKind
)
kind
);
return
token
.
IsKind
(
SyntaxKind
.
IdentifierToken
);
}
public
bool
Is
IdentifierStartCharacter
(
char
c
)
public
bool
Is
GlobalNamespaceKeyword
(
SyntaxToken
token
)
{
return
SyntaxFacts
.
IsIdentifierStartCharacter
(
c
);
return
token
.
IsKind
(
SyntaxKind
.
GlobalKeyword
);
}
public
bool
Is
IdentifierPartCharacter
(
char
c
)
public
bool
Is
VerbatimIdentifier
(
SyntaxToken
token
)
{
return
SyntaxFacts
.
IsIdentifierPartCharacter
(
c
);
return
token
.
IsVerbatimIdentifier
(
);
}
public
bool
Is
IdentifierEscapeCharacter
(
char
c
)
public
bool
Is
Operator
(
SyntaxToken
token
)
{
return
c
==
'@'
;
var
kind
=
token
.
Kind
();
return
(
SyntaxFacts
.
IsAnyUnaryExpression
(
kind
)
&&
(
token
.
Parent
is
PrefixUnaryExpressionSyntax
||
token
.
Parent
is
PostfixUnaryExpressionSyntax
||
token
.
Parent
is
OperatorDeclarationSyntax
))
||
(
SyntaxFacts
.
IsBinaryExpression
(
kind
)
&&
(
token
.
Parent
is
BinaryExpressionSyntax
||
token
.
Parent
is
OperatorDeclarationSyntax
))
||
(
SyntaxFacts
.
IsAssignmentExpressionOperatorToken
(
kind
)
&&
token
.
Parent
is
AssignmentExpressionSyntax
);
}
public
bool
Is
ValidIdentifier
(
string
identifier
)
public
bool
Is
Keyword
(
SyntaxToken
token
)
{
var
token
=
SyntaxFactory
.
ParseToken
(
identifier
);
return
IsIdentifier
(
token
)
&&
!
token
.
ContainsDiagnostics
&&
token
.
ToString
().
Length
==
identifier
.
Length
;
var
kind
=
(
SyntaxKind
)
token
.
RawKind
;
return
SyntaxFacts
.
IsKeywordKind
(
kind
);
// both contextual and reserved keywords
}
public
bool
Is
VerbatimIdentifier
(
string
identifier
)
public
bool
Is
ContextualKeyword
(
SyntaxToken
token
)
{
var
token
=
SyntaxFactory
.
ParseToken
(
identifier
);
return
IsIdentifier
(
token
)
&&
!
token
.
ContainsDiagnostics
&&
token
.
ToString
().
Length
==
identifier
.
Length
&&
token
.
IsVerbatimIdentifier
();
var
kind
=
(
SyntaxKind
)
token
.
RawKind
;
return
SyntaxFacts
.
IsContextualKeyword
(
kind
);
}
public
bool
Is
TypeCharacter
(
char
c
)
public
bool
Is
PreprocessorKeyword
(
SyntaxToken
token
)
{
return
false
;
var
kind
=
(
SyntaxKind
)
token
.
RawKind
;
return
SyntaxFacts
.
IsPreprocessorKeyword
(
kind
);
}
public
bool
Is
StartOfUnicodeEscapeSequence
(
char
c
)
public
bool
Is
HashToken
(
SyntaxToken
token
)
{
return
c
==
'\\'
;
return
(
SyntaxKind
)
token
.
RawKind
==
SyntaxKind
.
HashToken
;
}
public
bool
Is
Literal
(
SyntaxToken
t
oken
)
public
bool
Is
InInactiveRegion
(
SyntaxTree
syntaxTree
,
int
position
,
CancellationToken
cancellationT
oken
)
{
switch
(
token
.
Kind
())
var
csharpTree
=
syntaxTree
as
SyntaxTree
;
if
(
csharpTree
==
null
)
{
case
SyntaxKind
.
NumericLiteralToken
:
case
SyntaxKind
.
CharacterLiteralToken
:
case
SyntaxKind
.
StringLiteralToken
:
case
SyntaxKind
.
NullKeyword
:
case
SyntaxKind
.
TrueKeyword
:
case
SyntaxKind
.
FalseKeyword
:
case
SyntaxKind
.
InterpolatedStringStartToken
:
case
SyntaxKind
.
InterpolatedStringEndToken
:
case
SyntaxKind
.
InterpolatedVerbatimStringStartToken
:
case
SyntaxKind
.
InterpolatedStringTextToken
:
return
true
;
return
false
;
}
return
false
;
return
csharpTree
.
IsInInactiveRegion
(
position
,
cancellationToken
)
;
}
public
bool
Is
StringLiteralOrInterpolatedStringLiteral
(
SyntaxToken
t
oken
)
public
bool
Is
InNonUserCode
(
SyntaxTree
syntaxTree
,
int
position
,
CancellationToken
cancellationT
oken
)
{
return
token
.
IsKind
(
SyntaxKind
.
StringLiteralToken
,
SyntaxKind
.
InterpolatedStringTextToken
);
}
var
csharpTree
=
syntaxTree
as
SyntaxTree
;
if
(
csharpTree
==
null
)
{
return
false
;
}
public
bool
IsNumericLiteralExpression
(
SyntaxNode
node
)
{
return
node
?.
IsKind
(
SyntaxKind
.
NumericLiteralExpression
)
==
true
;
return
csharpTree
.
IsInNonUserCode
(
position
,
cancellationToken
);
}
public
bool
Is
TypeNamedVarInVariableOrFieldDeclaration
(
SyntaxToken
token
,
SyntaxNode
parent
)
public
bool
Is
EntirelyWithinStringOrCharOrNumericLiteral
(
SyntaxTree
syntaxTree
,
int
position
,
CancellationToken
cancellationToken
)
{
var
typedToken
=
token
;
var
typedParent
=
parent
;
if
(
typedParent
.
IsKind
(
SyntaxKind
.
IdentifierName
))
{
TypeSyntax
declaredType
=
null
;
if
(
typedParent
.
IsParentKind
(
SyntaxKind
.
VariableDeclaration
))
{
declaredType
=
((
VariableDeclarationSyntax
)
typedParent
.
Parent
).
Type
;
}
else
if
(
typedParent
.
IsParentKind
(
SyntaxKind
.
FieldDeclaration
))
{
declaredType
=
((
FieldDeclarationSyntax
)
typedParent
.
Parent
).
Declaration
.
Type
;
}
return
declaredType
==
typedParent
&&
typedToken
.
ValueText
==
"var"
;
var
csharpTree
=
syntaxTree
as
SyntaxTree
;
if
(
csharpTree
==
null
)
{
return
false
;
}
return
false
;
return
csharpTree
.
IsEntirelyWithinStringOrCharLiteral
(
position
,
cancellationToken
)
;
}
public
bool
Is
TypeNamedDynamic
(
SyntaxToken
token
,
SyntaxNode
parent
)
public
bool
Is
Directive
(
SyntaxNode
node
)
{
var
typedParent
=
parent
as
ExpressionSyntax
;
return
node
is
DirectiveTriviaSyntax
;
}
if
(
typedParent
!=
null
)
public
bool
TryGetExternalSourceInfo
(
SyntaxNode
node
,
out
ExternalSourceInfo
info
)
{
var
lineDirective
=
node
as
LineDirectiveTriviaSyntax
;
if
(
lineDirective
!=
null
)
{
if
(
SyntaxFacts
.
IsInTypeOnlyContext
(
typedParent
)
&&
typedParent
.
IsKind
(
SyntaxKind
.
IdentifierName
)
&&
token
.
ValueText
==
"dynamic"
)
if
(
lineDirective
.
Line
.
Kind
()
==
SyntaxKind
.
DefaultKeyword
)
{
info
=
new
ExternalSourceInfo
(
null
,
ends
:
true
);
return
true
;
}
}
return
false
;
}
public
bool
IsBindableToken
(
SyntaxToken
token
)
{
if
(
this
.
IsWord
(
token
)
||
this
.
IsLiteral
(
token
)
||
this
.
IsOperator
(
token
))
{
switch
((
SyntaxKind
)
token
.
RawKind
)
else
if
(
lineDirective
.
Line
.
Kind
()
==
SyntaxKind
.
NumericLiteralToken
&&
lineDirective
.
Line
.
Value
is
int
)
{
case
SyntaxKind
.
DelegateKeyword
:
case
SyntaxKind
.
VoidKeyword
:
return
false
;
info
=
new
ExternalSourceInfo
((
int
)
lineDirective
.
Line
.
Value
,
false
);
return
true
;
}
return
true
;
}
info
=
default
(
ExternalSourceInfo
);
return
false
;
}
public
bool
IsSimpleMemberAccessExpression
(
SyntaxNode
node
)
=>
(
node
as
MemberAccessExpressionSyntax
)?.
Kind
()
==
SyntaxKind
.
SimpleMemberAccessExpression
;
public
bool
IsConditionalMemberAccessExpression
(
SyntaxNode
node
)
=>
node
is
ConditionalAccessExpressionSyntax
;
public
bool
IsPointerMemberAccessExpression
(
SyntaxNode
node
)
=>
(
node
as
MemberAccessExpressionSyntax
)?.
Kind
()
==
SyntaxKind
.
PointerMemberAccessExpression
;
public
void
GetNameAndArityOfSimpleName
(
SyntaxNode
node
,
out
string
name
,
out
int
arity
)
public
bool
IsRightSideOfQualifiedName
(
SyntaxNode
node
)
{
name
=
null
;
arity
=
0
;
var
simpleName
=
node
as
SimpleNameSyntax
;
if
(
simpleName
!=
null
)
{
name
=
simpleName
.
Identifier
.
ValueText
;
arity
=
simpleName
.
Arity
;
}
var
name
=
node
as
SimpleNameSyntax
;
return
name
.
IsRightSideOfQualifiedName
();
}
public
SyntaxNode
GetTargetOfMemberBinding
(
SyntaxNode
node
)
=>
(
node
as
MemberBindingExpressionSyntax
).
GetParentConditionalAccessExpression
()?.
Expression
;
public
SyntaxNode
GetExpressionOfMemberAccessExpression
(
SyntaxNode
node
,
bool
allowImplicitTarget
)
=>
(
node
as
MemberAccessExpressionSyntax
)?.
Expression
;
public
SyntaxNode
GetExpressionOfConditionalAccessExpression
(
SyntaxNode
node
)
=>
(
node
as
ConditionalAccessExpressionSyntax
)?.
Expression
;
public
SyntaxNode
GetExpressionOfElementAccessExpression
(
SyntaxNode
node
)
=>
(
node
as
ElementAccessExpressionSyntax
)?.
Expression
;
public
SyntaxNode
GetArgumentListOfElementAccessExpression
(
SyntaxNode
node
)
=>
(
node
as
ElementAccessExpressionSyntax
)?.
ArgumentList
;
public
SyntaxNode
GetExpressionOfInterpolation
(
SyntaxNode
node
)
=>
(
node
as
InterpolationSyntax
)?.
Expression
;
public
bool
IsNameOfMemberAccessExpression
(
SyntaxNode
node
)
{
var
name
=
node
as
SimpleNameSyntax
;
return
name
.
IsMemberAccessExpressionName
();
}
public
bool
Is
InStaticContext
(
SyntaxNode
node
)
public
bool
Is
ObjectCreationExpressionType
(
SyntaxNode
node
)
{
return
node
.
IsInStaticContext
();
return
node
.
IsParentKind
(
SyntaxKind
.
ObjectCreationExpression
)
&&
((
ObjectCreationExpressionSyntax
)
node
.
Parent
).
Type
==
node
;
}
public
bool
Is
InNamespaceOrTypeContext
(
SyntaxNode
node
)
public
bool
Is
AttributeName
(
SyntaxNode
node
)
{
return
SyntaxFacts
.
Is
InNamespaceOrTypeContext
(
node
as
ExpressionSyntax
);
return
SyntaxFacts
.
Is
AttributeName
(
node
);
}
public
SyntaxNode
GetExpressionOfArgument
(
SyntaxNode
node
)
public
bool
IsInvocationExpression
(
SyntaxNode
node
)
{
return
((
ArgumentSyntax
)
node
).
Expression
;
return
node
is
InvocationExpressionSyntax
;
}
public
RefKind
GetRefKindOfArgument
(
SyntaxNode
node
)
=>
(
node
as
ArgumentSyntax
).
GetRefKind
();
public
bool
IsAnonymousFunction
(
SyntaxNode
node
)
{
return
node
is
ParenthesizedLambdaExpressionSyntax
||
node
is
SimpleLambdaExpressionSyntax
||
node
is
AnonymousMethodExpressionSyntax
;
}
public
bool
Is
SimpleArgument
(
SyntaxNode
node
)
public
bool
Is
GenericName
(
SyntaxNode
node
)
{
var
argument
=
(
ArgumentSyntax
)
node
;
return
argument
.
RefOrOutKeyword
.
Kind
()
==
SyntaxKind
.
None
&&
argument
.
NameColon
==
null
;
return
node
is
GenericNameSyntax
;
}
public
bool
IsNamedParameter
(
SyntaxNode
node
)
=>
node
.
CheckParent
<
NameColonSyntax
>(
p
=>
p
.
Name
==
node
);
public
SyntaxNode
GetDefaultOfParameter
(
SyntaxNode
node
)
=>
(
node
as
ParameterSyntax
)?.
Default
;
public
bool
Is
InConstantContext
(
SyntaxNode
node
)
public
bool
Is
SkippedTokensTrivia
(
SyntaxNode
node
)
{
return
(
node
as
ExpressionSyntax
).
IsInConstantContext
()
;
return
node
is
SkippedTokensTriviaSyntax
;
}
public
bool
IsInConstructo
r
(
SyntaxNode
node
)
public
bool
HasIncompleteParentMembe
r
(
SyntaxNode
node
)
{
return
node
.
GetAncestor
<
ConstructorDeclarationSyntax
>()
!=
null
;
return
node
.
IsParentKind
(
SyntaxKind
.
IncompleteMember
)
;
}
public
bool
IsUnsafeContext
(
SyntaxNode
nod
e
)
public
SyntaxToken
GetIdentifierOfGenericName
(
SyntaxNode
genericNam
e
)
{
return
node
.
IsUnsafeContext
();
var
csharpGenericName
=
genericName
as
GenericNameSyntax
;
return
csharpGenericName
!=
null
?
csharpGenericName
.
Identifier
:
default
(
SyntaxToken
);
}
public
SyntaxNode
GetNameOfAttribut
e
(
SyntaxNode
node
)
public
bool
IsUsingDirectiveNam
e
(
SyntaxNode
node
)
{
return
((
AttributeSyntax
)
node
).
Name
;
return
node
.
IsParentKind
(
SyntaxKind
.
UsingDirective
)
&&
((
UsingDirectiveSyntax
)
node
.
Parent
).
Name
==
node
;
}
public
bool
Is
Attribute
(
SyntaxNode
node
)
public
bool
Is
ForEachStatement
(
SyntaxNode
node
)
{
return
node
is
Attribute
Syntax
;
return
node
is
ForEachStatement
Syntax
;
}
public
bool
Is
AttributeNamedArgumentIdentifier
(
SyntaxNode
node
)
public
bool
Is
LockStatement
(
SyntaxNode
node
)
{
var
identifier
=
node
as
IdentifierNameSyntax
;
return
identifier
.
IsAttributeNamedArgumentIdentifier
();
return
node
is
LockStatementSyntax
;
}
public
SyntaxNode
GetContainingTypeDeclaration
(
SyntaxNode
root
,
int
position
)
{
if
(
root
==
null
)
{
throw
new
ArgumentNullException
(
nameof
(
root
));
}
public
bool
IsUsingStatement
(
SyntaxNode
node
)
=>
node
.
Kind
()
==
SyntaxKind
.
UsingStatement
;
if
(
position
<
0
||
position
>
root
.
Span
.
End
)
{
throw
new
ArgumentOutOfRangeException
(
nameof
(
position
));
}
public
bool
IsReturnStatement
(
SyntaxNode
node
)
=>
node
.
Kind
()
==
SyntaxKind
.
ReturnStatement
;
return
root
.
FindToken
(
position
)
.
GetAncestors
<
SyntaxNode
>()
.
FirstOrDefault
(
n
=>
n
is
BaseTypeDeclarationSyntax
||
n
is
DelegateDeclarationSyntax
);
}
public
SyntaxNode
GetExpressionOfReturnStatement
(
SyntaxNode
node
)
=>
(
node
as
ReturnStatementSyntax
)?.
Expression
;
public
SyntaxNode
GetContainingVariableDeclaratorOfFieldDeclaration
(
SyntaxNode
node
)
public
bool
IsThisConstructorInitializer
(
SyntaxToken
token
)
{
throw
ExceptionUtilities
.
Unreachable
;
return
token
.
Parent
.
IsKind
(
SyntaxKind
.
ThisConstructorInitializer
)
&&
((
ConstructorInitializerSyntax
)
token
.
Parent
).
ThisOrBaseKeyword
==
token
;
}
public
SyntaxToken
FindTokenOnLeftOfPosition
(
SyntaxNode
node
,
int
position
,
bool
includeSkipped
,
bool
includeDirectives
,
bool
includeDocumentationComments
)
public
bool
IsBaseConstructorInitializer
(
SyntaxToken
token
)
{
return
node
.
FindTokenOnLeftOfPosition
(
position
,
includeSkipped
,
includeDirectives
,
includeDocumentationComments
);
return
token
.
Parent
.
IsKind
(
SyntaxKind
.
BaseConstructorInitializer
)
&&
((
ConstructorInitializerSyntax
)
token
.
Parent
).
ThisOrBaseKeyword
==
token
;
}
public
SyntaxToken
FindTokenOnRightOfPosition
(
SyntaxNode
node
,
int
position
,
bool
includeSkipped
,
bool
includeDirectives
,
bool
includeDocumentationComments
)
{
return
node
.
FindTokenOnRightOfPosition
(
position
,
includeSkipped
,
includeDirectives
,
includeDocumentationComments
);
}
public
bool
IsQueryExpression
(
SyntaxNode
node
)
=>
node
.
Kind
()
==
SyntaxKind
.
QueryExpression
;
public
bool
IsObjectCreationExpression
(
SyntaxNode
node
)
{
return
node
is
ObjectCreationExpressionSyntax
;
}
public
bool
IsThrowExpression
(
SyntaxNode
node
)
=>
node
.
Kind
()
==
SyntaxKind
.
ThrowExpression
;
public
bool
IsObjectInitializerNamedAssignmentIdentifier
(
SyntaxNode
node
)
public
bool
IsPredefinedType
(
SyntaxToken
token
)
=>
TryGetPredefinedType
(
token
,
out
var
actualType
)
&&
actualType
!=
PredefinedType
.
None
;
public
bool
IsPredefinedType
(
SyntaxToken
token
,
PredefinedType
type
)
=>
TryGetPredefinedType
(
token
,
out
var
actualType
)
&&
actualType
==
type
;
public
bool
TryGetPredefinedType
(
SyntaxToken
token
,
out
PredefinedType
type
)
{
return
IsObjectInitializerNamedAssignmentIdentifier
(
node
,
out
var
unused
);
type
=
GetPredefinedType
(
token
);
return
type
!=
PredefinedType
.
None
;
}
public
bool
IsObjectInitializerNamedAssignmentIdentifier
(
SyntaxNode
node
,
out
SyntaxNode
initializedInstance
)
private
PredefinedType
GetPredefinedType
(
SyntaxToken
token
)
{
initializedInstance
=
null
;
var
identifier
=
node
as
IdentifierNameSyntax
;
if
(
identifier
!=
null
&&
identifier
.
IsLeftSideOfAssignExpression
()
&&
identifier
.
Parent
.
IsParentKind
(
SyntaxKind
.
ObjectInitializerExpression
))
switch
((
SyntaxKind
)
token
.
RawKind
)
{
var
objectInitializer
=
identifier
.
Parent
.
Parent
;
if
(
objectInitializer
.
IsParentKind
(
SyntaxKind
.
ObjectCreationExpression
))
{
initializedInstance
=
objectInitializer
.
Parent
;
return
true
;
}
else
if
(
objectInitializer
.
IsParentKind
(
SyntaxKind
.
SimpleAssignmentExpression
))
{
initializedInstance
=
((
AssignmentExpressionSyntax
)
objectInitializer
.
Parent
).
Left
;
return
true
;
}
case
SyntaxKind
.
BoolKeyword
:
return
PredefinedType
.
Boolean
;
case
SyntaxKind
.
ByteKeyword
:
return
PredefinedType
.
Byte
;
case
SyntaxKind
.
SByteKeyword
:
return
PredefinedType
.
SByte
;
case
SyntaxKind
.
IntKeyword
:
return
PredefinedType
.
Int32
;
case
SyntaxKind
.
UIntKeyword
:
return
PredefinedType
.
UInt32
;
case
SyntaxKind
.
ShortKeyword
:
return
PredefinedType
.
Int16
;
case
SyntaxKind
.
UShortKeyword
:
return
PredefinedType
.
UInt16
;
case
SyntaxKind
.
LongKeyword
:
return
PredefinedType
.
Int64
;
case
SyntaxKind
.
ULongKeyword
:
return
PredefinedType
.
UInt64
;
case
SyntaxKind
.
FloatKeyword
:
return
PredefinedType
.
Single
;
case
SyntaxKind
.
DoubleKeyword
:
return
PredefinedType
.
Double
;
case
SyntaxKind
.
DecimalKeyword
:
return
PredefinedType
.
Decimal
;
case
SyntaxKind
.
StringKeyword
:
return
PredefinedType
.
String
;
case
SyntaxKind
.
CharKeyword
:
return
PredefinedType
.
Char
;
case
SyntaxKind
.
ObjectKeyword
:
return
PredefinedType
.
Object
;
case
SyntaxKind
.
VoidKeyword
:
return
PredefinedType
.
Void
;
default
:
return
PredefinedType
.
None
;
}
return
false
;
}
public
bool
Is
ElementAccessExpression
(
SyntaxNode
node
)
public
bool
Is
PredefinedOperator
(
SyntaxToken
token
)
{
return
node
.
Kind
()
==
SyntaxKind
.
ElementAccessExpression
;
return
TryGetPredefinedOperator
(
token
,
out
var
actualOperator
)
&&
actualOperator
!=
PredefinedOperator
.
None
;
}
public
SyntaxNode
ConvertToSingleLine
(
SyntaxNode
node
,
bool
useElasticTrivia
=
false
)
=>
node
.
ConvertToSingleLine
(
useElasticTrivia
);
public
SyntaxToken
ToIdentifierToken
(
string
name
)
public
bool
IsPredefinedOperator
(
SyntaxToken
token
,
PredefinedOperator
op
)
{
return
name
.
ToIdentifierToken
()
;
return
TryGetPredefinedOperator
(
token
,
out
var
actualOperator
)
&&
actualOperator
==
op
;
}
public
SyntaxNode
Parenthesize
(
SyntaxNode
expression
,
bool
includeElasticTrivia
)
public
bool
TryGetPredefinedOperator
(
SyntaxToken
token
,
out
PredefinedOperator
op
)
{
return
((
ExpressionSyntax
)
expression
).
Parenthesize
(
includeElasticTrivia
);
op
=
GetPredefinedOperator
(
token
);
return
op
!=
PredefinedOperator
.
None
;
}
p
ublic
bool
IsIndexerMemberCRef
(
SyntaxNode
node
)
p
rivate
PredefinedOperator
GetPredefinedOperator
(
SyntaxToken
token
)
{
return
node
.
Kind
()
==
SyntaxKind
.
IndexerMemberCref
;
}
switch
((
SyntaxKind
)
token
.
RawKind
)
{
case
SyntaxKind
.
PlusToken
:
case
SyntaxKind
.
PlusEqualsToken
:
return
PredefinedOperator
.
Addition
;
public
SyntaxNode
GetContainingMemberDeclaration
(
SyntaxNode
root
,
int
position
,
bool
useFullSpan
=
true
)
{
Contract
.
ThrowIfNull
(
root
,
"root"
);
Contract
.
ThrowIfTrue
(
position
<
0
||
position
>
root
.
FullSpan
.
End
,
"position"
);
case
SyntaxKind
.
MinusToken
:
case
SyntaxKind
.
MinusEqualsToken
:
return
PredefinedOperator
.
Subtraction
;
var
end
=
root
.
FullSpan
.
End
;
if
(
end
==
0
)
{
// empty file
return
null
;
}
case
SyntaxKind
.
AmpersandToken
:
case
SyntaxKind
.
AmpersandEqualsToken
:
return
PredefinedOperator
.
BitwiseAnd
;
// make sure position doesn't touch end of root
position
=
Math
.
Min
(
position
,
end
-
1
);
case
SyntaxKind
.
BarToken
:
case
SyntaxKind
.
BarEqualsToken
:
return
PredefinedOperator
.
BitwiseOr
;
var
node
=
root
.
FindToken
(
position
).
Parent
;
while
(
node
!=
null
)
{
if
(
useFullSpan
||
node
.
Span
.
Contains
(
position
))
{
var
kind
=
node
.
Kind
();
if
((
kind
!=
SyntaxKind
.
GlobalStatement
)
&&
(
kind
!=
SyntaxKind
.
IncompleteMember
)
&&
(
node
is
MemberDeclarationSyntax
))
{
return
node
;
}
}
case
SyntaxKind
.
MinusMinusToken
:
return
PredefinedOperator
.
Decrement
;
node
=
node
.
Parent
;
}
case
SyntaxKind
.
PlusPlusToken
:
return
PredefinedOperator
.
Increment
;
return
null
;
}
case
SyntaxKind
.
SlashToken
:
case
SyntaxKind
.
SlashEqualsToken
:
return
PredefinedOperator
.
Division
;
public
bool
IsMethodLevelMember
(
SyntaxNode
node
)
{
return
node
is
BaseMethodDeclarationSyntax
||
node
is
BasePropertyDeclarationSyntax
||
node
is
EnumMemberDeclarationSyntax
||
node
is
BaseFieldDeclarationSyntax
;
}
case
SyntaxKind
.
EqualsEqualsToken
:
return
PredefinedOperator
.
Equality
;
public
bool
IsTopLevelNodeWithMembers
(
SyntaxNode
node
)
{
return
node
is
NamespaceDeclarationSyntax
||
node
is
TypeDeclarationSyntax
||
node
is
EnumDeclarationSyntax
;
}
case
SyntaxKind
.
CaretToken
:
case
SyntaxKind
.
CaretEqualsToken
:
return
PredefinedOperator
.
ExclusiveOr
;
public
bool
TryGetDeclaredSymbolInfo
(
Project
project
,
SyntaxNode
node
,
out
DeclaredSymbolInfo
declaredSymbolInfo
)
{
switch
(
node
.
Kind
())
{
case
SyntaxKind
.
ClassDeclaration
:
var
classDecl
=
(
ClassDeclarationSyntax
)
node
;
declaredSymbolInfo
=
new
DeclaredSymbolInfo
(
project
,
classDecl
.
Identifier
.
ValueText
,
GetTypeParameterSuffix
(
classDecl
.
TypeParameterList
),
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
DeclaredSymbolInfoKind
.
Class
,
GetAccessibility
(
classDecl
,
classDecl
.
Modifiers
),
classDecl
.
Identifier
.
Span
,
GetInheritanceNames
(
project
,
classDecl
.
BaseList
));
return
true
;
case
SyntaxKind
.
ConstructorDeclaration
:
var
ctorDecl
=
(
ConstructorDeclarationSyntax
)
node
;
declaredSymbolInfo
=
new
DeclaredSymbolInfo
(
project
,
ctorDecl
.
Identifier
.
ValueText
,
GetConstructorSuffix
(
ctorDecl
),
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
DeclaredSymbolInfoKind
.
Constructor
,
GetAccessibility
(
ctorDecl
,
ctorDecl
.
Modifiers
),
ctorDecl
.
Identifier
.
Span
,
inheritanceNames
:
ImmutableArray
<
string
>.
Empty
,
parameterCount
:
ctorDecl
.
ParameterList
?.
Parameters
.
Count
??
0
);
return
true
;
case
SyntaxKind
.
DelegateDeclaration
:
var
delegateDecl
=
(
DelegateDeclarationSyntax
)
node
;
declaredSymbolInfo
=
new
DeclaredSymbolInfo
(
project
,
delegateDecl
.
Identifier
.
ValueText
,
GetTypeParameterSuffix
(
delegateDecl
.
TypeParameterList
),
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
DeclaredSymbolInfoKind
.
Delegate
,
GetAccessibility
(
delegateDecl
,
delegateDecl
.
Modifiers
),
delegateDecl
.
Identifier
.
Span
,
inheritanceNames
:
ImmutableArray
<
string
>.
Empty
);
return
true
;
case
SyntaxKind
.
EnumDeclaration
:
var
enumDecl
=
(
EnumDeclarationSyntax
)
node
;
declaredSymbolInfo
=
new
DeclaredSymbolInfo
(
project
,
enumDecl
.
Identifier
.
ValueText
,
null
,
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
DeclaredSymbolInfoKind
.
Enum
,
GetAccessibility
(
enumDecl
,
enumDecl
.
Modifiers
),
enumDecl
.
Identifier
.
Span
,
inheritanceNames
:
ImmutableArray
<
string
>.
Empty
);
return
true
;
case
SyntaxKind
.
EnumMemberDeclaration
:
var
enumMember
=
(
EnumMemberDeclarationSyntax
)
node
;
declaredSymbolInfo
=
new
DeclaredSymbolInfo
(
project
,
enumMember
.
Identifier
.
ValueText
,
null
,
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
DeclaredSymbolInfoKind
.
EnumMember
,
Accessibility
.
Public
,
enumMember
.
Identifier
.
Span
,
inheritanceNames
:
ImmutableArray
<
string
>.
Empty
);
return
true
;
case
SyntaxKind
.
EventDeclaration
:
var
eventDecl
=
(
EventDeclarationSyntax
)
node
;
declaredSymbolInfo
=
new
DeclaredSymbolInfo
(
project
,
eventDecl
.
Identifier
.
ValueText
,
null
,
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
DeclaredSymbolInfoKind
.
Event
,
GetAccessibility
(
eventDecl
,
eventDecl
.
Modifiers
),
eventDecl
.
Identifier
.
Span
,
inheritanceNames
:
ImmutableArray
<
string
>.
Empty
);
return
true
;
case
SyntaxKind
.
IndexerDeclaration
:
var
indexerDecl
=
(
IndexerDeclarationSyntax
)
node
;
declaredSymbolInfo
=
new
DeclaredSymbolInfo
(
project
,
"this"
,
GetIndexerSuffix
(
indexerDecl
),
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
DeclaredSymbolInfoKind
.
Indexer
,
GetAccessibility
(
indexerDecl
,
indexerDecl
.
Modifiers
),
indexerDecl
.
ThisKeyword
.
Span
,
inheritanceNames
:
ImmutableArray
<
string
>.
Empty
);
return
true
;
case
SyntaxKind
.
InterfaceDeclaration
:
var
interfaceDecl
=
(
InterfaceDeclarationSyntax
)
node
;
declaredSymbolInfo
=
new
DeclaredSymbolInfo
(
project
,
interfaceDecl
.
Identifier
.
ValueText
,
GetTypeParameterSuffix
(
interfaceDecl
.
TypeParameterList
),
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
DeclaredSymbolInfoKind
.
Interface
,
GetAccessibility
(
interfaceDecl
,
interfaceDecl
.
Modifiers
),
interfaceDecl
.
Identifier
.
Span
,
GetInheritanceNames
(
project
,
interfaceDecl
.
BaseList
));
return
true
;
case
SyntaxKind
.
MethodDeclaration
:
var
method
=
(
MethodDeclarationSyntax
)
node
;
declaredSymbolInfo
=
new
DeclaredSymbolInfo
(
project
,
method
.
Identifier
.
ValueText
,
GetMethodSuffix
(
method
),
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
IsExtensionMethod
(
method
)
?
DeclaredSymbolInfoKind
.
ExtensionMethod
:
DeclaredSymbolInfoKind
.
Method
,
GetAccessibility
(
method
,
method
.
Modifiers
),
method
.
Identifier
.
Span
,
inheritanceNames
:
ImmutableArray
<
string
>.
Empty
,
parameterCount
:
method
.
ParameterList
?.
Parameters
.
Count
??
0
,
typeParameterCount
:
method
.
TypeParameterList
?.
Parameters
.
Count
??
0
);
return
true
;
case
SyntaxKind
.
PropertyDeclaration
:
var
property
=
(
PropertyDeclarationSyntax
)
node
;
declaredSymbolInfo
=
new
DeclaredSymbolInfo
(
project
,
property
.
Identifier
.
ValueText
,
null
,
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
DeclaredSymbolInfoKind
.
Property
,
GetAccessibility
(
property
,
property
.
Modifiers
),
property
.
Identifier
.
Span
,
inheritanceNames
:
ImmutableArray
<
string
>.
Empty
);
return
true
;
case
SyntaxKind
.
StructDeclaration
:
var
structDecl
=
(
StructDeclarationSyntax
)
node
;
declaredSymbolInfo
=
new
DeclaredSymbolInfo
(
project
,
structDecl
.
Identifier
.
ValueText
,
GetTypeParameterSuffix
(
structDecl
.
TypeParameterList
),
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
DeclaredSymbolInfoKind
.
Struct
,
GetAccessibility
(
structDecl
,
structDecl
.
Modifiers
),
structDecl
.
Identifier
.
Span
,
GetInheritanceNames
(
project
,
structDecl
.
BaseList
));
return
true
;
case
SyntaxKind
.
VariableDeclarator
:
// could either be part of a field declaration or an event field declaration
var
variableDeclarator
=
(
VariableDeclaratorSyntax
)
node
;
var
variableDeclaration
=
variableDeclarator
.
Parent
as
VariableDeclarationSyntax
;
var
fieldDeclaration
=
variableDeclaration
?.
Parent
as
BaseFieldDeclarationSyntax
;
if
(
fieldDeclaration
!=
null
)
{
var
kind
=
fieldDeclaration
is
EventFieldDeclarationSyntax
?
DeclaredSymbolInfoKind
.
Event
:
fieldDeclaration
.
Modifiers
.
Any
(
m
=>
m
.
Kind
()
==
SyntaxKind
.
ConstKeyword
)
?
DeclaredSymbolInfoKind
.
Constant
:
DeclaredSymbolInfoKind
.
Field
;
case
SyntaxKind
.
GreaterThanToken
:
return
PredefinedOperator
.
GreaterThan
;
case
SyntaxKind
.
GreaterThanEqualsToken
:
return
PredefinedOperator
.
GreaterThanOrEqual
;
case
SyntaxKind
.
ExclamationEqualsToken
:
return
PredefinedOperator
.
Inequality
;
case
SyntaxKind
.
LessThanLessThanToken
:
case
SyntaxKind
.
LessThanLessThanEqualsToken
:
return
PredefinedOperator
.
LeftShift
;
case
SyntaxKind
.
LessThanEqualsToken
:
return
PredefinedOperator
.
LessThanOrEqual
;
case
SyntaxKind
.
AsteriskToken
:
case
SyntaxKind
.
AsteriskEqualsToken
:
return
PredefinedOperator
.
Multiplication
;
case
SyntaxKind
.
PercentToken
:
case
SyntaxKind
.
PercentEqualsToken
:
return
PredefinedOperator
.
Modulus
;
declaredSymbolInfo
=
new
DeclaredSymbolInfo
(
project
,
variableDeclarator
.
Identifier
.
ValueText
,
null
,
GetContainerDisplayName
(
fieldDeclaration
.
Parent
),
GetFullyQualifiedContainerName
(
fieldDeclaration
.
Parent
),
kind
,
GetAccessibility
(
fieldDeclaration
,
fieldDeclaration
.
Modifiers
),
variableDeclarator
.
Identifier
.
Span
,
inheritanceNames
:
ImmutableArray
<
string
>.
Empty
);
return
true
;
}
case
SyntaxKind
.
ExclamationToken
:
case
SyntaxKind
.
TildeToken
:
return
PredefinedOperator
.
Complement
;
break
;
case
SyntaxKind
.
GreaterThanGreaterThanToken
:
case
SyntaxKind
.
GreaterThanGreaterThanEqualsToken
:
return
PredefinedOperator
.
RightShift
;
}
declaredSymbolInfo
=
default
(
DeclaredSymbolInfo
);
return
false
;
return
PredefinedOperator
.
None
;
}
p
rivate
string
GetConstructorSuffix
(
ConstructorDeclarationSyntax
constructor
)
=>
constructor
.
Modifiers
.
Any
(
SyntaxKind
.
StaticKeyword
)
?
".static "
+
constructor
.
Identifier
+
"()"
:
GetSuffix
(
'('
,
')'
,
constructor
.
ParameterList
.
Parameters
);
p
ublic
string
GetText
(
int
kind
)
{
return
SyntaxFacts
.
GetText
((
SyntaxKind
)
kind
);
}
private
string
GetMethodSuffix
(
MethodDeclarationSyntax
method
)
=>
GetTypeParameterSuffix
(
method
.
TypeParameterList
)
+
GetSuffix
(
'('
,
')'
,
method
.
ParameterList
.
Parameters
);
public
bool
IsIdentifierStartCharacter
(
char
c
)
{
return
SyntaxFacts
.
IsIdentifierStartCharacter
(
c
);
}
private
string
GetIndexerSuffix
(
IndexerDeclarationSyntax
indexer
)
=>
GetSuffix
(
'['
,
']'
,
indexer
.
ParameterList
.
Parameters
);
public
bool
IsIdentifierPartCharacter
(
char
c
)
{
return
SyntaxFacts
.
IsIdentifierPartCharacter
(
c
);
}
p
rivate
string
GetTypeParameterSuffix
(
TypeParameterListSyntax
typeParameterList
)
p
ublic
bool
IsIdentifierEscapeCharacter
(
char
c
)
{
if
(
typeParameterList
==
null
)
return
c
==
'@'
;
}
public
bool
IsValidIdentifier
(
string
identifier
)
{
var
token
=
SyntaxFactory
.
ParseToken
(
identifier
);
return
IsIdentifier
(
token
)
&&
!
token
.
ContainsDiagnostics
&&
token
.
ToString
().
Length
==
identifier
.
Length
;
}
public
bool
IsVerbatimIdentifier
(
string
identifier
)
{
var
token
=
SyntaxFactory
.
ParseToken
(
identifier
);
return
IsIdentifier
(
token
)
&&
!
token
.
ContainsDiagnostics
&&
token
.
ToString
().
Length
==
identifier
.
Length
&&
token
.
IsVerbatimIdentifier
();
}
public
bool
IsTypeCharacter
(
char
c
)
{
return
false
;
}
public
bool
IsStartOfUnicodeEscapeSequence
(
char
c
)
{
return
c
==
'\\'
;
}
public
bool
IsLiteral
(
SyntaxToken
token
)
{
switch
(
token
.
Kind
())
{
return
null
;
case
SyntaxKind
.
NumericLiteralToken
:
case
SyntaxKind
.
CharacterLiteralToken
:
case
SyntaxKind
.
StringLiteralToken
:
case
SyntaxKind
.
NullKeyword
:
case
SyntaxKind
.
TrueKeyword
:
case
SyntaxKind
.
FalseKeyword
:
case
SyntaxKind
.
InterpolatedStringStartToken
:
case
SyntaxKind
.
InterpolatedStringEndToken
:
case
SyntaxKind
.
InterpolatedVerbatimStringStartToken
:
case
SyntaxKind
.
InterpolatedStringTextToken
:
return
true
;
}
var
pooledBuilder
=
PooledStringBuilder
.
GetInstance
();
return
false
;
}
var
builder
=
pooledBuilder
.
Builder
;
builder
.
Append
(
'<'
);
public
bool
IsStringLiteralOrInterpolatedStringLiteral
(
SyntaxToken
token
)
{
return
token
.
IsKind
(
SyntaxKind
.
StringLiteralToken
,
SyntaxKind
.
InterpolatedStringTextToken
);
}
var
first
=
true
;
foreach
(
var
parameter
in
typeParameterList
.
Parameters
)
public
bool
IsNumericLiteralExpression
(
SyntaxNode
node
)
{
return
node
?.
IsKind
(
SyntaxKind
.
NumericLiteralExpression
)
==
true
;
}
public
bool
IsTypeNamedVarInVariableOrFieldDeclaration
(
SyntaxToken
token
,
SyntaxNode
parent
)
{
var
typedToken
=
token
;
var
typedParent
=
parent
;
if
(
typedParent
.
IsKind
(
SyntaxKind
.
IdentifierName
))
{
if
(!
first
)
TypeSyntax
declaredType
=
null
;
if
(
typedParent
.
IsParentKind
(
SyntaxKind
.
VariableDeclaration
))
{
builder
.
Append
(
", "
);
declaredType
=
((
VariableDeclarationSyntax
)
typedParent
.
Parent
).
Type
;
}
else
if
(
typedParent
.
IsParentKind
(
SyntaxKind
.
FieldDeclaration
))
{
declaredType
=
((
FieldDeclarationSyntax
)
typedParent
.
Parent
).
Declaration
.
Type
;
}
builder
.
Append
(
parameter
.
Identifier
.
Text
)
;
return
declaredType
==
typedParent
&&
typedToken
.
ValueText
==
"var"
;
}
builder
.
Append
(
'>'
);
return
pooledBuilder
.
ToStringAndFree
();
return
false
;
}
/// <summary>
/// Builds up the suffix to show for something with parameters in navigate-to.
/// While it would be nice to just use the compiler SymbolDisplay API for this,
/// it would be too expensive as it requires going back to Symbols (which requires
/// creating compilations, etc.) in a perf sensitive area.
///
/// So, instead, we just build a reasonable suffix using the pure syntax that a
/// user provided. That means that if they wrote "Method(System.Int32 i)" we'll
/// show that as "Method(System.Int32)" not "Method(int)". Given that this is
/// actually what the user wrote, and it saves us from ever having to go back to
/// symbols/compilations, this is well worth it, even if it does mean we have to
/// create our own 'symbol display' logic here.
/// </summary>
private
string
GetSuffix
(
char
openBrace
,
char
closeBrace
,
SeparatedSyntaxList
<
ParameterSyntax
>
parameters
)
public
bool
IsTypeNamedDynamic
(
SyntaxToken
token
,
SyntaxNode
parent
)
{
var
pooledBuilder
=
PooledStringBuilder
.
GetInstance
()
;
var
typedParent
=
parent
as
ExpressionSyntax
;
var
builder
=
pooledBuilder
.
Builder
;
builder
.
Append
(
openBrace
);
AppendParameters
(
parameters
,
builder
);
builder
.
Append
(
closeBrace
);
if
(
typedParent
!=
null
)
{
if
(
SyntaxFacts
.
IsInTypeOnlyContext
(
typedParent
)
&&
typedParent
.
IsKind
(
SyntaxKind
.
IdentifierName
)
&&
token
.
ValueText
==
"dynamic"
)
{
return
true
;
}
}
return
pooledBuilder
.
ToStringAndFree
()
;
return
false
;
}
p
rivate
void
AppendParameters
(
SeparatedSyntaxList
<
ParameterSyntax
>
parameters
,
StringBuilder
builder
)
p
ublic
bool
IsBindableToken
(
SyntaxToken
token
)
{
var
first
=
true
;
foreach
(
var
parameter
in
parameters
)
if
(
this
.
IsWord
(
token
)
||
this
.
IsLiteral
(
token
)
||
this
.
IsOperator
(
token
))
{
if
(!
first
)
switch
((
SyntaxKind
)
token
.
RawKind
)
{
builder
.
Append
(
", "
);
case
SyntaxKind
.
DelegateKeyword
:
case
SyntaxKind
.
VoidKeyword
:
return
false
;
}
foreach
(
var
modifier
in
parameter
.
Modifiers
)
{
builder
.
Append
(
modifier
.
Text
);
builder
.
Append
(
' '
);
}
return
true
;
}
return
false
;
}
public
bool
IsSimpleMemberAccessExpression
(
SyntaxNode
node
)
=>
(
node
as
MemberAccessExpressionSyntax
)?.
Kind
()
==
SyntaxKind
.
SimpleMemberAccessExpression
;
public
bool
IsConditionalMemberAccessExpression
(
SyntaxNode
node
)
=>
node
is
ConditionalAccessExpressionSyntax
;
public
bool
IsPointerMemberAccessExpression
(
SyntaxNode
node
)
=>
(
node
as
MemberAccessExpressionSyntax
)?.
Kind
()
==
SyntaxKind
.
PointerMemberAccessExpression
;
public
void
GetNameAndArityOfSimpleName
(
SyntaxNode
node
,
out
string
name
,
out
int
arity
)
{
name
=
null
;
arity
=
0
;
var
simpleName
=
node
as
SimpleNameSyntax
;
if
(
simpleName
!=
null
)
{
name
=
simpleName
.
Identifier
.
ValueText
;
arity
=
simpleName
.
Arity
;
}
}
public
SyntaxNode
GetTargetOfMemberBinding
(
SyntaxNode
node
)
=>
(
node
as
MemberBindingExpressionSyntax
).
GetParentConditionalAccessExpression
()?.
Expression
;
public
SyntaxNode
GetExpressionOfMemberAccessExpression
(
SyntaxNode
node
,
bool
allowImplicitTarget
)
=>
(
node
as
MemberAccessExpressionSyntax
)?.
Expression
;
public
SyntaxNode
GetExpressionOfConditionalAccessExpression
(
SyntaxNode
node
)
=>
(
node
as
ConditionalAccessExpressionSyntax
)?.
Expression
;
public
SyntaxNode
GetExpressionOfElementAccessExpression
(
SyntaxNode
node
)
=>
(
node
as
ElementAccessExpressionSyntax
)?.
Expression
;
public
SyntaxNode
GetArgumentListOfElementAccessExpression
(
SyntaxNode
node
)
=>
(
node
as
ElementAccessExpressionSyntax
)?.
ArgumentList
;
public
SyntaxNode
GetExpressionOfInterpolation
(
SyntaxNode
node
)
=>
(
node
as
InterpolationSyntax
)?.
Expression
;
public
bool
IsInStaticContext
(
SyntaxNode
node
)
{
return
node
.
IsInStaticContext
();
}
public
bool
IsInNamespaceOrTypeContext
(
SyntaxNode
node
)
{
return
SyntaxFacts
.
IsInNamespaceOrTypeContext
(
node
as
ExpressionSyntax
);
}
public
SyntaxNode
GetExpressionOfArgument
(
SyntaxNode
node
)
{
return
((
ArgumentSyntax
)
node
).
Expression
;
}
public
RefKind
GetRefKindOfArgument
(
SyntaxNode
node
)
=>
(
node
as
ArgumentSyntax
).
GetRefKind
();
public
bool
IsSimpleArgument
(
SyntaxNode
node
)
{
var
argument
=
(
ArgumentSyntax
)
node
;
return
argument
.
RefOrOutKeyword
.
Kind
()
==
SyntaxKind
.
None
&&
argument
.
NameColon
==
null
;
}
public
bool
IsInConstantContext
(
SyntaxNode
node
)
{
return
(
node
as
ExpressionSyntax
).
IsInConstantContext
();
}
public
bool
IsInConstructor
(
SyntaxNode
node
)
{
return
node
.
GetAncestor
<
ConstructorDeclarationSyntax
>()
!=
null
;
}
public
bool
IsUnsafeContext
(
SyntaxNode
node
)
{
return
node
.
IsUnsafeContext
();
}
if
(
parameter
.
Type
!=
null
)
{
AppendTokens
(
parameter
.
Type
,
builder
);
}
else
{
builder
.
Append
(
parameter
.
Identifier
.
Text
);
}
public
SyntaxNode
GetNameOfAttribute
(
SyntaxNode
node
)
{
return
((
AttributeSyntax
)
node
).
Name
;
}
first
=
false
;
}
public
bool
IsAttribute
(
SyntaxNode
node
)
{
return
node
is
AttributeSyntax
;
}
private
bool
IsExtensionMethod
(
MethodDeclarationSyntax
method
)
=>
method
.
ParameterList
.
Parameters
.
Count
>
0
&&
method
.
ParameterList
.
Parameters
[
0
].
Modifiers
.
Any
(
SyntaxKind
.
ThisKeyword
);
public
bool
IsAttributeNamedArgumentIdentifier
(
SyntaxNode
node
)
{
var
identifier
=
node
as
IdentifierNameSyntax
;
return
identifier
.
IsAttributeNamedArgumentIdentifier
();
}
p
rivate
Accessibility
GetAccessibility
(
SyntaxNode
node
,
SyntaxTokenList
modifiers
)
p
ublic
SyntaxNode
GetContainingTypeDeclaration
(
SyntaxNode
root
,
int
position
)
{
var
sawInternal
=
false
;
foreach
(
var
modifier
in
modifiers
)
if
(
root
==
null
)
{
switch
(
modifier
.
Kind
())
{
case
SyntaxKind
.
PublicKeyword
:
return
Accessibility
.
Public
;
case
SyntaxKind
.
PrivateKeyword
:
return
Accessibility
.
Private
;
case
SyntaxKind
.
ProtectedKeyword
:
return
Accessibility
.
Protected
;
case
SyntaxKind
.
InternalKeyword
:
sawInternal
=
true
;
continue
;
}
throw
new
ArgumentNullException
(
nameof
(
root
));
}
if
(
sawInternal
)
if
(
position
<
0
||
position
>
root
.
Span
.
End
)
{
return
Accessibility
.
Internal
;
throw
new
ArgumentOutOfRangeException
(
nameof
(
position
))
;
}
// No accessibility modifiers:
switch
(
node
.
Parent
.
Kind
())
{
case
SyntaxKind
.
ClassDeclaration
:
case
SyntaxKind
.
StructDeclaration
:
// Anything without modifiers is private if it's in a class/struct declaration.
return
Accessibility
.
Private
;
case
SyntaxKind
.
InterfaceDeclaration
:
// Anything without modifiers is public if it's in an interface declaration.
return
Accessibility
.
Public
;
case
SyntaxKind
.
CompilationUnit
:
// Things are private by default in script
if
(((
CSharpParseOptions
)
node
.
SyntaxTree
.
Options
).
Kind
==
SourceCodeKind
.
Script
)
{
return
Accessibility
.
Private
;
}
return
Accessibility
.
Internal
;
default
:
// Otherwise it's internal
return
Accessibility
.
Internal
;
}
return
root
.
FindToken
(
position
)
.
GetAncestors
<
SyntaxNode
>()
.
FirstOrDefault
(
n
=>
n
is
BaseTypeDeclarationSyntax
||
n
is
DelegateDeclarationSyntax
);
}
p
rivate
ImmutableArray
<
string
>
GetInheritanceNames
(
Project
project
,
BaseListSyntax
baseList
)
p
ublic
SyntaxNode
GetContainingVariableDeclaratorOfFieldDeclaration
(
SyntaxNode
node
)
{
if
(
baseList
==
null
)
{
return
ImmutableArray
<
string
>.
Empty
;
}
var
builder
=
ArrayBuilder
<
string
>.
GetInstance
(
baseList
.
Types
.
Count
);
throw
ExceptionUtilities
.
Unreachable
;
}
// It's not sufficient to just store the textual names we see in the inheritance list
// of a type. For example if we have:
//
// using Y = X;
// ...
// using Z = Y;
// ...
// class C : Z
//
// It's insufficient to just state that 'C' derives from 'Z'. If we search for derived
// types from 'B' we won't examine 'C'. To solve this, we keep track of the aliasing
// that occurs in containing scopes. Then, when we're adding an inheritance name we
// walk the alias maps and we also add any names that these names alias to. In the
// above example we'd put Z, Y, and X in the inheritance names list for 'C'.
public
SyntaxToken
FindTokenOnLeftOfPosition
(
SyntaxNode
node
,
int
position
,
bool
includeSkipped
,
bool
includeDirectives
,
bool
includeDocumentationComments
)
{
return
node
.
FindTokenOnLeftOfPosition
(
position
,
includeSkipped
,
includeDirectives
,
includeDocumentationComments
);
}
// Each dictionary in this list is a mapping from alias name to the name of the thing
// it aliases. Then, each scope with alias mapping gets its own entry in this list.
// For the above example, we would produce: [{Z => Y}, {Y => X}]
var
aliasMaps
=
AllocateAliasMapList
();
try
{
AddAliasMaps
(
baseList
,
aliasMaps
);
public
SyntaxToken
FindTokenOnRightOfPosition
(
SyntaxNode
node
,
int
position
,
bool
includeSkipped
,
bool
includeDirectives
,
bool
includeDocumentationComments
)
{
return
node
.
FindTokenOnRightOfPosition
(
position
,
includeSkipped
,
includeDirectives
,
includeDocumentationComments
);
}
foreach
(
var
baseType
in
baseList
.
Types
)
{
AddInheritanceName
(
builder
,
baseType
.
Type
,
aliasMaps
)
;
}
public
bool
IsObjectCreationExpression
(
SyntaxNode
node
)
{
return
node
is
ObjectCreationExpressionSyntax
;
}
DeclaredSymbolInfo
.
Intern
(
project
,
builder
);
return
builder
.
ToImmutableAndFree
();
}
finally
{
FreeAliasMapList
(
aliasMaps
);
}
public
bool
IsObjectInitializerNamedAssignmentIdentifier
(
SyntaxNode
node
)
{
return
IsObjectInitializerNamedAssignmentIdentifier
(
node
,
out
var
unused
);
}
private
void
AddAliasMaps
(
SyntaxNode
node
,
List
<
Dictionary
<
string
,
string
>>
aliasMaps
)
public
bool
IsObjectInitializerNamedAssignmentIdentifier
(
SyntaxNode
node
,
out
SyntaxNode
initializedInstance
)
{
for
(
var
current
=
node
;
current
!=
null
;
current
=
current
.
Parent
)
initializedInstance
=
null
;
var
identifier
=
node
as
IdentifierNameSyntax
;
if
(
identifier
!=
null
&&
identifier
.
IsLeftSideOfAssignExpression
()
&&
identifier
.
Parent
.
IsParentKind
(
SyntaxKind
.
ObjectInitializerExpression
))
{
if
(
current
.
IsKind
(
SyntaxKind
.
NamespaceDeclaration
))
var
objectInitializer
=
identifier
.
Parent
.
Parent
;
if
(
objectInitializer
.
IsParentKind
(
SyntaxKind
.
ObjectCreationExpression
))
{
ProcessUsings
(
aliasMaps
,
((
NamespaceDeclarationSyntax
)
current
).
Usings
);
initializedInstance
=
objectInitializer
.
Parent
;
return
true
;
}
else
if
(
current
.
IsKind
(
SyntaxKind
.
CompilationUnit
))
else
if
(
objectInitializer
.
IsParentKind
(
SyntaxKind
.
SimpleAssignmentExpression
))
{
ProcessUsings
(
aliasMaps
,
((
CompilationUnitSyntax
)
current
).
Usings
);
initializedInstance
=
((
AssignmentExpressionSyntax
)
objectInitializer
.
Parent
).
Left
;
return
true
;
}
}
return
false
;
}
p
rivate
void
ProcessUsings
(
List
<
Dictionary
<
string
,
string
>>
aliasMaps
,
SyntaxList
<
UsingDirectiveSyntax
>
usings
)
p
ublic
bool
IsElementAccessExpression
(
SyntaxNode
node
)
{
Dictionary
<
string
,
string
>
aliasMap
=
null
;
return
node
.
Kind
()
==
SyntaxKind
.
ElementAccessExpression
;
}
foreach
(
var
usingDecl
in
usings
)
{
if
(
usingDecl
.
Alias
!=
null
)
{
var
mappedName
=
GetTypeName
(
usingDecl
.
Name
);
if
(
mappedName
!=
null
)
{
aliasMap
=
aliasMap
??
AllocateAliasMap
();
public
SyntaxNode
ConvertToSingleLine
(
SyntaxNode
node
,
bool
useElasticTrivia
=
false
)
=>
node
.
ConvertToSingleLine
(
useElasticTrivia
);
// If we have: using X = Foo, then we store a mapping from X -> Foo
// here. That way if we see a class that inherits from X we also state
// that it inherits from Foo as well.
aliasMap
[
usingDecl
.
Alias
.
Name
.
Identifier
.
ValueText
]
=
mappedName
;
}
}
}
public
SyntaxToken
ToIdentifierToken
(
string
name
)
{
return
name
.
ToIdentifierToken
();
}
if
(
aliasMap
!=
null
)
{
aliasMaps
.
Add
(
aliasMap
);
}
public
SyntaxNode
Parenthesize
(
SyntaxNode
expression
,
bool
includeElasticTrivia
)
{
return
((
ExpressionSyntax
)
expression
).
Parenthesize
(
includeElasticTrivia
);
}
private
void
AddInheritanceName
(
ArrayBuilder
<
string
>
builder
,
TypeSyntax
type
,
List
<
Dictionary
<
string
,
string
>>
aliasMaps
)
public
bool
IsIndexerMemberCRef
(
SyntaxNode
node
)
{
var
name
=
GetTypeName
(
type
);
if
(
name
!=
null
)
return
node
.
Kind
()
==
SyntaxKind
.
IndexerMemberCref
;
}
public
SyntaxNode
GetContainingMemberDeclaration
(
SyntaxNode
root
,
int
position
,
bool
useFullSpan
=
true
)
{
Contract
.
ThrowIfNull
(
root
,
"root"
);
Contract
.
ThrowIfTrue
(
position
<
0
||
position
>
root
.
FullSpan
.
End
,
"position"
);
var
end
=
root
.
FullSpan
.
End
;
if
(
end
==
0
)
{
// First, add the name that the typename that the type directly says it inherits from.
builder
.
Add
(
name
);
// empty file
return
null
;
}
// Now, walk the alias chain and add any names this alias may eventually map to.
var
currentName
=
name
;
foreach
(
var
aliasMap
in
aliasMaps
)
// make sure position doesn't touch end of root
position
=
Math
.
Min
(
position
,
end
-
1
);
var
node
=
root
.
FindToken
(
position
).
Parent
;
while
(
node
!=
null
)
{
if
(
useFullSpan
||
node
.
Span
.
Contains
(
position
))
{
if
(
aliasMap
.
TryGetValue
(
currentName
,
out
var
mappedName
))
var
kind
=
node
.
Kind
();
if
((
kind
!=
SyntaxKind
.
GlobalStatement
)
&&
(
kind
!=
SyntaxKind
.
IncompleteMember
)
&&
(
node
is
MemberDeclarationSyntax
))
{
// Looks like this could be an alias. Also include the name the alias points to
builder
.
Add
(
mappedName
);
// Keep on searching. An alias in an inner namespcae can refer to an
// alias in an outer namespace.
currentName
=
mappedName
;
return
node
;
}
}
}
}
private
string
GetTypeName
(
TypeSyntax
type
)
{
if
(
type
is
SimpleNameSyntax
simpleName
)
{
return
GetSimpleTypeName
(
simpleName
);
}
else
if
(
type
is
QualifiedNameSyntax
qualifiedName
)
{
return
GetSimpleTypeName
(
qualifiedName
.
Right
);
}
else
if
(
type
is
AliasQualifiedNameSyntax
aliasName
)
{
return
GetSimpleTypeName
(
aliasName
.
Name
);
node
=
node
.
Parent
;
}
return
null
;
}
private
static
string
GetSimpleTypeName
(
SimpleNameSyntax
name
)
=>
name
.
Identifier
.
ValueText
;
private
string
GetContainerDisplayName
(
SyntaxNode
node
)
public
bool
IsMethodLevelMember
(
SyntaxNode
node
)
{
return
GetDisplayName
(
node
,
DisplayNameOptions
.
IncludeTypeParameters
)
;
return
node
is
BaseMethodDeclarationSyntax
||
node
is
BasePropertyDeclarationSyntax
||
node
is
EnumMemberDeclarationSyntax
||
node
is
BaseFieldDeclarationSyntax
;
}
p
rivate
string
GetFullyQualifiedContainerName
(
SyntaxNode
node
)
p
ublic
bool
IsTopLevelNodeWithMembers
(
SyntaxNode
node
)
{
return
GetDisplayName
(
node
,
DisplayNameOptions
.
IncludeNamespaces
);
return
node
is
NamespaceDeclarationSyntax
||
node
is
TypeDeclarationSyntax
||
node
is
EnumDeclarationSyntax
;
}
private
const
string
dotToken
=
"."
;
...
...
src/Workspaces/Core/Portable/FindSymbols/SyntaxTree/SyntaxTreeIndex_Create.cs
浏览文件 @
d6aed247
...
...
@@ -5,6 +5,7 @@
using
System.Threading
;
using
System.Threading.Tasks
;
using
Microsoft.CodeAnalysis.ErrorReporting
;
using
Microsoft.CodeAnalysis.Host
;
using
Microsoft.CodeAnalysis.LanguageServices
;
using
Microsoft.CodeAnalysis.Shared.Extensions
;
using
Microsoft.CodeAnalysis.Shared.Utilities
;
...
...
@@ -12,6 +13,11 @@
namespace
Microsoft.CodeAnalysis.FindSymbols
{
internal
interface
IDeclaredSymbolInfoFactoryService
:
ILanguageService
{
bool
TryGetDeclaredSymbolInfo
(
Project
project
,
SyntaxNode
node
,
out
DeclaredSymbolInfo
declaredSymbolInfo
);
}
internal
sealed
partial
class
SyntaxTreeIndex
{
// The probability of getting a false positive when calling ContainsIdentifier.
...
...
@@ -28,6 +34,7 @@ internal sealed partial class SyntaxTreeIndex
{
var
project
=
document
.
Project
;
var
syntaxFacts
=
document
.
GetLanguageService
<
ISyntaxFactsService
>();
var
infoFactory
=
document
.
GetLanguageService
<
IDeclaredSymbolInfoFactoryService
>();
var
ignoreCase
=
syntaxFacts
!=
null
&&
!
syntaxFacts
.
IsCaseSensitive
;
var
isCaseSensitive
=
!
ignoreCase
;
...
...
@@ -68,6 +75,7 @@ internal sealed partial class SyntaxTreeIndex
containsQueryExpression
=
containsQueryExpression
||
syntaxFacts
.
IsQueryExpression
(
node
);
containsElementAccess
=
containsElementAccess
||
syntaxFacts
.
IsElementAccessExpression
(
node
);
containsIndexerMemberCref
=
containsIndexerMemberCref
||
syntaxFacts
.
IsIndexerMemberCRef
(
node
);
// We've received a number of error reports where DeclaredSymbolInfo.GetSymbolAsync() will
// crash because the document's syntax root doesn't contain the span of the node returned
// by TryGetDeclaredSymbolInfo(). There are two possibilities for this crash:
...
...
@@ -78,7 +86,7 @@ internal sealed partial class SyntaxTreeIndex
// the future then we know the problem lies in (2). If, however, the problem is really in
// TryGetDeclaredSymbolInfo, then this will at least prevent us from returning bad spans
// and will prevent the crash from occurring.
if
(
syntaxFacts
.
TryGetDeclaredSymbolInfo
(
project
,
node
,
out
var
declaredSymbolInfo
))
if
(
infoFactory
.
TryGetDeclaredSymbolInfo
(
project
,
node
,
out
var
declaredSymbolInfo
))
{
if
(
root
.
FullSpan
.
Contains
(
declaredSymbolInfo
.
Span
))
{
...
...
src/Workspaces/Core/Portable/LanguageServices/SyntaxFactsService/AbstractSyntaxFactsService.cs
浏览文件 @
d6aed247
...
...
@@ -2,19 +2,20 @@
using
System
;
using
System.Collections.Generic
;
using
Microsoft.CodeAnalysis.Shared.Extensions
;
using
System.Collections.Immutable
;
using
System.Diagnostics
;
using
System.Linq
;
using
System.Text
;
using
System.Threading
;
using
Microsoft.CodeAnalysis.FindSymbols
;
using
Microsoft.CodeAnalysis.Shared.Extensions
;
using
Microsoft.CodeAnalysis.Shared.Utilities
;
using
Microsoft.CodeAnalysis.Text
;
using
Roslyn.Utilities
;
using
System.Text
;
namespace
Microsoft.CodeAnalysis.LanguageServices
{
internal
abstract
class
Abstract
SyntaxFacts
Service
internal
abstract
class
Abstract
DeclaredSymbolInfoFactoryService
:
IDeclaredSymbolInfoFactory
Service
{
private
readonly
static
ObjectPool
<
List
<
Dictionary
<
string
,
string
>>>
s_aliasMapListPool
=
new
ObjectPool
<
List
<
Dictionary
<
string
,
string
>>>(()
=>
new
List
<
Dictionary
<
string
,
string
>>());
...
...
@@ -27,6 +28,53 @@ internal abstract class AbstractSyntaxFactsService
private
readonly
static
ObjectPool
<
Dictionary
<
string
,
string
>>
s_aliasMapPool
=
new
ObjectPool
<
Dictionary
<
string
,
string
>>(()
=>
new
Dictionary
<
string
,
string
>(
StringComparer
.
OrdinalIgnoreCase
));
protected
static
List
<
Dictionary
<
string
,
string
>>
AllocateAliasMapList
()
=>
s_aliasMapListPool
.
Allocate
();
protected
static
void
FreeAliasMapList
(
List
<
Dictionary
<
string
,
string
>>
list
)
{
if
(
list
!=
null
)
{
foreach
(
var
aliasMap
in
list
)
{
FreeAliasMap
(
aliasMap
);
}
s_aliasMapListPool
.
ClearAndFree
(
list
);
}
}
protected
static
void
FreeAliasMap
(
Dictionary
<
string
,
string
>
aliasMap
)
{
if
(
aliasMap
!=
null
)
{
s_aliasMapPool
.
ClearAndFree
(
aliasMap
);
}
}
protected
static
Dictionary
<
string
,
string
>
AllocateAliasMap
()
=>
s_aliasMapPool
.
Allocate
();
protected
static
void
AppendTokens
(
SyntaxNode
node
,
StringBuilder
builder
)
{
foreach
(
var
child
in
node
.
ChildNodesAndTokens
())
{
if
(
child
.
IsToken
)
{
builder
.
Append
(
child
.
AsToken
().
Text
);
}
else
{
AppendTokens
(
child
.
AsNode
(),
builder
);
}
}
}
public
abstract
bool
TryGetDeclaredSymbolInfo
(
Project
project
,
SyntaxNode
node
,
out
DeclaredSymbolInfo
declaredSymbolInfo
);
}
internal
abstract
class
AbstractSyntaxFactsService
{
private
readonly
static
ObjectPool
<
Stack
<(
SyntaxNodeOrToken
nodeOrToken
,
bool
leading
,
bool
trailing
)>>
s_stackPool
=
new
ObjectPool
<
Stack
<(
SyntaxNodeOrToken
nodeOrToken
,
bool
leading
,
bool
trailing
)>>(()
=>
new
Stack
<(
SyntaxNodeOrToken
nodeOrToken
,
bool
leading
,
bool
trailing
)>());
...
...
@@ -77,33 +125,6 @@ protected AbstractSyntaxFactsService()
public
abstract
bool
IsShebangDirectiveTrivia
(
SyntaxTrivia
trivia
);
public
abstract
bool
IsPreprocessorDirective
(
SyntaxTrivia
trivia
);
protected
static
List
<
Dictionary
<
string
,
string
>>
AllocateAliasMapList
()
=>
s_aliasMapListPool
.
Allocate
();
protected
static
void
FreeAliasMapList
(
List
<
Dictionary
<
string
,
string
>>
list
)
{
if
(
list
!=
null
)
{
foreach
(
var
aliasMap
in
list
)
{
FreeAliasMap
(
aliasMap
);
}
s_aliasMapListPool
.
ClearAndFree
(
list
);
}
}
protected
static
void
FreeAliasMap
(
Dictionary
<
string
,
string
>
aliasMap
)
{
if
(
aliasMap
!=
null
)
{
s_aliasMapPool
.
ClearAndFree
(
aliasMap
);
}
}
protected
static
Dictionary
<
string
,
string
>
AllocateAliasMap
()
=>
s_aliasMapPool
.
Allocate
();
public
bool
IsOnSingleLine
(
SyntaxNode
node
,
bool
fullSpan
)
{
// Use an actual Stack so we can write out deeply recursive structures without overflowing.
...
...
@@ -392,20 +413,5 @@ public string GetBannerText(SyntaxNode documentationCommentTriviaSyntax, Cancell
=>
DocumentationCommentService
.
GetBannerText
(
documentationCommentTriviaSyntax
,
cancellationToken
);
protected
abstract
IDocumentationCommentService
DocumentationCommentService
{
get
;
}
protected
static
void
AppendTokens
(
SyntaxNode
node
,
StringBuilder
builder
)
{
foreach
(
var
child
in
node
.
ChildNodesAndTokens
())
{
if
(
child
.
IsToken
)
{
builder
.
Append
(
child
.
AsToken
().
Text
);
}
else
{
AppendTokens
(
child
.
AsNode
(),
builder
);
}
}
}
}
}
\ No newline at end of file
src/Workspaces/Core/Portable/LanguageServices/SyntaxFactsService/ISyntaxFactsService.cs
浏览文件 @
d6aed247
...
...
@@ -4,7 +4,6 @@
using
System.Collections.Generic
;
using
System.Collections.Immutable
;
using
System.Threading
;
using
Microsoft.CodeAnalysis.FindSymbols
;
using
Microsoft.CodeAnalysis.Host
;
using
Microsoft.CodeAnalysis.Text
;
...
...
@@ -224,8 +223,6 @@ internal interface ISyntaxFactsService : ILanguageService
bool
AreEquivalent
(
SyntaxToken
token1
,
SyntaxToken
token2
);
bool
AreEquivalent
(
SyntaxNode
node1
,
SyntaxNode
node2
);
bool
TryGetDeclaredSymbolInfo
(
Project
project
,
SyntaxNode
node
,
out
DeclaredSymbolInfo
declaredSymbolInfo
);
string
GetDisplayName
(
SyntaxNode
node
,
DisplayNameOptions
options
,
string
rootNamespace
=
null
);
SyntaxNode
GetContainingTypeDeclaration
(
SyntaxNode
root
,
int
position
);
...
...
src/Workspaces/VisualBasic/Portable/LanguageServices/VisualBasicSyntaxFactsService.vb
浏览文件 @
d6aed247
...
...
@@ -16,1238 +16,1241 @@ Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports
Microsoft.CodeAnalysis.VisualBasic.SyntaxFacts
Namespace
Microsoft.CodeAnalysis.VisualBasic
<
ExportLanguageServiceFactory
(
GetType
(
ISyntaxFactsService
),
LanguageNames
.
VisualBasic
),
[
Shared
]
>
Friend
Class
VisualBasicSyntaxFactsServiceFactory
Implements
ILanguageServiceFactory
Public
Function
CreateLanguageService
(
languageServices
As
HostLanguageServices
)
As
ILanguageService
Implements
ILanguageServiceFactory
.
CreateLanguageService
Return
VisualBasicSyntaxFactsService
.
Instance
End
Function
End
Class
Friend
Class
VisualBasicSyntaxFactsService
Inherits
AbstractSyntaxFactsService
Implements
ISyntaxFactsService
Public
Shared
ReadOnly
Property
Instance
As
New
VisualBasicSyntaxFactsService
Private
Sub
New
()
End
Sub
Public
ReadOnly
Property
IsCaseSensitive
As
Boolean
Implements
ISyntaxFactsService
.
IsCaseSensitive
Get
Return
False
End
Get
End
Property
Public
ReadOnly
Property
StringComparer
As
StringComparer
Implements
ISyntaxFactsService
.
StringComparer
Get
Return
CaseInsensitiveComparison
.
Comparer
End
Get
End
Property
Protected
Overrides
ReadOnly
Property
DocumentationCommentService
As
IDocumentationCommentService
Get
Return
VisualBasicDocumentationCommentService
.
Instance
End
Get
End
Property
Public
Function
SupportsIndexingInitializer
(
options
As
ParseOptions
)
As
Boolean
Implements
ISyntaxFactsService
.
SupportsIndexingInitializer
Return
False
End
Function
Public
Function
SupportsThrowExpression
(
options
As
ParseOptions
)
As
Boolean
Implements
ISyntaxFactsService
.
SupportsThrowExpression
Return
False
End
Function
<
ExportLanguageService
(
GetType
(
IDeclaredSymbolInfoFactoryService
),
LanguageNames
.
VisualBasic
),
[
Shared
]
>
Friend
Class
VisualBasicDeclaredSymbolInfoFactoryService
Inherits
AbstractDeclaredSymbolInfoFactoryService
Public
Function
IsAwaitKeyword
(
token
As
SyntaxToken
)
As
Boolean
Implements
ISyntaxFactsService
.
IsAwaitKeyword
Return
token
.
Kind
=
SyntaxKind
.
AwaitKeyword
End
Function
Private
Function
GetInheritanceNames
(
project
As
Project
,
typeBlock
As
TypeBlockSyntax
)
As
ImmutableArray
(
Of
String
)
Dim
builder
=
ArrayBuilder
(
Of
String
).
GetInstance
()
Public
Function
IsIdentifier
(
token
As
SyntaxToken
)
As
Boolean
Implements
ISyntaxFactsService
.
IsIdentifier
Return
token
.
Kind
=
SyntaxKind
.
IdentifierToken
End
Function
Dim
aliasMap
=
GetAliasMap
(
typeBlock
)
Try
For
Each
inheritsStatement
In
typeBlock
.
Inherits
AddInheritanceNames
(
builder
,
inheritsStatement
.
Types
,
aliasMap
)
Next
Public
Function
IsGlobalNamespaceKeyword
(
token
As
SyntaxToken
)
As
Boolean
Implements
ISyntaxFactsService
.
IsGlobalNamespaceKeyword
Return
token
.
Kind
=
SyntaxKind
.
GlobalKeyword
End
Function
For
Each
implementsStatement
In
typeBlock
.
Implements
AddInheritanceNames
(
builder
,
implementsStatement
.
Types
,
aliasMap
)
Next
Public
Function
IsVerbatimIdentifier
(
token
As
SyntaxToken
)
As
Boolean
Implements
ISyntaxFactsService
.
IsVerbatimIdentifier
Return
False
DeclaredSymbolInfo
.
Intern
(
project
,
builder
)
Return
builder
.
ToImmutableAndFree
()
Finally
FreeAliasMap
(
aliasMap
)
End
Try
End
Function
Public
Function
IsOperator
(
token
As
SyntaxToken
)
As
Boolean
Implements
ISyntaxFactsService
.
IsOperator
Return
(
IsUnaryExpressionOperatorToken
(
CType
(
token
.
Kind
,
SyntaxKind
))
AndAlso
(
TypeOf
token
.
Parent
Is
UnaryExpressionSyntax
OrElse
TypeOf
token
.
Parent
Is
OperatorStatementSyntax
))
OrElse
(
IsBinaryExpressionOperatorToken
(
CType
(
token
.
Kind
,
SyntaxKind
))
AndAlso
(
TypeOf
token
.
Parent
Is
BinaryExpressionSyntax
OrElse
TypeOf
token
.
Parent
Is
OperatorStatementSyntax
))
End
Function
Private
Function
GetAliasMap
(
typeBlock
As
TypeBlockSyntax
)
As
Dictionary
(
Of
String
,
String
)
Dim
compilationUnit
=
typeBlock
.
SyntaxTree
.
GetCompilationUnitRoot
()
Public
Function
IsContextualKeyword
(
token
As
SyntaxToken
)
As
Boolean
Implements
ISyntaxFactsService
.
IsContextualKeyword
Return
token
.
IsContextualKeyword
()
End
Function
Dim
aliasMap
As
Dictionary
(
Of
String
,
String
)
=
Nothing
For
Each
import
In
compilationUnit
.
Imports
For
Each
clause
In
import
.
ImportsClauses
If
clause
.
IsKind
(
SyntaxKind
.
SimpleImportsClause
)
Then
Dim
simpleImport
=
DirectCast
(
clause
,
SimpleImportsClauseSyntax
)
If
simpleImport
.
Alias
IsNot
Nothing
Then
Dim
mappedName
=
GetTypeName
(
simpleImport
.
Name
)
If
mappedName
IsNot
Nothing
Then
aliasMap
=
If
(
aliasMap
,
AllocateAliasMap
())
aliasMap
(
simpleImport
.
Alias
.
Identifier
.
ValueText
)
=
mappedName
End
If
End
If
End
If
Next
Next
Public
Function
IsKeyword
(
token
As
SyntaxToken
)
As
Boolean
Implements
ISyntaxFactsService
.
IsKeyword
Return
token
.
IsKeyword
()
Return
aliasMap
End
Function
Public
Function
IsPreprocessorKeyword
(
token
As
SyntaxToken
)
As
Boolean
Implements
ISyntaxFactsService
.
IsPreprocessorKeyword
Return
token
.
IsPreprocessorKeyword
()
End
Function
Private
Sub
AddInheritanceNames
(
builder
As
ArrayBuilder
(
Of
String
),
types
As
SeparatedSyntaxList
(
Of
TypeSyntax
),
aliasMap
As
Dictionary
(
Of
String
,
String
))
Public
Function
IsHashToken
(
token
As
SyntaxToken
)
As
Boolean
Implements
ISyntaxFactsService
.
IsHashToken
Return
token
.
Kind
=
SyntaxKind
.
HashToken
End
Function
For
Each
typeSyntax
In
types
AddInheritanceName
(
builder
,
typeSyntax
,
aliasMap
)
Next
End
Sub
Public
Function
TryGetCorrespondingOpenBrace
(
token
As
SyntaxToken
,
ByRef
openBrace
As
SyntaxToken
)
As
Boolean
Implements
ISyntaxFactsService
.
TryGetCorrespondingOpenBrace
Private
Sub
AddInheritanceName
(
builder
As
ArrayBuilder
(
Of
String
),
typeSyntax
As
TypeSyntax
,
aliasMap
As
Dictionary
(
Of
String
,
String
))
Dim
name
=
GetTypeName
(
typeSyntax
)
If
name
IsNot
Nothing
Then
builder
.
Add
(
name
)
If
token
.
Kind
=
SyntaxKind
.
CloseBraceToken
Then
Dim
tuples
=
token
.
Parent
.
GetBraces
()
openBrace
=
tuples
.
Item1
Return
openBrace
.
Kind
=
SyntaxKind
.
OpenBraceToken
Dim
mappedName
As
String
=
Nothing
If
aliasMap
?
.
TryGetValue
(
name
,
mappedName
)
=
True
Then
' Looks Like this could be an alias. Also include the name the alias points to
builder
.
Add
(
mappedName
)
End
If
End
If
End
Sub
Return
False
End
Function
Public
Function
IsInInactiveRegion
(
syntaxTree
As
SyntaxTree
,
position
As
Integer
,
cancellationToken
As
CancellationToken
)
As
Boolean
Implements
ISyntaxFactsService
.
IsInInactiveRegion
Dim
vbTree
=
TryCast
(
syntaxTree
,
SyntaxTree
)
If
vbTree
Is
Nothing
Then
Return
False
Private
Function
GetTypeName
(
typeSyntax
As
TypeSyntax
)
As
String
If
TypeOf
typeSyntax
Is
SimpleNameSyntax
Then
Return
GetSimpleName
(
DirectCast
(
typeSyntax
,
SimpleNameSyntax
))
ElseIf
TypeOf
typeSyntax
Is
QualifiedNameSyntax
Then
Return
GetSimpleName
(
DirectCast
(
typeSyntax
,
QualifiedNameSyntax
).
Right
)
End
If
Return
vbTree
.
IsInInactiveRegion
(
position
,
cancellationToken
)
Return
Nothing
End
Function
Public
Function
IsInNonUserCode
(
syntaxTree
As
SyntaxTree
,
position
As
Integer
,
cancellationToken
As
CancellationToken
)
As
Boolean
Implements
ISyntaxFactsService
.
IsInNonUserCode
Dim
vbTree
=
TryCast
(
syntaxTree
,
SyntaxTree
)
If
vbTree
Is
Nothing
Then
Return
False
End
If
Return
vbTree
.
IsInNonUserCode
(
position
,
cancellationToken
)
Private
Function
GetSimpleName
(
simpleName
As
SimpleNameSyntax
)
As
String
Return
simpleName
.
Identifier
.
ValueText
End
Function
Public
Function
IsEntirelyWithinStringOrCharOrNumericLiteral
(
syntaxTree
As
SyntaxTree
,
position
As
Integer
,
cancellationToken
As
CancellationToken
)
As
Boolean
Implements
ISyntaxFactsService
.
IsEntirelyWithinStringOrCharOrNumericLiteral
Dim
vbTree
=
TryCast
(
syntaxTree
,
SyntaxTree
)
If
vbTree
Is
Nothing
Then
Return
False
End
If
Return
vbTree
.
IsEntirelyWithinStringOrCharOrNumericLiteral
(
position
,
cancellationToken
)
Private
Function
GetContainerDisplayName
(
node
As
SyntaxNode
)
As
String
Return
VisualBasicSyntaxFactsService
.
Instance
.
GetDisplayName
(
node
,
DisplayNameOptions
.
IncludeTypeParameters
)
End
Function
P
ublic
Function
IsDirective
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsDirective
Return
TypeOf
node
Is
DirectiveTriviaSyntax
P
rivate
Function
GetFullyQualifiedContainerName
(
node
As
SyntaxNode
)
As
String
Return
VisualBasicSyntaxFactsService
.
Instance
.
GetDisplayName
(
node
,
DisplayNameOptions
.
IncludeNamespaces
)
End
Function
Public
Function
TryGetExternalSourceInfo
(
node
As
SyntaxNode
,
ByRef
info
As
ExternalSourceInfo
)
As
Boolean
Implements
ISyntaxFactsService
.
TryGetExternalSourceInfo
Select
Case
node
.
Kind
Case
SyntaxKind
.
ExternalSourceDirectiveTrivia
info
=
New
ExternalSourceInfo
(
CInt
(
DirectCast
(
node
,
ExternalSourceDirectiveTriviaSyntax
).
LineStart
.
Value
),
False
)
Public
Overrides
Function
TryGetDeclaredSymbolInfo
(
project
As
Project
,
node
As
SyntaxNode
,
ByRef
declaredSymbolInfo
As
DeclaredSymbolInfo
)
As
Boolean
Select
Case
node
.
Kind
()
Case
SyntaxKind
.
ClassBlock
Dim
classDecl
=
CType
(
node
,
ClassBlockSyntax
)
declaredSymbolInfo
=
New
DeclaredSymbolInfo
(
project
,
classDecl
.
ClassStatement
.
Identifier
.
ValueText
,
GetTypeParameterSuffix
(
classDecl
.
ClassStatement
.
TypeParameterList
),
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
DeclaredSymbolInfoKind
.
Class
,
GetAccessibility
(
classDecl
,
classDecl
.
ClassStatement
.
Modifiers
),
classDecl
.
ClassStatement
.
Identifier
.
Span
,
GetInheritanceNames
(
project
,
classDecl
))
Return
True
Case
SyntaxKind
.
ConstructorBlock
Dim
constructor
=
CType
(
node
,
ConstructorBlockSyntax
)
Dim
typeBlock
=
TryCast
(
constructor
.
Parent
,
TypeBlockSyntax
)
If
typeBlock
IsNot
Nothing
Then
declaredSymbolInfo
=
New
DeclaredSymbolInfo
(
project
,
typeBlock
.
BlockStatement
.
Identifier
.
ValueText
,
GetConstructorSuffix
(
constructor
),
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
DeclaredSymbolInfoKind
.
Constructor
,
GetAccessibility
(
constructor
,
constructor
.
SubNewStatement
.
Modifiers
),
constructor
.
SubNewStatement
.
NewKeyword
.
Span
,
ImmutableArray
(
Of
String
).
Empty
,
parameterCount
:
=
If
(
constructor
.
SubNewStatement
.
ParameterList
?
.
Parameters
.
Count
,
0
))
Case
SyntaxKind
.
EndExternalSourceDirectiveTrivia
info
=
New
ExternalSourceInfo
(
Nothing
,
True
)
Return
True
End
If
Case
SyntaxKind
.
DelegateFunctionStatement
,
SyntaxKind
.
DelegateSubStatement
Dim
delegateDecl
=
CType
(
node
,
DelegateStatementSyntax
)
declaredSymbolInfo
=
New
DeclaredSymbolInfo
(
project
,
delegateDecl
.
Identifier
.
ValueText
,
GetTypeParameterSuffix
(
delegateDecl
.
TypeParameterList
),
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
DeclaredSymbolInfoKind
.
Delegate
,
GetAccessibility
(
delegateDecl
,
delegateDecl
.
Modifiers
),
delegateDecl
.
Identifier
.
Span
,
ImmutableArray
(
Of
String
).
Empty
)
Return
True
End
Select
Return
False
End
Function
Public
Function
IsObjectCreationExpressionType
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsObjectCreationExpressionType
Return
node
.
IsParentKind
(
SyntaxKind
.
ObjectCreationExpression
)
AndAlso
DirectCast
(
node
.
Parent
,
ObjectCreationExpressionSyntax
).
Type
Is
node
End
Function
Public
Function
IsAttributeName
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsAttributeName
Return
node
.
IsParentKind
(
SyntaxKind
.
Attribute
)
AndAlso
DirectCast
(
node
.
Parent
,
AttributeSyntax
).
Name
Is
node
End
Function
Public
Function
IsRightSideOfQualifiedName
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsRightSideOfQualifiedName
Dim
vbNode
=
TryCast
(
node
,
SimpleNameSyntax
)
Return
vbNode
IsNot
Nothing
AndAlso
vbNode
.
IsRightSideOfQualifiedName
()
End
Function
Public
Function
IsNameOfMemberAccessExpression
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsNameOfMemberAccessExpression
Dim
vbNode
=
TryCast
(
node
,
SimpleNameSyntax
)
Return
vbNode
IsNot
Nothing
AndAlso
vbNode
.
IsMemberAccessExpressionName
()
End
Function
Public
Function
IsConditionalMemberAccessExpression
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsConditionalMemberAccessExpression
Return
TypeOf
node
Is
ConditionalAccessExpressionSyntax
End
Function
Public
Function
IsInvocationExpression
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsInvocationExpression
Return
TypeOf
node
Is
InvocationExpressionSyntax
End
Function
Public
Function
IsAnonymousFunction
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsAnonymousFunction
Return
TypeOf
node
Is
LambdaExpressionSyntax
End
Function
Public
Function
IsGenericName
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsGenericName
Return
TypeOf
node
Is
GenericNameSyntax
End
Function
Public
Function
IsNamedParameter
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsNamedParameter
Return
node
.
CheckParent
(
Of
SimpleArgumentSyntax
)(
Function
(
p
)
p
.
IsNamed
AndAlso
p
.
NameColonEquals
.
Name
Is
node
)
End
Function
Public
Function
GetDefaultOfParameter
(
node
As
SyntaxNode
)
As
SyntaxNode
Implements
ISyntaxFactsService
.
GetDefaultOfParameter
Return
TryCast
(
node
,
ParameterSyntax
)
?
.
Default
End
Function
Case
SyntaxKind
.
EnumBlock
Dim
enumDecl
=
CType
(
node
,
EnumBlockSyntax
)
declaredSymbolInfo
=
New
DeclaredSymbolInfo
(
project
,
enumDecl
.
EnumStatement
.
Identifier
.
ValueText
,
Nothing
,
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
DeclaredSymbolInfoKind
.
Enum
,
GetAccessibility
(
enumDecl
,
enumDecl
.
EnumStatement
.
Modifiers
),
enumDecl
.
EnumStatement
.
Identifier
.
Span
,
ImmutableArray
(
Of
String
).
Empty
)
Return
True
Case
SyntaxKind
.
EnumMemberDeclaration
Dim
enumMember
=
CType
(
node
,
EnumMemberDeclarationSyntax
)
declaredSymbolInfo
=
New
DeclaredSymbolInfo
(
project
,
enumMember
.
Identifier
.
ValueText
,
Nothing
,
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
DeclaredSymbolInfoKind
.
EnumMember
,
Accessibility
.
Public
,
enumMember
.
Identifier
.
Span
,
ImmutableArray
(
Of
String
).
Empty
)
Return
True
Case
SyntaxKind
.
EventStatement
Dim
eventDecl
=
CType
(
node
,
EventStatementSyntax
)
Dim
statementOrBlock
=
If
(
TypeOf
node
.
Parent
Is
EventBlockSyntax
,
node
.
Parent
,
node
)
Dim
eventParent
=
statementOrBlock
.
Parent
declaredSymbolInfo
=
New
DeclaredSymbolInfo
(
project
,
eventDecl
.
Identifier
.
ValueText
,
Nothing
,
GetContainerDisplayName
(
eventParent
),
GetFullyQualifiedContainerName
(
eventParent
),
DeclaredSymbolInfoKind
.
Event
,
GetAccessibility
(
statementOrBlock
,
eventDecl
.
Modifiers
),
eventDecl
.
Identifier
.
Span
,
ImmutableArray
(
Of
String
).
Empty
)
Return
True
Case
SyntaxKind
.
FunctionBlock
,
SyntaxKind
.
SubBlock
Dim
funcDecl
=
CType
(
node
,
MethodBlockSyntax
)
declaredSymbolInfo
=
New
DeclaredSymbolInfo
(
project
,
funcDecl
.
SubOrFunctionStatement
.
Identifier
.
ValueText
,
GetMethodSuffix
(
funcDecl
),
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
DeclaredSymbolInfoKind
.
Method
,
GetAccessibility
(
node
,
funcDecl
.
SubOrFunctionStatement
.
Modifiers
),
funcDecl
.
SubOrFunctionStatement
.
Identifier
.
Span
,
ImmutableArray
(
Of
String
).
Empty
,
parameterCount
:
=
If
(
funcDecl
.
SubOrFunctionStatement
.
ParameterList
?
.
Parameters
.
Count
,
0
),
typeParameterCount
:
=
If
(
funcDecl
.
SubOrFunctionStatement
.
TypeParameterList
?
.
Parameters
.
Count
,
0
))
Return
True
Case
SyntaxKind
.
InterfaceBlock
Dim
interfaceDecl
=
CType
(
node
,
InterfaceBlockSyntax
)
declaredSymbolInfo
=
New
DeclaredSymbolInfo
(
project
,
interfaceDecl
.
InterfaceStatement
.
Identifier
.
ValueText
,
GetTypeParameterSuffix
(
interfaceDecl
.
InterfaceStatement
.
TypeParameterList
),
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
DeclaredSymbolInfoKind
.
Interface
,
GetAccessibility
(
interfaceDecl
,
interfaceDecl
.
InterfaceStatement
.
Modifiers
),
interfaceDecl
.
InterfaceStatement
.
Identifier
.
Span
,
GetInheritanceNames
(
project
,
interfaceDecl
))
Return
True
Case
SyntaxKind
.
ModifiedIdentifier
Dim
modifiedIdentifier
=
CType
(
node
,
ModifiedIdentifierSyntax
)
Dim
variableDeclarator
=
TryCast
(
modifiedIdentifier
.
Parent
,
VariableDeclaratorSyntax
)
Dim
fieldDecl
=
TryCast
(
variableDeclarator
?
.
Parent
,
FieldDeclarationSyntax
)
If
fieldDecl
IsNot
Nothing
Then
Dim
kind
=
If
(
fieldDecl
.
Modifiers
.
Any
(
Function
(
m
)
m
.
Kind
()
=
SyntaxKind
.
ConstKeyword
),
DeclaredSymbolInfoKind
.
Constant
,
DeclaredSymbolInfoKind
.
Field
)
declaredSymbolInfo
=
New
DeclaredSymbolInfo
(
project
,
modifiedIdentifier
.
Identifier
.
ValueText
,
Nothing
,
GetContainerDisplayName
(
fieldDecl
.
Parent
),
GetFullyQualifiedContainerName
(
fieldDecl
.
Parent
),
kind
,
GetAccessibility
(
fieldDecl
,
fieldDecl
.
Modifiers
),
modifiedIdentifier
.
Identifier
.
Span
,
ImmutableArray
(
Of
String
).
Empty
)
Return
True
End
If
Case
SyntaxKind
.
ModuleBlock
Dim
moduleDecl
=
CType
(
node
,
ModuleBlockSyntax
)
declaredSymbolInfo
=
New
DeclaredSymbolInfo
(
project
,
moduleDecl
.
ModuleStatement
.
Identifier
.
ValueText
,
GetTypeParameterSuffix
(
moduleDecl
.
ModuleStatement
.
TypeParameterList
),
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
DeclaredSymbolInfoKind
.
Module
,
GetAccessibility
(
moduleDecl
,
moduleDecl
.
ModuleStatement
.
Modifiers
),
moduleDecl
.
ModuleStatement
.
Identifier
.
Span
,
GetInheritanceNames
(
project
,
moduleDecl
))
Return
True
Case
SyntaxKind
.
PropertyStatement
Dim
propertyDecl
=
CType
(
node
,
PropertyStatementSyntax
)
Dim
statementOrBlock
=
If
(
TypeOf
node
.
Parent
Is
PropertyBlockSyntax
,
node
.
Parent
,
node
)
Dim
propertyParent
=
statementOrBlock
.
Parent
declaredSymbolInfo
=
New
DeclaredSymbolInfo
(
project
,
propertyDecl
.
Identifier
.
ValueText
,
GetPropertySuffix
(
propertyDecl
),
GetContainerDisplayName
(
propertyParent
),
GetFullyQualifiedContainerName
(
propertyParent
),
DeclaredSymbolInfoKind
.
Property
,
GetAccessibility
(
statementOrBlock
,
propertyDecl
.
Modifiers
),
propertyDecl
.
Identifier
.
Span
,
ImmutableArray
(
Of
String
).
Empty
)
Return
True
Case
SyntaxKind
.
StructureBlock
Dim
structDecl
=
CType
(
node
,
StructureBlockSyntax
)
declaredSymbolInfo
=
New
DeclaredSymbolInfo
(
project
,
structDecl
.
StructureStatement
.
Identifier
.
ValueText
,
GetTypeParameterSuffix
(
structDecl
.
StructureStatement
.
TypeParameterList
),
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
DeclaredSymbolInfoKind
.
Struct
,
GetAccessibility
(
structDecl
,
structDecl
.
StructureStatement
.
Modifiers
),
structDecl
.
StructureStatement
.
Identifier
.
Span
,
GetInheritanceNames
(
project
,
structDecl
))
Return
True
End
Select
Public
Function
IsSkippedTokensTrivia
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsSkippedTokensTrivia
Return
TypeOf
node
Is
SkippedTokensTriviaSyntax
declaredSymbolInfo
=
Nothing
Return
False
End
Function
Public
Function
HasIncompleteParentMember
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
HasIncompleteParentMember
Return
node
.
IsParentKind
(
SyntaxKind
.
IncompleteMember
)
End
Function
Private
Function
GetAccessibility
(
node
As
SyntaxNode
,
modifiers
As
SyntaxTokenList
)
As
Accessibility
Dim
sawFriend
=
False
Public
Function
GetIdentifierOfGenericName
(
genericName
As
SyntaxNode
)
As
SyntaxToken
Implements
ISyntaxFactsService
.
GetIdentifierOfGenericName
Dim
vbGenericName
=
TryCast
(
genericName
,
GenericNameSyntax
)
Return
If
(
vbGenericName
IsNot
Nothing
,
vbGenericName
.
Identifier
,
Nothing
)
End
Function
For
Each
modifier
In
modifiers
Select
Case
modifier
.
Kind
()
Case
SyntaxKind
.
PublicKeyword
:
Return
Accessibility
.
Public
Case
SyntaxKind
.
PrivateKeyword
:
Return
Accessibility
.
Private
Case
SyntaxKind
.
ProtectedKeyword
:
Return
Accessibility
.
Protected
Case
SyntaxKind
.
FriendKeyword
sawFriend
=
True
Continue
For
End
Select
Next
Public
Function
IsUsingDirectiveName
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsUsingDirectiveName
Return
node
.
IsParentKind
(
SyntaxKind
.
SimpleImportsClause
)
AndAlso
DirectCast
(
node
.
Parent
,
SimpleImportsClauseSyntax
).
Name
Is
node
End
Function
If
sawFriend
Then
Return
Accessibility
.
Internal
End
If
Public
Function
IsForEachStatement
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsForEachStatement
Return
TypeOf
node
Is
ForEachStatementSyntax
End
Function
' No accessibility modifiers
Select
Case
node
.
Parent
.
Kind
()
Case
SyntaxKind
.
ClassBlock
' In a class, fields and shared-constructors are private by default,
' everything Else Is Public
If
node
.
Kind
()
=
SyntaxKind
.
FieldDeclaration
Then
Return
Accessibility
.
Private
End
If
Public
Function
IsLockStatement
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsLockStatement
Return
TypeOf
node
Is
SyncLockStatementSyntax
End
Function
If
node
.
Kind
()
=
SyntaxKind
.
ConstructorBlock
AndAlso
DirectCast
(
node
,
ConstructorBlockSyntax
).
SubNewStatement
.
Modifiers
.
Any
(
SyntaxKind
.
SharedKeyword
)
Then
Return
Accessibility
.
Private
End
If
Public
Function
IsUsingStatement
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsUsingStatement
Return
node
.
Kind
()
=
SyntaxKind
.
UsingStatement
Return
Accessibility
.
Public
Case
SyntaxKind
.
StructureBlock
,
SyntaxKind
.
InterfaceBlock
,
SyntaxKind
.
ModuleBlock
' Everything in a struct/interface/module is public
Return
Accessibility
.
Public
End
Select
' Otherwise, it's internal
Return
Accessibility
.
Internal
End
Function
Public
Function
IsReturnStatement
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsReturnStatement
Return
node
.
Kind
()
=
SyntaxKind
.
ReturnStatement
Private
Function
GetMethodSuffix
(
method
As
MethodBlockSyntax
)
As
String
Return
GetTypeParameterSuffix
(
method
.
SubOrFunctionStatement
.
TypeParameterList
)
&
GetSuffix
(
method
.
SubOrFunctionStatement
.
ParameterList
)
End
Function
P
ublic
Function
GetExpressionOfReturnStatement
(
node
As
SyntaxNode
)
As
SyntaxNode
Implements
ISyntaxFactsService
.
GetExpressionOfReturnStatement
Return
TryCast
(
node
,
ReturnStatementSyntax
)
?
.
Expression
P
rivate
Function
GetConstructorSuffix
(
method
As
ConstructorBlockSyntax
)
As
String
Return
".New"
&
GetSuffix
(
method
.
SubNewStatement
.
ParameterList
)
End
Function
Public
Function
IsThisConstructorInitializer
(
token
As
SyntaxToken
)
As
Boolean
Implements
ISyntaxFactsService
.
IsThisConstructorInitializer
If
TypeOf
token
.
Parent
Is
IdentifierNameSyntax
AndAlso
token
.
HasMatchingText
(
SyntaxKind
.
NewKeyword
)
Then
Dim
memberAccess
=
TryCast
(
token
.
Parent
.
Parent
,
MemberAccessExpressionSyntax
)
Return
memberAccess
.
IsThisConstructorInitializer
()
Private
Function
GetPropertySuffix
(
[
property
]
As
PropertyStatementSyntax
)
As
String
If
[
property
]
.
ParameterList
Is
Nothing
Then
Return
Nothing
End
If
Return
False
Return
GetSuffix
(
[
property
]
.
ParameterList
)
End
Function
Public
Function
IsBaseConstructorInitializer
(
token
As
SyntaxToken
)
As
Boolean
Implements
ISyntaxFactsService
.
IsBaseConstructorInitializer
If
TypeOf
token
.
Parent
Is
IdentifierNameSyntax
AndAlso
token
.
HasMatchingText
(
SyntaxKind
.
NewKeyword
)
Then
Dim
memberAccess
=
TryCast
(
token
.
Parent
.
Parent
,
MemberAccessExpressionSyntax
)
Return
memberAccess
.
IsBaseConstructorInitializer
()
Private
Function
GetTypeParameterSuffix
(
typeParameterList
As
TypeParameterListSyntax
)
As
String
If
typeParameterList
Is
Nothing
Then
Return
Nothing
End
If
Return
False
End
Function
Dim
pooledBuilder
=
PooledStringBuilder
.
GetInstance
()
Public
Function
IsQueryExpression
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsQueryExpression
Return
node
.
Kind
()
=
SyntaxKind
.
QueryExpression
End
Function
Dim
builder
=
pooledBuilder
.
Builder
builder
.
Append
(
"(Of "
)
Public
Function
IsThrowExpression
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsThrowExpression
' VB does not support throw expressions currently.
Return
False
End
Function
Dim
First
=
True
For
Each
parameter
In
typeParameterList
.
Parameters
If
Not
First
Then
builder
.
Append
(
", "
)
End
If
Public
Function
IsPredefinedType
(
token
As
SyntaxToken
)
As
Boolean
Implements
ISyntaxFactsService
.
IsPredefinedType
Dim
actualType
As
PredefinedType
=
PredefinedType
.
None
Return
TryGetPredefinedType
(
token
,
actualType
)
AndAlso
actualType
<>
PredefinedType
.
None
End
Function
builder
.
Append
(
parameter
.
Identifier
.
Text
)
First
=
False
Next
Public
Function
IsPredefinedType
(
token
As
SyntaxToken
,
type
As
PredefinedType
)
As
Boolean
Implements
ISyntaxFactsService
.
IsPredefinedType
Dim
actualType
As
PredefinedType
=
PredefinedType
.
None
Return
TryGetPredefinedType
(
token
,
actualType
)
AndAlso
actualType
=
type
End
Function
builder
.
Append
(
")"
c
)
Public
Function
TryGetPredefinedType
(
token
As
SyntaxToken
,
ByRef
type
As
PredefinedType
)
As
Boolean
Implements
ISyntaxFactsService
.
TryGetPredefinedType
type
=
GetPredefinedType
(
token
)
Return
type
<>
PredefinedType
.
None
Return
pooledBuilder
.
ToStringAndFree
()
End
Function
Private
Function
GetPredefinedType
(
token
As
SyntaxToken
)
As
PredefinedType
Select
Case
token
.
Kind
Case
SyntaxKind
.
BooleanKeyword
Return
PredefinedType
.
Boolean
Case
SyntaxKind
.
ByteKeyword
Return
PredefinedType
.
Byte
Case
SyntaxKind
.
SByteKeyword
Return
PredefinedType
.
SByte
Case
SyntaxKind
.
IntegerKeyword
Return
PredefinedType
.
Int32
Case
SyntaxKind
.
UIntegerKeyword
Return
PredefinedType
.
UInt32
Case
SyntaxKind
.
ShortKeyword
Return
PredefinedType
.
Int16
Case
SyntaxKind
.
UShortKeyword
Return
PredefinedType
.
UInt16
Case
SyntaxKind
.
LongKeyword
Return
PredefinedType
.
Int64
Case
SyntaxKind
.
ULongKeyword
Return
PredefinedType
.
UInt64
Case
SyntaxKind
.
SingleKeyword
Return
PredefinedType
.
Single
Case
SyntaxKind
.
DoubleKeyword
Return
PredefinedType
.
Double
Case
SyntaxKind
.
DecimalKeyword
Return
PredefinedType
.
Decimal
Case
SyntaxKind
.
StringKeyword
Return
PredefinedType
.
String
Case
SyntaxKind
.
CharKeyword
Return
PredefinedType
.
Char
Case
SyntaxKind
.
ObjectKeyword
Return
PredefinedType
.
Object
Case
SyntaxKind
.
DateKeyword
Return
PredefinedType
.
DateTime
Case
Else
Return
PredefinedType
.
None
End
Select
End
Function
''' <summary>
''' Builds up the suffix to show for something with parameters in navigate-to.
''' While it would be nice to just use the compiler SymbolDisplay API for this,
''' it would be too expensive as it requires going back to Symbols (which requires
''' creating compilations, etc.) in a perf sensitive area.
'''
''' So, instead, we just build a reasonable suffix using the pure syntax that a
''' user provided. That means that if they wrote "Method(System.Int32 i)" we'll
''' show that as "Method(System.Int32)" Not "Method(Integer)". Given that this Is
''' actually what the user wrote, And it saves us from ever having to go back to
''' symbols/compilations, this Is well worth it, even if it does mean we have to
''' create our own 'symbol display' logic here.
''' </summary>
Private
Function
GetSuffix
(
parameterList
As
ParameterListSyntax
)
As
String
If
parameterList
Is
Nothing
OrElse
parameterList
.
Parameters
.
Count
=
0
Then
Return
"()"
End
If
Public
Function
IsPredefinedOperator
(
token
As
SyntaxToken
)
As
Boolean
Implements
ISyntaxFactsService
.
IsPredefinedOperator
Dim
actualOp
As
PredefinedOperator
=
PredefinedOperator
.
None
Return
TryGetPredefinedOperator
(
token
,
actualOp
)
AndAlso
actualOp
<>
PredefinedOperator
.
None
End
Function
Dim
pooledBuilder
=
PooledStringBuilder
.
GetInstance
()
Public
Function
IsPredefinedOperator
(
token
As
SyntaxToken
,
op
As
PredefinedOperator
)
As
Boolean
Implements
ISyntaxFactsService
.
IsPredefinedOperator
Dim
actualOp
As
PredefinedOperator
=
PredefinedOperator
.
None
Return
TryGetPredefinedOperator
(
token
,
actualOp
)
AndAlso
actualOp
=
op
End
Function
Dim
builder
=
pooledBuilder
.
Builder
builder
.
Append
(
"("
c
)
If
parameterList
IsNot
Nothing
Then
AppendParameters
(
parameterList
.
Parameters
,
builder
)
End
If
builder
.
Append
(
")"
c
)
Public
Function
TryGetPredefinedOperator
(
token
As
SyntaxToken
,
ByRef
op
As
PredefinedOperator
)
As
Boolean
Implements
ISyntaxFactsService
.
TryGetPredefinedOperator
op
=
GetPredefinedOperator
(
token
)
Return
op
<>
PredefinedOperator
.
None
Return
pooledBuilder
.
ToStringAndFree
()
End
Function
Private
Function
GetPredefinedOperator
(
token
As
SyntaxToken
)
As
PredefinedOperator
Select
Case
token
.
Kind
Case
SyntaxKind
.
PlusToken
,
SyntaxKind
.
PlusEqualsToken
Return
PredefinedOperator
.
Addition
Case
SyntaxKind
.
MinusToken
,
SyntaxKind
.
MinusEqualsToken
Return
PredefinedOperator
.
Subtraction
Case
SyntaxKind
.
AndKeyword
,
SyntaxKind
.
AndAlsoKeyword
Return
PredefinedOperator
.
BitwiseAnd
Case
SyntaxKind
.
OrKeyword
,
SyntaxKind
.
OrElseKeyword
Return
PredefinedOperator
.
BitwiseOr
Case
SyntaxKind
.
AmpersandToken
,
SyntaxKind
.
AmpersandEqualsToken
Return
PredefinedOperator
.
Concatenate
Case
SyntaxKind
.
SlashToken
,
SyntaxKind
.
SlashEqualsToken
Return
PredefinedOperator
.
Division
Case
SyntaxKind
.
EqualsToken
Return
PredefinedOperator
.
Equality
Case
SyntaxKind
.
XorKeyword
Return
PredefinedOperator
.
ExclusiveOr
Private
Sub
AppendParameters
(
parameters
As
SeparatedSyntaxList
(
Of
ParameterSyntax
),
builder
As
StringBuilder
)
Dim
First
=
True
For
Each
parameter
In
parameters
If
Not
First
Then
builder
.
Append
(
", "
)
End
If
Case
SyntaxKind
.
CaretToken
,
SyntaxKind
.
CaretEqualsToken
Return
PredefinedOperator
.
Exponent
For
Each
modifier
In
parameter
.
Modifiers
If
modifier
.
Kind
()
<>
SyntaxKind
.
ByValKeyword
Then
builder
.
Append
(
modifier
.
Text
)
builder
.
Append
(
" "
c
)
End
If
Next
Case
SyntaxKind
.
GreaterThanToken
Return
PredefinedOperator
.
GreaterThan
If
parameter
.
AsClause
?
.
Type
IsNot
Nothing
Then
AppendTokens
(
parameter
.
AsClause
.
Type
,
builder
)
End
If
Case
SyntaxKind
.
GreaterThanEqualsToken
Return
PredefinedOperator
.
GreaterThanOrEqual
First
=
False
Next
End
Sub
End
Class
Case
SyntaxKind
.
LessThanGreaterThanToken
Return
PredefinedOperator
.
Inequality
<
ExportLanguageServiceFactory
(
GetType
(
ISyntaxFactsService
),
LanguageNames
.
VisualBasic
),
[
Shared
]
>
Friend
Class
VisualBasicSyntaxFactsServiceFactory
Implements
ILanguageServiceFactory
Case
SyntaxKind
.
BackslashToken
,
SyntaxKind
.
BackslashEqualsToken
Return
PredefinedOperator
.
IntegerDivision
Public
Function
CreateLanguageService
(
languageServices
As
HostLanguageServices
)
As
ILanguageService
Implements
ILanguageServiceFactory
.
CreateLanguageService
Return
VisualBasicSyntaxFactsService
.
Instance
End
Function
End
Class
Case
SyntaxKind
.
LessThanLessThanToken
,
SyntaxKind
.
LessThanLessThanEqualsToken
Return
PredefinedOperator
.
LeftShift
Friend
Class
VisualBasicSyntaxFactsService
Inherits
AbstractSyntaxFactsService
Implements
ISyntaxFactsService
Case
SyntaxKind
.
LessThanToken
Return
PredefinedOperator
.
LessThan
Public
Shared
ReadOnly
Property
Instance
As
New
VisualBasicSyntaxFactsService
Case
SyntaxKind
.
LessThanEqualsToken
Return
PredefinedOperator
.
LessThanOrEqual
Private
Sub
New
()
End
Sub
Case
SyntaxKind
.
LikeKeyword
Return
PredefinedOperator
.
Like
Public
ReadOnly
Property
IsCaseSensitive
As
Boolean
Implements
ISyntaxFactsService
.
IsCaseSensitive
Get
Return
False
End
Get
End
Property
Case
SyntaxKind
.
NotKeyword
Return
PredefinedOperator
.
Complement
Public
ReadOnly
Property
StringComparer
As
StringComparer
Implements
ISyntaxFactsService
.
StringComparer
Get
Return
CaseInsensitiveComparison
.
Comparer
End
Get
End
Property
Case
SyntaxKind
.
ModKeyword
Return
PredefinedOperator
.
Modulus
Protected
Overrides
ReadOnly
Property
DocumentationCommentService
As
IDocumentationCommentService
Get
Return
VisualBasicDocumentationCommentService
.
Instance
End
Get
End
Property
Case
SyntaxKind
.
AsteriskToken
,
SyntaxKind
.
AsteriskEqualsToken
Return
PredefinedOperator
.
Multiplication
Public
Function
SupportsIndexingInitializer
(
options
As
ParseOptions
)
As
Boolean
Implements
ISyntaxFactsService
.
SupportsIndexingInitializer
Return
False
End
Function
Case
SyntaxKind
.
GreaterThanGreaterThanToken
,
SyntaxKind
.
GreaterThanGreaterThanEqualsToken
Return
PredefinedOperator
.
RightShift
Public
Function
SupportsThrowExpression
(
options
As
ParseOptions
)
As
Boolean
Implements
ISyntaxFactsService
.
SupportsThrowExpression
Return
False
End
Function
Case
Else
Return
PredefinedOperator
.
None
End
Select
Public
Function
IsAwaitKeyword
(
token
As
SyntaxToken
)
As
Boolean
Implements
ISyntaxFactsService
.
IsAwaitKeyword
Return
token
.
Kind
=
SyntaxKind
.
AwaitKeyword
End
Function
Public
Function
GetText
(
kind
As
Integer
)
As
String
Implements
ISyntaxFactsService
.
GetText
Return
SyntaxFacts
.
GetText
(
CType
(
kind
,
SyntaxKind
))
Public
Function
IsIdentifier
(
token
As
SyntaxToken
)
As
Boolean
Implements
ISyntaxFactsService
.
IsIdentifier
Return
token
.
Kind
=
SyntaxKind
.
IdentifierToken
End
Function
Public
Function
Is
IdentifierPartCharacter
(
c
As
Char
)
As
Boolean
Implements
ISyntaxFactsService
.
IsIdentifierPartCharacter
Return
SyntaxFacts
.
IsIdentifierPartCharacter
(
c
)
Public
Function
Is
GlobalNamespaceKeyword
(
token
As
SyntaxToken
)
As
Boolean
Implements
ISyntaxFactsService
.
IsGlobalNamespaceKeyword
Return
token
.
Kind
=
SyntaxKind
.
GlobalKeyword
End
Function
Public
Function
Is
IdentifierStartCharacter
(
c
As
Char
)
As
Boolean
Implements
ISyntaxFactsService
.
IsIdentifierStartCharact
er
Return
SyntaxFacts
.
IsIdentifierStartCharacter
(
c
)
Public
Function
Is
VerbatimIdentifier
(
token
As
SyntaxToken
)
As
Boolean
Implements
ISyntaxFactsService
.
IsVerbatimIdentifi
er
Return
False
End
Function
Public
Function
IsIdentifierEscapeCharacter
(
c
As
Char
)
As
Boolean
Implements
ISyntaxFactsService
.
IsIdentifierEscapeCharacter
Return
c
=
"["
c
OrElse
c
=
"]"
c
Public
Function
IsOperator
(
token
As
SyntaxToken
)
As
Boolean
Implements
ISyntaxFactsService
.
IsOperator
Return
(
IsUnaryExpressionOperatorToken
(
CType
(
token
.
Kind
,
SyntaxKind
))
AndAlso
(
TypeOf
token
.
Parent
Is
UnaryExpressionSyntax
OrElse
TypeOf
token
.
Parent
Is
OperatorStatementSyntax
))
OrElse
(
IsBinaryExpressionOperatorToken
(
CType
(
token
.
Kind
,
SyntaxKind
))
AndAlso
(
TypeOf
token
.
Parent
Is
BinaryExpressionSyntax
OrElse
TypeOf
token
.
Parent
Is
OperatorStatementSyntax
))
End
Function
Public
Function
IsValidIdentifier
(
identifier
As
String
)
As
Boolean
Implements
ISyntaxFactsService
.
IsValidIdentifier
Dim
token
=
SyntaxFactory
.
ParseToken
(
identifier
)
' TODO: There is no way to get the diagnostics to see if any are actually errors?
Return
IsIdentifier
(
token
)
AndAlso
Not
token
.
ContainsDiagnostics
AndAlso
token
.
ToString
().
Length
=
identifier
.
Length
Public
Function
IsContextualKeyword
(
token
As
SyntaxToken
)
As
Boolean
Implements
ISyntaxFactsService
.
IsContextualKeyword
Return
token
.
IsContextualKeyword
()
End
Function
Public
Function
Is
VerbatimIdentifier
(
identifier
As
String
)
As
Boolean
Implements
ISyntaxFactsService
.
IsVerbatimIdentifier
Return
IsValidIdentifier
(
identifier
)
AndAlso
MakeHalfWidthIdentifier
(
identifier
.
First
())
=
"["
AndAlso
MakeHalfWidthIdentifier
(
identifier
.
Last
())
=
"]"
Public
Function
Is
Keyword
(
token
As
SyntaxToken
)
As
Boolean
Implements
ISyntaxFactsService
.
IsKeyword
Return
token
.
IsKeyword
()
End
Function
Public
Function
IsTypeCharacter
(
c
As
Char
)
As
Boolean
Implements
ISyntaxFactsService
.
IsTypeCharacter
Return
c
=
"%"
c
OrElse
c
=
"&"
c
OrElse
c
=
"@"
c
OrElse
c
=
"!"
c
OrElse
c
=
"#"
c
OrElse
c
=
"$"
c
Public
Function
IsPreprocessorKeyword
(
token
As
SyntaxToken
)
As
Boolean
Implements
ISyntaxFactsService
.
IsPreprocessorKeyword
Return
token
.
IsPreprocessorKeyword
()
End
Function
Public
Function
Is
StartOfUnicodeEscapeSequence
(
c
As
Char
)
As
Boolean
Implements
ISyntaxFactsService
.
IsStartOfUnicodeEscapeSequence
Return
False
' VB does not support identifiers with escaped unicode characters
Public
Function
Is
HashToken
(
token
As
SyntaxToken
)
As
Boolean
Implements
ISyntaxFactsService
.
IsHashToken
Return
token
.
Kind
=
SyntaxKind
.
HashToken
End
Function
Public
Function
IsLiteral
(
token
As
SyntaxToken
)
As
Boolean
Implements
ISyntaxFactsService
.
IsLiteral
Select
Case
token
.
Kind
()
Case
_
SyntaxKind
.
IntegerLiteralToken
,
SyntaxKind
.
CharacterLiteralToken
,
SyntaxKind
.
DecimalLiteralToken
,
SyntaxKind
.
FloatingLiteralToken
,
SyntaxKind
.
DateLiteralToken
,
SyntaxKind
.
StringLiteralToken
,
SyntaxKind
.
DollarSignDoubleQuoteToken
,
SyntaxKind
.
DoubleQuoteToken
,
SyntaxKind
.
InterpolatedStringTextToken
,
SyntaxKind
.
TrueKeyword
,
SyntaxKind
.
FalseKeyword
,
SyntaxKind
.
NothingKeyword
Return
True
End
Select
Public
Function
TryGetCorrespondingOpenBrace
(
token
As
SyntaxToken
,
ByRef
openBrace
As
SyntaxToken
)
As
Boolean
Implements
ISyntaxFactsService
.
TryGetCorrespondingOpenBrace
If
token
.
Kind
=
SyntaxKind
.
CloseBraceToken
Then
Dim
tuples
=
token
.
Parent
.
GetBraces
()
openBrace
=
tuples
.
Item1
Return
openBrace
.
Kind
=
SyntaxKind
.
OpenBraceToken
End
If
Return
False
End
Function
Public
Function
IsStringLiteralOrInterpolatedStringLiteral
(
token
As
SyntaxToken
)
As
Boolean
Implements
ISyntaxFactsService
.
IsStringLiteralOrInterpolatedStringLiteral
Return
token
.
IsKind
(
SyntaxKind
.
StringLiteralToken
,
SyntaxKind
.
InterpolatedStringTextToken
)
End
Function
Public
Function
IsInInactiveRegion
(
syntaxTree
As
SyntaxTree
,
position
As
Integer
,
cancellationToken
As
CancellationToken
)
As
Boolean
Implements
ISyntaxFactsService
.
IsInInactiveRegion
Dim
vbTree
=
TryCast
(
syntaxTree
,
SyntaxTree
)
If
vbTree
Is
Nothing
Then
Return
False
End
If
Public
Function
IsNumericLiteralExpression
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsNumericLiteralExpression
Return
If
(
node
Is
Nothing
,
False
,
node
.
IsKind
(
SyntaxKind
.
NumericLiteralExpression
))
Return
vbTree
.
IsInInactiveRegion
(
position
,
cancellationToken
)
End
Function
Public
Function
Is
BindableToken
(
token
As
Microsoft
.
CodeAnalysis
.
SyntaxToken
)
As
Boolean
Implements
ISyntaxFactsService
.
IsBindableToken
Return
Me
.
IsWord
(
token
)
OrElse
Me
.
IsLiteral
(
token
)
OrElse
Me
.
IsOperator
(
token
)
End
Function
Public
Function
Is
InNonUserCode
(
syntaxTree
As
SyntaxTree
,
position
As
Integer
,
cancellationToken
As
CancellationToken
)
As
Boolean
Implements
ISyntaxFactsService
.
IsInNonUserCode
Dim
vbTree
=
TryCast
(
syntaxTree
,
SyntaxTree
)
If
vbTree
Is
Nothing
Then
Return
False
End
If
Public
Function
IsSimpleMemberAccessExpression
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsSimpleMemberAccessExpression
Return
TypeOf
node
Is
MemberAccessExpressionSyntax
AndAlso
DirectCast
(
node
,
MemberAccessExpressionSyntax
).
Kind
=
SyntaxKind
.
SimpleMemberAccessExpression
End
Function
Public
Function
IsPointerMemberAccessExpression
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsPointerMemberAccessExpression
Return
False
Return
vbTree
.
IsInNonUserCode
(
position
,
cancellationToken
)
End
Function
Public
Sub
GetNameAndArityOfSimpleName
(
node
As
SyntaxNode
,
ByRef
name
As
String
,
ByRef
arity
As
Integer
)
Implements
ISyntaxFactsService
.
GetNameAndArityOfSimpleName
Dim
simpleName
=
TryCast
(
node
,
SimpleNameSyntax
)
If
simpleName
IsNot
Nothing
Then
name
=
simpleName
.
Identifier
.
ValueText
arity
=
simpleName
.
Arity
Public
Function
IsEntirelyWithinStringOrCharOrNumericLiteral
(
syntaxTree
As
SyntaxTree
,
position
As
Integer
,
cancellationToken
As
CancellationToken
)
As
Boolean
Implements
ISyntaxFactsService
.
IsEntirelyWithinStringOrCharOrNumericLiteral
Dim
vbTree
=
TryCast
(
syntaxTree
,
SyntaxTree
)
If
vbTree
Is
Nothing
Then
Return
False
End
If
End
Sub
Public
Function
GetExpressionOfMemberAccessExpression
(
node
As
SyntaxNode
,
Optional
allowImplicitTarget
As
Boolean
=
False
)
As
SyntaxNode
Implements
ISyntaxFactsService
.
GetExpressionOfMemberAccessExpression
Return
TryCast
(
node
,
MemberAccessExpressionSyntax
)
?
.
GetExpressionOfMemberAccessExpression
(
allowImplicitTarget
)
Return
vbTree
.
IsEntirelyWithinStringOrCharOrNumericLiteral
(
position
,
cancellationToken
)
End
Function
Public
Function
GetTargetOfMemberBinding
(
node
As
SyntaxNode
)
As
SyntaxNode
Implements
ISyntaxFactsService
.
GetTargetOfMemberBinding
' Member bindings are a C# concept.
Return
Nothing
Public
Function
IsDirective
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsDirective
Return
TypeOf
node
Is
DirectiveTriviaSyntax
End
Function
Public
Function
GetExpressionOfConditionalAccessExpression
(
node
As
SyntaxNode
)
As
SyntaxNode
Implements
ISyntaxFactsService
.
GetExpressionOfConditionalAccessExpression
Return
TryCast
(
node
,
ConditionalAccessExpressionSyntax
)
?
.
Expression
End
Function
Public
Function
TryGetExternalSourceInfo
(
node
As
SyntaxNode
,
ByRef
info
As
ExternalSourceInfo
)
As
Boolean
Implements
ISyntaxFactsService
.
TryGetExternalSourceInfo
Select
Case
node
.
Kind
Case
SyntaxKind
.
ExternalSourceDirectiveTrivia
info
=
New
ExternalSourceInfo
(
CInt
(
DirectCast
(
node
,
ExternalSourceDirectiveTriviaSyntax
).
LineStart
.
Value
),
False
)
Return
True
Public
Function
GetExpressionOfElementAccessExpression
(
node
As
SyntaxNode
)
As
SyntaxNode
Implements
ISyntaxFactsService
.
GetExpressionOfElementAccessExpression
Return
TryCast
(
node
,
InvocationExpressionSyntax
)
?
.
Expression
End
Function
Case
SyntaxKind
.
EndExternalSourceDirectiveTrivia
info
=
New
ExternalSourceInfo
(
Nothing
,
True
)
Return
True
End
Select
Public
Function
GetArgumentListOfElementAccessExpression
(
node
As
SyntaxNode
)
As
SyntaxNode
Implements
ISyntaxFactsService
.
GetArgumentListOfElementAccessExpression
Return
TryCast
(
node
,
InvocationExpressionSyntax
)
?
.
ArgumentList
Return
False
End
Function
Public
Function
GetExpressionOfInterpolation
(
node
As
SyntaxNode
)
As
SyntaxNode
Implements
ISyntaxFactsService
.
GetExpressionOfInterpolation
Return
TryCast
(
node
,
InterpolationSyntax
)
?
.
Expression
Public
Function
IsObjectCreationExpressionType
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsObjectCreationExpressionType
Return
node
.
IsParentKind
(
SyntaxKind
.
ObjectCreationExpression
)
AndAlso
DirectCast
(
node
.
Parent
,
ObjectCreationExpressionSyntax
).
Type
Is
node
End
Function
Public
Function
IsInNamespaceOrTypeContext
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsInNamespaceOrTypeContext
Return
SyntaxFacts
.
IsInNamespaceOrTypeContext
(
node
)
Public
Function
IsAttributeName
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsAttributeName
Return
node
.
IsParentKind
(
SyntaxKind
.
Attribute
)
AndAlso
DirectCast
(
node
.
Parent
,
AttributeSyntax
).
Name
Is
node
End
Function
Public
Function
IsInStaticContext
(
node
As
Microsoft
.
CodeAnalysis
.
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsInStaticContext
Return
node
.
IsInStaticContext
()
Public
Function
IsRightSideOfQualifiedName
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsRightSideOfQualifiedName
Dim
vbNode
=
TryCast
(
node
,
SimpleNameSyntax
)
Return
vbNode
IsNot
Nothing
AndAlso
vbNode
.
IsRightSideOfQualifiedName
()
End
Function
Public
Function
GetExpressionOfArgument
(
node
As
Microsoft
.
CodeAnalysis
.
SyntaxNode
)
As
Microsoft
.
CodeAnalysis
.
SyntaxNode
Implements
ISyntaxFactsService
.
GetExpressionOfArgument
Return
TryCast
(
node
,
ArgumentSyntax
).
GetArgumentExpression
()
Public
Function
IsNameOfMemberAccessExpression
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsNameOfMemberAccessExpression
Dim
vbNode
=
TryCast
(
node
,
SimpleNameSyntax
)
Return
vbNode
IsNot
Nothing
AndAlso
vbNode
.
IsMemberAccessExpressionName
()
End
Function
Public
Function
GetRefKindOfArgument
(
node
As
Microsoft
.
CodeAnalysis
.
SyntaxNode
)
As
Microsoft
.
CodeAnalysis
.
RefKind
Implements
ISyntaxFactsService
.
GetRefKindOfArgument
' TODO(cyrusn): Consider the method this argument is passed to, to determine this.
Return
RefKind
.
None
Public
Function
IsConditionalMemberAccessExpression
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsConditionalMemberAccessExpression
Return
TypeOf
node
Is
ConditionalAccessExpressionSyntax
End
Function
Public
Function
IsSimpleArgument
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsSimpleArgument
Dim
argument
=
DirectCast
(
node
,
ArgumentSyntax
)
Return
Not
argument
.
IsNamed
AndAlso
Not
argument
.
IsOmitted
Public
Function
IsInvocationExpression
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsInvocationExpression
Return
TypeOf
node
Is
InvocationExpressionSyntax
End
Function
Public
Function
Is
InConstantContext
(
node
As
Microsoft
.
CodeAnalysis
.
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsInConstantContext
Return
node
.
IsInConstantContext
()
Public
Function
Is
AnonymousFunction
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsAnonymousFunction
Return
TypeOf
node
Is
LambdaExpressionSyntax
End
Function
Public
Function
Is
InConstructor
(
node
As
Microsoft
.
CodeAnalysis
.
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsInConstructor
Return
node
.
GetAncestors
(
Of
StatementSyntax
).
Any
(
Function
(
s
)
s
.
Kind
=
SyntaxKind
.
ConstructorBlock
)
Public
Function
Is
GenericName
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsGenericName
Return
TypeOf
node
Is
GenericNameSyntax
End
Function
Public
Function
Is
UnsafeContext
(
node
As
Microsoft
.
CodeAnalysis
.
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsUnsafeContext
Return
False
Public
Function
Is
NamedParameter
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsNamedParameter
Return
node
.
CheckParent
(
Of
SimpleArgumentSyntax
)(
Function
(
p
)
p
.
IsNamed
AndAlso
p
.
NameColonEquals
.
Name
Is
node
)
End
Function
Public
Function
Get
NameOfAttribute
(
node
As
Microsoft
.
CodeAnalysis
.
SyntaxNode
)
As
Microsoft
.
CodeAnalysis
.
SyntaxNode
Implements
ISyntaxFactsService
.
GetNameOfAttribute
Return
DirectCast
(
node
,
AttributeSyntax
).
Name
Public
Function
Get
DefaultOfParameter
(
node
As
SyntaxNode
)
As
SyntaxNode
Implements
ISyntaxFactsService
.
GetDefaultOfParameter
Return
TryCast
(
node
,
ParameterSyntax
)
?
.
Default
End
Function
Public
Function
Is
Attribute
(
node
As
Microsoft
.
CodeAnalysis
.
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsAttribute
Return
TypeOf
node
Is
Attribute
Syntax
Public
Function
Is
SkippedTokensTrivia
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsSkippedTokensTrivia
Return
TypeOf
node
Is
SkippedTokensTrivia
Syntax
End
Function
Public
Function
IsAttributeNamedArgumentIdentifier
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsAttributeNamedArgumentIdentifier
Dim
identifierName
=
TryCast
(
node
,
IdentifierNameSyntax
)
Return
identifierName
.
IsParentKind
(
SyntaxKind
.
NameColonEquals
)
AndAlso
identifierName
.
Parent
.
IsParentKind
(
SyntaxKind
.
SimpleArgument
)
AndAlso
identifierName
.
Parent
.
Parent
.
IsParentKind
(
SyntaxKind
.
ArgumentList
)
AndAlso
identifierName
.
Parent
.
Parent
.
Parent
.
IsParentKind
(
SyntaxKind
.
Attribute
)
Public
Function
HasIncompleteParentMember
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
HasIncompleteParentMember
Return
node
.
IsParentKind
(
SyntaxKind
.
IncompleteMember
)
End
Function
Public
Function
GetContainingTypeDeclaration
(
root
As
SyntaxNode
,
position
As
Integer
)
As
SyntaxNode
Implements
ISyntaxFactsService
.
GetContainingTypeDeclaration
If
root
Is
Nothing
Then
Throw
New
ArgumentNullException
(
NameOf
(
root
))
End
If
If
position
<
0
OrElse
position
>
root
.
Span
.
End
Then
Throw
New
ArgumentOutOfRangeException
(
NameOf
(
position
))
End
If
Return
root
.
FindToken
(
position
).
GetAncestors
(
Of
SyntaxNode
)().
FirstOrDefault
(
Function
(
n
)
TypeOf
n
Is
TypeBlockSyntax
OrElse
TypeOf
n
Is
DelegateStatementSyntax
)
Public
Function
GetIdentifierOfGenericName
(
genericName
As
SyntaxNode
)
As
SyntaxToken
Implements
ISyntaxFactsService
.
GetIdentifierOfGenericName
Dim
vbGenericName
=
TryCast
(
genericName
,
GenericNameSyntax
)
Return
If
(
vbGenericName
IsNot
Nothing
,
vbGenericName
.
Identifier
,
Nothing
)
End
Function
Public
Function
GetContainingVariableDeclaratorOfFieldDeclaration
(
node
As
SyntaxNode
)
As
SyntaxNode
Implements
ISyntaxFactsService
.
GetContainingVariableDeclaratorOfFieldDeclaration
If
node
Is
Nothing
Then
Throw
New
ArgumentNullException
(
NameOf
(
node
))
End
If
Dim
parent
=
node
.
Parent
While
node
IsNot
Nothing
If
node
.
Kind
=
SyntaxKind
.
VariableDeclarator
AndAlso
node
.
IsParentKind
(
SyntaxKind
.
FieldDeclaration
)
Then
Return
node
End
If
node
=
node
.
Parent
End
While
Return
Nothing
Public
Function
IsUsingDirectiveName
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsUsingDirectiveName
Return
node
.
IsParentKind
(
SyntaxKind
.
SimpleImportsClause
)
AndAlso
DirectCast
(
node
.
Parent
,
SimpleImportsClauseSyntax
).
Name
Is
node
End
Function
Public
Function
FindTokenOnLeftOfPosition
(
node
As
SyntaxNode
,
position
As
Integer
,
Optional
includeSkipped
As
Boolean
=
True
,
Optional
includeDirectives
As
Boolean
=
False
,
Optional
includeDocumentationComments
As
Boolean
=
False
)
As
SyntaxToken
Implements
ISyntaxFactsService
.
FindTokenOnLeftOfPosition
Return
node
.
FindTokenOnLeftOfPosition
(
position
,
includeSkipped
,
includeDirectives
,
includeDocumentationComments
)
Public
Function
IsForEachStatement
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsForEachStatement
Return
TypeOf
node
Is
ForEachStatementSyntax
End
Function
Public
Function
FindTokenOnRightOfPosition
(
node
As
SyntaxNode
,
position
As
Integer
,
Optional
includeSkipped
As
Boolean
=
True
,
Optional
includeDirectives
As
Boolean
=
False
,
Optional
includeDocumentationComments
As
Boolean
=
False
)
As
SyntaxToken
Implements
ISyntaxFactsService
.
FindTokenOnRightOfPosition
Return
node
.
FindTokenOnRightOfPosition
(
position
,
includeSkipped
,
includeDirectives
,
includeDocumentationComments
)
Public
Function
IsLockStatement
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsLockStatement
Return
TypeOf
node
Is
SyncLockStatementSyntax
End
Function
Public
Function
Is
ObjectCreationExpression
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsObjectCreationExpression
Return
TypeOf
node
Is
ObjectCreationExpressionSyntax
Public
Function
Is
UsingStatement
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsUsingStatement
Return
node
.
Kind
()
=
SyntaxKind
.
UsingStatement
End
Function
Public
Function
IsObjectInitializerNamedAssignmentIdentifier
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsObjectInitializerNamedAssignmentIdentifier
Dim
unused
As
SyntaxNode
=
Nothing
Return
IsObjectInitializerNamedAssignmentIdentifier
(
node
,
unused
)
Public
Function
IsReturnStatement
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsReturnStatement
Return
node
.
Kind
()
=
SyntaxKind
.
ReturnStatement
End
Function
Public
Function
IsObjectInitializerNamedAssignmentIdentifier
(
node
As
SyntaxNode
,
ByRef
initializedInstance
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsObjectInitializerNamedAssignmentIdentifier
Public
Function
GetExpressionOfReturnStatement
(
node
As
SyntaxNode
)
As
SyntaxNode
Implements
ISyntaxFactsService
.
GetExpressionOfReturnStatement
Return
TryCast
(
node
,
ReturnStatementSyntax
)
?
.
Expression
End
Function
Dim
identifier
=
TryCast
(
node
,
IdentifierNameSyntax
)
If
identifier
?
.
IsChildNode
(
Of
NamedFieldInitializerSyntax
)(
Function
(
n
)
n
.
Name
)
Then
' .parent is the NamedField.
' .parent.parent is the ObjectInitializer.
' .parent.parent.parent will be the ObjectCreationExpression.
initializedInstance
=
identifier
.
Parent
.
Parent
.
Parent
Return
True
Public
Function
IsThisConstructorInitializer
(
token
As
SyntaxToken
)
As
Boolean
Implements
ISyntaxFactsService
.
IsThisConstructorInitializer
If
TypeOf
token
.
Parent
Is
IdentifierNameSyntax
AndAlso
token
.
HasMatchingText
(
SyntaxKind
.
NewKeyword
)
Then
Dim
memberAccess
=
TryCast
(
token
.
Parent
.
Parent
,
MemberAccessExpressionSyntax
)
Return
memberAccess
.
IsThisConstructorInitializer
()
End
If
Return
False
End
Function
Public
Function
Is
ElementAccessExpression
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsElementAccessExpression
' VB doesn't have a specialized node for element access. Instead, it just uses a
n
' invocation expression or dictionary access expression.
Return
node
.
Kind
=
SyntaxKind
.
InvocationExpression
OrElse
node
.
Kind
=
SyntaxKind
.
DictionaryAccessExpression
End
Function
Public
Function
Is
BaseConstructorInitializer
(
token
As
SyntaxToken
)
As
Boolean
Implements
ISyntaxFactsService
.
IsBaseConstructorInitializer
If
TypeOf
token
.
Parent
Is
IdentifierNameSyntax
AndAlso
token
.
HasMatchingText
(
SyntaxKind
.
NewKeyword
)
The
n
Dim
memberAccess
=
TryCast
(
token
.
Parent
.
Parent
,
MemberAccessExpressionSyntax
)
Return
memberAccess
.
IsBaseConstructorInitializer
()
End
If
Public
Function
ToIdentifierToken
(
name
As
String
)
As
SyntaxToken
Implements
ISyntaxFactsService
.
ToIdentifierToken
Return
name
.
ToIdentifierToken
()
Return
False
End
Function
Public
Function
Parenthesize
(
expression
As
SyntaxNode
,
Optional
includeElasticTrivia
As
Boolean
=
True
)
As
SyntaxNode
Implements
ISyntaxFactsService
.
Parenthesize
Return
DirectCast
(
expression
,
ExpressionSyntax
).
Parenthesize
()
Public
Function
IsQueryExpression
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsQueryExpression
Return
node
.
Kind
()
=
SyntaxKind
.
QueryExpression
End
Function
Public
Function
IsTypeNamedVarInVariableOrFieldDeclaration
(
token
As
SyntaxToken
,
parent
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsTypeNamedVarInVariableOrFieldDeclaration
Public
Function
IsThrowExpression
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsThrowExpression
' VB does not support throw expressions currently.
Return
False
End
Function
Public
Function
IsTypeNamedDynamic
(
token
As
SyntaxToken
,
parent
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsTypeNamedDynamic
Return
False
Public
Function
IsPredefinedType
(
token
As
SyntaxToken
)
As
Boolean
Implements
ISyntaxFactsService
.
IsPredefinedType
Dim
actualType
As
PredefinedType
=
PredefinedType
.
None
Return
TryGetPredefinedType
(
token
,
actualType
)
AndAlso
actualType
<>
PredefinedType
.
None
End
Function
Public
Function
IsIndexerMemberCRef
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsIndexerMemberCRef
Return
False
Public
Function
IsPredefinedType
(
token
As
SyntaxToken
,
type
As
PredefinedType
)
As
Boolean
Implements
ISyntaxFactsService
.
IsPredefinedType
Dim
actualType
As
PredefinedType
=
PredefinedType
.
None
Return
TryGetPredefinedType
(
token
,
actualType
)
AndAlso
actualType
=
type
End
Function
Public
Function
GetContainingMemberDeclaration
(
root
As
SyntaxNode
,
position
As
Integer
,
Optional
useFullSpan
As
Boolean
=
True
)
As
SyntaxNode
Implements
ISyntaxFactsService
.
GetContainingMemberDeclaration
Contract
.
ThrowIfNull
(
root
,
NameOf
(
root
))
Contract
.
ThrowIfTrue
(
position
<
0
OrElse
position
>
root
.
FullSpan
.
End
,
NameOf
(
position
))
Dim
[
end
]
=
root
.
FullSpan
.
End
If
[
end
]
=
0
Then
' empty file
Return
Nothing
End
If
' make sure position doesn't touch end of root
position
=
Math
.
Min
(
position
,
[
end
]
-
1
)
Dim
node
=
root
.
FindToken
(
position
).
Parent
While
node
IsNot
Nothing
If
useFullSpan
OrElse
node
.
Span
.
Contains
(
position
)
Then
If
TypeOf
node
Is
MethodBlockBaseSyntax
AndAlso
Not
TypeOf
node
.
Parent
Is
PropertyBlockSyntax
Then
Return
node
End
If
If
TypeOf
node
Is
PropertyStatementSyntax
AndAlso
Not
TypeOf
node
.
Parent
Is
PropertyBlockSyntax
Then
Return
node
End
If
If
TypeOf
node
Is
EventStatementSyntax
AndAlso
Not
TypeOf
node
.
Parent
Is
EventBlockSyntax
Then
Return
node
End
If
If
TypeOf
node
Is
PropertyBlockSyntax
OrElse
TypeOf
node
Is
TypeBlockSyntax
OrElse
TypeOf
node
Is
EnumBlockSyntax
OrElse
TypeOf
node
Is
NamespaceBlockSyntax
OrElse
TypeOf
node
Is
EventBlockSyntax
OrElse
TypeOf
node
Is
FieldDeclarationSyntax
Then
Return
node
End
If
End
If
node
=
node
.
Parent
End
While
Return
Nothing
Public
Function
TryGetPredefinedType
(
token
As
SyntaxToken
,
ByRef
type
As
PredefinedType
)
As
Boolean
Implements
ISyntaxFactsService
.
TryGetPredefinedType
type
=
GetPredefinedType
(
token
)
Return
type
<>
PredefinedType
.
None
End
Function
Public
Function
IsMethodLevelMember
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsMethodLevelMember
Private
Function
GetPredefinedType
(
token
As
SyntaxToken
)
As
PredefinedType
Select
Case
token
.
Kind
Case
SyntaxKind
.
BooleanKeyword
Return
PredefinedType
.
Boolean
Case
SyntaxKind
.
ByteKeyword
Return
PredefinedType
.
Byte
Case
SyntaxKind
.
SByteKeyword
Return
PredefinedType
.
SByte
Case
SyntaxKind
.
IntegerKeyword
Return
PredefinedType
.
Int32
Case
SyntaxKind
.
UIntegerKeyword
Return
PredefinedType
.
UInt32
Case
SyntaxKind
.
ShortKeyword
Return
PredefinedType
.
Int16
Case
SyntaxKind
.
UShortKeyword
Return
PredefinedType
.
UInt16
Case
SyntaxKind
.
LongKeyword
Return
PredefinedType
.
Int64
Case
SyntaxKind
.
ULongKeyword
Return
PredefinedType
.
UInt64
Case
SyntaxKind
.
SingleKeyword
Return
PredefinedType
.
Single
Case
SyntaxKind
.
DoubleKeyword
Return
PredefinedType
.
Double
Case
SyntaxKind
.
DecimalKeyword
Return
PredefinedType
.
Decimal
Case
SyntaxKind
.
StringKeyword
Return
PredefinedType
.
String
Case
SyntaxKind
.
CharKeyword
Return
PredefinedType
.
Char
Case
SyntaxKind
.
ObjectKeyword
Return
PredefinedType
.
Object
Case
SyntaxKind
.
DateKeyword
Return
PredefinedType
.
DateTime
Case
Else
Return
PredefinedType
.
None
End
Select
End
Function
' Note: Derived types of MethodBaseSyntax are expanded explicitly, since PropertyStatementSyntax and
' EventStatementSyntax will NOT be parented by MethodBlockBaseSyntax. Additionally, there are things
' like AccessorStatementSyntax and DelegateStatementSyntax that we never want to tread as method level
' members.
Public
Function
IsPredefinedOperator
(
token
As
SyntaxToken
)
As
Boolean
Implements
ISyntaxFactsService
.
IsPredefinedOperator
Dim
actualOp
As
PredefinedOperator
=
PredefinedOperator
.
None
Return
TryGetPredefinedOperator
(
token
,
actualOp
)
AndAlso
actualOp
<>
PredefinedOperator
.
None
End
Function
If
TypeOf
node
Is
MethodStatementSyntax
AndAlso
Not
TypeOf
node
.
Parent
Is
MethodBlockBaseSyntax
Then
Return
True
End
If
Public
Function
IsPredefinedOperator
(
token
As
SyntaxToken
,
op
As
PredefinedOperator
)
As
Boolean
Implements
ISyntaxFactsService
.
IsPredefinedOperator
Dim
actualOp
As
PredefinedOperator
=
PredefinedOperator
.
None
Return
TryGetPredefinedOperator
(
token
,
actualOp
)
AndAlso
actualOp
=
op
End
Function
If
TypeOf
node
Is
SubNewStatementSyntax
AndAlso
Not
TypeOf
node
.
Parent
Is
MethodBlockBaseSyntax
Then
Return
True
End
If
Public
Function
TryGetPredefinedOperator
(
token
As
SyntaxToken
,
ByRef
op
As
PredefinedOperator
)
As
Boolean
Implements
ISyntaxFactsService
.
TryGetPredefinedOperator
op
=
GetPredefinedOperator
(
token
)
Return
op
<>
PredefinedOperator
.
None
End
Function
If
TypeOf
node
Is
OperatorStatementSyntax
AndAlso
Not
TypeOf
node
.
Parent
Is
MethodBlockBaseSyntax
Then
Return
True
End
If
Private
Function
GetPredefinedOperator
(
token
As
SyntaxToken
)
As
PredefinedOperator
Select
Case
token
.
Kind
Case
SyntaxKind
.
PlusToken
,
SyntaxKind
.
PlusEqualsToken
Return
PredefinedOperator
.
Addition
If
TypeOf
node
Is
PropertyStatementSyntax
AndAlso
Not
TypeOf
node
.
Parent
Is
PropertyBlockSyntax
Then
Return
True
End
If
Case
SyntaxKind
.
MinusToken
,
SyntaxKind
.
MinusEqualsToken
Return
PredefinedOperator
.
Subtraction
If
TypeOf
node
Is
EventStatementSyntax
AndAlso
Not
TypeOf
node
.
Parent
Is
EventBlockSyntax
Then
Return
True
End
If
Case
SyntaxKind
.
AndKeyword
,
SyntaxKind
.
AndAlsoKeyword
Return
PredefinedOperator
.
BitwiseAnd
If
TypeOf
node
Is
DeclareStatementSyntax
Then
Return
True
End
If
Case
SyntaxKind
.
OrKeyword
,
SyntaxKind
.
OrElseKeyword
Return
PredefinedOperator
.
BitwiseOr
Return
TypeOf
node
Is
ConstructorBlockSyntax
OrElse
TypeOf
node
Is
MethodBlockSyntax
OrElse
TypeOf
node
Is
OperatorBlockSyntax
OrElse
TypeOf
node
Is
EventBlockSyntax
OrElse
TypeOf
node
Is
PropertyBlockSyntax
OrElse
TypeOf
node
Is
EnumMemberDeclarationSyntax
OrElse
TypeOf
node
Is
FieldDeclarationSyntax
End
Function
Case
SyntaxKind
.
AmpersandToken
,
SyntaxKind
.
AmpersandEqualsToken
Return
PredefinedOperator
.
Concatenate
Public
Function
GetMemberBodySpanForSpeculativeBinding
(
node
As
SyntaxNode
)
As
TextSpan
Implements
ISyntaxFactsService
.
GetMemberBodySpanForSpeculativeBinding
Dim
member
=
GetContainingMemberDeclaration
(
node
,
node
.
SpanStart
)
If
member
Is
Nothing
Then
Return
Nothing
End
If
Case
SyntaxKind
.
SlashToken
,
SyntaxKind
.
SlashEqualsToken
Return
PredefinedOperator
.
Division
' TODO: currently we only support method for now
Dim
method
=
TryCast
(
member
,
MethodBlockBaseSyntax
)
If
method
IsNot
Nothing
Then
If
method
.
BlockStatement
Is
Nothing
OrElse
method
.
EndBlockStatement
Is
Nothing
Then
Return
Nothing
End
If
Case
SyntaxKind
.
EqualsToken
Return
PredefinedOperator
.
Equality
' We don't want to include the BlockStatement or any trailing trivia up to and including its statement
' terminator in the span. Instead, we use the start of the first statement's leading trivia (if any) up
' to the start of the EndBlockStatement. If there aren't any statements in the block, we use the start
' of the EndBlockStatements leading trivia.
Case
SyntaxKind
.
XorKeyword
Return
PredefinedOperator
.
ExclusiveOr
Dim
firstStatement
=
method
.
Statements
.
FirstOrDefault
()
Dim
spanStart
=
If
(
firstStatement
IsNot
Nothing
,
firstStatement
.
FullSpan
.
Start
,
method
.
EndBlockStatement
.
FullSpan
.
Start
)
Case
SyntaxKind
.
CaretToken
,
SyntaxKind
.
CaretEqualsToken
Return
PredefinedOperator
.
Exponent
Return
TextSpan
.
FromBounds
(
spanStart
,
method
.
EndBlockStatement
.
SpanStart
)
End
If
Case
SyntaxKind
.
GreaterThanToken
Return
PredefinedOperator
.
GreaterThan
Return
Nothing
End
Function
Case
SyntaxKind
.
GreaterThanEqualsToken
Return
PredefinedOperator
.
GreaterThanOrEqual
Public
Function
ContainsInMemberBody
(
node
As
SyntaxNode
,
span
As
TextSpan
)
As
Boolean
Implements
ISyntaxFactsService
.
ContainsInMemberBody
Dim
method
=
TryCast
(
node
,
MethodBlockBaseSyntax
)
If
method
IsNot
Nothing
Then
Return
method
.
Statements
.
Count
>
0
AndAlso
ContainsExclusively
(
GetSyntaxListSpan
(
method
.
Statements
),
span
)
End
If
Case
SyntaxKind
.
LessThanGreaterThanToken
Return
PredefinedOperator
.
Inequality
Dim
[
event
]
=
TryCast
(
node
,
EventBlockSyntax
)
If
[
event
]
IsNot
Nothing
Then
Return
[
event
]
.
Accessors
.
Count
>
0
AndAlso
ContainsExclusively
(
GetSyntaxListSpan
(
[
event
]
.
Accessors
),
span
)
End
If
Case
SyntaxKind
.
BackslashToken
,
SyntaxKind
.
BackslashEqualsToken
Return
PredefinedOperator
.
IntegerDivision
Dim
[
property
]
=
TryCast
(
node
,
PropertyBlockSyntax
)
If
[
property
]
IsNot
Nothing
Then
Return
[
property
]
.
Accessors
.
Count
>
0
AndAlso
ContainsExclusively
(
GetSyntaxListSpan
(
[
property
]
.
Accessors
),
span
)
End
If
Case
SyntaxKind
.
LessThanLessThanToken
,
SyntaxKind
.
LessThanLessThanEqualsToken
Return
PredefinedOperator
.
LeftShift
Dim
field
=
TryCast
(
node
,
FieldDeclarationSyntax
)
If
field
IsNot
Nothing
Then
Return
field
.
Declarators
.
Count
>
0
AndAlso
ContainsExclusively
(
GetSeparatedSyntaxListSpan
(
field
.
Declarators
),
span
)
End
If
Case
SyntaxKind
.
LessThanToken
Return
PredefinedOperator
.
LessThan
Dim
[
enum
]
=
TryCast
(
node
,
EnumMemberDeclarationSyntax
)
If
[
enum
]
IsNot
Nothing
Then
Return
[
enum
]
.
Initializer
IsNot
Nothing
AndAlso
ContainsExclusively
(
[
enum
]
.
Initializer
.
Span
,
span
)
End
If
Case
SyntaxKind
.
LessThanEqualsToken
Return
PredefinedOperator
.
LessThanOrEqual
Dim
propStatement
=
TryCast
(
node
,
PropertyStatementSyntax
)
If
propStatement
IsNot
Nothing
Then
Return
propStatement
.
Initializer
IsNot
Nothing
AndAlso
ContainsExclusively
(
propStatement
.
Initializer
.
Span
,
span
)
End
If
Case
SyntaxKind
.
LikeKeyword
Return
PredefinedOperator
.
Like
Return
False
Case
SyntaxKind
.
NotKeyword
Return
PredefinedOperator
.
Complement
Case
SyntaxKind
.
ModKeyword
Return
PredefinedOperator
.
Modulus
Case
SyntaxKind
.
AsteriskToken
,
SyntaxKind
.
AsteriskEqualsToken
Return
PredefinedOperator
.
Multiplication
Case
SyntaxKind
.
GreaterThanGreaterThanToken
,
SyntaxKind
.
GreaterThanGreaterThanEqualsToken
Return
PredefinedOperator
.
RightShift
Case
Else
Return
PredefinedOperator
.
None
End
Select
End
Function
Private
Function
ContainsExclusively
(
outerSpan
As
TextSpan
,
innerSpan
As
TextSpan
)
As
Boolean
If
innerSpan
.
IsEmpty
Then
Return
outerSpan
.
Contains
(
innerSpan
.
Start
)
End
If
Public
Function
GetText
(
kind
As
Integer
)
As
String
Implements
ISyntaxFactsService
.
GetText
Return
SyntaxFacts
.
GetText
(
CType
(
kind
,
SyntaxKind
))
End
Function
Return
outerSpan
.
Contains
(
innerSpan
)
Public
Function
IsIdentifierPartCharacter
(
c
As
Char
)
As
Boolean
Implements
ISyntaxFactsService
.
IsIdentifierPartCharacter
Return
SyntaxFacts
.
IsIdentifierPartCharacter
(
c
)
End
Function
Private
Function
GetSyntaxListSpan
(
Of
T
As
SyntaxNode
)(
list
As
SyntaxList
(
Of
T
))
As
TextSpan
Contract
.
Requires
(
list
.
Count
>
0
)
Return
TextSpan
.
FromBounds
(
list
.
First
.
SpanStart
,
list
.
Last
.
Span
.
End
)
Public
Function
IsIdentifierStartCharacter
(
c
As
Char
)
As
Boolean
Implements
ISyntaxFactsService
.
IsIdentifierStartCharacter
Return
SyntaxFacts
.
IsIdentifierStartCharacter
(
c
)
End
Function
Private
Function
GetSeparatedSyntaxListSpan
(
Of
T
As
SyntaxNode
)(
list
As
SeparatedSyntaxList
(
Of
T
))
As
TextSpan
Contract
.
Requires
(
list
.
Count
>
0
)
Return
TextSpan
.
FromBounds
(
list
.
First
.
SpanStart
,
list
.
Last
.
Span
.
End
)
Public
Function
IsIdentifierEscapeCharacter
(
c
As
Char
)
As
Boolean
Implements
ISyntaxFactsService
.
IsIdentifierEscapeCharacter
Return
c
=
"["
c
OrElse
c
=
"]"
c
End
Function
Public
Function
GetMethodLevelMembers
(
root
As
SyntaxNode
)
As
List
(
Of
SyntaxNode
)
Implements
ISyntaxFactsService
.
GetMethodLevelMembers
Dim
list
=
New
List
(
Of
SyntaxNode
)(
)
AppendMethodLevelMembers
(
root
,
list
)
Return
list
Public
Function
IsValidIdentifier
(
identifier
As
String
)
As
Boolean
Implements
ISyntaxFactsService
.
IsValidIdentifier
Dim
token
=
SyntaxFactory
.
ParseToken
(
identifier
)
' TODO: There is no way to get the diagnostics to see if any are actually errors?
Return
IsIdentifier
(
token
)
AndAlso
Not
token
.
ContainsDiagnostics
AndAlso
token
.
ToString
().
Length
=
identifier
.
Length
End
Function
Public
Function
IsTopLevelNodeWithMembers
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsTopLevelNodeWithMembers
Return
TypeOf
node
Is
NamespaceBlockSyntax
OrElse
TypeOf
node
Is
TypeBlockSyntax
OrElse
TypeOf
node
Is
EnumBlockSyntax
Public
Function
IsVerbatimIdentifier
(
identifier
As
String
)
As
Boolean
Implements
ISyntaxFactsService
.
IsVerbatimIdentifier
Return
IsValidIdentifier
(
identifier
)
AndAlso
MakeHalfWidthIdentifier
(
identifier
.
First
())
=
"["
AndAlso
MakeHalfWidthIdentifier
(
identifier
.
Last
())
=
"]"
End
Function
Public
Function
TryGetDeclaredSymbolInfo
(
project
As
Project
,
node
As
SyntaxNode
,
ByRef
declaredSymbolInfo
As
DeclaredSymbolInfo
)
As
Boolean
Implements
ISyntaxFactsService
.
TryGetDeclaredSymbolInfo
Select
Case
node
.
Kind
()
Case
SyntaxKind
.
ClassBlock
Dim
classDecl
=
CType
(
node
,
ClassBlockSyntax
)
declaredSymbolInfo
=
New
DeclaredSymbolInfo
(
project
,
classDecl
.
ClassStatement
.
Identifier
.
ValueText
,
GetTypeParameterSuffix
(
classDecl
.
ClassStatement
.
TypeParameterList
),
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
DeclaredSymbolInfoKind
.
Class
,
GetAccessibility
(
classDecl
,
classDecl
.
ClassStatement
.
Modifiers
),
classDecl
.
ClassStatement
.
Identifier
.
Span
,
GetInheritanceNames
(
project
,
classDecl
))
Return
True
Case
SyntaxKind
.
ConstructorBlock
Dim
constructor
=
CType
(
node
,
ConstructorBlockSyntax
)
Dim
typeBlock
=
TryCast
(
constructor
.
Parent
,
TypeBlockSyntax
)
If
typeBlock
IsNot
Nothing
Then
declaredSymbolInfo
=
New
DeclaredSymbolInfo
(
project
,
typeBlock
.
BlockStatement
.
Identifier
.
ValueText
,
GetConstructorSuffix
(
constructor
),
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
DeclaredSymbolInfoKind
.
Constructor
,
GetAccessibility
(
constructor
,
constructor
.
SubNewStatement
.
Modifiers
),
constructor
.
SubNewStatement
.
NewKeyword
.
Span
,
ImmutableArray
(
Of
String
).
Empty
,
parameterCount
:
=
If
(
constructor
.
SubNewStatement
.
ParameterList
?
.
Parameters
.
Count
,
0
))
Public
Function
IsTypeCharacter
(
c
As
Char
)
As
Boolean
Implements
ISyntaxFactsService
.
IsTypeCharacter
Return
c
=
"%"
c
OrElse
c
=
"&"
c
OrElse
c
=
"@"
c
OrElse
c
=
"!"
c
OrElse
c
=
"#"
c
OrElse
c
=
"$"
c
End
Function
Return
True
End
If
Case
SyntaxKind
.
DelegateFunctionStatement
,
SyntaxKind
.
DelegateSubStatement
Dim
delegateDecl
=
CType
(
node
,
DelegateStatementSyntax
)
declaredSymbolInfo
=
New
DeclaredSymbolInfo
(
project
,
delegateDecl
.
Identifier
.
ValueText
,
GetTypeParameterSuffix
(
delegateDecl
.
TypeParameterList
),
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
DeclaredSymbolInfoKind
.
Delegate
,
GetAccessibility
(
delegateDecl
,
delegateDecl
.
Modifiers
),
delegateDecl
.
Identifier
.
Span
,
ImmutableArray
(
Of
String
).
Empty
)
Return
True
Case
SyntaxKind
.
EnumBlock
Dim
enumDecl
=
CType
(
node
,
EnumBlockSyntax
)
declaredSymbolInfo
=
New
DeclaredSymbolInfo
(
project
,
enumDecl
.
EnumStatement
.
Identifier
.
ValueText
,
Nothing
,
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
DeclaredSymbolInfoKind
.
Enum
,
GetAccessibility
(
enumDecl
,
enumDecl
.
EnumStatement
.
Modifiers
),
enumDecl
.
EnumStatement
.
Identifier
.
Span
,
ImmutableArray
(
Of
String
).
Empty
)
Return
True
Case
SyntaxKind
.
EnumMemberDeclaration
Dim
enumMember
=
CType
(
node
,
EnumMemberDeclarationSyntax
)
declaredSymbolInfo
=
New
DeclaredSymbolInfo
(
project
,
enumMember
.
Identifier
.
ValueText
,
Nothing
,
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
DeclaredSymbolInfoKind
.
EnumMember
,
Accessibility
.
Public
,
enumMember
.
Identifier
.
Span
,
ImmutableArray
(
Of
String
).
Empty
)
Return
True
Case
SyntaxKind
.
EventStatement
Dim
eventDecl
=
CType
(
node
,
EventStatementSyntax
)
Dim
statementOrBlock
=
If
(
TypeOf
node
.
Parent
Is
EventBlockSyntax
,
node
.
Parent
,
node
)
Dim
eventParent
=
statementOrBlock
.
Parent
declaredSymbolInfo
=
New
DeclaredSymbolInfo
(
project
,
eventDecl
.
Identifier
.
ValueText
,
Nothing
,
GetContainerDisplayName
(
eventParent
),
GetFullyQualifiedContainerName
(
eventParent
),
DeclaredSymbolInfoKind
.
Event
,
GetAccessibility
(
statementOrBlock
,
eventDecl
.
Modifiers
),
eventDecl
.
Identifier
.
Span
,
ImmutableArray
(
Of
String
).
Empty
)
Return
True
Case
SyntaxKind
.
FunctionBlock
,
SyntaxKind
.
SubBlock
Dim
funcDecl
=
CType
(
node
,
MethodBlockSyntax
)
declaredSymbolInfo
=
New
DeclaredSymbolInfo
(
project
,
funcDecl
.
SubOrFunctionStatement
.
Identifier
.
ValueText
,
GetMethodSuffix
(
funcDecl
),
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
DeclaredSymbolInfoKind
.
Method
,
GetAccessibility
(
node
,
funcDecl
.
SubOrFunctionStatement
.
Modifiers
),
funcDecl
.
SubOrFunctionStatement
.
Identifier
.
Span
,
ImmutableArray
(
Of
String
).
Empty
,
parameterCount
:
=
If
(
funcDecl
.
SubOrFunctionStatement
.
ParameterList
?
.
Parameters
.
Count
,
0
),
typeParameterCount
:
=
If
(
funcDecl
.
SubOrFunctionStatement
.
TypeParameterList
?
.
Parameters
.
Count
,
0
))
Return
True
Case
SyntaxKind
.
InterfaceBlock
Dim
interfaceDecl
=
CType
(
node
,
InterfaceBlockSyntax
)
declaredSymbolInfo
=
New
DeclaredSymbolInfo
(
project
,
interfaceDecl
.
InterfaceStatement
.
Identifier
.
ValueText
,
GetTypeParameterSuffix
(
interfaceDecl
.
InterfaceStatement
.
TypeParameterList
),
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
DeclaredSymbolInfoKind
.
Interface
,
GetAccessibility
(
interfaceDecl
,
interfaceDecl
.
InterfaceStatement
.
Modifiers
),
interfaceDecl
.
InterfaceStatement
.
Identifier
.
Span
,
GetInheritanceNames
(
project
,
interfaceDecl
))
Return
True
Case
SyntaxKind
.
ModifiedIdentifier
Dim
modifiedIdentifier
=
CType
(
node
,
ModifiedIdentifierSyntax
)
Dim
variableDeclarator
=
TryCast
(
modifiedIdentifier
.
Parent
,
VariableDeclaratorSyntax
)
Dim
fieldDecl
=
TryCast
(
variableDeclarator
?
.
Parent
,
FieldDeclarationSyntax
)
If
fieldDecl
IsNot
Nothing
Then
Dim
kind
=
If
(
fieldDecl
.
Modifiers
.
Any
(
Function
(
m
)
m
.
Kind
()
=
SyntaxKind
.
ConstKeyword
),
DeclaredSymbolInfoKind
.
Constant
,
DeclaredSymbolInfoKind
.
Field
)
declaredSymbolInfo
=
New
DeclaredSymbolInfo
(
project
,
modifiedIdentifier
.
Identifier
.
ValueText
,
Nothing
,
GetContainerDisplayName
(
fieldDecl
.
Parent
),
GetFullyQualifiedContainerName
(
fieldDecl
.
Parent
),
kind
,
GetAccessibility
(
fieldDecl
,
fieldDecl
.
Modifiers
),
modifiedIdentifier
.
Identifier
.
Span
,
ImmutableArray
(
Of
String
).
Empty
)
Return
True
End
If
Case
SyntaxKind
.
ModuleBlock
Dim
moduleDecl
=
CType
(
node
,
ModuleBlockSyntax
)
declaredSymbolInfo
=
New
DeclaredSymbolInfo
(
project
,
moduleDecl
.
ModuleStatement
.
Identifier
.
ValueText
,
GetTypeParameterSuffix
(
moduleDecl
.
ModuleStatement
.
TypeParameterList
),
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
DeclaredSymbolInfoKind
.
Module
,
GetAccessibility
(
moduleDecl
,
moduleDecl
.
ModuleStatement
.
Modifiers
),
moduleDecl
.
ModuleStatement
.
Identifier
.
Span
,
GetInheritanceNames
(
project
,
moduleDecl
))
Return
True
Case
SyntaxKind
.
PropertyStatement
Dim
propertyDecl
=
CType
(
node
,
PropertyStatementSyntax
)
Dim
statementOrBlock
=
If
(
TypeOf
node
.
Parent
Is
PropertyBlockSyntax
,
node
.
Parent
,
node
)
Dim
propertyParent
=
statementOrBlock
.
Parent
declaredSymbolInfo
=
New
DeclaredSymbolInfo
(
project
,
propertyDecl
.
Identifier
.
ValueText
,
GetPropertySuffix
(
propertyDecl
),
GetContainerDisplayName
(
propertyParent
),
GetFullyQualifiedContainerName
(
propertyParent
),
DeclaredSymbolInfoKind
.
Property
,
GetAccessibility
(
statementOrBlock
,
propertyDecl
.
Modifiers
),
propertyDecl
.
Identifier
.
Span
,
ImmutableArray
(
Of
String
).
Empty
)
Return
True
Case
SyntaxKind
.
StructureBlock
Dim
structDecl
=
CType
(
node
,
StructureBlockSyntax
)
declaredSymbolInfo
=
New
DeclaredSymbolInfo
(
project
,
structDecl
.
StructureStatement
.
Identifier
.
ValueText
,
GetTypeParameterSuffix
(
structDecl
.
StructureStatement
.
TypeParameterList
),
GetContainerDisplayName
(
node
.
Parent
),
GetFullyQualifiedContainerName
(
node
.
Parent
),
DeclaredSymbolInfoKind
.
Struct
,
GetAccessibility
(
structDecl
,
structDecl
.
StructureStatement
.
Modifiers
),
structDecl
.
StructureStatement
.
Identifier
.
Span
,
GetInheritanceNames
(
project
,
structDecl
))
Public
Function
IsStartOfUnicodeEscapeSequence
(
c
As
Char
)
As
Boolean
Implements
ISyntaxFactsService
.
IsStartOfUnicodeEscapeSequence
Return
False
' VB does not support identifiers with escaped unicode characters
End
Function
Public
Function
IsLiteral
(
token
As
SyntaxToken
)
As
Boolean
Implements
ISyntaxFactsService
.
IsLiteral
Select
Case
token
.
Kind
()
Case
_
SyntaxKind
.
IntegerLiteralToken
,
SyntaxKind
.
CharacterLiteralToken
,
SyntaxKind
.
DecimalLiteralToken
,
SyntaxKind
.
FloatingLiteralToken
,
SyntaxKind
.
DateLiteralToken
,
SyntaxKind
.
StringLiteralToken
,
SyntaxKind
.
DollarSignDoubleQuoteToken
,
SyntaxKind
.
DoubleQuoteToken
,
SyntaxKind
.
InterpolatedStringTextToken
,
SyntaxKind
.
TrueKeyword
,
SyntaxKind
.
FalseKeyword
,
SyntaxKind
.
NothingKeyword
Return
True
End
Select
declaredSymbolInfo
=
Nothing
Return
False
End
Function
Private
Function
GetMethodSuffix
(
method
As
MethodBlockSyntax
)
As
String
Return
GetTypeParameterSuffix
(
method
.
SubOrFunctionStatement
.
TypeParameterList
)
&
GetSuffix
(
method
.
SubOrFunctionStatement
.
ParameterList
)
Public
Function
IsStringLiteralOrInterpolatedStringLiteral
(
token
As
SyntaxToken
)
As
Boolean
Implements
ISyntaxFactsService
.
IsStringLiteralOrInterpolatedStringLiteral
Return
token
.
IsKind
(
SyntaxKind
.
StringLiteralToken
,
SyntaxKind
.
InterpolatedStringTextToken
)
End
Function
P
rivate
Function
GetConstructorSuffix
(
method
As
ConstructorBlockSyntax
)
As
String
Return
".New"
&
GetSuffix
(
method
.
SubNewStatement
.
ParameterList
)
P
ublic
Function
IsNumericLiteralExpression
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsNumericLiteralExpression
Return
If
(
node
Is
Nothing
,
False
,
node
.
IsKind
(
SyntaxKind
.
NumericLiteralExpression
)
)
End
Function
Private
Function
GetPropertySuffix
(
[
property
]
As
PropertyStatementSyntax
)
As
String
If
[
property
]
.
ParameterList
Is
Nothing
Then
Return
Nothing
Public
Function
IsBindableToken
(
token
As
Microsoft
.
CodeAnalysis
.
SyntaxToken
)
As
Boolean
Implements
ISyntaxFactsService
.
IsBindableToken
Return
Me
.
IsWord
(
token
)
OrElse
Me
.
IsLiteral
(
token
)
OrElse
Me
.
IsOperator
(
token
)
End
Function
Public
Function
IsSimpleMemberAccessExpression
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsSimpleMemberAccessExpression
Return
TypeOf
node
Is
MemberAccessExpressionSyntax
AndAlso
DirectCast
(
node
,
MemberAccessExpressionSyntax
).
Kind
=
SyntaxKind
.
SimpleMemberAccessExpression
End
Function
Public
Function
IsPointerMemberAccessExpression
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsPointerMemberAccessExpression
Return
False
End
Function
Public
Sub
GetNameAndArityOfSimpleName
(
node
As
SyntaxNode
,
ByRef
name
As
String
,
ByRef
arity
As
Integer
)
Implements
ISyntaxFactsService
.
GetNameAndArityOfSimpleName
Dim
simpleName
=
TryCast
(
node
,
SimpleNameSyntax
)
If
simpleName
IsNot
Nothing
Then
name
=
simpleName
.
Identifier
.
ValueText
arity
=
simpleName
.
Arity
End
If
End
Sub
Return
GetSuffix
(
[
property
]
.
ParameterList
)
Public
Function
GetExpressionOfMemberAccessExpression
(
node
As
SyntaxNode
,
Optional
allowImplicitTarget
As
Boolean
=
False
)
As
SyntaxNode
Implements
ISyntaxFactsService
.
GetExpressionOfMemberAccessExpression
Return
TryCast
(
node
,
MemberAccessExpressionSyntax
)
?
.
GetExpressionOfMemberAccessExpression
(
allowImplicitTarget
)
End
Function
Private
Function
GetTypeParameterSuffix
(
typeParameterList
As
TypeParameterListSyntax
)
As
String
If
typeParameterList
Is
Nothing
Then
Return
Nothing
Public
Function
GetTargetOfMemberBinding
(
node
As
SyntaxNode
)
As
SyntaxNode
Implements
ISyntaxFactsService
.
GetTargetOfMemberBinding
' Member bindings are a C# concept.
Return
Nothing
End
Function
Public
Function
GetExpressionOfConditionalAccessExpression
(
node
As
SyntaxNode
)
As
SyntaxNode
Implements
ISyntaxFactsService
.
GetExpressionOfConditionalAccessExpression
Return
TryCast
(
node
,
ConditionalAccessExpressionSyntax
)
?
.
Expression
End
Function
Public
Function
GetExpressionOfElementAccessExpression
(
node
As
SyntaxNode
)
As
SyntaxNode
Implements
ISyntaxFactsService
.
GetExpressionOfElementAccessExpression
Return
TryCast
(
node
,
InvocationExpressionSyntax
)
?
.
Expression
End
Function
Public
Function
GetArgumentListOfElementAccessExpression
(
node
As
SyntaxNode
)
As
SyntaxNode
Implements
ISyntaxFactsService
.
GetArgumentListOfElementAccessExpression
Return
TryCast
(
node
,
InvocationExpressionSyntax
)
?
.
ArgumentList
End
Function
Public
Function
GetExpressionOfInterpolation
(
node
As
SyntaxNode
)
As
SyntaxNode
Implements
ISyntaxFactsService
.
GetExpressionOfInterpolation
Return
TryCast
(
node
,
InterpolationSyntax
)
?
.
Expression
End
Function
Public
Function
IsInNamespaceOrTypeContext
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsInNamespaceOrTypeContext
Return
SyntaxFacts
.
IsInNamespaceOrTypeContext
(
node
)
End
Function
Public
Function
IsInStaticContext
(
node
As
Microsoft
.
CodeAnalysis
.
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsInStaticContext
Return
node
.
IsInStaticContext
()
End
Function
Public
Function
GetExpressionOfArgument
(
node
As
Microsoft
.
CodeAnalysis
.
SyntaxNode
)
As
Microsoft
.
CodeAnalysis
.
SyntaxNode
Implements
ISyntaxFactsService
.
GetExpressionOfArgument
Return
TryCast
(
node
,
ArgumentSyntax
).
GetArgumentExpression
()
End
Function
Public
Function
GetRefKindOfArgument
(
node
As
Microsoft
.
CodeAnalysis
.
SyntaxNode
)
As
Microsoft
.
CodeAnalysis
.
RefKind
Implements
ISyntaxFactsService
.
GetRefKindOfArgument
' TODO(cyrusn): Consider the method this argument is passed to, to determine this.
Return
RefKind
.
None
End
Function
Public
Function
IsSimpleArgument
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsSimpleArgument
Dim
argument
=
DirectCast
(
node
,
ArgumentSyntax
)
Return
Not
argument
.
IsNamed
AndAlso
Not
argument
.
IsOmitted
End
Function
Public
Function
IsInConstantContext
(
node
As
Microsoft
.
CodeAnalysis
.
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsInConstantContext
Return
node
.
IsInConstantContext
()
End
Function
Public
Function
IsInConstructor
(
node
As
Microsoft
.
CodeAnalysis
.
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsInConstructor
Return
node
.
GetAncestors
(
Of
StatementSyntax
).
Any
(
Function
(
s
)
s
.
Kind
=
SyntaxKind
.
ConstructorBlock
)
End
Function
Public
Function
IsUnsafeContext
(
node
As
Microsoft
.
CodeAnalysis
.
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsUnsafeContext
Return
False
End
Function
Public
Function
GetNameOfAttribute
(
node
As
Microsoft
.
CodeAnalysis
.
SyntaxNode
)
As
Microsoft
.
CodeAnalysis
.
SyntaxNode
Implements
ISyntaxFactsService
.
GetNameOfAttribute
Return
DirectCast
(
node
,
AttributeSyntax
).
Name
End
Function
Public
Function
IsAttribute
(
node
As
Microsoft
.
CodeAnalysis
.
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsAttribute
Return
TypeOf
node
Is
AttributeSyntax
End
Function
Public
Function
IsAttributeNamedArgumentIdentifier
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsAttributeNamedArgumentIdentifier
Dim
identifierName
=
TryCast
(
node
,
IdentifierNameSyntax
)
Return
identifierName
.
IsParentKind
(
SyntaxKind
.
NameColonEquals
)
AndAlso
identifierName
.
Parent
.
IsParentKind
(
SyntaxKind
.
SimpleArgument
)
AndAlso
identifierName
.
Parent
.
Parent
.
IsParentKind
(
SyntaxKind
.
ArgumentList
)
AndAlso
identifierName
.
Parent
.
Parent
.
Parent
.
IsParentKind
(
SyntaxKind
.
Attribute
)
End
Function
Public
Function
GetContainingTypeDeclaration
(
root
As
SyntaxNode
,
position
As
Integer
)
As
SyntaxNode
Implements
ISyntaxFactsService
.
GetContainingTypeDeclaration
If
root
Is
Nothing
Then
Throw
New
ArgumentNullException
(
NameOf
(
root
))
End
If
Dim
pooledBuilder
=
PooledStringBuilder
.
GetInstance
()
If
position
<
0
OrElse
position
>
root
.
Span
.
End
Then
Throw
New
ArgumentOutOfRangeException
(
NameOf
(
position
))
End
If
Dim
builder
=
pooledBuilder
.
Builder
builder
.
Append
(
"(Of "
)
Return
root
.
FindToken
(
position
).
GetAncestors
(
Of
SyntaxNode
)().
FirstOrDefault
(
Function
(
n
)
TypeOf
n
Is
TypeBlockSyntax
OrElse
TypeOf
n
Is
DelegateStatementSyntax
)
End
Function
Dim
First
=
True
For
Each
parameter
In
typeParameterList
.
Parameters
If
Not
First
Then
builder
.
Append
(
", "
)
Public
Function
GetContainingVariableDeclaratorOfFieldDeclaration
(
node
As
SyntaxNode
)
As
SyntaxNode
Implements
ISyntaxFactsService
.
GetContainingVariableDeclaratorOfFieldDeclaration
If
node
Is
Nothing
Then
Throw
New
ArgumentNullException
(
NameOf
(
node
))
End
If
Dim
parent
=
node
.
Parent
While
node
IsNot
Nothing
If
node
.
Kind
=
SyntaxKind
.
VariableDeclarator
AndAlso
node
.
IsParentKind
(
SyntaxKind
.
FieldDeclaration
)
Then
Return
node
End
If
builder
.
Append
(
parameter
.
Identifier
.
Text
)
First
=
False
Next
node
=
node
.
Parent
End
While
builder
.
Append
(
")"
c
)
Return
Nothing
End
Function
Return
pooledBuilder
.
ToStringAndFree
()
Public
Function
FindTokenOnLeftOfPosition
(
node
As
SyntaxNode
,
position
As
Integer
,
Optional
includeSkipped
As
Boolean
=
True
,
Optional
includeDirectives
As
Boolean
=
False
,
Optional
includeDocumentationComments
As
Boolean
=
False
)
As
SyntaxToken
Implements
ISyntaxFactsService
.
FindTokenOnLeftOfPosition
Return
node
.
FindTokenOnLeftOfPosition
(
position
,
includeSkipped
,
includeDirectives
,
includeDocumentationComments
)
End
Function
Public
Function
FindTokenOnRightOfPosition
(
node
As
SyntaxNode
,
position
As
Integer
,
Optional
includeSkipped
As
Boolean
=
True
,
Optional
includeDirectives
As
Boolean
=
False
,
Optional
includeDocumentationComments
As
Boolean
=
False
)
As
SyntaxToken
Implements
ISyntaxFactsService
.
FindTokenOnRightOfPosition
Return
node
.
FindTokenOnRightOfPosition
(
position
,
includeSkipped
,
includeDirectives
,
includeDocumentationComments
)
End
Function
Public
Function
IsObjectCreationExpression
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsObjectCreationExpression
Return
TypeOf
node
Is
ObjectCreationExpressionSyntax
End
Function
''' <summary>
''' Builds up the suffix to show for something with parameters in navigate-to.
''' While it would be nice to just use the compiler SymbolDisplay API for this,
''' it would be too expensive as it requires going back to Symbols (which requires
''' creating compilations, etc.) in a perf sensitive area.
'''
''' So, instead, we just build a reasonable suffix using the pure syntax that a
''' user provided. That means that if they wrote "Method(System.Int32 i)" we'll
''' show that as "Method(System.Int32)" Not "Method(Integer)". Given that this Is
''' actually what the user wrote, And it saves us from ever having to go back to
''' symbols/compilations, this Is well worth it, even if it does mean we have to
''' create our own 'symbol display' logic here.
''' </summary>
Private
Function
GetSuffix
(
parameterList
As
ParameterListSyntax
)
As
String
If
parameterList
Is
Nothing
OrElse
parameterList
.
Parameters
.
Count
=
0
Then
Return
"()"
Public
Function
IsObjectInitializerNamedAssignmentIdentifier
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsObjectInitializerNamedAssignmentIdentifier
Dim
unused
As
SyntaxNode
=
Nothing
Return
IsObjectInitializerNamedAssignmentIdentifier
(
node
,
unused
)
End
Function
Public
Function
IsObjectInitializerNamedAssignmentIdentifier
(
node
As
SyntaxNode
,
ByRef
initializedInstance
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsObjectInitializerNamedAssignmentIdentifier
Dim
identifier
=
TryCast
(
node
,
IdentifierNameSyntax
)
If
identifier
?
.
IsChildNode
(
Of
NamedFieldInitializerSyntax
)(
Function
(
n
)
n
.
Name
)
Then
' .parent is the NamedField.
' .parent.parent is the ObjectInitializer.
' .parent.parent.parent will be the ObjectCreationExpression.
initializedInstance
=
identifier
.
Parent
.
Parent
.
Parent
Return
True
End
If
Return
False
End
Function
Public
Function
IsElementAccessExpression
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsElementAccessExpression
' VB doesn't have a specialized node for element access. Instead, it just uses an
' invocation expression or dictionary access expression.
Return
node
.
Kind
=
SyntaxKind
.
InvocationExpression
OrElse
node
.
Kind
=
SyntaxKind
.
DictionaryAccessExpression
End
Function
Public
Function
ToIdentifierToken
(
name
As
String
)
As
SyntaxToken
Implements
ISyntaxFactsService
.
ToIdentifierToken
Return
name
.
ToIdentifierToken
()
End
Function
Public
Function
Parenthesize
(
expression
As
SyntaxNode
,
Optional
includeElasticTrivia
As
Boolean
=
True
)
As
SyntaxNode
Implements
ISyntaxFactsService
.
Parenthesize
Return
DirectCast
(
expression
,
ExpressionSyntax
).
Parenthesize
()
End
Function
Public
Function
IsTypeNamedVarInVariableOrFieldDeclaration
(
token
As
SyntaxToken
,
parent
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsTypeNamedVarInVariableOrFieldDeclaration
Return
False
End
Function
Public
Function
IsTypeNamedDynamic
(
token
As
SyntaxToken
,
parent
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsTypeNamedDynamic
Return
False
End
Function
Public
Function
IsIndexerMemberCRef
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsIndexerMemberCRef
Return
False
End
Function
Public
Function
GetContainingMemberDeclaration
(
root
As
SyntaxNode
,
position
As
Integer
,
Optional
useFullSpan
As
Boolean
=
True
)
As
SyntaxNode
Implements
ISyntaxFactsService
.
GetContainingMemberDeclaration
Contract
.
ThrowIfNull
(
root
,
NameOf
(
root
))
Contract
.
ThrowIfTrue
(
position
<
0
OrElse
position
>
root
.
FullSpan
.
End
,
NameOf
(
position
))
Dim
[
end
]
=
root
.
FullSpan
.
End
If
[
end
]
=
0
Then
' empty file
Return
Nothing
End
If
Dim
pooledBuilder
=
PooledStringBuilder
.
GetInstance
()
' make sure position doesn't touch end of root
position
=
Math
.
Min
(
position
,
[
end
]
-
1
)
Dim
builder
=
pooledBuilder
.
Builder
builder
.
Append
(
"("
c
)
If
parameterList
IsNot
Nothing
Then
AppendParameters
(
parameterList
.
Parameters
,
builder
)
End
If
builder
.
Append
(
")"
c
)
Dim
node
=
root
.
FindToken
(
position
).
Parent
While
node
IsNot
Nothing
If
useFullSpan
OrElse
node
.
Span
.
Contains
(
position
)
Then
Return
pooledBuilder
.
ToStringAndFree
()
End
Function
If
TypeOf
node
Is
MethodBlockBaseSyntax
AndAlso
Not
TypeOf
node
.
Parent
Is
PropertyBlockSyntax
Then
Return
node
End
If
Private
Sub
AppendParameters
(
parameters
As
SeparatedSyntaxList
(
Of
ParameterSyntax
),
builder
As
StringBuilder
)
Dim
First
=
True
For
Each
parameter
In
parameters
If
Not
First
Then
builder
.
Append
(
", "
)
End
If
If
TypeOf
node
Is
PropertyStatementSyntax
AndAlso
Not
TypeOf
node
.
Parent
Is
PropertyBlockSyntax
Then
Return
node
End
If
For
Each
modifier
In
parameter
.
Modifiers
If
modifier
.
Kind
()
<>
SyntaxKind
.
ByValKeyword
Then
builder
.
Append
(
modifier
.
Text
)
builder
.
Append
(
" "
c
)
If
TypeOf
node
Is
EventStatementSyntax
AndAlso
Not
TypeOf
node
.
Parent
Is
EventBlockSyntax
Then
Return
node
End
If
Next
If
parameter
.
AsClause
?
.
Type
IsNot
Nothing
Then
AppendTokens
(
parameter
.
AsClause
.
Type
,
builder
)
If
TypeOf
node
Is
PropertyBlockSyntax
OrElse
TypeOf
node
Is
TypeBlockSyntax
OrElse
TypeOf
node
Is
EnumBlockSyntax
OrElse
TypeOf
node
Is
NamespaceBlockSyntax
OrElse
TypeOf
node
Is
EventBlockSyntax
OrElse
TypeOf
node
Is
FieldDeclarationSyntax
Then
Return
node
End
If
End
If
First
=
False
Next
End
Sub
node
=
node
.
Parent
End
While
Private
Function
GetAccessibility
(
node
As
SyntaxNode
,
modifiers
As
SyntaxTokenList
)
As
Accessibility
Dim
sawFriend
=
False
Return
Nothing
End
Function
For
Each
modifier
In
modifiers
Select
Case
modifier
.
Kind
()
Case
SyntaxKind
.
PublicKeyword
:
Return
Accessibility
.
Public
Case
SyntaxKind
.
PrivateKeyword
:
Return
Accessibility
.
Private
Case
SyntaxKind
.
ProtectedKeyword
:
Return
Accessibility
.
Protected
Case
SyntaxKind
.
FriendKeyword
sawFriend
=
True
Continue
For
End
Select
Next
Public
Function
IsMethodLevelMember
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsMethodLevelMember
If
sawFriend
Then
Return
Accessibility
.
Internal
' Note: Derived types of MethodBaseSyntax are expanded explicitly, since PropertyStatementSyntax and
' EventStatementSyntax will NOT be parented by MethodBlockBaseSyntax. Additionally, there are things
' like AccessorStatementSyntax and DelegateStatementSyntax that we never want to tread as method level
' members.
If
TypeOf
node
Is
MethodStatementSyntax
AndAlso
Not
TypeOf
node
.
Parent
Is
MethodBlockBaseSyntax
Then
Return
True
End
If
' No accessibility modifiers
Select
Case
node
.
Parent
.
Kind
()
Case
SyntaxKind
.
ClassBlock
' In a class, fields and shared-constructors are private by default,
' everything Else Is Public
If
node
.
Kind
()
=
SyntaxKind
.
FieldDeclaration
Then
Return
Accessibility
.
Private
End
If
If
TypeOf
node
Is
SubNewStatementSyntax
AndAlso
Not
TypeOf
node
.
Parent
Is
MethodBlockBaseSyntax
Then
Return
True
End
If
If
node
.
Kind
()
=
SyntaxKind
.
ConstructorBlock
AndAlso
DirectCast
(
node
,
ConstructorBlockSyntax
).
SubNewStatement
.
Modifiers
.
Any
(
SyntaxKind
.
SharedKeyword
)
Then
Return
Accessibility
.
Private
End
If
If
TypeOf
node
Is
OperatorStatementSyntax
AndAlso
Not
TypeOf
node
.
Parent
Is
MethodBlockBaseSyntax
Then
Return
True
End
If
Return
Accessibility
.
Public
If
TypeOf
node
Is
PropertyStatementSyntax
AndAlso
Not
TypeOf
node
.
Parent
Is
PropertyBlockSyntax
Then
Return
True
End
If
Case
SyntaxKind
.
StructureBlock
,
SyntaxKind
.
InterfaceBlock
,
SyntaxKind
.
ModuleBlock
' Everything in a struct/interface/module is public
Return
Accessibility
.
Public
End
Select
If
TypeOf
node
Is
EventStatementSyntax
AndAlso
Not
TypeOf
node
.
Parent
Is
EventBlockSyntax
Then
Return
True
End
If
' Otherwise, it's internal
Return
Accessibility
.
Internal
End
Function
If
TypeOf
node
Is
DeclareStatementSyntax
Then
Return
True
End
If
Private
Function
GetInheritanceNames
(
project
As
Project
,
typeBlock
As
TypeBlockSyntax
)
As
ImmutableArray
(
Of
String
)
Dim
builder
=
ArrayBuilder
(
Of
String
).
GetInstance
()
Return
TypeOf
node
Is
ConstructorBlockSyntax
OrElse
TypeOf
node
Is
MethodBlockSyntax
OrElse
TypeOf
node
Is
OperatorBlockSyntax
OrElse
TypeOf
node
Is
EventBlockSyntax
OrElse
TypeOf
node
Is
PropertyBlockSyntax
OrElse
TypeOf
node
Is
EnumMemberDeclarationSyntax
OrElse
TypeOf
node
Is
FieldDeclarationSyntax
End
Function
Dim
aliasMap
=
GetAliasMap
(
typeBlock
)
Try
For
Each
inheritsStatement
In
typeBlock
.
Inherits
AddInheritanceNames
(
builder
,
inheritsStatement
.
Types
,
aliasMap
)
Next
Public
Function
GetMemberBodySpanForSpeculativeBinding
(
node
As
SyntaxNode
)
As
TextSpan
Implements
ISyntaxFactsService
.
GetMemberBodySpanForSpeculativeBinding
Dim
member
=
GetContainingMemberDeclaration
(
node
,
node
.
SpanStart
)
If
member
Is
Nothing
Then
Return
Nothing
End
If
For
Each
implementsStatement
In
typeBlock
.
Implements
AddInheritanceNames
(
builder
,
implementsStatement
.
Types
,
aliasMap
)
Next
' TODO: currently we only support method for now
Dim
method
=
TryCast
(
member
,
MethodBlockBaseSyntax
)
If
method
IsNot
Nothing
Then
If
method
.
BlockStatement
Is
Nothing
OrElse
method
.
EndBlockStatement
Is
Nothing
Then
Return
Nothing
End
If
DeclaredSymbolInfo
.
Intern
(
project
,
builder
)
Return
builder
.
ToImmutableAndFree
()
Finally
FreeAliasMap
(
aliasMap
)
End
Try
End
Function
' We don't want to include the BlockStatement or any trailing trivia up to and including its statement
' terminator in the span. Instead, we use the start of the first statement's leading trivia (if any) up
' to the start of the EndBlockStatement. If there aren't any statements in the block, we use the start
' of the EndBlockStatements leading trivia.
Private
Function
GetAliasMap
(
typeBlock
As
TypeBlockSyntax
)
As
Dictionary
(
Of
String
,
String
)
Dim
compilationUnit
=
typeBlock
.
SyntaxTree
.
GetCompilationUnitRoot
()
Dim
firstStatement
=
method
.
Statements
.
FirstOrDefault
()
Dim
spanStart
=
If
(
firstStatement
IsNot
Nothing
,
firstStatement
.
FullSpan
.
Start
,
method
.
EndBlockStatement
.
FullSpan
.
Start
)
Dim
aliasMap
As
Dictionary
(
Of
String
,
String
)
=
Nothing
For
Each
import
In
compilationUnit
.
Imports
For
Each
clause
In
import
.
ImportsClauses
If
clause
.
IsKind
(
SyntaxKind
.
SimpleImportsClause
)
Then
Dim
simpleImport
=
DirectCast
(
clause
,
SimpleImportsClauseSyntax
)
If
simpleImport
.
Alias
IsNot
Nothing
Then
Dim
mappedName
=
GetTypeName
(
simpleImport
.
Name
)
If
mappedName
IsNot
Nothing
Then
aliasMap
=
If
(
aliasMap
,
AllocateAliasMap
())
aliasMap
(
simpleImport
.
Alias
.
Identifier
.
ValueText
)
=
mappedName
End
If
End
If
End
If
Next
Next
Return
TextSpan
.
FromBounds
(
spanStart
,
method
.
EndBlockStatement
.
SpanStart
)
End
If
Return
aliasMap
Return
Nothing
End
Function
Private
Sub
AddInheritanceNames
(
builder
As
ArrayBuilder
(
Of
String
),
types
As
SeparatedSyntaxList
(
Of
TypeSyntax
),
aliasMap
As
Dictionary
(
Of
String
,
String
))
Public
Function
ContainsInMemberBody
(
node
As
SyntaxNode
,
span
As
TextSpan
)
As
Boolean
Implements
ISyntaxFactsService
.
ContainsInMemberBody
Dim
method
=
TryCast
(
node
,
MethodBlockBaseSyntax
)
If
method
IsNot
Nothing
Then
Return
method
.
Statements
.
Count
>
0
AndAlso
ContainsExclusively
(
GetSyntaxListSpan
(
method
.
Statements
),
span
)
End
If
For
Each
typeSyntax
In
types
AddInheritanceName
(
builder
,
typeSyntax
,
aliasMap
)
Next
End
Sub
Dim
[
event
]
=
TryCast
(
node
,
EventBlockSyntax
)
If
[
event
]
IsNot
Nothing
Then
Return
[
event
]
.
Accessors
.
Count
>
0
AndAlso
ContainsExclusively
(
GetSyntaxListSpan
(
[
event
]
.
Accessors
),
span
)
End
If
Private
Sub
AddInheritanceName
(
builder
As
ArrayBuilder
(
Of
String
),
typeSyntax
As
TypeSyntax
,
aliasMap
As
Dictionary
(
Of
String
,
String
))
Dim
name
=
GetTypeName
(
typeSyntax
)
If
name
IsNot
Nothing
Then
builder
.
Add
(
name
)
Dim
[
property
]
=
TryCast
(
node
,
PropertyBlockSyntax
)
If
[
property
]
IsNot
Nothing
Then
Return
[
property
]
.
Accessors
.
Count
>
0
AndAlso
ContainsExclusively
(
GetSyntaxListSpan
(
[
property
]
.
Accessors
),
span
)
End
If
Dim
mappedName
As
String
=
Nothing
If
aliasMap
?
.
TryGetValue
(
name
,
mappedName
)
=
True
Then
' Looks Like this could be an alias. Also include the name the alias points to
builder
.
Add
(
mappedName
)
End
If
Dim
field
=
TryCast
(
node
,
FieldDeclarationSyntax
)
If
field
IsNot
Nothing
Then
Return
field
.
Declarators
.
Count
>
0
AndAlso
ContainsExclusively
(
GetSeparatedSyntaxListSpan
(
field
.
Declarators
),
span
)
End
If
End
Sub
Private
Function
GetTypeName
(
typeSyntax
As
TypeSyntax
)
As
String
If
TypeOf
typeSyntax
Is
SimpleNameSyntax
Then
Return
GetSimpleName
(
DirectCast
(
typeSyntax
,
SimpleNameSyntax
))
ElseIf
TypeOf
typeSyntax
Is
QualifiedNameSyntax
Then
Return
GetSimpleName
(
DirectCast
(
typeSyntax
,
QualifiedNameSyntax
).
Right
)
Dim
[
enum
]
=
TryCast
(
node
,
EnumMemberDeclarationSyntax
)
If
[
enum
]
IsNot
Nothing
Then
Return
[
enum
]
.
Initializer
IsNot
Nothing
AndAlso
ContainsExclusively
(
[
enum
]
.
Initializer
.
Span
,
span
)
End
If
Return
Nothing
Dim
propStatement
=
TryCast
(
node
,
PropertyStatementSyntax
)
If
propStatement
IsNot
Nothing
Then
Return
propStatement
.
Initializer
IsNot
Nothing
AndAlso
ContainsExclusively
(
propStatement
.
Initializer
.
Span
,
span
)
End
If
Return
False
End
Function
Private
Function
GetSimpleName
(
simpleName
As
SimpleNameSyntax
)
As
String
Return
simpleName
.
Identifier
.
ValueText
Private
Function
ContainsExclusively
(
outerSpan
As
TextSpan
,
innerSpan
As
TextSpan
)
As
Boolean
If
innerSpan
.
IsEmpty
Then
Return
outerSpan
.
Contains
(
innerSpan
.
Start
)
End
If
Return
outerSpan
.
Contains
(
innerSpan
)
End
Function
Private
Function
GetContainerDisplayName
(
node
As
SyntaxNode
)
As
String
Return
GetDisplayName
(
node
,
DisplayNameOptions
.
IncludeTypeParameters
)
Private
Function
GetSyntaxListSpan
(
Of
T
As
SyntaxNode
)(
list
As
SyntaxList
(
Of
T
))
As
TextSpan
Contract
.
Requires
(
list
.
Count
>
0
)
Return
TextSpan
.
FromBounds
(
list
.
First
.
SpanStart
,
list
.
Last
.
Span
.
End
)
End
Function
Private
Function
GetFullyQualifiedContainerName
(
node
As
SyntaxNode
)
As
String
Return
GetDisplayName
(
node
,
DisplayNameOptions
.
IncludeNamespaces
)
Private
Function
GetSeparatedSyntaxListSpan
(
Of
T
As
SyntaxNode
)(
list
As
SeparatedSyntaxList
(
Of
T
))
As
TextSpan
Contract
.
Requires
(
list
.
Count
>
0
)
Return
TextSpan
.
FromBounds
(
list
.
First
.
SpanStart
,
list
.
Last
.
Span
.
End
)
End
Function
Public
Function
GetMethodLevelMembers
(
root
As
SyntaxNode
)
As
List
(
Of
SyntaxNode
)
Implements
ISyntaxFactsService
.
GetMethodLevelMembers
Dim
list
=
New
List
(
Of
SyntaxNode
)()
AppendMethodLevelMembers
(
root
,
list
)
Return
list
End
Function
Public
Function
IsTopLevelNodeWithMembers
(
node
As
SyntaxNode
)
As
Boolean
Implements
ISyntaxFactsService
.
IsTopLevelNodeWithMembers
Return
TypeOf
node
Is
NamespaceBlockSyntax
OrElse
TypeOf
node
Is
TypeBlockSyntax
OrElse
TypeOf
node
Is
EnumBlockSyntax
End
Function
Private
Const
s_dotToken
As
String
=
"."
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录