Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
ca892c8d
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,发现更多精彩内容 >>
提交
ca892c8d
编写于
6月 17, 2020
作者:
G
Gen Lu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add info for receiver of complex array type in syntax index
上级
fda2b7db
变更
11
隐藏空白更改
内联
并排
Showing
11 changed file
with
199 addition
and
171 deletion
+199
-171
src/EditorFeatures/CSharpTest/Completion/CompletionProviders/ExtensionMethodImportCompletionProviderTests.cs
...Providers/ExtensionMethodImportCompletionProviderTests.cs
+63
-1
src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/ExtensionMethodImportCompletionHelper.CacheEntry.cs
...vider/ExtensionMethodImportCompletionHelper.CacheEntry.cs
+11
-28
src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/ExtensionMethodImportCompletionHelper.cs
...mpletionProvider/ExtensionMethodImportCompletionHelper.cs
+31
-29
src/Workspaces/CSharp/Portable/FindSymbols/CSharpDeclaredSymbolInfoFactoryService.cs
...ble/FindSymbols/CSharpDeclaredSymbolInfoFactoryService.cs
+13
-15
src/Workspaces/Core/Portable/FindSymbols/SymbolTree/SymbolTreeInfo.Node.cs
...re/Portable/FindSymbols/SymbolTree/SymbolTreeInfo.Node.cs
+1
-1
src/Workspaces/Core/Portable/FindSymbols/SymbolTree/SymbolTreeInfo_Metadata.cs
...ortable/FindSymbols/SymbolTree/SymbolTreeInfo_Metadata.cs
+7
-7
src/Workspaces/Core/Portable/FindSymbols/SyntaxTree/SyntaxTreeIndex.ExtensionMethodInfo.cs
...Symbols/SyntaxTree/SyntaxTreeIndex.ExtensionMethodInfo.cs
+24
-36
src/Workspaces/Core/Portable/FindSymbols/SyntaxTree/SyntaxTreeIndex_Create.cs
...Portable/FindSymbols/SyntaxTree/SyntaxTreeIndex_Create.cs
+19
-31
src/Workspaces/Core/Portable/FindSymbols/SyntaxTree/SyntaxTreeIndex_Forwarders.cs
...able/FindSymbols/SyntaxTree/SyntaxTreeIndex_Forwarders.cs
+2
-5
src/Workspaces/Core/Portable/LanguageServices/DeclaredSymbolFactoryService/AbstractDeclaredSymbolInfoFactoryService.cs
...actoryService/AbstractDeclaredSymbolInfoFactoryService.cs
+14
-3
src/Workspaces/VisualBasic/Portable/FindSymbols/VisualBasicDeclaredSymbolInfoFactoryService.vb
...indSymbols/VisualBasicDeclaredSymbolInfoFactoryService.vb
+14
-15
未找到文件。
src/EditorFeatures/CSharpTest/Completion/CompletionProviders/ExtensionMethodImportCompletionProviderTests.cs
浏览文件 @
ca892c8d
...
...
@@ -1379,7 +1379,7 @@ public void M(int x)
[
InlineData
(
ReferenceType
.
Metadata
,
"[,]"
,
"ExtentionMethod4"
)]
[
InlineData
(
ReferenceType
.
Metadata
,
"[][,]"
,
"ExtentionMethod5"
)]
[
Theory
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
Completion
)]
public
async
Task
TestExtensionMethodsForArrayType
(
ReferenceType
refType
,
string
rank
,
string
expectedName
)
public
async
Task
TestExtensionMethodsFor
Simple
ArrayType
(
ReferenceType
refType
,
string
rank
,
string
expectedName
)
{
var
refDoc
=
$@"
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo(""Project1"")]
...
...
@@ -1429,6 +1429,68 @@ public void M(int{rank} x)
glyph
:
(
int
)
Glyph
.
ExtensionMethodPublic
,
inlineDescription
:
"Foo"
);
}
[
InlineData
(
ReferenceType
.
Project
,
"[]"
,
"ExtentionMethod2"
)]
[
InlineData
(
ReferenceType
.
Project
,
"[][]"
,
"ExtentionMethod3"
)]
[
InlineData
(
ReferenceType
.
Project
,
"[,]"
,
"ExtentionMethod4"
)]
[
InlineData
(
ReferenceType
.
Project
,
"[][,]"
,
"ExtentionMethod5"
)]
[
InlineData
(
ReferenceType
.
Metadata
,
"[]"
,
"ExtentionMethod2"
)]
[
InlineData
(
ReferenceType
.
Metadata
,
"[][]"
,
"ExtentionMethod3"
)]
[
InlineData
(
ReferenceType
.
Metadata
,
"[,]"
,
"ExtentionMethod4"
)]
[
InlineData
(
ReferenceType
.
Metadata
,
"[][,]"
,
"ExtentionMethod5"
)]
[
Theory
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
Completion
)]
public
async
Task
TestExtensionMethodsForGenericArrayType
(
ReferenceType
refType
,
string
rank
,
string
expectedName
)
{
var
refDoc
=
$@"
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo(""Project1"")]
namespace Foo
{{
public
static
class
ExtensionClass
{{
public
static
bool
ExtentionMethod1
<
T
>(
this
T
x
)
=>
true
;
public
static
bool
ExtentionMethod2
<
T
>(
this
T
[]
x
)
=>
true
;
public
static
bool
ExtentionMethod3
<
T
>(
this
T
[][]
x
)
=>
true
;
public
static
bool
ExtentionMethod4
<
T
>(
this
T
[,]
x
)
=>
true
;
public
static
bool
ExtentionMethod5
<
T
>(
this
T
[][,]
x
)
=>
true
;
}}
}}
"
;
var
srcDoc
=
$@"
namespace Baz
{{
public
class
Bat
{{
public
void
M
(
int
{
rank
}
x
)
{{
x
.
$$
}}
}}
}}
"
;
var
markup
=
refType
switch
{
ReferenceType
.
Project
=>
CreateMarkupForProjectWithProjectReference
(
srcDoc
,
refDoc
,
LanguageNames
.
CSharp
,
LanguageNames
.
CSharp
),
ReferenceType
.
Metadata
=>
CreateMarkupForProjectWithMetadataReference
(
srcDoc
,
refDoc
,
LanguageNames
.
CSharp
,
LanguageNames
.
CSharp
),
_
=>
null
,
};
await
VerifyImportItemExistsAsync
(
markup
,
expectedName
,
displayTextSuffix
:
"<>"
,
glyph
:
(
int
)
Glyph
.
ExtensionMethodPublic
,
inlineDescription
:
"Foo"
);
}
private
Task
VerifyImportItemExistsAsync
(
string
markup
,
string
expectedItem
,
int
glyph
,
string
inlineDescription
,
string
displayTextSuffix
=
null
,
string
expectedDescriptionOrNull
=
null
)
=>
VerifyItemExistsAsync
(
markup
,
expectedItem
,
displayTextSuffix
:
displayTextSuffix
,
glyph
:
glyph
,
inlineDescription
:
inlineDescription
,
expectedDescriptionOrNull
:
expectedDescriptionOrNull
);
...
...
src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/ExtensionMethodImportCompletionHelper.CacheEntry.cs
浏览文件 @
ca892c8d
...
...
@@ -6,7 +6,6 @@
using
System
;
using
System.Collections.Generic
;
using
System.Collections.Immutable
;
using
System.Composition
;
using
System.Threading
;
using
System.Threading.Tasks
;
...
...
@@ -14,7 +13,6 @@
using
Microsoft.CodeAnalysis.FindSymbols
;
using
Microsoft.CodeAnalysis.Host.Mef
;
using
Microsoft.CodeAnalysis.LanguageServices
;
using
Microsoft.CodeAnalysis.PooledObjects
;
using
Microsoft.CodeAnalysis.Shared.Extensions
;
using
Roslyn.Utilities
;
...
...
@@ -28,39 +26,33 @@ internal static partial class ExtensionMethodImportCompletionHelper
public
string
Language
{
get
;
}
/// <summary>
/// Mapping from the name of
target
type to extension method symbol infos.
/// Mapping from the name of
receiver
type to extension method symbol infos.
/// </summary>
public
readonly
MultiDictionary
<
string
,
DeclaredSymbolInfo
>
SimpleExtensionMethodInfo
{
get
;
}
public
readonly
ImmutableArray
<
DeclaredSymbolInfo
>
ComplexExtensionMethodInfo
{
get
;
}
public
readonly
MultiDictionary
<
string
,
DeclaredSymbolInfo
>
ReceiverTypeNameToExtensionMethodMap
{
get
;
}
private
CacheEntry
(
Checksum
checksum
,
string
language
,
MultiDictionary
<
string
,
DeclaredSymbolInfo
>
simpleExtensionMethodInfo
,
ImmutableArray
<
DeclaredSymbolInfo
>
complexExtensionMethodInfo
)
MultiDictionary
<
string
,
DeclaredSymbolInfo
>
receiverTypeNameToExtensionMethodMap
)
{
Checksum
=
checksum
;
Language
=
language
;
SimpleExtensionMethodInfo
=
simpleExtensionMethodInfo
;
ComplexExtensionMethodInfo
=
complexExtensionMethodInfo
;
ReceiverTypeNameToExtensionMethodMap
=
receiverTypeNameToExtensionMethodMap
;
}
public
class
Builder
:
IDisposable
public
class
Builder
{
private
readonly
Checksum
_checksum
;
private
readonly
string
_language
;
private
readonly
MultiDictionary
<
string
,
DeclaredSymbolInfo
>
_simpleItemBuilder
;
private
readonly
ArrayBuilder
<
DeclaredSymbolInfo
>
_complexItemBuilder
;
private
readonly
MultiDictionary
<
string
,
DeclaredSymbolInfo
>
_mapBuilder
;
public
Builder
(
Checksum
checksum
,
string
langauge
,
IEqualityComparer
<
string
>
comparer
)
{
_checksum
=
checksum
;
_language
=
langauge
;
_simpleItemBuilder
=
new
MultiDictionary
<
string
,
DeclaredSymbolInfo
>(
comparer
);
_complexItemBuilder
=
ArrayBuilder
<
DeclaredSymbolInfo
>.
GetInstance
();
_mapBuilder
=
new
MultiDictionary
<
string
,
DeclaredSymbolInfo
>(
comparer
);
}
public
CacheEntry
ToCacheEntry
()
...
...
@@ -68,28 +60,19 @@ public CacheEntry ToCacheEntry()
return
new
CacheEntry
(
_checksum
,
_language
,
_simpleItemBuilder
,
_complexItemBuilder
.
ToImmutable
());
_mapBuilder
);
}
public
void
AddItem
(
SyntaxTreeIndex
syntaxIndex
)
{
foreach
(
var
(
targetType
,
symbolInfoIndices
)
in
syntaxIndex
.
SimpleExtensionMethodInfo
)
foreach
(
var
(
receiverType
,
symbolInfoIndices
)
in
syntaxIndex
.
ReceiverTypeNameToExtensionMethodMap
)
{
foreach
(
var
index
in
symbolInfoIndices
)
{
_
simpleItemBuilder
.
Add
(
target
Type
,
syntaxIndex
.
DeclaredSymbolInfos
[
index
]);
_
mapBuilder
.
Add
(
receiver
Type
,
syntaxIndex
.
DeclaredSymbolInfos
[
index
]);
}
}
foreach
(
var
index
in
syntaxIndex
.
ComplexExtensionMethodInfo
)
{
_complexItemBuilder
.
Add
(
syntaxIndex
.
DeclaredSymbolInfos
[
index
]);
}
}
public
void
Dispose
()
=>
_complexItemBuilder
.
Free
();
}
}
...
...
@@ -125,7 +108,7 @@ public CacheServiceFactory()
cacheEntry
.
Language
!=
project
.
Language
)
{
var
syntaxFacts
=
project
.
LanguageServices
.
GetRequiredService
<
ISyntaxFactsService
>();
using
var
builder
=
new
CacheEntry
.
Builder
(
checksum
,
project
.
Language
,
syntaxFacts
.
StringComparer
);
var
builder
=
new
CacheEntry
.
Builder
(
checksum
,
project
.
Language
,
syntaxFacts
.
StringComparer
);
foreach
(
var
document
in
project
.
Documents
)
{
...
...
src/Features/Core/Portable/Completion/Providers/ImportCompletionProvider/ExtensionMethodImportCompletionHelper.cs
浏览文件 @
ca892c8d
...
...
@@ -163,7 +163,7 @@ private static string GetReceiverTypeName(ITypeSymbol typeSymbol)
private
static
async
Task
<
ImmutableArray
<
SerializableImportCompletionItem
>>
GetExtensionMethodItemsAsync
(
Document
document
,
ITypeSymbol
receiverTypeSymbol
,
ImmutableArray
<
string
>
target
TypeNames
,
ImmutableArray
<
string
>
receiver
TypeNames
,
GetIndicesResult
indices
,
int
position
,
ISet
<
string
>
namespaceFilter
,
...
...
@@ -180,13 +180,15 @@ private static string GetReceiverTypeName(ITypeSymbol typeSymbol)
var
currentCompilation
=
semanticModel
.
Compilation
;
var
currentAssembly
=
currentCompilation
.
Assembly
;
using
var
_1
=
ArrayBuilder
<
SerializableImportCompletionItem
>.
GetInstance
(
out
var
builder
);
using
var
_1
=
ArrayBuilder
<
SerializableImportCompletionItem
>.
GetInstance
(
out
var
completionItems
builder
);
using
var
_2
=
PooledDictionary
<
INamespaceSymbol
,
string
>.
GetInstance
(
out
var
namespaceNameCache
);
receiverTypeNames
=
AttachComplexTypes
(
receiverTypeNames
);
// Get extension method items from source
foreach
(
var
(
project
,
syntaxIndex
)
in
indices
.
SyntaxIndices
!)
{
var
filter
=
CreateAggregatedFilter
(
target
TypeNames
,
syntaxIndex
);
var
filter
=
CreateAggregatedFilter
(
receiver
TypeNames
,
syntaxIndex
);
var
compilation
=
await
project
.
GetRequiredCompilationAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
var
assembly
=
compilation
.
Assembly
;
...
...
@@ -199,13 +201,13 @@ private static string GetReceiverTypeName(ITypeSymbol typeSymbol)
var
isSymbolFromCurrentCompilation
=
project
==
currentProject
;
GetExtensionMethodItemsWorker
(
position
,
semanticModel
,
receiverTypeSymbol
,
matchingMethodSymbols
,
isSymbolFromCurrentCompilation
,
builder
,
namespaceNameCache
,
cancellationToken
);
completionItems
builder
,
namespaceNameCache
,
cancellationToken
);
}
// Get extension method items from PE
foreach
(
var
(
peReference
,
symbolInfo
)
in
indices
.
SymbolInfos
!)
{
var
filter
=
CreateAggregatedFilter
(
target
TypeNames
,
symbolInfo
);
var
filter
=
CreateAggregatedFilter
(
receiver
TypeNames
,
symbolInfo
);
if
(
currentCompilation
.
GetAssemblyOrModuleSymbol
(
peReference
)
is
IAssemblySymbol
assembly
)
{
var
internalsVisible
=
currentAssembly
.
IsSameAssemblyOrHasFriendAccessTo
(
assembly
);
...
...
@@ -216,11 +218,23 @@ private static string GetReceiverTypeName(ITypeSymbol typeSymbol)
GetExtensionMethodItemsWorker
(
position
,
semanticModel
,
receiverTypeSymbol
,
matchingMethodSymbols
,
isSymbolFromCurrentCompilation
:
true
,
builder
,
namespaceNameCache
,
cancellationToken
);
isSymbolFromCurrentCompilation
:
true
,
completionItems
builder
,
namespaceNameCache
,
cancellationToken
);
}
}
return
builder
.
ToImmutable
();
return
completionItemsbuilder
.
ToImmutable
();
// Add string represent complex types (i.e. "" and "[]") to the receiver type, so we would include in the filter
// info about extension methods with complex receiver type.
static
ImmutableArray
<
string
>
AttachComplexTypes
(
ImmutableArray
<
string
>
receiverTypeNames
)
{
using
var
_
=
ArrayBuilder
<
string
>.
GetInstance
(
receiverTypeNames
.
Length
+
2
,
out
var
receiverTypeNamesBuilder
);
receiverTypeNamesBuilder
.
AddRange
(
receiverTypeNames
);
receiverTypeNamesBuilder
.
Add
(
string
.
Empty
);
receiverTypeNamesBuilder
.
Add
(
"[]"
);
return
receiverTypeNamesBuilder
.
ToImmutable
();
}
}
private
static
void
GetExtensionMethodItemsWorker
(
...
...
@@ -314,7 +328,7 @@ private static string GetFullyQualifiedNamespaceName(INamespaceSymbol symbol, Di
continue
;
}
foreach
(
var
(
methodName
,
target
TypeName
)
in
methodNames
)
foreach
(
var
(
methodName
,
receiver
TypeName
)
in
methodNames
)
{
cancellationToken
.
ThrowIfCancellationRequested
();
...
...
@@ -324,7 +338,7 @@ private static string GetFullyQualifiedNamespaceName(INamespaceSymbol symbol, Di
{
counter
.
TotalExtensionMethodsChecked
++;
if
(
MatchExtensionMethod
(
methodSymbol
,
target
TypeName
,
internalsVisible
))
if
(
MatchExtensionMethod
(
methodSymbol
,
receiver
TypeName
,
internalsVisible
))
{
// Find a potential match.
builder
.
Add
(
methodSymbol
);
...
...
@@ -418,14 +432,13 @@ static bool MatchExtensionMethod(IMethodSymbol method, string filterReceiverType
}
// Create filter for extension methods from source.
private
static
MultiDictionary
<
string
,
(
string
,
string
)>
CreateAggregatedFilter
(
ImmutableArray
<
string
>
target
TypeNames
,
CacheEntry
syntaxIndex
)
private
static
MultiDictionary
<
string
,
(
string
,
string
)>
CreateAggregatedFilter
(
ImmutableArray
<
string
>
receiver
TypeNames
,
CacheEntry
syntaxIndex
)
{
var
results
=
new
MultiDictionary
<
string
,
(
string
,
string
)>();
// Add simple extension methods with matching target type name
foreach
(
var
targetTypeName
in
targetTypeNames
)
foreach
(
var
receiverTypeName
in
receiverTypeNames
)
{
var
methodInfos
=
syntaxIndex
.
SimpleExtensionMethodInfo
[
target
TypeName
];
var
methodInfos
=
syntaxIndex
.
ReceiverTypeNameToExtensionMethodMap
[
receiver
TypeName
];
if
(
methodInfos
.
Count
==
0
)
{
continue
;
...
...
@@ -433,32 +446,21 @@ static bool MatchExtensionMethod(IMethodSymbol method, string filterReceiverType
foreach
(
var
methodInfo
in
methodInfos
)
{
results
.
Add
(
methodInfo
.
FullyQualifiedContainerName
,
(
methodInfo
.
Name
,
target
TypeName
));
results
.
Add
(
methodInfo
.
FullyQualifiedContainerName
,
(
methodInfo
.
Name
,
receiver
TypeName
));
}
}
// Add all complex extension methods, we will need to completely rely on symbols to match them.
foreach
(
var
methodInfo
in
syntaxIndex
.
ComplexExtensionMethodInfo
)
{
results
.
Add
(
methodInfo
.
FullyQualifiedContainerName
,
(
methodInfo
.
Name
,
string
.
Empty
));
}
return
results
;
}
// Create filter for extension methods from metadata
private
static
MultiDictionary
<
string
,
(
string
,
string
)>
CreateAggregatedFilter
(
ImmutableArray
<
string
>
target
TypeNames
,
SymbolTreeInfo
symbolInfo
)
private
static
MultiDictionary
<
string
,
(
string
,
string
)>
CreateAggregatedFilter
(
ImmutableArray
<
string
>
receiver
TypeNames
,
SymbolTreeInfo
symbolInfo
)
{
var
results
=
new
MultiDictionary
<
string
,
(
string
,
string
)>();
using
var
_
=
ArrayBuilder
<
string
>.
GetInstance
(
targetTypeNames
.
Length
+
2
,
out
var
builder
);
builder
.
AddRange
(
targetTypeNames
);
builder
.
Add
(
string
.
Empty
);
builder
.
Add
(
"[]"
);
foreach
(
var
targetTypeName
in
builder
)
foreach
(
var
receiverTypeName
in
receiverTypeNames
)
{
var
methodInfos
=
symbolInfo
.
GetExtensionMethodInfoForReceiverType
(
target
TypeName
);
var
methodInfos
=
symbolInfo
.
GetExtensionMethodInfoForReceiverType
(
receiver
TypeName
);
if
(
methodInfos
.
Count
==
0
)
{
continue
;
...
...
@@ -466,7 +468,7 @@ static bool MatchExtensionMethod(IMethodSymbol method, string filterReceiverType
foreach
(
var
methodInfo
in
methodInfos
)
{
results
.
Add
(
methodInfo
.
FullyQualifiedContainerName
,
(
methodInfo
.
Name
,
target
TypeName
));
results
.
Add
(
methodInfo
.
FullyQualifiedContainerName
,
(
methodInfo
.
Name
,
receiver
TypeName
));
}
}
...
...
src/Workspaces/CSharp/Portable/FindSymbols/CSharpDeclaredSymbolInfoFactoryService.cs
浏览文件 @
ca892c8d
...
...
@@ -506,8 +506,8 @@ public override bool TryGetAliasesFromUsingDirective(SyntaxNode node, out Immuta
{
if
(
node
is
UsingDirectiveSyntax
usingDirectiveNode
&&
usingDirectiveNode
.
Alias
!=
null
)
{
if
(
TryGetSimpleTypeName
(
usingDirectiveNode
.
Alias
.
Name
,
typeParameterNames
:
null
,
out
var
aliasName
)
&&
TryGetSimpleTypeName
(
usingDirectiveNode
.
Name
,
typeParameterNames
:
null
,
out
var
name
))
if
(
TryGetSimpleTypeName
(
usingDirectiveNode
.
Alias
.
Name
,
typeParameterNames
:
null
,
out
var
aliasName
,
out
_
)
&&
TryGetSimpleTypeName
(
usingDirectiveNode
.
Name
,
typeParameterNames
:
null
,
out
var
name
,
out
_
))
{
aliases
=
ImmutableArray
.
Create
<(
string
,
string
)>((
aliasName
,
name
));
return
true
;
...
...
@@ -518,18 +518,20 @@ public override bool TryGetAliasesFromUsingDirective(SyntaxNode node, out Immuta
return
false
;
}
public
override
string
Get
Target
TypeName
(
SyntaxNode
node
)
public
override
string
Get
Receiver
TypeName
(
SyntaxNode
node
)
{
var
methodDeclaration
=
(
MethodDeclarationSyntax
)
node
;
Debug
.
Assert
(
IsExtensionMethod
(
methodDeclaration
));
var
typeParameterNames
=
methodDeclaration
.
TypeParameterList
?.
Parameters
.
SelectAsArray
(
p
=>
p
.
Identifier
.
Text
);
TryGetSimpleTypeName
(
methodDeclaration
.
ParameterList
.
Parameters
[
0
].
Type
,
typeParameterNames
,
out
var
targetTypeName
);
return
targetTypeName
;
TryGetSimpleTypeName
(
methodDeclaration
.
ParameterList
.
Parameters
[
0
].
Type
,
typeParameterNames
,
out
var
targetTypeName
,
out
var
isArray
);
return
CreateReceiverTypeString
(
targetTypeName
,
isArray
)
;
}
private
static
bool
TryGetSimpleTypeName
(
SyntaxNode
node
,
ImmutableArray
<
string
>?
typeParameterNames
,
out
string
simpleTypeName
)
private
static
bool
TryGetSimpleTypeName
(
SyntaxNode
node
,
ImmutableArray
<
string
>?
typeParameterNames
,
out
string
simpleTypeName
,
out
bool
isArray
)
{
isArray
=
false
;
if
(
node
is
TypeSyntax
typeNode
)
{
switch
(
typeNode
)
...
...
@@ -541,12 +543,8 @@ private static bool TryGetSimpleTypeName(SyntaxNode node, ImmutableArray<string>
return
simpleTypeName
!=
null
;
case
ArrayTypeSyntax
arrayTypeNode
:
// We do not differentiate array of different kinds for simplicity.
// e.g. int[], int[][], int[,], etc. are all represented as int[] in the index.
simpleTypeName
=
TryGetSimpleTypeName
(
arrayTypeNode
.
ElementType
,
typeParameterNames
,
out
var
elementTypeName
)
?
CreateTargetTypeStringForArray
(
elementTypeName
)
:
null
;
return
simpleTypeName
!=
null
;
isArray
=
true
;
return
TryGetSimpleTypeName
(
arrayTypeNode
.
ElementType
,
typeParameterNames
,
out
simpleTypeName
,
out
_
);
case
GenericNameSyntax
genericNameNode
:
var
name
=
genericNameNode
.
Identifier
.
Text
;
...
...
@@ -559,17 +557,17 @@ private static bool TryGetSimpleTypeName(SyntaxNode node, ImmutableArray<string>
return
simpleTypeName
!=
null
;
case
AliasQualifiedNameSyntax
aliasQualifiedNameNode
:
return
TryGetSimpleTypeName
(
aliasQualifiedNameNode
.
Name
,
typeParameterNames
,
out
simpleTypeName
);
return
TryGetSimpleTypeName
(
aliasQualifiedNameNode
.
Name
,
typeParameterNames
,
out
simpleTypeName
,
out
_
);
case
QualifiedNameSyntax
qualifiedNameNode
:
// For an identifier to the right of a '.', it can't be a type parameter,
// so we don't need to check for it further.
return
TryGetSimpleTypeName
(
qualifiedNameNode
.
Right
,
typeParameterNames
:
null
,
out
simpleTypeName
);
return
TryGetSimpleTypeName
(
qualifiedNameNode
.
Right
,
typeParameterNames
:
null
,
out
simpleTypeName
,
out
_
);
case
NullableTypeSyntax
nullableNode
:
// Ignore nullability, becase nullable reference type might not be enabled universally.
// In the worst case we just include more methods to check in out filter.
return
TryGetSimpleTypeName
(
nullableNode
.
ElementType
,
typeParameterNames
,
out
simpleTypeName
);
return
TryGetSimpleTypeName
(
nullableNode
.
ElementType
,
typeParameterNames
,
out
simpleTypeName
,
out
isArray
);
}
}
...
...
src/Workspaces/Core/Portable/FindSymbols/SymbolTree/SymbolTreeInfo.Node.cs
浏览文件 @
ca892c8d
...
...
@@ -95,7 +95,7 @@ private string GetDebuggerDisplay()
/// <summary>
/// Similar to <see cref="SyntaxTreeIndex.ExtensionMethodInfo"/>, we divide extension methods into simple
/// and complex categories for filtering purpose. Whether a method is simple is determined based on if we
/// can determine it's
target
type easily with a pure text matching. For complex methods, we will need to
/// can determine it's
receiver
type easily with a pure text matching. For complex methods, we will need to
/// rely on symbol to decide if it's feasible.
///
/// Simple types include:
...
...
src/Workspaces/Core/Portable/FindSymbols/SymbolTree/SymbolTreeInfo_Metadata.cs
浏览文件 @
ca892c8d
...
...
@@ -230,7 +230,7 @@ private struct MetadataInfoCreator : IDisposable
private
readonly
List
<
MetadataDefinition
>
_allTypeDefinitions
;
// Map from node represents extension method to list of possible parameter type info.
// We can have more than one if there's multiple methods with same name but different
target
type.
// We can have more than one if there's multiple methods with same name but different
receiver
type.
// e.g.
//
// public static bool AnotherExtensionMethod1(this int x);
...
...
@@ -371,8 +371,8 @@ private void GenerateMetadataNodes()
{
if
(
definition
.
Kind
==
MetadataDefinitionKind
.
Member
)
{
// We need to support having multiple methods with same name but different
target
type.
_extensionMethodToParameterTypeInfo
.
Add
(
childNode
,
definition
.
Target
TypeInfo
);
// We need to support having multiple methods with same name but different
receiver
type.
_extensionMethodToParameterTypeInfo
.
Add
(
childNode
,
definition
.
Receiver
TypeInfo
);
}
LookupMetadataDefinitions
(
definition
,
definitionMap
);
...
...
@@ -434,7 +434,7 @@ private void GenerateMetadataNodes()
method
.
GetParameters
().
Count
>
0
&&
method
.
GetCustomAttributes
().
Count
>
0
)
{
// Decode method signature to get the
target
type name (i.e. type name for the first parameter)
// Decode method signature to get the
receiver
type name (i.e. type name for the first parameter)
var
blob
=
_metadataReader
.
GetBlobReader
(
method
.
Signature
);
var
decoder
=
new
SignatureDecoder
<
ParameterTypeInfo
,
object
>(
ParameterTypeInfoProvider
.
Instance
,
_metadataReader
,
genericContext
:
null
);
var
signature
=
decoder
.
DecodeMethodSignature
(
ref
blob
);
...
...
@@ -797,17 +797,17 @@ private struct MetadataDefinition
/// <summary>
/// Only applies to member kind. Represents the type info of the first parameter.
/// </summary>
public
ParameterTypeInfo
Target
TypeInfo
{
get
;
}
public
ParameterTypeInfo
Receiver
TypeInfo
{
get
;
}
public
NamespaceDefinition
Namespace
{
get
;
private
set
;
}
public
TypeDefinition
Type
{
get
;
private
set
;
}
public
MetadataDefinition
(
MetadataDefinitionKind
kind
,
string
name
,
ParameterTypeInfo
target
TypeInfo
=
default
)
public
MetadataDefinition
(
MetadataDefinitionKind
kind
,
string
name
,
ParameterTypeInfo
receiver
TypeInfo
=
default
)
:
this
()
{
Kind
=
kind
;
Name
=
name
;
TargetTypeInfo
=
target
TypeInfo
;
ReceiverTypeInfo
=
receiver
TypeInfo
;
}
public
static
MetadataDefinition
Create
(
...
...
src/Workspaces/Core/Portable/FindSymbols/SyntaxTree/SyntaxTreeIndex.ExtensionMethodInfo.cs
浏览文件 @
ca892c8d
...
...
@@ -16,45 +16,47 @@ internal partial class SyntaxTreeIndex
private
readonly
struct
ExtensionMethodInfo
{
// We divide extension methods into two categories, simple and complex, for filtering purpose.
// Whether a method is simple is determined based on if we can determine it's
target
type easily
// Whether a method is simple is determined based on if we can determine it's
receiver
type easily
// with a pure text matching. For complex methods, we will need to rely on symbol to decide if it's
// feasible.
//
// Complex methods include:
// - Method declared in the document which includes using alias directive
// - Generic method where the
target
type is a type-paramter (e.g. List<T> would be considered simple, not complex)
// - If the
target
type name is one of the following (i.e. name of the type for the first parameter)
// - Generic method where the
receiver
type is a type-paramter (e.g. List<T> would be considered simple, not complex)
// - If the
receiver
type name is one of the following (i.e. name of the type for the first parameter)
// 1. ValueTuple type
// 2. Pointer type
//
// The rest of methods are considered simple.
/// <summary>
/// Name of the simple method's target type name to the index of its DeclaredSymbolInfo in `_declarationInfo`.
/// All predefined types are converted to its metadata form. e.g. int => Int32. For generic types, type parameters are ignored.
/// Name of the extension method's receiver type to the index of its DeclaredSymbolInfo in `_declarationInfo`.
///
/// For simple types, the receiver type name is it's metadata name. All predefined types are converted to its metadata form.
/// e.g. int => Int32. For generic types, type parameters are ignored.
///
/// For complex types, the receiver type name is "".
///
/// For any kind of array types, it's "{element's receiver type name}[]".
/// e.g.
/// int[][,] => "Int32[]"
/// T (where T is a type parameter) => ""
/// T[,] (where T is a type parameter) => "T[]"
/// </summary>
public
readonly
ImmutableDictionary
<
string
,
ImmutableArray
<
int
>>
SimpleExtensionMethodInfo
{
get
;
}
public
readonly
ImmutableDictionary
<
string
,
ImmutableArray
<
int
>>
ReceiverTypeNameToExtensionMethodMap
{
get
;
}
/// <summary>
/// Indices of to all complex methods' DeclaredSymbolInfo in `_declarationInfo`.
/// </summary>
public
readonly
ImmutableArray
<
int
>
ComplexExtensionMethodInfo
{
get
;
}
public
bool
ContainsExtensionMethod
=>
SimpleExtensionMethodInfo
.
Count
>
0
||
ComplexExtensionMethodInfo
.
Length
>
0
;
public
bool
ContainsExtensionMethod
=>
ReceiverTypeNameToExtensionMethodMap
.
Count
>
0
;
public
ExtensionMethodInfo
(
ImmutableDictionary
<
string
,
ImmutableArray
<
int
>>
simpleExtensionMethodInfo
,
ImmutableArray
<
int
>
complexExtensionMethodInfo
)
public
ExtensionMethodInfo
(
ImmutableDictionary
<
string
,
ImmutableArray
<
int
>>
receiverTypeNameToExtensionMethodMap
)
{
SimpleExtensionMethodInfo
=
simpleExtensionMethodInfo
;
ComplexExtensionMethodInfo
=
complexExtensionMethodInfo
;
ReceiverTypeNameToExtensionMethodMap
=
receiverTypeNameToExtensionMethodMap
;
}
public
void
WriteTo
(
ObjectWriter
writer
)
{
writer
.
WriteInt32
(
SimpleExtensionMethodInfo
.
Count
);
writer
.
WriteInt32
(
ReceiverTypeNameToExtensionMethodMap
.
Count
);
foreach
(
var
kvp
in
SimpleExtensionMethodInfo
)
foreach
(
var
kvp
in
ReceiverTypeNameToExtensionMethodMap
)
{
writer
.
WriteString
(
kvp
.
Key
);
writer
.
WriteInt32
(
kvp
.
Value
.
Length
);
...
...
@@ -64,19 +66,13 @@ public void WriteTo(ObjectWriter writer)
writer
.
WriteInt32
(
declaredSymbolInfoIndex
);
}
}
writer
.
WriteInt32
(
ComplexExtensionMethodInfo
.
Length
);
foreach
(
var
declaredSymbolInfoIndex
in
ComplexExtensionMethodInfo
)
{
writer
.
WriteInt32
(
declaredSymbolInfoIndex
);
}
}
public
static
ExtensionMethodInfo
?
TryReadFrom
(
ObjectReader
reader
)
{
try
{
var
simpleExtensionMethodInfo
=
ImmutableDictionary
.
CreateBuilder
<
string
,
ImmutableArray
<
int
>>();
var
receiverTypeNameToExtensionMethodMapBuilder
=
ImmutableDictionary
.
CreateBuilder
<
string
,
ImmutableArray
<
int
>>();
var
count
=
reader
.
ReadInt32
();
for
(
var
i
=
0
;
i
<
count
;
++
i
)
...
...
@@ -91,18 +87,10 @@ public void WriteTo(ObjectWriter writer)
arrayBuilder
.
Add
(
declaredSymbolInfoIndex
);
}
simpleExtensionMethodInfo
[
typeName
]
=
arrayBuilder
.
ToImmutableAndFree
();
}
count
=
reader
.
ReadInt32
();
var
complexExtensionMethodInfo
=
ArrayBuilder
<
int
>.
GetInstance
(
count
);
for
(
var
i
=
0
;
i
<
count
;
++
i
)
{
var
declaredSymbolInfoIndex
=
reader
.
ReadInt32
();
complexExtensionMethodInfo
.
Add
(
declaredSymbolInfoIndex
);
receiverTypeNameToExtensionMethodMapBuilder
[
typeName
]
=
arrayBuilder
.
ToImmutableAndFree
();
}
return
new
ExtensionMethodInfo
(
simpleExtensionMethodInfo
.
ToImmutable
(),
complexExtensionMethodInfo
.
ToImmutableAndFre
e
());
return
new
ExtensionMethodInfo
(
receiverTypeNameToExtensionMethodMapBuilder
.
ToImmutabl
e
());
}
catch
(
Exception
)
{
...
...
src/Workspaces/Core/Portable/FindSymbols/SyntaxTree/SyntaxTreeIndex_Create.cs
浏览文件 @
ca892c8d
...
...
@@ -25,9 +25,9 @@ internal interface IDeclaredSymbolInfoFactoryService : ILanguageService
// otherwise we would not be able to get correct data from syntax.
bool
TryGetDeclaredSymbolInfo
(
StringTable
stringTable
,
SyntaxNode
node
,
string
rootNamespace
,
out
DeclaredSymbolInfo
declaredSymbolInfo
);
// Get the name of the
target
type of specified extension method declaration node.
// The returned value would be
null for complex type
.
string
Get
Target
TypeName
(
SyntaxNode
node
);
// Get the name of the
receiver
type of specified extension method declaration node.
// The returned value would be
"" or "[]" for complex types
.
string
Get
Receiver
TypeName
(
SyntaxNode
node
);
bool
TryGetAliasesFromUsingDirective
(
SyntaxNode
node
,
out
ImmutableArray
<(
string
aliasName
,
string
name
)>
aliases
);
...
...
@@ -71,8 +71,7 @@ internal sealed partial class SyntaxTreeIndex
var
longLiterals
=
LongLiteralHashSetPool
.
Allocate
();
var
declaredSymbolInfos
=
ArrayBuilder
<
DeclaredSymbolInfo
>.
GetInstance
();
var
complexExtensionMethodInfoBuilder
=
ArrayBuilder
<
int
>.
GetInstance
();
var
simpleExtensionMethodInfoBuilder
=
PooledDictionary
<
string
,
ArrayBuilder
<
int
>>.
GetInstance
();
var
extensionMethodInfoBuilder
=
PooledDictionary
<
string
,
ArrayBuilder
<
int
>>.
GetInstance
();
using
var
_
=
PooledDictionary
<
string
,
string
>.
GetInstance
(
out
var
usingAliases
);
try
...
...
@@ -171,8 +170,7 @@ internal sealed partial class SyntaxTreeIndex
usingAliases
,
declaredSymbolInfoIndex
,
declaredSymbolInfo
,
simpleExtensionMethodInfoBuilder
,
complexExtensionMethodInfoBuilder
);
extensionMethodInfoBuilder
);
}
else
{
...
...
@@ -273,8 +271,7 @@ internal sealed partial class SyntaxTreeIndex
new
DeclarationInfo
(
declaredSymbolInfos
.
ToImmutable
()),
new
ExtensionMethodInfo
(
simpleExtensionMethodInfoBuilder
.
ToImmutableDictionary
(
s_getKey
,
s_getValuesAsImmutableArray
),
complexExtensionMethodInfoBuilder
.
ToImmutable
()));
extensionMethodInfoBuilder
.
ToImmutableDictionary
(
s_getKey
,
s_getValuesAsImmutableArray
)));
}
finally
{
...
...
@@ -282,13 +279,12 @@ internal sealed partial class SyntaxTreeIndex
StringLiteralHashSetPool
.
ClearAndFree
(
stringLiterals
);
LongLiteralHashSetPool
.
ClearAndFree
(
longLiterals
);
foreach
(
var
(
_
,
builder
)
in
simpleE
xtensionMethodInfoBuilder
)
foreach
(
var
(
_
,
builder
)
in
e
xtensionMethodInfoBuilder
)
{
builder
.
Free
();
}
simpleExtensionMethodInfoBuilder
.
Free
();
complexExtensionMethodInfoBuilder
.
Free
();
extensionMethodInfoBuilder
.
Free
();
declaredSymbolInfos
.
Free
();
}
}
...
...
@@ -302,43 +298,35 @@ internal sealed partial class SyntaxTreeIndex
PooledDictionary
<
string
,
string
>
aliases
,
int
declaredSymbolInfoIndex
,
DeclaredSymbolInfo
declaredSymbolInfo
,
PooledDictionary
<
string
,
ArrayBuilder
<
int
>>
simpleInfoBuilder
,
ArrayBuilder
<
int
>
complexInfoBuilder
)
PooledDictionary
<
string
,
ArrayBuilder
<
int
>>
extensionMethodsInfoBuilder
)
{
if
(
declaredSymbolInfo
.
Kind
!=
DeclaredSymbolInfoKind
.
ExtensionMethod
)
{
return
;
}
var
targetTypeName
=
infoFactory
.
GetTargetTypeName
(
node
);
// complex method
if
(
targetTypeName
==
null
)
{
complexInfoBuilder
.
Add
(
declaredSymbolInfoIndex
);
return
;
}
var
receiverTypeName
=
infoFactory
.
GetReceiverTypeName
(
node
);
// Target type is an alias
if
(
aliases
.
TryGetValue
(
target
TypeName
,
out
var
originalName
))
if
(
aliases
.
TryGetValue
(
receiver
TypeName
,
out
var
originalName
))
{
// it is an alias of multiple with identical name,
// simply treat it as a complex method.
if
(
originalName
==
null
)
{
complexInfoBuilder
.
Add
(
declaredSymbolInfoIndex
);
return
;
receiverTypeName
=
string
.
Empty
;
}
else
{
// replace the alias with its original name.
receiverTypeName
=
originalName
;
}
// replace the alias with its original name.
targetTypeName
=
originalName
;
}
// So we've got a simple method.
if
(!
simpleInfoBuilder
.
TryGetValue
(
targetTypeName
,
out
var
arrayBuilder
))
if
(!
extensionMethodsInfoBuilder
.
TryGetValue
(
string
.
Empty
,
out
var
arrayBuilder
))
{
arrayBuilder
=
ArrayBuilder
<
int
>.
GetInstance
();
simpleInfoBuilder
[
target
TypeName
]
=
arrayBuilder
;
extensionMethodsInfoBuilder
[
receiver
TypeName
]
=
arrayBuilder
;
}
arrayBuilder
.
Add
(
declaredSymbolInfoIndex
);
...
...
src/Workspaces/Core/Portable/FindSymbols/SyntaxTree/SyntaxTreeIndex_Forwarders.cs
浏览文件 @
ca892c8d
...
...
@@ -11,11 +11,8 @@ internal sealed partial class SyntaxTreeIndex
{
public
ImmutableArray
<
DeclaredSymbolInfo
>
DeclaredSymbolInfos
=>
_declarationInfo
.
DeclaredSymbolInfos
;
public
ImmutableDictionary
<
string
,
ImmutableArray
<
int
>>
SimpleExtensionMethodInfo
=>
_extensionMethodInfo
.
SimpleExtensionMethodInfo
;
public
ImmutableArray
<
int
>
ComplexExtensionMethodInfo
=>
_extensionMethodInfo
.
ComplexExtensionMethodInfo
;
public
ImmutableDictionary
<
string
,
ImmutableArray
<
int
>>
ReceiverTypeNameToExtensionMethodMap
=>
_extensionMethodInfo
.
ReceiverTypeNameToExtensionMethodMap
;
public
bool
ContainsExtensionMethod
=>
_extensionMethodInfo
.
ContainsExtensionMethod
;
...
...
src/Workspaces/Core/Portable/LanguageServices/DeclaredSymbolFactoryService/AbstractDeclaredSymbolInfoFactoryService.cs
浏览文件 @
ca892c8d
...
...
@@ -32,8 +32,19 @@ internal abstract class AbstractDeclaredSymbolInfoFactoryService : IDeclaredSymb
protected
static
List
<
Dictionary
<
string
,
string
>>
AllocateAliasMapList
()
=>
s_aliasMapListPool
.
Allocate
();
protected
static
string
CreateTargetTypeStringForArray
(
string
elementTypeName
)
=>
elementTypeName
+
"[]"
;
// We do not differentiate arrays of different kinds for simplicity.
// e.g. int[], int[][], int[,], etc. are all represented as int[] in the index.
protected
static
string
CreateReceiverTypeString
(
string
typeName
,
bool
isArray
)
{
if
(
typeName
==
null
)
{
return
isArray
?
"[]"
:
string
.
Empty
;
}
else
{
return
isArray
?
typeName
+
"[]"
:
typeName
;
}
}
protected
static
void
FreeAliasMapList
(
List
<
Dictionary
<
string
,
string
>>
list
)
{
...
...
@@ -98,7 +109,7 @@ public static string GetMetadataAritySuffix(int arity)
/// on `node` should return a `DeclaredSymbolInfo` of kind `ExtensionMethod`.
/// If the return value is null, then it means this is a "complex" method (as described at <see cref="SyntaxTreeIndex.ExtensionMethodInfo"/>).
/// </summary>
public
abstract
string
Get
Target
TypeName
(
SyntaxNode
node
);
public
abstract
string
Get
Receiver
TypeName
(
SyntaxNode
node
);
public
abstract
bool
TryGetAliasesFromUsingDirective
(
SyntaxNode
node
,
out
ImmutableArray
<(
string
aliasName
,
string
name
)>
aliases
);
...
...
src/Workspaces/VisualBasic/Portable/FindSymbols/VisualBasicDeclaredSymbolInfoFactoryService.vb
浏览文件 @
ca892c8d
...
...
@@ -463,15 +463,16 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.FindSymbols
Next
End
Sub
Public
Overrides
Function
Get
Target
TypeName
(
node
As
SyntaxNode
)
As
String
Public
Overrides
Function
Get
Receiver
TypeName
(
node
As
SyntaxNode
)
As
String
Dim
funcDecl
=
CType
(
node
,
MethodBlockSyntax
)
Debug
.
Assert
(
IsExtensionMethod
(
funcDecl
))
Dim
typeParameterNames
=
funcDecl
.
SubOrFunctionStatement
.
TypeParameterList
?
.
Parameters
.
SelectAsArray
(
Function
(
p
)
p
.
Identifier
.
Text
)
Dim
targetTypeName
As
String
=
Nothing
TryGetSimpleTypeNameWorker
(
funcDecl
.
BlockStatement
.
ParameterList
.
Parameters
(
0
).
AsClause
?
.
Type
,
typeParameterNames
,
targetTypeName
)
Dim
isArray
As
Boolean
=
False
Return
targetTypeName
TryGetSimpleTypeNameWorker
(
funcDecl
.
BlockStatement
.
ParameterList
.
Parameters
(
0
).
AsClause
?
.
Type
,
typeParameterNames
,
targetTypeName
,
isArray
)
Return
CreateReceiverTypeString
(
targetTypeName
,
isArray
)
End
Function
Public
Overrides
Function
TryGetAliasesFromUsingDirective
(
node
As
SyntaxNode
,
ByRef
aliases
As
ImmutableArray
(
Of
(
aliasName
As
String
,
name
As
String
)))
As
Boolean
...
...
@@ -488,8 +489,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.FindSymbols
#
Disable
Warning
BC42030
' Variable is passed by reference before it has been assigned a value
If
simpleImportsClause
.
Alias
IsNot
Nothing
AndAlso
TryGetSimpleTypeNameWorker
(
simpleImportsClause
.
Alias
,
Nothing
,
aliasName
)
AndAlso
TryGetSimpleTypeNameWorker
(
simpleImportsClause
,
Nothing
,
name
)
Then
TryGetSimpleTypeNameWorker
(
simpleImportsClause
.
Alias
,
Nothing
,
aliasName
,
False
)
AndAlso
TryGetSimpleTypeNameWorker
(
simpleImportsClause
,
Nothing
,
name
,
False
)
Then
#
Enable
Warning
BC42030
' Variable is passed by reference before it has been assigned a value
builder
.
Add
((
aliasName
,
name
))
...
...
@@ -505,7 +506,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.FindSymbols
Return
False
End
Function
Private
Shared
Function
TryGetSimpleTypeNameWorker
(
node
As
SyntaxNode
,
typeParameterNames
As
ImmutableArray
(
Of
String
)
?
,
ByRef
simpleTypeName
As
String
)
As
Boolean
Private
Shared
Function
TryGetSimpleTypeNameWorker
(
node
As
SyntaxNode
,
typeParameterNames
As
ImmutableArray
(
Of
String
)
?
,
ByRef
simpleTypeName
As
String
,
ByRef
isArray
As
Boolean
)
As
Boolean
isArray
=
False
If
TypeOf
node
Is
IdentifierNameSyntax
Then
Dim
identifierName
=
DirectCast
(
node
,
IdentifierNameSyntax
)
Dim
text
=
identifierName
.
Identifier
.
Text
...
...
@@ -513,14 +517,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.FindSymbols
Return
simpleTypeName
IsNot
Nothing
ElseIf
TypeOf
node
Is
ArrayTypeSyntax
Then
' We do Not differentiate array of different kinds for simplicity.
' e.g. int(), int()(), int(,), etc. are all represented as int[] in the index.
isArray
=
True
Dim
arrayType
=
DirectCast
(
node
,
ArrayTypeSyntax
)
Dim
elementTypeName
As
String
#
Disable
Warning
BC42030
' Variable is passed by reference before it has been assigned a value
simpleTypeName
=
If
(
TryGetSimpleTypeNameWorker
(
arrayType
.
ElementType
,
typeParameterNames
,
elementTypeName
),
CreateTargetTypeStringForArray
(
elementTypeName
),
Nothing
)
#
Enable
Warning
BC42030
' Variable is passed by reference before it has been assigned a value
Return
simpleTypeName
IsNot
Nothing
Return
TryGetSimpleTypeNameWorker
(
arrayType
.
ElementType
,
typeParameterNames
,
simpleTypeName
,
False
)
ElseIf
TypeOf
node
Is
GenericNameSyntax
Then
Dim
genericName
=
DirectCast
(
node
,
GenericNameSyntax
)
...
...
@@ -533,10 +532,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.FindSymbols
' For an identifier to the right of a '.', it can't be a type parameter,
' so we don't need to check for it further.
Dim
qualifiedName
=
DirectCast
(
node
,
QualifiedNameSyntax
)
Return
TryGetSimpleTypeNameWorker
(
qualifiedName
.
Right
,
Nothing
,
simpleTypeName
)
Return
TryGetSimpleTypeNameWorker
(
qualifiedName
.
Right
,
Nothing
,
simpleTypeName
,
False
)
ElseIf
TypeOf
node
Is
NullableTypeSyntax
Then
Return
TryGetSimpleTypeNameWorker
(
DirectCast
(
node
,
NullableTypeSyntax
).
ElementType
,
typeParameterNames
,
simpleTypeName
)
Return
TryGetSimpleTypeNameWorker
(
DirectCast
(
node
,
NullableTypeSyntax
).
ElementType
,
typeParameterNames
,
simpleTypeName
,
isArray
)
ElseIf
TypeOf
node
Is
PredefinedTypeSyntax
Then
simpleTypeName
=
GetSpecialTypeName
(
DirectCast
(
node
,
PredefinedTypeSyntax
))
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录