Add the ability for users to await expressions.
This enabled things like @await Foo(). We special case the await keyword and allow another snippet of code to follow it.
This commit is contained in:
parent
aef8a79081
commit
50314ca7e5
|
|
@ -0,0 +1,41 @@
|
||||||
|
using Microsoft.AspNet.Razor.Tokenizer.Symbols;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Razor.Parser
|
||||||
|
{
|
||||||
|
public partial class CSharpCodeParser
|
||||||
|
{
|
||||||
|
private void SetUpExpressions()
|
||||||
|
{
|
||||||
|
MapKeywords(AwaitExpression, CSharpKeyword.Await);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AwaitExpression(bool topLevel)
|
||||||
|
{
|
||||||
|
// Ensure that we're on the await statement (only runs in debug)
|
||||||
|
Assert(CSharpKeyword.Await);
|
||||||
|
|
||||||
|
// Accept the "await" and move on
|
||||||
|
AcceptAndMoveNext();
|
||||||
|
|
||||||
|
// Accept 1 or more spaces between the await and the following code.
|
||||||
|
AcceptWhile(IsSpacingToken(includeNewLines: false, includeComments: true));
|
||||||
|
|
||||||
|
// Accept a single code piece to await. This will accept up until a method "call" signature.
|
||||||
|
// Ex: "@await |Foo|()" Inbetween the pipes is what is accepted. The Statement/ImplicitExpression
|
||||||
|
// handling capture method calls and the parameters passed in.
|
||||||
|
AcceptWhile(CSharpSymbolType.Identifier);
|
||||||
|
|
||||||
|
// Top level basically indicates if we're within an expression or statement.
|
||||||
|
// Ex: topLevel true = @await Foo() | topLevel false = @{ await Foo(); }
|
||||||
|
// Note that in this case @{ <b>@await Foo()</b> } top level is true for await.
|
||||||
|
// Therefore, if we're top level then we want to act like an implicit expression,
|
||||||
|
// otherwise just act as whatever we're contained in.
|
||||||
|
if (topLevel)
|
||||||
|
{
|
||||||
|
// Setup the Span to be an async implicit expression (an implicit expresison that allows spaces).
|
||||||
|
// Spaces are allowed because of "@await Foo()".
|
||||||
|
AsyncImplicitExpression();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -18,6 +18,7 @@ namespace Microsoft.AspNet.Razor.Parser
|
||||||
|
|
||||||
internal static ISet<string> DefaultKeywords = new HashSet<string>()
|
internal static ISet<string> DefaultKeywords = new HashSet<string>()
|
||||||
{
|
{
|
||||||
|
"await",
|
||||||
"if",
|
"if",
|
||||||
"do",
|
"do",
|
||||||
"try",
|
"try",
|
||||||
|
|
@ -45,6 +46,7 @@ namespace Microsoft.AspNet.Razor.Parser
|
||||||
Keywords = new HashSet<string>();
|
Keywords = new HashSet<string>();
|
||||||
SetUpKeywords();
|
SetUpKeywords();
|
||||||
SetupDirectives();
|
SetupDirectives();
|
||||||
|
SetUpExpressions();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected internal ISet<string> Keywords { get; private set; }
|
protected internal ISet<string> Keywords { get; private set; }
|
||||||
|
|
@ -307,6 +309,18 @@ namespace Microsoft.AspNet.Razor.Parser
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ImplicitExpression()
|
private void ImplicitExpression()
|
||||||
|
{
|
||||||
|
ImplicitExpression(AcceptedCharacters.NonWhiteSpace);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Async implicit expressions include the "await" keyword and therefore need to allow spaces to
|
||||||
|
// separate the "await" and the following code.
|
||||||
|
private void AsyncImplicitExpression()
|
||||||
|
{
|
||||||
|
ImplicitExpression(AcceptedCharacters.AnyExceptNewline);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ImplicitExpression(AcceptedCharacters acceptedCharacters)
|
||||||
{
|
{
|
||||||
Context.CurrentBlock.Type = BlockType.Expression;
|
Context.CurrentBlock.Type = BlockType.Expression;
|
||||||
Context.CurrentBlock.CodeGenerator = new ExpressionCodeGenerator();
|
Context.CurrentBlock.CodeGenerator = new ExpressionCodeGenerator();
|
||||||
|
|
@ -314,7 +328,7 @@ namespace Microsoft.AspNet.Razor.Parser
|
||||||
using (PushSpanConfig(span =>
|
using (PushSpanConfig(span =>
|
||||||
{
|
{
|
||||||
span.EditHandler = new ImplicitExpressionEditHandler(Language.TokenizeString, Keywords, acceptTrailingDot: IsNested);
|
span.EditHandler = new ImplicitExpressionEditHandler(Language.TokenizeString, Keywords, acceptTrailingDot: IsNested);
|
||||||
span.EditHandler.AcceptedCharacters = AcceptedCharacters.NonWhiteSpace;
|
span.EditHandler.AcceptedCharacters = acceptedCharacters;
|
||||||
span.CodeGenerator = new ExpressionCodeGenerator();
|
span.CodeGenerator = new ExpressionCodeGenerator();
|
||||||
}))
|
}))
|
||||||
{
|
{
|
||||||
|
|
@ -325,14 +339,14 @@ namespace Microsoft.AspNet.Razor.Parser
|
||||||
AcceptAndMoveNext();
|
AcceptAndMoveNext();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (MethodCallOrArrayIndex());
|
while (MethodCallOrArrayIndex(acceptedCharacters));
|
||||||
|
|
||||||
PutCurrentBack();
|
PutCurrentBack();
|
||||||
Output(SpanKind.Code);
|
Output(SpanKind.Code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool MethodCallOrArrayIndex()
|
private bool MethodCallOrArrayIndex(AcceptedCharacters acceptedCharacters)
|
||||||
{
|
{
|
||||||
if (!EndOfFile)
|
if (!EndOfFile)
|
||||||
{
|
{
|
||||||
|
|
@ -361,9 +375,11 @@ namespace Microsoft.AspNet.Razor.Parser
|
||||||
if (At(right))
|
if (At(right))
|
||||||
{
|
{
|
||||||
AcceptAndMoveNext();
|
AcceptAndMoveNext();
|
||||||
Span.EditHandler.AcceptedCharacters = AcceptedCharacters.NonWhiteSpace;
|
|
||||||
|
// At the ending brace, restore the initial accepted characters.
|
||||||
|
Span.EditHandler.AcceptedCharacters = acceptedCharacters;
|
||||||
}
|
}
|
||||||
return MethodCallOrArrayIndex();
|
return MethodCallOrArrayIndex(acceptedCharacters);
|
||||||
}
|
}
|
||||||
if (CurrentSymbol.Type == CSharpSymbolType.Dot)
|
if (CurrentSymbol.Type == CSharpSymbolType.Dot)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ namespace Microsoft.AspNet.Razor.Tokenizer
|
||||||
{
|
{
|
||||||
private static readonly Dictionary<string, CSharpKeyword> _keywords = new Dictionary<string, CSharpKeyword>(StringComparer.Ordinal)
|
private static readonly Dictionary<string, CSharpKeyword> _keywords = new Dictionary<string, CSharpKeyword>(StringComparer.Ordinal)
|
||||||
{
|
{
|
||||||
|
{ "await", CSharpKeyword.Await },
|
||||||
{ "abstract", CSharpKeyword.Abstract },
|
{ "abstract", CSharpKeyword.Abstract },
|
||||||
{ "byte", CSharpKeyword.Byte },
|
{ "byte", CSharpKeyword.Byte },
|
||||||
{ "class", CSharpKeyword.Class },
|
{ "class", CSharpKeyword.Class },
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ namespace Microsoft.AspNet.Razor.Tokenizer.Symbols
|
||||||
{
|
{
|
||||||
public enum CSharpKeyword
|
public enum CSharpKeyword
|
||||||
{
|
{
|
||||||
|
Await,
|
||||||
Abstract,
|
Abstract,
|
||||||
Byte,
|
Byte,
|
||||||
Class,
|
Class,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue