private void ReloadScript() { // Reset cached function ResetFunctionValue(); TraceWriter.Verbose(string.Format(CultureInfo.InvariantCulture, "Script for function '{0}' changed. Reloading.", Metadata.Name)); TraceWriter.Verbose("Compiling function script."); Script <object> script = CreateScript(); Compilation compilation = script.GetCompilation(); ImmutableArray <Diagnostic> compilationResult = compilation.GetDiagnostics(); CSharpFunctionSignature signature = CSharpFunctionSignature.FromCompilation(compilation, _functionEntryPointResolver); compilationResult = ValidateFunctionBindingArguments(signature, compilationResult.ToBuilder()); TraceCompilationDiagnostics(compilationResult); bool compilationSucceeded = !compilationResult.Any(d => d.Severity == DiagnosticSeverity.Error); TraceWriter.Verbose(string.Format(CultureInfo.InvariantCulture, "Compilation {0}.", compilationSucceeded ? "succeeded" : "failed")); // If the compilation succeeded, AND: // - We haven't cached a function (failed to compile on load), OR // - We're referencing local function types (i.e. POCOs defined in the function) AND Our our function signature has changed // Restart our host. if (compilationSucceeded && (_functionSignature == null || (_functionSignature.HasLocalTypeReference || !_functionSignature.Equals(signature)))) { _host.RestartEvent.Set(); } }
private MethodInfo CreateFunctionTarget(CancellationToken cancellationToken) { // TODO:Get this from some context set in/by the host. bool debug = true; MemoryStream assemblyStream = null; MemoryStream pdbStream = null; try { Script <object> script = CreateScript(); Compilation compilation = GetScriptCompilation(script, debug); CSharpFunctionSignature functionSignature = CSharpFunctionSignature.FromCompilation(compilation, _functionEntryPointResolver); ValidateFunctionBindingArguments(functionSignature, throwIfFailed: true); using (assemblyStream = new MemoryStream()) { using (pdbStream = new MemoryStream()) { var result = compilation.Emit(assemblyStream, pdbStream); // Check if cancellation was requested while we were compiling, // and if so quit here. cancellationToken.ThrowIfCancellationRequested(); if (!result.Success) { throw new CompilationErrorException("Script compilation failed.", result.Diagnostics); } Assembly assembly = Assembly.Load(assemblyStream.GetBuffer(), pdbStream.GetBuffer()); _assemblyLoader.CreateOrUpdateContext(Metadata, assembly, _metadataResolver, TraceWriter); // Get our function entry point System.Reflection.TypeInfo scriptType = assembly.DefinedTypes.FirstOrDefault(t => string.Compare(t.Name, ScriptClassName, StringComparison.Ordinal) == 0); _functionSignature = functionSignature; return(_functionEntryPointResolver.GetFunctionEntryPoint(scriptType.DeclaredMethods.ToList())); } } } catch (CompilationErrorException ex) { TraceWriter.Error("Function compilation error"); TraceCompilationDiagnostics(ex.Diagnostics); throw; } }
private ImmutableArray <Diagnostic> ValidateFunctionBindingArguments(CSharpFunctionSignature functionSignature, ImmutableArray <Diagnostic> .Builder builder = null, bool throwIfFailed = false) { var resultBuilder = builder ?? ImmutableArray <Diagnostic> .Empty.ToBuilder(); if (!functionSignature.Parameters.Any(p => string.Compare(p.Name, _triggerInputName, StringComparison.Ordinal) == 0)) { string message = string.Format(CultureInfo.InvariantCulture, "Missing a trigger argument named '{0}'.", _triggerInputName); var descriptor = new DiagnosticDescriptor(CSharpConstants.MissingTriggerArgumentCompilationCode, "Missing trigger argument", message, "AzureFunctions", DiagnosticSeverity.Error, true); resultBuilder.Add(Diagnostic.Create(descriptor, Location.None)); } var bindings = _inputBindings.Where(b => !b.Metadata.IsTrigger).Union(_outputBindings); foreach (var binding in bindings) { if (binding.Metadata.Type == BindingType.Http) { continue; } if (!functionSignature.Parameters.Any(p => string.Compare(p.Name, binding.Metadata.Name, StringComparison.Ordinal) == 0)) { string message = string.Format(CultureInfo.InvariantCulture, "Missing binding argument named '{0}'.", binding.Metadata.Name); var descriptor = new DiagnosticDescriptor(CSharpConstants.MissingBindingArgumentCompilationCode, "Missing binding argument", message, "AzureFunctions", DiagnosticSeverity.Warning, true); resultBuilder.Add(Diagnostic.Create(descriptor, Location.None)); } } ImmutableArray <Diagnostic> result = resultBuilder.ToImmutable(); if (throwIfFailed && result.Any(d => d.Severity == DiagnosticSeverity.Error)) { throw new CompilationErrorException("Function compilation failed.", result); } return(resultBuilder.ToImmutable()); }