Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
cbc87518
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,发现更多精彩内容 >>
未验证
提交
cbc87518
编写于
2月 13, 2020
作者:
M
msftbot[bot]
提交者:
GitHub
2月 13, 2020
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #41556 from CyrusNajmabadi/awaitErrorRecovery
Simplify error recovery for misplaced await-expressions.
上级
a5ae0043
74d7ddc1
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
97 addition
and
145 deletion
+97
-145
src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
+47
-70
src/Compilers/CSharp/Test/Syntax/Parsing/AwaitParsingTests.cs
...Compilers/CSharp/Test/Syntax/Parsing/AwaitParsingTests.cs
+22
-36
src/Compilers/CSharp/Test/Syntax/Parsing/LocalFunctionParsingTests.cs
...s/CSharp/Test/Syntax/Parsing/LocalFunctionParsingTests.cs
+17
-28
src/Compilers/CSharp/Test/Syntax/Parsing/StatementParsingTests.cs
...ilers/CSharp/Test/Syntax/Parsing/StatementParsingTests.cs
+11
-11
未找到文件。
src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
浏览文件 @
cbc87518
...
...
@@ -6319,7 +6319,7 @@ private StatementSyntax ParseStatementCore()
// it as either a declaration or as an "await X();" statement that is in a non-async
// method.
return
ParsePossibleDeclarationOrBadAwaitStatement
();
return
Try
ParsePossibleDeclarationOrBadAwaitStatement
();
}
finally
{
...
...
@@ -6327,87 +6327,64 @@ private StatementSyntax ParseStatementCore()
}
}
private
StatementSyntax
ParsePossibleDeclarationOrBadAwaitStatement
()
private
StatementSyntax
Try
ParsePossibleDeclarationOrBadAwaitStatement
()
{
ResetPoint
resetPointBeforeStatement
=
this
.
GetResetPoint
();
try
{
StatementSyntax
result
=
ParsePossibleDeclarationOrBadAwaitStatement
(
ref
resetPointBeforeStatement
);
return
result
;
}
finally
{
this
.
Release
(
ref
resetPointBeforeStatement
);
}
}
private
StatementSyntax
ParsePossibleDeclarationOrBadAwaitStatement
(
ref
ResetPoint
resetPointBeforeStatement
)
{
// Precondition: We have already attempted to parse the statement as a non-declaration and failed.
//
// That means that we are in one of the following cases:
//
// 1) This is not a statement. This can happen if the start of the statement was an
// accessibility modifier, but the rest of the statement did not parse as a local
// function. If there was an accessibility modifier and the statement parsed as
// local function, that should be marked as a mistake with local function visibility.
// Otherwise, it's likely the user just forgot a closing brace on their method.
// 2) This is a perfectly mundane and correct local declaration statement like "int x;"
// 3) This is a perfectly mundane but erroneous local declaration statement, like "int X();"
// 4) We are in the rare case of the code containing "await x;" and the intention is that
// "await" is the type of "x". This only works in a non-async method.
// 5) We have what would be a legal await statement, like "await X();", but we are not in
// an async method, so the parse failed. (Had we been in an async method then the parse
// attempt done by our caller would have succeeded.)
// 6) The statement begins with "await" but is not a legal local declaration and not a legal
// await expression regardless of whether the method is marked as "async".
bool
beginsWithAwait
=
this
.
CurrentToken
.
ContextualKind
==
SyntaxKind
.
AwaitKeyword
;
StatementSyntax
result
=
ParseLocalDeclarationStatement
();
// Case (1)
if
(
result
==
null
)
{
this
.
Reset
(
ref
resetPointBeforeStatement
);
return
null
;
}
// Precondition: We have already attempted to parse the statement as a non-declaration and failed.
//
// That means that we are in one of the following cases:
//
// 1) This is not a statement. This can happen if the start of the statement was an
// accessibility modifier, but the rest of the statement did not parse as a local
// function. If there was an accessibility modifier and the statement parsed as
// local function, that should be marked as a mistake with local function visibility.
// Otherwise, it's likely the user just forgot a closing brace on their method.
// 2) This is a perfectly mundane and correct local declaration statement like "int x;"
// 3) This is a perfectly mundane but erroneous local declaration statement, like "int X();"
// 4) We are in the rare case of the code containing "await x;" and the intention is that
// "await" is the type of "x". This only works in a non-async method.
// 5) We have a misplaced await statement in a non-async method, like "await X();",
// so the parse failed. Had we been in an async method then the parse attempt
// done by our caller would have succeeded. Retry as if we were async. Later
// semantic code will error out that this isn't legal.
bool
beginsWithAwait
=
this
.
CurrentToken
.
ContextualKind
==
SyntaxKind
.
AwaitKeyword
;
StatementSyntax
result
=
ParseLocalDeclarationStatement
();
// Case (1)
if
(
result
==
null
)
{
this
.
Reset
(
ref
resetPointBeforeStatement
);
return
null
;
}
// Cases (2), (3) and (4):
if
(!
beginsWithAwait
||
!
result
.
ContainsDiagnostics
)
{
return
result
;
}
// Cases (2), (3) and (4):
if
(!
beginsWithAwait
||
!
result
.
ContainsDiagnostics
)
{
return
result
;
}
// The statement begins with "await" and could not be parsed as a legal declaration statement.
// We know from our precondition that it is not a legal "await X();" statement, though it is
// possible that it was only not legal because we were not in an async context.
// The statement begins with "await" and could not be parsed as a legal declaration statement.
// We know from our precondition that it is not a legal "await X();" statement, though it is
// possible that it was only not legal because we were not in an async context.
Debug
.
Assert
(!
IsInAsync
);
Debug
.
Assert
(!
IsInAsync
);
// Let's see if we're in case (5). Pretend that we're in an async method and see if parsing
// a non-declaration statement would have succeeded.
// Let's see if we're in case (5). Pretend that we're in an async method and retry.
this
.
Reset
(
ref
resetPointBeforeStatement
);
IsInAsync
=
true
;
result
=
ParseStatementNoDeclaration
(
allowAnyExpression
:
false
);
IsInAsync
=
false
;
this
.
Reset
(
ref
resetPointBeforeStatement
);
IsInAsync
=
true
;
result
=
ParseStatementNoDeclaration
(
allowAnyExpression
:
false
);
IsInAsync
=
false
;
if
(!
result
.
ContainsDiagnostics
)
{
// We are in case (5). We do not report that we have an "await" expression in a non-async
// method at parse time; rather we do that in BindAwait(), during the initial round of
// semantic analysis.
return
result
;
}
// We are in case (6); we can't figure out what is going on here. Our best guess is that it is
// a malformed local declaration, so back up and re-parse it.
this
.
Reset
(
ref
resetPointBeforeStatement
);
result
=
ParseLocalDeclarationStatement
();
Debug
.
Assert
(
result
.
ContainsDiagnostics
);
return
result
;
finally
{
this
.
Release
(
ref
resetPointBeforeStatement
);
}
}
/// <summary>
...
...
src/Compilers/CSharp/Test/Syntax/Parsing/AwaitParsingTests.cs
浏览文件 @
cbc87518
...
...
@@ -1890,28 +1890,21 @@ public void BadLocalDeclarationAndAwaitExpressionInSyncContext()
N
(
SyntaxKind
.
Block
);
{
N
(
SyntaxKind
.
OpenBraceToken
);
N
(
SyntaxKind
.
LocalDeclarat
ionStatement
);
N
(
SyntaxKind
.
Express
ionStatement
);
{
N
(
SyntaxKind
.
VariableDeclarat
ion
);
N
(
SyntaxKind
.
AwaitExpress
ion
);
{
N
(
SyntaxKind
.
IdentifierName
);
{
N
(
SyntaxKind
.
IdentifierToken
,
"await"
);
}
N
(
SyntaxKind
.
VariableDeclarator
);
N
(
SyntaxKind
.
AwaitKeyword
);
N
(
SyntaxKind
.
InvocationExpression
);
{
N
(
SyntaxKind
.
IdentifierToken
,
"goo"
);
N
(
SyntaxKind
.
BracketedArgumentList
);
N
(
SyntaxKind
.
IdentifierName
);
{
M
(
SyntaxKind
.
OpenBracketToken
);
M
(
SyntaxKind
.
Argument
);
{
M
(
SyntaxKind
.
IdentifierName
);
{
M
(
SyntaxKind
.
IdentifierToken
);
}
}
N
(
SyntaxKind
.
CloseBracketToken
);
N
(
SyntaxKind
.
IdentifierToken
,
"goo"
);
}
N
(
SyntaxKind
.
ArgumentList
);
{
N
(
SyntaxKind
.
OpenParenToken
);
M
(
SyntaxKind
.
CloseParenToken
);
}
}
}
...
...
@@ -1943,28 +1936,21 @@ public void BadStatementInSyncContext()
N
(
SyntaxKind
.
Block
);
{
N
(
SyntaxKind
.
OpenBraceToken
);
N
(
SyntaxKind
.
LocalDeclarat
ionStatement
);
N
(
SyntaxKind
.
Express
ionStatement
);
{
N
(
SyntaxKind
.
VariableDeclarat
ion
);
N
(
SyntaxKind
.
AwaitExpress
ion
);
{
N
(
SyntaxKind
.
IdentifierName
);
{
N
(
SyntaxKind
.
IdentifierToken
,
"await"
);
}
N
(
SyntaxKind
.
VariableDeclarator
);
N
(
SyntaxKind
.
AwaitKeyword
);
N
(
SyntaxKind
.
InvocationExpression
);
{
N
(
SyntaxKind
.
IdentifierToken
,
"goo"
);
N
(
SyntaxKind
.
BracketedArgumentList
);
N
(
SyntaxKind
.
IdentifierName
);
{
M
(
SyntaxKind
.
OpenBracketToken
);
M
(
SyntaxKind
.
Argument
);
{
M
(
SyntaxKind
.
IdentifierName
);
{
M
(
SyntaxKind
.
IdentifierToken
);
}
}
N
(
SyntaxKind
.
CloseBracketToken
);
N
(
SyntaxKind
.
IdentifierToken
,
"goo"
);
}
N
(
SyntaxKind
.
ArgumentList
);
{
N
(
SyntaxKind
.
OpenParenToken
);
M
(
SyntaxKind
.
CloseParenToken
);
}
}
}
...
...
src/Compilers/CSharp/Test/Syntax/Parsing/LocalFunctionParsingTests.cs
浏览文件 @
cbc87518
...
...
@@ -71,28 +71,17 @@ void M6()
N
(
SyntaxKind
.
Block
);
{
N
(
SyntaxKind
.
OpenBraceToken
);
N
(
SyntaxKind
.
LocalDeclarationStatement
);
{
N
(
SyntaxKind
.
VariableDeclaration
);
{
N
(
SyntaxKind
.
IdentifierName
);
{
N
(
SyntaxKind
.
IdentifierToken
,
"await"
);
}
N
(
SyntaxKind
.
VariableDeclarator
);
{
N
(
SyntaxKind
.
IdentifierToken
,
"L"
);
}
}
M
(
SyntaxKind
.
SemicolonToken
);
}
N
(
SyntaxKind
.
ExpressionStatement
);
{
N
(
SyntaxKind
.
LessThanExpression
);
{
M
(
SyntaxKind
.
IdentifierName
);
N
(
SyntaxKind
.
AwaitExpression
);
{
M
(
SyntaxKind
.
IdentifierToken
);
N
(
SyntaxKind
.
AwaitKeyword
);
N
(
SyntaxKind
.
IdentifierName
);
{
N
(
SyntaxKind
.
IdentifierToken
,
"L"
);
}
}
N
(
SyntaxKind
.
LessThanToken
);
M
(
SyntaxKind
.
IdentifierName
);
...
...
@@ -206,21 +195,21 @@ void M6()
N
(
SyntaxKind
.
Block
);
{
N
(
SyntaxKind
.
OpenBraceToken
);
N
(
SyntaxKind
.
LocalDeclarat
ionStatement
);
N
(
SyntaxKind
.
Express
ionStatement
);
{
N
(
SyntaxKind
.
VariableDeclarat
ion
);
N
(
SyntaxKind
.
AwaitExpress
ion
);
{
N
(
SyntaxKind
.
IdentifierName
);
{
N
(
SyntaxKind
.
IdentifierToken
,
"await"
);
}
N
(
SyntaxKind
.
VariableDeclarator
);
N
(
SyntaxKind
.
AwaitKeyword
);
N
(
SyntaxKind
.
InvocationExpression
);
{
N
(
SyntaxKind
.
IdentifierToken
,
"L"
);
M
(
SyntaxKind
.
BracketedArgumentList
);
N
(
SyntaxKind
.
IdentifierName
);
{
M
(
SyntaxKind
.
OpenBracketToken
);
M
(
SyntaxKind
.
CloseBracketToken
);
N
(
SyntaxKind
.
IdentifierToken
,
"L"
);
}
N
(
SyntaxKind
.
ArgumentList
);
{
N
(
SyntaxKind
.
OpenParenToken
);
M
(
SyntaxKind
.
CloseParenToken
);
}
}
}
...
...
src/Compilers/CSharp/Test/Syntax/Parsing/StatementParsingTests.cs
浏览文件 @
cbc87518
...
...
@@ -2752,25 +2752,25 @@ async void M()
[
Fact
]
public
void
TestAwaitUsingVarWithVarAndNoUsingDeclarationTree
()
{
UsingStatement
(
@"await var a = b;"
,
TestOptions
.
Regular8
,
expectedErrors
:
// (1,1
1): error CS1003: Syntax error, ',' expected
UsingStatement
(
@"await var a = b;"
,
TestOptions
.
Regular8
,
// (1,1
): error CS1073: Unexpected token 'a'
// await var a = b;
Diagnostic
(
ErrorCode
.
ERR_SyntaxError
,
"a"
).
WithArguments
(
","
,
""
).
WithLocation
(
1
,
11
)
);
N
(
SyntaxKind
.
LocalDeclarationStatement
);
Diagnostic
(
ErrorCode
.
ERR_UnexpectedToken
,
"await var "
).
WithArguments
(
"a"
).
WithLocation
(
1
,
1
),
// (1,11): error CS1002: ; expected
// await var a = b;
Diagnostic
(
ErrorCode
.
ERR_SemicolonExpected
,
"a"
).
WithLocation
(
1
,
11
));
N
(
SyntaxKind
.
ExpressionStatement
);
{
N
(
SyntaxKind
.
VariableDeclarat
ion
);
N
(
SyntaxKind
.
AwaitExpress
ion
);
{
N
(
SyntaxKind
.
AwaitKeyword
);
N
(
SyntaxKind
.
IdentifierName
);
{
N
(
SyntaxKind
.
IdentifierToken
,
"await"
);
}
N
(
SyntaxKind
.
VariableDeclarator
);
{
N
(
SyntaxKind
.
IdentifierToken
,
"var"
);
}
}
N
(
SyntaxKind
.
SemicolonToken
);
M
(
SyntaxKind
.
SemicolonToken
);
}
EOF
();
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录