Add diagnostics to the IR.
- Added a `Diagnostics` and `HasDiagnostics` properties to `RazorIRNode`. The `HasDiagnostics` property was necessary in order to traverse nodes without forcibly instantiating their diagnostic lists. - Added `GetAllDiagnostics` extension method for `RazorIRNode` to provide a way to retrieve all diagnostics that exist on and under a `RazorIRNode`. - Updated `RazorIRNodeWriter` to display any diagnostics that exist on IR nodes. - Internal `RazorIRNode`s do not have mutable `Diagnostics` because we don't currently add diagnostics to these elements. - Added `DefaultIRLoweringPhaseTest` to validate that errors flow from syntax tree to IR document. Also added a missing test. - Updated the `CSharpLoweringPhaseTest`s to properly validate that errors flow from IR document => csharp document. This resulted in movement of code to the ir lowering phase tests. #1412
This commit is contained in:
parent
6860806213
commit
e3287ae672
|
|
@ -20,9 +20,6 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
var irDocument = codeDocument.GetIRDocument();
|
||||
ThrowForMissingDocumentDependency(irDocument);
|
||||
|
||||
var syntaxTree = codeDocument.GetSyntaxTree();
|
||||
ThrowForMissingDocumentDependency(syntaxTree);
|
||||
|
||||
var target = irDocument.Target;
|
||||
if (target == null)
|
||||
{
|
||||
|
|
@ -59,13 +56,7 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
documentWriter.WriteDocument(irDocument);
|
||||
|
||||
var diagnostics = new List<RazorDiagnostic>();
|
||||
diagnostics.AddRange(syntaxTree.Diagnostics);
|
||||
|
||||
var importSyntaxTrees = codeDocument.GetImportSyntaxTrees();
|
||||
for (var i = 0; i < importSyntaxTrees?.Count; i++)
|
||||
{
|
||||
diagnostics.AddRange(importSyntaxTrees[i].Diagnostics);
|
||||
}
|
||||
diagnostics.AddRange(irDocument.GetAllDiagnostics());
|
||||
diagnostics.AddRange(renderingContext.Diagnostics);
|
||||
|
||||
var csharpDocument = RazorCSharpDocument.Create(
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
|
||||
// This might not have been set if there are no tag helpers.
|
||||
var tagHelperContext = codeDocument.GetTagHelperContext();
|
||||
|
||||
|
||||
var document = new DocumentIRNode();
|
||||
var builder = RazorIRBuilder.Create(document);
|
||||
|
||||
|
|
@ -76,6 +76,26 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
builder.Insert(i++, @using);
|
||||
}
|
||||
|
||||
// The document should contain all errors that currently exist in the system. This involves
|
||||
// adding the errors from the primary and imported syntax trees.
|
||||
|
||||
for (i = 0; i < syntaxTree.Diagnostics.Count; i++)
|
||||
{
|
||||
document.Diagnostics.Add(syntaxTree.Diagnostics[i]);
|
||||
}
|
||||
|
||||
if (imports != null)
|
||||
{
|
||||
for (i = 0; i < imports.Count; i++)
|
||||
{
|
||||
var import = imports[i];
|
||||
for (var j = 0; j < import.Diagnostics.Count; j++)
|
||||
{
|
||||
document.Diagnostics.Add(import.Diagnostics[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
codeDocument.SetIRDocument(document);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,10 +8,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
{
|
||||
internal sealed class AddPreallocatedTagHelperHtmlAttributeIRNode : ExtensionIRNode
|
||||
{
|
||||
public override RazorDiagnosticCollection Diagnostics { get; } = ReadOnlyDiagnosticCollection.Instance;
|
||||
|
||||
public override RazorIRNodeCollection Children => ReadOnlyIRNodeCollection.Instance;
|
||||
|
||||
public override SourceSpan? Source { get; set; }
|
||||
|
||||
public override bool HasDiagnostics => false;
|
||||
|
||||
public string VariableName { get; set; }
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
|
|
|
|||
|
|
@ -8,12 +8,29 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
{
|
||||
public sealed class AddTagHelperHtmlAttributeIRNode : RazorIRNode
|
||||
{
|
||||
private RazorDiagnosticCollection _diagnostics;
|
||||
|
||||
public override ItemCollection Annotations => ReadOnlyItemCollection.Empty;
|
||||
|
||||
public override RazorDiagnosticCollection Diagnostics
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_diagnostics == null)
|
||||
{
|
||||
_diagnostics = new DefaultDiagnosticCollection();
|
||||
}
|
||||
|
||||
return _diagnostics;
|
||||
}
|
||||
}
|
||||
|
||||
public override RazorIRNodeCollection Children { get; } = new DefaultIRNodeCollection();
|
||||
|
||||
public override SourceSpan? Source { get; set; }
|
||||
|
||||
public override bool HasDiagnostics => _diagnostics != null && _diagnostics.Count > 0;
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
internal HtmlAttributeValueStyle ValueStyle { get; set; }
|
||||
|
|
|
|||
|
|
@ -7,12 +7,29 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
{
|
||||
public sealed class CSharpCodeAttributeValueIRNode : RazorIRNode
|
||||
{
|
||||
private RazorDiagnosticCollection _diagnostics;
|
||||
|
||||
public override ItemCollection Annotations => ReadOnlyItemCollection.Empty;
|
||||
|
||||
public override RazorDiagnosticCollection Diagnostics
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_diagnostics == null)
|
||||
{
|
||||
_diagnostics = new DefaultDiagnosticCollection();
|
||||
}
|
||||
|
||||
return _diagnostics;
|
||||
}
|
||||
}
|
||||
|
||||
public override RazorIRNodeCollection Children { get; } = new DefaultIRNodeCollection();
|
||||
|
||||
public override SourceSpan? Source { get; set; }
|
||||
|
||||
public override bool HasDiagnostics => _diagnostics != null && _diagnostics.Count > 0;
|
||||
|
||||
public string Prefix { get; set; }
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
public sealed class CSharpCodeIRNode : RazorIRNode
|
||||
{
|
||||
private ItemCollection _annotations;
|
||||
private RazorDiagnosticCollection _diagnostics;
|
||||
|
||||
public override ItemCollection Annotations
|
||||
{
|
||||
|
|
@ -22,10 +23,25 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
}
|
||||
}
|
||||
|
||||
public override RazorDiagnosticCollection Diagnostics
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_diagnostics == null)
|
||||
{
|
||||
_diagnostics = new DefaultDiagnosticCollection();
|
||||
}
|
||||
|
||||
return _diagnostics;
|
||||
}
|
||||
}
|
||||
|
||||
public override RazorIRNodeCollection Children { get; } = new DefaultIRNodeCollection();
|
||||
|
||||
public override SourceSpan? Source { get; set; }
|
||||
|
||||
public override bool HasDiagnostics => _diagnostics != null && _diagnostics.Count > 0;
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
{
|
||||
if (visitor == null)
|
||||
|
|
|
|||
|
|
@ -7,12 +7,29 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
{
|
||||
public sealed class CSharpExpressionAttributeValueIRNode : RazorIRNode
|
||||
{
|
||||
private RazorDiagnosticCollection _diagnostics;
|
||||
|
||||
public override ItemCollection Annotations => ReadOnlyItemCollection.Empty;
|
||||
|
||||
public override RazorDiagnosticCollection Diagnostics
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_diagnostics == null)
|
||||
{
|
||||
_diagnostics = new DefaultDiagnosticCollection();
|
||||
}
|
||||
|
||||
return _diagnostics;
|
||||
}
|
||||
}
|
||||
|
||||
public override RazorIRNodeCollection Children { get; } = new DefaultIRNodeCollection();
|
||||
|
||||
public override SourceSpan? Source { get; set; }
|
||||
|
||||
public override bool HasDiagnostics => _diagnostics != null && _diagnostics.Count > 0;
|
||||
|
||||
public string Prefix { get; set; }
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
public sealed class CSharpExpressionIRNode : RazorIRNode
|
||||
{
|
||||
private ItemCollection _annotations;
|
||||
private RazorDiagnosticCollection _diagnostics;
|
||||
|
||||
public override ItemCollection Annotations
|
||||
{
|
||||
|
|
@ -22,10 +23,25 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
}
|
||||
}
|
||||
|
||||
public override RazorDiagnosticCollection Diagnostics
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_diagnostics == null)
|
||||
{
|
||||
_diagnostics = new DefaultDiagnosticCollection();
|
||||
}
|
||||
|
||||
return _diagnostics;
|
||||
}
|
||||
}
|
||||
|
||||
public override RazorIRNodeCollection Children { get; } = new DefaultIRNodeCollection();
|
||||
|
||||
public override SourceSpan? Source { get; set; }
|
||||
|
||||
public override bool HasDiagnostics => _diagnostics != null && _diagnostics.Count > 0;
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
{
|
||||
if (visitor == null)
|
||||
|
|
|
|||
|
|
@ -7,12 +7,29 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
{
|
||||
public sealed class ChecksumIRNode : RazorIRNode
|
||||
{
|
||||
private RazorDiagnosticCollection _diagnostics;
|
||||
|
||||
public override ItemCollection Annotations => ReadOnlyItemCollection.Empty;
|
||||
|
||||
public override RazorDiagnosticCollection Diagnostics
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_diagnostics == null)
|
||||
{
|
||||
_diagnostics = new DefaultDiagnosticCollection();
|
||||
}
|
||||
|
||||
return _diagnostics;
|
||||
}
|
||||
}
|
||||
|
||||
public override RazorIRNodeCollection Children => ReadOnlyIRNodeCollection.Instance;
|
||||
|
||||
public override SourceSpan? Source { get; set; }
|
||||
|
||||
public override bool HasDiagnostics => _diagnostics != null && _diagnostics.Count > 0;
|
||||
|
||||
public string Bytes { get; set; }
|
||||
|
||||
public string FilePath { get; set; }
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
public sealed class ClassDeclarationIRNode : MemberDeclarationIRNode
|
||||
{
|
||||
private ItemCollection _annotations;
|
||||
private RazorDiagnosticCollection _diagnostics;
|
||||
|
||||
public override ItemCollection Annotations
|
||||
{
|
||||
|
|
@ -23,10 +24,25 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
}
|
||||
}
|
||||
|
||||
public override RazorDiagnosticCollection Diagnostics
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_diagnostics == null)
|
||||
{
|
||||
_diagnostics = new DefaultDiagnosticCollection();
|
||||
}
|
||||
|
||||
return _diagnostics;
|
||||
}
|
||||
}
|
||||
|
||||
public override RazorIRNodeCollection Children { get; } = new DefaultIRNodeCollection();
|
||||
|
||||
public override SourceSpan? Source { get; set; }
|
||||
|
||||
public override bool HasDiagnostics => _diagnostics != null && _diagnostics.Count > 0;
|
||||
|
||||
public string AccessModifier { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
|
|
|||
|
|
@ -7,12 +7,29 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
{
|
||||
public sealed class CreateTagHelperIRNode : RazorIRNode
|
||||
{
|
||||
private RazorDiagnosticCollection _diagnostics;
|
||||
|
||||
public override ItemCollection Annotations => ReadOnlyItemCollection.Empty;
|
||||
|
||||
public override RazorDiagnosticCollection Diagnostics
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_diagnostics == null)
|
||||
{
|
||||
_diagnostics = new DefaultDiagnosticCollection();
|
||||
}
|
||||
|
||||
return _diagnostics;
|
||||
}
|
||||
}
|
||||
|
||||
public override RazorIRNodeCollection Children => ReadOnlyIRNodeCollection.Instance;
|
||||
|
||||
public override SourceSpan? Source { get; set; }
|
||||
|
||||
public override bool HasDiagnostics => _diagnostics != null && _diagnostics.Count > 0;
|
||||
|
||||
public string TagHelperTypeName { get; set; }
|
||||
|
||||
public TagHelperDescriptor Descriptor { get; set; }
|
||||
|
|
|
|||
|
|
@ -9,10 +9,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
{
|
||||
internal sealed class DeclarePreallocatedTagHelperAttributeIRNode : ExtensionIRNode
|
||||
{
|
||||
public override RazorDiagnosticCollection Diagnostics { get; } = ReadOnlyDiagnosticCollection.Instance;
|
||||
|
||||
public override RazorIRNodeCollection Children => ReadOnlyIRNodeCollection.Instance;
|
||||
|
||||
public override SourceSpan? Source { get; set; }
|
||||
|
||||
public override bool HasDiagnostics => false;
|
||||
|
||||
public string VariableName { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
|
|
|||
|
|
@ -9,10 +9,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
{
|
||||
internal sealed class DeclarePreallocatedTagHelperHtmlAttributeIRNode : ExtensionIRNode
|
||||
{
|
||||
public override RazorDiagnosticCollection Diagnostics { get; } = ReadOnlyDiagnosticCollection.Instance;
|
||||
|
||||
public override RazorIRNodeCollection Children => ReadOnlyIRNodeCollection.Instance;
|
||||
|
||||
public override SourceSpan? Source { get; set; }
|
||||
|
||||
public override bool HasDiagnostics => false;
|
||||
|
||||
public string VariableName { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
|
|
|||
|
|
@ -8,12 +8,29 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
{
|
||||
public sealed class DeclareTagHelperFieldsIRNode : RazorIRNode
|
||||
{
|
||||
private RazorDiagnosticCollection _diagnostics;
|
||||
|
||||
public override ItemCollection Annotations => ReadOnlyItemCollection.Empty;
|
||||
|
||||
public override RazorDiagnosticCollection Diagnostics
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_diagnostics == null)
|
||||
{
|
||||
_diagnostics = new DefaultDiagnosticCollection();
|
||||
}
|
||||
|
||||
return _diagnostics;
|
||||
}
|
||||
}
|
||||
|
||||
public override RazorIRNodeCollection Children => ReadOnlyIRNodeCollection.Instance;
|
||||
|
||||
public override SourceSpan? Source { get; set; }
|
||||
|
||||
public override bool HasDiagnostics => _diagnostics != null && _diagnostics.Count > 0;
|
||||
|
||||
public ISet<string> UsedTagHelperTypeNames { get; set; } = new HashSet<string>(StringComparer.Ordinal);
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,128 @@
|
|||
// 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.Intermediate
|
||||
{
|
||||
public sealed class DefaultDiagnosticCollection : RazorDiagnosticCollection
|
||||
{
|
||||
private readonly List<RazorDiagnostic> _inner = new List<RazorDiagnostic>();
|
||||
|
||||
public override RazorDiagnostic this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (index < 0 || index >= Count)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
}
|
||||
|
||||
return _inner[index];
|
||||
}
|
||||
set
|
||||
{
|
||||
if (index < 0 || index >= Count)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
}
|
||||
|
||||
_inner[index] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override int Count => _inner.Count;
|
||||
|
||||
public override bool IsReadOnly => false;
|
||||
|
||||
public override void Add(RazorDiagnostic item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(item));
|
||||
}
|
||||
|
||||
_inner.Add(item);
|
||||
}
|
||||
|
||||
public override void Clear()
|
||||
{
|
||||
_inner.Clear();
|
||||
}
|
||||
|
||||
public override bool Contains(RazorDiagnostic item)
|
||||
{
|
||||
return _inner.Contains(item);
|
||||
}
|
||||
|
||||
public override void CopyTo(RazorDiagnostic[] array, int arrayIndex)
|
||||
{
|
||||
if (array == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(array));
|
||||
}
|
||||
|
||||
if (arrayIndex < 0 || arrayIndex > array.Length)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(arrayIndex));
|
||||
}
|
||||
else if (array.Length - arrayIndex < Count)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(arrayIndex));
|
||||
}
|
||||
|
||||
_inner.CopyTo(array, arrayIndex);
|
||||
}
|
||||
|
||||
public override IEnumerator<RazorDiagnostic> GetEnumerator()
|
||||
{
|
||||
return _inner.GetEnumerator();
|
||||
}
|
||||
|
||||
public override int IndexOf(RazorDiagnostic item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(item));
|
||||
}
|
||||
|
||||
return _inner.IndexOf(item);
|
||||
}
|
||||
|
||||
public override void Insert(int index, RazorDiagnostic item)
|
||||
{
|
||||
if (index < 0 || index > Count)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
}
|
||||
|
||||
if (item == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(item));
|
||||
}
|
||||
|
||||
_inner.Insert(index, item);
|
||||
}
|
||||
|
||||
public override bool Remove(RazorDiagnostic item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(item));
|
||||
}
|
||||
|
||||
return _inner.Remove(item);
|
||||
}
|
||||
|
||||
public override void RemoveAt(int index)
|
||||
{
|
||||
if (index < 0 || index >= Count)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
}
|
||||
|
||||
_inner.RemoveAt(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
public sealed class DirectiveIRNode : RazorIRNode
|
||||
{
|
||||
private ItemCollection _annotations;
|
||||
private RazorDiagnosticCollection _diagnostics;
|
||||
|
||||
public override ItemCollection Annotations
|
||||
{
|
||||
|
|
@ -23,10 +24,25 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
}
|
||||
}
|
||||
|
||||
public override RazorDiagnosticCollection Diagnostics
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_diagnostics == null)
|
||||
{
|
||||
_diagnostics = new DefaultDiagnosticCollection();
|
||||
}
|
||||
|
||||
return _diagnostics;
|
||||
}
|
||||
}
|
||||
|
||||
public override RazorIRNodeCollection Children { get; } = new DefaultIRNodeCollection();
|
||||
|
||||
public override SourceSpan? Source { get; set; }
|
||||
|
||||
public override bool HasDiagnostics => _diagnostics != null && _diagnostics.Count > 0;
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public IEnumerable<DirectiveTokenIRNode> Tokens => Children.OfType<DirectiveTokenIRNode>();
|
||||
|
|
|
|||
|
|
@ -5,12 +5,29 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
{
|
||||
public sealed class DirectiveTokenIRNode : RazorIRNode
|
||||
{
|
||||
private RazorDiagnosticCollection _diagnostics;
|
||||
|
||||
public override ItemCollection Annotations => ReadOnlyItemCollection.Empty;
|
||||
|
||||
public override RazorDiagnosticCollection Diagnostics
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_diagnostics == null)
|
||||
{
|
||||
_diagnostics = new DefaultDiagnosticCollection();
|
||||
}
|
||||
|
||||
return _diagnostics;
|
||||
}
|
||||
}
|
||||
|
||||
public override RazorIRNodeCollection Children => ReadOnlyIRNodeCollection.Instance;
|
||||
|
||||
public override SourceSpan? Source { get; set; }
|
||||
|
||||
public override bool HasDiagnostics => _diagnostics != null && _diagnostics.Count > 0;
|
||||
|
||||
public string Content { get; set; }
|
||||
|
||||
public DirectiveTokenDescriptor Descriptor { get; set; }
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
public sealed class DocumentIRNode : RazorIRNode
|
||||
{
|
||||
private ItemCollection _annotations;
|
||||
private RazorDiagnosticCollection _diagnostics;
|
||||
|
||||
public override ItemCollection Annotations
|
||||
{
|
||||
|
|
@ -23,6 +24,19 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
}
|
||||
}
|
||||
|
||||
public override RazorDiagnosticCollection Diagnostics
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_diagnostics == null)
|
||||
{
|
||||
_diagnostics = new DefaultDiagnosticCollection();
|
||||
}
|
||||
|
||||
return _diagnostics;
|
||||
}
|
||||
}
|
||||
|
||||
public override RazorIRNodeCollection Children { get; } = new DefaultIRNodeCollection();
|
||||
|
||||
public string DocumentKind { get; set; }
|
||||
|
|
@ -31,6 +45,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
|
||||
public override SourceSpan? Source { get; set; }
|
||||
|
||||
public override bool HasDiagnostics => _diagnostics != null && _diagnostics.Count > 0;
|
||||
|
||||
public CodeTarget Target { get; set; }
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
public abstract class ExtensionIRNode : RazorIRNode
|
||||
{
|
||||
private ItemCollection _annotations;
|
||||
private RazorDiagnosticCollection _diagnostics;
|
||||
|
||||
public override ItemCollection Annotations
|
||||
{
|
||||
|
|
@ -22,9 +23,24 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
}
|
||||
}
|
||||
|
||||
public override RazorDiagnosticCollection Diagnostics
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_diagnostics == null)
|
||||
{
|
||||
_diagnostics = new DefaultDiagnosticCollection();
|
||||
}
|
||||
|
||||
return _diagnostics;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool HasDiagnostics => _diagnostics != null && _diagnostics.Count > 0;
|
||||
|
||||
public abstract void WriteNode(CodeTarget target, CSharpRenderingContext context);
|
||||
|
||||
protected static void AcceptExtensionNode<TNode>(TNode node, RazorIRNodeVisitor visitor)
|
||||
protected static void AcceptExtensionNode<TNode>(TNode node, RazorIRNodeVisitor visitor)
|
||||
where TNode : ExtensionIRNode
|
||||
{
|
||||
var typedVisitor = visitor as IExtensionIRNodeVisitor<TNode>;
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
public sealed class FieldDeclarationIRNode : MemberDeclarationIRNode
|
||||
{
|
||||
private ItemCollection _annotations;
|
||||
private RazorDiagnosticCollection _diagnostics;
|
||||
|
||||
public override ItemCollection Annotations
|
||||
{
|
||||
|
|
@ -23,12 +24,27 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
}
|
||||
}
|
||||
|
||||
public override RazorDiagnosticCollection Diagnostics
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_diagnostics == null)
|
||||
{
|
||||
_diagnostics = new DefaultDiagnosticCollection();
|
||||
}
|
||||
|
||||
return _diagnostics;
|
||||
}
|
||||
}
|
||||
|
||||
public override RazorIRNodeCollection Children => ReadOnlyIRNodeCollection.Instance;
|
||||
|
||||
public IList<string> Modifiers { get; set; } = new List<string>();
|
||||
|
||||
public override SourceSpan? Source { get; set; }
|
||||
|
||||
public override bool HasDiagnostics => _diagnostics != null && _diagnostics.Count > 0;
|
||||
|
||||
public string AccessModifier { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
|
|
|||
|
|
@ -7,12 +7,29 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
{
|
||||
public sealed class HtmlAttributeIRNode : RazorIRNode
|
||||
{
|
||||
private RazorDiagnosticCollection _diagnostics;
|
||||
|
||||
public override ItemCollection Annotations => ReadOnlyItemCollection.Empty;
|
||||
|
||||
public override RazorDiagnosticCollection Diagnostics
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_diagnostics == null)
|
||||
{
|
||||
_diagnostics = new DefaultDiagnosticCollection();
|
||||
}
|
||||
|
||||
return _diagnostics;
|
||||
}
|
||||
}
|
||||
|
||||
public override RazorIRNodeCollection Children { get; } = new DefaultIRNodeCollection();
|
||||
|
||||
public override SourceSpan? Source { get; set; }
|
||||
|
||||
public override bool HasDiagnostics => _diagnostics != null && _diagnostics.Count > 0;
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public string Prefix { get; set; }
|
||||
|
|
|
|||
|
|
@ -8,12 +8,29 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
{
|
||||
public sealed class HtmlAttributeValueIRNode : RazorIRNode
|
||||
{
|
||||
private RazorDiagnosticCollection _diagnostics;
|
||||
|
||||
public override ItemCollection Annotations => ReadOnlyItemCollection.Empty;
|
||||
|
||||
public override RazorDiagnosticCollection Diagnostics
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_diagnostics == null)
|
||||
{
|
||||
_diagnostics = new DefaultDiagnosticCollection();
|
||||
}
|
||||
|
||||
return _diagnostics;
|
||||
}
|
||||
}
|
||||
|
||||
public override RazorIRNodeCollection Children { get; } = new DefaultIRNodeCollection();
|
||||
|
||||
public override SourceSpan? Source { get; set; }
|
||||
|
||||
public override bool HasDiagnostics => _diagnostics != null && _diagnostics.Count > 0;
|
||||
|
||||
public string Prefix { get; set; }
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
|
|
|
|||
|
|
@ -8,12 +8,29 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
{
|
||||
public sealed class HtmlContentIRNode : RazorIRNode
|
||||
{
|
||||
private RazorDiagnosticCollection _diagnostics;
|
||||
|
||||
public override ItemCollection Annotations => ReadOnlyItemCollection.Empty;
|
||||
|
||||
public override RazorDiagnosticCollection Diagnostics
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_diagnostics == null)
|
||||
{
|
||||
_diagnostics = new DefaultDiagnosticCollection();
|
||||
}
|
||||
|
||||
return _diagnostics;
|
||||
}
|
||||
}
|
||||
|
||||
public override RazorIRNodeCollection Children { get; } = new DefaultIRNodeCollection();
|
||||
|
||||
public override SourceSpan? Source { get; set; }
|
||||
|
||||
public override bool HasDiagnostics => _diagnostics != null && _diagnostics.Count > 0;
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
{
|
||||
if (visitor == null)
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
public sealed class MethodDeclarationIRNode : MemberDeclarationIRNode
|
||||
{
|
||||
private ItemCollection _annotations;
|
||||
private RazorDiagnosticCollection _diagnostics;
|
||||
|
||||
public override ItemCollection Annotations
|
||||
{
|
||||
|
|
@ -23,10 +24,25 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
}
|
||||
}
|
||||
|
||||
public override RazorDiagnosticCollection Diagnostics
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_diagnostics == null)
|
||||
{
|
||||
_diagnostics = new DefaultDiagnosticCollection();
|
||||
}
|
||||
|
||||
return _diagnostics;
|
||||
}
|
||||
}
|
||||
|
||||
public override RazorIRNodeCollection Children { get; } = new DefaultIRNodeCollection();
|
||||
|
||||
public override SourceSpan? Source { get; set; }
|
||||
|
||||
public override bool HasDiagnostics => _diagnostics != null && _diagnostics.Count > 0;
|
||||
|
||||
public string AccessModifier { get; set; }
|
||||
|
||||
public IList<string> Modifiers { get; set; } = new List<string>();
|
||||
|
|
@ -44,5 +60,6 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
|
||||
visitor.VisitMethodDeclaration(this);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
public sealed class NamespaceDeclarationIRNode : RazorIRNode
|
||||
{
|
||||
private ItemCollection _annotations;
|
||||
private RazorDiagnosticCollection _diagnostics;
|
||||
|
||||
public override ItemCollection Annotations
|
||||
{
|
||||
|
|
@ -22,10 +23,25 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
}
|
||||
}
|
||||
|
||||
public override RazorDiagnosticCollection Diagnostics
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_diagnostics == null)
|
||||
{
|
||||
_diagnostics = new DefaultDiagnosticCollection();
|
||||
}
|
||||
|
||||
return _diagnostics;
|
||||
}
|
||||
}
|
||||
|
||||
public override RazorIRNodeCollection Children { get; } = new DefaultIRNodeCollection();
|
||||
|
||||
public override SourceSpan? Source { get; set; }
|
||||
|
||||
public override bool HasDiagnostics => _diagnostics != null && _diagnostics.Count > 0;
|
||||
|
||||
public string Content { get; set; }
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
public sealed class PropertyDeclarationIRNode : MemberDeclarationIRNode
|
||||
{
|
||||
private ItemCollection _annotations;
|
||||
private RazorDiagnosticCollection _diagnostics;
|
||||
|
||||
public override ItemCollection Annotations
|
||||
{
|
||||
|
|
@ -23,12 +24,27 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
}
|
||||
}
|
||||
|
||||
public override RazorDiagnosticCollection Diagnostics
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_diagnostics == null)
|
||||
{
|
||||
_diagnostics = new DefaultDiagnosticCollection();
|
||||
}
|
||||
|
||||
return _diagnostics;
|
||||
}
|
||||
}
|
||||
|
||||
public override RazorIRNodeCollection Children => ReadOnlyIRNodeCollection.Instance;
|
||||
|
||||
public IList<string> Modifiers { get; set; } = new List<string>();
|
||||
|
||||
public override SourceSpan? Source { get; set; }
|
||||
|
||||
public override bool HasDiagnostics => _diagnostics != null && _diagnostics.Count > 0;
|
||||
|
||||
public string AccessModifier { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
// 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;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
||||
{
|
||||
public abstract class RazorDiagnosticCollection : IList<RazorDiagnostic>
|
||||
{
|
||||
public abstract RazorDiagnostic this[int index] { get; set; }
|
||||
|
||||
public abstract int Count { get; }
|
||||
|
||||
public abstract bool IsReadOnly { get; }
|
||||
|
||||
public abstract void Add(RazorDiagnostic item);
|
||||
|
||||
public abstract void Clear();
|
||||
|
||||
public abstract bool Contains(RazorDiagnostic item);
|
||||
|
||||
public abstract void CopyTo(RazorDiagnostic[] array, int arrayIndex);
|
||||
|
||||
public abstract IEnumerator<RazorDiagnostic> GetEnumerator();
|
||||
|
||||
public abstract int IndexOf(RazorDiagnostic item);
|
||||
|
||||
public abstract void Insert(int index, RazorDiagnostic item);
|
||||
|
||||
public abstract bool Remove(RazorDiagnostic item);
|
||||
|
||||
public abstract void RemoveAt(int index);
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,10 +7,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
{
|
||||
public abstract ItemCollection Annotations { get; }
|
||||
|
||||
public abstract RazorDiagnosticCollection Diagnostics { get; }
|
||||
|
||||
public abstract RazorIRNodeCollection Children { get; }
|
||||
|
||||
public abstract SourceSpan? Source { get; set; }
|
||||
|
||||
public abstract bool HasDiagnostics { get; }
|
||||
|
||||
public abstract void Accept(RazorIRNodeVisitor visitor);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
// 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.Intermediate
|
||||
{
|
||||
public static class RazorIRNodeExtensions
|
||||
{
|
||||
private static readonly IReadOnlyList<RazorDiagnostic> EmptyDiagnostics = Array.Empty<RazorDiagnostic>();
|
||||
|
||||
public static IReadOnlyList<RazorDiagnostic> GetAllDiagnostics(this RazorIRNode node)
|
||||
{
|
||||
if (node == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(node));
|
||||
}
|
||||
|
||||
HashSet<RazorDiagnostic> diagnostics = null;
|
||||
|
||||
AddAllDiagnostics(node);
|
||||
|
||||
return diagnostics?.ToList() ?? EmptyDiagnostics;
|
||||
|
||||
void AddAllDiagnostics(RazorIRNode n)
|
||||
{
|
||||
if (n.HasDiagnostics)
|
||||
{
|
||||
if (diagnostics == null)
|
||||
{
|
||||
diagnostics = new HashSet<RazorDiagnostic>();
|
||||
}
|
||||
|
||||
diagnostics.UnionWith(n.Diagnostics);
|
||||
}
|
||||
|
||||
for (var i = 0; i < n.Children.Count; i++)
|
||||
{
|
||||
AddAllDiagnostics(n.Children[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,8 +7,23 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
{
|
||||
public sealed class RazorIRToken : RazorIRNode
|
||||
{
|
||||
private RazorDiagnosticCollection _diagnostics;
|
||||
|
||||
public override ItemCollection Annotations => ReadOnlyItemCollection.Empty;
|
||||
|
||||
public override RazorDiagnosticCollection Diagnostics
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_diagnostics == null)
|
||||
{
|
||||
_diagnostics = new DefaultDiagnosticCollection();
|
||||
}
|
||||
|
||||
return _diagnostics;
|
||||
}
|
||||
}
|
||||
|
||||
public override RazorIRNodeCollection Children => ReadOnlyIRNodeCollection.Instance;
|
||||
|
||||
public string Content { get; set; }
|
||||
|
|
@ -21,6 +36,8 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
|
||||
public override SourceSpan? Source { get; set; }
|
||||
|
||||
public override bool HasDiagnostics => _diagnostics != null && _diagnostics.Count > 0;
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
{
|
||||
if (visitor == null)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,133 @@
|
|||
// 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.Intermediate
|
||||
{
|
||||
public sealed class ReadOnlyDiagnosticCollection : RazorDiagnosticCollection
|
||||
{
|
||||
public static readonly ReadOnlyDiagnosticCollection Instance = new ReadOnlyDiagnosticCollection();
|
||||
|
||||
private ReadOnlyDiagnosticCollection()
|
||||
{
|
||||
}
|
||||
|
||||
public override RazorDiagnostic this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (index < 0 || index >= Count)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
}
|
||||
|
||||
throw null; // Unreachable
|
||||
}
|
||||
set
|
||||
{
|
||||
if (index < 0 || index >= Count)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
}
|
||||
|
||||
throw null; // Unreachable
|
||||
}
|
||||
}
|
||||
|
||||
public override int Count => 0;
|
||||
|
||||
public override bool IsReadOnly => true;
|
||||
|
||||
public override void Add(RazorDiagnostic item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(item));
|
||||
}
|
||||
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override void Clear()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override bool Contains(RazorDiagnostic item)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void CopyTo(RazorDiagnostic[] array, int arrayIndex)
|
||||
{
|
||||
if (array == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(array));
|
||||
}
|
||||
|
||||
if (arrayIndex < 0 || arrayIndex > array.Length)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(arrayIndex));
|
||||
}
|
||||
else if (array.Length - arrayIndex < Count)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(arrayIndex));
|
||||
}
|
||||
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override IEnumerator<RazorDiagnostic> GetEnumerator()
|
||||
{
|
||||
return Enumerable.Empty<RazorDiagnostic>().GetEnumerator();
|
||||
}
|
||||
|
||||
public override int IndexOf(RazorDiagnostic item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(item));
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public override void Insert(int index, RazorDiagnostic item)
|
||||
{
|
||||
if (index < 0 || index > Count)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
}
|
||||
|
||||
if (item == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(item));
|
||||
}
|
||||
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override bool Remove(RazorDiagnostic item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(item));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void RemoveAt(int index)
|
||||
{
|
||||
if (index < 0 || index >= Count)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
}
|
||||
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,10 +8,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
{
|
||||
internal sealed class SetPreallocatedTagHelperPropertyIRNode : ExtensionIRNode
|
||||
{
|
||||
public override RazorDiagnosticCollection Diagnostics => ReadOnlyDiagnosticCollection.Instance;
|
||||
|
||||
public override RazorIRNodeCollection Children => ReadOnlyIRNodeCollection.Instance;
|
||||
|
||||
public override SourceSpan? Source { get; set; }
|
||||
|
||||
public override bool HasDiagnostics => false;
|
||||
|
||||
public string VariableName { get; set; }
|
||||
|
||||
public string AttributeName { get; set; }
|
||||
|
|
|
|||
|
|
@ -8,12 +8,29 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
{
|
||||
public sealed class SetTagHelperPropertyIRNode : RazorIRNode
|
||||
{
|
||||
private RazorDiagnosticCollection _diagnostics;
|
||||
|
||||
public override ItemCollection Annotations => ReadOnlyItemCollection.Empty;
|
||||
|
||||
public override RazorDiagnosticCollection Diagnostics
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_diagnostics == null)
|
||||
{
|
||||
_diagnostics = new DefaultDiagnosticCollection();
|
||||
}
|
||||
|
||||
return _diagnostics;
|
||||
}
|
||||
}
|
||||
|
||||
public override RazorIRNodeCollection Children { get; } = new DefaultIRNodeCollection();
|
||||
|
||||
public override SourceSpan? Source { get; set; }
|
||||
|
||||
public override bool HasDiagnostics => _diagnostics != null && _diagnostics.Count > 0;
|
||||
|
||||
public string TagHelperTypeName { get; set; }
|
||||
|
||||
public string PropertyName { get; set; }
|
||||
|
|
|
|||
|
|
@ -7,12 +7,29 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
{
|
||||
public sealed class TagHelperBodyIRNode : RazorIRNode
|
||||
{
|
||||
private RazorDiagnosticCollection _diagnostics;
|
||||
|
||||
public override ItemCollection Annotations => ReadOnlyItemCollection.Empty;
|
||||
|
||||
public override RazorDiagnosticCollection Diagnostics
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_diagnostics == null)
|
||||
{
|
||||
_diagnostics = new DefaultDiagnosticCollection();
|
||||
}
|
||||
|
||||
return _diagnostics;
|
||||
}
|
||||
}
|
||||
|
||||
public override RazorIRNodeCollection Children { get; } = new DefaultIRNodeCollection();
|
||||
|
||||
public override SourceSpan? Source { get; set; }
|
||||
|
||||
public override bool HasDiagnostics => _diagnostics != null && _diagnostics.Count > 0;
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
{
|
||||
if (visitor == null)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
public sealed class TagHelperIRNode : RazorIRNode
|
||||
{
|
||||
private ItemCollection _annotations;
|
||||
private RazorDiagnosticCollection _diagnostics;
|
||||
|
||||
public override ItemCollection Annotations
|
||||
{
|
||||
|
|
@ -22,10 +23,25 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
}
|
||||
}
|
||||
|
||||
public override RazorDiagnosticCollection Diagnostics
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_diagnostics == null)
|
||||
{
|
||||
_diagnostics = new DefaultDiagnosticCollection();
|
||||
}
|
||||
|
||||
return _diagnostics;
|
||||
}
|
||||
}
|
||||
|
||||
public override RazorIRNodeCollection Children { get; } = new DefaultIRNodeCollection();
|
||||
|
||||
public override SourceSpan? Source { get; set; }
|
||||
|
||||
public override bool HasDiagnostics => _diagnostics != null && _diagnostics.Count > 0;
|
||||
|
||||
public string TagName { get; set; }
|
||||
|
||||
public TagMode TagMode { get; set; }
|
||||
|
|
|
|||
|
|
@ -7,12 +7,29 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
{
|
||||
public sealed class UsingStatementIRNode : RazorIRNode
|
||||
{
|
||||
private RazorDiagnosticCollection _diagnostics;
|
||||
|
||||
public override ItemCollection Annotations => ReadOnlyItemCollection.Empty;
|
||||
|
||||
public override RazorDiagnosticCollection Diagnostics
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_diagnostics == null)
|
||||
{
|
||||
_diagnostics = new DefaultDiagnosticCollection();
|
||||
}
|
||||
|
||||
return _diagnostics;
|
||||
}
|
||||
}
|
||||
|
||||
public override RazorIRNodeCollection Children => ReadOnlyIRNodeCollection.Instance;
|
||||
|
||||
public override SourceSpan? Source { get; set; }
|
||||
|
||||
public override bool HasDiagnostics => _diagnostics != null && _diagnostics.Count > 0;
|
||||
|
||||
public string Content { get; set; }
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
|
|
|
|||
|
|
@ -30,26 +30,6 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
$"provided by the '{nameof(RazorCodeDocument)}'.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Execute_ThrowsForMissingDependency_SyntaxTree()
|
||||
{
|
||||
// Arrange
|
||||
var phase = new DefaultRazorCSharpLoweringPhase();
|
||||
|
||||
var engine = RazorEngine.CreateEmpty(b => b.Phases.Add(phase));
|
||||
|
||||
var codeDocument = TestRazorCodeDocument.CreateEmpty();
|
||||
|
||||
var irDocument = new DocumentIRNode();
|
||||
codeDocument.SetIRDocument(irDocument);
|
||||
|
||||
// Act & Assert
|
||||
ExceptionAssert.Throws<InvalidOperationException>(
|
||||
() => phase.Execute(codeDocument),
|
||||
$"The '{nameof(DefaultRazorCSharpLoweringPhase)}' phase requires a '{nameof(RazorSyntaxTree)}' " +
|
||||
$"provided by the '{nameof(RazorCodeDocument)}'.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Execute_ThrowsForMissingDependency_CodeTarget()
|
||||
{
|
||||
|
|
@ -76,13 +56,12 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void Execute_CollatesSyntaxDiagnosticsFromSourceDocument()
|
||||
public void Execute_CollatesIRDocumentDiagnosticsFromSourceDocument()
|
||||
{
|
||||
// Arrange
|
||||
var phase = new DefaultRazorCSharpLoweringPhase();
|
||||
var engine = RazorEngine.CreateEmpty(b => b.Phases.Add(phase));
|
||||
var codeDocument = TestRazorCodeDocument.Create("<p class=@(");
|
||||
codeDocument.SetSyntaxTree(RazorSyntaxTree.Parse(codeDocument.Source));
|
||||
var options = RazorCodeGenerationOptions.CreateDefault();
|
||||
var irDocument = new DocumentIRNode()
|
||||
{
|
||||
|
|
@ -90,6 +69,10 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
Target = CodeTarget.CreateDefault(codeDocument, options),
|
||||
Options = options,
|
||||
};
|
||||
var expectedDiagnostic = RazorDiagnostic.Create(
|
||||
new RazorDiagnosticDescriptor("1234", () => "I am an error.", RazorDiagnosticSeverity.Error),
|
||||
new SourceSpan("SomeFile.cshtml", 11, 0, 11, 1));
|
||||
irDocument.Diagnostics.Add(expectedDiagnostic);
|
||||
codeDocument.SetIRDocument(irDocument);
|
||||
|
||||
// Act
|
||||
|
|
@ -98,49 +81,7 @@ namespace Microsoft.AspNetCore.Razor.Language
|
|||
// Assert
|
||||
var csharpDocument = codeDocument.GetCSharpDocument();
|
||||
var diagnostic = Assert.Single(csharpDocument.Diagnostics);
|
||||
Assert.Equal(@"The explicit expression block is missing a closing "")"" character. Make sure you have a matching "")"" character for all the ""("" characters within this block, and that none of the "")"" characters are being interpreted as markup.",
|
||||
diagnostic.GetMessage());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Execute_CollatesSyntaxDiagnosticsFromImportDocuments()
|
||||
{
|
||||
// Arrange
|
||||
var phase = new DefaultRazorCSharpLoweringPhase();
|
||||
var engine = RazorEngine.CreateEmpty(b => b.Phases.Add(phase));
|
||||
|
||||
var codeDocument = TestRazorCodeDocument.CreateEmpty();
|
||||
codeDocument.SetSyntaxTree(RazorSyntaxTree.Parse(codeDocument.Source));
|
||||
codeDocument.SetImportSyntaxTrees(new[]
|
||||
{
|
||||
RazorSyntaxTree.Parse(TestRazorSourceDocument.Create("@ ")),
|
||||
RazorSyntaxTree.Parse(TestRazorSourceDocument.Create("<p @(")),
|
||||
});
|
||||
var options = RazorCodeGenerationOptions.CreateDefault();
|
||||
var irDocument = new DocumentIRNode()
|
||||
{
|
||||
DocumentKind = "test",
|
||||
Target = CodeTarget.CreateDefault(codeDocument, options),
|
||||
Options = options,
|
||||
};
|
||||
codeDocument.SetIRDocument(irDocument);
|
||||
|
||||
// Act
|
||||
phase.Execute(codeDocument);
|
||||
|
||||
// Assert
|
||||
var csharpDocument = codeDocument.GetCSharpDocument();
|
||||
Assert.Collection(csharpDocument.Diagnostics,
|
||||
diagnostic =>
|
||||
{
|
||||
Assert.Equal(@"A space or line break was encountered after the ""@"" character. Only valid identifiers, keywords, comments, ""("" and ""{"" are valid at the start of a code block and they must occur immediately following ""@"" with no space in between.",
|
||||
diagnostic.GetMessage());
|
||||
},
|
||||
diagnostic =>
|
||||
{
|
||||
Assert.Equal(@"The explicit expression block is missing a closing "")"" character. Make sure you have a matching "")"" character for all the ""("" characters within this block, and that none of the "")"" characters are being interpreted as markup.",
|
||||
diagnostic.GetMessage());
|
||||
});
|
||||
Assert.Same(expectedDiagnostic, diagnostic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,85 @@
|
|||
// 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.AspNetCore.Razor.Language.CodeGeneration;
|
||||
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Razor.Language
|
||||
{
|
||||
public class DefaultRazorIRLoweringPhaseTest
|
||||
{
|
||||
[Fact]
|
||||
public void Execute_ThrowsForMissingDependency_SyntaxTree()
|
||||
{
|
||||
// Arrange
|
||||
var phase = new DefaultRazorIRLoweringPhase();
|
||||
|
||||
var engine = RazorEngine.CreateEmpty(b => b.Phases.Add(phase));
|
||||
|
||||
var codeDocument = TestRazorCodeDocument.CreateEmpty();
|
||||
|
||||
// Act & Assert
|
||||
ExceptionAssert.Throws<InvalidOperationException>(
|
||||
() => phase.Execute(codeDocument),
|
||||
$"The '{nameof(DefaultRazorIRLoweringPhase)}' phase requires a '{nameof(RazorSyntaxTree)}' " +
|
||||
$"provided by the '{nameof(RazorCodeDocument)}'.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Execute_CollatesSyntaxDiagnosticsFromSourceDocument()
|
||||
{
|
||||
// Arrange
|
||||
var phase = new DefaultRazorIRLoweringPhase();
|
||||
var engine = RazorEngine.CreateEmpty(b => b.Phases.Add(phase));
|
||||
var codeDocument = TestRazorCodeDocument.Create("<p class=@(");
|
||||
codeDocument.SetSyntaxTree(RazorSyntaxTree.Parse(codeDocument.Source));
|
||||
var options = RazorCodeGenerationOptions.CreateDefault();
|
||||
|
||||
// Act
|
||||
phase.Execute(codeDocument);
|
||||
|
||||
// Assert
|
||||
var irDocument = codeDocument.GetIRDocument();
|
||||
var diagnostic = Assert.Single(irDocument.Diagnostics);
|
||||
Assert.Equal(@"The explicit expression block is missing a closing "")"" character. Make sure you have a matching "")"" character for all the ""("" characters within this block, and that none of the "")"" characters are being interpreted as markup.",
|
||||
diagnostic.GetMessage());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Execute_CollatesSyntaxDiagnosticsFromImportDocuments()
|
||||
{
|
||||
// Arrange
|
||||
var phase = new DefaultRazorIRLoweringPhase();
|
||||
var engine = RazorEngine.CreateEmpty(b => b.Phases.Add(phase));
|
||||
|
||||
var codeDocument = TestRazorCodeDocument.CreateEmpty();
|
||||
codeDocument.SetSyntaxTree(RazorSyntaxTree.Parse(codeDocument.Source));
|
||||
codeDocument.SetImportSyntaxTrees(new[]
|
||||
{
|
||||
RazorSyntaxTree.Parse(TestRazorSourceDocument.Create("@ ")),
|
||||
RazorSyntaxTree.Parse(TestRazorSourceDocument.Create("<p @(")),
|
||||
});
|
||||
var options = RazorCodeGenerationOptions.CreateDefault();
|
||||
|
||||
// Act
|
||||
phase.Execute(codeDocument);
|
||||
|
||||
// Assert
|
||||
var irDocument = codeDocument.GetIRDocument();
|
||||
Assert.Collection(irDocument.Diagnostics,
|
||||
diagnostic =>
|
||||
{
|
||||
Assert.Equal(@"A space or line break was encountered after the ""@"" character. Only valid identifiers, keywords, comments, ""("" and ""{"" are valid at the start of a code block and they must occur immediately following ""@"" with no space in between.",
|
||||
diagnostic.GetMessage());
|
||||
},
|
||||
diagnostic =>
|
||||
{
|
||||
Assert.Equal(@"The explicit expression block is missing a closing "")"" character. Make sure you have a matching "")"" character for all the ""("" characters within this block, and that none of the "")"" characters are being interpreted as markup.",
|
||||
diagnostic.GetMessage());
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -210,10 +210,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
{
|
||||
public override ItemCollection Annotations { get; } = new DefaultItemCollection();
|
||||
|
||||
public override RazorDiagnosticCollection Diagnostics { get; } = new DefaultDiagnosticCollection();
|
||||
|
||||
public override RazorIRNodeCollection Children { get; } = new DefaultIRNodeCollection();
|
||||
|
||||
public override SourceSpan? Source { get; set; }
|
||||
|
||||
public override bool HasDiagnostics => Diagnostics.Count > 0;
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
|
|
|||
|
|
@ -499,10 +499,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
|
||||
public override ItemCollection Annotations { get; } = new DefaultItemCollection();
|
||||
|
||||
public override RazorDiagnosticCollection Diagnostics => new DefaultDiagnosticCollection();
|
||||
|
||||
public override RazorIRNodeCollection Children { get; }
|
||||
|
||||
public override SourceSpan? Source { get; set; }
|
||||
|
||||
public override bool HasDiagnostics => Diagnostics.Count > 0;
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
|
|
|
|||
|
|
@ -126,10 +126,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
|||
|
||||
public override ItemCollection Annotations { get; } = new DefaultItemCollection();
|
||||
|
||||
public override RazorDiagnosticCollection Diagnostics { get; } = new DefaultDiagnosticCollection();
|
||||
|
||||
public override RazorIRNodeCollection Children { get; } = new DefaultIRNodeCollection();
|
||||
|
||||
public override SourceSpan? Source { get; set; }
|
||||
|
||||
public override bool HasDiagnostics => Diagnostics.Count > 0;
|
||||
|
||||
public override void Accept(RazorIRNodeVisitor visitor)
|
||||
{
|
||||
((DerivedIRNodeWalker)visitor).VisitBasic(this);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||
using Microsoft.AspNetCore.Razor.Language.Legacy;
|
||||
|
||||
|
|
@ -188,24 +190,66 @@ namespace Microsoft.AspNetCore.Razor.Language.IntegrationTests
|
|||
{
|
||||
if (node.Source != null)
|
||||
{
|
||||
var sourceRange = node.Source.Value;
|
||||
_writer.Write("(");
|
||||
_writer.Write(sourceRange.AbsoluteIndex);
|
||||
_writer.Write(":");
|
||||
_writer.Write(sourceRange.LineIndex);
|
||||
_writer.Write(",");
|
||||
_writer.Write(sourceRange.CharacterIndex);
|
||||
_writer.Write(" [");
|
||||
_writer.Write(sourceRange.Length);
|
||||
_writer.Write("] ");
|
||||
WriteSourceRange(node.Source.Value);
|
||||
}
|
||||
}
|
||||
|
||||
if (sourceRange.FilePath != null)
|
||||
protected void WriteSourceRange(SourceSpan sourceRange)
|
||||
{
|
||||
_writer.Write("(");
|
||||
_writer.Write(sourceRange.AbsoluteIndex);
|
||||
_writer.Write(":");
|
||||
_writer.Write(sourceRange.LineIndex);
|
||||
_writer.Write(",");
|
||||
_writer.Write(sourceRange.CharacterIndex);
|
||||
_writer.Write(" [");
|
||||
_writer.Write(sourceRange.Length);
|
||||
_writer.Write("] ");
|
||||
|
||||
if (sourceRange.FilePath != null)
|
||||
{
|
||||
var fileName = sourceRange.FilePath.Substring(sourceRange.FilePath.LastIndexOf('/') + 1);
|
||||
_writer.Write(fileName);
|
||||
}
|
||||
|
||||
_writer.Write(")");
|
||||
}
|
||||
|
||||
protected void WriteDiagnostics(RazorIRNode node)
|
||||
{
|
||||
if (node.HasDiagnostics)
|
||||
{
|
||||
_writer.Write("| ");
|
||||
for (var i = 0; i < node.Diagnostics.Count; i++)
|
||||
{
|
||||
var fileName = sourceRange.FilePath.Substring(sourceRange.FilePath.LastIndexOf('/') + 1);
|
||||
_writer.Write(fileName);
|
||||
}
|
||||
var diagnostic = node.Diagnostics[i];
|
||||
_writer.Write("{");
|
||||
WriteSourceRange(diagnostic.Span);
|
||||
_writer.Write(": ");
|
||||
_writer.Write(diagnostic.Severity);
|
||||
_writer.Write(" ");
|
||||
_writer.Write(diagnostic.Id);
|
||||
_writer.Write(": ");
|
||||
|
||||
_writer.Write(")");
|
||||
// Purposefully not writing out the entire message to ensure readable IR and because messages
|
||||
// can span multiple lines. Not using string.GetHashCode because we can't have any collisions.
|
||||
using (var md5 = MD5.Create())
|
||||
{
|
||||
var diagnosticMessage = diagnostic.GetMessage();
|
||||
var messageBytes = Encoding.UTF8.GetBytes(diagnosticMessage);
|
||||
var messageHash = md5.ComputeHash(messageBytes);
|
||||
var stringHashBuilder = new StringBuilder();
|
||||
|
||||
for (var j = 0; j < messageHash.Length; j++)
|
||||
{
|
||||
stringHashBuilder.Append(messageHash[j].ToString("x2"));
|
||||
}
|
||||
|
||||
var stringHash = stringHashBuilder.ToString();
|
||||
_writer.Write(stringHash);
|
||||
}
|
||||
_writer.Write("} ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue