Merge branch 'master' into merge/release/2.2-to-master
This commit is contained in:
commit
631e557b2d
|
|
@ -12,7 +12,7 @@ os:
|
|||
osx_image: xcode8.2
|
||||
branches:
|
||||
only:
|
||||
- dev
|
||||
- master
|
||||
- /^release\/.*$/
|
||||
- /^(.*\/)?ci-.*$/
|
||||
before_install:
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ resources:
|
|||
- repository: buildtools
|
||||
type: git
|
||||
name: aspnet-BuildTools
|
||||
ref: refs/heads/release/2.2
|
||||
ref: refs/heads/master
|
||||
|
||||
phases:
|
||||
- template: .vsts-pipelines/templates/project-ci.yml@buildtools
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
Contributing
|
||||
======
|
||||
|
||||
Information on contributing to this repo is in the [Contributing Guide](https://github.com/aspnet/Home/blob/dev/CONTRIBUTING.md) in the Home repo.
|
||||
Information on contributing to this repo is in the [Contributing Guide](https://github.com/aspnet/Home/blob/master/CONTRIBUTING.md) in the Home repo.
|
||||
|
|
|
|||
|
|
@ -4,20 +4,20 @@
|
|||
</PropertyGroup>
|
||||
<PropertyGroup Label="Package Versions">
|
||||
<BenchmarkDotNetPackageVersion>0.10.13</BenchmarkDotNetPackageVersion>
|
||||
<InternalAspNetCoreSdkPackageVersion>2.2.0-preview1-20180807.2</InternalAspNetCoreSdkPackageVersion>
|
||||
<MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>2.2.0-preview1-34967</MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>
|
||||
<MicrosoftAspNetCoreHtmlAbstractionsPackageVersion>2.2.0-preview1-34967</MicrosoftAspNetCoreHtmlAbstractionsPackageVersion>
|
||||
<MicrosoftAspNetCoreTestingPackageVersion>2.2.0-preview1-34967</MicrosoftAspNetCoreTestingPackageVersion>
|
||||
<InternalAspNetCoreSdkPackageVersion>3.0.0-alpha1-20180810.1</InternalAspNetCoreSdkPackageVersion>
|
||||
<MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>3.0.0-alpha1-10275</MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>
|
||||
<MicrosoftAspNetCoreHtmlAbstractionsPackageVersion>3.0.0-alpha1-10275</MicrosoftAspNetCoreHtmlAbstractionsPackageVersion>
|
||||
<MicrosoftAspNetCoreTestingPackageVersion>3.0.0-alpha1-10275</MicrosoftAspNetCoreTestingPackageVersion>
|
||||
<MicrosoftBuildFrameworkPackageVersion>15.6.82</MicrosoftBuildFrameworkPackageVersion>
|
||||
<MicrosoftBuildPackageVersion>15.6.82</MicrosoftBuildPackageVersion>
|
||||
<MicrosoftBuildUtilitiesCorePackageVersion>15.6.82</MicrosoftBuildUtilitiesCorePackageVersion>
|
||||
<MicrosoftCodeAnalysisCommonPackageVersion>2.8.0</MicrosoftCodeAnalysisCommonPackageVersion>
|
||||
<MicrosoftCodeAnalysisCSharpPackageVersion>2.8.0</MicrosoftCodeAnalysisCSharpPackageVersion>
|
||||
<MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>2.2.0-preview1-34967</MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>
|
||||
<MicrosoftExtensionsCopyOnWriteDictionarySourcesPackageVersion>2.2.0-preview1-34967</MicrosoftExtensionsCopyOnWriteDictionarySourcesPackageVersion>
|
||||
<MicrosoftExtensionsDependencyModelPackageVersion>2.1.0</MicrosoftExtensionsDependencyModelPackageVersion>
|
||||
<MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion>2.2.0-preview1-34967</MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion>
|
||||
<MicrosoftExtensionsWebEncodersPackageVersion>2.2.0-preview1-34967</MicrosoftExtensionsWebEncodersPackageVersion>
|
||||
<MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>3.0.0-alpha1-10275</MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>
|
||||
<MicrosoftExtensionsCopyOnWriteDictionarySourcesPackageVersion>3.0.0-alpha1-10275</MicrosoftExtensionsCopyOnWriteDictionarySourcesPackageVersion>
|
||||
<MicrosoftExtensionsDependencyModelPackageVersion>3.0.0-preview1-26810-02</MicrosoftExtensionsDependencyModelPackageVersion>
|
||||
<MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion>3.0.0-alpha1-10275</MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion>
|
||||
<MicrosoftExtensionsWebEncodersPackageVersion>3.0.0-alpha1-10275</MicrosoftExtensionsWebEncodersPackageVersion>
|
||||
<MicrosoftNETCoreApp20PackageVersion>2.0.9</MicrosoftNETCoreApp20PackageVersion>
|
||||
<MicrosoftNETCoreApp21PackageVersion>2.1.2</MicrosoftNETCoreApp21PackageVersion>
|
||||
<MicrosoftNETCoreApp22PackageVersion>2.2.0-preview1-26618-02</MicrosoftNETCoreApp22PackageVersion>
|
||||
|
|
@ -25,6 +25,7 @@
|
|||
<MicrosoftVisualStudioComponentModelHostPackageVersion>15.0.26606</MicrosoftVisualStudioComponentModelHostPackageVersion>
|
||||
<MicrosoftVisualStudioEditorPackageVersion>15.6.161-preview</MicrosoftVisualStudioEditorPackageVersion>
|
||||
<MicrosoftVisualStudioLanguageIntellisensePackageVersion>15.6.161-preview</MicrosoftVisualStudioLanguageIntellisensePackageVersion>
|
||||
<MicrosoftVisualStudioLanguagePackageVersion>15.8.519</MicrosoftVisualStudioLanguagePackageVersion>
|
||||
<MicrosoftVisualStudioOLEInteropPackageVersion>7.10.6070</MicrosoftVisualStudioOLEInteropPackageVersion>
|
||||
<MicrosoftVisualStudioProjectSystemAnalyzersPackageVersion>15.3.224</MicrosoftVisualStudioProjectSystemAnalyzersPackageVersion>
|
||||
<MicrosoftVisualStudioProjectSystemManagedVSPackageVersion>2.0.6142705</MicrosoftVisualStudioProjectSystemManagedVSPackageVersion>
|
||||
|
|
@ -42,10 +43,10 @@
|
|||
<MoqPackageVersion>4.7.49</MoqPackageVersion>
|
||||
<NETStandardLibrary20PackageVersion>2.0.3</NETStandardLibrary20PackageVersion>
|
||||
<NewtonsoftJsonPackageVersion>11.0.2</NewtonsoftJsonPackageVersion>
|
||||
<StreamJsonRpcPackageVersion>1.1.92</StreamJsonRpcPackageVersion>
|
||||
<SystemDiagnosticsDiagnosticSourcePackageVersion>4.5.0</SystemDiagnosticsDiagnosticSourcePackageVersion>
|
||||
<StreamJsonRpcPackageVersion>1.3.23</StreamJsonRpcPackageVersion>
|
||||
<SystemDiagnosticsDiagnosticSourcePackageVersion>4.6.0-preview1-26807-04</SystemDiagnosticsDiagnosticSourcePackageVersion>
|
||||
<SystemRuntimeInteropServicesRuntimeInformationPackageVersion>4.3.0</SystemRuntimeInteropServicesRuntimeInformationPackageVersion>
|
||||
<SystemValueTuplePackageVersion>4.5.0</SystemValueTuplePackageVersion>
|
||||
<SystemValueTuplePackageVersion>4.6.0-preview1-26807-04</SystemValueTuplePackageVersion>
|
||||
<VisualStudio_NewtonsoftJsonPackageVersion>9.0.1</VisualStudio_NewtonsoftJsonPackageVersion>
|
||||
<VSIX_MicrosoftCodeAnalysisCommonPackageVersion>2.9.0-beta4-62911-02</VSIX_MicrosoftCodeAnalysisCommonPackageVersion>
|
||||
<VSIX_MicrosoftCodeAnalysisCSharpFeaturesPackageVersion>2.9.0-beta4-62911-02</VSIX_MicrosoftCodeAnalysisCSharpFeaturesPackageVersion>
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@
|
|||
<PropertyGroup>
|
||||
<!-- These properties are use by the automation that updates dependencies.props -->
|
||||
<LineupPackageId>Internal.AspNetCore.Universe.Lineup</LineupPackageId>
|
||||
<LineupPackageVersion>2.2.0-*</LineupPackageVersion>
|
||||
<LineupPackageRestoreSource>https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json</LineupPackageRestoreSource>
|
||||
</PropertyGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
version:2.2.0-preview1-20180807.2
|
||||
commithash:11495dbd236104434e08cb1152fcb58cf2a20923
|
||||
version:3.0.0-alpha1-20180810.1
|
||||
commithash:45c32b4f020e14a9295be31866051a18d293309d
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/release/2.2/tools/korebuild.schema.json",
|
||||
"channel": "release/2.2",
|
||||
"$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/master/tools/korebuild.schema.json",
|
||||
"channel": "master",
|
||||
"toolsets": {
|
||||
"visualstudio": {
|
||||
"required": false,
|
||||
|
|
|
|||
6
run.ps1
6
run.ps1
|
|
@ -52,8 +52,8 @@ in the file are overridden by command line parameters.
|
|||
Example config file:
|
||||
```json
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json",
|
||||
"channel": "dev",
|
||||
"$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/master/tools/korebuild.schema.json",
|
||||
"channel": "master",
|
||||
"toolsSource": "https://aspnetcore.blob.core.windows.net/buildtools"
|
||||
}
|
||||
```
|
||||
|
|
@ -192,7 +192,7 @@ if (!$DotNetHome) {
|
|||
else { Join-Path $PSScriptRoot '.dotnet'}
|
||||
}
|
||||
|
||||
if (!$Channel) { $Channel = 'dev' }
|
||||
if (!$Channel) { $Channel = 'master' }
|
||||
if (!$ToolsSource) { $ToolsSource = 'https://aspnetcore.blob.core.windows.net/buildtools' }
|
||||
|
||||
# Execute
|
||||
|
|
|
|||
2
run.sh
2
run.sh
|
|
@ -248,7 +248,7 @@ if [ -f "$config_file" ]; then
|
|||
[ ! -z "${config_tools_source:-}" ] && tools_source="$config_tools_source"
|
||||
fi
|
||||
|
||||
[ -z "$channel" ] && channel='dev'
|
||||
[ -z "$channel" ] && channel='master'
|
||||
[ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools'
|
||||
|
||||
get_korebuild
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||
{
|
||||
|
|
@ -33,6 +35,15 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
|
||||
public CSharpKeyword? Keyword { get; set; }
|
||||
|
||||
protected override SyntaxToken GetSyntaxToken()
|
||||
{
|
||||
switch (Type)
|
||||
{
|
||||
default:
|
||||
return SyntaxFactory.UnknownToken(Content, Errors.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var other = obj as CSharpToken;
|
||||
|
|
|
|||
|
|
@ -856,7 +856,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
// Capture whitespace
|
||||
var whitespace = ReadWhile(token => token.Type == HtmlTokenType.WhiteSpace || token.Type == HtmlTokenType.NewLine);
|
||||
|
||||
if (At(HtmlTokenType.Transition))
|
||||
if (At(HtmlTokenType.Transition) || At(HtmlTokenType.RazorCommentTransition))
|
||||
{
|
||||
// Transition outside of attribute value => Switch to recovery mode
|
||||
Accept(whitespace);
|
||||
|
|
@ -931,7 +931,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
{
|
||||
// First, determine if this is a 'data-' attribute (since those can't use conditional attributes)
|
||||
var name = string.Concat(nameTokens.Select(s => s.Content));
|
||||
var attributeCanBeConditional =
|
||||
var attributeCanBeConditional =
|
||||
Context.FeatureFlags.EXPERIMENTAL_AllowConditionalDataDashAttributes ||
|
||||
!name.StartsWith("data-", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
|
|
@ -1590,6 +1590,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
{
|
||||
Span.Start = CurrentLocation;
|
||||
|
||||
ParserState = ParserState.Misc;
|
||||
NextToken();
|
||||
while (!EndOfFile)
|
||||
{
|
||||
|
|
@ -1636,7 +1637,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
return;
|
||||
}
|
||||
|
||||
Output(SpanKindInternal.Markup);
|
||||
if (ParserState == ParserState.Content)
|
||||
{
|
||||
Output(SpanKindInternal.Markup, SyntaxKind.HtmlText);
|
||||
}
|
||||
else
|
||||
{
|
||||
Output(SpanKindInternal.Markup);
|
||||
}
|
||||
|
||||
// Start tag block
|
||||
var tagBlock = Context.Builder.StartBlock(BlockKindInternal.Tag);
|
||||
|
|
@ -1645,6 +1653,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
|
||||
if (!At(HtmlTokenType.ForwardSlash))
|
||||
{
|
||||
ParserState = ParserState.StartTag;
|
||||
OptionalBangEscape();
|
||||
|
||||
// Parsing a start tag
|
||||
|
|
@ -1655,6 +1664,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
Optional(HtmlTokenType.ForwardSlash);
|
||||
Optional(HtmlTokenType.CloseAngle);
|
||||
|
||||
ParserState = ParserState.Content;
|
||||
|
||||
// If the script tag expects javascript content then we should do minimal parsing until we reach
|
||||
// the end script tag. Don't want to incorrectly parse a "var tag = '<input />';" as an HTML tag.
|
||||
if (scriptTag && !CurrentScriptTagExpectsHtml())
|
||||
|
|
@ -1670,6 +1681,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
{
|
||||
// Parsing an end tag
|
||||
// This section can accept things like: '</p >' or '</p>' etc.
|
||||
ParserState = ParserState.EndTag;
|
||||
Optional(HtmlTokenType.ForwardSlash);
|
||||
|
||||
// Whitespace here is invalid (according to the spec)
|
||||
|
|
@ -1677,6 +1689,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
Optional(HtmlTokenType.Text);
|
||||
Optional(HtmlTokenType.WhiteSpace);
|
||||
Optional(HtmlTokenType.CloseAngle);
|
||||
ParserState = ParserState.Content;
|
||||
}
|
||||
|
||||
Output(SpanKindInternal.Markup);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||
{
|
||||
|
|
@ -30,5 +32,46 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
throw new ArgumentNullException(nameof(content));
|
||||
}
|
||||
}
|
||||
|
||||
protected override SyntaxToken GetSyntaxToken()
|
||||
{
|
||||
switch (Type)
|
||||
{
|
||||
case HtmlTokenType.Text:
|
||||
return SyntaxFactory.HtmlTextToken(Content, Errors.ToArray());
|
||||
case HtmlTokenType.WhiteSpace:
|
||||
return SyntaxFactory.WhitespaceToken(Content, Errors.ToArray());
|
||||
case HtmlTokenType.NewLine:
|
||||
return SyntaxFactory.NewLineToken(Content, Errors.ToArray());
|
||||
case HtmlTokenType.OpenAngle:
|
||||
return SyntaxFactory.Punctuation(SyntaxKind.OpenAngle, Content, Errors.ToArray());
|
||||
case HtmlTokenType.Bang:
|
||||
return SyntaxFactory.Punctuation(SyntaxKind.Bang, Content, Errors.ToArray());
|
||||
case HtmlTokenType.ForwardSlash:
|
||||
return SyntaxFactory.Punctuation(SyntaxKind.ForwardSlash, Content, Errors.ToArray());
|
||||
case HtmlTokenType.QuestionMark:
|
||||
return SyntaxFactory.Punctuation(SyntaxKind.QuestionMark, Content, Errors.ToArray());
|
||||
case HtmlTokenType.DoubleHyphen:
|
||||
return SyntaxFactory.Punctuation(SyntaxKind.DoubleHyphen, Content, Errors.ToArray());
|
||||
case HtmlTokenType.LeftBracket:
|
||||
return SyntaxFactory.Punctuation(SyntaxKind.LeftBracket, Content, Errors.ToArray());
|
||||
case HtmlTokenType.CloseAngle:
|
||||
return SyntaxFactory.Punctuation(SyntaxKind.CloseAngle, Content, Errors.ToArray());
|
||||
case HtmlTokenType.RightBracket:
|
||||
return SyntaxFactory.Punctuation(SyntaxKind.RightBracket, Content, Errors.ToArray());
|
||||
case HtmlTokenType.Equals:
|
||||
return SyntaxFactory.Punctuation(SyntaxKind.Equals, Content, Errors.ToArray());
|
||||
case HtmlTokenType.DoubleQuote:
|
||||
return SyntaxFactory.Punctuation(SyntaxKind.DoubleQuote, Content, Errors.ToArray());
|
||||
case HtmlTokenType.SingleQuote:
|
||||
return SyntaxFactory.Punctuation(SyntaxKind.SingleQuote, Content, Errors.ToArray());
|
||||
case HtmlTokenType.Transition:
|
||||
return SyntaxFactory.Punctuation(SyntaxKind.Transition, Content, Errors.ToArray());
|
||||
case HtmlTokenType.Colon:
|
||||
return SyntaxFactory.Punctuation(SyntaxKind.Colon, Content, Errors.ToArray());
|
||||
default:
|
||||
return SyntaxFactory.UnknownToken(Content, Errors.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
// 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 Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||
{
|
||||
internal interface IToken
|
||||
|
|
@ -10,5 +12,9 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
string Content { get; }
|
||||
|
||||
SourceLocation Start { get; }
|
||||
|
||||
SyntaxKind SyntaxKind { get; }
|
||||
|
||||
SyntaxToken SyntaxToken { get; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||
{
|
||||
|
|
@ -31,6 +32,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
|
||||
public SpanEditHandler EditHandler { get; private set; }
|
||||
|
||||
public HtmlNodeSyntax SyntaxNode { get; private set; }
|
||||
|
||||
public override bool IsBlock => false;
|
||||
|
||||
public override int Length
|
||||
|
|
@ -94,6 +97,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
{
|
||||
Kind = builder.Kind;
|
||||
Tokens = builder.Tokens;
|
||||
SyntaxNode = builder.SyntaxNode;
|
||||
|
||||
for (var i = 0; i <Tokens.Count; i++)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,7 +3,9 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||
{
|
||||
|
|
@ -33,6 +35,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
Start = location;
|
||||
}
|
||||
|
||||
public HtmlNodeSyntax SyntaxNode { get; private set; }
|
||||
|
||||
public ISpanChunkGenerator ChunkGenerator { get; set; }
|
||||
|
||||
public SourceLocation Start
|
||||
|
|
@ -76,8 +80,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
Start = SourceLocation.Undefined;
|
||||
}
|
||||
|
||||
public Span Build()
|
||||
public Span Build(SyntaxKind syntaxKind = SyntaxKind.Unknown)
|
||||
{
|
||||
SyntaxNode = GetSyntaxNode(syntaxKind);
|
||||
|
||||
var span = new Span(this);
|
||||
|
||||
for (var i = 0; i < span.Tokens.Count; i++)
|
||||
|
|
@ -109,5 +115,27 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
_tokens.Add(token);
|
||||
_tracker.UpdateLocation(token.Content);
|
||||
}
|
||||
|
||||
private HtmlNodeSyntax GetSyntaxNode(SyntaxKind syntaxKind)
|
||||
{
|
||||
if (syntaxKind == SyntaxKind.HtmlText)
|
||||
{
|
||||
var textTokens = new SyntaxListBuilder<SyntaxToken>(SyntaxListBuilder.Create());
|
||||
foreach (var token in Tokens)
|
||||
{
|
||||
if (token.SyntaxKind == SyntaxKind.Unknown)
|
||||
{
|
||||
Debug.Assert(false, $"Unexpected html token {((HtmlToken)token).Type}");
|
||||
continue;
|
||||
}
|
||||
|
||||
textTokens.Add(token.SyntaxToken);
|
||||
}
|
||||
var textResult = textTokens.ToList();
|
||||
return SyntaxFactory.HtmlText(new SyntaxList<SyntaxToken>(textResult.Node));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax;
|
||||
using Microsoft.Extensions.Internal;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||
|
|
@ -58,10 +59,15 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
}
|
||||
}
|
||||
|
||||
public SyntaxKind SyntaxKind => SyntaxToken.Kind;
|
||||
|
||||
public SyntaxToken SyntaxToken => GetSyntaxToken();
|
||||
|
||||
protected abstract SyntaxToken GetSyntaxToken();
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var other = obj as TokenBase<TType>;
|
||||
return other != null &&
|
||||
return obj is TokenBase<TType> other &&
|
||||
string.Equals(Content, other.Content, StringComparison.Ordinal) &&
|
||||
Type.Equals(other.Type);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||
{
|
||||
|
|
@ -25,6 +26,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
Span = new SpanBuilder(CurrentLocation);
|
||||
}
|
||||
|
||||
protected ParserState ParserState { get; set; }
|
||||
|
||||
protected SpanBuilder Span { get; private set; }
|
||||
|
||||
protected Action<SpanBuilder> SpanConfig { get; set; }
|
||||
|
|
@ -34,6 +37,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
get { return _tokenizer.Current; }
|
||||
}
|
||||
|
||||
protected SyntaxToken CurrentSyntaxToken => CurrentToken?.SyntaxToken;
|
||||
|
||||
protected TToken PreviousToken { get; private set; }
|
||||
|
||||
protected SourceLocation CurrentLocation => _tokenizer.Tokenizer.CurrentLocation;
|
||||
|
|
@ -388,31 +393,31 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
}
|
||||
}
|
||||
|
||||
protected internal void Output(SpanKindInternal kind)
|
||||
protected internal void Output(SpanKindInternal kind, SyntaxKind syntaxKind = SyntaxKind.Unknown)
|
||||
{
|
||||
Configure(kind, null);
|
||||
Output();
|
||||
Output(syntaxKind);
|
||||
}
|
||||
|
||||
protected internal void Output(SpanKindInternal kind, AcceptedCharactersInternal accepts)
|
||||
protected internal void Output(SpanKindInternal kind, AcceptedCharactersInternal accepts, SyntaxKind syntaxKind = SyntaxKind.Unknown)
|
||||
{
|
||||
Configure(kind, accepts);
|
||||
Output();
|
||||
Output(syntaxKind);
|
||||
}
|
||||
|
||||
protected internal void Output(AcceptedCharactersInternal accepts)
|
||||
protected internal void Output(AcceptedCharactersInternal accepts, SyntaxKind syntaxKind = SyntaxKind.Unknown)
|
||||
{
|
||||
Configure(null, accepts);
|
||||
Output();
|
||||
Output(syntaxKind);
|
||||
}
|
||||
|
||||
private void Output()
|
||||
private void Output(SyntaxKind syntaxKind)
|
||||
{
|
||||
if (Span.Tokens.Count > 0)
|
||||
{
|
||||
var nextStart = Span.End;
|
||||
|
||||
var builtSpan = Span.Build();
|
||||
var builtSpan = Span.Build(syntaxKind);
|
||||
Context.Builder.Add(builtSpan);
|
||||
Initialize(Span);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Razor.LanguageServer.StrongNamed, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Razor.Performance, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Razor.Extensions.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||
{
|
||||
internal struct ArrayElement<T>
|
||||
{
|
||||
public T Value;
|
||||
|
||||
public static implicit operator T(ArrayElement<T> element)
|
||||
{
|
||||
return element.Value;
|
||||
}
|
||||
|
||||
//NOTE: there is no opposite conversion operator T -> ArrayElement<T>
|
||||
//
|
||||
// that is because it is preferred to update array elements in-place
|
||||
// "elements[i].Value = v" results in much better code than "elements[i] = (ArrayElement<T>)v"
|
||||
//
|
||||
// The reason is that x86 ABI requires that structs must be returned in
|
||||
// a return buffer even if they can fit in a register like this one.
|
||||
// Also since struct contains a reference, the write to the buffer is done with a checked GC barrier
|
||||
// as JIT does not know if the write goes to a stack or a heap location.
|
||||
// Assigning to Value directly easily avoids all this redundancy.
|
||||
|
||||
public static ArrayElement<T>[] MakeElementArray(T[] items)
|
||||
{
|
||||
if (items == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var array = new ArrayElement<T>[items.Length];
|
||||
for (var i = 0; i < items.Length; i++)
|
||||
{
|
||||
array[i].Value = items[i];
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
public static T[] MakeArray(ArrayElement<T>[] items)
|
||||
{
|
||||
if (items == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var array = new T[items.Length];
|
||||
for (var i = 0; i < items.Length; i++)
|
||||
{
|
||||
array[i] = items[i].Value;
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,514 @@
|
|||
// 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 System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||
{
|
||||
internal abstract class GreenNode
|
||||
{
|
||||
private static readonly RazorDiagnostic[] EmptyDiagnostics = Array.Empty<RazorDiagnostic>();
|
||||
private static readonly SyntaxAnnotation[] EmptyAnnotations = Array.Empty<SyntaxAnnotation>();
|
||||
private static readonly ConditionalWeakTable<GreenNode, RazorDiagnostic[]> DiagnosticsTable =
|
||||
new ConditionalWeakTable<GreenNode, RazorDiagnostic[]>();
|
||||
private static readonly ConditionalWeakTable<GreenNode, SyntaxAnnotation[]> AnnotationsTable =
|
||||
new ConditionalWeakTable<GreenNode, SyntaxAnnotation[]>();
|
||||
|
||||
private NodeFlags _flags;
|
||||
private byte _slotCount;
|
||||
|
||||
protected GreenNode(SyntaxKind kind)
|
||||
{
|
||||
Kind = kind;
|
||||
}
|
||||
|
||||
protected GreenNode(SyntaxKind kind, int fullWidth)
|
||||
: this(kind)
|
||||
{
|
||||
FullWidth = fullWidth;
|
||||
}
|
||||
|
||||
protected GreenNode(SyntaxKind kind, RazorDiagnostic[] diagnostics, SyntaxAnnotation[] annotations)
|
||||
: this(kind, 0, diagnostics, annotations)
|
||||
{
|
||||
}
|
||||
|
||||
protected GreenNode(SyntaxKind kind, int fullWidth, RazorDiagnostic[] diagnostics, SyntaxAnnotation[] annotations)
|
||||
: this(kind, fullWidth)
|
||||
{
|
||||
if (diagnostics?.Length > 0)
|
||||
{
|
||||
_flags |= NodeFlags.ContainsDiagnostics;
|
||||
DiagnosticsTable.Add(this, diagnostics);
|
||||
}
|
||||
|
||||
if (annotations?.Length > 0)
|
||||
{
|
||||
foreach (var annotation in annotations)
|
||||
{
|
||||
if (annotation == null)
|
||||
{
|
||||
throw new ArgumentException(nameof(annotations), "Annotation cannot be null");
|
||||
}
|
||||
}
|
||||
|
||||
_flags |= NodeFlags.ContainsAnnotations;
|
||||
AnnotationsTable.Add(this, annotations);
|
||||
}
|
||||
}
|
||||
|
||||
protected void AdjustFlagsAndWidth(GreenNode node)
|
||||
{
|
||||
if (node == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_flags |= (node.Flags & NodeFlags.InheritMask);
|
||||
FullWidth += node.FullWidth;
|
||||
}
|
||||
|
||||
#region Kind
|
||||
internal SyntaxKind Kind { get; }
|
||||
|
||||
internal virtual bool IsList => false;
|
||||
|
||||
internal virtual bool IsToken => false;
|
||||
|
||||
internal virtual bool IsTrivia => false;
|
||||
#endregion
|
||||
|
||||
#region Slots
|
||||
public int SlotCount
|
||||
{
|
||||
get
|
||||
{
|
||||
int count = _slotCount;
|
||||
if (count == byte.MaxValue)
|
||||
{
|
||||
count = GetSlotCount();
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
protected set
|
||||
{
|
||||
_slotCount = (byte)value;
|
||||
}
|
||||
}
|
||||
|
||||
internal abstract GreenNode GetSlot(int index);
|
||||
|
||||
// for slot counts >= byte.MaxValue
|
||||
protected virtual int GetSlotCount()
|
||||
{
|
||||
return _slotCount;
|
||||
}
|
||||
|
||||
public virtual int GetSlotOffset(int index)
|
||||
{
|
||||
var offset = 0;
|
||||
for (var i = 0; i < index; i++)
|
||||
{
|
||||
var child = GetSlot(i);
|
||||
if (child != null)
|
||||
offset += child.FullWidth;
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
public virtual int FindSlotIndexContainingOffset(int offset)
|
||||
{
|
||||
Debug.Assert(0 <= offset && offset < FullWidth);
|
||||
|
||||
int i;
|
||||
var accumulatedWidth = 0;
|
||||
for (i = 0; ; i++)
|
||||
{
|
||||
Debug.Assert(i < SlotCount);
|
||||
var child = GetSlot(i);
|
||||
if (child != null)
|
||||
{
|
||||
accumulatedWidth += child.FullWidth;
|
||||
if (offset < accumulatedWidth)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Flags
|
||||
internal NodeFlags Flags => _flags;
|
||||
|
||||
internal void SetFlags(NodeFlags flags)
|
||||
{
|
||||
_flags |= flags;
|
||||
}
|
||||
|
||||
internal void ClearFlags(NodeFlags flags)
|
||||
{
|
||||
_flags &= ~flags;
|
||||
}
|
||||
|
||||
internal virtual bool IsMissing => (_flags & NodeFlags.IsMissing) != 0;
|
||||
|
||||
public bool ContainsDiagnostics
|
||||
{
|
||||
get
|
||||
{
|
||||
return (_flags & NodeFlags.ContainsDiagnostics) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
public bool ContainsAnnotations
|
||||
{
|
||||
get
|
||||
{
|
||||
return (_flags & NodeFlags.ContainsAnnotations) != 0;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Spans
|
||||
internal int FullWidth { get; private set; }
|
||||
|
||||
public virtual int Width
|
||||
{
|
||||
get
|
||||
{
|
||||
return FullWidth - GetLeadingTriviaWidth() - GetTrailingTriviaWidth();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual int GetLeadingTriviaWidth()
|
||||
{
|
||||
return FullWidth != 0 ? GetFirstTerminal().GetLeadingTriviaWidth() : 0;
|
||||
}
|
||||
|
||||
public virtual int GetTrailingTriviaWidth()
|
||||
{
|
||||
return FullWidth != 0 ? GetLastTerminal().GetTrailingTriviaWidth() : 0;
|
||||
}
|
||||
|
||||
public bool HasLeadingTrivia
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetLeadingTriviaWidth() != 0;
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasTrailingTrivia
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetTrailingTriviaWidth() != 0;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Diagnostics
|
||||
internal abstract GreenNode SetDiagnostics(RazorDiagnostic[] diagnostics);
|
||||
|
||||
internal RazorDiagnostic[] GetDiagnostics()
|
||||
{
|
||||
if (ContainsDiagnostics)
|
||||
{
|
||||
if (DiagnosticsTable.TryGetValue(this, out var diagnostics))
|
||||
{
|
||||
return diagnostics;
|
||||
}
|
||||
}
|
||||
|
||||
return EmptyDiagnostics;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Annotations
|
||||
internal abstract GreenNode SetAnnotations(SyntaxAnnotation[] annotations);
|
||||
|
||||
internal SyntaxAnnotation[] GetAnnotations()
|
||||
{
|
||||
if (ContainsAnnotations)
|
||||
{
|
||||
if (AnnotationsTable.TryGetValue(this, out var annotations))
|
||||
{
|
||||
Debug.Assert(annotations.Length != 0, "There cannot be an empty annotation entry.");
|
||||
return annotations;
|
||||
}
|
||||
}
|
||||
|
||||
return EmptyAnnotations;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Text
|
||||
public virtual string ToFullString()
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
var writer = new StringWriter(builder, System.Globalization.CultureInfo.InvariantCulture);
|
||||
WriteTo(writer);
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
public virtual void WriteTo(TextWriter writer)
|
||||
{
|
||||
WriteTo(writer, leading: true, trailing: true);
|
||||
}
|
||||
|
||||
protected internal void WriteTo(TextWriter writer, bool leading, bool trailing)
|
||||
{
|
||||
// Use an actual Stack so we can write out deeply recursive structures without overflowing.
|
||||
var stack = new Stack<StackEntry>();
|
||||
stack.Push(new StackEntry(this, leading, trailing));
|
||||
|
||||
// Separated out stack processing logic so that it does not unintentionally refer to
|
||||
// "this", "leading" or "trailing.
|
||||
ProcessStack(writer, stack);
|
||||
}
|
||||
|
||||
protected virtual void WriteTriviaTo(TextWriter writer)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected virtual void WriteTokenTo(TextWriter writer, bool leading, bool trailing)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Tokens
|
||||
|
||||
public virtual object GetValue()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public virtual string GetValueText()
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public virtual GreenNode GetLeadingTrivia()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public virtual GreenNode GetTrailingTrivia()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public virtual GreenNode WithLeadingTrivia(GreenNode trivia)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
public virtual GreenNode WithTrailingTrivia(GreenNode trivia)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
public InternalSyntax.SyntaxToken GetFirstToken()
|
||||
{
|
||||
return (InternalSyntax.SyntaxToken)GetFirstTerminal();
|
||||
}
|
||||
|
||||
public InternalSyntax.SyntaxToken GetLastToken()
|
||||
{
|
||||
return (InternalSyntax.SyntaxToken)GetLastTerminal();
|
||||
}
|
||||
|
||||
internal GreenNode GetFirstTerminal()
|
||||
{
|
||||
var node = this;
|
||||
|
||||
do
|
||||
{
|
||||
GreenNode firstChild = null;
|
||||
for (int i = 0, n = node.SlotCount; i < n; i++)
|
||||
{
|
||||
var child = node.GetSlot(i);
|
||||
if (child != null)
|
||||
{
|
||||
firstChild = child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
node = firstChild;
|
||||
} while (node?._slotCount > 0);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
internal GreenNode GetLastTerminal()
|
||||
{
|
||||
var node = this;
|
||||
|
||||
do
|
||||
{
|
||||
GreenNode lastChild = null;
|
||||
for (var i = node.SlotCount - 1; i >= 0; i--)
|
||||
{
|
||||
var child = node.GetSlot(i);
|
||||
if (child != null)
|
||||
{
|
||||
lastChild = child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
node = lastChild;
|
||||
} while (node?._slotCount > 0);
|
||||
|
||||
return node;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Factories
|
||||
public virtual GreenNode CreateList(IEnumerable<GreenNode> nodes, bool alwaysCreateListNode = false)
|
||||
{
|
||||
if (nodes == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var list = nodes.ToArray();
|
||||
|
||||
switch (list.Length)
|
||||
{
|
||||
case 0:
|
||||
return null;
|
||||
case 1:
|
||||
if (alwaysCreateListNode)
|
||||
{
|
||||
goto default;
|
||||
}
|
||||
else
|
||||
{
|
||||
return list[0];
|
||||
}
|
||||
case 2:
|
||||
return InternalSyntax.SyntaxList.List(list[0], list[1]);
|
||||
case 3:
|
||||
return InternalSyntax.SyntaxList.List(list[0], list[1], list[2]);
|
||||
default:
|
||||
return InternalSyntax.SyntaxList.List(list);
|
||||
}
|
||||
}
|
||||
|
||||
public SyntaxNode CreateRed()
|
||||
{
|
||||
return CreateRed(null, 0);
|
||||
}
|
||||
|
||||
internal abstract SyntaxNode CreateRed(SyntaxNode parent, int position);
|
||||
#endregion
|
||||
|
||||
internal virtual GreenNode Accept(InternalSyntax.SyntaxVisitor visitor)
|
||||
{
|
||||
return visitor.Visit(this);
|
||||
}
|
||||
|
||||
#region StaticMethods
|
||||
|
||||
private static void ProcessStack(TextWriter writer,
|
||||
Stack<StackEntry> stack)
|
||||
{
|
||||
while (stack.Count > 0)
|
||||
{
|
||||
var current = stack.Pop();
|
||||
var currentNode = current.Node;
|
||||
var currentLeading = current.Leading;
|
||||
var currentTrailing = current.Trailing;
|
||||
|
||||
if (currentNode.IsToken)
|
||||
{
|
||||
currentNode.WriteTokenTo(writer, currentLeading, currentTrailing);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (currentNode.IsTrivia)
|
||||
{
|
||||
currentNode.WriteTriviaTo(writer);
|
||||
continue;
|
||||
}
|
||||
|
||||
var firstIndex = GetFirstNonNullChildIndex(currentNode);
|
||||
var lastIndex = GetLastNonNullChildIndex(currentNode);
|
||||
|
||||
for (var i = lastIndex; i >= firstIndex; i--)
|
||||
{
|
||||
var child = currentNode.GetSlot(i);
|
||||
if (child != null)
|
||||
{
|
||||
var first = i == firstIndex;
|
||||
var last = i == lastIndex;
|
||||
stack.Push(new StackEntry(child, currentLeading | !first, currentTrailing | !last));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int GetFirstNonNullChildIndex(GreenNode node)
|
||||
{
|
||||
int n = node.SlotCount;
|
||||
int firstIndex = 0;
|
||||
for (; firstIndex < n; firstIndex++)
|
||||
{
|
||||
var child = node.GetSlot(firstIndex);
|
||||
if (child != null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return firstIndex;
|
||||
}
|
||||
|
||||
private static int GetLastNonNullChildIndex(GreenNode node)
|
||||
{
|
||||
int n = node.SlotCount;
|
||||
int lastIndex = n - 1;
|
||||
for (; lastIndex >= 0; lastIndex--)
|
||||
{
|
||||
var child = node.GetSlot(lastIndex);
|
||||
if (child != null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return lastIndex;
|
||||
}
|
||||
|
||||
private struct StackEntry
|
||||
{
|
||||
public StackEntry(GreenNode node, bool leading, bool trailing)
|
||||
{
|
||||
Node = node;
|
||||
Leading = leading;
|
||||
Trailing = trailing;
|
||||
}
|
||||
|
||||
public GreenNode Node { get; }
|
||||
|
||||
public bool Leading { get; }
|
||||
|
||||
public bool Trailing { get; }
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||
{
|
||||
internal abstract class HtmlNodeSyntax : SyntaxNode
|
||||
{
|
||||
internal HtmlNodeSyntax(GreenNode green, SyntaxNode parent, int position)
|
||||
: base(green, parent, position)
|
||||
{
|
||||
}
|
||||
|
||||
internal new InternalSyntax.HtmlNodeSyntax Green => (InternalSyntax.HtmlNodeSyntax)base.Green;
|
||||
|
||||
internal override SyntaxNode Accept(SyntaxVisitor visitor)
|
||||
{
|
||||
return visitor.VisitHtmlNode(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||
{
|
||||
internal class HtmlTextSyntax : HtmlNodeSyntax
|
||||
{
|
||||
private SyntaxNode _textTokens;
|
||||
|
||||
internal HtmlTextSyntax(GreenNode green, SyntaxNode parent, int position)
|
||||
: base(green, parent, position)
|
||||
{
|
||||
}
|
||||
|
||||
public SyntaxList<SyntaxNode> TextTokens => new SyntaxList<SyntaxNode>(GetRed(ref _textTokens, 0));
|
||||
|
||||
public string Value => TextTokens[0]?.ToFullString() ?? string.Empty;
|
||||
|
||||
internal override SyntaxNode Accept(SyntaxVisitor visitor)
|
||||
{
|
||||
return visitor.VisitHtmlText(this);
|
||||
}
|
||||
|
||||
internal override SyntaxNode GetCachedSlot(int index)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0: return _textTokens;
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
internal override SyntaxNode GetNodeSlot(int slot)
|
||||
{
|
||||
switch (slot)
|
||||
{
|
||||
case 0: return GetRed(ref _textTokens, 0);
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||
{
|
||||
internal class HtmlTextTokenSyntax : SyntaxToken
|
||||
{
|
||||
internal HtmlTextTokenSyntax(GreenNode green, SyntaxNode parent, int position)
|
||||
: base(green, parent, position)
|
||||
{
|
||||
}
|
||||
|
||||
internal new InternalSyntax.HtmlTextTokenSyntax Green => (InternalSyntax.HtmlTextTokenSyntax)base.Green;
|
||||
|
||||
public string Value => Text;
|
||||
|
||||
internal override SyntaxToken WithLeadingTriviaCore(SyntaxNode trivia)
|
||||
{
|
||||
return new InternalSyntax.HtmlTextTokenSyntax(Text, trivia?.Green, GetTrailingTrivia().Node?.Green).CreateRed(Parent, Position) as HtmlTextTokenSyntax;
|
||||
}
|
||||
|
||||
internal override SyntaxToken WithTrailingTriviaCore(SyntaxNode trivia)
|
||||
{
|
||||
return new InternalSyntax.HtmlTextTokenSyntax(Text, GetLeadingTrivia().Node?.Green, trivia?.Green).CreateRed(Parent, Position) as HtmlTextTokenSyntax;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax
|
||||
{
|
||||
internal abstract class HtmlNodeSyntax : GreenNode
|
||||
{
|
||||
protected HtmlNodeSyntax(SyntaxKind kind)
|
||||
: base(kind)
|
||||
{
|
||||
}
|
||||
|
||||
protected HtmlNodeSyntax(SyntaxKind kind, int fullWidth)
|
||||
: base(kind, fullWidth)
|
||||
{
|
||||
}
|
||||
|
||||
protected HtmlNodeSyntax(SyntaxKind kind, RazorDiagnostic[] diagnostics, SyntaxAnnotation[] annotations)
|
||||
: base(kind, diagnostics, annotations)
|
||||
{
|
||||
}
|
||||
|
||||
internal override GreenNode Accept(SyntaxVisitor visitor)
|
||||
{
|
||||
return visitor.VisitHtmlNode(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
// 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;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax
|
||||
{
|
||||
internal class HtmlTextSyntax : HtmlNodeSyntax
|
||||
{
|
||||
private readonly GreenNode _value;
|
||||
|
||||
internal HtmlTextSyntax(GreenNode value) : base(SyntaxKind.HtmlText)
|
||||
{
|
||||
SlotCount = 1;
|
||||
_value = value;
|
||||
AdjustFlagsAndWidth(value);
|
||||
}
|
||||
|
||||
internal HtmlTextSyntax(GreenNode value, RazorDiagnostic[] diagnostics, SyntaxAnnotation[] annotations)
|
||||
: base(SyntaxKind.HtmlText, diagnostics, annotations)
|
||||
{
|
||||
SlotCount = 1;
|
||||
_value = value;
|
||||
AdjustFlagsAndWidth(value);
|
||||
}
|
||||
|
||||
internal SyntaxList<GreenNode> TextTokens => new SyntaxList<GreenNode>(_value);
|
||||
|
||||
internal override GreenNode GetSlot(int index)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0: return _value;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
internal override GreenNode Accept(SyntaxVisitor visitor)
|
||||
{
|
||||
return visitor.VisitHtmlText(this);
|
||||
}
|
||||
|
||||
internal override SyntaxNode CreateRed(SyntaxNode parent, int position)
|
||||
{
|
||||
return new Syntax.HtmlTextSyntax(this, parent, position);
|
||||
}
|
||||
|
||||
internal override GreenNode SetDiagnostics(RazorDiagnostic[] diagnostics)
|
||||
{
|
||||
return new HtmlTextSyntax(_value, diagnostics, GetAnnotations());
|
||||
}
|
||||
|
||||
internal override GreenNode SetAnnotations(SyntaxAnnotation[] annotations)
|
||||
{
|
||||
return new HtmlTextSyntax(_value, GetDiagnostics(), annotations);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax
|
||||
{
|
||||
internal class HtmlTextTokenSyntax : SyntaxToken
|
||||
{
|
||||
internal HtmlTextTokenSyntax(string text, params RazorDiagnostic[] diagnostics)
|
||||
: base(SyntaxKind.HtmlTextLiteralToken, text, null, null, diagnostics, null)
|
||||
{
|
||||
}
|
||||
|
||||
internal HtmlTextTokenSyntax(string text, GreenNode leadingTrivia, GreenNode trailingTrivia)
|
||||
: base(SyntaxKind.HtmlTextLiteralToken, text, leadingTrivia, trailingTrivia)
|
||||
{
|
||||
}
|
||||
|
||||
protected HtmlTextTokenSyntax(SyntaxKind kind, string name, GreenNode leadingTrivia, GreenNode trailingTrivia)
|
||||
: base(kind, name, leadingTrivia, trailingTrivia)
|
||||
{
|
||||
}
|
||||
|
||||
protected HtmlTextTokenSyntax(SyntaxKind kind, string name, GreenNode leadingTrivia, GreenNode trailingTrivia, RazorDiagnostic[] diagnostics, SyntaxAnnotation[] annotations)
|
||||
: base(kind, name, leadingTrivia, trailingTrivia, diagnostics, annotations)
|
||||
{
|
||||
}
|
||||
|
||||
internal override SyntaxNode CreateRed(SyntaxNode parent, int position)
|
||||
{
|
||||
return new Syntax.HtmlTextTokenSyntax(this, parent, position);
|
||||
}
|
||||
|
||||
public override SyntaxToken TokenWithLeadingTrivia(GreenNode trivia)
|
||||
{
|
||||
return new HtmlTextTokenSyntax(Kind, Text, trivia, TrailingTrivia);
|
||||
}
|
||||
|
||||
public override SyntaxToken TokenWithTrailingTrivia(GreenNode trivia)
|
||||
{
|
||||
return new HtmlTextTokenSyntax(Kind, Text, LeadingTrivia, trivia);
|
||||
}
|
||||
|
||||
internal override GreenNode SetDiagnostics(RazorDiagnostic[] diagnostics)
|
||||
{
|
||||
return new HtmlTextTokenSyntax(Kind, Text, LeadingTrivia, TrailingTrivia, diagnostics, GetAnnotations());
|
||||
}
|
||||
|
||||
internal override GreenNode SetAnnotations(SyntaxAnnotation[] annotations)
|
||||
{
|
||||
return new HtmlTextTokenSyntax(Kind, Text, LeadingTrivia, TrailingTrivia, GetDiagnostics(), annotations);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax
|
||||
{
|
||||
internal class NewLineTokenSyntax : SyntaxToken
|
||||
{
|
||||
internal NewLineTokenSyntax(string text, params RazorDiagnostic[] diagnostics)
|
||||
: base(SyntaxKind.NewLine, text, null, null, diagnostics, null)
|
||||
{
|
||||
}
|
||||
|
||||
internal NewLineTokenSyntax(string text, GreenNode leadingTrivia, GreenNode trailingTrivia)
|
||||
: base(SyntaxKind.NewLine, text, leadingTrivia, trailingTrivia)
|
||||
{
|
||||
}
|
||||
|
||||
protected NewLineTokenSyntax(SyntaxKind kind, string name, GreenNode leadingTrivia, GreenNode trailingTrivia)
|
||||
: base(kind, name, leadingTrivia, trailingTrivia)
|
||||
{
|
||||
}
|
||||
|
||||
protected NewLineTokenSyntax(SyntaxKind kind, string name, GreenNode leadingTrivia, GreenNode trailingTrivia, RazorDiagnostic[] diagnostics, SyntaxAnnotation[] annotations)
|
||||
: base(kind, name, leadingTrivia, trailingTrivia, diagnostics, annotations)
|
||||
{
|
||||
}
|
||||
|
||||
internal override SyntaxNode CreateRed(SyntaxNode parent, int position) => new Syntax.NewLineTokenSyntax(this, parent, position);
|
||||
|
||||
public override SyntaxToken TokenWithLeadingTrivia(GreenNode trivia)
|
||||
{
|
||||
return new NewLineTokenSyntax(Kind, Text, trivia, TrailingTrivia);
|
||||
}
|
||||
|
||||
public override SyntaxToken TokenWithTrailingTrivia(GreenNode trivia)
|
||||
{
|
||||
return new NewLineTokenSyntax(Kind, Text, LeadingTrivia, trivia);
|
||||
}
|
||||
|
||||
internal override GreenNode SetDiagnostics(RazorDiagnostic[] diagnostics)
|
||||
{
|
||||
return new NewLineTokenSyntax(Kind, Text, LeadingTrivia, TrailingTrivia, diagnostics, GetAnnotations());
|
||||
}
|
||||
|
||||
internal override GreenNode SetAnnotations(SyntaxAnnotation[] annotations)
|
||||
{
|
||||
return new NewLineTokenSyntax(Kind, Text, LeadingTrivia, TrailingTrivia, GetDiagnostics(), annotations);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax
|
||||
{
|
||||
internal class PunctuationSyntax : SyntaxToken
|
||||
{
|
||||
internal PunctuationSyntax(SyntaxKind kind, string name, RazorDiagnostic[] diagnostics)
|
||||
: this(kind, name, null, null, diagnostics, null)
|
||||
{
|
||||
}
|
||||
|
||||
internal PunctuationSyntax(SyntaxKind kind, string name, GreenNode leadingTrivia, GreenNode trailingTrivia)
|
||||
: this(kind, name, leadingTrivia, trailingTrivia, null, null)
|
||||
{
|
||||
}
|
||||
|
||||
internal PunctuationSyntax(SyntaxKind kind, string name, GreenNode leadingTrivia, GreenNode trailingTrivia, RazorDiagnostic[] diagnostics, SyntaxAnnotation[] annotations)
|
||||
: base(kind, name, leadingTrivia, trailingTrivia, diagnostics, annotations)
|
||||
{
|
||||
}
|
||||
|
||||
internal override SyntaxNode CreateRed(SyntaxNode parent, int position) => new Syntax.PunctuationSyntax(this, parent, position);
|
||||
|
||||
public override SyntaxToken TokenWithLeadingTrivia(GreenNode trivia)
|
||||
{
|
||||
return new PunctuationSyntax(Kind, Text, trivia, TrailingTrivia);
|
||||
}
|
||||
|
||||
public override SyntaxToken TokenWithTrailingTrivia(GreenNode trivia)
|
||||
{
|
||||
return new PunctuationSyntax(Kind, Text, LeadingTrivia, trivia);
|
||||
}
|
||||
|
||||
internal override GreenNode SetDiagnostics(RazorDiagnostic[] diagnostics)
|
||||
{
|
||||
return new PunctuationSyntax(Kind, Text, LeadingTrivia, TrailingTrivia, diagnostics, GetAnnotations());
|
||||
}
|
||||
|
||||
internal override GreenNode SetAnnotations(SyntaxAnnotation[] annotations)
|
||||
{
|
||||
return new PunctuationSyntax(Kind, Text, LeadingTrivia, TrailingTrivia, GetDiagnostics(), annotations);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax
|
||||
{
|
||||
internal static class SyntaxFactory
|
||||
{
|
||||
internal static HtmlTextSyntax HtmlText(SyntaxList<SyntaxToken> textTokens)
|
||||
{
|
||||
return new HtmlTextSyntax(textTokens.Node);
|
||||
}
|
||||
|
||||
internal static HtmlTextTokenSyntax HtmlTextToken(string text, params RazorDiagnostic[] diagnostics)
|
||||
{
|
||||
return new HtmlTextTokenSyntax(text, diagnostics);
|
||||
}
|
||||
|
||||
internal static WhitespaceTokenSyntax WhitespaceToken(string text, params RazorDiagnostic[] diagnostics)
|
||||
{
|
||||
return new WhitespaceTokenSyntax(text, diagnostics);
|
||||
}
|
||||
|
||||
internal static NewLineTokenSyntax NewLineToken(string text, params RazorDiagnostic[] diagnostics)
|
||||
{
|
||||
return new NewLineTokenSyntax(text, diagnostics);
|
||||
}
|
||||
|
||||
internal static PunctuationSyntax Punctuation(SyntaxKind syntaxKind, string text, params RazorDiagnostic[] diagnostics)
|
||||
{
|
||||
return new PunctuationSyntax(syntaxKind, text, diagnostics);
|
||||
}
|
||||
|
||||
internal static UnknownTokenSyntax UnknownToken(string text, params RazorDiagnostic[] diagnostics)
|
||||
{
|
||||
return new UnknownTokenSyntax(text, diagnostics);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,418 @@
|
|||
// 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 System.Diagnostics;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax
|
||||
{
|
||||
internal abstract class SyntaxList : GreenNode
|
||||
{
|
||||
internal SyntaxList()
|
||||
: base(SyntaxKind.List)
|
||||
{
|
||||
}
|
||||
|
||||
internal SyntaxList(RazorDiagnostic[] diagnostics, SyntaxAnnotation[] annotations)
|
||||
: base(SyntaxKind.List, diagnostics, annotations)
|
||||
{
|
||||
}
|
||||
|
||||
internal override bool IsList => true;
|
||||
|
||||
internal static GreenNode List(GreenNode child)
|
||||
{
|
||||
return child;
|
||||
}
|
||||
|
||||
internal static WithTwoChildren List(GreenNode child0, GreenNode child1)
|
||||
{
|
||||
Debug.Assert(child0 != null);
|
||||
Debug.Assert(child1 != null);
|
||||
|
||||
var result = new WithTwoChildren(child0, child1);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static WithThreeChildren List(GreenNode child0, GreenNode child1, GreenNode child2)
|
||||
{
|
||||
Debug.Assert(child0 != null);
|
||||
Debug.Assert(child1 != null);
|
||||
Debug.Assert(child2 != null);
|
||||
|
||||
var result = new WithThreeChildren(child0, child1, child2);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static GreenNode List(GreenNode[] nodes)
|
||||
{
|
||||
return List(nodes, nodes.Length);
|
||||
}
|
||||
|
||||
internal static GreenNode List(GreenNode[] nodes, int count)
|
||||
{
|
||||
var array = new ArrayElement<GreenNode>[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
Debug.Assert(nodes[i] != null);
|
||||
array[i].Value = nodes[i];
|
||||
}
|
||||
|
||||
return List(array);
|
||||
}
|
||||
|
||||
internal static SyntaxList List(ArrayElement<GreenNode>[] children)
|
||||
{
|
||||
// "WithLotsOfChildren" list will allocate a separate array to hold
|
||||
// precomputed node offsets. It may not be worth it for smallish lists.
|
||||
if (children.Length < 10)
|
||||
{
|
||||
return new WithManyChildren(children);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new WithLotsOfChildren(children);
|
||||
}
|
||||
}
|
||||
|
||||
internal abstract void CopyTo(ArrayElement<GreenNode>[] array, int offset);
|
||||
|
||||
internal static GreenNode Concat(GreenNode left, GreenNode right)
|
||||
{
|
||||
if (left == null)
|
||||
{
|
||||
return right;
|
||||
}
|
||||
|
||||
if (right == null)
|
||||
{
|
||||
return left;
|
||||
}
|
||||
|
||||
var leftList = left as SyntaxList;
|
||||
var rightList = right as SyntaxList;
|
||||
if (leftList != null)
|
||||
{
|
||||
if (rightList != null)
|
||||
{
|
||||
var tmp = new ArrayElement<GreenNode>[left.SlotCount + right.SlotCount];
|
||||
leftList.CopyTo(tmp, 0);
|
||||
rightList.CopyTo(tmp, left.SlotCount);
|
||||
return List(tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
var tmp = new ArrayElement<GreenNode>[left.SlotCount + 1];
|
||||
leftList.CopyTo(tmp, 0);
|
||||
tmp[left.SlotCount].Value = right;
|
||||
return List(tmp);
|
||||
}
|
||||
}
|
||||
else if (rightList != null)
|
||||
{
|
||||
var tmp = new ArrayElement<GreenNode>[rightList.SlotCount + 1];
|
||||
tmp[0].Value = left;
|
||||
rightList.CopyTo(tmp, 1);
|
||||
return List(tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
return List(left, right);
|
||||
}
|
||||
}
|
||||
|
||||
internal class WithTwoChildren : SyntaxList
|
||||
{
|
||||
private readonly GreenNode _child0;
|
||||
private readonly GreenNode _child1;
|
||||
|
||||
internal WithTwoChildren(GreenNode child0, GreenNode child1)
|
||||
{
|
||||
SlotCount = 2;
|
||||
AdjustFlagsAndWidth(child0);
|
||||
_child0 = child0;
|
||||
AdjustFlagsAndWidth(child1);
|
||||
_child1 = child1;
|
||||
}
|
||||
|
||||
internal WithTwoChildren(RazorDiagnostic[] diagnostics, SyntaxAnnotation[] annotations, GreenNode child0, GreenNode child1)
|
||||
{
|
||||
SlotCount = 2;
|
||||
AdjustFlagsAndWidth(child0);
|
||||
_child0 = child0;
|
||||
AdjustFlagsAndWidth(child1);
|
||||
_child1 = child1;
|
||||
}
|
||||
|
||||
internal override GreenNode GetSlot(int index)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
return _child0;
|
||||
case 1:
|
||||
return _child1;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
internal override void CopyTo(ArrayElement<GreenNode>[] array, int offset)
|
||||
{
|
||||
array[offset].Value = _child0;
|
||||
array[offset + 1].Value = _child1;
|
||||
}
|
||||
|
||||
internal override SyntaxNode CreateRed(SyntaxNode parent, int position)
|
||||
{
|
||||
return new Syntax.SyntaxList.WithTwoChildren(this, parent, position);
|
||||
}
|
||||
|
||||
internal override GreenNode SetDiagnostics(RazorDiagnostic[] errors)
|
||||
{
|
||||
return new WithTwoChildren(errors, this.GetAnnotations(), _child0, _child1);
|
||||
}
|
||||
|
||||
internal override GreenNode SetAnnotations(SyntaxAnnotation[] annotations)
|
||||
{
|
||||
return new WithTwoChildren(GetDiagnostics(), annotations, _child0, _child1);
|
||||
}
|
||||
}
|
||||
|
||||
internal class WithThreeChildren : SyntaxList
|
||||
{
|
||||
private readonly GreenNode _child0;
|
||||
private readonly GreenNode _child1;
|
||||
private readonly GreenNode _child2;
|
||||
|
||||
internal WithThreeChildren(GreenNode child0, GreenNode child1, GreenNode child2)
|
||||
{
|
||||
SlotCount = 3;
|
||||
AdjustFlagsAndWidth(child0);
|
||||
_child0 = child0;
|
||||
AdjustFlagsAndWidth(child1);
|
||||
_child1 = child1;
|
||||
AdjustFlagsAndWidth(child2);
|
||||
_child2 = child2;
|
||||
}
|
||||
|
||||
internal WithThreeChildren(RazorDiagnostic[] diagnostics, SyntaxAnnotation[] annotations, GreenNode child0, GreenNode child1, GreenNode child2)
|
||||
: base(diagnostics, annotations)
|
||||
{
|
||||
SlotCount = 3;
|
||||
AdjustFlagsAndWidth(child0);
|
||||
_child0 = child0;
|
||||
AdjustFlagsAndWidth(child1);
|
||||
_child1 = child1;
|
||||
AdjustFlagsAndWidth(child2);
|
||||
_child2 = child2;
|
||||
}
|
||||
|
||||
internal override GreenNode GetSlot(int index)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
return _child0;
|
||||
case 1:
|
||||
return _child1;
|
||||
case 2:
|
||||
return _child2;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
internal override void CopyTo(ArrayElement<GreenNode>[] array, int offset)
|
||||
{
|
||||
array[offset].Value = _child0;
|
||||
array[offset + 1].Value = _child1;
|
||||
array[offset + 2].Value = _child2;
|
||||
}
|
||||
|
||||
internal override SyntaxNode CreateRed(SyntaxNode parent, int position)
|
||||
{
|
||||
return new Syntax.SyntaxList.WithThreeChildren(this, parent, position);
|
||||
}
|
||||
|
||||
internal override GreenNode SetDiagnostics(RazorDiagnostic[] errors)
|
||||
{
|
||||
return new WithThreeChildren(errors, GetAnnotations(), _child0, _child1, _child2);
|
||||
}
|
||||
|
||||
internal override GreenNode SetAnnotations(SyntaxAnnotation[] annotations)
|
||||
{
|
||||
return new WithThreeChildren(GetDiagnostics(), annotations, _child0, _child1, _child2);
|
||||
}
|
||||
}
|
||||
|
||||
internal abstract class WithManyChildrenBase : SyntaxList
|
||||
{
|
||||
internal readonly ArrayElement<GreenNode>[] children;
|
||||
|
||||
internal WithManyChildrenBase(ArrayElement<GreenNode>[] children)
|
||||
{
|
||||
this.children = children;
|
||||
this.InitializeChildren();
|
||||
}
|
||||
|
||||
internal WithManyChildrenBase(RazorDiagnostic[] diagnostics, SyntaxAnnotation[] annotations, ArrayElement<GreenNode>[] children)
|
||||
: base(diagnostics, annotations)
|
||||
{
|
||||
this.children = children;
|
||||
this.InitializeChildren();
|
||||
}
|
||||
|
||||
private void InitializeChildren()
|
||||
{
|
||||
var n = children.Length;
|
||||
if (n < byte.MaxValue)
|
||||
{
|
||||
SlotCount = (byte)n;
|
||||
}
|
||||
else
|
||||
{
|
||||
SlotCount = byte.MaxValue;
|
||||
}
|
||||
|
||||
for (var i = 0; i < children.Length; i++)
|
||||
{
|
||||
AdjustFlagsAndWidth(children[i]);
|
||||
}
|
||||
}
|
||||
|
||||
protected override int GetSlotCount()
|
||||
{
|
||||
return children.Length;
|
||||
}
|
||||
|
||||
internal override GreenNode GetSlot(int index)
|
||||
{
|
||||
return children[index];
|
||||
}
|
||||
|
||||
internal override void CopyTo(ArrayElement<GreenNode>[] array, int offset)
|
||||
{
|
||||
Array.Copy(children, 0, array, offset, children.Length);
|
||||
}
|
||||
|
||||
internal override SyntaxNode CreateRed(SyntaxNode parent, int position)
|
||||
{
|
||||
return new Syntax.SyntaxList.WithManyChildren(this, parent, position);
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class WithManyChildren : WithManyChildrenBase
|
||||
{
|
||||
internal WithManyChildren(ArrayElement<GreenNode>[] children)
|
||||
: base(children)
|
||||
{
|
||||
}
|
||||
|
||||
internal WithManyChildren(RazorDiagnostic[] diagnostics, SyntaxAnnotation[] annotations, ArrayElement<GreenNode>[] children)
|
||||
: base(diagnostics, annotations, children)
|
||||
{
|
||||
}
|
||||
|
||||
internal override GreenNode SetDiagnostics(RazorDiagnostic[] errors)
|
||||
{
|
||||
return new WithManyChildren(errors, GetAnnotations(), children);
|
||||
}
|
||||
|
||||
internal override GreenNode SetAnnotations(SyntaxAnnotation[] annotations)
|
||||
{
|
||||
return new WithManyChildren(GetDiagnostics(), annotations, children);
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class WithLotsOfChildren : WithManyChildrenBase
|
||||
{
|
||||
private readonly int[] _childOffsets;
|
||||
|
||||
internal WithLotsOfChildren(ArrayElement<GreenNode>[] children)
|
||||
: base(children)
|
||||
{
|
||||
_childOffsets = CalculateOffsets(children);
|
||||
}
|
||||
|
||||
internal WithLotsOfChildren(RazorDiagnostic[] diagnostics, SyntaxAnnotation[] annotations, ArrayElement<GreenNode>[] children, int[] childOffsets)
|
||||
: base(diagnostics, annotations, children)
|
||||
{
|
||||
_childOffsets = childOffsets;
|
||||
}
|
||||
|
||||
public override int GetSlotOffset(int index)
|
||||
{
|
||||
return _childOffsets[index];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find the slot that contains the given offset.
|
||||
/// </summary>
|
||||
/// <param name="offset">The target offset. Must be between 0 and <see cref="GreenNode.FullWidth"/>.</param>
|
||||
/// <returns>The slot index of the slot containing the given offset.</returns>
|
||||
/// <remarks>
|
||||
/// This implementation uses a binary search to find the first slot that contains
|
||||
/// the given offset.
|
||||
/// </remarks>
|
||||
public override int FindSlotIndexContainingOffset(int offset)
|
||||
{
|
||||
Debug.Assert(offset >= 0 && offset < FullWidth);
|
||||
return BinarySearchUpperBound(_childOffsets, offset) - 1;
|
||||
}
|
||||
|
||||
private static int[] CalculateOffsets(ArrayElement<GreenNode>[] children)
|
||||
{
|
||||
var n = children.Length;
|
||||
var childOffsets = new int[n];
|
||||
var offset = 0;
|
||||
for (var i = 0; i < n; i++)
|
||||
{
|
||||
childOffsets[i] = offset;
|
||||
offset += children[i].Value.FullWidth;
|
||||
}
|
||||
return childOffsets;
|
||||
}
|
||||
|
||||
internal override GreenNode SetDiagnostics(RazorDiagnostic[] errors)
|
||||
{
|
||||
return new WithLotsOfChildren(errors, this.GetAnnotations(), children, _childOffsets);
|
||||
}
|
||||
|
||||
internal override GreenNode SetAnnotations(SyntaxAnnotation[] annotations)
|
||||
{
|
||||
return new WithLotsOfChildren(GetDiagnostics(), annotations, children, _childOffsets);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Search a sorted integer array for the target value in O(log N) time.
|
||||
/// </summary>
|
||||
/// <param name="array">The array of integers which must be sorted in ascending order.</param>
|
||||
/// <param name="value">The target value.</param>
|
||||
/// <returns>An index in the array pointing to the position where <paramref name="value"/> should be
|
||||
/// inserted in order to maintain the sorted order. All values to the right of this position will be
|
||||
/// strictly greater than <paramref name="value"/>. Note that this may return a position off the end
|
||||
/// of the array if all elements are less than or equal to <paramref name="value"/>.</returns>
|
||||
private static int BinarySearchUpperBound(int[] array, int value)
|
||||
{
|
||||
var low = 0;
|
||||
var high = array.Length - 1;
|
||||
|
||||
while (low <= high)
|
||||
{
|
||||
var middle = low + ((high - low) >> 1);
|
||||
if (array[middle] > value)
|
||||
{
|
||||
high = middle - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
low = middle + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return low;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,201 @@
|
|||
// 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 System.Diagnostics;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax
|
||||
{
|
||||
internal class SyntaxListBuilder
|
||||
{
|
||||
private ArrayElement<GreenNode>[] _nodes;
|
||||
|
||||
public int Count { get; private set; }
|
||||
|
||||
public SyntaxListBuilder(int size)
|
||||
{
|
||||
_nodes = new ArrayElement<GreenNode>[size];
|
||||
}
|
||||
|
||||
public static SyntaxListBuilder Create()
|
||||
{
|
||||
return new SyntaxListBuilder(8);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
Count = 0;
|
||||
}
|
||||
|
||||
public GreenNode this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
return _nodes[index];
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_nodes[index].Value = value;
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(GreenNode item)
|
||||
{
|
||||
if (item == null) return;
|
||||
|
||||
if (item.IsList)
|
||||
{
|
||||
var slotCount = item.SlotCount;
|
||||
|
||||
// Necessary, but not sufficient (e.g. for nested lists).
|
||||
EnsureAdditionalCapacity(slotCount);
|
||||
|
||||
for (var i = 0; i < slotCount; i++)
|
||||
{
|
||||
Add(item.GetSlot(i));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EnsureAdditionalCapacity(1);
|
||||
|
||||
_nodes[Count++].Value = item;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddRange(GreenNode[] items)
|
||||
{
|
||||
AddRange(items, 0, items.Length);
|
||||
}
|
||||
|
||||
public void AddRange(GreenNode[] items, int offset, int length)
|
||||
{
|
||||
// Necessary, but not sufficient (e.g. for nested lists).
|
||||
EnsureAdditionalCapacity(length - offset);
|
||||
|
||||
var oldCount = Count;
|
||||
|
||||
for (var i = offset; i < length; i++)
|
||||
{
|
||||
Add(items[i]);
|
||||
}
|
||||
|
||||
Validate(oldCount, Count);
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
private void Validate(int start, int end)
|
||||
{
|
||||
for (var i = start; i < end; i++)
|
||||
{
|
||||
Debug.Assert(_nodes[i].Value != null);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddRange(SyntaxList<GreenNode> list)
|
||||
{
|
||||
this.AddRange(list, 0, list.Count);
|
||||
}
|
||||
|
||||
public void AddRange(SyntaxList<GreenNode> list, int offset, int length)
|
||||
{
|
||||
// Necessary, but not sufficient (e.g. for nested lists).
|
||||
EnsureAdditionalCapacity(length - offset);
|
||||
|
||||
var oldCount = Count;
|
||||
|
||||
for (var i = offset; i < length; i++)
|
||||
{
|
||||
Add(list[i]);
|
||||
}
|
||||
|
||||
Validate(oldCount, Count);
|
||||
}
|
||||
|
||||
public void AddRange<TNode>(SyntaxList<TNode> list) where TNode : GreenNode
|
||||
{
|
||||
this.AddRange(list, 0, list.Count);
|
||||
}
|
||||
|
||||
public void AddRange<TNode>(SyntaxList<TNode> list, int offset, int length) where TNode : GreenNode
|
||||
{
|
||||
AddRange(new SyntaxList<GreenNode>(list.Node), offset, length);
|
||||
}
|
||||
|
||||
public void RemoveLast()
|
||||
{
|
||||
Count--;
|
||||
_nodes[Count].Value = null;
|
||||
}
|
||||
|
||||
private void EnsureAdditionalCapacity(int additionalCount)
|
||||
{
|
||||
var currentSize = _nodes.Length;
|
||||
var requiredSize = Count + additionalCount;
|
||||
|
||||
if (requiredSize <= currentSize) return;
|
||||
|
||||
var newSize =
|
||||
requiredSize < 8 ? 8 :
|
||||
requiredSize >= (int.MaxValue / 2) ? int.MaxValue :
|
||||
Math.Max(requiredSize, currentSize * 2); // NB: Size will *at least* double.
|
||||
Debug.Assert(newSize >= requiredSize);
|
||||
|
||||
Array.Resize(ref _nodes, newSize);
|
||||
}
|
||||
|
||||
public bool Any(SyntaxKind kind)
|
||||
{
|
||||
for (var i = 0; i < Count; i++)
|
||||
{
|
||||
if (_nodes[i].Value.Kind == kind)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public GreenNode[] ToArray()
|
||||
{
|
||||
var array = new GreenNode[Count];
|
||||
for (var i = 0; i < array.Length; i++)
|
||||
{
|
||||
array[i] = _nodes[i];
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
internal GreenNode ToListNode()
|
||||
{
|
||||
switch (Count)
|
||||
{
|
||||
case 0:
|
||||
return null;
|
||||
case 1:
|
||||
return _nodes[0];
|
||||
case 2:
|
||||
return SyntaxList.List(_nodes[0], _nodes[1]);
|
||||
case 3:
|
||||
return SyntaxList.List(_nodes[0], _nodes[1], _nodes[2]);
|
||||
default:
|
||||
var tmp = new ArrayElement<GreenNode>[Count];
|
||||
Array.Copy(_nodes, tmp, Count);
|
||||
return SyntaxList.List(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
public SyntaxList<GreenNode> ToList()
|
||||
{
|
||||
return new SyntaxList<GreenNode>(ToListNode());
|
||||
}
|
||||
|
||||
public SyntaxList<TNode> ToList<TNode>() where TNode : GreenNode
|
||||
{
|
||||
return new SyntaxList<TNode>(ToListNode());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax
|
||||
{
|
||||
internal readonly struct SyntaxListBuilder<TNode> where TNode : GreenNode
|
||||
{
|
||||
private readonly SyntaxListBuilder _builder;
|
||||
|
||||
public SyntaxListBuilder(int size)
|
||||
: this(new SyntaxListBuilder(size))
|
||||
{
|
||||
}
|
||||
|
||||
public static SyntaxListBuilder<TNode> Create()
|
||||
{
|
||||
return new SyntaxListBuilder<TNode>(8);
|
||||
}
|
||||
|
||||
internal SyntaxListBuilder(SyntaxListBuilder builder)
|
||||
{
|
||||
_builder = builder;
|
||||
}
|
||||
|
||||
public bool IsNull
|
||||
{
|
||||
get
|
||||
{
|
||||
return _builder == null;
|
||||
}
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return _builder.Count;
|
||||
}
|
||||
}
|
||||
|
||||
public TNode this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
return (TNode)_builder[index];
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_builder[index] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_builder.Clear();
|
||||
}
|
||||
|
||||
public SyntaxListBuilder<TNode> Add(TNode node)
|
||||
{
|
||||
_builder.Add(node);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void AddRange(TNode[] items, int offset, int length)
|
||||
{
|
||||
_builder.AddRange(items, offset, length);
|
||||
}
|
||||
|
||||
public void AddRange(SyntaxList<TNode> nodes)
|
||||
{
|
||||
_builder.AddRange(nodes);
|
||||
}
|
||||
|
||||
public void AddRange(SyntaxList<TNode> nodes, int offset, int length)
|
||||
{
|
||||
_builder.AddRange(nodes, offset, length);
|
||||
}
|
||||
|
||||
public bool Any(SyntaxKind kind)
|
||||
{
|
||||
return _builder.Any(kind);
|
||||
}
|
||||
|
||||
public SyntaxList<TNode> ToList()
|
||||
{
|
||||
return _builder.ToList<TNode>();
|
||||
}
|
||||
|
||||
public GreenNode ToListNode()
|
||||
{
|
||||
return _builder.ToListNode();
|
||||
}
|
||||
|
||||
public static implicit operator SyntaxListBuilder(SyntaxListBuilder<TNode> builder)
|
||||
{
|
||||
return builder._builder;
|
||||
}
|
||||
|
||||
public static implicit operator SyntaxList<TNode>(SyntaxListBuilder<TNode> builder)
|
||||
{
|
||||
if (builder._builder != null)
|
||||
{
|
||||
return builder.ToList();
|
||||
}
|
||||
|
||||
return default(SyntaxList<TNode>);
|
||||
}
|
||||
|
||||
public SyntaxList<TDerived> ToList<TDerived>() where TDerived : GreenNode
|
||||
{
|
||||
return new SyntaxList<TDerived>(ToListNode());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
// 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.Diagnostics;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax
|
||||
{
|
||||
internal readonly struct SyntaxList<TNode>
|
||||
where TNode : GreenNode
|
||||
{
|
||||
private readonly GreenNode _node;
|
||||
|
||||
public SyntaxList(GreenNode node)
|
||||
{
|
||||
_node = node;
|
||||
}
|
||||
|
||||
public GreenNode Node
|
||||
{
|
||||
get
|
||||
{
|
||||
return ((GreenNode)_node);
|
||||
}
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return (_node == null) ? 0 : _node.IsList ? _node.SlotCount : 1;
|
||||
}
|
||||
}
|
||||
|
||||
public TNode Last
|
||||
{
|
||||
get
|
||||
{
|
||||
var node = _node;
|
||||
if (node.IsList)
|
||||
{
|
||||
return ((TNode)node.GetSlot(node.SlotCount - 1));
|
||||
}
|
||||
|
||||
return ((TNode)node);
|
||||
}
|
||||
}
|
||||
|
||||
/* Not Implemented: Default */
|
||||
public TNode this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
var node = _node;
|
||||
if (node.IsList)
|
||||
{
|
||||
return ((TNode)node.GetSlot(index));
|
||||
}
|
||||
|
||||
Debug.Assert(index == 0);
|
||||
return ((TNode)node);
|
||||
}
|
||||
}
|
||||
|
||||
public GreenNode ItemUntyped(int index)
|
||||
{
|
||||
var node = _node;
|
||||
if (node.IsList)
|
||||
{
|
||||
return node.GetSlot(index);
|
||||
}
|
||||
|
||||
Debug.Assert(index == 0);
|
||||
return node;
|
||||
}
|
||||
|
||||
public bool Any()
|
||||
{
|
||||
return _node != null;
|
||||
}
|
||||
|
||||
public bool Any(SyntaxKind kind)
|
||||
{
|
||||
for (var i = 0; i < Count; i++)
|
||||
{
|
||||
var element = ItemUntyped(i);
|
||||
if ((element.Kind == kind))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public TNode[] Nodes
|
||||
{
|
||||
get
|
||||
{
|
||||
var arr = new TNode[Count];
|
||||
for (var i = 0; i < Count; i++)
|
||||
{
|
||||
arr[i] = this[i];
|
||||
}
|
||||
|
||||
return arr;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool operator ==(SyntaxList<TNode> left, SyntaxList<TNode> right)
|
||||
{
|
||||
return (left._node == right._node);
|
||||
}
|
||||
|
||||
public static bool operator !=(SyntaxList<TNode> left, SyntaxList<TNode> right)
|
||||
{
|
||||
return !(left._node == right._node);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return (obj is SyntaxList<TNode> && (_node == ((SyntaxList<TNode>)obj)._node));
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return _node != null ? _node.GetHashCode() : 0;
|
||||
}
|
||||
|
||||
public static implicit operator SyntaxList<TNode>(TNode node)
|
||||
{
|
||||
return new SyntaxList<TNode>(node);
|
||||
}
|
||||
|
||||
public static implicit operator SyntaxList<GreenNode>(SyntaxList<TNode> nodes)
|
||||
{
|
||||
return new SyntaxList<GreenNode>(nodes._node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
// 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 System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax
|
||||
{
|
||||
internal abstract class SyntaxToken : GreenNode
|
||||
{
|
||||
internal SyntaxToken(SyntaxKind tokenKind, string text, GreenNode leadingTrivia, GreenNode trailingTrivia)
|
||||
: base(tokenKind, text.Length)
|
||||
{
|
||||
Text = text;
|
||||
LeadingTrivia = leadingTrivia;
|
||||
AdjustFlagsAndWidth(leadingTrivia);
|
||||
TrailingTrivia = trailingTrivia;
|
||||
AdjustFlagsAndWidth(trailingTrivia);
|
||||
}
|
||||
|
||||
internal SyntaxToken(SyntaxKind tokenKind, string text, GreenNode leadingTrivia, GreenNode trailingTrivia, RazorDiagnostic[] diagnostics, SyntaxAnnotation[] annotations)
|
||||
: base(tokenKind, text.Length, diagnostics, annotations)
|
||||
{
|
||||
Text = text;
|
||||
LeadingTrivia = leadingTrivia;
|
||||
AdjustFlagsAndWidth(leadingTrivia);
|
||||
TrailingTrivia = trailingTrivia;
|
||||
AdjustFlagsAndWidth(trailingTrivia);
|
||||
}
|
||||
|
||||
public string Text { get; }
|
||||
|
||||
public GreenNode LeadingTrivia { get; }
|
||||
|
||||
public GreenNode TrailingTrivia { get; }
|
||||
|
||||
internal override bool IsToken => true;
|
||||
|
||||
public override int Width => Text.Length;
|
||||
|
||||
protected override void WriteTokenTo(TextWriter writer, bool leading, bool trailing)
|
||||
{
|
||||
if (leading)
|
||||
{
|
||||
var trivia = GetLeadingTrivia();
|
||||
if (trivia != null)
|
||||
{
|
||||
trivia.WriteTo(writer, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
writer.Write(Text);
|
||||
|
||||
if (trailing)
|
||||
{
|
||||
var trivia = GetTrailingTrivia();
|
||||
if (trivia != null)
|
||||
{
|
||||
trivia.WriteTo(writer, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override sealed GreenNode GetLeadingTrivia()
|
||||
{
|
||||
return LeadingTrivia;
|
||||
}
|
||||
|
||||
public override int GetLeadingTriviaWidth()
|
||||
{
|
||||
return LeadingTrivia == null ? 0 : LeadingTrivia.FullWidth;
|
||||
}
|
||||
|
||||
public override sealed GreenNode GetTrailingTrivia()
|
||||
{
|
||||
return TrailingTrivia;
|
||||
}
|
||||
|
||||
public override int GetTrailingTriviaWidth()
|
||||
{
|
||||
return TrailingTrivia == null ? 0 : TrailingTrivia.FullWidth;
|
||||
}
|
||||
|
||||
public sealed override GreenNode WithLeadingTrivia(GreenNode trivia)
|
||||
{
|
||||
return TokenWithLeadingTrivia(trivia);
|
||||
}
|
||||
|
||||
public abstract SyntaxToken TokenWithLeadingTrivia(GreenNode trivia);
|
||||
|
||||
public sealed override GreenNode WithTrailingTrivia(GreenNode trivia)
|
||||
{
|
||||
return TokenWithTrailingTrivia(trivia);
|
||||
}
|
||||
|
||||
public abstract SyntaxToken TokenWithTrailingTrivia(GreenNode trivia);
|
||||
|
||||
protected override sealed int GetSlotCount()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal override sealed GreenNode GetSlot(int index)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
internal override GreenNode Accept(SyntaxVisitor visitor)
|
||||
{
|
||||
return visitor.VisitSyntaxToken(this);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Text;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
// 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 System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax
|
||||
{
|
||||
internal class SyntaxTrivia : GreenNode
|
||||
{
|
||||
internal SyntaxTrivia(SyntaxKind kind, string text)
|
||||
: base(kind, text.Length)
|
||||
{
|
||||
Text = text;
|
||||
}
|
||||
|
||||
internal SyntaxTrivia(SyntaxKind kind, string text, RazorDiagnostic[] diagnostics, SyntaxAnnotation[] annotations)
|
||||
: base(kind, text.Length, diagnostics, annotations)
|
||||
{
|
||||
Text = text;
|
||||
}
|
||||
|
||||
public string Text { get; }
|
||||
|
||||
internal override bool IsTrivia => true;
|
||||
|
||||
public override int Width => Text.Length;
|
||||
|
||||
protected override void WriteTriviaTo(TextWriter writer)
|
||||
{
|
||||
writer.Write(Text);
|
||||
}
|
||||
|
||||
public sealed override string ToFullString()
|
||||
{
|
||||
return Text;
|
||||
}
|
||||
|
||||
public sealed override int GetLeadingTriviaWidth()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public sealed override int GetTrailingTriviaWidth()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected override sealed int GetSlotCount()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal override sealed GreenNode GetSlot(int index)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
internal override SyntaxNode CreateRed(SyntaxNode parent, int position)
|
||||
{
|
||||
return new Syntax.SyntaxTrivia(this, parent, position);
|
||||
}
|
||||
|
||||
internal override GreenNode Accept(SyntaxVisitor visitor)
|
||||
{
|
||||
return visitor.VisitSyntaxTrivia(this);
|
||||
}
|
||||
|
||||
internal override GreenNode SetDiagnostics(RazorDiagnostic[] diagnostics)
|
||||
{
|
||||
return new SyntaxTrivia(Kind, Text, diagnostics, GetAnnotations());
|
||||
}
|
||||
|
||||
internal override GreenNode SetAnnotations(SyntaxAnnotation[] annotations)
|
||||
{
|
||||
return new SyntaxTrivia(Kind, Text, GetDiagnostics(), annotations);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax
|
||||
{
|
||||
internal abstract class SyntaxVisitor
|
||||
{
|
||||
public virtual GreenNode Visit(GreenNode node)
|
||||
{
|
||||
if (node != null)
|
||||
{
|
||||
return node.Accept(this);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public virtual GreenNode VisitSyntaxNode(GreenNode node)
|
||||
{
|
||||
return node;
|
||||
}
|
||||
|
||||
public virtual GreenNode VisitHtmlNode(HtmlNodeSyntax node)
|
||||
{
|
||||
return VisitSyntaxNode(node);
|
||||
}
|
||||
|
||||
public virtual GreenNode VisitHtmlText(HtmlTextSyntax node)
|
||||
{
|
||||
return VisitHtmlNode(node);
|
||||
}
|
||||
|
||||
public virtual SyntaxToken VisitSyntaxToken(SyntaxToken token)
|
||||
{
|
||||
return token;
|
||||
}
|
||||
|
||||
public virtual SyntaxTrivia VisitSyntaxTrivia(SyntaxTrivia trivia)
|
||||
{
|
||||
return trivia;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax
|
||||
{
|
||||
internal class UnknownTokenSyntax : SyntaxToken
|
||||
{
|
||||
internal UnknownTokenSyntax(string text, params RazorDiagnostic[] diagnostics)
|
||||
: base(SyntaxKind.Unknown, text, null, null, diagnostics, null)
|
||||
{
|
||||
}
|
||||
|
||||
internal UnknownTokenSyntax(string text, GreenNode leadingTrivia, GreenNode trailingTrivia)
|
||||
: base(SyntaxKind.Unknown, text, leadingTrivia, trailingTrivia)
|
||||
{
|
||||
}
|
||||
|
||||
protected UnknownTokenSyntax(SyntaxKind kind, string name, GreenNode leadingTrivia, GreenNode trailingTrivia)
|
||||
: base(kind, name, leadingTrivia, trailingTrivia)
|
||||
{
|
||||
}
|
||||
|
||||
protected UnknownTokenSyntax(SyntaxKind kind, string name, GreenNode leadingTrivia, GreenNode trailingTrivia, RazorDiagnostic[] diagnostics, SyntaxAnnotation[] annotations)
|
||||
: base(kind, name, leadingTrivia, trailingTrivia, diagnostics, annotations)
|
||||
{
|
||||
}
|
||||
|
||||
internal override SyntaxNode CreateRed(SyntaxNode parent, int position) => new Syntax.UnknownTokenSyntax(this, parent, position);
|
||||
|
||||
public override SyntaxToken TokenWithLeadingTrivia(GreenNode trivia)
|
||||
{
|
||||
return new UnknownTokenSyntax(Kind, Text, trivia, TrailingTrivia);
|
||||
}
|
||||
|
||||
public override SyntaxToken TokenWithTrailingTrivia(GreenNode trivia)
|
||||
{
|
||||
return new UnknownTokenSyntax(Kind, Text, LeadingTrivia, trivia);
|
||||
}
|
||||
|
||||
internal override GreenNode SetDiagnostics(RazorDiagnostic[] diagnostics)
|
||||
{
|
||||
return new UnknownTokenSyntax(Kind, Text, LeadingTrivia, TrailingTrivia, diagnostics, GetAnnotations());
|
||||
}
|
||||
|
||||
internal override GreenNode SetAnnotations(SyntaxAnnotation[] annotations)
|
||||
{
|
||||
return new UnknownTokenSyntax(Kind, Text, LeadingTrivia, TrailingTrivia, GetDiagnostics(), annotations);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax.InternalSyntax
|
||||
{
|
||||
internal class WhitespaceTokenSyntax : SyntaxToken
|
||||
{
|
||||
internal WhitespaceTokenSyntax(string text, params RazorDiagnostic[] diagnostics)
|
||||
: base(SyntaxKind.Whitespace, text, null, null, diagnostics, null)
|
||||
{
|
||||
}
|
||||
|
||||
internal WhitespaceTokenSyntax(string text, GreenNode leadingTrivia, GreenNode trailingTrivia)
|
||||
: base(SyntaxKind.Whitespace, text, leadingTrivia, trailingTrivia)
|
||||
{
|
||||
}
|
||||
|
||||
protected WhitespaceTokenSyntax(SyntaxKind kind, string name, GreenNode leadingTrivia, GreenNode trailingTrivia)
|
||||
: base(kind, name, leadingTrivia, trailingTrivia)
|
||||
{
|
||||
}
|
||||
|
||||
protected WhitespaceTokenSyntax(SyntaxKind kind, string name, GreenNode leadingTrivia, GreenNode trailingTrivia, RazorDiagnostic[] diagnostics, SyntaxAnnotation[] annotations)
|
||||
: base(kind, name, leadingTrivia, trailingTrivia, diagnostics, annotations)
|
||||
{
|
||||
}
|
||||
|
||||
internal override SyntaxNode CreateRed(SyntaxNode parent, int position) => new Syntax.WhitespaceTokenSyntax(this, parent, position);
|
||||
|
||||
public override SyntaxToken TokenWithLeadingTrivia(GreenNode trivia)
|
||||
{
|
||||
return new WhitespaceTokenSyntax(Kind, Text, trivia, TrailingTrivia);
|
||||
}
|
||||
|
||||
public override SyntaxToken TokenWithTrailingTrivia(GreenNode trivia)
|
||||
{
|
||||
return new WhitespaceTokenSyntax(Kind, Text, LeadingTrivia, trivia);
|
||||
}
|
||||
|
||||
internal override GreenNode SetDiagnostics(RazorDiagnostic[] diagnostics)
|
||||
{
|
||||
return new WhitespaceTokenSyntax(Kind, Text, LeadingTrivia, TrailingTrivia, diagnostics, GetAnnotations());
|
||||
}
|
||||
|
||||
internal override GreenNode SetAnnotations(SyntaxAnnotation[] annotations)
|
||||
{
|
||||
return new WhitespaceTokenSyntax(Kind, Text, LeadingTrivia, TrailingTrivia, GetDiagnostics(), annotations);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||
{
|
||||
internal class NewLineTokenSyntax : SyntaxToken
|
||||
{
|
||||
internal NewLineTokenSyntax(GreenNode green, SyntaxNode parent, int position)
|
||||
: base(green, parent, position)
|
||||
{
|
||||
}
|
||||
|
||||
internal new InternalSyntax.NewLineTokenSyntax Green => (InternalSyntax.NewLineTokenSyntax)base.Green;
|
||||
|
||||
public string Value => Text;
|
||||
|
||||
internal override SyntaxToken WithLeadingTriviaCore(SyntaxNode trivia)
|
||||
{
|
||||
return new InternalSyntax.NewLineTokenSyntax(Text, trivia?.Green, GetTrailingTrivia().Node?.Green).CreateRed(Parent, Position) as NewLineTokenSyntax;
|
||||
}
|
||||
|
||||
internal override SyntaxToken WithTrailingTriviaCore(SyntaxNode trivia)
|
||||
{
|
||||
return new InternalSyntax.NewLineTokenSyntax(Text, GetLeadingTrivia().Node?.Green, trivia?.Green).CreateRed(Parent, Position) as NewLineTokenSyntax;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
// 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;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||
{
|
||||
[Flags]
|
||||
internal enum NodeFlags : byte
|
||||
{
|
||||
None = 0,
|
||||
ContainsDiagnostics = 1 << 0,
|
||||
ContainsStructuredTrivia = 1 << 1,
|
||||
ContainsDirectives = 1 << 2,
|
||||
ContainsSkippedText = 1 << 3,
|
||||
ContainsAnnotations = 1 << 4,
|
||||
IsMissing = 1 << 5,
|
||||
|
||||
InheritMask = ContainsDiagnostics | ContainsStructuredTrivia | ContainsDirectives | ContainsSkippedText | ContainsAnnotations | IsMissing,
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,248 @@
|
|||
// 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 System.Diagnostics;
|
||||
using System.Threading;
|
||||
|
||||
#if DETECT_LEAKS
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
#endif
|
||||
|
||||
// define TRACE_LEAKS to get additional diagnostics that can lead to the leak sources. note: it will
|
||||
// make everything about 2-3x slower
|
||||
//
|
||||
// #define TRACE_LEAKS
|
||||
|
||||
// define DETECT_LEAKS to detect possible leaks
|
||||
// #if DEBUG
|
||||
// #define DETECT_LEAKS //for now always enable DETECT_LEAKS in debug.
|
||||
// #endif
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||
{
|
||||
/// <summary>
|
||||
/// Generic implementation of object pooling pattern with predefined pool size limit. The main
|
||||
/// purpose is that limited number of frequently used objects can be kept in the pool for
|
||||
/// further recycling.
|
||||
///
|
||||
/// Notes:
|
||||
/// 1) it is not the goal to keep all returned objects. Pool is not meant for storage. If there
|
||||
/// is no space in the pool, extra returned objects will be dropped.
|
||||
///
|
||||
/// 2) it is implied that if object was obtained from a pool, the caller will return it back in
|
||||
/// a relatively short time. Keeping checked out objects for long durations is ok, but
|
||||
/// reduces usefulness of pooling. Just new up your own.
|
||||
///
|
||||
/// Not returning objects to the pool in not detrimental to the pool's work, but is a bad practice.
|
||||
/// Rationale:
|
||||
/// If there is no intent for reusing the object, do not use pool - just use "new".
|
||||
/// </summary>
|
||||
internal class ObjectPool<T> where T : class
|
||||
{
|
||||
private struct Element
|
||||
{
|
||||
internal T Value;
|
||||
}
|
||||
|
||||
/// <remarks>
|
||||
/// Not using <see cref="T:System.Func{T}"/> because this file is linked into the (debugger) Formatter,
|
||||
/// which does not have that type (since it compiles against .NET 2.0).
|
||||
/// </remarks>
|
||||
internal delegate T Factory();
|
||||
|
||||
// storage for the pool objects.
|
||||
private readonly Element[] _items;
|
||||
|
||||
// factory is stored for the lifetime of the pool. We will call this only when pool needs to
|
||||
// expand. compared to "new T()", Func gives more flexibility to implementers and faster
|
||||
// than "new T()".
|
||||
private readonly Factory _factory;
|
||||
|
||||
#if DETECT_LEAKS
|
||||
private static readonly ConditionalWeakTable<T, LeakTracker> leakTrackers = new ConditionalWeakTable<T, LeakTracker>();
|
||||
|
||||
private class LeakTracker : IDisposable
|
||||
{
|
||||
private volatile bool disposed;
|
||||
|
||||
#if TRACE_LEAKS
|
||||
internal volatile System.Diagnostics.StackTrace Trace = null;
|
||||
#endif
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
disposed = true;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
private string GetTrace()
|
||||
{
|
||||
#if TRACE_LEAKS
|
||||
return Trace == null? "": Trace.ToString();
|
||||
#else
|
||||
return "Leak tracing information is disabled. Define TRACE_LEAKS on ObjectPool`1.cs to get more info \n";
|
||||
#endif
|
||||
}
|
||||
|
||||
~LeakTracker()
|
||||
{
|
||||
if (!this.disposed &&
|
||||
!Environment.HasShutdownStarted &&
|
||||
!AppDomain.CurrentDomain.IsFinalizingForUnload())
|
||||
{
|
||||
string report = string.Format("Pool detected potential leaking of {0}. \n Location of the leak: \n {1} ",
|
||||
typeof(T).ToString(),
|
||||
GetTrace());
|
||||
|
||||
// If you are seeing this message it means that object has been allocated from the pool
|
||||
// and has not been returned back. This is not critical, but turns pool into rather
|
||||
// inefficient kind of "new".
|
||||
Debug.WriteLine("TRACEOBJECTPOOLLEAKS_BEGIN\n" + report + "TRACEOBJECTPOOLLEAKS_END");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
internal ObjectPool(Factory factory)
|
||||
: this(factory, Environment.ProcessorCount * 2)
|
||||
{ }
|
||||
|
||||
internal ObjectPool(Factory factory, int size)
|
||||
{
|
||||
_factory = factory;
|
||||
_items = new Element[size];
|
||||
}
|
||||
|
||||
private T CreateInstance()
|
||||
{
|
||||
var inst = _factory();
|
||||
return inst;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Produces an instance.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Search strategy is a simple linear probing which is chosen for it cache-friendliness.
|
||||
/// Note that Free will try to store recycled objects close to the start thus statistically
|
||||
/// reducing how far we will typically search.
|
||||
/// </remarks>
|
||||
internal T Allocate()
|
||||
{
|
||||
var items = _items;
|
||||
T inst;
|
||||
|
||||
for (var i = 0; i < items.Length; i++)
|
||||
{
|
||||
// Note that the read is optimistically not synchronized. That is intentional.
|
||||
// We will interlock only when we have a candidate. in a worst case we may miss some
|
||||
// recently returned objects. Not a big deal.
|
||||
inst = items[i].Value;
|
||||
if (inst != null)
|
||||
{
|
||||
if (inst == Interlocked.CompareExchange(ref items[i].Value, null, inst))
|
||||
{
|
||||
goto gotInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inst = CreateInstance();
|
||||
gotInstance:
|
||||
|
||||
#if DETECT_LEAKS
|
||||
var tracker = new LeakTracker();
|
||||
leakTrackers.Add(inst, tracker);
|
||||
|
||||
#if TRACE_LEAKS
|
||||
var frame = new System.Diagnostics.StackTrace(false);
|
||||
tracker.Trace = frame;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return inst;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns objects to the pool.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Search strategy is a simple linear probing which is chosen for it cache-friendliness.
|
||||
/// Note that Free will try to store recycled objects close to the start thus statistically
|
||||
/// reducing how far we will typically search in Allocate.
|
||||
/// </remarks>
|
||||
internal void Free(T obj)
|
||||
{
|
||||
Validate(obj);
|
||||
ForgetTrackedObject(obj);
|
||||
|
||||
var items = _items;
|
||||
for (var i = 0; i < items.Length; i++)
|
||||
{
|
||||
if (items[i].Value == null)
|
||||
{
|
||||
// Intentionally not using interlocked here.
|
||||
// In a worst case scenario two objects may be stored into same slot.
|
||||
// It is very unlikely to happen and will only mean that one of the objects will get collected.
|
||||
items[i].Value = obj;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes an object from leak tracking.
|
||||
///
|
||||
/// This is called when an object is returned to the pool. It may also be explicitly
|
||||
/// called if an object allocated from the pool is intentionally not being returned
|
||||
/// to the pool. This can be of use with pooled arrays if the consumer wants to
|
||||
/// return a larger array to the pool than was originally allocated.
|
||||
/// </summary>
|
||||
[Conditional("DEBUG")]
|
||||
internal void ForgetTrackedObject(T old, T replacement = null)
|
||||
{
|
||||
#if DETECT_LEAKS
|
||||
LeakTracker tracker;
|
||||
if (leakTrackers.TryGetValue(old, out tracker))
|
||||
{
|
||||
tracker.Dispose();
|
||||
leakTrackers.Remove(old);
|
||||
}
|
||||
else
|
||||
{
|
||||
string report = string.Format("Object of type {0} was freed, but was not from pool. \n Callstack: \n {1} ",
|
||||
typeof(T).ToString(),
|
||||
new System.Diagnostics.StackTrace(false));
|
||||
|
||||
Debug.WriteLine("TRACEOBJECTPOOLLEAKS_BEGIN\n" + report + "TRACEOBJECTPOOLLEAKS_END");
|
||||
}
|
||||
|
||||
if (replacement != null)
|
||||
{
|
||||
tracker = new LeakTracker();
|
||||
leakTrackers.Add(replacement, tracker);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
private void Validate(object obj)
|
||||
{
|
||||
Debug.Assert(obj != null, "freeing null?");
|
||||
|
||||
var items = _items;
|
||||
for (var i = 0; i < items.Length; i++)
|
||||
{
|
||||
var value = items[i].Value;
|
||||
if (value == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Assert(value != obj, "freeing twice?");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language
|
||||
{
|
||||
internal enum ParserState
|
||||
{
|
||||
Unknown,
|
||||
Misc,
|
||||
Content,
|
||||
StartTag,
|
||||
EndTag,
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||
{
|
||||
internal class PunctuationSyntax : SyntaxToken
|
||||
{
|
||||
internal PunctuationSyntax(GreenNode green, SyntaxNode parent, int position)
|
||||
: base(green, parent, position)
|
||||
{
|
||||
}
|
||||
|
||||
internal new InternalSyntax.PunctuationSyntax Green => (InternalSyntax.PunctuationSyntax)base.Green;
|
||||
|
||||
public string Punctuation => Text;
|
||||
|
||||
internal override SyntaxToken WithLeadingTriviaCore(SyntaxNode trivia)
|
||||
{
|
||||
return new InternalSyntax.PunctuationSyntax(Kind, Text, trivia?.Green, GetTrailingTrivia().Node?.Green).CreateRed(Parent, Position) as PunctuationSyntax;
|
||||
}
|
||||
|
||||
internal override SyntaxToken WithTrailingTriviaCore(SyntaxNode trivia)
|
||||
{
|
||||
return new InternalSyntax.PunctuationSyntax(Kind, Text, GetLeadingTrivia().Node?.Green, trivia?.Green).CreateRed(Parent, Position) as PunctuationSyntax;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,169 @@
|
|||
// 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 System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||
{
|
||||
internal static class SpecializedCollections
|
||||
{
|
||||
public static IEnumerator<T> EmptyEnumerator<T>()
|
||||
{
|
||||
return Empty.Enumerator<T>.Instance;
|
||||
}
|
||||
|
||||
public static IEnumerable<T> EmptyEnumerable<T>()
|
||||
{
|
||||
return Empty.List<T>.Instance;
|
||||
}
|
||||
|
||||
public static ICollection<T> EmptyCollection<T>()
|
||||
{
|
||||
return Empty.List<T>.Instance;
|
||||
}
|
||||
|
||||
public static IList<T> EmptyList<T>()
|
||||
{
|
||||
return Empty.List<T>.Instance;
|
||||
}
|
||||
|
||||
public static IReadOnlyList<T> EmptyReadOnlyList<T>()
|
||||
{
|
||||
return Empty.List<T>.Instance;
|
||||
}
|
||||
|
||||
private class Empty
|
||||
{
|
||||
internal class Enumerator<T> : Enumerator, IEnumerator<T>
|
||||
{
|
||||
public static new readonly IEnumerator<T> Instance = new Enumerator<T>();
|
||||
|
||||
protected Enumerator()
|
||||
{
|
||||
}
|
||||
|
||||
public new T Current => throw new InvalidOperationException();
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
internal class Enumerator : IEnumerator
|
||||
{
|
||||
public static readonly IEnumerator Instance = new Enumerator();
|
||||
|
||||
protected Enumerator()
|
||||
{
|
||||
}
|
||||
|
||||
public object Current => throw new InvalidOperationException();
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
internal class Enumerable<T> : IEnumerable<T>
|
||||
{
|
||||
// PERF: cache the instance of enumerator.
|
||||
// accessing a generic static field is kinda slow from here,
|
||||
// but since empty enumerables are singletons, there is no harm in having
|
||||
// one extra instance field
|
||||
private readonly IEnumerator<T> _enumerator = Enumerator<T>.Instance;
|
||||
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
return _enumerator;
|
||||
}
|
||||
|
||||
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
||||
internal class Collection<T> : Enumerable<T>, ICollection<T>
|
||||
{
|
||||
public static readonly ICollection<T> Instance = new Collection<T>();
|
||||
|
||||
protected Collection()
|
||||
{
|
||||
}
|
||||
|
||||
public void Add(T item)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public bool Contains(T item)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public void CopyTo(T[] array, int arrayIndex)
|
||||
{
|
||||
}
|
||||
|
||||
public int Count => 0;
|
||||
|
||||
public bool IsReadOnly => true;
|
||||
|
||||
public bool Remove(T item)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
|
||||
internal class List<T> : Collection<T>, IList<T>, IReadOnlyList<T>
|
||||
{
|
||||
public static readonly new List<T> Instance = new List<T>();
|
||||
|
||||
protected List()
|
||||
{
|
||||
}
|
||||
|
||||
public int IndexOf(T item)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void Insert(int index, T item)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public void RemoveAt(int index)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public T this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
// 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 System.Diagnostics;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||
{
|
||||
/// <summary>
|
||||
/// A SyntaxAnnotation is used to annotate syntax elements with additional information.
|
||||
///
|
||||
/// Since syntax elements are immutable, annotating them requires creating new instances of them
|
||||
/// with the annotations attached.
|
||||
/// </summary>
|
||||
[DebuggerDisplay("{GetDebuggerDisplay(), nq}")]
|
||||
internal sealed class SyntaxAnnotation : IEquatable<SyntaxAnnotation>
|
||||
{
|
||||
// use a value identity instead of object identity so a deserialized instance matches the original instance.
|
||||
private readonly long _id;
|
||||
private static long s_nextId;
|
||||
|
||||
// use a value identity instead of object identity so a deserialized instance matches the original instance.
|
||||
public string Kind { get; }
|
||||
public string Data { get; }
|
||||
|
||||
public SyntaxAnnotation()
|
||||
{
|
||||
_id = System.Threading.Interlocked.Increment(ref s_nextId);
|
||||
}
|
||||
|
||||
public SyntaxAnnotation(string kind)
|
||||
: this()
|
||||
{
|
||||
Kind = kind;
|
||||
}
|
||||
|
||||
public SyntaxAnnotation(string kind, string data)
|
||||
: this(kind)
|
||||
{
|
||||
Data = data;
|
||||
}
|
||||
|
||||
private string GetDebuggerDisplay()
|
||||
{
|
||||
return string.Format("Annotation: Kind='{0}' Data='{1}'", this.Kind ?? "", this.Data ?? "");
|
||||
}
|
||||
|
||||
public bool Equals(SyntaxAnnotation other)
|
||||
{
|
||||
return (object)other != null && _id == other._id;
|
||||
}
|
||||
|
||||
public static bool operator ==(SyntaxAnnotation left, SyntaxAnnotation right)
|
||||
{
|
||||
if ((object)left == (object)right)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((object)left == null || (object)right == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return left.Equals(right);
|
||||
}
|
||||
|
||||
public static bool operator !=(SyntaxAnnotation left, SyntaxAnnotation right)
|
||||
{
|
||||
if ((object)left == (object)right)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((object)left == null || (object)right == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return !left.Equals(right);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return Equals(obj as SyntaxAnnotation);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return _id.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language
|
||||
{
|
||||
internal enum SyntaxKind : byte
|
||||
{
|
||||
Unknown,
|
||||
List,
|
||||
Whitespace,
|
||||
NewLine,
|
||||
|
||||
// HTML
|
||||
HtmlText,
|
||||
HtmlDocument,
|
||||
HtmlDeclaration,
|
||||
HtmlTextLiteralToken,
|
||||
OpenAngle,
|
||||
Bang,
|
||||
ForwardSlash,
|
||||
QuestionMark,
|
||||
DoubleHyphen,
|
||||
LeftBracket,
|
||||
CloseAngle,
|
||||
RightBracket,
|
||||
Equals,
|
||||
DoubleQuote,
|
||||
SingleQuote,
|
||||
Transition,
|
||||
Colon,
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||
{
|
||||
internal abstract class SyntaxList : SyntaxNode
|
||||
{
|
||||
internal SyntaxList(InternalSyntax.SyntaxList green, SyntaxNode parent, int position)
|
||||
: base(green, parent, position)
|
||||
{
|
||||
}
|
||||
|
||||
internal override SyntaxNode Accept(SyntaxVisitor visitor)
|
||||
{
|
||||
return visitor.Visit(this);
|
||||
}
|
||||
|
||||
internal class WithTwoChildren : SyntaxList
|
||||
{
|
||||
private SyntaxNode _child0;
|
||||
private SyntaxNode _child1;
|
||||
|
||||
internal WithTwoChildren(InternalSyntax.SyntaxList green, SyntaxNode parent, int position)
|
||||
: base(green, parent, position)
|
||||
{
|
||||
}
|
||||
|
||||
internal override SyntaxNode GetNodeSlot(int index)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
return GetRedElement(ref _child0, 0);
|
||||
case 1:
|
||||
return GetRedElement(ref _child1, 1);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
internal override SyntaxNode GetCachedSlot(int index)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
return _child0;
|
||||
case 1:
|
||||
return _child1;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class WithThreeChildren : SyntaxList
|
||||
{
|
||||
private SyntaxNode _child0;
|
||||
private SyntaxNode _child1;
|
||||
private SyntaxNode _child2;
|
||||
|
||||
internal WithThreeChildren(InternalSyntax.SyntaxList green, SyntaxNode parent, int position)
|
||||
: base(green, parent, position)
|
||||
{
|
||||
}
|
||||
|
||||
internal override SyntaxNode GetNodeSlot(int index)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
return GetRedElement(ref _child0, 0);
|
||||
case 1:
|
||||
return GetRedElement(ref _child1, 1);
|
||||
case 2:
|
||||
return GetRedElement(ref _child2, 2);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
internal override SyntaxNode GetCachedSlot(int index)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0:
|
||||
return _child0;
|
||||
case 1:
|
||||
return _child1;
|
||||
case 2:
|
||||
return _child2;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class WithManyChildren : SyntaxList
|
||||
{
|
||||
private readonly ArrayElement<SyntaxNode>[] _children;
|
||||
|
||||
internal WithManyChildren(InternalSyntax.SyntaxList green, SyntaxNode parent, int position)
|
||||
: base(green, parent, position)
|
||||
{
|
||||
_children = new ArrayElement<SyntaxNode>[green.SlotCount];
|
||||
}
|
||||
|
||||
internal override SyntaxNode GetNodeSlot(int index)
|
||||
{
|
||||
return this.GetRedElement(ref _children[index].Value, index);
|
||||
}
|
||||
|
||||
internal override SyntaxNode GetCachedSlot(int index)
|
||||
{
|
||||
return _children[index];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,172 @@
|
|||
// 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 System.Diagnostics;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||
{
|
||||
internal class SyntaxListBuilder
|
||||
{
|
||||
private ArrayElement<GreenNode>[] _nodes;
|
||||
|
||||
public int Count { get; private set; }
|
||||
|
||||
public SyntaxListBuilder(int size)
|
||||
{
|
||||
_nodes = new ArrayElement<GreenNode>[size];
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
Count = 0;
|
||||
}
|
||||
|
||||
public void Add(SyntaxNode item)
|
||||
{
|
||||
AddInternal(item.Green);
|
||||
}
|
||||
|
||||
internal void AddInternal(GreenNode item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
throw new ArgumentNullException();
|
||||
}
|
||||
|
||||
if (_nodes == null || Count >= _nodes.Length)
|
||||
{
|
||||
Grow(Count == 0 ? 8 : _nodes.Length * 2);
|
||||
}
|
||||
|
||||
_nodes[Count++].Value = item;
|
||||
}
|
||||
|
||||
public void AddRange(SyntaxNode[] items)
|
||||
{
|
||||
AddRange(items, 0, items.Length);
|
||||
}
|
||||
|
||||
public void AddRange(SyntaxNode[] items, int offset, int length)
|
||||
{
|
||||
if (_nodes == null || Count + length > _nodes.Length)
|
||||
{
|
||||
Grow(Count + length);
|
||||
}
|
||||
|
||||
for (int i = offset, j = Count; i < offset + length; ++i, ++j)
|
||||
{
|
||||
_nodes[j].Value = items[i].Green;
|
||||
}
|
||||
|
||||
var start = Count;
|
||||
Count += length;
|
||||
Validate(start, Count);
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
private void Validate(int start, int end)
|
||||
{
|
||||
for (var i = start; i < end; i++)
|
||||
{
|
||||
if (_nodes[i].Value == null)
|
||||
{
|
||||
throw new ArgumentException("Cannot add a null node.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void AddRange(SyntaxList<SyntaxNode> list)
|
||||
{
|
||||
AddRange(list, 0, list.Count);
|
||||
}
|
||||
|
||||
public void AddRange(SyntaxList<SyntaxNode> list, int offset, int count)
|
||||
{
|
||||
if (_nodes == null || Count + count > _nodes.Length)
|
||||
{
|
||||
Grow(Count + count);
|
||||
}
|
||||
|
||||
var dst = Count;
|
||||
for (int i = offset, limit = offset + count; i < limit; i++)
|
||||
{
|
||||
_nodes[dst].Value = list.ItemInternal(i).Green;
|
||||
dst++;
|
||||
}
|
||||
|
||||
var start = Count;
|
||||
Count += count;
|
||||
Validate(start, Count);
|
||||
}
|
||||
|
||||
public void AddRange<TNode>(SyntaxList<TNode> list) where TNode : SyntaxNode
|
||||
{
|
||||
AddRange(list, 0, list.Count);
|
||||
}
|
||||
|
||||
public void AddRange<TNode>(SyntaxList<TNode> list, int offset, int count) where TNode : SyntaxNode
|
||||
{
|
||||
AddRange(new SyntaxList<SyntaxNode>(list.Node), offset, count);
|
||||
}
|
||||
|
||||
private void Grow(int size)
|
||||
{
|
||||
var tmp = new ArrayElement<GreenNode>[size];
|
||||
Array.Copy(_nodes, tmp, _nodes.Length);
|
||||
_nodes = tmp;
|
||||
}
|
||||
|
||||
public bool Any(SyntaxKind kind)
|
||||
{
|
||||
for (var i = 0; i < Count; i++)
|
||||
{
|
||||
if (_nodes[i].Value.Kind == kind)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
internal GreenNode ToListNode()
|
||||
{
|
||||
switch (Count)
|
||||
{
|
||||
case 0:
|
||||
return null;
|
||||
case 1:
|
||||
return _nodes[0].Value;
|
||||
case 2:
|
||||
return InternalSyntax.SyntaxList.List(_nodes[0].Value, _nodes[1].Value);
|
||||
case 3:
|
||||
return InternalSyntax.SyntaxList.List(_nodes[0].Value, _nodes[1].Value, _nodes[2].Value);
|
||||
default:
|
||||
var tmp = new ArrayElement<GreenNode>[Count];
|
||||
for (var i = 0; i < Count; i++)
|
||||
{
|
||||
tmp[i].Value = _nodes[i].Value;
|
||||
}
|
||||
|
||||
return InternalSyntax.SyntaxList.List(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
public static implicit operator SyntaxList<SyntaxNode>(SyntaxListBuilder builder)
|
||||
{
|
||||
if (builder == null)
|
||||
{
|
||||
return default(SyntaxList<SyntaxNode>);
|
||||
}
|
||||
|
||||
return builder.ToList();
|
||||
}
|
||||
|
||||
internal void RemoveLast()
|
||||
{
|
||||
Count -= 1;
|
||||
_nodes[Count] = default(ArrayElement<GreenNode>);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||
{
|
||||
internal static class SyntaxListBuilderExtensions
|
||||
{
|
||||
public static SyntaxList<SyntaxNode> ToList(this SyntaxListBuilder builder)
|
||||
{
|
||||
if (builder == null || builder.Count == 0)
|
||||
{
|
||||
return default(SyntaxList<SyntaxNode>);
|
||||
}
|
||||
|
||||
return new SyntaxList<SyntaxNode>(builder.ToListNode().CreateRed());
|
||||
}
|
||||
|
||||
public static SyntaxList<TNode> ToList<TNode>(this SyntaxListBuilder builder)
|
||||
where TNode : SyntaxNode
|
||||
{
|
||||
if (builder == null || builder.Count == 0)
|
||||
{
|
||||
return new SyntaxList<TNode>();
|
||||
}
|
||||
|
||||
return new SyntaxList<TNode>(builder.ToListNode().CreateRed());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||
{
|
||||
internal readonly struct SyntaxListBuilder<TNode>
|
||||
where TNode : SyntaxNode
|
||||
{
|
||||
private readonly SyntaxListBuilder _builder;
|
||||
|
||||
public SyntaxListBuilder(int size)
|
||||
: this(new SyntaxListBuilder(size))
|
||||
{
|
||||
}
|
||||
|
||||
public static SyntaxListBuilder<TNode> Create()
|
||||
{
|
||||
return new SyntaxListBuilder<TNode>(8);
|
||||
}
|
||||
|
||||
internal SyntaxListBuilder(SyntaxListBuilder builder)
|
||||
{
|
||||
_builder = builder;
|
||||
}
|
||||
|
||||
public bool IsNull
|
||||
{
|
||||
get
|
||||
{
|
||||
return _builder == null;
|
||||
}
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return _builder.Count;
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_builder.Clear();
|
||||
}
|
||||
|
||||
public SyntaxListBuilder<TNode> Add(TNode node)
|
||||
{
|
||||
_builder.Add(node);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void AddRange(TNode[] items, int offset, int length)
|
||||
{
|
||||
_builder.AddRange(items, offset, length);
|
||||
}
|
||||
|
||||
public void AddRange(SyntaxList<TNode> nodes)
|
||||
{
|
||||
_builder.AddRange(nodes);
|
||||
}
|
||||
|
||||
public void AddRange(SyntaxList<TNode> nodes, int offset, int length)
|
||||
{
|
||||
_builder.AddRange(nodes, offset, length);
|
||||
}
|
||||
|
||||
public bool Any(SyntaxKind kind)
|
||||
{
|
||||
return _builder.Any(kind);
|
||||
}
|
||||
|
||||
public SyntaxList<TNode> ToList()
|
||||
{
|
||||
return _builder.ToList();
|
||||
}
|
||||
|
||||
public static implicit operator SyntaxListBuilder(SyntaxListBuilder<TNode> builder)
|
||||
{
|
||||
return builder._builder;
|
||||
}
|
||||
|
||||
public static implicit operator SyntaxList<TNode>(SyntaxListBuilder<TNode> builder)
|
||||
{
|
||||
if (builder._builder != null)
|
||||
{
|
||||
return builder.ToList();
|
||||
}
|
||||
|
||||
return default(SyntaxList<TNode>);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,606 @@
|
|||
// 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 System.Linq;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||
{
|
||||
internal readonly struct SyntaxList<TNode> : IReadOnlyList<TNode>, IEquatable<SyntaxList<TNode>>
|
||||
where TNode : SyntaxNode
|
||||
{
|
||||
public SyntaxList(SyntaxNode node)
|
||||
{
|
||||
Node = node;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a singleton list of syntax nodes.
|
||||
/// </summary>
|
||||
/// <param name="node">The single element node.</param>
|
||||
public SyntaxList(TNode node)
|
||||
: this((SyntaxNode)node)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a list of syntax nodes.
|
||||
/// </summary>
|
||||
/// <param name="nodes">A sequence of element nodes.</param>
|
||||
public SyntaxList(IEnumerable<TNode> nodes)
|
||||
: this(CreateNode(nodes))
|
||||
{
|
||||
}
|
||||
|
||||
private static SyntaxNode CreateNode(IEnumerable<TNode> nodes)
|
||||
{
|
||||
if (nodes == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var builder = (nodes is ICollection<TNode> collection) ? new SyntaxListBuilder<TNode>(collection.Count) : SyntaxListBuilder<TNode>.Create();
|
||||
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
builder.Add(node);
|
||||
}
|
||||
|
||||
return builder.ToList().Node;
|
||||
}
|
||||
|
||||
internal SyntaxNode Node { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The number of nodes in the list.
|
||||
/// </summary>
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return Node == null ? 0 : (Node.IsList ? Node.SlotCount : 1);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the node at the specified index.
|
||||
/// </summary>
|
||||
/// <param name="index">The zero-based index of the node to get or set.</param>
|
||||
/// <returns>The node at the specified index.</returns>
|
||||
public TNode this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Node != null)
|
||||
{
|
||||
if (Node.IsList)
|
||||
{
|
||||
if (unchecked((uint)index < (uint)Node.SlotCount))
|
||||
{
|
||||
return (TNode)Node.GetNodeSlot(index);
|
||||
}
|
||||
}
|
||||
else if (index == 0)
|
||||
{
|
||||
return (TNode)Node;
|
||||
}
|
||||
}
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
internal SyntaxNode ItemInternal(int index)
|
||||
{
|
||||
if (Node.IsList)
|
||||
{
|
||||
return Node.GetNodeSlot(index);
|
||||
}
|
||||
|
||||
Debug.Assert(index == 0);
|
||||
return Node;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The absolute span of the list elements in characters, including the leading and trailing trivia of the first and last elements.
|
||||
/// </summary>
|
||||
public TextSpan FullSpan
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Count == 0)
|
||||
{
|
||||
return default(TextSpan);
|
||||
}
|
||||
else
|
||||
{
|
||||
return TextSpan.FromBounds(this[0].FullSpan.Start, this[Count - 1].FullSpan.End);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The absolute span of the list elements in characters, not including the leading and trailing trivia of the first and last elements.
|
||||
/// </summary>
|
||||
public TextSpan Span
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Count == 0)
|
||||
{
|
||||
return default(TextSpan);
|
||||
}
|
||||
else
|
||||
{
|
||||
return TextSpan.FromBounds(this[0].Span.Start, this[Count - 1].Span.End);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the string representation of the nodes in this list, not including
|
||||
/// the first node's leading trivia and the last node's trailing trivia.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The string representation of the nodes in this list, not including
|
||||
/// the first node's leading trivia and the last node's trailing trivia.
|
||||
/// </returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return Node != null ? Node.ToString() : string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the full string representation of the nodes in this list including
|
||||
/// the first node's leading trivia and the last node's trailing trivia.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The full string representation of the nodes in this list including
|
||||
/// the first node's leading trivia and the last node's trailing trivia.
|
||||
/// </returns>
|
||||
public string ToFullString()
|
||||
{
|
||||
return Node != null ? Node.ToFullString() : string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new list with the specified node added at the end.
|
||||
/// </summary>
|
||||
/// <param name="node">The node to add.</param>
|
||||
public SyntaxList<TNode> Add(TNode node)
|
||||
{
|
||||
return Insert(Count, node);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new list with the specified nodes added at the end.
|
||||
/// </summary>
|
||||
/// <param name="nodes">The nodes to add.</param>
|
||||
public SyntaxList<TNode> AddRange(IEnumerable<TNode> nodes)
|
||||
{
|
||||
return InsertRange(Count, nodes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new list with the specified node inserted at the index.
|
||||
/// </summary>
|
||||
/// <param name="index">The index to insert at.</param>
|
||||
/// <param name="node">The node to insert.</param>
|
||||
public SyntaxList<TNode> Insert(int index, TNode node)
|
||||
{
|
||||
if (node == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(node));
|
||||
}
|
||||
|
||||
return InsertRange(index, new[] { node });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new list with the specified nodes inserted at the index.
|
||||
/// </summary>
|
||||
/// <param name="index">The index to insert at.</param>
|
||||
/// <param name="nodes">The nodes to insert.</param>
|
||||
public SyntaxList<TNode> InsertRange(int index, IEnumerable<TNode> nodes)
|
||||
{
|
||||
if (index < 0 || index > Count)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
}
|
||||
|
||||
if (nodes == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(nodes));
|
||||
}
|
||||
|
||||
var list = this.ToList();
|
||||
list.InsertRange(index, nodes);
|
||||
|
||||
if (list.Count == 0)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
else
|
||||
{
|
||||
return CreateList(list[0].Green, list);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new list with the element at specified index removed.
|
||||
/// </summary>
|
||||
/// <param name="index">The index of the element to remove.</param>
|
||||
public SyntaxList<TNode> RemoveAt(int index)
|
||||
{
|
||||
if (index < 0 || index > Count)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
}
|
||||
|
||||
return Remove(this[index]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new list with the element removed.
|
||||
/// </summary>
|
||||
/// <param name="node">The element to remove.</param>
|
||||
public SyntaxList<TNode> Remove(TNode node)
|
||||
{
|
||||
return CreateList(this.Where(x => x != node).ToList());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new list with the specified element replaced with the new node.
|
||||
/// </summary>
|
||||
/// <param name="nodeInList">The element to replace.</param>
|
||||
/// <param name="newNode">The new node.</param>
|
||||
public SyntaxList<TNode> Replace(TNode nodeInList, TNode newNode)
|
||||
{
|
||||
return ReplaceRange(nodeInList, new[] { newNode });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new list with the specified element replaced with new nodes.
|
||||
/// </summary>
|
||||
/// <param name="nodeInList">The element to replace.</param>
|
||||
/// <param name="newNodes">The new nodes.</param>
|
||||
public SyntaxList<TNode> ReplaceRange(TNode nodeInList, IEnumerable<TNode> newNodes)
|
||||
{
|
||||
if (nodeInList == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(nodeInList));
|
||||
}
|
||||
|
||||
if (newNodes == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(newNodes));
|
||||
}
|
||||
|
||||
var index = IndexOf(nodeInList);
|
||||
if (index >= 0 && index < Count)
|
||||
{
|
||||
var list = this.ToList();
|
||||
list.RemoveAt(index);
|
||||
list.InsertRange(index, newNodes);
|
||||
return CreateList(list);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException(nameof(nodeInList));
|
||||
}
|
||||
}
|
||||
|
||||
static SyntaxList<TNode> CreateList(List<TNode> items)
|
||||
{
|
||||
if (items.Count == 0)
|
||||
{
|
||||
return default(SyntaxList<TNode>);
|
||||
}
|
||||
else
|
||||
{
|
||||
return CreateList(items[0].Green, items);
|
||||
}
|
||||
}
|
||||
|
||||
static SyntaxList<TNode> CreateList(GreenNode creator, List<TNode> items)
|
||||
{
|
||||
if (items.Count == 0)
|
||||
{
|
||||
return default(SyntaxList<TNode>);
|
||||
}
|
||||
|
||||
var newGreen = creator.CreateList(items.Select(n => n.Green));
|
||||
return new SyntaxList<TNode>(newGreen.CreateRed());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The first node in the list.
|
||||
/// </summary>
|
||||
public TNode First()
|
||||
{
|
||||
return this[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The first node in the list or default if the list is empty.
|
||||
/// </summary>
|
||||
public TNode FirstOrDefault()
|
||||
{
|
||||
if (this.Any())
|
||||
{
|
||||
return this[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The last node in the list.
|
||||
/// </summary>
|
||||
public TNode Last()
|
||||
{
|
||||
return this[Count - 1];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The last node in the list or default if the list is empty.
|
||||
/// </summary>
|
||||
public TNode LastOrDefault()
|
||||
{
|
||||
if (Any())
|
||||
{
|
||||
return this[Count - 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// True if the list has at least one node.
|
||||
/// </summary>
|
||||
public bool Any()
|
||||
{
|
||||
Debug.Assert(Node == null || Count != 0);
|
||||
return Node != null;
|
||||
}
|
||||
|
||||
// for debugging
|
||||
private TNode[] Nodes
|
||||
{
|
||||
get { return this.ToArray(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get's the enumerator for this list.
|
||||
/// </summary>
|
||||
public Enumerator GetEnumerator()
|
||||
{
|
||||
return new Enumerator(in this);
|
||||
}
|
||||
|
||||
IEnumerator<TNode> IEnumerable<TNode>.GetEnumerator()
|
||||
{
|
||||
if (this.Any())
|
||||
{
|
||||
return new EnumeratorImpl(this);
|
||||
}
|
||||
|
||||
return SpecializedCollections.EmptyEnumerator<TNode>();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
if (this.Any())
|
||||
{
|
||||
return new EnumeratorImpl(this);
|
||||
}
|
||||
|
||||
return SpecializedCollections.EmptyEnumerator<TNode>();
|
||||
}
|
||||
|
||||
public static bool operator ==(SyntaxList<TNode> left, SyntaxList<TNode> right)
|
||||
{
|
||||
return left.Node == right.Node;
|
||||
}
|
||||
|
||||
public static bool operator !=(SyntaxList<TNode> left, SyntaxList<TNode> right)
|
||||
{
|
||||
return left.Node != right.Node;
|
||||
}
|
||||
|
||||
public bool Equals(SyntaxList<TNode> other)
|
||||
{
|
||||
return Node == other.Node;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is SyntaxList<TNode> && Equals((SyntaxList<TNode>)obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Node?.GetHashCode() ?? 0;
|
||||
}
|
||||
|
||||
public static implicit operator SyntaxList<TNode>(SyntaxList<SyntaxNode> nodes)
|
||||
{
|
||||
return new SyntaxList<TNode>(nodes.Node);
|
||||
}
|
||||
|
||||
public static implicit operator SyntaxList<SyntaxNode>(SyntaxList<TNode> nodes)
|
||||
{
|
||||
return new SyntaxList<SyntaxNode>(nodes.Node);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The index of the node in this list, or -1 if the node is not in the list.
|
||||
/// </summary>
|
||||
public int IndexOf(TNode node)
|
||||
{
|
||||
var index = 0;
|
||||
foreach (var child in this)
|
||||
{
|
||||
if (object.Equals(child, node))
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int IndexOf(Func<TNode, bool> predicate)
|
||||
{
|
||||
var index = 0;
|
||||
foreach (var child in this)
|
||||
{
|
||||
if (predicate(child))
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
internal int IndexOf(SyntaxKind kind)
|
||||
{
|
||||
var index = 0;
|
||||
foreach (var child in this)
|
||||
{
|
||||
if (child.Kind == kind)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int LastIndexOf(TNode node)
|
||||
{
|
||||
for (var i = Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (object.Equals(this[i], node))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int LastIndexOf(Func<TNode, bool> predicate)
|
||||
{
|
||||
for (var i = Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (predicate(this[i]))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public struct Enumerator
|
||||
{
|
||||
private readonly SyntaxList<TNode> _list;
|
||||
private int _index;
|
||||
|
||||
internal Enumerator(in SyntaxList<TNode> list)
|
||||
{
|
||||
_list = list;
|
||||
_index = -1;
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
var newIndex = _index + 1;
|
||||
if (newIndex < _list.Count)
|
||||
{
|
||||
_index = newIndex;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public TNode Current
|
||||
{
|
||||
get
|
||||
{
|
||||
return (TNode)_list.ItemInternal(_index);
|
||||
}
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
_index = -1;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
|
||||
private class EnumeratorImpl : IEnumerator<TNode>
|
||||
{
|
||||
private Enumerator _e;
|
||||
|
||||
internal EnumeratorImpl(in SyntaxList<TNode> list)
|
||||
{
|
||||
_e = new Enumerator(in list);
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
return _e.MoveNext();
|
||||
}
|
||||
|
||||
public TNode Current
|
||||
{
|
||||
get
|
||||
{
|
||||
return _e.Current;
|
||||
}
|
||||
}
|
||||
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
object IEnumerator.Current
|
||||
{
|
||||
get
|
||||
{
|
||||
return _e.Current;
|
||||
}
|
||||
}
|
||||
|
||||
void IEnumerator.Reset()
|
||||
{
|
||||
_e.Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,252 @@
|
|||
// 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.Diagnostics;
|
||||
using System.Threading;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||
{
|
||||
internal abstract class SyntaxNode
|
||||
{
|
||||
public SyntaxNode(GreenNode green, SyntaxNode parent, int position)
|
||||
{
|
||||
Green = green;
|
||||
Parent = parent;
|
||||
Position = position;
|
||||
}
|
||||
|
||||
internal GreenNode Green { get; }
|
||||
|
||||
public SyntaxNode Parent { get; }
|
||||
|
||||
public int Position { get; }
|
||||
|
||||
public int EndPosition => Position + FullWidth;
|
||||
|
||||
public SyntaxKind Kind => Green.Kind;
|
||||
|
||||
public int Width => Green.Width;
|
||||
|
||||
public int FullWidth => Green.FullWidth;
|
||||
|
||||
public int SpanStart => Position + Green.GetLeadingTriviaWidth();
|
||||
|
||||
public TextSpan FullSpan => new TextSpan(Position, Green.FullWidth);
|
||||
|
||||
public TextSpan Span
|
||||
{
|
||||
get
|
||||
{
|
||||
// Start with the full span.
|
||||
var start = Position;
|
||||
var width = Green.FullWidth;
|
||||
|
||||
// adjust for preceding trivia (avoid calling this twice, do not call Green.Width)
|
||||
var precedingWidth = Green.GetLeadingTriviaWidth();
|
||||
start += precedingWidth;
|
||||
width -= precedingWidth;
|
||||
|
||||
// adjust for following trivia width
|
||||
width -= Green.GetTrailingTriviaWidth();
|
||||
|
||||
Debug.Assert(width >= 0);
|
||||
return new TextSpan(start, width);
|
||||
}
|
||||
}
|
||||
|
||||
internal int SlotCount => Green.SlotCount;
|
||||
|
||||
public bool IsList => Green.IsList;
|
||||
|
||||
public bool IsMissing => Green.IsMissing;
|
||||
|
||||
public bool HasLeadingTrivia
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetLeadingTrivia().Count > 0;
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasTrailingTrivia
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetTrailingTrivia().Count > 0;
|
||||
}
|
||||
}
|
||||
|
||||
public bool ContainsDiagnostics => Green.ContainsDiagnostics;
|
||||
|
||||
public bool ContainsAnnotations => Green.ContainsAnnotations;
|
||||
|
||||
internal abstract SyntaxNode Accept(SyntaxVisitor visitor);
|
||||
|
||||
internal abstract SyntaxNode GetNodeSlot(int index);
|
||||
|
||||
internal abstract SyntaxNode GetCachedSlot(int index);
|
||||
|
||||
internal SyntaxNode GetRed(ref SyntaxNode field, int slot)
|
||||
{
|
||||
var result = field;
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
var green = Green.GetSlot(slot);
|
||||
if (green != null)
|
||||
{
|
||||
Interlocked.CompareExchange(ref field, green.CreateRed(this, GetChildPosition(slot)), null);
|
||||
result = field;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected T GetRed<T>(ref T field, int slot) where T : SyntaxNode
|
||||
{
|
||||
var result = field;
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
var green = Green.GetSlot(slot);
|
||||
if (green != null)
|
||||
{
|
||||
Interlocked.CompareExchange(ref field, (T)green.CreateRed(this, this.GetChildPosition(slot)), null);
|
||||
result = field;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal SyntaxNode GetRedElement(ref SyntaxNode element, int slot)
|
||||
{
|
||||
Debug.Assert(IsList);
|
||||
|
||||
var result = element;
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
var green = Green.GetSlot(slot);
|
||||
// passing list's parent
|
||||
Interlocked.CompareExchange(ref element, green.CreateRed(Parent, GetChildPosition(slot)), null);
|
||||
result = element;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal virtual int GetChildPosition(int index)
|
||||
{
|
||||
var offset = 0;
|
||||
var green = Green;
|
||||
while (index > 0)
|
||||
{
|
||||
index--;
|
||||
var prevSibling = GetCachedSlot(index);
|
||||
if (prevSibling != null)
|
||||
{
|
||||
return prevSibling.EndPosition + offset;
|
||||
}
|
||||
var greenChild = green.GetSlot(index);
|
||||
if (greenChild != null)
|
||||
{
|
||||
offset += greenChild.FullWidth;
|
||||
}
|
||||
}
|
||||
|
||||
return Position + offset;
|
||||
}
|
||||
|
||||
public virtual SyntaxTriviaList GetLeadingTrivia()
|
||||
{
|
||||
var firstToken = GetFirstToken();
|
||||
return firstToken != null ? firstToken.GetLeadingTrivia() : default(SyntaxTriviaList);
|
||||
}
|
||||
|
||||
public virtual SyntaxTriviaList GetTrailingTrivia()
|
||||
{
|
||||
var lastToken = GetLastToken();
|
||||
return lastToken != null ? lastToken.GetTrailingTrivia() : default(SyntaxTriviaList);
|
||||
}
|
||||
|
||||
internal SyntaxToken GetFirstToken()
|
||||
{
|
||||
return ((SyntaxToken)GetFirstTerminal());
|
||||
}
|
||||
|
||||
internal SyntaxToken GetLastToken()
|
||||
{
|
||||
return ((SyntaxToken)GetLastTerminal());
|
||||
}
|
||||
|
||||
public SyntaxNode GetFirstTerminal()
|
||||
{
|
||||
var node = this;
|
||||
|
||||
do
|
||||
{
|
||||
var foundChild = false;
|
||||
for (int i = 0, n = node.SlotCount; i < n; i++)
|
||||
{
|
||||
var child = node.GetNodeSlot(i);
|
||||
if (child != null)
|
||||
{
|
||||
node = child;
|
||||
foundChild = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundChild)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
while (node.SlotCount != 0);
|
||||
|
||||
return node == this ? this : node;
|
||||
}
|
||||
|
||||
public SyntaxNode GetLastTerminal()
|
||||
{
|
||||
var node = this;
|
||||
|
||||
do
|
||||
{
|
||||
for (var i = node.SlotCount - 1; i >= 0; i--)
|
||||
{
|
||||
var child = node.GetNodeSlot(i);
|
||||
if (child != null)
|
||||
{
|
||||
node = child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (node.SlotCount != 0);
|
||||
|
||||
return node == this ? this : node;
|
||||
}
|
||||
|
||||
public RazorDiagnostic[] GetDiagnostics()
|
||||
{
|
||||
return Green.GetDiagnostics();
|
||||
}
|
||||
|
||||
public SyntaxAnnotation[] GetAnnotations()
|
||||
{
|
||||
return Green.GetAnnotations();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Green.ToString();
|
||||
}
|
||||
|
||||
public virtual string ToFullString()
|
||||
{
|
||||
return Green.ToFullString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
// 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 System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||
{
|
||||
internal abstract class SyntaxToken : SyntaxNode
|
||||
{
|
||||
internal SyntaxToken(GreenNode green, SyntaxNode parent, int position)
|
||||
: base(green, parent, position)
|
||||
{
|
||||
}
|
||||
|
||||
internal new InternalSyntax.SyntaxToken Green => (InternalSyntax.SyntaxToken)base.Green;
|
||||
|
||||
public string Text => Green.Text;
|
||||
|
||||
internal override sealed SyntaxNode GetCachedSlot(int index)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
internal override sealed SyntaxNode GetNodeSlot(int slot)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
internal override SyntaxNode Accept(SyntaxVisitor visitor)
|
||||
{
|
||||
return visitor.VisitSyntaxToken(this);
|
||||
}
|
||||
|
||||
internal abstract SyntaxToken WithLeadingTriviaCore(SyntaxNode trivia);
|
||||
|
||||
internal abstract SyntaxToken WithTrailingTriviaCore(SyntaxNode trivia);
|
||||
|
||||
public SyntaxToken WithLeadingTrivia(SyntaxNode trivia) => WithLeadingTriviaCore(trivia);
|
||||
|
||||
public SyntaxToken WithTrailingTrivia(SyntaxNode trivia) => WithTrailingTriviaCore(trivia);
|
||||
|
||||
public SyntaxToken WithLeadingTrivia(IEnumerable<SyntaxTrivia> trivia)
|
||||
{
|
||||
var greenList = trivia?.Select(t => t.Green);
|
||||
return WithLeadingTriviaCore(Green.CreateList(greenList)?.CreateRed());
|
||||
}
|
||||
|
||||
public SyntaxToken WithTrailingTrivia(IEnumerable<SyntaxTrivia> trivia)
|
||||
{
|
||||
var greenList = trivia?.Select(t => t.Green);
|
||||
return WithTrailingTriviaCore(Green.CreateList(greenList)?.CreateRed());
|
||||
}
|
||||
|
||||
public override SyntaxTriviaList GetLeadingTrivia()
|
||||
{
|
||||
if (Green.LeadingTrivia == null)
|
||||
{
|
||||
return default(SyntaxTriviaList);
|
||||
}
|
||||
|
||||
return new SyntaxTriviaList(Green.LeadingTrivia.CreateRed(this, Position), Position);
|
||||
}
|
||||
|
||||
public override SyntaxTriviaList GetTrailingTrivia()
|
||||
{
|
||||
var trailingGreen = Green.TrailingTrivia;
|
||||
if (trailingGreen == null)
|
||||
{
|
||||
return default(SyntaxTriviaList);
|
||||
}
|
||||
|
||||
var leading = Green.LeadingTrivia;
|
||||
int index = 0;
|
||||
if (leading != null)
|
||||
{
|
||||
index = leading.IsList ? leading.SlotCount : 1;
|
||||
}
|
||||
int trailingPosition = Position + FullWidth;
|
||||
trailingPosition -= trailingGreen.FullWidth;
|
||||
|
||||
return new SyntaxTriviaList(trailingGreen.CreateRed(this, trailingPosition), trailingPosition, index);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Text;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
// 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;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||
{
|
||||
internal class SyntaxTrivia : SyntaxNode
|
||||
{
|
||||
internal SyntaxTrivia(GreenNode green, SyntaxNode parent, int position)
|
||||
: base(green, parent, position)
|
||||
{
|
||||
}
|
||||
|
||||
internal new InternalSyntax.SyntaxTrivia Green => (InternalSyntax.SyntaxTrivia)base.Green;
|
||||
|
||||
public string Text => Green.Text;
|
||||
|
||||
internal override sealed SyntaxNode GetCachedSlot(int index)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
internal override sealed SyntaxNode GetNodeSlot(int slot)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
internal override SyntaxNode Accept(SyntaxVisitor visitor)
|
||||
{
|
||||
return visitor.VisitSyntaxTrivia(this);
|
||||
}
|
||||
|
||||
public sealed override SyntaxTriviaList GetTrailingTrivia()
|
||||
{
|
||||
return default(SyntaxTriviaList);
|
||||
}
|
||||
|
||||
public sealed override SyntaxTriviaList GetLeadingTrivia()
|
||||
{
|
||||
return default(SyntaxTriviaList);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Text;
|
||||
}
|
||||
|
||||
public sealed override string ToFullString()
|
||||
{
|
||||
return Text;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,785 @@
|
|||
// 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 System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.Extensions.Internal;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||
{
|
||||
[StructLayout(LayoutKind.Auto)]
|
||||
internal readonly struct SyntaxTriviaList : IEquatable<SyntaxTriviaList>, IReadOnlyList<SyntaxTrivia>
|
||||
{
|
||||
public static SyntaxTriviaList Empty => default(SyntaxTriviaList);
|
||||
|
||||
internal SyntaxTriviaList(SyntaxNode node, int position, int index = 0)
|
||||
{
|
||||
Node = node;
|
||||
Position = position;
|
||||
Index = index;
|
||||
}
|
||||
|
||||
internal SyntaxTriviaList(SyntaxNode node)
|
||||
{
|
||||
Node = node;
|
||||
Position = node.Position;
|
||||
Index = 0;
|
||||
}
|
||||
|
||||
public SyntaxTriviaList(SyntaxTrivia trivia)
|
||||
{
|
||||
Node = trivia;
|
||||
Position = 0;
|
||||
Index = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a list of trivia.
|
||||
/// </summary>
|
||||
/// <param name="trivias">An array of trivia.</param>
|
||||
public SyntaxTriviaList(params SyntaxTrivia[] trivias)
|
||||
: this(CreateNode(trivias), 0, 0)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a list of trivia.
|
||||
/// </summary>
|
||||
/// <param name="trivias">A sequence of trivia.</param>
|
||||
public SyntaxTriviaList(IEnumerable<SyntaxTrivia> trivias)
|
||||
: this(SyntaxTriviaListBuilder.Create(trivias).Node, 0, 0)
|
||||
{
|
||||
}
|
||||
|
||||
private static SyntaxNode CreateNode(SyntaxTrivia[] trivias)
|
||||
{
|
||||
if (trivias == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var builder = new SyntaxTriviaListBuilder(trivias.Length);
|
||||
builder.Add(trivias);
|
||||
return builder.ToList().Node;
|
||||
}
|
||||
|
||||
internal SyntaxNode Node { get; }
|
||||
|
||||
internal int Position { get; }
|
||||
|
||||
internal int Index { get; }
|
||||
|
||||
public int Count
|
||||
{
|
||||
get { return Node == null ? 0 : (Node.IsList ? Node.SlotCount : 1); }
|
||||
}
|
||||
|
||||
public SyntaxTrivia ElementAt(int index)
|
||||
{
|
||||
return this[index];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the trivia at the specified index.
|
||||
/// </summary>
|
||||
/// <param name="index">The zero-based index of the trivia to get.</param>
|
||||
/// <returns>The token at the specified index.</returns>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// <paramref name="index" /> is less than 0.-or-<paramref name="index" /> is equal to or greater than <see cref="Count" />. </exception>
|
||||
public SyntaxTrivia this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Node != null)
|
||||
{
|
||||
if (Node.IsList)
|
||||
{
|
||||
if (unchecked((uint)index < (uint)Node.SlotCount))
|
||||
{
|
||||
return Node.GetNodeSlot(index) as SyntaxTrivia;
|
||||
}
|
||||
}
|
||||
else if (index == 0)
|
||||
{
|
||||
return Node as SyntaxTrivia;
|
||||
}
|
||||
}
|
||||
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The absolute span of the list elements in characters, including the leading and trailing trivia of the first and last elements.
|
||||
/// </summary>
|
||||
public TextSpan FullSpan
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Node == null)
|
||||
{
|
||||
return default(TextSpan);
|
||||
}
|
||||
|
||||
return new TextSpan(Position, Node.FullWidth);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The absolute span of the list elements in characters, not including the leading and trailing trivia of the first and last elements.
|
||||
/// </summary>
|
||||
public TextSpan Span
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Node == null)
|
||||
{
|
||||
return default(TextSpan);
|
||||
}
|
||||
|
||||
return TextSpan.FromBounds(Position + Node.Green.GetLeadingTriviaWidth(),
|
||||
Position + Node.FullWidth - Node.Green.GetTrailingTriviaWidth());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the first trivia in the list.
|
||||
/// </summary>
|
||||
/// <returns>The first trivia in the list.</returns>
|
||||
/// <exception cref="InvalidOperationException">The list is empty.</exception>
|
||||
public SyntaxTrivia First()
|
||||
{
|
||||
if (Any())
|
||||
{
|
||||
return this[0];
|
||||
}
|
||||
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the last trivia in the list.
|
||||
/// </summary>
|
||||
/// <returns>The last trivia in the list.</returns>
|
||||
/// <exception cref="InvalidOperationException">The list is empty.</exception>
|
||||
public SyntaxTrivia Last()
|
||||
{
|
||||
if (Any())
|
||||
{
|
||||
return this[Count - 1];
|
||||
}
|
||||
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Does this list have any items.
|
||||
/// </summary>
|
||||
public bool Any()
|
||||
{
|
||||
return Node != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list which contains all elements of <see cref="SyntaxTriviaList"/> in reversed order.
|
||||
/// </summary>
|
||||
/// <returns><see cref="Reversed"/> which contains all elements of <see cref="SyntaxTriviaList"/> in reversed order</returns>
|
||||
public Reversed Reverse()
|
||||
{
|
||||
return new Reversed(this);
|
||||
}
|
||||
|
||||
public Enumerator GetEnumerator()
|
||||
{
|
||||
return new Enumerator(this);
|
||||
}
|
||||
|
||||
public int IndexOf(SyntaxTrivia triviaInList)
|
||||
{
|
||||
for (int i = 0, n = Count; i < n; i++)
|
||||
{
|
||||
var trivia = this[i];
|
||||
if (trivia == triviaInList)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
internal int IndexOf(SyntaxKind kind)
|
||||
{
|
||||
for (int i = 0, n = Count; i < n; i++)
|
||||
{
|
||||
if (this[i].Kind == kind)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="SyntaxTriviaList"/> with the specified trivia added to the end.
|
||||
/// </summary>
|
||||
/// <param name="trivia">The trivia to add.</param>
|
||||
public SyntaxTriviaList Add(SyntaxTrivia trivia)
|
||||
{
|
||||
return Insert(Count, trivia);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="SyntaxTriviaList"/> with the specified trivia added to the end.
|
||||
/// </summary>
|
||||
/// <param name="trivia">The trivia to add.</param>
|
||||
public SyntaxTriviaList AddRange(IEnumerable<SyntaxTrivia> trivia)
|
||||
{
|
||||
return InsertRange(Count, trivia);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="SyntaxTriviaList"/> with the specified trivia inserted at the index.
|
||||
/// </summary>
|
||||
/// <param name="index">The index in the list to insert the trivia at.</param>
|
||||
/// <param name="trivia">The trivia to insert.</param>
|
||||
public SyntaxTriviaList Insert(int index, SyntaxTrivia trivia)
|
||||
{
|
||||
if (trivia == default(SyntaxTrivia))
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(trivia));
|
||||
}
|
||||
|
||||
return InsertRange(index, new[] { trivia });
|
||||
}
|
||||
|
||||
private static readonly ObjectPool<SyntaxTriviaListBuilder> s_builderPool =
|
||||
new ObjectPool<SyntaxTriviaListBuilder>(() => SyntaxTriviaListBuilder.Create());
|
||||
|
||||
private static SyntaxTriviaListBuilder GetBuilder()
|
||||
=> s_builderPool.Allocate();
|
||||
|
||||
private static void ClearAndFreeBuilder(SyntaxTriviaListBuilder builder)
|
||||
{
|
||||
// It's possible someone might create a list with a huge amount of trivia
|
||||
// in it. We don't want to hold onto such items forever. So only cache
|
||||
// reasonably sized lists. In IDE testing, around 99% of all trivia lists
|
||||
// were 16 or less elements.
|
||||
const int MaxBuilderCount = 16;
|
||||
if (builder.Count <= MaxBuilderCount)
|
||||
{
|
||||
builder.Clear();
|
||||
s_builderPool.Free(builder);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="SyntaxTriviaList"/> with the specified trivia inserted at the index.
|
||||
/// </summary>
|
||||
/// <param name="index">The index in the list to insert the trivia at.</param>
|
||||
/// <param name="trivia">The trivia to insert.</param>
|
||||
public SyntaxTriviaList InsertRange(int index, IEnumerable<SyntaxTrivia> trivia)
|
||||
{
|
||||
var thisCount = Count;
|
||||
if (index < 0 || index > thisCount)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
}
|
||||
|
||||
if (trivia == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(trivia));
|
||||
}
|
||||
|
||||
// Just return ourselves if we're not being asked to add anything.
|
||||
if (trivia is ICollection<SyntaxTrivia> triviaCollection && triviaCollection.Count == 0)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
var builder = GetBuilder();
|
||||
try
|
||||
{
|
||||
for (var i = 0; i < index; i++)
|
||||
{
|
||||
builder.Add(this[i]);
|
||||
}
|
||||
|
||||
builder.AddRange(trivia);
|
||||
|
||||
for (var i = index; i < thisCount; i++)
|
||||
{
|
||||
builder.Add(this[i]);
|
||||
}
|
||||
|
||||
return builder.Count == thisCount ? this : builder.ToList();
|
||||
}
|
||||
finally
|
||||
{
|
||||
ClearAndFreeBuilder(builder);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="SyntaxTriviaList"/> with the element at the specified index removed.
|
||||
/// </summary>
|
||||
/// <param name="index">The index identifying the element to remove.</param>
|
||||
public SyntaxTriviaList RemoveAt(int index)
|
||||
{
|
||||
if (index < 0 || index >= Count)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
}
|
||||
|
||||
var list = this.ToList();
|
||||
list.RemoveAt(index);
|
||||
return new SyntaxTriviaList(list);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="SyntaxTriviaList"/> with the specified element removed.
|
||||
/// </summary>
|
||||
/// <param name="triviaInList">The trivia element to remove.</param>
|
||||
public SyntaxTriviaList Remove(SyntaxTrivia triviaInList)
|
||||
{
|
||||
var index = IndexOf(triviaInList);
|
||||
if (index >= 0 && index < Count)
|
||||
{
|
||||
return RemoveAt(index);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="SyntaxTriviaList"/> with the specified element replaced with new trivia.
|
||||
/// </summary>
|
||||
/// <param name="triviaInList">The trivia element to replace.</param>
|
||||
/// <param name="newTrivia">The trivia to replace the element with.</param>
|
||||
public SyntaxTriviaList Replace(SyntaxTrivia triviaInList, SyntaxTrivia newTrivia)
|
||||
{
|
||||
if (newTrivia == default(SyntaxTrivia))
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(newTrivia));
|
||||
}
|
||||
|
||||
return ReplaceRange(triviaInList, new[] { newTrivia });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="SyntaxTriviaList"/> with the specified element replaced with new trivia.
|
||||
/// </summary>
|
||||
/// <param name="triviaInList">The trivia element to replace.</param>
|
||||
/// <param name="newTrivia">The trivia to replace the element with.</param>
|
||||
public SyntaxTriviaList ReplaceRange(SyntaxTrivia triviaInList, IEnumerable<SyntaxTrivia> newTrivia)
|
||||
{
|
||||
var index = IndexOf(triviaInList);
|
||||
if (index >= 0 && index < Count)
|
||||
{
|
||||
var list = this.ToList();
|
||||
list.RemoveAt(index);
|
||||
list.InsertRange(index, newTrivia);
|
||||
return new SyntaxTriviaList(list);
|
||||
}
|
||||
|
||||
throw new ArgumentOutOfRangeException(nameof(triviaInList));
|
||||
}
|
||||
|
||||
// for debugging
|
||||
private SyntaxTrivia[] Nodes => this.ToArray();
|
||||
|
||||
IEnumerator<SyntaxTrivia> IEnumerable<SyntaxTrivia>.GetEnumerator()
|
||||
{
|
||||
if (Node == null)
|
||||
{
|
||||
return SpecializedCollections.EmptyEnumerator<SyntaxTrivia>();
|
||||
}
|
||||
|
||||
return new EnumeratorImpl(this);
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
if (Node == null)
|
||||
{
|
||||
return SpecializedCollections.EmptyEnumerator<SyntaxTrivia>();
|
||||
}
|
||||
|
||||
return new EnumeratorImpl(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// get the green node at the specific slot
|
||||
/// </summary>
|
||||
private SyntaxNode GetNodeAt(int i)
|
||||
{
|
||||
return GetNodeAt(Node, i);
|
||||
}
|
||||
|
||||
private static SyntaxNode GetNodeAt(SyntaxNode node, int i)
|
||||
{
|
||||
Debug.Assert(node.IsList || (i == 0 && !node.IsList));
|
||||
return node.IsList ? node.GetNodeSlot(i) : node;
|
||||
}
|
||||
|
||||
public bool Equals(SyntaxTriviaList other)
|
||||
{
|
||||
return Node == other.Node && Index == other.Index;
|
||||
}
|
||||
|
||||
public static bool operator ==(SyntaxTriviaList left, SyntaxTriviaList right)
|
||||
{
|
||||
return left.Equals(right);
|
||||
}
|
||||
|
||||
public static bool operator !=(SyntaxTriviaList left, SyntaxTriviaList right)
|
||||
{
|
||||
return !left.Equals(right);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return (obj is SyntaxTriviaList) && Equals((SyntaxTriviaList)obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
var hash = HashCodeCombiner.Start();
|
||||
hash.Add(Node);
|
||||
hash.Add(Index);
|
||||
return hash.CombinedHash;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy <paramref name="count"/> number of items starting at <paramref name="offset"/> from this list into <paramref name="array"/> starting at <paramref name="arrayOffset"/>.
|
||||
/// </summary>
|
||||
internal void CopyTo(int offset, SyntaxTrivia[] array, int arrayOffset, int count)
|
||||
{
|
||||
if (offset < 0 || count < 0 || Count < offset + count)
|
||||
{
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
|
||||
if (count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// get first one without creating any red node
|
||||
var first = this[offset];
|
||||
array[arrayOffset] = first;
|
||||
|
||||
// calculate trivia position from the first ourselves from now on
|
||||
var position = first.Position;
|
||||
var current = first;
|
||||
|
||||
for (var i = 1; i < count; i++)
|
||||
{
|
||||
position += current.FullWidth;
|
||||
current = GetNodeAt(offset + i) as SyntaxTrivia;
|
||||
|
||||
array[arrayOffset + i] = current;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Node != null ? Node.ToString() : string.Empty;
|
||||
}
|
||||
|
||||
public string ToFullString()
|
||||
{
|
||||
return Node != null ? Node.ToFullString() : string.Empty;
|
||||
}
|
||||
|
||||
public static SyntaxTriviaList Create(SyntaxTrivia trivia)
|
||||
{
|
||||
return new SyntaxTriviaList(trivia);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reversed enumerable.
|
||||
/// </summary>
|
||||
public struct Reversed : IEnumerable<SyntaxTrivia>, IEquatable<Reversed>
|
||||
{
|
||||
private SyntaxTriviaList _list;
|
||||
|
||||
public Reversed(in SyntaxTriviaList list)
|
||||
{
|
||||
_list = list;
|
||||
}
|
||||
|
||||
public Enumerator GetEnumerator()
|
||||
{
|
||||
return new Enumerator(in _list);
|
||||
}
|
||||
|
||||
IEnumerator<SyntaxTrivia> IEnumerable<SyntaxTrivia>.GetEnumerator()
|
||||
{
|
||||
if (_list.Count == 0)
|
||||
{
|
||||
return SpecializedCollections.EmptyEnumerator<SyntaxTrivia>();
|
||||
}
|
||||
|
||||
return new ReversedEnumeratorImpl(in _list);
|
||||
}
|
||||
|
||||
IEnumerator
|
||||
IEnumerable.GetEnumerator()
|
||||
{
|
||||
if (_list.Count == 0)
|
||||
{
|
||||
return SpecializedCollections.EmptyEnumerator<SyntaxTrivia>();
|
||||
}
|
||||
|
||||
return new ReversedEnumeratorImpl(in _list);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return _list.GetHashCode();
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is Reversed && Equals((Reversed)obj);
|
||||
}
|
||||
|
||||
public bool Equals(Reversed other)
|
||||
{
|
||||
return _list.Equals(other._list);
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Auto)]
|
||||
public struct Enumerator
|
||||
{
|
||||
private readonly SyntaxNode _singleNodeOrList;
|
||||
private readonly int _baseIndex;
|
||||
private readonly int _count;
|
||||
|
||||
private int _index;
|
||||
private SyntaxNode _current;
|
||||
private int _position;
|
||||
|
||||
public Enumerator(in SyntaxTriviaList list)
|
||||
: this()
|
||||
{
|
||||
if (list.Any())
|
||||
{
|
||||
_singleNodeOrList = list.Node;
|
||||
_baseIndex = list.Index;
|
||||
_count = list.Count;
|
||||
|
||||
_index = _count;
|
||||
_current = null;
|
||||
|
||||
var last = list.Last();
|
||||
_position = last.Position + last.FullWidth;
|
||||
}
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
if (_count == 0 || _index <= 0)
|
||||
{
|
||||
_current = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
_index--;
|
||||
|
||||
_current = GetNodeAt(_singleNodeOrList, _index);
|
||||
_position -= _current.FullWidth;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public SyntaxTrivia Current
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_current == null)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
return (SyntaxTrivia)_current;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ReversedEnumeratorImpl : IEnumerator<SyntaxTrivia>
|
||||
{
|
||||
private Enumerator _enumerator;
|
||||
|
||||
// SyntaxTriviaList is a relatively big struct so is passed as ref
|
||||
internal ReversedEnumeratorImpl(in SyntaxTriviaList list)
|
||||
{
|
||||
_enumerator = new Enumerator(in list);
|
||||
}
|
||||
|
||||
public SyntaxTrivia Current => _enumerator.Current;
|
||||
|
||||
object IEnumerator.Current => _enumerator.Current;
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
return _enumerator.MoveNext();
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Auto)]
|
||||
public struct Enumerator
|
||||
{
|
||||
private SyntaxNode _singleNodeOrList;
|
||||
private int _baseIndex;
|
||||
private int _count;
|
||||
|
||||
private int _index;
|
||||
private SyntaxNode _current;
|
||||
private int _position;
|
||||
|
||||
internal Enumerator(in SyntaxTriviaList list)
|
||||
{
|
||||
_singleNodeOrList = list.Node;
|
||||
_baseIndex = list.Index;
|
||||
_count = list.Count;
|
||||
|
||||
_index = -1;
|
||||
_current = null;
|
||||
_position = list.Position;
|
||||
}
|
||||
|
||||
private void InitializeFrom(SyntaxNode node, int index, int position)
|
||||
{
|
||||
_singleNodeOrList = node;
|
||||
_baseIndex = index;
|
||||
_count = node.IsList ? node.SlotCount : 1;
|
||||
|
||||
_index = -1;
|
||||
_current = null;
|
||||
_position = position;
|
||||
}
|
||||
|
||||
// PERF: Used to initialize an enumerator for leading trivia directly from a token.
|
||||
// This saves constructing an intermediate SyntaxTriviaList. Also, passing token
|
||||
// by ref since it's a non-trivial struct
|
||||
internal void InitializeFromLeadingTrivia(in SyntaxToken token)
|
||||
{
|
||||
InitializeFrom(token.GetLeadingTrivia().Node, 0, token.Position);
|
||||
}
|
||||
|
||||
// PERF: Used to initialize an enumerator for trailing trivia directly from a token.
|
||||
// This saves constructing an intermediate SyntaxTriviaList. Also, passing token
|
||||
// by ref since it's a non-trivial struct
|
||||
internal void InitializeFromTrailingTrivia(in SyntaxToken token)
|
||||
{
|
||||
var leading = token.GetLeadingTrivia().Node;
|
||||
var index = 0;
|
||||
if (leading != null)
|
||||
{
|
||||
index = leading.IsList ? leading.SlotCount : 1;
|
||||
}
|
||||
|
||||
var trailing = token.GetTrailingTrivia().Node;
|
||||
var trailingPosition = token.Position + token.FullWidth;
|
||||
if (trailing != null)
|
||||
{
|
||||
trailingPosition -= trailing.FullWidth;
|
||||
}
|
||||
|
||||
InitializeFrom(trailing, index, trailingPosition);
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
var newIndex = _index + 1;
|
||||
if (newIndex >= _count)
|
||||
{
|
||||
// invalidate iterator
|
||||
_current = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
_index = newIndex;
|
||||
|
||||
if (_current != null)
|
||||
{
|
||||
_position += _current.FullWidth;
|
||||
}
|
||||
|
||||
_current = GetNodeAt(_singleNodeOrList, newIndex);
|
||||
return true;
|
||||
}
|
||||
|
||||
public SyntaxTrivia Current
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_current == null)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
return _current as SyntaxTrivia;
|
||||
}
|
||||
}
|
||||
|
||||
internal bool TryMoveNextAndGetCurrent(out SyntaxTrivia current)
|
||||
{
|
||||
if (!MoveNext())
|
||||
{
|
||||
current = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
current = _current as SyntaxTrivia;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private class EnumeratorImpl : IEnumerator<SyntaxTrivia>
|
||||
{
|
||||
private Enumerator _enumerator;
|
||||
|
||||
// SyntaxTriviaList is a relatively big struct so is passed as ref
|
||||
internal EnumeratorImpl(in SyntaxTriviaList list)
|
||||
{
|
||||
_enumerator = new Enumerator(list);
|
||||
}
|
||||
|
||||
public SyntaxTrivia Current => _enumerator.Current;
|
||||
|
||||
object IEnumerator.Current => _enumerator.Current;
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
return _enumerator.MoveNext();
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
// 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 System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||
{
|
||||
internal class SyntaxTriviaListBuilder
|
||||
{
|
||||
private SyntaxTrivia[] _nodes;
|
||||
|
||||
public SyntaxTriviaListBuilder(int size)
|
||||
{
|
||||
_nodes = new SyntaxTrivia[size];
|
||||
}
|
||||
|
||||
public static SyntaxTriviaListBuilder Create()
|
||||
{
|
||||
return new SyntaxTriviaListBuilder(4);
|
||||
}
|
||||
|
||||
public static SyntaxTriviaList Create(IEnumerable<SyntaxTrivia> trivia)
|
||||
{
|
||||
if (trivia == null)
|
||||
{
|
||||
return new SyntaxTriviaList();
|
||||
}
|
||||
|
||||
var builder = Create();
|
||||
builder.AddRange(trivia);
|
||||
return builder.ToList();
|
||||
}
|
||||
|
||||
public int Count { get; private set; }
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
Count = 0;
|
||||
}
|
||||
|
||||
public SyntaxTrivia this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (index < 0 || index > Count)
|
||||
{
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
|
||||
return _nodes[index];
|
||||
}
|
||||
}
|
||||
|
||||
public void AddRange(IEnumerable<SyntaxTrivia> items)
|
||||
{
|
||||
if (items != null)
|
||||
{
|
||||
foreach (var item in items)
|
||||
{
|
||||
Add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public SyntaxTriviaListBuilder Add(SyntaxTrivia item)
|
||||
{
|
||||
if (_nodes == null || Count >= _nodes.Length)
|
||||
{
|
||||
Grow(Count == 0 ? 8 : _nodes.Length * 2);
|
||||
}
|
||||
|
||||
_nodes[Count++] = item;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void Add(SyntaxTrivia[] items)
|
||||
{
|
||||
Add(items, 0, items.Length);
|
||||
}
|
||||
|
||||
public void Add(SyntaxTrivia[] items, int offset, int length)
|
||||
{
|
||||
if (_nodes == null || Count + length > _nodes.Length)
|
||||
{
|
||||
Grow(Count + length);
|
||||
}
|
||||
|
||||
Array.Copy(items, offset, _nodes, Count, length);
|
||||
Count += length;
|
||||
}
|
||||
|
||||
public void Add(in SyntaxTriviaList list)
|
||||
{
|
||||
Add(list, 0, list.Count);
|
||||
}
|
||||
|
||||
public void Add(in SyntaxTriviaList list, int offset, int length)
|
||||
{
|
||||
if (_nodes == null || Count + length > _nodes.Length)
|
||||
{
|
||||
Grow(Count + length);
|
||||
}
|
||||
|
||||
list.CopyTo(offset, _nodes, Count, length);
|
||||
Count += length;
|
||||
}
|
||||
|
||||
private void Grow(int size)
|
||||
{
|
||||
var tmp = new SyntaxTrivia[size];
|
||||
Array.Copy(_nodes, tmp, _nodes.Length);
|
||||
_nodes = tmp;
|
||||
}
|
||||
|
||||
public static implicit operator SyntaxTriviaList(SyntaxTriviaListBuilder builder)
|
||||
{
|
||||
return builder.ToList();
|
||||
}
|
||||
|
||||
public SyntaxTriviaList ToList()
|
||||
{
|
||||
if (Count > 0)
|
||||
{
|
||||
var tmp = new ArrayElement<GreenNode>[Count];
|
||||
for (var i = 0; i < Count; i++)
|
||||
{
|
||||
tmp[i].Value = _nodes[i].Green;
|
||||
}
|
||||
return new SyntaxTriviaList(InternalSyntax.SyntaxList.List(tmp).CreateRed(), position: 0, index: 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return default(SyntaxTriviaList);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||
{
|
||||
internal abstract class SyntaxVisitor
|
||||
{
|
||||
public virtual SyntaxNode Visit(SyntaxNode node)
|
||||
{
|
||||
if (node != null)
|
||||
{
|
||||
return node.Accept(this);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public virtual SyntaxNode VisitSyntaxNode(SyntaxNode node)
|
||||
{
|
||||
return node;
|
||||
}
|
||||
|
||||
public virtual SyntaxNode VisitHtmlNode(HtmlNodeSyntax node)
|
||||
{
|
||||
return VisitSyntaxNode(node);
|
||||
}
|
||||
|
||||
public virtual SyntaxNode VisitHtmlText(HtmlTextSyntax node)
|
||||
{
|
||||
return VisitHtmlNode(node);
|
||||
}
|
||||
|
||||
public virtual SyntaxToken VisitSyntaxToken(SyntaxToken token)
|
||||
{
|
||||
return token;
|
||||
}
|
||||
|
||||
public virtual SyntaxTrivia VisitSyntaxTrivia(SyntaxTrivia trivia)
|
||||
{
|
||||
return trivia;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,261 @@
|
|||
// 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.Extensions.Internal;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||
{
|
||||
/// <summary>
|
||||
/// Immutable abstract representation of a span of text. For example, in an error diagnostic that reports a
|
||||
/// location, it could come from a parsed string, text from a tool editor buffer, etc.
|
||||
/// </summary>
|
||||
internal readonly struct TextSpan : IEquatable<TextSpan>, IComparable<TextSpan>
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a TextSpan instance beginning with the position Start and having the Length
|
||||
/// specified with <paramref name="length" />.
|
||||
/// </summary>
|
||||
public TextSpan(int start, int length)
|
||||
{
|
||||
if (start < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(start));
|
||||
}
|
||||
|
||||
if (start + length < start)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(length));
|
||||
}
|
||||
|
||||
Start = start;
|
||||
Length = length;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start point of the span.
|
||||
/// </summary>
|
||||
public int Start { get; }
|
||||
|
||||
/// <summary>
|
||||
/// End of the span.
|
||||
/// </summary>
|
||||
public int End => Start + Length;
|
||||
|
||||
/// <summary>
|
||||
/// Length of the span.
|
||||
/// </summary>
|
||||
public int Length { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether or not the span is empty.
|
||||
/// </summary>
|
||||
public bool IsEmpty => Length == 0;
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the position lies within the span.
|
||||
/// </summary>
|
||||
/// <param name="position">
|
||||
/// The position to check.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the position is greater than or equal to Start and strictly less
|
||||
/// than End, otherwise <c>false</c>.
|
||||
/// </returns>
|
||||
public bool Contains(int position)
|
||||
{
|
||||
return unchecked((uint)(position - Start) < (uint)Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether <paramref name="span"/> falls completely within this span.
|
||||
/// </summary>
|
||||
/// <param name="span">
|
||||
/// The span to check.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the specified span falls completely within this span, otherwise <c>false</c>.
|
||||
/// </returns>
|
||||
public bool Contains(TextSpan span)
|
||||
{
|
||||
return span.Start >= Start && span.End <= End;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether <paramref name="span"/> overlaps this span. Two spans are considered to overlap
|
||||
/// if they have positions in common and neither is empty. Empty spans do not overlap with any
|
||||
/// other span.
|
||||
/// </summary>
|
||||
/// <param name="span">
|
||||
/// The span to check.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the spans overlap, otherwise <c>false</c>.
|
||||
/// </returns>
|
||||
public bool OverlapsWith(TextSpan span)
|
||||
{
|
||||
var overlapStart = Math.Max(Start, span.Start);
|
||||
var overlapEnd = Math.Min(End, span.End);
|
||||
|
||||
return overlapStart < overlapEnd;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the overlap with the given span, or null if there is no overlap.
|
||||
/// </summary>
|
||||
/// <param name="span">
|
||||
/// The span to check.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The overlap of the spans, or null if the overlap is empty.
|
||||
/// </returns>
|
||||
public TextSpan? Overlap(TextSpan span)
|
||||
{
|
||||
var overlapStart = Math.Max(Start, span.Start);
|
||||
var overlapEnd = Math.Min(End, span.End);
|
||||
|
||||
return overlapStart < overlapEnd
|
||||
? FromBounds(overlapStart, overlapEnd)
|
||||
: (TextSpan?)null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether <paramref name="span"/> intersects this span. Two spans are considered to
|
||||
/// intersect if they have positions in common or the end of one span
|
||||
/// coincides with the start of the other span.
|
||||
/// </summary>
|
||||
/// <param name="span">
|
||||
/// The span to check.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the spans intersect, otherwise <c>false</c>.
|
||||
/// </returns>
|
||||
public bool IntersectsWith(TextSpan span)
|
||||
{
|
||||
return span.Start <= End && span.End >= Start;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether <paramref name="position"/> intersects this span.
|
||||
/// A position is considered to intersect if it is between the start and
|
||||
/// end positions (inclusive) of this span.
|
||||
/// </summary>
|
||||
/// <param name="position">
|
||||
/// The position to check.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the position intersects, otherwise <c>false</c>.
|
||||
/// </returns>
|
||||
public bool IntersectsWith(int position)
|
||||
{
|
||||
return unchecked((uint)(position - Start) <= (uint)Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the intersection with the given span, or null if there is no intersection.
|
||||
/// </summary>
|
||||
/// <param name="span">
|
||||
/// The span to check.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The intersection of the spans, or null if the intersection is empty.
|
||||
/// </returns>
|
||||
public TextSpan? Intersection(TextSpan span)
|
||||
{
|
||||
var intersectStart = Math.Max(Start, span.Start);
|
||||
var intersectEnd = Math.Min(End, span.End);
|
||||
|
||||
return intersectStart <= intersectEnd
|
||||
? FromBounds(intersectStart, intersectEnd)
|
||||
: (TextSpan?)null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="TextSpan"/> from <paramref name="start" /> and <paramref
|
||||
/// name="end"/> positions as opposed to a position and length.
|
||||
///
|
||||
/// The returned TextSpan contains the range with <paramref name="start"/> inclusive,
|
||||
/// and <paramref name="end"/> exclusive.
|
||||
/// </summary>
|
||||
public static TextSpan FromBounds(int start, int end)
|
||||
{
|
||||
if (start < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(start), "start must not be negative");
|
||||
}
|
||||
|
||||
if (end < start)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(end), "end must not be less than start");
|
||||
}
|
||||
|
||||
return new TextSpan(start, end - start);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if two instances of <see cref="TextSpan"/> are the same.
|
||||
/// </summary>
|
||||
public static bool operator ==(TextSpan left, TextSpan right)
|
||||
{
|
||||
return left.Equals(right);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if two instances of <see cref="TextSpan"/> are different.
|
||||
/// </summary>
|
||||
public static bool operator !=(TextSpan left, TextSpan right)
|
||||
{
|
||||
return !left.Equals(right);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if current instance of <see cref="TextSpan"/> is equal to another.
|
||||
/// </summary>
|
||||
public bool Equals(TextSpan other)
|
||||
{
|
||||
return Start == other.Start && Length == other.Length;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if current instance of <see cref="TextSpan"/> is equal to another.
|
||||
/// </summary>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is TextSpan && Equals((TextSpan)obj);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Produces a hash code for <see cref="TextSpan"/>.
|
||||
/// </summary>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
var combiner = new HashCodeCombiner();
|
||||
combiner.Add(Start);
|
||||
combiner.Add(Length);
|
||||
|
||||
return combiner.CombinedHash;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides a string representation for <see cref="TextSpan"/>.
|
||||
/// </summary>
|
||||
public override string ToString()
|
||||
{
|
||||
return $"[{Start}..{End})";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compares current instance of <see cref="TextSpan"/> with another.
|
||||
/// </summary>
|
||||
public int CompareTo(TextSpan other)
|
||||
{
|
||||
var diff = Start - other.Start;
|
||||
if (diff != 0)
|
||||
{
|
||||
return diff;
|
||||
}
|
||||
|
||||
return Length - other.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||
{
|
||||
internal class UnknownTokenSyntax : SyntaxToken
|
||||
{
|
||||
internal UnknownTokenSyntax(GreenNode green, SyntaxNode parent, int position)
|
||||
: base(green, parent, position)
|
||||
{
|
||||
}
|
||||
|
||||
internal new InternalSyntax.UnknownTokenSyntax Green => (InternalSyntax.UnknownTokenSyntax)base.Green;
|
||||
|
||||
public string Value => Text;
|
||||
|
||||
internal override SyntaxToken WithLeadingTriviaCore(SyntaxNode trivia)
|
||||
{
|
||||
return new InternalSyntax.UnknownTokenSyntax(Text, trivia?.Green, GetTrailingTrivia().Node?.Green).CreateRed(Parent, Position) as UnknownTokenSyntax;
|
||||
}
|
||||
|
||||
internal override SyntaxToken WithTrailingTriviaCore(SyntaxNode trivia)
|
||||
{
|
||||
return new InternalSyntax.UnknownTokenSyntax(Text, GetLeadingTrivia().Node?.Green, trivia?.Green).CreateRed(Parent, Position) as UnknownTokenSyntax;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Syntax
|
||||
{
|
||||
internal class WhitespaceTokenSyntax : SyntaxToken
|
||||
{
|
||||
internal WhitespaceTokenSyntax(GreenNode green, SyntaxNode parent, int position)
|
||||
: base(green, parent, position)
|
||||
{
|
||||
}
|
||||
|
||||
internal new InternalSyntax.WhitespaceTokenSyntax Green => (InternalSyntax.WhitespaceTokenSyntax)base.Green;
|
||||
|
||||
public string Value => Text;
|
||||
|
||||
internal override SyntaxToken WithLeadingTriviaCore(SyntaxNode trivia)
|
||||
{
|
||||
return new InternalSyntax.WhitespaceTokenSyntax(Text, trivia?.Green, GetTrailingTrivia().Node?.Green).CreateRed(Parent, Position) as WhitespaceTokenSyntax;
|
||||
}
|
||||
|
||||
internal override SyntaxToken WithTrailingTriviaCore(SyntaxNode trivia)
|
||||
{
|
||||
return new InternalSyntax.WhitespaceTokenSyntax(Text, GetLeadingTrivia().Node?.Green, trivia?.Green).CreateRed(Parent, Position) as WhitespaceTokenSyntax;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Razor.LanguageServer.StrongNamed, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.VisualStudio.LiveShare.Razor.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.VisualStudio.LiveShare.Razor, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Razor.Performance, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Razor.LanguageServer.StrongNamed, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.VisualStudio.LiveShare.Razor, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.VisualStudio.LiveShare.Razor.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.CodeAnalysis.Razor.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,98 @@
|
|||
// 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 System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.AspNetCore.Razor.Language.Legacy;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
[System.Composition.Shared]
|
||||
[Export(typeof(RazorCompletionFactsService))]
|
||||
internal class DefaultRazorCompletionFactsService : RazorCompletionFactsService
|
||||
{
|
||||
private static readonly IEnumerable<DirectiveDescriptor> DefaultDirectives = new[]
|
||||
{
|
||||
CSharpCodeParser.AddTagHelperDirectiveDescriptor,
|
||||
CSharpCodeParser.RemoveTagHelperDirectiveDescriptor,
|
||||
CSharpCodeParser.TagHelperPrefixDirectiveDescriptor,
|
||||
};
|
||||
|
||||
public override IReadOnlyList<RazorCompletionItem> GetCompletionItems(RazorSyntaxTree syntaxTree, SourceSpan location)
|
||||
{
|
||||
var completionItems = new List<RazorCompletionItem>();
|
||||
|
||||
if (AtDirectiveCompletionPoint(syntaxTree, location))
|
||||
{
|
||||
var directiveCompletions = GetDirectiveCompletionItems(syntaxTree);
|
||||
completionItems.AddRange(directiveCompletions);
|
||||
}
|
||||
|
||||
return completionItems;
|
||||
}
|
||||
|
||||
// Internal for testing
|
||||
internal static List<RazorCompletionItem> GetDirectiveCompletionItems(RazorSyntaxTree syntaxTree)
|
||||
{
|
||||
var directives = syntaxTree.Options.Directives.Concat(DefaultDirectives);
|
||||
var completionItems = new List<RazorCompletionItem>();
|
||||
foreach (var directive in directives)
|
||||
{
|
||||
var completionDisplayText = directive.DisplayName ?? directive.Directive;
|
||||
var completionItem = new RazorCompletionItem(
|
||||
completionDisplayText,
|
||||
directive.Directive,
|
||||
directive.Description,
|
||||
RazorCompletionItemKind.Directive);
|
||||
completionItems.Add(completionItem);
|
||||
}
|
||||
|
||||
return completionItems;
|
||||
}
|
||||
|
||||
// Internal for testing
|
||||
internal static bool AtDirectiveCompletionPoint(RazorSyntaxTree syntaxTree, SourceSpan location)
|
||||
{
|
||||
if (syntaxTree == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var change = new SourceChange(location, string.Empty);
|
||||
var owner = syntaxTree.Root.LocateOwner(change);
|
||||
|
||||
if (owner == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (owner.ChunkGenerator is ExpressionChunkGenerator &&
|
||||
owner.Tokens.All(IsDirectiveCompletableToken) &&
|
||||
// Do not provide IntelliSense for explicit expressions. Explicit expressions will usually look like:
|
||||
// [@] [(] [DateTime.Now] [)]
|
||||
owner.Parent?.Children.Count > 1 &&
|
||||
owner.Parent.Children[1] == owner)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Internal for testing
|
||||
internal static bool IsDirectiveCompletableToken(IToken token)
|
||||
{
|
||||
if (!(token is CSharpToken csharpToken))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return csharpToken.Type == CSharpTokenType.Identifier ||
|
||||
// Marker symbol
|
||||
csharpToken.Type == CSharpTokenType.Unknown;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9,7 +9,9 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Features" Version="$(VSIX_MicrosoftCodeAnalysisCSharpFeaturesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.EditorFeatures.Text" Version="$(VSIX_MicrosoftCodeAnalysisEditorFeaturesTextPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Text.UI" Version="$(MicrosoftVisualStudioTextUIPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Language.Intellisense" Version="$(MicrosoftVisualStudioLanguageIntellisensePackageVersion)" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Language" Version="$(MicrosoftVisualStudioLanguagePackageVersion)" />
|
||||
<PackageReference Include="StreamJsonRpc" Version="$(StreamJsonRpcPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Razor.LanguageServer.StrongNamed, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.VisualStudio.LiveShare.Razor, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.VisualStudio.LiveShare.Razor.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.VisualStudio.Editor.Razor.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
// 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.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
public abstract class RazorCompletionFactsService
|
||||
{
|
||||
public abstract IReadOnlyList<RazorCompletionItem> GetCompletionItems(RazorSyntaxTree syntaxTree, SourceSpan location);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
// 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;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
public sealed class RazorCompletionItem
|
||||
{
|
||||
public RazorCompletionItem(
|
||||
string displayText,
|
||||
string insertText,
|
||||
string description,
|
||||
RazorCompletionItemKind kind)
|
||||
{
|
||||
if (displayText == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(displayText));
|
||||
}
|
||||
|
||||
if (insertText == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(insertText));
|
||||
}
|
||||
|
||||
if (description == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(description));
|
||||
}
|
||||
|
||||
DisplayText = displayText;
|
||||
InsertText = insertText;
|
||||
Description = description;
|
||||
Kind = kind;
|
||||
}
|
||||
|
||||
public string DisplayText { get; }
|
||||
|
||||
public string InsertText { get; }
|
||||
|
||||
public string Description { get; }
|
||||
|
||||
public RazorCompletionItemKind Kind { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
public enum RazorCompletionItemKind
|
||||
{
|
||||
Directive
|
||||
}
|
||||
}
|
||||
|
|
@ -13,9 +13,9 @@ using Microsoft.AspNetCore.Razor.Language;
|
|||
using Microsoft.AspNetCore.Razor.Language.Legacy;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.Completion;
|
||||
using Microsoft.CodeAnalysis.Razor;
|
||||
using Microsoft.CodeAnalysis.Tags;
|
||||
using Microsoft.CodeAnalysis.Text;
|
||||
using Microsoft.VisualStudio.Language.Intellisense.AsyncCompletion;
|
||||
using Microsoft.VisualStudio.Text;
|
||||
using Microsoft.VisualStudio.Text.Projection;
|
||||
|
||||
|
|
@ -36,16 +36,41 @@ namespace Microsoft.VisualStudio.Editor.Razor
|
|||
CSharpCodeParser.TagHelperPrefixDirectiveDescriptor,
|
||||
};
|
||||
private readonly Lazy<RazorCodeDocumentProvider> _codeDocumentProvider;
|
||||
private readonly Lazy<RazorCompletionFactsService> _completionFactsService;
|
||||
private readonly IAsyncCompletionBroker _asyncCompletionBroker;
|
||||
private readonly RazorTextBufferProvider _textBufferProvider;
|
||||
|
||||
[ImportingConstructor]
|
||||
public RazorDirectiveCompletionProvider([Import(typeof(RazorCodeDocumentProvider))] Lazy<RazorCodeDocumentProvider> codeDocumentProvider)
|
||||
public RazorDirectiveCompletionProvider(
|
||||
[Import(typeof(RazorCodeDocumentProvider))] Lazy<RazorCodeDocumentProvider> codeDocumentProvider,
|
||||
[Import(typeof(RazorCompletionFactsService))] Lazy<RazorCompletionFactsService> completionFactsService,
|
||||
IAsyncCompletionBroker asyncCompletionBroker,
|
||||
RazorTextBufferProvider textBufferProvider)
|
||||
{
|
||||
if (codeDocumentProvider == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(codeDocumentProvider));
|
||||
}
|
||||
|
||||
if (completionFactsService == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(completionFactsService));
|
||||
}
|
||||
|
||||
if (asyncCompletionBroker == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(asyncCompletionBroker));
|
||||
}
|
||||
|
||||
if (textBufferProvider == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(textBufferProvider));
|
||||
}
|
||||
|
||||
_codeDocumentProvider = codeDocumentProvider;
|
||||
_completionFactsService = completionFactsService;
|
||||
_asyncCompletionBroker = asyncCompletionBroker;
|
||||
_textBufferProvider = textBufferProvider;
|
||||
}
|
||||
|
||||
public override Task<CompletionDescription> GetDescriptionAsync(Document document, CompletionItem item, CancellationToken cancellationToken)
|
||||
|
|
@ -86,6 +111,13 @@ namespace Microsoft.VisualStudio.Editor.Razor
|
|||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
if (!_textBufferProvider.TryGetFromDocument(context.Document, out var textBuffer) ||
|
||||
!_asyncCompletionBroker.IsCompletionSupported(textBuffer.ContentType))
|
||||
{
|
||||
// Completion is not supported.
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
var result = AddCompletionItems(context);
|
||||
|
||||
return result;
|
||||
|
|
@ -109,70 +141,41 @@ namespace Microsoft.VisualStudio.Editor.Razor
|
|||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
if (!AtDirectiveCompletionPoint(syntaxTree, context))
|
||||
if (!TryGetRazorSnapshotPoint(context, out var razorSnapshotPoint))
|
||||
{
|
||||
// Can't have a valid directive at the current location.
|
||||
// Could not find associated Razor location.
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
var completionItems = GetCompletionItems(syntaxTree);
|
||||
context.AddItems(completionItems);
|
||||
var location = new SourceSpan(razorSnapshotPoint.Position, 0);
|
||||
var razorCompletionItems = _completionFactsService.Value.GetCompletionItems(syntaxTree, location);
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
// Internal virtual for testing
|
||||
internal virtual IEnumerable<CompletionItem> GetCompletionItems(RazorSyntaxTree syntaxTree)
|
||||
{
|
||||
var directives = syntaxTree.Options.Directives.Concat(DefaultDirectives);
|
||||
var completionItems = new List<CompletionItem>();
|
||||
foreach (var directive in directives)
|
||||
foreach (var razorCompletionItem in razorCompletionItems)
|
||||
{
|
||||
var propertyDictionary = new Dictionary<string, string>(StringComparer.Ordinal);
|
||||
|
||||
if (!string.IsNullOrEmpty(directive.Description))
|
||||
if (razorCompletionItem.Kind != RazorCompletionItemKind.Directive)
|
||||
{
|
||||
propertyDictionary[DescriptionKey] = directive.Description;
|
||||
// Don't support any other types of completion kinds other than directives.
|
||||
continue;
|
||||
}
|
||||
|
||||
var propertyDictionary = new Dictionary<string, string>(StringComparer.Ordinal);
|
||||
if (!string.IsNullOrEmpty(razorCompletionItem.Description))
|
||||
{
|
||||
propertyDictionary[DescriptionKey] = razorCompletionItem.Description;
|
||||
}
|
||||
|
||||
var completionItem = CompletionItem.Create(
|
||||
directive.Directive,
|
||||
razorCompletionItem.InsertText,
|
||||
// This groups all Razor directives together
|
||||
sortText: "_RazorDirective_",
|
||||
rules: CompletionItemRules.Create(formatOnCommit: false),
|
||||
tags: ImmutableArray.Create(WellKnownTags.Intrinsic),
|
||||
properties: propertyDictionary.ToImmutableDictionary());
|
||||
completionItems.Add(completionItem);
|
||||
|
||||
context.AddItem(completionItem);
|
||||
}
|
||||
|
||||
return completionItems;
|
||||
}
|
||||
|
||||
// Internal for testing
|
||||
internal bool AtDirectiveCompletionPoint(RazorSyntaxTree syntaxTree, CompletionContext context)
|
||||
{
|
||||
if (TryGetRazorSnapshotPoint(context, out var razorSnapshotPoint))
|
||||
{
|
||||
var change = new SourceChange(razorSnapshotPoint.Position, 0, string.Empty);
|
||||
var owner = syntaxTree.Root.LocateOwner(change);
|
||||
|
||||
if (owner == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (owner.ChunkGenerator is ExpressionChunkGenerator &&
|
||||
owner.Tokens.All(IsDirectiveCompletableSymbol) &&
|
||||
// Do not provide IntelliSense for explicit expressions. Explicit expressions will usually look like:
|
||||
// [@] [(] [DateTime.Now] [)]
|
||||
owner.Parent?.Children.Count > 1 &&
|
||||
owner.Parent.Children[1] == owner)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
protected virtual bool TryGetRazorSnapshotPoint(CompletionContext context, out SnapshotPoint snapshotPoint)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,119 @@
|
|||
// 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 System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Razor.Language;
|
||||
using Microsoft.CodeAnalysis.Razor;
|
||||
using Microsoft.VisualStudio.Core.Imaging;
|
||||
using Microsoft.VisualStudio.Imaging;
|
||||
using Microsoft.VisualStudio.Language.Intellisense.AsyncCompletion;
|
||||
using Microsoft.VisualStudio.Language.Intellisense.AsyncCompletion.Data;
|
||||
using Microsoft.VisualStudio.Text;
|
||||
using Microsoft.VisualStudio.Text.Adornments;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
internal class RazorDirectiveCompletionSource : IAsyncCompletionSource
|
||||
{
|
||||
// Internal for testing
|
||||
internal static readonly object DescriptionKey = new object();
|
||||
internal static readonly ImageElement DirectiveImageGlyph = new ImageElement(
|
||||
new ImageId(KnownImageIds.ImageCatalogGuid, KnownImageIds.Type),
|
||||
"Razor Directive.");
|
||||
internal static readonly ImmutableArray<CompletionFilter> DirectiveCompletionFilters = new[] {
|
||||
new CompletionFilter("Razor Directive", "r", DirectiveImageGlyph)
|
||||
}.ToImmutableArray();
|
||||
|
||||
// Internal for testing
|
||||
internal readonly VisualStudioRazorParser _parser;
|
||||
private readonly RazorCompletionFactsService _completionFactsService;
|
||||
private readonly ForegroundDispatcher _foregroundDispatcher;
|
||||
|
||||
public RazorDirectiveCompletionSource(
|
||||
ForegroundDispatcher foregroundDispatcher,
|
||||
VisualStudioRazorParser parser,
|
||||
RazorCompletionFactsService completionFactsService)
|
||||
{
|
||||
if (foregroundDispatcher == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(foregroundDispatcher));
|
||||
}
|
||||
|
||||
if (parser == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(parser));
|
||||
}
|
||||
|
||||
if (completionFactsService == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(completionFactsService));
|
||||
}
|
||||
|
||||
_foregroundDispatcher = foregroundDispatcher;
|
||||
_parser = parser;
|
||||
_completionFactsService = completionFactsService;
|
||||
}
|
||||
|
||||
public Task<CompletionContext> GetCompletionContextAsync(
|
||||
InitialTrigger trigger,
|
||||
SnapshotPoint triggerLocation,
|
||||
SnapshotSpan applicableSpan,
|
||||
CancellationToken token)
|
||||
{
|
||||
_foregroundDispatcher.AssertBackgroundThread();
|
||||
|
||||
var syntaxTree = _parser.CodeDocument?.GetSyntaxTree();
|
||||
var location = new SourceSpan(applicableSpan.Start.Position, applicableSpan.Length);
|
||||
var razorCompletionItems = _completionFactsService.GetCompletionItems(syntaxTree, location);
|
||||
|
||||
var completionItems = new List<CompletionItem>();
|
||||
foreach (var razorCompletionItem in razorCompletionItems)
|
||||
{
|
||||
if (razorCompletionItem.Kind != RazorCompletionItemKind.Directive)
|
||||
{
|
||||
// Don't support any other types of completion kinds other than directives.
|
||||
continue;
|
||||
}
|
||||
|
||||
var completionItem = new CompletionItem(
|
||||
displayText: razorCompletionItem.DisplayText,
|
||||
filterText: razorCompletionItem.DisplayText,
|
||||
insertText: razorCompletionItem.InsertText,
|
||||
source: this,
|
||||
icon: DirectiveImageGlyph,
|
||||
filters: DirectiveCompletionFilters,
|
||||
suffix: string.Empty,
|
||||
sortText: razorCompletionItem.DisplayText,
|
||||
attributeIcons: ImmutableArray<ImageElement>.Empty);
|
||||
completionItem.Properties.AddProperty(DescriptionKey, razorCompletionItem.Description);
|
||||
completionItems.Add(completionItem);
|
||||
}
|
||||
var context = new CompletionContext(completionItems.ToImmutableArray());
|
||||
return Task.FromResult(context);
|
||||
}
|
||||
|
||||
public Task<object> GetDescriptionAsync(CompletionItem item, CancellationToken token)
|
||||
{
|
||||
if (!item.Properties.TryGetProperty<string>(DescriptionKey, out var directiveDescription))
|
||||
{
|
||||
directiveDescription = string.Empty;
|
||||
}
|
||||
|
||||
return Task.FromResult<object>(directiveDescription);
|
||||
}
|
||||
|
||||
public bool TryGetApplicableToSpan(char typeChar, SnapshotPoint triggerLocation, out SnapshotSpan applicableToSpan, CancellationToken token)
|
||||
{
|
||||
// The applicable span for completion is the piece of text a completion is for. For example:
|
||||
// @Date|Time.Now
|
||||
// If you trigger completion at the | then the applicable span is the region of 'DateTime'; however, Razor
|
||||
// doesn't know this information so we rely on Roslyn to define what the applicable span for a completion is.
|
||||
applicableToSpan = default(SnapshotSpan);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
// 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 System.ComponentModel.Composition;
|
||||
using System.Linq;
|
||||
using Microsoft.CodeAnalysis.Razor;
|
||||
using Microsoft.VisualStudio.Language.Intellisense.AsyncCompletion;
|
||||
using Microsoft.VisualStudio.Text;
|
||||
using Microsoft.VisualStudio.Text.Editor;
|
||||
using Microsoft.VisualStudio.Utilities;
|
||||
|
||||
namespace Microsoft.VisualStudio.Editor.Razor
|
||||
{
|
||||
[System.Composition.Shared]
|
||||
[Export(typeof(IAsyncCompletionSourceProvider))]
|
||||
[Name("Razor directive completion provider.")]
|
||||
[ContentType(RazorLanguage.CoreContentType)]
|
||||
internal class RazorDirectiveCompletionSourceProvider : IAsyncCompletionSourceProvider
|
||||
{
|
||||
private readonly ForegroundDispatcher _foregroundDispatcher;
|
||||
private readonly RazorCompletionFactsService _completionFactsService;
|
||||
|
||||
[ImportingConstructor]
|
||||
public RazorDirectiveCompletionSourceProvider(
|
||||
ForegroundDispatcher foregroundDispatcher,
|
||||
RazorCompletionFactsService completionFactsService)
|
||||
{
|
||||
if (foregroundDispatcher == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(foregroundDispatcher));
|
||||
}
|
||||
|
||||
if (completionFactsService == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(completionFactsService));
|
||||
}
|
||||
|
||||
_foregroundDispatcher = foregroundDispatcher;
|
||||
_completionFactsService = completionFactsService;
|
||||
}
|
||||
|
||||
public IAsyncCompletionSource GetOrCreate(ITextView textView)
|
||||
{
|
||||
if (textView == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(textView));
|
||||
}
|
||||
|
||||
var razorBuffer = textView.BufferGraph.GetRazorBuffers().FirstOrDefault();
|
||||
if (!razorBuffer.Properties.TryGetProperty(typeof(RazorDirectiveCompletionSource), out IAsyncCompletionSource completionSource))
|
||||
{
|
||||
completionSource = CreateCompletionSource(razorBuffer);
|
||||
razorBuffer.Properties.AddProperty(typeof(RazorDirectiveCompletionSource), completionSource);
|
||||
}
|
||||
|
||||
return completionSource;
|
||||
}
|
||||
|
||||
// Internal for testing
|
||||
internal IAsyncCompletionSource CreateCompletionSource(ITextBuffer razorBuffer)
|
||||
{
|
||||
if (!razorBuffer.Properties.TryGetProperty(typeof(VisualStudioRazorParser), out VisualStudioRazorParser parser))
|
||||
{
|
||||
// Parser hasn't been associated with the text buffer yet.
|
||||
return null;
|
||||
}
|
||||
|
||||
var completionSource = new RazorDirectiveCompletionSource(_foregroundDispatcher, parser, _completionFactsService);
|
||||
return completionSource;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -42,6 +42,18 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
|||
+ "}");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RazorCommentInOpeningTagBlock()
|
||||
{
|
||||
ParseDocumentTest("<text @* razor comment *@></text>");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RazorCommentInClosingTagBlock()
|
||||
{
|
||||
ParseDocumentTest("<text></text @* razor comment *@>");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UnterminatedRazorCommentInVerbatimBlock()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -13,3 +13,6 @@
|
|||
<p>But this should show the comment syntax: @bar</p>
|
||||
|
||||
@(a@**@b)
|
||||
|
||||
<input value="@*this razor comment is the actual value*@" type="text" />
|
||||
<input @*this razor comment will not be rendered*@ type="text" />
|
||||
|
|
|
|||
|
|
@ -38,5 +38,14 @@ Document -
|
|||
CSharpExpression - (323:14,2 [2] RazorComments.cshtml)
|
||||
IntermediateToken - (323:14,2 [1] RazorComments.cshtml) - CSharp - a
|
||||
IntermediateToken - (328:14,7 [1] RazorComments.cshtml) - CSharp - b
|
||||
HtmlContent - (330:14,9 [2] RazorComments.cshtml)
|
||||
IntermediateToken - (330:14,9 [2] RazorComments.cshtml) - Html - \n
|
||||
HtmlContent - (330:14,9 [85] RazorComments.cshtml)
|
||||
IntermediateToken - (330:14,9 [4] RazorComments.cshtml) - Html - \n\n
|
||||
IntermediateToken - (334:16,0 [6] RazorComments.cshtml) - Html - <input
|
||||
IntermediateToken - (340:16,6 [51] RazorComments.cshtml) - Html - value="@*this razor comment is the actual value*@"
|
||||
IntermediateToken - (391:16,57 [12] RazorComments.cshtml) - Html - type="text"
|
||||
IntermediateToken - (403:16,69 [3] RazorComments.cshtml) - Html - />
|
||||
IntermediateToken - (406:16,72 [2] RazorComments.cshtml) - Html - \n
|
||||
IntermediateToken - (408:17,0 [7] RazorComments.cshtml) - Html - <input
|
||||
HtmlContent - (458:17,50 [17] RazorComments.cshtml)
|
||||
IntermediateToken - (458:17,50 [15] RazorComments.cshtml) - Html - type="text" />
|
||||
IntermediateToken - (473:17,65 [2] RazorComments.cshtml) - Html - \n
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
#pragma checksum "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorComments.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "051345e2cc0313fea445db2f6cf48fe28b0b4edf"
|
||||
#pragma checksum "TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorComments.cshtml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "4d553281e07fafc67ca0139b27ee95724a37f162"
|
||||
// <auto-generated/>
|
||||
#pragma warning disable 1591
|
||||
[assembly: global::Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute(typeof(Microsoft.AspNetCore.Razor.Language.IntegrationTests.TestFiles.TestFiles_IntegrationTests_CodeGenerationIntegrationTest_RazorComments_Runtime), @"default", @"/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorComments.cshtml")]
|
||||
namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests.TestFiles
|
||||
{
|
||||
#line hidden
|
||||
[global::Microsoft.AspNetCore.Razor.Hosting.RazorSourceChecksumAttribute(@"SHA1", @"051345e2cc0313fea445db2f6cf48fe28b0b4edf", @"/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorComments.cshtml")]
|
||||
[global::Microsoft.AspNetCore.Razor.Hosting.RazorSourceChecksumAttribute(@"SHA1", @"4d553281e07fafc67ca0139b27ee95724a37f162", @"/TestFiles/IntegrationTests/CodeGenerationIntegrationTest/RazorComments.cshtml")]
|
||||
public class TestFiles_IntegrationTests_CodeGenerationIntegrationTest_RazorComments_Runtime
|
||||
{
|
||||
#pragma warning disable 1998
|
||||
|
|
@ -45,7 +45,8 @@ Write(ab);
|
|||
|
||||
#line default
|
||||
#line hidden
|
||||
WriteLiteral("\r\n");
|
||||
WriteLiteral("\r\n\r\n<input value=\"@*this razor comment is the actual value*@\" type=\"text\" />\r\n<input ");
|
||||
WriteLiteral(" type=\"text\" />\r\n");
|
||||
}
|
||||
#pragma warning restore 1998
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,5 +33,14 @@ Document -
|
|||
CSharpExpression - (323:14,2 [2] RazorComments.cshtml)
|
||||
IntermediateToken - (323:14,2 [1] RazorComments.cshtml) - CSharp - a
|
||||
IntermediateToken - (328:14,7 [1] RazorComments.cshtml) - CSharp - b
|
||||
HtmlContent - (330:14,9 [2] RazorComments.cshtml)
|
||||
IntermediateToken - (330:14,9 [2] RazorComments.cshtml) - Html - \n
|
||||
HtmlContent - (330:14,9 [85] RazorComments.cshtml)
|
||||
IntermediateToken - (330:14,9 [4] RazorComments.cshtml) - Html - \n\n
|
||||
IntermediateToken - (334:16,0 [6] RazorComments.cshtml) - Html - <input
|
||||
IntermediateToken - (340:16,6 [51] RazorComments.cshtml) - Html - value="@*this razor comment is the actual value*@"
|
||||
IntermediateToken - (391:16,57 [12] RazorComments.cshtml) - Html - type="text"
|
||||
IntermediateToken - (403:16,69 [3] RazorComments.cshtml) - Html - />
|
||||
IntermediateToken - (406:16,72 [2] RazorComments.cshtml) - Html - \n
|
||||
IntermediateToken - (408:17,0 [7] RazorComments.cshtml) - Html - <input
|
||||
HtmlContent - (458:17,50 [17] RazorComments.cshtml)
|
||||
IntermediateToken - (458:17,50 [15] RazorComments.cshtml) - Html - type="text" />
|
||||
IntermediateToken - (473:17,65 [2] RazorComments.cshtml) - Html - \n
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@ Directive block - Gen<Directive:{section;RazorBlock;Unrestricted} [RZ1006(16:0,1
|
|||
HtmlTokenType.OpenAngle;[<];
|
||||
HtmlTokenType.Text;[p];
|
||||
HtmlTokenType.CloseAngle;[>];
|
||||
Markup span - Gen<Markup> - [Foo] - SpanEditHandler;Accepts:Any - (22:1,3) - Tokens:1
|
||||
HtmlTokenType.Text;[Foo];
|
||||
SyntaxKind.HtmlText - [Foo] - [22..25) - FullWidth: 3 - Slots: 1
|
||||
SyntaxKind.HtmlTextLiteralToken;[Foo];
|
||||
Tag block - Gen<None> - 4 - (25:1,6)
|
||||
Markup span - Gen<Markup> - [</p>] - SpanEditHandler;Accepts:Any - (25:1,6) - Tokens:4
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
|
|
|
|||
|
|
@ -51,12 +51,13 @@ Markup block - Gen<None> - 130 - (0:0,0)
|
|||
HtmlTokenType.OpenAngle;[<];
|
||||
HtmlTokenType.Text;[p];
|
||||
HtmlTokenType.CloseAngle;[>];
|
||||
Markup span - Gen<Markup> - [This is extra] - SpanEditHandler;Accepts:Any - (113:5,3) - Tokens:5
|
||||
HtmlTokenType.Text;[This];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[is];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[extra];
|
||||
SyntaxKind.HtmlText - [This is extra] - [113..126) - FullWidth: 13 - Slots: 1
|
||||
SyntaxKind.List - [This is extra] - [113..126) - FullWidth: 13 - Slots: 5
|
||||
SyntaxKind.HtmlTextLiteralToken;[This];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[is];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[extra];
|
||||
Tag block - Gen<None> - 4 - (126:5,16)
|
||||
Markup span - Gen<Markup> - [</p>] - SpanEditHandler;Accepts:Any - (126:5,16) - Tokens:4
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
|
|
|
|||
|
|
@ -19,12 +19,13 @@ Directive block - Gen<Directive:{custom;RazorBlock;Unrestricted}> - 33 - (0:0,0)
|
|||
HtmlTokenType.OpenAngle;[<];
|
||||
HtmlTokenType.Text;[p];
|
||||
HtmlTokenType.CloseAngle;[>];
|
||||
Markup span - Gen<Markup> - [F{o}o] - SpanEditHandler;Accepts:Any - (22:0,22) - Tokens:5
|
||||
HtmlTokenType.Text;[F];
|
||||
HtmlTokenType.Text;[{];
|
||||
HtmlTokenType.Text;[o];
|
||||
HtmlTokenType.Text;[}];
|
||||
HtmlTokenType.Text;[o];
|
||||
SyntaxKind.HtmlText - [F{o}o] - [22..27) - FullWidth: 5 - Slots: 1
|
||||
SyntaxKind.List - [F{o}o] - [22..27) - FullWidth: 5 - Slots: 5
|
||||
SyntaxKind.HtmlTextLiteralToken;[F];
|
||||
SyntaxKind.HtmlTextLiteralToken;[{];
|
||||
SyntaxKind.HtmlTextLiteralToken;[o];
|
||||
SyntaxKind.HtmlTextLiteralToken;[}];
|
||||
SyntaxKind.HtmlTextLiteralToken;[o];
|
||||
Tag block - Gen<None> - 4 - (27:0,27)
|
||||
Markup span - Gen<Markup> - [</p>] - SpanEditHandler;Accepts:Any - (27:0,27) - Tokens:4
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
|
|
|
|||
|
|
@ -19,12 +19,13 @@ Directive block - Gen<Directive:{section;RazorBlock;Unrestricted}> - 32 - (0:0,0
|
|||
HtmlTokenType.OpenAngle;[<];
|
||||
HtmlTokenType.Text;[p];
|
||||
HtmlTokenType.CloseAngle;[>];
|
||||
Markup span - Gen<Markup> - [F{o}o] - SpanEditHandler;Accepts:Any - (21:0,21) - Tokens:5
|
||||
HtmlTokenType.Text;[F];
|
||||
HtmlTokenType.Text;[{];
|
||||
HtmlTokenType.Text;[o];
|
||||
HtmlTokenType.Text;[}];
|
||||
HtmlTokenType.Text;[o];
|
||||
SyntaxKind.HtmlText - [F{o}o] - [21..26) - FullWidth: 5 - Slots: 1
|
||||
SyntaxKind.List - [F{o}o] - [21..26) - FullWidth: 5 - Slots: 5
|
||||
SyntaxKind.HtmlTextLiteralToken;[F];
|
||||
SyntaxKind.HtmlTextLiteralToken;[{];
|
||||
SyntaxKind.HtmlTextLiteralToken;[o];
|
||||
SyntaxKind.HtmlTextLiteralToken;[}];
|
||||
SyntaxKind.HtmlTextLiteralToken;[o];
|
||||
Tag block - Gen<None> - 4 - (26:0,26)
|
||||
Markup span - Gen<Markup> - [</p>] - SpanEditHandler;Accepts:Any - (26:0,26) - Tokens:4
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
Markup span at (0:0,0 [6] ) (Accepts:Any) - Parent: Tag block at (0:0,0 [6] )
|
||||
Markup span at (6:0,6 [7] ) (Accepts:Any) - Parent: Tag block at (6:0,6 [7] )
|
||||
Transition span at (13:0,13 [1] ) (Accepts:None) - Parent: Comment block at (13:0,13 [19] )
|
||||
MetaCode span at (14:0,14 [1] ) (Accepts:None) - Parent: Comment block at (13:0,13 [19] )
|
||||
Comment span at (15:0,15 [15] ) (Accepts:Any) - Parent: Comment block at (13:0,13 [19] )
|
||||
MetaCode span at (30:0,30 [1] ) (Accepts:None) - Parent: Comment block at (13:0,13 [19] )
|
||||
Transition span at (31:0,31 [1] ) (Accepts:None) - Parent: Comment block at (13:0,13 [19] )
|
||||
Markup span at (32:0,32 [1] ) (Accepts:Any) - Parent: Markup block at (0:0,0 [33] )
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
Markup block - Gen<None> - 33 - (0:0,0)
|
||||
Tag block - Gen<None> - 6 - (0:0,0)
|
||||
Markup span - Gen<Markup> - [<text>] - SpanEditHandler;Accepts:Any - (0:0,0) - Tokens:3
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
HtmlTokenType.Text;[text];
|
||||
HtmlTokenType.CloseAngle;[>];
|
||||
Tag block - Gen<None> - 7 - (6:0,6)
|
||||
Markup span - Gen<Markup> - [</text ] - SpanEditHandler;Accepts:Any - (6:0,6) - Tokens:4
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
HtmlTokenType.ForwardSlash;[/];
|
||||
HtmlTokenType.Text;[text];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
Comment block - Gen<RazorComment> - 19 - (13:0,13)
|
||||
Transition span - Gen<None> - [@] - SpanEditHandler;Accepts:None - (13:0,13) - Tokens:1
|
||||
HtmlTokenType.RazorCommentTransition;[@];
|
||||
MetaCode span - Gen<None> - [*] - SpanEditHandler;Accepts:None - (14:0,14) - Tokens:1
|
||||
HtmlTokenType.RazorCommentStar;[*];
|
||||
Comment span - Gen<None> - [ razor comment ] - SpanEditHandler;Accepts:Any - (15:0,15) - Tokens:1
|
||||
HtmlTokenType.RazorComment;[ razor comment ];
|
||||
MetaCode span - Gen<None> - [*] - SpanEditHandler;Accepts:None - (30:0,30) - Tokens:1
|
||||
HtmlTokenType.RazorCommentStar;[*];
|
||||
Transition span - Gen<None> - [@] - SpanEditHandler;Accepts:None - (31:0,31) - Tokens:1
|
||||
HtmlTokenType.RazorCommentTransition;[@];
|
||||
Markup span - Gen<Markup> - [>] - SpanEditHandler;Accepts:Any - (32:0,32) - Tokens:1
|
||||
HtmlTokenType.CloseAngle;[>];
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
Markup span at (0:0,0 [6] ) (Accepts:Any) - Parent: Tag block at (0:0,0 [26] )
|
||||
Transition span at (6:0,6 [1] ) (Accepts:None) - Parent: Comment block at (6:0,6 [19] )
|
||||
MetaCode span at (7:0,7 [1] ) (Accepts:None) - Parent: Comment block at (6:0,6 [19] )
|
||||
Comment span at (8:0,8 [15] ) (Accepts:Any) - Parent: Comment block at (6:0,6 [19] )
|
||||
MetaCode span at (23:0,23 [1] ) (Accepts:None) - Parent: Comment block at (6:0,6 [19] )
|
||||
Transition span at (24:0,24 [1] ) (Accepts:None) - Parent: Comment block at (6:0,6 [19] )
|
||||
Markup span at (25:0,25 [1] ) (Accepts:Any) - Parent: Tag block at (0:0,0 [26] )
|
||||
Markup span at (26:0,26 [7] ) (Accepts:Any) - Parent: Tag block at (26:0,26 [7] )
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
Markup block - Gen<None> - 33 - (0:0,0)
|
||||
Tag block - Gen<None> - 26 - (0:0,0)
|
||||
Markup span - Gen<Markup> - [<text ] - SpanEditHandler;Accepts:Any - (0:0,0) - Tokens:3
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
HtmlTokenType.Text;[text];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
Comment block - Gen<RazorComment> - 19 - (6:0,6)
|
||||
Transition span - Gen<None> - [@] - SpanEditHandler;Accepts:None - (6:0,6) - Tokens:1
|
||||
HtmlTokenType.RazorCommentTransition;[@];
|
||||
MetaCode span - Gen<None> - [*] - SpanEditHandler;Accepts:None - (7:0,7) - Tokens:1
|
||||
HtmlTokenType.RazorCommentStar;[*];
|
||||
Comment span - Gen<None> - [ razor comment ] - SpanEditHandler;Accepts:Any - (8:0,8) - Tokens:1
|
||||
HtmlTokenType.RazorComment;[ razor comment ];
|
||||
MetaCode span - Gen<None> - [*] - SpanEditHandler;Accepts:None - (23:0,23) - Tokens:1
|
||||
HtmlTokenType.RazorCommentStar;[*];
|
||||
Transition span - Gen<None> - [@] - SpanEditHandler;Accepts:None - (24:0,24) - Tokens:1
|
||||
HtmlTokenType.RazorCommentTransition;[@];
|
||||
Markup span - Gen<Markup> - [>] - SpanEditHandler;Accepts:Any - (25:0,25) - Tokens:1
|
||||
HtmlTokenType.CloseAngle;[>];
|
||||
Tag block - Gen<None> - 7 - (26:0,26)
|
||||
Markup span - Gen<Markup> - [</text>] - SpanEditHandler;Accepts:Any - (26:0,26) - Tokens:4
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
HtmlTokenType.ForwardSlash;[/];
|
||||
HtmlTokenType.Text;[text];
|
||||
HtmlTokenType.CloseAngle;[>];
|
||||
|
|
@ -33,8 +33,8 @@ Markup block - Gen<None> - 45 - (0:0,0)
|
|||
HtmlTokenType.RazorCommentTransition;[@];
|
||||
Markup span - Gen<None> - [LF] - SpanEditHandler;Accepts:Any - (37:5,2) - Tokens:1
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
Markup span - Gen<Markup> - [LF] - SpanEditHandler;Accepts:Any - (39:6,0) - Tokens:1
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
SyntaxKind.HtmlText - [LF] - [39..41) - FullWidth: 2 - Slots: 1
|
||||
SyntaxKind.NewLine;[LF];
|
||||
Tag block - Gen<None> - 4 - (41:7,0)
|
||||
Markup span - Gen<Markup> - [</p>] - SpanEditHandler;Accepts:Any - (41:7,0) - Tokens:4
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
|
|
|
|||
|
|
@ -32,8 +32,8 @@ Markup block - Gen<None> - 42 - (0:0,0)
|
|||
HtmlTokenType.RazorCommentStar;[*];
|
||||
Transition span - Gen<None> - [@] - SpanEditHandler;Accepts:None - (35:1,30) - Tokens:1
|
||||
HtmlTokenType.RazorCommentTransition;[@];
|
||||
Markup span - Gen<Markup> - [LF] - SpanEditHandler;Accepts:Any - (36:1,31) - Tokens:1
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
SyntaxKind.HtmlText - [LF] - [36..38) - FullWidth: 2 - Slots: 1
|
||||
SyntaxKind.NewLine;[LF];
|
||||
Tag block - Gen<None> - 4 - (38:2,0)
|
||||
Markup span - Gen<Markup> - [</p>] - SpanEditHandler;Accepts:Any - (38:2,0) - Tokens:4
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ Markup block - Gen<None> - 46 - (0:0,0)
|
|||
HtmlTokenType.OpenAngle;[<];
|
||||
HtmlTokenType.Text;[p];
|
||||
HtmlTokenType.CloseAngle;[>];
|
||||
Markup span - Gen<Markup> - [Foo] - SpanEditHandler;Accepts:Any - (36:7,3) - Tokens:1
|
||||
HtmlTokenType.Text;[Foo];
|
||||
SyntaxKind.HtmlText - [Foo] - [36..39) - FullWidth: 3 - Slots: 1
|
||||
SyntaxKind.HtmlTextLiteralToken;[Foo];
|
||||
Tag block - Gen<None> - 4 - (39:7,6)
|
||||
Markup span - Gen<Markup> - [</p>] - SpanEditHandler;Accepts:Any - (39:7,6) - Tokens:4
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ Markup block - Gen<None> - 26 - (0:0,0)
|
|||
HtmlTokenType.OpenAngle;[<];
|
||||
HtmlTokenType.Text;[p];
|
||||
HtmlTokenType.CloseAngle;[>];
|
||||
Markup span - Gen<Markup> - [Foo] - SpanEditHandler;Accepts:Any - (17:0,17) - Tokens:1
|
||||
HtmlTokenType.Text;[Foo];
|
||||
SyntaxKind.HtmlText - [Foo] - [17..20) - FullWidth: 3 - Slots: 1
|
||||
SyntaxKind.HtmlTextLiteralToken;[Foo];
|
||||
Tag block - Gen<None> - 4 - (20:0,20)
|
||||
Markup span - Gen<Markup> - [</p>] - SpanEditHandler;Accepts:Any - (20:0,20) - Tokens:4
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
|
|
|
|||
|
|
@ -22,10 +22,11 @@ Markup block - Gen<None> - 27 - (0:0,0)
|
|||
HtmlTokenType.OpenAngle;[<];
|
||||
HtmlTokenType.Text;[p];
|
||||
HtmlTokenType.CloseAngle;[>];
|
||||
Markup span - Gen<Markup> - [Foo{}] - SpanEditHandler;Accepts:Any - (18:0,18) - Tokens:3
|
||||
HtmlTokenType.Text;[Foo];
|
||||
HtmlTokenType.Text;[{];
|
||||
HtmlTokenType.Text;[}];
|
||||
SyntaxKind.HtmlText - [Foo{}] - [18..23) - FullWidth: 5 - Slots: 1
|
||||
SyntaxKind.List - [Foo{}] - [18..23) - FullWidth: 5 - Slots: 3
|
||||
SyntaxKind.HtmlTextLiteralToken;[Foo];
|
||||
SyntaxKind.HtmlTextLiteralToken;[{];
|
||||
SyntaxKind.HtmlTextLiteralToken;[}];
|
||||
Tag block - Gen<None> - 4 - (23:0,23)
|
||||
Markup span - Gen<Markup> - [</p>] - SpanEditHandler;Accepts:Any - (23:0,23) - Tokens:4
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
|
|
|
|||
|
|
@ -38,8 +38,8 @@ Markup block - Gen<None> - 44 - (0:0,0)
|
|||
HtmlTokenType.OpenAngle;[<];
|
||||
HtmlTokenType.Text;[p];
|
||||
HtmlTokenType.CloseAngle;[>];
|
||||
Markup span - Gen<Markup> - [Foo] - SpanEditHandler;Accepts:Any - (33:0,33) - Tokens:1
|
||||
HtmlTokenType.Text;[Foo];
|
||||
SyntaxKind.HtmlText - [Foo] - [33..36) - FullWidth: 3 - Slots: 1
|
||||
SyntaxKind.HtmlTextLiteralToken;[Foo];
|
||||
Tag block - Gen<None> - 4 - (36:0,36)
|
||||
Markup span - Gen<Markup> - [</p>] - SpanEditHandler;Accepts:Any - (36:0,36) - Tokens:4
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ Markup block - Gen<None> - 27 - (0:0,0)
|
|||
HtmlTokenType.OpenAngle;[<];
|
||||
HtmlTokenType.Text;[p];
|
||||
HtmlTokenType.CloseAngle;[>];
|
||||
Markup span - Gen<Markup> - [Foo] - SpanEditHandler;Accepts:Any - (18:0,18) - Tokens:1
|
||||
HtmlTokenType.Text;[Foo];
|
||||
SyntaxKind.HtmlText - [Foo] - [18..21) - FullWidth: 3 - Slots: 1
|
||||
SyntaxKind.HtmlTextLiteralToken;[Foo];
|
||||
Tag block - Gen<None> - 4 - (21:0,21)
|
||||
Markup span - Gen<Markup> - [</p>] - SpanEditHandler;Accepts:Any - (21:0,21) - Tokens:4
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ Markup block - Gen<None> - 25 - (0:0,0)
|
|||
HtmlTokenType.OpenAngle;[<];
|
||||
HtmlTokenType.Text;[p];
|
||||
HtmlTokenType.CloseAngle;[>];
|
||||
Markup span - Gen<Markup> - [Foo] - SpanEditHandler;Accepts:Any - (16:0,16) - Tokens:1
|
||||
HtmlTokenType.Text;[Foo];
|
||||
SyntaxKind.HtmlText - [Foo] - [16..19) - FullWidth: 3 - Slots: 1
|
||||
SyntaxKind.HtmlTextLiteralToken;[Foo];
|
||||
Tag block - Gen<None> - 4 - (19:0,19)
|
||||
Markup span - Gen<Markup> - [</p>] - SpanEditHandler;Accepts:Any - (19:0,19) - Tokens:4
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ Markup block - Gen<None> - 31 - (0:0,0)
|
|||
HtmlTokenType.OpenAngle;[<];
|
||||
HtmlTokenType.Text;[p];
|
||||
HtmlTokenType.CloseAngle;[>];
|
||||
Markup span - Gen<Markup> - [Foo] - SpanEditHandler;Accepts:Any - (22:0,22) - Tokens:1
|
||||
HtmlTokenType.Text;[Foo];
|
||||
SyntaxKind.HtmlText - [Foo] - [22..25) - FullWidth: 3 - Slots: 1
|
||||
SyntaxKind.HtmlTextLiteralToken;[Foo];
|
||||
Tag block - Gen<None> - 4 - (25:0,25)
|
||||
Markup span - Gen<Markup> - [</p>] - SpanEditHandler;Accepts:Any - (25:0,25) - Tokens:4
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
|
|
|
|||
|
|
@ -26,8 +26,8 @@ Markup block - Gen<None> - 165 - (0:0,0)
|
|||
HtmlTokenType.ForwardSlash;[/];
|
||||
HtmlTokenType.Text;[div];
|
||||
HtmlTokenType.CloseAngle;[>];
|
||||
Markup span - Gen<Markup> - [LF] - SpanEditHandler;Accepts:Any - (33:0,33) - Tokens:1
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
SyntaxKind.HtmlText - [LF] - [33..35) - FullWidth: 2 - Slots: 1
|
||||
SyntaxKind.NewLine;[LF];
|
||||
Tag block - Gen<None> - 5 - (35:1,0)
|
||||
Markup span - Gen<Markup> - [<div>] - SpanEditHandler;Accepts:Any - (35:1,0) - Tokens:3
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
|
|
@ -55,8 +55,8 @@ Markup block - Gen<None> - 165 - (0:0,0)
|
|||
HtmlTokenType.ForwardSlash;[/];
|
||||
HtmlTokenType.Text;[div];
|
||||
HtmlTokenType.CloseAngle;[>];
|
||||
Markup span - Gen<Markup> - [LF] - SpanEditHandler;Accepts:Any - (70:1,35) - Tokens:1
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
SyntaxKind.HtmlText - [LF] - [70..72) - FullWidth: 2 - Slots: 1
|
||||
SyntaxKind.NewLine;[LF];
|
||||
Tag block - Gen<None> - 5 - (72:2,0)
|
||||
Markup span - Gen<Markup> - [<div>] - SpanEditHandler;Accepts:Any - (72:2,0) - Tokens:3
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
|
|
@ -86,8 +86,8 @@ Markup block - Gen<None> - 165 - (0:0,0)
|
|||
HtmlTokenType.ForwardSlash;[/];
|
||||
HtmlTokenType.Text;[div];
|
||||
HtmlTokenType.CloseAngle;[>];
|
||||
Markup span - Gen<Markup> - [LF] - SpanEditHandler;Accepts:Any - (109:2,37) - Tokens:1
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
SyntaxKind.HtmlText - [LF] - [109..111) - FullWidth: 2 - Slots: 1
|
||||
SyntaxKind.NewLine;[LF];
|
||||
Tag block - Gen<None> - 5 - (111:3,0)
|
||||
Markup span - Gen<Markup> - [<div>] - SpanEditHandler;Accepts:Any - (111:3,0) - Tokens:3
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
|
|
|
|||
|
|
@ -23,10 +23,11 @@ Markup block - Gen<None> - 39 - (0:0,0)
|
|||
HtmlTokenType.SingleQuote;['];
|
||||
Markup span - Gen<Markup> - [>] - SpanEditHandler;Accepts:Any - (22:0,22) - Tokens:1
|
||||
HtmlTokenType.CloseAngle;[>];
|
||||
Markup span - Gen<Markup> - [ Foo ] - SpanEditHandler;Accepts:Any - (23:0,23) - Tokens:3
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[Foo];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
SyntaxKind.HtmlText - [ Foo ] - [23..28) - FullWidth: 5 - Slots: 1
|
||||
SyntaxKind.List - [ Foo ] - [23..28) - FullWidth: 5 - Slots: 3
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[Foo];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
Tag block - Gen<None> - 4 - (28:0,28)
|
||||
Markup span - Gen<Markup> - [</p>] - SpanEditHandler;Accepts:Any - (28:0,28) - Tokens:4
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
|
|
|
|||
|
|
@ -18,9 +18,10 @@ Markup block - Gen<None> - 31 - (0:0,0)
|
|||
CSharpTokenType.WhiteSpace;[ ];
|
||||
CSharpTokenType.LeftBrace;[{];
|
||||
CSharpTokenType.RightBrace;[}];
|
||||
Markup span - Gen<Markup> - [ Bar] - SpanEditHandler;Accepts:Any - (21:0,21) - Tokens:2
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[Bar];
|
||||
SyntaxKind.HtmlText - [ Bar] - [21..25) - FullWidth: 4 - Slots: 1
|
||||
SyntaxKind.List - [ Bar] - [21..25) - FullWidth: 4 - Slots: 2
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[Bar];
|
||||
Tag block - Gen<None> - 6 - (25:0,25)
|
||||
Markup span - Gen<Markup> - [</div>] - SpanEditHandler;Accepts:Any - (25:0,25) - Tokens:4
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
|
|
|
|||
|
|
@ -15,10 +15,11 @@ Markup block - Gen<None> - 51 - (0:0,0)
|
|||
HtmlTokenType.DoubleQuote;["];
|
||||
Markup span - Gen<Markup> - [>] - SpanEditHandler;Accepts:Any - (38:0,38) - Tokens:1
|
||||
HtmlTokenType.CloseAngle;[>];
|
||||
Markup span - Gen<Markup> - [Email me] - SpanEditHandler;Accepts:Any - (39:0,39) - Tokens:3
|
||||
HtmlTokenType.Text;[Email];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[me];
|
||||
SyntaxKind.HtmlText - [Email me] - [39..47) - FullWidth: 8 - Slots: 1
|
||||
SyntaxKind.List - [Email me] - [39..47) - FullWidth: 8 - Slots: 3
|
||||
SyntaxKind.HtmlTextLiteralToken;[Email];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[me];
|
||||
Tag block - Gen<None> - 4 - (47:0,47)
|
||||
Markup span - Gen<Markup> - [</a>] - SpanEditHandler;Accepts:Any - (47:0,47) - Tokens:4
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ Markup block - Gen<None> - 17 - (0:0,0)
|
|||
HtmlTokenType.OpenAngle;[<];
|
||||
HtmlTokenType.Text;[foo];
|
||||
HtmlTokenType.CloseAngle;[>];
|
||||
Markup span - Gen<Markup> - [${bar}] - SpanEditHandler;Accepts:Any - (5:0,5) - Tokens:1
|
||||
HtmlTokenType.Text;[${bar}];
|
||||
SyntaxKind.HtmlText - [${bar}] - [5..11) - FullWidth: 6 - Slots: 1
|
||||
SyntaxKind.HtmlTextLiteralToken;[${bar}];
|
||||
Tag block - Gen<None> - 6 - (11:0,11)
|
||||
Markup span - Gen<Markup> - [</foo>] - SpanEditHandler;Accepts:Any - (11:0,11) - Tokens:4
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ Markup block - Gen<None> - 20 - (0:0,0)
|
|||
HtmlTokenType.OpenAngle;[<];
|
||||
HtmlTokenType.Text;[text];
|
||||
HtmlTokenType.CloseAngle;[>];
|
||||
Markup span - Gen<Markup> - [Foo] - SpanEditHandler;Accepts:Any - (10:0,10) - Tokens:1
|
||||
HtmlTokenType.Text;[Foo];
|
||||
SyntaxKind.HtmlText - [Foo] - [10..13) - FullWidth: 3 - Slots: 1
|
||||
SyntaxKind.HtmlTextLiteralToken;[Foo];
|
||||
Tag block - Gen<None> - 7 - (13:0,13)
|
||||
Markup span - Gen<Markup> - [</text>] - SpanEditHandler;Accepts:Any - (13:0,13) - Tokens:4
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
|
|
|
|||
|
|
@ -12,20 +12,21 @@ Markup block - Gen<None> - 564 - (0:0,0)
|
|||
HtmlTokenType.OpenAngle;[<];
|
||||
HtmlTokenType.Text;[other];
|
||||
HtmlTokenType.CloseAngle;[>];
|
||||
Markup span - Gen<Markup> - [ var x = true;LF}LF{LF] - SpanEditHandler;Accepts:Any - (16:1,13) - Tokens:13
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[var];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[x];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Equals;[=];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[true;];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
HtmlTokenType.Text;[}];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
HtmlTokenType.Text;[{];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
SyntaxKind.HtmlText - [ var x = true;LF}LF{LF] - [16..38) - FullWidth: 22 - Slots: 1
|
||||
SyntaxKind.List - [ var x = true;LF}LF{LF] - [16..38) - FullWidth: 22 - Slots: 13
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[var];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[x];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.Equals;[=];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[true;];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
SyntaxKind.HtmlTextLiteralToken;[}];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
SyntaxKind.HtmlTextLiteralToken;[{];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
Tag block - Gen<None> - 6 - (38:4,0)
|
||||
Markup span - Gen<Markup> - [<base>] - SpanEditHandler;Accepts:Any - (38:4,0) - Tokens:3
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
|
|
@ -36,20 +37,21 @@ Markup block - Gen<None> - 564 - (0:0,0)
|
|||
HtmlTokenType.OpenAngle;[<];
|
||||
HtmlTokenType.Text;[other];
|
||||
HtmlTokenType.CloseAngle;[>];
|
||||
Markup span - Gen<Markup> - [ var x = true;LF}LF{LF] - SpanEditHandler;Accepts:Any - (51:4,13) - Tokens:13
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[var];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[x];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Equals;[=];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[true;];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
HtmlTokenType.Text;[}];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
HtmlTokenType.Text;[{];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
SyntaxKind.HtmlText - [ var x = true;LF}LF{LF] - [51..73) - FullWidth: 22 - Slots: 1
|
||||
SyntaxKind.List - [ var x = true;LF}LF{LF] - [51..73) - FullWidth: 22 - Slots: 13
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[var];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[x];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.Equals;[=];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[true;];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
SyntaxKind.HtmlTextLiteralToken;[}];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
SyntaxKind.HtmlTextLiteralToken;[{];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
Tag block - Gen<None> - 4 - (73:7,0)
|
||||
Markup span - Gen<Markup> - [<br>] - SpanEditHandler;Accepts:Any - (73:7,0) - Tokens:3
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
|
|
@ -60,20 +62,21 @@ Markup block - Gen<None> - 564 - (0:0,0)
|
|||
HtmlTokenType.OpenAngle;[<];
|
||||
HtmlTokenType.Text;[other];
|
||||
HtmlTokenType.CloseAngle;[>];
|
||||
Markup span - Gen<Markup> - [ var x = true;LF}LF{LF] - SpanEditHandler;Accepts:Any - (84:7,11) - Tokens:13
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[var];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[x];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Equals;[=];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[true;];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
HtmlTokenType.Text;[}];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
HtmlTokenType.Text;[{];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
SyntaxKind.HtmlText - [ var x = true;LF}LF{LF] - [84..106) - FullWidth: 22 - Slots: 1
|
||||
SyntaxKind.List - [ var x = true;LF}LF{LF] - [84..106) - FullWidth: 22 - Slots: 13
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[var];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[x];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.Equals;[=];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[true;];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
SyntaxKind.HtmlTextLiteralToken;[}];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
SyntaxKind.HtmlTextLiteralToken;[{];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
Tag block - Gen<None> - 5 - (106:10,0)
|
||||
Markup span - Gen<Markup> - [<col>] - SpanEditHandler;Accepts:Any - (106:10,0) - Tokens:3
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
|
|
@ -84,20 +87,21 @@ Markup block - Gen<None> - 564 - (0:0,0)
|
|||
HtmlTokenType.OpenAngle;[<];
|
||||
HtmlTokenType.Text;[other];
|
||||
HtmlTokenType.CloseAngle;[>];
|
||||
Markup span - Gen<Markup> - [ var x = true;LF}LF{LF] - SpanEditHandler;Accepts:Any - (118:10,12) - Tokens:13
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[var];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[x];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Equals;[=];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[true;];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
HtmlTokenType.Text;[}];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
HtmlTokenType.Text;[{];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
SyntaxKind.HtmlText - [ var x = true;LF}LF{LF] - [118..140) - FullWidth: 22 - Slots: 1
|
||||
SyntaxKind.List - [ var x = true;LF}LF{LF] - [118..140) - FullWidth: 22 - Slots: 13
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[var];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[x];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.Equals;[=];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[true;];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
SyntaxKind.HtmlTextLiteralToken;[}];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
SyntaxKind.HtmlTextLiteralToken;[{];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
Tag block - Gen<None> - 9 - (140:13,0)
|
||||
Markup span - Gen<Markup> - [<command>] - SpanEditHandler;Accepts:Any - (140:13,0) - Tokens:3
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
|
|
@ -108,20 +112,21 @@ Markup block - Gen<None> - 564 - (0:0,0)
|
|||
HtmlTokenType.OpenAngle;[<];
|
||||
HtmlTokenType.Text;[other];
|
||||
HtmlTokenType.CloseAngle;[>];
|
||||
Markup span - Gen<Markup> - [ var x = true;LF}LF{LF] - SpanEditHandler;Accepts:Any - (156:13,16) - Tokens:13
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[var];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[x];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Equals;[=];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[true;];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
HtmlTokenType.Text;[}];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
HtmlTokenType.Text;[{];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
SyntaxKind.HtmlText - [ var x = true;LF}LF{LF] - [156..178) - FullWidth: 22 - Slots: 1
|
||||
SyntaxKind.List - [ var x = true;LF}LF{LF] - [156..178) - FullWidth: 22 - Slots: 13
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[var];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[x];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.Equals;[=];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[true;];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
SyntaxKind.HtmlTextLiteralToken;[}];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
SyntaxKind.HtmlTextLiteralToken;[{];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
Tag block - Gen<None> - 7 - (178:16,0)
|
||||
Markup span - Gen<Markup> - [<embed>] - SpanEditHandler;Accepts:Any - (178:16,0) - Tokens:3
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
|
|
@ -132,20 +137,21 @@ Markup block - Gen<None> - 564 - (0:0,0)
|
|||
HtmlTokenType.OpenAngle;[<];
|
||||
HtmlTokenType.Text;[other];
|
||||
HtmlTokenType.CloseAngle;[>];
|
||||
Markup span - Gen<Markup> - [ var x = true;LF}LF{LF] - SpanEditHandler;Accepts:Any - (192:16,14) - Tokens:13
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[var];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[x];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Equals;[=];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[true;];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
HtmlTokenType.Text;[}];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
HtmlTokenType.Text;[{];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
SyntaxKind.HtmlText - [ var x = true;LF}LF{LF] - [192..214) - FullWidth: 22 - Slots: 1
|
||||
SyntaxKind.List - [ var x = true;LF}LF{LF] - [192..214) - FullWidth: 22 - Slots: 13
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[var];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[x];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.Equals;[=];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[true;];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
SyntaxKind.HtmlTextLiteralToken;[}];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
SyntaxKind.HtmlTextLiteralToken;[{];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
Tag block - Gen<None> - 4 - (214:19,0)
|
||||
Markup span - Gen<Markup> - [<hr>] - SpanEditHandler;Accepts:Any - (214:19,0) - Tokens:3
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
|
|
@ -156,20 +162,21 @@ Markup block - Gen<None> - 564 - (0:0,0)
|
|||
HtmlTokenType.OpenAngle;[<];
|
||||
HtmlTokenType.Text;[other];
|
||||
HtmlTokenType.CloseAngle;[>];
|
||||
Markup span - Gen<Markup> - [ var x = true;LF}LF{LF] - SpanEditHandler;Accepts:Any - (225:19,11) - Tokens:13
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[var];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[x];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Equals;[=];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[true;];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
HtmlTokenType.Text;[}];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
HtmlTokenType.Text;[{];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
SyntaxKind.HtmlText - [ var x = true;LF}LF{LF] - [225..247) - FullWidth: 22 - Slots: 1
|
||||
SyntaxKind.List - [ var x = true;LF}LF{LF] - [225..247) - FullWidth: 22 - Slots: 13
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[var];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[x];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.Equals;[=];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[true;];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
SyntaxKind.HtmlTextLiteralToken;[}];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
SyntaxKind.HtmlTextLiteralToken;[{];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
Tag block - Gen<None> - 5 - (247:22,0)
|
||||
Markup span - Gen<Markup> - [<img>] - SpanEditHandler;Accepts:Any - (247:22,0) - Tokens:3
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
|
|
@ -180,20 +187,21 @@ Markup block - Gen<None> - 564 - (0:0,0)
|
|||
HtmlTokenType.OpenAngle;[<];
|
||||
HtmlTokenType.Text;[other];
|
||||
HtmlTokenType.CloseAngle;[>];
|
||||
Markup span - Gen<Markup> - [ var x = true;LF}LF{LF] - SpanEditHandler;Accepts:Any - (259:22,12) - Tokens:13
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[var];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[x];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Equals;[=];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[true;];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
HtmlTokenType.Text;[}];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
HtmlTokenType.Text;[{];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
SyntaxKind.HtmlText - [ var x = true;LF}LF{LF] - [259..281) - FullWidth: 22 - Slots: 1
|
||||
SyntaxKind.List - [ var x = true;LF}LF{LF] - [259..281) - FullWidth: 22 - Slots: 13
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[var];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[x];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.Equals;[=];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[true;];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
SyntaxKind.HtmlTextLiteralToken;[}];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
SyntaxKind.HtmlTextLiteralToken;[{];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
Tag block - Gen<None> - 7 - (281:25,0)
|
||||
Markup span - Gen<Markup> - [<input>] - SpanEditHandler;Accepts:Any - (281:25,0) - Tokens:3
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
|
|
@ -204,20 +212,21 @@ Markup block - Gen<None> - 564 - (0:0,0)
|
|||
HtmlTokenType.OpenAngle;[<];
|
||||
HtmlTokenType.Text;[other];
|
||||
HtmlTokenType.CloseAngle;[>];
|
||||
Markup span - Gen<Markup> - [ var x = true;LF}LF{LF] - SpanEditHandler;Accepts:Any - (295:25,14) - Tokens:13
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[var];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[x];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Equals;[=];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[true;];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
HtmlTokenType.Text;[}];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
HtmlTokenType.Text;[{];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
SyntaxKind.HtmlText - [ var x = true;LF}LF{LF] - [295..317) - FullWidth: 22 - Slots: 1
|
||||
SyntaxKind.List - [ var x = true;LF}LF{LF] - [295..317) - FullWidth: 22 - Slots: 13
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[var];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[x];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.Equals;[=];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[true;];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
SyntaxKind.HtmlTextLiteralToken;[}];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
SyntaxKind.HtmlTextLiteralToken;[{];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
Tag block - Gen<None> - 8 - (317:28,0)
|
||||
Markup span - Gen<Markup> - [<keygen>] - SpanEditHandler;Accepts:Any - (317:28,0) - Tokens:3
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
|
|
@ -228,20 +237,21 @@ Markup block - Gen<None> - 564 - (0:0,0)
|
|||
HtmlTokenType.OpenAngle;[<];
|
||||
HtmlTokenType.Text;[other];
|
||||
HtmlTokenType.CloseAngle;[>];
|
||||
Markup span - Gen<Markup> - [ var x = true;LF}LF{LF] - SpanEditHandler;Accepts:Any - (332:28,15) - Tokens:13
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[var];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[x];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Equals;[=];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[true;];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
HtmlTokenType.Text;[}];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
HtmlTokenType.Text;[{];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
SyntaxKind.HtmlText - [ var x = true;LF}LF{LF] - [332..354) - FullWidth: 22 - Slots: 1
|
||||
SyntaxKind.List - [ var x = true;LF}LF{LF] - [332..354) - FullWidth: 22 - Slots: 13
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[var];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[x];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.Equals;[=];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[true;];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
SyntaxKind.HtmlTextLiteralToken;[}];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
SyntaxKind.HtmlTextLiteralToken;[{];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
Tag block - Gen<None> - 6 - (354:31,0)
|
||||
Markup span - Gen<Markup> - [<link>] - SpanEditHandler;Accepts:Any - (354:31,0) - Tokens:3
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
|
|
@ -252,20 +262,21 @@ Markup block - Gen<None> - 564 - (0:0,0)
|
|||
HtmlTokenType.OpenAngle;[<];
|
||||
HtmlTokenType.Text;[other];
|
||||
HtmlTokenType.CloseAngle;[>];
|
||||
Markup span - Gen<Markup> - [ var x = true;LF}LF{LF] - SpanEditHandler;Accepts:Any - (367:31,13) - Tokens:13
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[var];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[x];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Equals;[=];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[true;];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
HtmlTokenType.Text;[}];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
HtmlTokenType.Text;[{];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
SyntaxKind.HtmlText - [ var x = true;LF}LF{LF] - [367..389) - FullWidth: 22 - Slots: 1
|
||||
SyntaxKind.List - [ var x = true;LF}LF{LF] - [367..389) - FullWidth: 22 - Slots: 13
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[var];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[x];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.Equals;[=];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[true;];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
SyntaxKind.HtmlTextLiteralToken;[}];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
SyntaxKind.HtmlTextLiteralToken;[{];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
Tag block - Gen<None> - 6 - (389:34,0)
|
||||
Markup span - Gen<Markup> - [<meta>] - SpanEditHandler;Accepts:Any - (389:34,0) - Tokens:3
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
|
|
@ -276,20 +287,21 @@ Markup block - Gen<None> - 564 - (0:0,0)
|
|||
HtmlTokenType.OpenAngle;[<];
|
||||
HtmlTokenType.Text;[other];
|
||||
HtmlTokenType.CloseAngle;[>];
|
||||
Markup span - Gen<Markup> - [ var x = true;LF}LF{LF] - SpanEditHandler;Accepts:Any - (402:34,13) - Tokens:13
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[var];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[x];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Equals;[=];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[true;];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
HtmlTokenType.Text;[}];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
HtmlTokenType.Text;[{];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
SyntaxKind.HtmlText - [ var x = true;LF}LF{LF] - [402..424) - FullWidth: 22 - Slots: 1
|
||||
SyntaxKind.List - [ var x = true;LF}LF{LF] - [402..424) - FullWidth: 22 - Slots: 13
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[var];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[x];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.Equals;[=];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[true;];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
SyntaxKind.HtmlTextLiteralToken;[}];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
SyntaxKind.HtmlTextLiteralToken;[{];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
Tag block - Gen<None> - 7 - (424:37,0)
|
||||
Markup span - Gen<Markup> - [<param>] - SpanEditHandler;Accepts:Any - (424:37,0) - Tokens:3
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
|
|
@ -300,20 +312,21 @@ Markup block - Gen<None> - 564 - (0:0,0)
|
|||
HtmlTokenType.OpenAngle;[<];
|
||||
HtmlTokenType.Text;[other];
|
||||
HtmlTokenType.CloseAngle;[>];
|
||||
Markup span - Gen<Markup> - [ var x = true;LF}LF{LF] - SpanEditHandler;Accepts:Any - (438:37,14) - Tokens:13
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[var];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[x];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Equals;[=];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[true;];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
HtmlTokenType.Text;[}];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
HtmlTokenType.Text;[{];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
SyntaxKind.HtmlText - [ var x = true;LF}LF{LF] - [438..460) - FullWidth: 22 - Slots: 1
|
||||
SyntaxKind.List - [ var x = true;LF}LF{LF] - [438..460) - FullWidth: 22 - Slots: 13
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[var];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[x];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.Equals;[=];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[true;];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
SyntaxKind.HtmlTextLiteralToken;[}];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
SyntaxKind.HtmlTextLiteralToken;[{];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
Tag block - Gen<None> - 8 - (460:40,0)
|
||||
Markup span - Gen<Markup> - [<source>] - SpanEditHandler;Accepts:Any - (460:40,0) - Tokens:3
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
|
|
@ -324,20 +337,21 @@ Markup block - Gen<None> - 564 - (0:0,0)
|
|||
HtmlTokenType.OpenAngle;[<];
|
||||
HtmlTokenType.Text;[other];
|
||||
HtmlTokenType.CloseAngle;[>];
|
||||
Markup span - Gen<Markup> - [ var x = true;LF}LF{LF] - SpanEditHandler;Accepts:Any - (475:40,15) - Tokens:13
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[var];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[x];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Equals;[=];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[true;];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
HtmlTokenType.Text;[}];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
HtmlTokenType.Text;[{];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
SyntaxKind.HtmlText - [ var x = true;LF}LF{LF] - [475..497) - FullWidth: 22 - Slots: 1
|
||||
SyntaxKind.List - [ var x = true;LF}LF{LF] - [475..497) - FullWidth: 22 - Slots: 13
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[var];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[x];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.Equals;[=];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[true;];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
SyntaxKind.HtmlTextLiteralToken;[}];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
SyntaxKind.HtmlTextLiteralToken;[{];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
Tag block - Gen<None> - 7 - (497:43,0)
|
||||
Markup span - Gen<Markup> - [<track>] - SpanEditHandler;Accepts:Any - (497:43,0) - Tokens:3
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
|
|
@ -348,20 +362,21 @@ Markup block - Gen<None> - 564 - (0:0,0)
|
|||
HtmlTokenType.OpenAngle;[<];
|
||||
HtmlTokenType.Text;[other];
|
||||
HtmlTokenType.CloseAngle;[>];
|
||||
Markup span - Gen<Markup> - [ var x = true;LF}LF{LF] - SpanEditHandler;Accepts:Any - (511:43,14) - Tokens:13
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[var];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[x];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Equals;[=];
|
||||
HtmlTokenType.WhiteSpace;[ ];
|
||||
HtmlTokenType.Text;[true;];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
HtmlTokenType.Text;[}];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
HtmlTokenType.Text;[{];
|
||||
HtmlTokenType.NewLine;[LF];
|
||||
SyntaxKind.HtmlText - [ var x = true;LF}LF{LF] - [511..533) - FullWidth: 22 - Slots: 1
|
||||
SyntaxKind.List - [ var x = true;LF}LF{LF] - [511..533) - FullWidth: 22 - Slots: 13
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[var];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[x];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.Equals;[=];
|
||||
SyntaxKind.Whitespace;[ ];
|
||||
SyntaxKind.HtmlTextLiteralToken;[true;];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
SyntaxKind.HtmlTextLiteralToken;[}];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
SyntaxKind.HtmlTextLiteralToken;[{];
|
||||
SyntaxKind.NewLine;[LF];
|
||||
Tag block - Gen<None> - 5 - (533:46,0)
|
||||
Markup span - Gen<Markup> - [<wbr>] - SpanEditHandler;Accepts:Any - (533:46,0) - Tokens:3
|
||||
HtmlTokenType.OpenAngle;[<];
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue