@@ -106,22 +106,24 @@ private void ReloadScript()
106106 ImmutableArray < Diagnostic > compilationResult = compilation . GetDiagnostics ( ) ;
107107
108108 stopwatch . Stop ( ) ;
109- TraceWriter . Verbose ( string . Format ( CultureInfo . InvariantCulture , "Compilation completed ({0} milliseconds)." , stopwatch . ElapsedMilliseconds ) ) ;
110109
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 ) ) ;
116119
117120 // 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
121123 // 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 ) ) ) )
125127 {
126128 _host . RestartEvent . Set ( ) ;
127129 }
@@ -172,7 +174,7 @@ public override async Task Invoke(object[] parameters)
172174 }
173175 catch ( Exception ex )
174176 {
175- TraceWriter . Error ( ex . Message , ex ) ;
177+ TraceWriter . Error ( ex . Message , ex is CompilationErrorException ? null : ex ) ;
176178 TraceWriter . Verbose ( "Function completed (Failure)" ) ;
177179 throw ;
178180 }
@@ -205,23 +207,18 @@ internal MethodInfo GetFunctionTarget()
205207 {
206208 _assemblyLoader . ReleaseContext ( Metadata ) ;
207209
208- TraceWriter . Verbose ( "Compiling function script." ) ;
209- var stopwatch = new Stopwatch ( ) ;
210- stopwatch . Start ( ) ;
211-
212210 Script < object > script = CreateScript ( ) ;
213211 Compilation compilation = GetScriptCompilation ( script , debug ) ;
212+ CSharpFunctionSignature functionSignature = CSharpFunctionSignature . FromCompilation ( compilation , _functionEntryPointResolver ) ;
213+
214+ ValidateFunctionBindingArguments ( functionSignature , throwIfFailed : true ) ;
214215
215216 using ( assemblyStream = new MemoryStream ( ) )
216217 {
217218 using ( pdbStream = new MemoryStream ( ) )
218219 {
219220 var result = compilation . Emit ( assemblyStream , pdbStream ) ;
220221
221- stopwatch . Stop ( ) ;
222-
223- TraceWriter . Verbose ( string . Format ( CultureInfo . InvariantCulture , "Compilation completed ({0} milliseconds)." , stopwatch . ElapsedMilliseconds ) ) ;
224-
225222 if ( ! result . Success )
226223 {
227224 throw new CompilationErrorException ( "Script compilation failed." , result . Diagnostics ) ;
@@ -233,26 +230,73 @@ internal MethodInfo GetFunctionTarget()
233230 // Get our function entry point
234231 System . Reflection . TypeInfo scriptType = assembly . DefinedTypes . FirstOrDefault ( t => string . Compare ( t . Name , ScriptClassName , StringComparison . Ordinal ) == 0 ) ;
235232 _function = _functionEntryPointResolver . GetFunctionEntryPoint ( scriptType . DeclaredMethods . ToList ( ) ) ;
236- _functionSignature = CSharpFunctionSignature . FromCompilation ( compilation , _functionEntryPointResolver ) ;
233+ _functionSignature = functionSignature ;
237234 }
238235 }
239236 }
240237 catch ( CompilationErrorException ex )
241238 {
242239 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 ) ;
249241 throw ;
250242 }
251243 }
252244
253245 return _function ;
254246 }
255247
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+
256300 private Compilation GetScriptCompilation ( Script < object > script , bool debug )
257301 {
258302 Compilation compilation = script . GetCompilation ( ) ;
0 commit comments