forked from aspnet/AspNetWebStack
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRazorParser.cs
More file actions
161 lines (136 loc) · 5.78 KB
/
RazorParser.cs
File metadata and controls
161 lines (136 loc) · 5.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// 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 System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Razor.Parser.SyntaxTree;
using System.Web.Razor.Text;
namespace System.Web.Razor.Parser
{
public class RazorParser
{
public RazorParser(ParserBase codeParser, ParserBase markupParser)
{
if (codeParser == null)
{
throw new ArgumentNullException("codeParser");
}
if (markupParser == null)
{
throw new ArgumentNullException("markupParser");
}
MarkupParser = markupParser;
CodeParser = codeParser;
Optimizers = new List<ISyntaxTreeRewriter>()
{
// Move whitespace from start of expression block to markup
new WhiteSpaceRewriter(MarkupParser.BuildSpan),
// Collapse conditional attributes where the entire value is literal
new ConditionalAttributeCollapser(MarkupParser.BuildSpan),
};
}
internal ParserBase CodeParser { get; private set; }
internal ParserBase MarkupParser { get; private set; }
internal IList<ISyntaxTreeRewriter> Optimizers { get; private set; }
public bool DesignTimeMode { get; set; }
public virtual void Parse(TextReader input, ParserVisitor visitor)
{
ParserResults results = ParseCore(new SeekableTextReader(input));
// Replay the results on the visitor
visitor.Visit(results);
}
public virtual ParserResults Parse(TextReader input)
{
return ParseCore(new SeekableTextReader(input));
}
public virtual ParserResults Parse(ITextDocument input)
{
return ParseCore(input);
}
#pragma warning disable 0618
[Obsolete("Lookahead-based readers have been deprecated, use overrides which accept a TextReader or ITextDocument instead")]
public virtual void Parse(LookaheadTextReader input, ParserVisitor visitor)
{
ParserResults results = ParseCore(new SeekableTextReader(input));
// Replay the results on the visitor
visitor.Visit(results);
}
[Obsolete("Lookahead-based readers have been deprecated, use overrides which accept a TextReader or ITextDocument instead")]
public virtual ParserResults Parse(LookaheadTextReader input)
{
return ParseCore(new SeekableTextReader(input));
}
#pragma warning restore 0618
public virtual Task CreateParseTask(TextReader input, Action<Span> spanCallback, Action<RazorError> errorCallback)
{
return CreateParseTask(input, new CallbackVisitor(spanCallback, errorCallback));
}
public virtual Task CreateParseTask(TextReader input, Action<Span> spanCallback, Action<RazorError> errorCallback, SynchronizationContext context)
{
return CreateParseTask(input, new CallbackVisitor(spanCallback, errorCallback) { SynchronizationContext = context });
}
public virtual Task CreateParseTask(TextReader input, Action<Span> spanCallback, Action<RazorError> errorCallback, CancellationToken cancelToken)
{
return CreateParseTask(input, new CallbackVisitor(spanCallback, errorCallback) { CancelToken = cancelToken });
}
public virtual Task CreateParseTask(TextReader input, Action<Span> spanCallback, Action<RazorError> errorCallback, SynchronizationContext context, CancellationToken cancelToken)
{
return CreateParseTask(input, new CallbackVisitor(spanCallback, errorCallback)
{
SynchronizationContext = context,
CancelToken = cancelToken
});
}
[SuppressMessage("Microsoft.Web.FxCop", "MW1200:DoNotConstructTaskInstances", Justification = "This rule is not applicable to this assembly.")]
public virtual Task CreateParseTask(TextReader input,
ParserVisitor consumer)
{
return new Task(() =>
{
try
{
Parse(input, consumer);
}
catch (OperationCanceledException)
{
return; // Just return if we're cancelled.
}
});
}
private ParserResults ParseCore(ITextDocument input)
{
// Setup the parser context
ParserContext context = new ParserContext(input, CodeParser, MarkupParser, MarkupParser)
{
DesignTimeMode = DesignTimeMode
};
MarkupParser.Context = context;
CodeParser.Context = context;
// Execute the parse
MarkupParser.ParseDocument();
// Get the result
ParserResults results = context.CompleteParse();
// Rewrite whitespace if supported
Block current = results.Document;
foreach (ISyntaxTreeRewriter rewriter in Optimizers)
{
current = rewriter.Rewrite(current);
}
// Link the leaf nodes into a chain
Span prev = null;
foreach (Span node in current.Flatten())
{
node.Previous = prev;
if (prev != null)
{
prev.Next = node;
}
prev = node;
}
// Return the new result
return new ParserResults(current, results.ParserErrors);
}
}
}