4
4
using System ;
5
5
using System . Collections . Generic ;
6
6
using System . IO ;
7
+ using System . Linq ;
7
8
using System . Reflection ;
8
9
using System . Text ;
9
10
using System . Text . RegularExpressions ;
10
11
using System . Threading ;
11
12
using System . Threading . Tasks ;
13
+ using Microsoft . Azure . WebJobs . Host ;
12
14
using Microsoft . CodeAnalysis ;
13
15
using Microsoft . CodeAnalysis . Scripting ;
14
16
using Microsoft . CodeAnalysis . Scripting . Hosting ;
@@ -22,36 +24,26 @@ namespace Microsoft.Azure.WebJobs.Script.Description
22
24
{
23
25
internal class FSharpCompiler : ICompilationService
24
26
{
25
- private static readonly string [ ] TheWatchedFileTypes = { ".fs" , ".fsx" , ".dll" , ".exe" , ".fsi" } ;
27
+ private static readonly string [ ] FileTypes = { ".fs" , ".fsx" , ".dll" , ".exe" , ".fsi" } ;
26
28
private readonly IFunctionMetadataResolver _metadataResolver ;
27
29
private static readonly Lazy < InteractiveAssemblyLoader > AssemblyLoader
28
30
= new Lazy < InteractiveAssemblyLoader > ( ( ) => new InteractiveAssemblyLoader ( ) , LazyThreadSafetyMode . ExecutionAndPublication ) ;
29
31
30
32
private readonly OptimizationLevel _optimizationLevel ;
31
33
private readonly Regex _hashRRegex ;
34
+ private readonly TraceWriter _traceWriter ;
32
35
33
- public FSharpCompiler ( IFunctionMetadataResolver metadataResolver , OptimizationLevel optimizationLevel )
36
+ public FSharpCompiler ( IFunctionMetadataResolver metadataResolver , OptimizationLevel optimizationLevel , TraceWriter traceWriter )
34
37
{
35
38
_metadataResolver = metadataResolver ;
36
39
_optimizationLevel = optimizationLevel ;
40
+ _traceWriter = traceWriter ;
37
41
_hashRRegex = new Regex ( @"^\s*#r\s+" , RegexOptions . Compiled | RegexOptions . IgnoreCase ) ;
38
42
}
39
43
40
- public string Language
41
- {
42
- get
43
- {
44
- return "FSharp" ;
45
- }
46
- }
44
+ public string Language => "FSharp" ;
47
45
48
- public IEnumerable < string > SupportedFileTypes
49
- {
50
- get
51
- {
52
- return TheWatchedFileTypes ;
53
- }
54
- }
46
+ public IEnumerable < string > SupportedFileTypes => FileTypes ;
55
47
56
48
public ICompilation GetFunctionCompilation ( FunctionMetadata functionMetadata )
57
49
{
@@ -77,7 +69,6 @@ public ICompilation GetFunctionCompilation(FunctionMetadata functionMetadata)
77
69
var resolverSource = resolverSourceBuilder . ToString ( ) ;
78
70
79
71
Script < object > script = CodeAnalysis . CSharp . Scripting . CSharpScript . Create ( resolverSource , options : _metadataResolver . CreateScriptOptions ( ) , assemblyLoader : AssemblyLoader . Value ) ;
80
- Compilation compilation = script . GetCompilation ( ) ;
81
72
82
73
var compiler = new SimpleSourceCodeServices ( msbuildEnabled : FSharpOption < bool > . Some ( false ) ) ;
83
74
@@ -90,7 +81,7 @@ public ICompilation GetFunctionCompilation(FunctionMetadata functionMetadata)
90
81
91
82
string scriptFilePath = Path . Combine ( scriptPath , Path . GetFileName ( functionMetadata . ScriptFile ) ) ;
92
83
93
- var assemblyName = FunctionAssemblyLoader . GetAssemblyNameFromMetadata ( functionMetadata , compilation . AssemblyName ) ;
84
+ var assemblyName = FunctionAssemblyLoader . GetAssemblyNameFromMetadata ( functionMetadata , Guid . NewGuid ( ) . ToString ( ) ) ;
94
85
var assemblyFileName = Path . Combine ( scriptPath , assemblyName + ".dll" ) ;
95
86
var pdbName = Path . ChangeExtension ( assemblyFileName , "pdb" ) ;
96
87
@@ -123,31 +114,16 @@ public ICompilation GetFunctionCompilation(FunctionMetadata functionMetadata)
123
114
// as dictated by the C# reference resolver, and F# doesn't like getting multiple references to those.
124
115
otherFlags . Add ( "--noframework" ) ;
125
116
126
- // Add the references as reported by the C# reference resolver.
127
- foreach ( var mdr in compilation . References )
128
- {
129
- if ( ! mdr . Display . Contains ( "Unresolved " ) )
117
+ var references = script . Options . MetadataReferences
118
+ . Cast < UnresolvedMetadataReference > ( )
119
+ . Aggregate ( new List < PortableExecutableReference > ( ) , ( a , r ) =>
130
120
{
131
- otherFlags . Add ( "-r:" + mdr . Display ) ;
132
- }
133
- }
121
+ a . AddRange ( _metadataResolver . ResolveReference ( r . Reference , string . Empty , r . Properties ) ) ;
122
+ return a ;
123
+ } ) ;
134
124
135
- // Above we have used the C# reference resolver to get the basic set of DLL references for the compilation.
136
- //
137
- // However F# has its own view on default options. For scripts these should include the
138
- // following framework facade references.
139
-
140
- otherFlags . Add ( "-r:System.Linq.dll" ) ; // System.Linq.Expressions.Expression<T>
141
- otherFlags . Add ( "-r:System.Reflection.dll" ) ; // System.Reflection.ParameterInfo
142
- otherFlags . Add ( "-r:System.Linq.Expressions.dll" ) ; // System.Linq.IQueryable<T>
143
- otherFlags . Add ( "-r:System.Threading.Tasks.dll" ) ; // valuetype [System.Threading.Tasks]System.Threading.CancellationToken
144
- otherFlags . Add ( "-r:System.IO.dll" ) ; // System.IO.TextWriter
145
- otherFlags . Add ( "-r:System.Net.Requests.dll" ) ; // System.Net.WebResponse etc.
146
- otherFlags . Add ( "-r:System.Collections.dll" ) ; // System.Collections.Generic.List<T>
147
- otherFlags . Add ( "-r:System.Runtime.Numerics.dll" ) ; // BigInteger
148
- otherFlags . Add ( "-r:System.Threading.dll" ) ; // OperationCanceledException
149
- otherFlags . Add ( "-r:System.Runtime.dll" ) ;
150
- otherFlags . Add ( "-r:System.Numerics.dll" ) ;
125
+ // Add the references as reported by the metadata resolver.
126
+ otherFlags . AddRange ( references . Select ( r => "-r:" + r . Display ) ) ;
151
127
152
128
if ( _optimizationLevel == OptimizationLevel . Debug )
153
129
{
@@ -196,13 +172,17 @@ public ICompilation GetFunctionCompilation(FunctionMetadata functionMetadata)
196
172
var assembly = Assembly . Load ( assemblyBytes , pdbBytes ) ;
197
173
assemblyOption = FSharpOption < Assembly > . Some ( assembly ) ;
198
174
}
175
+ else
176
+ {
177
+ _traceWriter . Verbose ( $ "F# compilation failed with arguments: { string . Join ( " " , otherFlags ) } ") ;
178
+ }
199
179
}
200
180
finally
201
181
{
202
182
DeleteDirectoryAsync ( scriptPath , recursive : true )
203
183
. ContinueWith ( t => t . Exception . Handle ( e =>
204
184
{
205
- // TODO: Trace
185
+ _traceWriter . Warning ( $ "Unable to delete F# compilation file: { e . ToString ( ) } " ) ;
206
186
return true ;
207
187
} ) , TaskContinuationOptions . OnlyOnFaulted ) ;
208
188
}
0 commit comments