4
4
using System ;
5
5
using System . Collections . Generic ;
6
6
using System . Collections . Immutable ;
7
- using System . Diagnostics ;
8
7
using System . IO ;
9
- using System . Linq ;
10
- using System . Text . RegularExpressions ;
11
8
using System . Threading ;
12
9
using System . Threading . Tasks ;
13
10
using Microsoft . CodeAnalysis ;
14
- using Microsoft . CodeAnalysis . Scripting ;
15
- using Microsoft . CodeAnalysis . Text ;
16
11
17
12
namespace Microsoft . Azure . WebJobs . Script . Description . Node . TypeScript
18
13
{
19
14
public class TypeScriptCompilation : IJavaScriptCompilation
20
15
{
21
- private static readonly Regex DiagnosticRegex = new Regex ( "^(.*.ts)\\ ((\\ d*),(\\ d*)\\ ): (\\ w*) (TS[0-9]{0,4}): (.*)$" , RegexOptions . Compiled ) ;
16
+ private static readonly Lazy < ITypeScriptCompiler > _defaultCompiler = new Lazy < ITypeScriptCompiler > ( ( ) => new TypeScriptCompiler ( ) , LazyThreadSafetyMode . ExecutionAndPublication ) ;
17
+
22
18
private readonly string _inputFilePath ;
23
19
private readonly TypeScriptCompilationOptions _options ;
24
20
private readonly List < Diagnostic > _diagnostics = new List < Diagnostic > ( ) ;
21
+ private readonly ITypeScriptCompiler _compiler ;
25
22
26
- private TypeScriptCompilation ( string inputFilePath , TypeScriptCompilationOptions options )
23
+ private TypeScriptCompilation ( string inputFilePath , TypeScriptCompilationOptions options , ITypeScriptCompiler compiler )
27
24
{
25
+ _compiler = compiler ;
28
26
_inputFilePath = inputFilePath ;
29
27
_options = options ;
30
28
}
31
29
32
30
public bool SupportsDiagnostics => true ;
33
31
34
- private Task CompileAsync ( )
32
+ private async Task CompileAsync ( )
35
33
{
36
- var tcs = new TaskCompletionSource < object > ( ) ;
37
-
38
- try
39
- {
40
- string inputDirectory = Path . GetDirectoryName ( _inputFilePath ) ;
41
-
42
- var startInfo = new ProcessStartInfo
43
- {
44
- FileName = _options . ToolPath ,
45
- RedirectStandardOutput = true ,
46
- RedirectStandardError = true ,
47
- CreateNoWindow = true ,
48
- UseShellExecute = false ,
49
- ErrorDialog = false ,
50
- WorkingDirectory = inputDirectory ,
51
- Arguments = _options . ToArgumentString ( _inputFilePath )
52
- } ;
53
-
54
- var process = new Process { StartInfo = startInfo } ;
55
- process . ErrorDataReceived += ProcessDataReceived ;
56
- process . OutputDataReceived += ProcessDataReceived ;
57
- process . EnableRaisingEvents = true ;
58
- process . Exited += ( s , e ) =>
59
- {
60
- process . WaitForExit ( ) ;
61
- process . Close ( ) ;
62
-
63
- if ( _diagnostics . Any ( d => d . Severity == DiagnosticSeverity . Error ) )
64
- {
65
- tcs . SetException ( new CompilationErrorException ( "Compilation failed." , GetDiagnostics ( ) ) ) ;
66
- }
67
- else
68
- {
69
- tcs . SetResult ( null ) ;
70
- }
71
- } ;
72
-
73
- process . Start ( ) ;
74
-
75
- process . BeginErrorReadLine ( ) ;
76
- process . BeginOutputReadLine ( ) ;
77
- }
78
- catch ( Exception exc )
79
- {
80
- tcs . SetException ( exc ) ;
81
- }
82
-
83
- return tcs . Task ;
84
- }
85
-
86
- private void ProcessDataReceived ( object sender , DataReceivedEventArgs e )
87
- {
88
- if ( e . Data != null && TryParseDiagnostic ( e . Data , out Diagnostic diagnostic ) )
89
- {
90
- _diagnostics . Add ( diagnostic ) ;
91
- }
92
- }
93
-
94
- internal static bool TryParseDiagnostic ( string data , out Diagnostic diagnostic )
95
- {
96
- diagnostic = null ;
97
- Match match = DiagnosticRegex . Match ( data ) ;
98
-
99
- if ( match . Success )
100
- {
101
- DiagnosticSeverity severity = ( DiagnosticSeverity ) Enum . Parse ( typeof ( DiagnosticSeverity ) , match . Groups [ 4 ] . Value , true ) ;
102
- var descriptor = new DiagnosticDescriptor ( match . Groups [ 5 ] . Value , match . Groups [ 6 ] . Value , match . Groups [ 6 ] . Value , string . Empty , severity , true ) ;
103
- int line = int . Parse ( match . Groups [ 2 ] . Value ) - 1 ;
104
- int column = int . Parse ( match . Groups [ 3 ] . Value ) - 1 ;
105
- var linePosition = new LinePosition ( line , column ) ;
106
- var location = Location . Create ( match . Groups [ 1 ] . Value , new TextSpan ( linePosition . Line , 0 ) , new LinePositionSpan ( linePosition , linePosition ) ) ;
107
-
108
- diagnostic = Diagnostic . Create ( descriptor , location ) ;
109
- }
110
-
111
- return diagnostic != null ;
34
+ var diagnostics = await _compiler . CompileAsync ( _inputFilePath , _options ) ;
112
35
}
113
36
114
- public static async Task < TypeScriptCompilation > CompileAsync ( string inputFile , TypeScriptCompilationOptions options )
37
+ public static async Task < TypeScriptCompilation > CompileAsync ( string inputFile , TypeScriptCompilationOptions options , ITypeScriptCompiler compiler = null )
115
38
{
116
- var compilation = new TypeScriptCompilation ( inputFile , options ) ;
39
+ var compilation = new TypeScriptCompilation ( inputFile , options , compiler ?? _defaultCompiler . Value ) ;
117
40
await compilation . CompileAsync ( ) ;
118
41
119
42
return compilation ;
@@ -125,10 +48,10 @@ public static async Task<TypeScriptCompilation> CompileAsync(string inputFile, T
125
48
126
49
public string Emit ( CancellationToken cancellationToken )
127
50
{
128
- string inputFilePath = Path . GetDirectoryName ( _inputFilePath ) ;
129
- string outputFileName = Path . GetFileNameWithoutExtension ( _inputFilePath ) + ".js" ;
51
+ string relativeInputFilePath = FileUtility . GetRelativePath ( _options . RootDir , _inputFilePath ) ;
52
+ string outputFileName = Path . ChangeExtension ( relativeInputFilePath , ".js" ) ;
130
53
131
- return Path . Combine ( inputFilePath , _options . OutDir , outputFileName ) ;
54
+ return Path . Combine ( Path . GetDirectoryName ( _inputFilePath ) , _options . OutDir , outputFileName ) ;
132
55
}
133
56
}
134
57
}
0 commit comments