Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
a5a9e4fe
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,发现更多精彩内容 >>
未验证
提交
a5a9e4fe
编写于
2月 05, 2019
作者:
I
Ivan Basov
提交者:
GitHub
2月 05, 2019
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Reparse type after async (#32983)
上级
530518c2
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
427 addition
and
152 deletion
+427
-152
src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
+119
-152
src/Compilers/CSharp/Test/Syntax/Parsing/MemberDeclarationParsingTests.cs
...harp/Test/Syntax/Parsing/MemberDeclarationParsingTests.cs
+282
-0
src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests.vb
...Test2/IntelliSense/CSharpCompletionCommandHandlerTests.vb
+26
-0
未找到文件。
src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
浏览文件 @
a5a9e4fe
...
...
@@ -2276,124 +2276,139 @@ private MemberDeclarationSyntax ParseMemberDeclarationOrStatementCore(SyntaxKind
// indexers, and non-conversion operators -- starts with a type
// (possibly void). Parse that.
TypeSyntax
type
=
ParseReturnType
();
var
sawRef
=
type
.
Kind
==
SyntaxKind
.
RefType
;
// Check for misplaced modifiers. if we see any, then consider this member
// terminated and restart parsing.
if
(
GetModifier
(
this
.
CurrentToken
)
!=
DeclarationModifiers
.
None
&&
this
.
CurrentToken
.
ContextualKind
!=
SyntaxKind
.
PartialKeyword
&&
this
.
CurrentToken
.
ContextualKind
!=
SyntaxKind
.
AsyncKeyword
&&
IsComplete
(
type
))
{
var
misplacedModifier
=
this
.
CurrentToken
;
type
=
this
.
AddError
(
type
,
type
.
FullWidth
+
misplacedModifier
.
GetLeadingTriviaWidth
(),
misplacedModifier
.
Width
,
ErrorCode
.
ERR_BadModifierLocation
,
misplacedModifier
.
Text
);
return
_syntaxFactory
.
IncompleteMember
(
attributes
,
modifiers
.
ToList
(),
type
);
}
var
afterTypeResetPoint
=
this
.
GetResetPoint
();
parse_member_name
:;
// If we've seen the ref keyword, we know we must have an indexer, method, or property.
if
(!
sawRef
)
try
{
// Check here for operators
// Allow old-style implicit/explicit casting operator syntax, just so we can give a better error
if
(
IsOperatorKeyword
())
var
sawRef
=
type
.
Kind
==
SyntaxKind
.
RefType
;
// Check for misplaced modifiers. if we see any, then consider this member
// terminated and restart parsing.
if
(
GetModifier
(
this
.
CurrentToken
)
!=
DeclarationModifiers
.
None
&&
this
.
CurrentToken
.
ContextualKind
!=
SyntaxKind
.
PartialKeyword
&&
this
.
CurrentToken
.
ContextualKind
!=
SyntaxKind
.
AsyncKeyword
&&
IsComplete
(
type
))
{
return
this
.
ParseOperatorDeclaration
(
attributes
,
modifiers
,
type
);
var
misplacedModifier
=
this
.
CurrentToken
;
type
=
this
.
AddError
(
type
,
type
.
FullWidth
+
misplacedModifier
.
GetLeadingTriviaWidth
(),
misplacedModifier
.
Width
,
ErrorCode
.
ERR_BadModifierLocation
,
misplacedModifier
.
Text
);
return
_syntaxFactory
.
IncompleteMember
(
attributes
,
modifiers
.
ToList
(),
type
);
}
if
(
IsFieldDeclaration
(
isEvent
:
false
))
parse_member_name
:;
// If we've seen the ref keyword, we know we must have an indexer, method, or property.
if
(!
sawRef
)
{
if
(
acceptStatement
)
// Check here for operators
// Allow old-style implicit/explicit casting operator syntax, just so we can give a better error
if
(
IsOperatorKeyword
())
{
// if we are script at top-level then statements can occur
_termState
|=
TerminatorState
.
IsPossibleStatementStartOrStop
;
return
this
.
ParseOperatorDeclaration
(
attributes
,
modifiers
,
type
);
}
return
this
.
ParseNormalFieldDeclaration
(
attributes
,
modifiers
,
type
,
parentKind
);
if
(
IsFieldDeclaration
(
isEvent
:
false
))
{
if
(
acceptStatement
)
{
// if we are script at top-level then statements can occur
_termState
|=
TerminatorState
.
IsPossibleStatementStartOrStop
;
}
return
this
.
ParseNormalFieldDeclaration
(
attributes
,
modifiers
,
type
,
parentKind
);
}
}
}
// At this point we can either have indexers, methods, or
// properties (or something unknown). Try to break apart
// the following name and determine what to do from there.
ExplicitInterfaceSpecifierSyntax
explicitInterfaceOpt
;
SyntaxToken
identifierOrThisOpt
;
TypeParameterListSyntax
typeParameterListOpt
;
this
.
ParseMemberName
(
out
explicitInterfaceOpt
,
out
identifierOrThisOpt
,
out
typeParameterListOpt
,
isEvent
:
false
);
// At this point we can either have indexers, methods, or
// properties (or something unknown). Try to break apart
// the following name and determine what to do from there.
ExplicitInterfaceSpecifierSyntax
explicitInterfaceOpt
;
SyntaxToken
identifierOrThisOpt
;
TypeParameterListSyntax
typeParameterListOpt
;
this
.
ParseMemberName
(
out
explicitInterfaceOpt
,
out
identifierOrThisOpt
,
out
typeParameterListOpt
,
isEvent
:
false
);
// First, check if we got absolutely nothing. If so, then
// We need to consume a bad member and try again.
if
(
explicitInterfaceOpt
==
null
&&
identifierOrThisOpt
==
null
&&
typeParameterListOpt
==
null
)
{
if
(
attributes
.
Count
==
0
&&
modifiers
.
Count
==
0
&&
type
.
IsMissing
&&
!
sawRef
)
// First, check if we got absolutely nothing. If so, then
// We need to consume a bad member and try again.
if
(
explicitInterfaceOpt
==
null
&&
identifierOrThisOpt
==
null
&&
typeParameterListOpt
==
null
)
{
// we haven't advanced, the caller needs to consume the tokens ahead
return
null
;
if
(
attributes
.
Count
==
0
&&
modifiers
.
Count
==
0
&&
type
.
IsMissing
&&
!
sawRef
)
{
// we haven't advanced, the caller needs to consume the tokens ahead
return
null
;
}
var
incompleteMember
=
_syntaxFactory
.
IncompleteMember
(
attributes
,
modifiers
.
ToList
(),
type
.
IsMissing
?
null
:
type
);
if
(
incompleteMember
.
ContainsDiagnostics
)
{
return
incompleteMember
;
}
else
if
(
parentKind
==
SyntaxKind
.
NamespaceDeclaration
||
parentKind
==
SyntaxKind
.
CompilationUnit
&&
!
IsScript
)
{
return
this
.
AddErrorToLastToken
(
incompleteMember
,
ErrorCode
.
ERR_NamespaceUnexpected
);
}
else
{
//the error position should indicate CurrentToken
return
this
.
AddError
(
incompleteMember
,
incompleteMember
.
FullWidth
+
this
.
CurrentToken
.
GetLeadingTriviaWidth
(),
this
.
CurrentToken
.
Width
,
ErrorCode
.
ERR_InvalidMemberDecl
,
this
.
CurrentToken
.
Text
);
}
}
var
incompleteMember
=
_syntaxFactory
.
IncompleteMember
(
attributes
,
modifiers
.
ToList
(),
type
.
IsMissing
?
null
:
type
);
if
(
incompleteMember
.
ContainsDiagnostics
)
// If the modifiers did not include "async", and the type we got was "async", and there was an
// error in the identifier or its type parameters, then the user is probably in the midst of typing
// an async method. In that case we reconsider "async" to be a modifier, and treat the identifier
// (with the type parameters) as the type (with type arguments). Then we go back to looking for
// the member name again.
// For example, if we get
// async Task<
// then we want async to be a modifier and Task<MISSING> to be a type.
if
(!
sawRef
&&
identifierOrThisOpt
!=
null
&&
(
typeParameterListOpt
!=
null
&&
typeParameterListOpt
.
ContainsDiagnostics
||
this
.
CurrentToken
.
Kind
!=
SyntaxKind
.
OpenParenToken
&&
this
.
CurrentToken
.
Kind
!=
SyntaxKind
.
OpenBraceToken
&&
this
.
CurrentToken
.
Kind
!=
SyntaxKind
.
EqualsGreaterThanToken
)
&&
ReconsiderTypeAsAsyncModifier
(
ref
modifiers
,
type
,
identifierOrThisOpt
))
{
return
incompleteMember
;
this
.
Reset
(
ref
afterTypeResetPoint
);
explicitInterfaceOpt
=
null
;
identifierOrThisOpt
=
default
;
typeParameterListOpt
=
null
;
type
=
ParseReturnType
();
goto
parse_member_name
;
}
else
if
(
parentKind
==
SyntaxKind
.
NamespaceDeclaration
||
parentKind
==
SyntaxKind
.
CompilationUnit
&&
!
IsScript
)
Debug
.
Assert
(
identifierOrThisOpt
!=
null
);
if
(
identifierOrThisOpt
.
Kind
==
SyntaxKind
.
ThisKeyword
)
{
return
this
.
AddErrorToLastToken
(
incompleteMember
,
ErrorCode
.
ERR_NamespaceUnexpected
);
return
this
.
ParseIndexerDeclaration
(
attributes
,
modifiers
,
type
,
explicitInterfaceOpt
,
identifierOrThisOpt
,
typeParameterListOpt
);
}
else
{
//the error position should indicate CurrentToken
return
this
.
AddError
(
incompleteMember
,
incompleteMember
.
FullWidth
+
this
.
CurrentToken
.
GetLeadingTriviaWidth
(),
this
.
CurrentToken
.
Width
,
ErrorCode
.
ERR_InvalidMemberDecl
,
this
.
CurrentToken
.
Text
);
}
}
// If the modifiers did not include "async", and the type we got was "async", and there was an
// error in the identifier or its type parameters, then the user is probably in the midst of typing
// an async method. In that case we reconsider "async" to be a modifier, and treat the identifier
// (with the type parameters) as the type (with type arguments). Then we go back to looking for
// the member name again.
// For example, if we get
// async Task<
// then we want async to be a modifier and Task<MISSING> to be a type.
if
(!
sawRef
&&
identifierOrThisOpt
!=
null
&&
(
typeParameterListOpt
!=
null
&&
typeParameterListOpt
.
ContainsDiagnostics
||
this
.
CurrentToken
.
Kind
!=
SyntaxKind
.
OpenParenToken
&&
this
.
CurrentToken
.
Kind
!=
SyntaxKind
.
OpenBraceToken
&&
this
.
CurrentToken
.
Kind
!=
SyntaxKind
.
EqualsGreaterThanToken
)
&&
ReconsiderTypeAsAsyncModifier
(
ref
modifiers
,
ref
type
,
ref
explicitInterfaceOpt
,
identifierOrThisOpt
,
typeParameterListOpt
))
{
goto
parse_member_name
;
}
Debug
.
Assert
(
identifierOrThisOpt
!=
null
);
switch
(
this
.
CurrentToken
.
Kind
)
{
case
SyntaxKind
.
OpenBraceToken
:
case
SyntaxKind
.
EqualsGreaterThanToken
:
return
this
.
ParsePropertyDeclaration
(
attributes
,
modifiers
,
type
,
explicitInterfaceOpt
,
identifierOrThisOpt
,
typeParameterListOpt
);
if
(
identifierOrThisOpt
.
Kind
==
SyntaxKind
.
ThisKeyword
)
{
return
this
.
ParseIndexerDeclaration
(
attributes
,
modifiers
,
type
,
explicitInterfaceOpt
,
identifierOrThisOpt
,
typeParameterListOpt
);
default
:
// treat anything else as a method.
return
this
.
ParseMethodDeclaration
(
attributes
,
modifiers
,
type
,
explicitInterfaceOpt
,
identifierOrThisOpt
,
typeParameterListOpt
);
}
}
}
else
finally
{
switch
(
this
.
CurrentToken
.
Kind
)
{
case
SyntaxKind
.
OpenBraceToken
:
case
SyntaxKind
.
EqualsGreaterThanToken
:
return
this
.
ParsePropertyDeclaration
(
attributes
,
modifiers
,
type
,
explicitInterfaceOpt
,
identifierOrThisOpt
,
typeParameterListOpt
);
default
:
// treat anything else as a method.
return
this
.
ParseMethodDeclaration
(
attributes
,
modifiers
,
type
,
explicitInterfaceOpt
,
identifierOrThisOpt
,
typeParameterListOpt
);
}
this
.
Release
(
ref
afterTypeResetPoint
);
}
}
finally
...
...
@@ -2409,10 +2424,8 @@ private MemberDeclarationSyntax ParseMemberDeclarationOrStatementCore(SyntaxKind
// type parameter list
private
bool
ReconsiderTypeAsAsyncModifier
(
ref
SyntaxListBuilder
modifiers
,
ref
TypeSyntax
type
,
ref
ExplicitInterfaceSpecifierSyntax
explicitInterfaceOpt
,
SyntaxToken
identifierOrThisOpt
,
TypeParameterListSyntax
typeParameterListOpt
)
TypeSyntax
type
,
SyntaxToken
identifierOrThisOpt
)
{
if
(
type
.
Kind
!=
SyntaxKind
.
IdentifierName
)
return
false
;
if
(
identifierOrThisOpt
.
Kind
!=
SyntaxKind
.
IdentifierToken
)
return
false
;
...
...
@@ -2426,61 +2439,9 @@ private MemberDeclarationSyntax ParseMemberDeclarationOrStatementCore(SyntaxKind
}
modifiers
.
Add
(
ConvertToKeyword
(
identifier
));
SimpleNameSyntax
newType
=
typeParameterListOpt
==
null
?
(
SimpleNameSyntax
)
_syntaxFactory
.
IdentifierName
(
identifierOrThisOpt
)
:
_syntaxFactory
.
GenericName
(
identifierOrThisOpt
,
TypeArgumentFromTypeParameters
(
typeParameterListOpt
));
type
=
(
explicitInterfaceOpt
==
null
)
?
(
TypeSyntax
)
newType
:
_syntaxFactory
.
QualifiedName
(
explicitInterfaceOpt
.
Name
,
explicitInterfaceOpt
.
DotToken
,
newType
);
explicitInterfaceOpt
=
null
;
identifierOrThisOpt
=
default
(
SyntaxToken
);
typeParameterListOpt
=
default
(
TypeParameterListSyntax
);
return
true
;
}
private
TypeArgumentListSyntax
TypeArgumentFromTypeParameters
(
TypeParameterListSyntax
typeParameterList
)
{
var
types
=
_pool
.
AllocateSeparated
<
TypeSyntax
>();
foreach
(
var
p
in
typeParameterList
.
Parameters
.
GetWithSeparators
())
{
switch
((
SyntaxKind
)
p
.
RawKind
)
{
case
SyntaxKind
.
TypeParameter
:
var
typeParameter
=
(
TypeParameterSyntax
)
p
;
var
typeArgument
=
_syntaxFactory
.
IdentifierName
(
typeParameter
.
Identifier
);
// NOTE: reverse order of variance keyword and attributes list so they come out in the right order.
if
(
typeParameter
.
VarianceKeyword
!=
null
)
{
// This only happens in error scenarios, so don't bother to produce a diagnostic about
// having a variance keyword on a type argument.
typeArgument
=
AddLeadingSkippedSyntax
(
typeArgument
,
typeParameter
.
VarianceKeyword
);
}
if
(
typeParameter
.
AttributeLists
.
Node
!=
null
)
{
// This only happens in error scenarios, so don't bother to produce a diagnostic about
// having an attribute on a type argument.
typeArgument
=
AddLeadingSkippedSyntax
(
typeArgument
,
typeParameter
.
AttributeLists
.
Node
);
}
types
.
Add
(
typeArgument
);
break
;
case
SyntaxKind
.
CommaToken
:
types
.
AddSeparator
((
SyntaxToken
)
p
);
break
;
default
:
throw
ExceptionUtilities
.
UnexpectedValue
(
p
.
RawKind
);
}
}
var
result
=
_syntaxFactory
.
TypeArgumentList
(
typeParameterList
.
LessThanToken
,
types
.
ToList
(),
typeParameterList
.
GreaterThanToken
);
_pool
.
Free
(
types
);
return
result
;
}
//private bool ReconsiderTypeAsAsyncModifier(ref SyntaxListBuilder modifiers, ref type, ref identifierOrThisOpt, ref typeParameterListOpt))
// {
// goto parse_member_name;
// }
private
bool
IsFieldDeclaration
(
bool
isEvent
)
{
if
(
this
.
CurrentToken
.
Kind
!=
SyntaxKind
.
IdentifierToken
)
...
...
@@ -6569,9 +6530,15 @@ private StatementSyntax ParseStatementCore()
private
StatementSyntax
ParsePossibleDeclarationOrBadAwaitStatement
()
{
ResetPoint
resetPointBeforeStatement
=
this
.
GetResetPoint
();
StatementSyntax
result
=
ParsePossibleDeclarationOrBadAwaitStatement
(
ref
resetPointBeforeStatement
);
this
.
Release
(
ref
resetPointBeforeStatement
);
return
result
;
try
{
StatementSyntax
result
=
ParsePossibleDeclarationOrBadAwaitStatement
(
ref
resetPointBeforeStatement
);
return
result
;
}
finally
{
this
.
Release
(
ref
resetPointBeforeStatement
);
}
}
private
StatementSyntax
ParsePossibleDeclarationOrBadAwaitStatement
(
ref
ResetPoint
resetPointBeforeStatement
)
...
...
src/Compilers/CSharp/Test/Syntax/Parsing/MemberDeclarationParsingTests.cs
浏览文件 @
a5a9e4fe
...
...
@@ -458,5 +458,287 @@ public void TrashAfterDeclaration()
}
EOF
();
}
[
Fact
]
[
WorkItem
(
11959
,
"https://github.com/dotnet/roslyn/issues/11959"
)]
public
void
GenericAsyncTask_01
()
{
foreach
(
var
options
in
new
[]
{
TestOptions
.
Script
,
TestOptions
.
Regular
})
{
UsingDeclaration
(
"async Task<SomeNamespace.SomeType Method();"
,
options
:
options
,
// (1,1): error CS1073: Unexpected token '('
// async Task<SomeNamespace.SomeType Method();
Diagnostic
(
ErrorCode
.
ERR_UnexpectedToken
,
"async Task<SomeNamespace.SomeType Method"
).
WithArguments
(
"("
).
WithLocation
(
1
,
1
),
// (1,35): error CS1003: Syntax error, ',' expected
// async Task<SomeNamespace.SomeType Method();
Diagnostic
(
ErrorCode
.
ERR_SyntaxError
,
"Method"
).
WithArguments
(
","
,
""
).
WithLocation
(
1
,
35
),
// (1,41): error CS1003: Syntax error, '>' expected
// async Task<SomeNamespace.SomeType Method();
Diagnostic
(
ErrorCode
.
ERR_SyntaxError
,
"("
).
WithArguments
(
">"
,
"("
).
WithLocation
(
1
,
41
)
);
N
(
SyntaxKind
.
IncompleteMember
);
{
N
(
SyntaxKind
.
AsyncKeyword
);
N
(
SyntaxKind
.
GenericName
);
{
N
(
SyntaxKind
.
IdentifierToken
,
"Task"
);
N
(
SyntaxKind
.
TypeArgumentList
);
{
N
(
SyntaxKind
.
LessThanToken
);
N
(
SyntaxKind
.
QualifiedName
);
{
N
(
SyntaxKind
.
IdentifierName
);
{
N
(
SyntaxKind
.
IdentifierToken
,
"SomeNamespace"
);
}
N
(
SyntaxKind
.
DotToken
);
N
(
SyntaxKind
.
IdentifierName
);
{
N
(
SyntaxKind
.
IdentifierToken
,
"SomeType"
);
}
}
M
(
SyntaxKind
.
CommaToken
);
N
(
SyntaxKind
.
IdentifierName
);
{
N
(
SyntaxKind
.
IdentifierToken
,
"Method"
);
}
M
(
SyntaxKind
.
GreaterThanToken
);
}
}
}
EOF
();
}
}
[
Fact
]
[
WorkItem
(
11959
,
"https://github.com/dotnet/roslyn/issues/11959"
)]
public
void
GenericPublicTask_01
()
{
foreach
(
var
options
in
new
[]
{
TestOptions
.
Script
,
TestOptions
.
Regular
})
{
UsingDeclaration
(
"public Task<SomeNamespace.SomeType Method();"
,
options
:
options
,
// (1,1): error CS1073: Unexpected token '('
// public Task<SomeNamespace.SomeType Method();
Diagnostic
(
ErrorCode
.
ERR_UnexpectedToken
,
"public Task<SomeNamespace.SomeType Method"
).
WithArguments
(
"("
).
WithLocation
(
1
,
1
),
// (1,36): error CS1003: Syntax error, ',' expected
// public Task<SomeNamespace.SomeType Method();
Diagnostic
(
ErrorCode
.
ERR_SyntaxError
,
"Method"
).
WithArguments
(
","
,
""
).
WithLocation
(
1
,
36
),
// (1,42): error CS1003: Syntax error, '>' expected
// public Task<SomeNamespace.SomeType Method();
Diagnostic
(
ErrorCode
.
ERR_SyntaxError
,
"("
).
WithArguments
(
">"
,
"("
).
WithLocation
(
1
,
42
)
);
N
(
SyntaxKind
.
IncompleteMember
);
{
N
(
SyntaxKind
.
PublicKeyword
);
N
(
SyntaxKind
.
GenericName
);
{
N
(
SyntaxKind
.
IdentifierToken
,
"Task"
);
N
(
SyntaxKind
.
TypeArgumentList
);
{
N
(
SyntaxKind
.
LessThanToken
);
N
(
SyntaxKind
.
QualifiedName
);
{
N
(
SyntaxKind
.
IdentifierName
);
{
N
(
SyntaxKind
.
IdentifierToken
,
"SomeNamespace"
);
}
N
(
SyntaxKind
.
DotToken
);
N
(
SyntaxKind
.
IdentifierName
);
{
N
(
SyntaxKind
.
IdentifierToken
,
"SomeType"
);
}
}
M
(
SyntaxKind
.
CommaToken
);
N
(
SyntaxKind
.
IdentifierName
);
{
N
(
SyntaxKind
.
IdentifierToken
,
"Method"
);
}
M
(
SyntaxKind
.
GreaterThanToken
);
}
}
}
EOF
();
}
}
[
Fact
]
[
WorkItem
(
11959
,
"https://github.com/dotnet/roslyn/issues/11959"
)]
public
void
GenericAsyncTask_02
()
{
foreach
(
var
options
in
new
[]
{
TestOptions
.
Script
,
TestOptions
.
Regular
})
{
UsingDeclaration
(
"async Task<SomeNamespace. Method();"
,
options
:
options
,
// (1,1): error CS1073: Unexpected token '('
// async Task<SomeNamespace. Method();
Diagnostic
(
ErrorCode
.
ERR_UnexpectedToken
,
"async Task<SomeNamespace. Method"
).
WithArguments
(
"("
).
WithLocation
(
1
,
1
),
// (1,33): error CS1003: Syntax error, '>' expected
// async Task<SomeNamespace. Method();
Diagnostic
(
ErrorCode
.
ERR_SyntaxError
,
"("
).
WithArguments
(
">"
,
"("
).
WithLocation
(
1
,
33
)
);
N
(
SyntaxKind
.
IncompleteMember
);
{
N
(
SyntaxKind
.
AsyncKeyword
);
N
(
SyntaxKind
.
GenericName
);
{
N
(
SyntaxKind
.
IdentifierToken
,
"Task"
);
N
(
SyntaxKind
.
TypeArgumentList
);
{
N
(
SyntaxKind
.
LessThanToken
);
N
(
SyntaxKind
.
QualifiedName
);
{
N
(
SyntaxKind
.
IdentifierName
);
{
N
(
SyntaxKind
.
IdentifierToken
,
"SomeNamespace"
);
N
(
SyntaxKind
.
DotToken
);
N
(
SyntaxKind
.
IdentifierName
);
{
N
(
SyntaxKind
.
IdentifierToken
,
"Method"
);
}
M
(
SyntaxKind
.
GreaterThanToken
);
}
}
}
}
}
EOF
();
}
}
[
Fact
]
[
WorkItem
(
11959
,
"https://github.com/dotnet/roslyn/issues/11959"
)]
public
void
GenericPublicTask_02
()
{
foreach
(
var
options
in
new
[]
{
TestOptions
.
Script
,
TestOptions
.
Regular
})
{
UsingDeclaration
(
"public Task<SomeNamespace. Method();"
,
options
:
options
,
// (1,1): error CS1073: Unexpected token '('
// public Task<SomeNamespace. Method();
Diagnostic
(
ErrorCode
.
ERR_UnexpectedToken
,
"public Task<SomeNamespace. Method"
).
WithArguments
(
"("
).
WithLocation
(
1
,
1
),
// (1,34): error CS1003: Syntax error, '>' expected
// public Task<SomeNamespace. Method();
Diagnostic
(
ErrorCode
.
ERR_SyntaxError
,
"("
).
WithArguments
(
">"
,
"("
).
WithLocation
(
1
,
34
)
);
N
(
SyntaxKind
.
IncompleteMember
);
{
N
(
SyntaxKind
.
PublicKeyword
);
N
(
SyntaxKind
.
GenericName
);
{
N
(
SyntaxKind
.
IdentifierToken
,
"Task"
);
N
(
SyntaxKind
.
TypeArgumentList
);
{
N
(
SyntaxKind
.
LessThanToken
);
N
(
SyntaxKind
.
QualifiedName
);
{
N
(
SyntaxKind
.
IdentifierName
);
{
N
(
SyntaxKind
.
IdentifierToken
,
"SomeNamespace"
);
}
N
(
SyntaxKind
.
DotToken
);
N
(
SyntaxKind
.
IdentifierName
);
{
N
(
SyntaxKind
.
IdentifierToken
,
"Method"
);
}
}
M
(
SyntaxKind
.
GreaterThanToken
);
}
}
}
EOF
();
}
}
[
Fact
]
[
WorkItem
(
11959
,
"https://github.com/dotnet/roslyn/issues/11959"
)]
public
void
GenericAsyncTask_03
()
{
foreach
(
var
options
in
new
[]
{
TestOptions
.
Script
,
TestOptions
.
Regular
})
{
UsingDeclaration
(
"async Task<SomeNamespace.> Method();"
,
options
:
options
,
// (1,26): error CS1001: Identifier expected
// async Task<SomeNamespace.> Method();
Diagnostic
(
ErrorCode
.
ERR_IdentifierExpected
,
">"
).
WithLocation
(
1
,
26
)
);
N
(
SyntaxKind
.
MethodDeclaration
);
{
N
(
SyntaxKind
.
AsyncKeyword
);
N
(
SyntaxKind
.
GenericName
);
{
N
(
SyntaxKind
.
IdentifierToken
,
"Task"
);
N
(
SyntaxKind
.
TypeArgumentList
);
{
N
(
SyntaxKind
.
LessThanToken
);
N
(
SyntaxKind
.
QualifiedName
);
{
N
(
SyntaxKind
.
IdentifierName
);
{
N
(
SyntaxKind
.
IdentifierToken
,
"SomeNamespace"
);
}
N
(
SyntaxKind
.
DotToken
);
M
(
SyntaxKind
.
IdentifierName
);
{
M
(
SyntaxKind
.
IdentifierToken
);
}
}
N
(
SyntaxKind
.
GreaterThanToken
);
}
}
N
(
SyntaxKind
.
IdentifierToken
,
"Method"
);
N
(
SyntaxKind
.
ParameterList
);
{
N
(
SyntaxKind
.
OpenParenToken
);
N
(
SyntaxKind
.
CloseParenToken
);
}
N
(
SyntaxKind
.
SemicolonToken
);
}
EOF
();
}
}
[
Fact
]
[
WorkItem
(
11959
,
"https://github.com/dotnet/roslyn/issues/11959"
)]
public
void
GenericPublicTask_03
()
{
foreach
(
var
options
in
new
[]
{
TestOptions
.
Script
,
TestOptions
.
Regular
})
{
UsingDeclaration
(
"public Task<SomeNamespace.> Method();"
,
options
:
options
,
// (1,27): error CS1001: Identifier expected
// public Task<SomeNamespace.> Method();
Diagnostic
(
ErrorCode
.
ERR_IdentifierExpected
,
">"
).
WithLocation
(
1
,
27
)
);
N
(
SyntaxKind
.
MethodDeclaration
);
{
N
(
SyntaxKind
.
PublicKeyword
);
N
(
SyntaxKind
.
GenericName
);
{
N
(
SyntaxKind
.
IdentifierToken
,
"Task"
);
N
(
SyntaxKind
.
TypeArgumentList
);
{
N
(
SyntaxKind
.
LessThanToken
);
N
(
SyntaxKind
.
QualifiedName
);
{
N
(
SyntaxKind
.
IdentifierName
);
{
N
(
SyntaxKind
.
IdentifierToken
,
"SomeNamespace"
);
}
N
(
SyntaxKind
.
DotToken
);
M
(
SyntaxKind
.
IdentifierName
);
{
M
(
SyntaxKind
.
IdentifierToken
);
}
}
N
(
SyntaxKind
.
GreaterThanToken
);
}
}
N
(
SyntaxKind
.
IdentifierToken
,
"Method"
);
N
(
SyntaxKind
.
ParameterList
);
{
N
(
SyntaxKind
.
OpenParenToken
);
N
(
SyntaxKind
.
CloseParenToken
);
}
N
(
SyntaxKind
.
SemicolonToken
);
}
EOF
();
}
}
}
}
src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests.vb
浏览文件 @
a5a9e4fe
...
...
@@ -4135,6 +4135,32 @@ class C
End
Using
End
Function
<
WorkItem
(
11959
,
"https://github.com/dotnet/roslyn/issues/11959"
)
>
<
MemberData
(
NameOf
(
AllCompletionImplementations
))
>
<
WpfTheory
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
Completion
)
>
Public
Async
Function
TestGenericAsyncTaskDeclaration
(
completionImplementation
As
CompletionImplementation
)
As
Task
Using
state
=
TestStateFactory
.
CreateCSharpTestState
(
completionImplementation
,
<
Document
>
namespace
A
.
B
{
class
TestClass
{
}
}
namespace
A
{
class
C
{
async
Task
&
lt
;
A
$$
Method
()
{
}
}
}
</
Document
>
)
state
.
SendTypeChars
(
"."
)
Await
state
.
AssertSelectedCompletionItem
(
displayText
:
=
"B"
,
isSoftSelected
:
=
True
)
End
Using
End
Function
Private
Class
MultipleChangeCompletionProvider
Inherits
CompletionProvider
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录