2
2
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3
3
4
4
using System ;
5
+ using System . Collections . Concurrent ;
5
6
using System . Collections . Generic ;
6
7
using System . IO ;
7
8
using System . Linq ;
8
9
using System . Text ;
9
10
using System . Text . RegularExpressions ;
10
11
using System . Threading . Tasks ;
12
+ using Microsoft . AspNetCore . Razor . Language ;
13
+ using Microsoft . CodeAnalysis . Text ;
11
14
using Microsoft . Css . Parser . Parser ;
12
15
using Microsoft . Css . Parser . Tokens ;
13
16
using Microsoft . Css . Parser . TreeItems ;
@@ -57,28 +60,55 @@ protected override bool ValidateArguments()
57
60
58
61
protected override Task < int > ExecuteCoreAsync ( )
59
62
{
63
+ var allDiagnostics = new ConcurrentQueue < RazorDiagnostic > ( ) ;
64
+
60
65
Parallel . For ( 0 , Sources . Values . Count , i =>
61
66
{
62
67
var source = Sources . Values [ i ] ;
63
68
var output = Outputs . Values [ i ] ;
64
69
var cssScope = CssScopes . Values [ i ] ;
65
70
66
- var inputText = File . ReadAllText ( source ) ;
67
- var rewrittenCss = AddScopeToSelectors ( inputText , cssScope ) ;
68
- File . WriteAllText ( output , rewrittenCss ) ;
71
+ using var inputSourceStream = new FileStream ( source , FileMode . Open , FileAccess . Read , FileShare . ReadWrite | FileShare . Delete ) ;
72
+ var inputSourceText = SourceText . From ( inputSourceStream ) ;
73
+
74
+ var rewrittenCss = AddScopeToSelectors ( source , inputSourceText , cssScope , out var diagnostics ) ;
75
+ if ( diagnostics . Any ( ) )
76
+ {
77
+ foreach ( var diagnostic in diagnostics )
78
+ {
79
+ allDiagnostics . Enqueue ( diagnostic ) ;
80
+ }
81
+ }
82
+ else
83
+ {
84
+ File . WriteAllText ( output , rewrittenCss ) ;
85
+ }
69
86
} ) ;
70
87
71
- return Task . FromResult ( ExitCodeSuccess ) ;
88
+ foreach ( var diagnostic in allDiagnostics )
89
+ {
90
+ Error . WriteLine ( diagnostic . ToString ( ) ) ;
91
+ }
92
+
93
+ return Task . FromResult ( allDiagnostics . Any ( ) ? ExitCodeFailure : ExitCodeSuccess ) ;
72
94
}
73
95
74
96
// Public for tests
75
- public static string AddScopeToSelectors ( string inputText , string cssScope )
97
+ public static string AddScopeToSelectors ( string filePath , string inputSource , string cssScope , out IEnumerable < RazorDiagnostic > diagnostics )
98
+ => AddScopeToSelectors ( filePath , SourceText . From ( inputSource ) , cssScope , out diagnostics ) ;
99
+
100
+ private static string AddScopeToSelectors ( string filePath , SourceText inputSourceText , string cssScope , out IEnumerable < RazorDiagnostic > diagnostics )
76
101
{
77
102
var cssParser = new DefaultParserFactory ( ) . CreateParser ( ) ;
103
+ var inputText = inputSourceText . ToString ( ) ;
78
104
var stylesheet = cssParser . Parse ( inputText , insertComments : false ) ;
79
105
80
106
var resultBuilder = new StringBuilder ( ) ;
81
107
var previousInsertionPosition = 0 ;
108
+ var foundDiagnostics = new List < RazorDiagnostic > ( ) ;
109
+
110
+ var ensureNoImportsVisitor = new EnsureNoImports ( filePath , inputSourceText , stylesheet , foundDiagnostics ) ;
111
+ ensureNoImportsVisitor . Visit ( ) ;
82
112
83
113
var scopeInsertionPositionsVisitor = new FindScopeInsertionEdits ( stylesheet ) ;
84
114
scopeInsertionPositionsVisitor . Visit ( ) ;
@@ -105,6 +135,7 @@ public static string AddScopeToSelectors(string inputText, string cssScope)
105
135
106
136
resultBuilder . Append ( inputText . Substring ( previousInsertionPosition ) ) ;
107
137
138
+ diagnostics = foundDiagnostics ;
108
139
return resultBuilder . ToString ( ) ;
109
140
}
110
141
@@ -257,6 +288,36 @@ protected override void VisitAtDirective(AtDirective item)
257
288
}
258
289
}
259
290
291
+ private class EnsureNoImports : Visitor
292
+ {
293
+ private readonly string _filePath ;
294
+ private readonly SourceText _sourceText ;
295
+ private readonly List < RazorDiagnostic > _diagnostics ;
296
+
297
+ public EnsureNoImports ( string filePath , SourceText sourceText , ComplexItem root , List < RazorDiagnostic > diagnostics ) : base ( root )
298
+ {
299
+ _filePath = filePath ;
300
+ _sourceText = sourceText ;
301
+ _diagnostics = diagnostics ;
302
+ }
303
+
304
+ protected override void VisitAtDirective ( AtDirective item )
305
+ {
306
+ if ( item . Children . Count >= 2
307
+ && item . Children [ 0 ] is TokenItem firstChild
308
+ && firstChild . TokenType == CssTokenType . At
309
+ && item . Children [ 1 ] is TokenItem secondChild
310
+ && string . Equals ( secondChild . Text , "import" , StringComparison . OrdinalIgnoreCase ) )
311
+ {
312
+ var linePosition = _sourceText . Lines . GetLinePosition ( item . Start ) ;
313
+ var sourceSpan = new SourceSpan ( _filePath , item . Start , linePosition . Line , linePosition . Character , item . Length ) ;
314
+ _diagnostics . Add ( RazorDiagnosticFactory . CreateCssRewriting_ImportNotAllowed ( sourceSpan ) ) ;
315
+ }
316
+
317
+ base . VisitAtDirective ( item ) ;
318
+ }
319
+ }
320
+
260
321
private class Visitor
261
322
{
262
323
private readonly ComplexItem _root ;
0 commit comments