Merge branch 'release/2.2'
# Conflicts: # build/dependencies.props # korebuild-lock.txt
This commit is contained in:
commit
eec42e9a31
|
|
@ -18,6 +18,7 @@
|
||||||
<PublicSign Condition="'$(OS)' != 'Windows_NT'">true</PublicSign>
|
<PublicSign Condition="'$(OS)' != 'Windows_NT'">true</PublicSign>
|
||||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
<AssemblySigningCertName>Microsoft</AssemblySigningCertName>
|
<AssemblySigningCertName>Microsoft</AssemblySigningCertName>
|
||||||
|
<LangVersion>7.3</LangVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -47,5 +47,13 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
|
||||||
|
|
||||||
extension.WriteInjectProperty(context, this);
|
extension.WriteInjectProperty(context, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void FormatNode(IntermediateNodeFormatter formatter)
|
||||||
|
{
|
||||||
|
formatter.WriteContent(MemberName);
|
||||||
|
|
||||||
|
formatter.WriteProperty(nameof(MemberName), MemberName);
|
||||||
|
formatter.WriteProperty(nameof(TypeName), TypeName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,5 +47,13 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X
|
||||||
|
|
||||||
extension.WriteViewComponentTagHelper(context, this);
|
extension.WriteViewComponentTagHelper(context, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void FormatNode(IntermediateNodeFormatter formatter)
|
||||||
|
{
|
||||||
|
formatter.WriteContent(ClassName);
|
||||||
|
|
||||||
|
formatter.WriteProperty(nameof(ClassName), ClassName);
|
||||||
|
formatter.WriteProperty(nameof(TagHelper), TagHelper?.DisplayName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using Microsoft.AspNetCore.Razor.Language;
|
|
||||||
using Microsoft.AspNetCore.Razor.Language.CodeGeneration;
|
using Microsoft.AspNetCore.Razor.Language.CodeGeneration;
|
||||||
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||||
|
|
||||||
|
|
@ -47,5 +46,13 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||||
|
|
||||||
extension.WriteInjectProperty(context, this);
|
extension.WriteInjectProperty(context, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void FormatNode(IntermediateNodeFormatter formatter)
|
||||||
|
{
|
||||||
|
formatter.WriteContent(MemberName);
|
||||||
|
|
||||||
|
formatter.WriteProperty(nameof(MemberName), MemberName);
|
||||||
|
formatter.WriteProperty(nameof(TypeName), TypeName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,8 +33,8 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||||
|
|
||||||
private static void AddInstrumentation(InstrumentationItem item)
|
private static void AddInstrumentation(InstrumentationItem item)
|
||||||
{
|
{
|
||||||
var beginContextMethodName = "BeginContext"; /* ORIGINAL: BeginContextMethodName */
|
var beginContextMethodName = "BeginContext"; // ORIGINAL: BeginContextMethodName
|
||||||
var endContextMethodName = "EndContext"; /* ORIGINAL: EndContextMethodName */
|
var endContextMethodName = "EndContext"; // ORIGINAL: EndContextMethodName
|
||||||
|
|
||||||
var beginNode = new CSharpCodeIntermediateNode();
|
var beginNode = new CSharpCodeIntermediateNode();
|
||||||
beginNode.Children.Add(new IntermediateToken()
|
beginNode.Children.Add(new IntermediateToken()
|
||||||
|
|
|
||||||
|
|
@ -47,5 +47,13 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Extensions
|
||||||
|
|
||||||
extension.WriteViewComponentTagHelper(context, this);
|
extension.WriteViewComponentTagHelper(context, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void FormatNode(IntermediateNodeFormatter formatter)
|
||||||
|
{
|
||||||
|
formatter.WriteContent(ClassName);
|
||||||
|
|
||||||
|
formatter.WriteProperty(nameof(ClassName), ClassName);
|
||||||
|
formatter.WriteProperty(nameof(TagHelper), TagHelper?.DisplayName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,5 +48,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
|
||||||
|
|
||||||
extension.WriteTagHelperCreate(context, this);
|
extension.WriteTagHelperCreate(context, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void FormatNode(IntermediateNodeFormatter formatter)
|
||||||
|
{
|
||||||
|
formatter.WriteContent(TypeName);
|
||||||
|
|
||||||
|
formatter.WriteProperty(nameof(FieldName), FieldName);
|
||||||
|
formatter.WriteProperty(nameof(TagHelper), TagHelper?.DisplayName);
|
||||||
|
formatter.WriteProperty(nameof(TypeName), TypeName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -72,5 +72,13 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
|
||||||
|
|
||||||
extension.WriteTagHelperHtmlAttribute(context, this);
|
extension.WriteTagHelperHtmlAttribute(context, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void FormatNode(IntermediateNodeFormatter formatter)
|
||||||
|
{
|
||||||
|
formatter.WriteContent(AttributeName);
|
||||||
|
|
||||||
|
formatter.WriteProperty(nameof(AttributeName), AttributeName);
|
||||||
|
formatter.WriteProperty(nameof(AttributeStructure), AttributeStructure.ToString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -85,5 +85,18 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
|
||||||
|
|
||||||
extension.WriteTagHelperProperty(context, this);
|
extension.WriteTagHelperProperty(context, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void FormatNode(IntermediateNodeFormatter formatter)
|
||||||
|
{
|
||||||
|
formatter.WriteContent(AttributeName);
|
||||||
|
|
||||||
|
formatter.WriteProperty(nameof(AttributeName), AttributeName);
|
||||||
|
formatter.WriteProperty(nameof(AttributeStructure), AttributeStructure.ToString());
|
||||||
|
formatter.WriteProperty(nameof(BoundAttribute), BoundAttribute?.DisplayName);
|
||||||
|
formatter.WriteProperty(nameof(FieldName), FieldName);
|
||||||
|
formatter.WriteProperty(nameof(IsIndexerNameMatch), IsIndexerNameMatch.ToString());
|
||||||
|
formatter.WriteProperty(nameof(PropertyName), PropertyName);
|
||||||
|
formatter.WriteProperty(nameof(TagHelper), TagHelper?.DisplayName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Text;
|
||||||
using Microsoft.AspNetCore.Razor.Language.CodeGeneration;
|
using Microsoft.AspNetCore.Razor.Language.CodeGeneration;
|
||||||
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
using Microsoft.AspNetCore.Razor.Language.Intermediate;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,5 +44,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
|
||||||
|
|
||||||
extension.WriteTagHelperHtmlAttribute(context, this);
|
extension.WriteTagHelperHtmlAttribute(context, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void FormatNode(IntermediateNodeFormatter formatter)
|
||||||
|
{
|
||||||
|
formatter.WriteContent(VariableName);
|
||||||
|
|
||||||
|
formatter.WriteProperty(nameof(VariableName), VariableName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -74,5 +74,15 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
|
||||||
|
|
||||||
extension.WriteTagHelperHtmlAttributeValue(context, this);
|
extension.WriteTagHelperHtmlAttributeValue(context, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void FormatNode(IntermediateNodeFormatter formatter)
|
||||||
|
{
|
||||||
|
formatter.WriteContent(AttributeName);
|
||||||
|
|
||||||
|
formatter.WriteProperty(nameof(AttributeName), AttributeName);
|
||||||
|
formatter.WriteProperty(nameof(AttributeStructure), AttributeStructure.ToString());
|
||||||
|
formatter.WriteProperty(nameof(Value), Value);
|
||||||
|
formatter.WriteProperty(nameof(VariableName), VariableName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -79,5 +79,19 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
|
||||||
|
|
||||||
extension.WriteTagHelperProperty(context, this);
|
extension.WriteTagHelperProperty(context, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void FormatNode(IntermediateNodeFormatter formatter)
|
||||||
|
{
|
||||||
|
formatter.WriteContent(AttributeName);
|
||||||
|
|
||||||
|
formatter.WriteProperty(nameof(AttributeName), AttributeName);
|
||||||
|
formatter.WriteProperty(nameof(AttributeStructure), AttributeStructure.ToString());
|
||||||
|
formatter.WriteProperty(nameof(BoundAttribute), BoundAttribute?.DisplayName);
|
||||||
|
formatter.WriteProperty(nameof(FieldName), FieldName);
|
||||||
|
formatter.WriteProperty(nameof(IsIndexerNameMatch), IsIndexerNameMatch.ToString());
|
||||||
|
formatter.WriteProperty(nameof(PropertyName), PropertyName);
|
||||||
|
formatter.WriteProperty(nameof(TagHelper), TagHelper?.DisplayName);
|
||||||
|
formatter.WriteProperty(nameof(VariableName), VariableName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,5 +50,15 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
|
||||||
|
|
||||||
extension.WriteTagHelperPropertyValue(context, this);
|
extension.WriteTagHelperPropertyValue(context, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void FormatNode(IntermediateNodeFormatter formatter)
|
||||||
|
{
|
||||||
|
formatter.WriteContent(AttributeName);
|
||||||
|
|
||||||
|
formatter.WriteProperty(nameof(AttributeName), AttributeName);
|
||||||
|
formatter.WriteProperty(nameof(AttributeStructure), AttributeStructure.ToString());
|
||||||
|
formatter.WriteProperty(nameof(Value), Value);
|
||||||
|
formatter.WriteProperty(nameof(VariableName), VariableName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,5 +48,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
|
||||||
|
|
||||||
extension.WriteRazorCompiledItemAttribute(context, this);
|
extension.WriteRazorCompiledItemAttribute(context, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void FormatNode(IntermediateNodeFormatter formatter)
|
||||||
|
{
|
||||||
|
formatter.WriteProperty(nameof(Identifier), Identifier);
|
||||||
|
formatter.WriteProperty(nameof(Kind), Kind);
|
||||||
|
formatter.WriteProperty(nameof(TypeName), TypeName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,5 +55,11 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
|
||||||
|
|
||||||
extension.WriteRazorCompiledItemMetadataAttribute(context, this);
|
extension.WriteRazorCompiledItemMetadataAttribute(context, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void FormatNode(IntermediateNodeFormatter formatter)
|
||||||
|
{
|
||||||
|
formatter.WriteProperty(nameof(Key), Key);
|
||||||
|
formatter.WriteProperty(nameof(Value), Value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,5 +44,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Extensions
|
||||||
|
|
||||||
extension.WriteSection(context, this);
|
extension.WriteSection(context, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void FormatNode(IntermediateNodeFormatter formatter)
|
||||||
|
{
|
||||||
|
formatter.WriteContent(SectionName);
|
||||||
|
|
||||||
|
formatter.WriteProperty(nameof(SectionName), SectionName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,5 +20,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
||||||
|
|
||||||
visitor.VisitCSharpCodeAttributeValue(this);
|
visitor.VisitCSharpCodeAttributeValue(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void FormatNode(IntermediateNodeFormatter formatter)
|
||||||
|
{
|
||||||
|
formatter.WriteChildren(Children);
|
||||||
|
|
||||||
|
formatter.WriteProperty(nameof(Prefix), Prefix);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,5 +18,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
||||||
|
|
||||||
visitor.VisitCSharpCode(this);
|
visitor.VisitCSharpCode(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void FormatNode(IntermediateNodeFormatter formatter)
|
||||||
|
{
|
||||||
|
formatter.WriteChildren(Children);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,5 +20,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
||||||
|
|
||||||
visitor.VisitCSharpExpressionAttributeValue(this);
|
visitor.VisitCSharpExpressionAttributeValue(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void FormatNode(IntermediateNodeFormatter formatter)
|
||||||
|
{
|
||||||
|
formatter.WriteChildren(Children);
|
||||||
|
|
||||||
|
formatter.WriteProperty(nameof(Prefix), Prefix);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,5 +18,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
||||||
|
|
||||||
visitor.VisitCSharpExpression(this);
|
visitor.VisitCSharpExpression(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void FormatNode(IntermediateNodeFormatter formatter)
|
||||||
|
{
|
||||||
|
formatter.WriteChildren(Children);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
||||||
{
|
{
|
||||||
|
|
@ -29,5 +30,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
||||||
|
|
||||||
visitor.VisitClassDeclaration(this);
|
visitor.VisitClassDeclaration(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void FormatNode(IntermediateNodeFormatter formatter)
|
||||||
|
{
|
||||||
|
formatter.WriteContent(ClassName);
|
||||||
|
|
||||||
|
formatter.WriteProperty(nameof(BaseType), BaseType);
|
||||||
|
formatter.WriteProperty(nameof(ClassName), ClassName);
|
||||||
|
formatter.WriteProperty(nameof(Interfaces), string.Join(", ", Interfaces));
|
||||||
|
formatter.WriteProperty(nameof(Modifiers), string.Join(", ", Modifiers));
|
||||||
|
formatter.WriteProperty(nameof(TypeParameters), string.Join(", ", TypeParameters.Select(t => t.ParameterName)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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.IO;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
||||||
|
{
|
||||||
|
internal class DebuggerDisplayFormatter : IntermediateNodeFormatterBase
|
||||||
|
{
|
||||||
|
public DebuggerDisplayFormatter()
|
||||||
|
{
|
||||||
|
Writer = new StringWriter();
|
||||||
|
ContentMode = FormatterContentMode.PreferContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Writer.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -20,5 +20,13 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
||||||
{
|
{
|
||||||
visitor.VisitDirective(this);
|
visitor.VisitDirective(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void FormatNode(IntermediateNodeFormatter formatter)
|
||||||
|
{
|
||||||
|
formatter.WriteContent(DirectiveName);
|
||||||
|
|
||||||
|
formatter.WriteProperty(nameof(Directive), Directive?.DisplayName);
|
||||||
|
formatter.WriteProperty(nameof(DirectiveName), DirectiveName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
// Copyright(c) .NET Foundation.All rights reserved.
|
// Copyright(c) .NET Foundation.All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
||||||
{
|
{
|
||||||
public sealed class DirectiveTokenIntermediateNode : IntermediateNode
|
public sealed class DirectiveTokenIntermediateNode : IntermediateNode
|
||||||
|
|
@ -15,5 +17,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
||||||
{
|
{
|
||||||
visitor.VisitDirectiveToken(this);
|
visitor.VisitDirectiveToken(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void FormatNode(IntermediateNodeFormatter formatter)
|
||||||
|
{
|
||||||
|
formatter.WriteContent(Content);
|
||||||
|
|
||||||
|
formatter.WriteProperty(nameof(Content), Content);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -25,5 +25,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
||||||
|
|
||||||
visitor.VisitDocument(this);
|
visitor.VisitDocument(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void FormatNode(IntermediateNodeFormatter formatter)
|
||||||
|
{
|
||||||
|
formatter.WriteContent(DocumentKind);
|
||||||
|
|
||||||
|
formatter.WriteProperty(nameof(DocumentKind), DocumentKind);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,5 +25,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
||||||
|
|
||||||
visitor.VisitFieldDeclaration(this);
|
visitor.VisitFieldDeclaration(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void FormatNode(IntermediateNodeFormatter formatter)
|
||||||
|
{
|
||||||
|
formatter.WriteContent(FieldName);
|
||||||
|
|
||||||
|
formatter.WriteProperty(nameof(FieldName), FieldName);
|
||||||
|
formatter.WriteProperty(nameof(FieldType), FieldType);
|
||||||
|
formatter.WriteProperty(nameof(Modifiers), string.Join(" ", Modifiers));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -24,5 +24,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
||||||
|
|
||||||
visitor.VisitHtmlAttribute(this);
|
visitor.VisitHtmlAttribute(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void FormatNode(IntermediateNodeFormatter formatter)
|
||||||
|
{
|
||||||
|
formatter.WriteContent(AttributeName);
|
||||||
|
|
||||||
|
formatter.WriteProperty(nameof(AttributeName), AttributeName);
|
||||||
|
formatter.WriteProperty(nameof(Prefix), Prefix);
|
||||||
|
formatter.WriteProperty(nameof(Suffix), Suffix);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,5 +20,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
||||||
|
|
||||||
visitor.VisitHtmlAttributeValue(this);
|
visitor.VisitHtmlAttributeValue(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void FormatNode(IntermediateNodeFormatter formatter)
|
||||||
|
{
|
||||||
|
formatter.WriteChildren(Children);
|
||||||
|
|
||||||
|
formatter.WriteProperty(nameof(Prefix), Prefix);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,5 +18,10 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
||||||
|
|
||||||
visitor.VisitHtml(this);
|
visitor.VisitHtml(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void FormatNode(IntermediateNodeFormatter formatter)
|
||||||
|
{
|
||||||
|
formatter.WriteChildren(Children);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,11 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
||||||
{
|
{
|
||||||
|
[DebuggerDisplay("{DebuggerToString(),nq}")]
|
||||||
public abstract class IntermediateNode
|
public abstract class IntermediateNode
|
||||||
{
|
{
|
||||||
private ItemCollection _annotations;
|
private ItemCollection _annotations;
|
||||||
|
|
@ -39,7 +42,30 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
||||||
public bool HasDiagnostics => _diagnostics != null && _diagnostics.Count > 0;
|
public bool HasDiagnostics => _diagnostics != null && _diagnostics.Count > 0;
|
||||||
|
|
||||||
public SourceSpan? Source { get; set; }
|
public SourceSpan? Source { get; set; }
|
||||||
|
|
||||||
public abstract void Accept(IntermediateNodeVisitor visitor);
|
public abstract void Accept(IntermediateNodeVisitor visitor);
|
||||||
|
|
||||||
|
[DebuggerBrowsable(DebuggerBrowsableState.Collapsed)]
|
||||||
|
private string Tree
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var formatter = new DebuggerDisplayFormatter();
|
||||||
|
formatter.FormatTree(this);
|
||||||
|
return formatter.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string DebuggerToString()
|
||||||
|
{
|
||||||
|
var formatter = new DebuggerDisplayFormatter();
|
||||||
|
formatter.FormatNode(this);
|
||||||
|
return formatter.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public virtual void FormatNode(IntermediateNodeFormatter formatter)
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
||||||
|
{
|
||||||
|
public abstract class IntermediateNodeFormatter
|
||||||
|
{
|
||||||
|
public abstract void WriteChildren(IntermediateNodeCollection children);
|
||||||
|
|
||||||
|
public abstract void WriteContent(string content);
|
||||||
|
|
||||||
|
public abstract void WriteProperty(string key, string value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,180 @@
|
||||||
|
// 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;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
||||||
|
{
|
||||||
|
internal class IntermediateNodeFormatterBase : IntermediateNodeFormatter
|
||||||
|
{
|
||||||
|
private string _content;
|
||||||
|
private Dictionary<string, string> _properties = new Dictionary<string, string>(StringComparer.Ordinal);
|
||||||
|
|
||||||
|
protected FormatterContentMode ContentMode { get; set; }
|
||||||
|
|
||||||
|
protected bool IncludeSource { get; set; }
|
||||||
|
|
||||||
|
protected TextWriter Writer { get; set; }
|
||||||
|
|
||||||
|
public override void WriteChildren(IntermediateNodeCollection children)
|
||||||
|
{
|
||||||
|
if (children == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(children));
|
||||||
|
}
|
||||||
|
|
||||||
|
Writer.Write(" ");
|
||||||
|
Writer.Write("\"");
|
||||||
|
for (var i = 0; i < children.Count; i++)
|
||||||
|
{
|
||||||
|
var child = children[i] as IntermediateToken;
|
||||||
|
if (child != null)
|
||||||
|
{
|
||||||
|
Writer.Write(EscapeNewlines(child.Content));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Writer.Write("\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void WriteContent(string content)
|
||||||
|
{
|
||||||
|
if (content == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_content = EscapeNewlines(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void WriteProperty(string key, string value)
|
||||||
|
{
|
||||||
|
if (key == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_properties.Add(key, EscapeNewlines(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void FormatNode(IntermediateNode node)
|
||||||
|
{
|
||||||
|
if (node == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(node));
|
||||||
|
}
|
||||||
|
|
||||||
|
BeginNode(node);
|
||||||
|
node.FormatNode(this);
|
||||||
|
EndNode(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void FormatTree(IntermediateNode node)
|
||||||
|
{
|
||||||
|
if (node == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(node));
|
||||||
|
}
|
||||||
|
|
||||||
|
var visitor = new FormatterVisitor(this);
|
||||||
|
visitor.Visit(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BeginNode(IntermediateNode node)
|
||||||
|
{
|
||||||
|
Writer.Write(GetShortName(node));
|
||||||
|
|
||||||
|
if (IncludeSource)
|
||||||
|
{
|
||||||
|
Writer.Write(" ");
|
||||||
|
Writer.Write(node.Source?.ToString() ?? "(n/a)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EndNode(IntermediateNode node)
|
||||||
|
{
|
||||||
|
if (_content != null && (_properties.Count == 0 || ContentMode == FormatterContentMode.PreferContent))
|
||||||
|
{
|
||||||
|
Writer.Write(" ");
|
||||||
|
Writer.Write("\"");
|
||||||
|
Writer.Write(EscapeNewlines(_content));
|
||||||
|
Writer.Write("\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_properties.Count > 0 && (_content == null || ContentMode == FormatterContentMode.PreferProperties))
|
||||||
|
{
|
||||||
|
Writer.Write(" ");
|
||||||
|
Writer.Write("{ ");
|
||||||
|
Writer.Write(string.Join(", ", _properties.Select(kvp => $"{kvp.Key}: \"{kvp.Value}\"")));
|
||||||
|
Writer.Write(" }");
|
||||||
|
}
|
||||||
|
|
||||||
|
_content = null;
|
||||||
|
_properties.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetShortName(IntermediateNode node)
|
||||||
|
{
|
||||||
|
var typeName = node.GetType().Name;
|
||||||
|
return
|
||||||
|
typeName.EndsWith(nameof(IntermediateNode), StringComparison.Ordinal) ?
|
||||||
|
typeName.Substring(0, typeName.Length - nameof(IntermediateNode).Length) :
|
||||||
|
typeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string EscapeNewlines(string content)
|
||||||
|
{
|
||||||
|
return content.Replace("\r", "\\r").Replace("\n", "\\n").Replace("\t", "\\t");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Depending on the usage of the formatter we might prefer thoroughness (properties)
|
||||||
|
// or brevity (content). Generally if a node has a single string that provides value
|
||||||
|
// it has content.
|
||||||
|
//
|
||||||
|
// Some nodes have neither: TagHelperBody
|
||||||
|
// Some nodes have content: HtmlContent
|
||||||
|
// Some nodes have properties: Document
|
||||||
|
// Some nodes have both: TagHelperProperty
|
||||||
|
protected enum FormatterContentMode
|
||||||
|
{
|
||||||
|
PreferContent,
|
||||||
|
PreferProperties,
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class FormatterVisitor : IntermediateNodeWalker
|
||||||
|
{
|
||||||
|
private const int IndentSize = 2;
|
||||||
|
|
||||||
|
private readonly IntermediateNodeFormatterBase _formatter;
|
||||||
|
private int _indent = 0;
|
||||||
|
|
||||||
|
public FormatterVisitor(IntermediateNodeFormatterBase formatter)
|
||||||
|
{
|
||||||
|
_formatter = formatter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void VisitDefault(IntermediateNode node)
|
||||||
|
{
|
||||||
|
// Indent
|
||||||
|
for (var i = 0; i < _indent; i++)
|
||||||
|
{
|
||||||
|
_formatter.Writer.Write(' ');
|
||||||
|
}
|
||||||
|
_formatter.FormatNode(node);
|
||||||
|
_formatter.Writer.WriteLine();
|
||||||
|
|
||||||
|
// Process children
|
||||||
|
_indent += IndentSize;
|
||||||
|
base.VisitDefault(node);
|
||||||
|
_indent -= IndentSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -26,7 +26,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
||||||
|
|
||||||
visitor.VisitToken(this);
|
visitor.VisitToken(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void FormatNode(IntermediateNodeFormatter formatter)
|
||||||
|
{
|
||||||
|
formatter.WriteContent(Content);
|
||||||
|
|
||||||
|
formatter.WriteProperty(nameof(Content), Content);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -20,5 +20,13 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
||||||
{
|
{
|
||||||
visitor.VisitMalformedDirective(this);
|
visitor.VisitMalformedDirective(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void FormatNode(IntermediateNodeFormatter formatter)
|
||||||
|
{
|
||||||
|
formatter.WriteContent(DirectiveName);
|
||||||
|
|
||||||
|
formatter.WriteProperty(nameof(Directive), Directive?.DisplayName);
|
||||||
|
formatter.WriteProperty(nameof(DirectiveName), DirectiveName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
||||||
{
|
{
|
||||||
|
|
@ -28,5 +30,31 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
||||||
visitor.VisitMethodDeclaration(this);
|
visitor.VisitMethodDeclaration(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void FormatNode(IntermediateNodeFormatter formatter)
|
||||||
|
{
|
||||||
|
formatter.WriteContent(MethodName);
|
||||||
|
|
||||||
|
formatter.WriteProperty(nameof(MethodName), MethodName);
|
||||||
|
formatter.WriteProperty(nameof(Modifiers), string.Join(", ", Modifiers));
|
||||||
|
formatter.WriteProperty(nameof(Parameters), string.Join(", ", Parameters.Select(FormatMethodParameter)));
|
||||||
|
formatter.WriteProperty(nameof(ReturnType), ReturnType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string FormatMethodParameter(MethodParameter parameter)
|
||||||
|
{
|
||||||
|
var builder = new StringBuilder();
|
||||||
|
for (var i = 0; i <parameter.Modifiers.Count; i++)
|
||||||
|
{
|
||||||
|
builder.Append(parameter.Modifiers[i]);
|
||||||
|
builder.Append(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.Append(parameter.TypeName);
|
||||||
|
builder.Append(" ");
|
||||||
|
|
||||||
|
builder.Append(parameter.ParameterName);
|
||||||
|
|
||||||
|
return builder.ToString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,5 +20,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
||||||
|
|
||||||
visitor.VisitNamespaceDeclaration(this);
|
visitor.VisitNamespaceDeclaration(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void FormatNode(IntermediateNodeFormatter formatter)
|
||||||
|
{
|
||||||
|
formatter.WriteContent(Content);
|
||||||
|
|
||||||
|
formatter.WriteProperty(nameof(Content), Content);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,5 +22,13 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
||||||
|
|
||||||
visitor.VisitTagHelperHtmlAttribute(this);
|
visitor.VisitTagHelperHtmlAttribute(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void FormatNode(IntermediateNodeFormatter formatter)
|
||||||
|
{
|
||||||
|
formatter.WriteContent(AttributeName);
|
||||||
|
|
||||||
|
formatter.WriteProperty(nameof(AttributeName), AttributeName);
|
||||||
|
formatter.WriteProperty(nameof(AttributeStructure), AttributeStructure.ToString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,5 +44,14 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
||||||
|
|
||||||
visitor.VisitTagHelper(this);
|
visitor.VisitTagHelper(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void FormatNode(IntermediateNodeFormatter formatter)
|
||||||
|
{
|
||||||
|
formatter.WriteContent(TagName);
|
||||||
|
|
||||||
|
formatter.WriteProperty(nameof(TagHelpers), string.Join(", ", TagHelpers.Select(t => t.DisplayName)));
|
||||||
|
formatter.WriteProperty(nameof(TagMode), TagMode.ToString());
|
||||||
|
formatter.WriteProperty(nameof(TagName), TagName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,5 +28,16 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
||||||
|
|
||||||
visitor.VisitTagHelperProperty(this);
|
visitor.VisitTagHelperProperty(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void FormatNode(IntermediateNodeFormatter formatter)
|
||||||
|
{
|
||||||
|
formatter.WriteContent(AttributeName);
|
||||||
|
|
||||||
|
formatter.WriteProperty(nameof(AttributeName), AttributeName);
|
||||||
|
formatter.WriteProperty(nameof(AttributeStructure), AttributeStructure.ToString());
|
||||||
|
formatter.WriteProperty(nameof(BoundAttribute), BoundAttribute?.DisplayName);
|
||||||
|
formatter.WriteProperty(nameof(IsIndexerNameMatch), IsIndexerNameMatch.ToString());
|
||||||
|
formatter.WriteProperty(nameof(TagHelper), TagHelper?.DisplayName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,5 +20,12 @@ namespace Microsoft.AspNetCore.Razor.Language.Intermediate
|
||||||
|
|
||||||
visitor.VisitUsingDirective(this);
|
visitor.VisitUsingDirective(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void FormatNode(IntermediateNodeFormatter formatter)
|
||||||
|
{
|
||||||
|
formatter.WriteContent(Content);
|
||||||
|
|
||||||
|
formatter.WriteProperty(nameof(Content), Content);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -582,21 +582,18 @@ namespace Microsoft.AspNetCore.Razor.Language.Legacy
|
||||||
|
|
||||||
protected bool IsHtmlCommentAhead()
|
protected bool IsHtmlCommentAhead()
|
||||||
{
|
{
|
||||||
/*
|
// From HTML5 Specification, available at http://www.w3.org/TR/html52/syntax.html#comments
|
||||||
* From HTML5 Specification, available at http://www.w3.org/TR/html52/syntax.html#comments
|
|
||||||
*
|
// Comments must have the following format:
|
||||||
* Comments must have the following format:
|
// 1. The string "<!--"
|
||||||
* 1. The string "<!--"
|
// 2. Optionally, text, with the additional restriction that the text
|
||||||
* 2. Optionally, text, with the additional restriction that the text
|
// 2.1 must not start with the string ">" nor start with the string "->"
|
||||||
* 2.1 must not start with the string ">" nor start with the string "->"
|
// 2.2 nor contain the strings
|
||||||
* 2.2 nor contain the strings
|
// 2.2.1 "<!--"
|
||||||
* 2.2.1 "<!--"
|
// 2.2.2 "-->" As we will be treating this as a comment ending, there is no need to handle this case at all.
|
||||||
* 2.2.2 "-->" // As we will be treating this as a comment ending, there is no need to handle this case at all.
|
// 2.2.3 "--!>"
|
||||||
* 2.2.3 "--!>"
|
// 2.3 nor end with the string "<!-".
|
||||||
* 2.3 nor end with the string "<!-".
|
// 3. The string "-->"
|
||||||
* 3. The string "-->"
|
|
||||||
*
|
|
||||||
* */
|
|
||||||
|
|
||||||
if (CurrentToken.Type != HtmlTokenType.DoubleHyphen)
|
if (CurrentToken.Type != HtmlTokenType.DoubleHyphen)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -9,40 +9,30 @@ namespace Microsoft.CodeAnalysis.Razor
|
||||||
{
|
{
|
||||||
private const string DiagnosticPrefix = "RZ";
|
private const string DiagnosticPrefix = "RZ";
|
||||||
|
|
||||||
/*
|
// Razor.Language starts at 0, 1000, 2000, 3000. Therefore, we should offset by 500 to ensure we can easily
|
||||||
* Razor.Language starts at 0, 1000, 2000, 3000. Therefore, we should offset by 500 to ensure we can easily
|
// maintain this list of diagnostic descriptors in conjunction with the one in Razor.Language.
|
||||||
* maintain this list of diagnostic descriptors in conjunction with the one in Razor.Language.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#region General Errors
|
#region General Errors
|
||||||
|
|
||||||
/*
|
// General Errors ID Offset = 500
|
||||||
* General Errors ID Offset = 500
|
|
||||||
*/
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Language Errors
|
#region Language Errors
|
||||||
|
|
||||||
/*
|
// Language Errors ID Offset = 1500
|
||||||
* Language Errors ID Offset = 1500
|
|
||||||
*/
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Semantic Errors
|
#region Semantic Errors
|
||||||
|
|
||||||
/*
|
// Semantic Errors ID Offset = 2500
|
||||||
* Semantic Errors ID Offset = 2500
|
|
||||||
*/
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region TagHelper Errors
|
#region TagHelper Errors
|
||||||
|
|
||||||
/*
|
// TagHelper Errors ID Offset = 3500
|
||||||
* TagHelper Errors ID Offset = 3500
|
|
||||||
*/
|
|
||||||
|
|
||||||
internal static readonly RazorDiagnosticDescriptor TagHelper_InvalidAttributeNameNullOrEmpty =
|
internal static readonly RazorDiagnosticDescriptor TagHelper_InvalidAttributeNameNullOrEmpty =
|
||||||
new RazorDiagnosticDescriptor(
|
new RazorDiagnosticDescriptor(
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue