Skip to content
This repository has been archived by the owner on Dec 19, 2018. It is now read-only.

Commit

Permalink
Add extensible directive abstractions
Browse files Browse the repository at this point in the history
- Based generic directive implementation off of descriptors.
- Added parsing logic to consume descriptors and parse content that's expected.
- Added parsing errors to automagically detect unexpected directive pieces.
- Updated visitor implementations to understand the directive bits.
- Added a builder abstraction to easily create descriptors. Had to maintain the ability to manually construct a descriptor to enable convenient serialization/deserialization.

#853
  • Loading branch information
NTaylorMullen committed Nov 23, 2016
1 parent 47769c1 commit 30388a5
Show file tree
Hide file tree
Showing 16 changed files with 572 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,44 @@ public override void VisitImportSpan(AddImportChunkGenerator chunkGenerator, Spa
Namespace.Children.Insert(i, @using);
}

public override void VisitDirectiveToken(DirectiveTokenChunkGenerator chunkGenerator, Span span)
{
Builder.Add(new DirectiveTokenIRNode()
{
Content = span.Content,
Descriptor = chunkGenerator.Descriptor,
SourceLocation = span.Start,
});
}

public override void VisitStartDirectiveBlock(DirectiveChunkGenerator chunkGenerator, Block block)
{
Builder.Push(new DirectiveIRNode()
{
Name = chunkGenerator.Descriptor.Name,
Descriptor = chunkGenerator.Descriptor,
});
}

public override void VisitEndDirectiveBlock(DirectiveChunkGenerator chunkGenerator, Block block)
{
var directiveNode = (DirectiveIRNode)Builder.Pop();

var tokens = directiveNode.Children.OfType<DirectiveTokenIRNode>().ToList();
var exceptTokens = directiveNode.Children.Except(tokens).ToList();
directiveNode.Children.Clear();

for (var i = 0; i < exceptTokens.Count; i++)
{
directiveNode.Children.Add(exceptTokens[i]);
}

for (var i = 0; i < tokens.Count; i++)
{
directiveNode.Tokens.Add(tokens[i]);
}
}

