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
|
// using ( ==> Using Statement
|
||||||
UsingStatement(block);
|
UsingStatement(block);
|
||||||
}
|
}
|
||||||
else if (At(CSharpSymbolType.Identifier))
|
else if (At(CSharpSymbolType.Identifier) || At(CSharpKeyword.Static))
|
||||||
{
|
{
|
||||||
// using Identifier ==> Using Declaration
|
// using Identifier ==> Using Declaration
|
||||||
if (!topLevel)
|
if (!topLevel)
|
||||||
|
|
@ -126,31 +126,40 @@ namespace Microsoft.AspNet.Razor.Parser
|
||||||
// Set block type to directive
|
// Set block type to directive
|
||||||
Context.CurrentBlock.Type = BlockType.Directive;
|
Context.CurrentBlock.Type = BlockType.Directive;
|
||||||
|
|
||||||
// Parse a type name
|
if (At(CSharpSymbolType.Identifier))
|
||||||
Assert(CSharpSymbolType.Identifier);
|
|
||||||
NamespaceOrTypeName();
|
|
||||||
IEnumerable<CSharpSymbol> ws = ReadWhile(IsSpacingToken(includeNewLines: true, includeComments: true));
|
|
||||||
if (At(CSharpSymbolType.Assign))
|
|
||||||
{
|
{
|
||||||
// Alias
|
// non-static using
|
||||||
Accept(ws);
|
|
||||||
Assert(CSharpSymbolType.Assign);
|
|
||||||
AcceptAndMoveNext();
|
|
||||||
|
|
||||||
AcceptWhile(IsSpacingToken(includeNewLines: true, includeComments: true));
|
|
||||||
|
|
||||||
// One more namespace or type name
|
|
||||||
NamespaceOrTypeName();
|
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();
|
// static using
|
||||||
PutBack(ws);
|
AcceptAndMoveNext();
|
||||||
|
AcceptWhile(IsSpacingToken(includeNewLines: false, includeComments: true));
|
||||||
|
NamespaceOrTypeName();
|
||||||
}
|
}
|
||||||
|
|
||||||
Span.EditHandler.AcceptedCharacters = AcceptedCharacters.AnyExceptNewline;
|
Span.EditHandler.AcceptedCharacters = AcceptedCharacters.AnyExceptNewline;
|
||||||
Span.CodeGenerator = new AddImportCodeGenerator(
|
Span.CodeGenerator = new AddImportCodeGenerator(
|
||||||
Span.GetContent(syms => syms.Skip(1)));
|
Span.GetContent(symbols => symbols.Skip(1)));
|
||||||
|
|
||||||
// Optional ";"
|
// Optional ";"
|
||||||
if (EnsureCurrent())
|
if (EnsureCurrent())
|
||||||
|
|
|
||||||
|
|
@ -176,8 +176,11 @@ namespace Microsoft.AspNet.Razor.Test.Generator
|
||||||
BuildLineMapping(1, 0, 1, 51, 3, 0, 15),
|
BuildLineMapping(1, 0, 1, 51, 3, 0, 15),
|
||||||
BuildLineMapping(19, 1, 1, 132, 9, 0, 32),
|
BuildLineMapping(19, 1, 1, 132, 9, 0, 32),
|
||||||
BuildLineMapping(54, 2, 1, 230, 15, 0, 12),
|
BuildLineMapping(54, 2, 1, 230, 15, 0, 12),
|
||||||
BuildLineMapping(99, 4, 772, 39, 29, 21),
|
BuildLineMapping(71, 4, 1, 308, 21, 0, 19),
|
||||||
BuildLineMapping(161, 5, 888, 44, 35, 20)
|
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.
|
// 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.
|
// 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.Generator;
|
||||||
using Microsoft.AspNet.Razor.Parser;
|
using Microsoft.AspNet.Razor.Parser;
|
||||||
using Microsoft.AspNet.Razor.Parser.SyntaxTree;
|
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]
|
[Fact]
|
||||||
public void UsingStatement()
|
public void UsingStatement()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,24 @@ using Foo = System.Text.Encoding
|
||||||
#line 3 "Imports.cshtml"
|
#line 3 "Imports.cshtml"
|
||||||
using System
|
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 default
|
||||||
#line hidden
|
#line hidden
|
||||||
;
|
;
|
||||||
|
|
@ -36,12 +54,12 @@ using System
|
||||||
#pragma warning disable 1998
|
#pragma warning disable 1998
|
||||||
public override async Task ExecuteAsync()
|
public override async Task ExecuteAsync()
|
||||||
{
|
{
|
||||||
#line 5 "Imports.cshtml"
|
#line 9 "Imports.cshtml"
|
||||||
__o = typeof(Path).FullName;
|
__o = typeof(Path).FullName;
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
#line 6 "Imports.cshtml"
|
#line 10 "Imports.cshtml"
|
||||||
__o = typeof(Foo).FullName;
|
__o = typeof(Foo).FullName;
|
||||||
|
|
||||||
#line default
|
#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
|
namespace TestOutput
|
||||||
{
|
{
|
||||||
#line 1 "Imports.cshtml"
|
#line 1 "Imports.cshtml"
|
||||||
|
|
@ -16,6 +16,24 @@ using Foo = System.Text.Encoding
|
||||||
#line 3 "Imports.cshtml"
|
#line 3 "Imports.cshtml"
|
||||||
using System
|
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 default
|
||||||
#line hidden
|
#line hidden
|
||||||
;
|
;
|
||||||
|
|
@ -31,27 +49,30 @@ using System
|
||||||
#pragma warning disable 1998
|
#pragma warning disable 1998
|
||||||
public override async Task ExecuteAsync()
|
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 ");
|
WriteLiteral("\r\n<p>Path\'s full type name is ");
|
||||||
Instrumentation.EndContext();
|
Instrumentation.EndContext();
|
||||||
Instrumentation.BeginContext(99, 21, false);
|
Instrumentation.BeginContext(197, 21, false);
|
||||||
#line 5 "Imports.cshtml"
|
#line 9 "Imports.cshtml"
|
||||||
Write(typeof(Path).FullName);
|
Write(typeof(Path).FullName);
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
Instrumentation.EndContext();
|
Instrumentation.EndContext();
|
||||||
Instrumentation.BeginContext(120, 40, true);
|
Instrumentation.BeginContext(218, 40, true);
|
||||||
WriteLiteral("</p>\r\n<p>Foo\'s actual full type name is ");
|
WriteLiteral("</p>\r\n<p>Foo\'s actual full type name is ");
|
||||||
Instrumentation.EndContext();
|
Instrumentation.EndContext();
|
||||||
Instrumentation.BeginContext(161, 20, false);
|
Instrumentation.BeginContext(259, 20, false);
|
||||||
#line 6 "Imports.cshtml"
|
#line 10 "Imports.cshtml"
|
||||||
Write(typeof(Foo).FullName);
|
Write(typeof(Foo).FullName);
|
||||||
|
|
||||||
#line default
|
#line default
|
||||||
#line hidden
|
#line hidden
|
||||||
Instrumentation.EndContext();
|
Instrumentation.EndContext();
|
||||||
Instrumentation.BeginContext(181, 4, true);
|
Instrumentation.BeginContext(279, 4, true);
|
||||||
WriteLiteral("</p>");
|
WriteLiteral("</p>");
|
||||||
Instrumentation.EndContext();
|
Instrumentation.EndContext();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,5 +2,9 @@
|
||||||
@using Foo = System.Text.Encoding
|
@using Foo = System.Text.Encoding
|
||||||
@using System
|
@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>Path's full type name is @typeof(Path).FullName</p>
|
||||||
<p>Foo's actual full type name is @typeof(Foo).FullName</p>
|
<p>Foo's actual full type name is @typeof(Foo).FullName</p>
|
||||||
Loading…
Reference in New Issue