Add support for static usings.
- Added special cases to the using statement parser to understand `@using static Foo`. - Added several unit tests to validate the static using structure. - Modified existing import code generation tests to validate several static usings. #44
This commit is contained in:
parent
aaa14cd36b
commit
1879ac6427
|
|
@ -101,7 +101,7 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
// using ( ==> Using Statement
|
||||
UsingStatement(block);
|
||||
}
|
||||
else if (At(CSharpSymbolType.Identifier))
|
||||
else if (At(CSharpSymbolType.Identifier) || At(CSharpKeyword.Static))
|
||||
{
|
||||
// using Identifier ==> Using Declaration
|
||||
if (!topLevel)
|
||||
|
|
@ -126,31 +126,40 @@ namespace Microsoft.AspNet.Razor.Parser
|
|||
// Set block type to directive
|
||||
Context.CurrentBlock.Type = BlockType.Directive;
|
||||
|
||||
// Parse a type name
|
||||
Assert(CSharpSymbolType.Identifier);
|
||||
NamespaceOrTypeName();
|
||||
IEnumerable<CSharpSymbol> ws = ReadWhile(IsSpacingToken(includeNewLines: true, includeComments: true));
|
||||
if (At(CSharpSymbolType.Assign))
|
||||
if (At(CSharpSymbolType.Identifier))
|
||||
{
|
||||
// Alias
|
||||
Accept(ws);
|
||||
Assert(CSharpSymbolType.Assign);
|
||||
AcceptAndMoveNext();
|
||||
|
||||
AcceptWhile(IsSpacingToken(includeNewLines: true, includeComments: true));
|
||||
|
||||
// One more namespace or type name
|
||||
// non-static using
|
||||
NamespaceOrTypeName();
|
||||
var whitespace = ReadWhile(IsSpacingToken(includeNewLines: true, includeComments: true));
|
||||
if (At(CSharpSymbolType.Assign))
|
||||
{
|
||||
// Alias
|
||||
Accept(whitespace);
|
||||
Assert(CSharpSymbolType.Assign);
|
||||
AcceptAndMoveNext();
|
||||
|
||||
AcceptWhile(IsSpacingToken(includeNewLines: true, includeComments: true));
|
||||
|
||||
// One more namespace or type name
|
||||
NamespaceOrTypeName();
|
||||
}
|
||||
else
|
||||
{
|
||||
PutCurrentBack();
|
||||
PutBack(whitespace);
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (At(CSharpKeyword.Static))
|
||||
{
|
||||
PutCurrentBack();
|
||||
PutBack(ws);
|
||||
// static using
|
||||
AcceptAndMoveNext();
|
||||
AcceptWhile(IsSpacingToken(includeNewLines: false, includeComments: true));
|
||||
NamespaceOrTypeName();
|
||||
}
|
||||
|
||||
Span.EditHandler.AcceptedCharacters = AcceptedCharacters.AnyExceptNewline;
|
||||
Span.CodeGenerator = new AddImportCodeGenerator(
|
||||
Span.GetContent(syms => syms.Skip(1)));
|
||||
Span.GetContent(symbols => symbols.Skip(1)));
|
||||
|
||||
// Optional ";"
|
||||
if (EnsureCurrent())
|
||||
|
|
|
|||
|
|
@ -176,8 +176,11 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
|||
BuildLineMapping(1, 0, 1, 51, 3, 0, 15),
|
||||
BuildLineMapping(19, 1, 1, 132, 9, 0, 32),
|
||||
BuildLineMapping(54, 2, 1, 230, 15, 0, 12),
|
||||
BuildLineMapping(99, 4, 772, 39, 29, 21),
|
||||
BuildLineMapping(161, 5, 888, 44, 35, 20)
|
||||
BuildLineMapping(71, 4, 1, 308, 21, 0, 19),
|
||||
BuildLineMapping(93, 5, 1, 393, 27, 0, 27),
|
||||
BuildLineMapping(123, 6, 1, 486, 33, 0, 41),
|
||||
BuildLineMapping(197, 8, 1057, 57, 29, 21),
|
||||
BuildLineMapping(259, 9, 1174, 62, 35, 20)
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Razor.Generator;
|
||||
using Microsoft.AspNet.Razor.Parser;
|
||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
||||
|
|
@ -148,6 +149,53 @@ namespace Microsoft.AspNet.Razor.Test.Parser.CSharp
|
|||
));
|
||||
}
|
||||
|
||||
public static TheoryData StaticUsingData
|
||||
{
|
||||
get
|
||||
{
|
||||
var factory = SpanFactory.CreateCsHtml();
|
||||
Func<string, string, DirectiveBlock> createUsing = (code, import) =>
|
||||
new DirectiveBlock(
|
||||
factory.CodeTransition(),
|
||||
factory.Code(code)
|
||||
.AsNamespaceImport(import)
|
||||
.Accepts(AcceptedCharacters.AnyExceptNewline));
|
||||
|
||||
// document, expectedResult
|
||||
return new TheoryData<string, DirectiveBlock>
|
||||
{
|
||||
{ "@using static", createUsing("using static", " static") },
|
||||
{ "@using static ", createUsing("using static ", " static ") },
|
||||
{ "@using static ", createUsing("using static ", " static ") },
|
||||
{ "@using static System", createUsing("using static System", " static System") },
|
||||
{
|
||||
"@using static System",
|
||||
createUsing("using static System", " static System")
|
||||
},
|
||||
{
|
||||
"@using static System.Console",
|
||||
createUsing("using static System.Console", " static System.Console")
|
||||
},
|
||||
{
|
||||
"@using static global::System.Console",
|
||||
createUsing("using static global::System.Console", " static global::System.Console")
|
||||
},
|
||||
{
|
||||
"@using static global::System.Console ",
|
||||
createUsing("using static global::System.Console", " static global::System.Console")
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(StaticUsingData))]
|
||||
public void StaticUsingImport(string document, DirectiveBlock expectedResult)
|
||||
{
|
||||
// Act & Assert
|
||||
ParseBlockTest(document, expectedResult);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UsingStatement()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -15,6 +15,24 @@ using Foo = System.Text.Encoding
|
|||
#line 3 "Imports.cshtml"
|
||||
using System
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
;
|
||||
#line 5 "Imports.cshtml"
|
||||
using static System
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
;
|
||||
#line 6 "Imports.cshtml"
|
||||
using static System.Console
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
;
|
||||
#line 7 "Imports.cshtml"
|
||||
using static global::System.Text.Encoding
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
;
|
||||
|
|
@ -36,12 +54,12 @@ using System
|
|||
#pragma warning disable 1998
|
||||
public override async Task ExecuteAsync()
|
||||
{
|
||||
#line 5 "Imports.cshtml"
|
||||
#line 9 "Imports.cshtml"
|
||||
__o = typeof(Path).FullName;
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#line 6 "Imports.cshtml"
|
||||
#line 10 "Imports.cshtml"
|
||||
__o = typeof(Foo).FullName;
|
||||
|
||||
#line default
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#pragma checksum "Imports.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "1b57def0ce2632d0f50d63dbdc5e0e719c202863"
|
||||
#pragma checksum "Imports.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "f452adb7c255f6d9d6d2573c6add7cb28022b151"
|
||||
namespace TestOutput
|
||||
{
|
||||
#line 1 "Imports.cshtml"
|
||||
|
|
@ -16,6 +16,24 @@ using Foo = System.Text.Encoding
|
|||
#line 3 "Imports.cshtml"
|
||||
using System
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
;
|
||||
#line 5 "Imports.cshtml"
|
||||
using static System
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
;
|
||||
#line 6 "Imports.cshtml"
|
||||
using static System.Console
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
;
|
||||
#line 7 "Imports.cshtml"
|
||||
using static global::System.Text.Encoding
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
;
|
||||
|
|
@ -31,27 +49,30 @@ using System
|
|||
#pragma warning disable 1998
|
||||
public override async Task ExecuteAsync()
|
||||
{
|
||||
Instrumentation.BeginContext(68, 30, true);
|
||||
Instrumentation.BeginContext(68, 2, true);
|
||||
WriteLiteral("\r\n");
|
||||
Instrumentation.EndContext();
|
||||
Instrumentation.BeginContext(166, 30, true);
|
||||
WriteLiteral("\r\n<p>Path\'s full type name is ");
|
||||
Instrumentation.EndContext();
|
||||
Instrumentation.BeginContext(99, 21, false);
|
||||
#line 5 "Imports.cshtml"
|
||||
Instrumentation.BeginContext(197, 21, false);
|
||||
#line 9 "Imports.cshtml"
|
||||
Write(typeof(Path).FullName);
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
Instrumentation.EndContext();
|
||||
Instrumentation.BeginContext(120, 40, true);
|
||||
Instrumentation.BeginContext(218, 40, true);
|
||||
WriteLiteral("</p>\r\n<p>Foo\'s actual full type name is ");
|
||||
Instrumentation.EndContext();
|
||||
Instrumentation.BeginContext(161, 20, false);
|
||||
#line 6 "Imports.cshtml"
|
||||
Instrumentation.BeginContext(259, 20, false);
|
||||
#line 10 "Imports.cshtml"
|
||||
Write(typeof(Foo).FullName);
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
Instrumentation.EndContext();
|
||||
Instrumentation.BeginContext(181, 4, true);
|
||||
Instrumentation.BeginContext(279, 4, true);
|
||||
WriteLiteral("</p>");
|
||||
Instrumentation.EndContext();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,5 +2,9 @@
|
|||
@using Foo = System.Text.Encoding
|
||||
@using System
|
||||
|
||||
@using static System
|
||||
@using static System.Console
|
||||
@using static global::System.Text.Encoding
|
||||
|
||||
<p>Path's full type name is @typeof(Path).FullName</p>
|
||||
<p>Foo's actual full type name is @typeof(Foo).FullName</p>
|
||||
Loading…
Reference in New Issue