private class ContainerRazorIRNode : RazorIRNode
{
private SourceLocation? _location;
Expand Down
103 changes: 103 additions & 0 deletions src/Microsoft.AspNetCore.Razor.Evolution/DirectiveDescriptor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// 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.Evolution
{
public class DirectiveDescriptor
{
public static IDirectiveDescriptorBuilder Create(string name)
{
return new DefaultDirectiveDescriptorBuilder(name, DirectiveDescriptorType.SingleLine);
}

public static IDirectiveDescriptorBuilder CreateRazorBlock(string name)
{
return new DefaultDirectiveDescriptorBuilder(name, DirectiveDescriptorType.RazorBlock);
}

public static IDirectiveDescriptorBuilder CreateCodeBlock(string name)
{
return new DefaultDirectiveDescriptorBuilder(name, DirectiveDescriptorType.CodeBlock);
}

public string Name { get; set; }

public DirectiveDescriptorType Type { get; set; }

public IList<DirectiveTokenDescriptor> Tokens { get; set; }

private class DefaultDirectiveDescriptorBuilder : IDirectiveDescriptorBuilder
{
private readonly List<DirectiveTokenDescriptor> _tokenDescriptors;
private readonly string _name;
private readonly DirectiveDescriptorType _type;

public DefaultDirectiveDescriptorBuilder(string name, DirectiveDescriptorType type)
{
_name = name;
_type = type;
_tokenDescriptors = new List<DirectiveTokenDescriptor>();
}

public IDirectiveDescriptorBuilder AddType()
{
var descriptor = new DirectiveTokenDescriptor()
{
Type = DirectiveTokenType.Type
};
_tokenDescriptors.Add(descriptor);

return this;
}

public IDirectiveDescriptorBuilder AddMember()
{
var descriptor = new DirectiveTokenDescriptor()
{
Type = DirectiveTokenType.Member
};
_tokenDescriptors.Add(descriptor);

return this;
}

public IDirectiveDescriptorBuilder AddString()
{
var descriptor = new DirectiveTokenDescriptor()
{
Type = DirectiveTokenType.String
};
_tokenDescriptors.Add(descriptor);

return this;
}

public IDirectiveDescriptorBuilder AddLiteral(string literal, bool optional)
{
var descriptor = new DirectiveTokenDescriptor()
{
Type = DirectiveTokenType.Literal,
Value = literal,
Optional = optional,
};
_tokenDescriptors.Add(descriptor);

return this;
}

public DirectiveDescriptor Build()
{
var descriptor = new DirectiveDescriptor
{
Name = _name,
Type = _type,
Tokens = _tokenDescriptors,
};

return descriptor;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright(c) .NET Foundation.All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

namespace Microsoft.AspNetCore.Razor.Evolution
{
public enum DirectiveDescriptorType
{
SingleLine,
RazorBlock,
CodeBlock
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright(c) .NET Foundation.All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

namespace Microsoft.AspNetCore.Razor.Evolution
{
public class DirectiveTokenDescriptor
{
public DirectiveTokenType Type { get; set; }

public string Value { get; set; }

public bool Optional { get; set; }
}
}
13 changes: 13 additions & 0 deletions src/Microsoft.AspNetCore.Razor.Evolution/DirectiveTokenType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright(c) .NET Foundation.All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

namespace Microsoft.AspNetCore.Razor.Evolution
{
public enum DirectiveTokenType
{
Type,
Member,
String,
Literal
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright(c) .NET Foundation.All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

namespace Microsoft.AspNetCore.Razor.Evolution
{
public interface IDirectiveDescriptorBuilder
{
IDirectiveDescriptorBuilder AddType();

IDirectiveDescriptorBuilder AddMember();

IDirectiveDescriptorBuilder AddString();

IDirectiveDescriptorBuilder AddLiteral(string literal, bool optional);

DirectiveDescriptor Build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright(c) .NET Foundation.All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Collections.Generic;
using Microsoft.AspNetCore.Razor.Evolution.Legacy;

namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
{
public class DirectiveIRNode : RazorIRNode
{
public override IList<RazorIRNode> Children { get; } = new List<RazorIRNode>();

public override RazorIRNode Parent { get; set; }

internal override SourceLocation SourceLocation { get; set; }

public string Name { get; set; }

public IList<DirectiveTokenIRNode> Tokens { get; } = new List<DirectiveTokenIRNode>();

public DirectiveDescriptor Descriptor { get; set; }

public override void Accept(RazorIRNodeVisitor visitor)
{
visitor.VisitDirective(this);
}

public override TResult Accept<TResult>(RazorIRNodeVisitor<TResult> visitor)
{
return visitor.VisitDirective(this);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright(c) .NET Foundation.All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Collections.Generic;
using Microsoft.AspNetCore.Razor.Evolution.Legacy;

namespace Microsoft.AspNetCore.Razor.Evolution.Intermediate
{
public class DirectiveTokenIRNode : RazorIRNode
{
public override IList<RazorIRNode> Children { get; } = EmptyArray;

public override RazorIRNode Parent { get; set; }

internal override SourceLocation SourceLocation { get; set; }

public string Content { get; set; }

public DirectiveTokenDescriptor Descriptor { get; set; }

public override void Accept(RazorIRNodeVisitor visitor)
{
visitor.VisitDirectiveToken(this);
}

public override TResult Accept<TResult>(RazorIRNodeVisitor<TResult> visitor)
{
return visitor.VisitDirectiveToken(this);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ public virtual void VisitDefault(RazorIRNode node)
{
}

public virtual void VisitDirectiveToken(DirectiveTokenIRNode node)
{
VisitDefault(node);
}

public virtual void VisitDirective(DirectiveIRNode node)
{
VisitDefault(node);
}

public virtual void VisitTemplate(TemplateIRNode node)
{
VisitDefault(node);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@ public virtual TResult VisitDefault(RazorIRNode node)
return default(TResult);
}

public virtual TResult VisitDirectiveToken(DirectiveTokenIRNode node)
{
return VisitDefault(node);
}

public virtual TResult VisitDirective(DirectiveIRNode node)
{
return VisitDefault(node);
}

public virtual TResult VisitTemplate(TemplateIRNode node)
{
return VisitDefault(node);
Expand Down
Loading

0 comments on commit 30388a5

Please sign in to comment.