@@ -106,22 +106,24 @@ private void ReloadScript()
106
106
ImmutableArray < Diagnostic > compilationResult = compilation . GetDiagnostics ( ) ;
107
107
108
108
stopwatch . Stop ( ) ;
109
- TraceWriter . Verbose ( string . Format ( CultureInfo . InvariantCulture , "Compilation completed ({0} milliseconds)." , stopwatch . ElapsedMilliseconds ) ) ;
110
109
111
- foreach ( var diagnostic in compilationResult )
112
- {
113
- var traceEvent = new TraceEvent ( GetTraceLevelFromDiagnostic ( diagnostic ) , diagnostic . ToString ( ) ) ;
114
- TraceWriter . Trace ( traceEvent ) ;
115
- }
110
+ CSharpFunctionSignature signature = CSharpFunctionSignature . FromCompilation ( compilation , _functionEntryPointResolver ) ;
111
+ compilationResult = ValidateFunctionBindingArguments ( signature , compilationResult . ToBuilder ( ) ) ;
112
+
113
+ TraceCompilationDiagnostics ( compilationResult ) ;
114
+
115
+ bool compilationSucceeded = ! compilationResult . Any ( d => d . Severity == DiagnosticSeverity . Error ) ;
116
+
117
+ TraceWriter . Verbose ( string . Format ( CultureInfo . InvariantCulture , "Compilation {0} ({1} ms)." ,
118
+ compilationSucceeded ? "succeeded" : "failed" , stopwatch . ElapsedMilliseconds ) ) ;
116
119
117
120
// If the compilation succeeded, AND:
118
- // - We're referencing local function types (i.e. POCOs defined in the function)
119
- // OR
120
- // - Our our function signature has changed
121
+ // - We haven't cached a function (failed to compile on load), OR
122
+ // - We're referencing local function types (i.e. POCOs defined in the function) AND Our our function signature has changed
121
123
// Restart our host.
122
- if ( ! compilationResult . Any ( d => d . Severity == DiagnosticSeverity . Error ) &&
123
- ( _functionSignature . HasLocalTypeReference ||
124
- ! _functionSignature . Equals ( CSharpFunctionSignature . FromCompilation ( compilation , _functionEntryPointResolver ) ) ) )
124
+ if ( compilationSucceeded &&
125
+ ( _functionSignature == null ||
126
+ ( _functionSignature . HasLocalTypeReference || ! _functionSignature . Equals ( signature ) ) ) )
125
127
{
126
128
_host . RestartEvent . Set ( ) ;
127
129
}
@@ -172,7 +174,7 @@ public override async Task Invoke(object[] parameters)
172
174
}
173
175
catch ( Exception ex )
174
176
{
175
- TraceWriter . Error ( ex . Message , ex ) ;
177
+ TraceWriter . Error ( ex . Message , ex is CompilationErrorException ? null : ex ) ;
176
178
TraceWriter . Verbose ( "Function completed (Failure)" ) ;
177
179
throw ;
178
180
}
@@ -205,23 +207,18 @@ internal MethodInfo GetFunctionTarget()
205
207
{
206
208
_assemblyLoader . ReleaseContext ( Metadata ) ;
207
209
208
- TraceWriter . Verbose ( "Compiling function script." ) ;
209
- var stopwatch = new Stopwatch ( ) ;
210
- stopwatch . Start ( ) ;
211
-
212
210
Script < object > script = CreateScript ( ) ;
213
211
Compilation compilation = GetScriptCompilation ( script , debug ) ;
212
+ CSharpFunctionSignature functionSignature = CSharpFunctionSignature . FromCompilation ( compilation , _functionEntryPointResolver ) ;
213
+
214
+ ValidateFunctionBindingArguments ( functionSignature , throwIfFailed : true ) ;
214
215
215
216
using ( assemblyStream = new MemoryStream ( ) )
216
217
{
217
218
using ( pdbStream = new MemoryStream ( ) )
218
219
{
219
220
var result = compilation . Emit ( assemblyStream , pdbStream ) ;
220
221
221
- stopwatch . Stop ( ) ;
222
-
223
- TraceWriter . Verbose ( string . Format ( CultureInfo . InvariantCulture , "Compilation completed ({0} milliseconds)." , stopwatch . ElapsedMilliseconds ) ) ;
224
-
225
222
if ( ! result . Success )
226
223
{
227
224
throw new CompilationErrorException ( "Script compilation failed." , result . Diagnostics ) ;
@@ -233,26 +230,73 @@ internal MethodInfo GetFunctionTarget()
233
230
// Get our function entry point
234
231
System . Reflection . TypeInfo scriptType = assembly . DefinedTypes . FirstOrDefault ( t => string . Compare ( t . Name , ScriptClassName , StringComparison . Ordinal ) == 0 ) ;
235
232
_function = _functionEntryPointResolver . GetFunctionEntryPoint ( scriptType . DeclaredMethods . ToList ( ) ) ;
236
- _functionSignature = CSharpFunctionSignature . FromCompilation ( compilation , _functionEntryPointResolver ) ;
233
+ _functionSignature = functionSignature ;
237
234
}
238
235
}
239
236
}
240
237
catch ( CompilationErrorException ex )
241
238
{
242
239
TraceWriter . Error ( "Function compilation error" ) ;
243
-
244
- foreach ( var diagnostic in ex . Diagnostics . Where ( d => ! d . IsSuppressed ) )
245
- {
246
- TraceLevel level = GetTraceLevelFromDiagnostic ( diagnostic ) ;
247
- TraceWriter . Trace ( new TraceEvent ( level , diagnostic . ToString ( ) ) ) ;
248
- }
240
+ TraceCompilationDiagnostics ( ex . Diagnostics ) ;
249
241
throw ;
250
242
}
251
243
}
252
244
253
245
return _function ;
254
246
}
255
247
248
+ private void TraceCompilationDiagnostics ( ImmutableArray < Diagnostic > diagnostics )
249
+ {
250
+ foreach ( var diagnostic in diagnostics . Where ( d => ! d . IsSuppressed ) )
251
+ {
252
+ TraceLevel level = GetTraceLevelFromDiagnostic ( diagnostic ) ;
253
+ TraceWriter . Trace ( new TraceEvent ( level , diagnostic . ToString ( ) ) ) ;
254
+ }
255
+ }
256
+
257
+ private ImmutableArray < Diagnostic > ValidateFunctionBindingArguments ( CSharpFunctionSignature functionSignature ,
258
+ ImmutableArray < Diagnostic > . Builder builder = null , bool throwIfFailed = false )
259
+ {
260
+ var resultBuilder = builder ?? ImmutableArray < Diagnostic > . Empty . ToBuilder ( ) ;
261
+
262
+ if ( ! functionSignature . Parameters . Any ( p => string . Compare ( p . Name , _triggerInputName , StringComparison . Ordinal ) == 0 ) )
263
+ {
264
+ string message = string . Format ( CultureInfo . InvariantCulture , "Missing a trigger argument named '{0}'." , _triggerInputName ) ;
265
+ var descriptor = new DiagnosticDescriptor ( CSharpConstants . MissingTriggerArgumentCompilationCode ,
266
+ "Missing trigger argument" , message , "AzureFunctions" , DiagnosticSeverity . Error , true ) ;
267
+
268
+ resultBuilder . Add ( Diagnostic . Create ( descriptor , Location . None ) ) ;
269
+ }
270
+
271
+ var bindings = _inputBindings . Where ( b => ! b . IsTrigger ) . Union ( _outputBindings ) ;
272
+
273
+ foreach ( var binding in bindings )
274
+ {
275
+ if ( binding . Type == "http" )
276
+ {
277
+ continue ;
278
+ }
279
+
280
+ if ( ! functionSignature . Parameters . Any ( p => string . Compare ( p . Name , binding . Name , StringComparison . Ordinal ) == 0 ) )
281
+ {
282
+ string message = string . Format ( CultureInfo . InvariantCulture , "Missing binding argument named '{0}'." , binding . Name ) ;
283
+ var descriptor = new DiagnosticDescriptor ( CSharpConstants . MissingBindingArgumentCompilationCode ,
284
+ "Missing binding argument" , message , "AzureFunctions" , DiagnosticSeverity . Warning , true ) ;
285
+
286
+ resultBuilder . Add ( Diagnostic . Create ( descriptor , Location . None ) ) ;
287
+ }
288
+ }
289
+
290
+ ImmutableArray < Diagnostic > result = resultBuilder . ToImmutable ( ) ;
291
+
292
+ if ( throwIfFailed && result . Any ( d => d . Severity == DiagnosticSeverity . Error ) )
293
+ {
294
+ throw new CompilationErrorException ( "Function compilation failed." , result ) ;
295
+ }
296
+
297
+ return resultBuilder . ToImmutable ( ) ;
298
+ }
299
+
256
300
private Compilation GetScriptCompilation ( Script < object > script , bool debug )
257
301
{
258
302
Compilation compilation = script . GetCompilation ( ) ;
0 commit comments