private (ImmutableArray <SyntaxTree> added, ImmutableArray <SyntaxTree> removed) UpdateCompilationInternal(DocumentUri documentUri, int?version)
        {
            try
            {
                var context = this.provider.Create(workspace, documentUri);

                var output = workspace.UpsertSyntaxTrees(context.Compilation.SyntaxTreeGrouping.SyntaxTrees);

                // there shouldn't be concurrent upsert requests (famous last words...), so a simple overwrite should be sufficient
                this.activeContexts[documentUri] = context;

                // convert all the diagnostics to LSP diagnostics
                var diagnostics = GetDiagnosticsFromContext(context).ToDiagnostics(context.LineStarts);

                // publish all the diagnostics
                this.PublishDocumentDiagnostics(documentUri, version, diagnostics);

                return(output);
            }
            catch (Exception exception)
            {
                // this is a fatal error likely due to a code defect

                // publish a single fatal error diagnostic to tell the user something horrible has occurred
                // TODO: Tell user how to create an issue on GitHub.
                var fatalError = new Diagnostic
                {
                    Range = new Range
                    {
                        Start = new Position(0, 0),
                        End   = new Position(1, 0),
                    },
                    Severity = DiagnosticSeverity.Error,
                    Message  = exception.Message,
                    Code     = new DiagnosticCode("Fatal")
                };

                // the file is no longer in a state that can be parsed
                // clear all info to prevent cascading failures elsewhere
                var closedTrees = CloseCompilationInternal(documentUri, version, fatalError.AsEnumerable());

                return(ImmutableArray <SyntaxTree> .Empty, closedTrees);
            }
        }
Beispiel #2
0
        private (ImmutableArray <ISourceFile> added, ImmutableArray <ISourceFile> removed) UpdateCompilationInternal(DocumentUri documentUri, int?version, IDictionary <ISourceFile, ISemanticModel> modelLookup, IEnumerable <ISourceFile> removedFiles, bool reloadBicepConfig = false)
        {
            var configuration = this.GetConfigurationSafely(documentUri, out var configurationDiagnostic);

            try
            {
                var context = this.activeContexts.AddOrUpdate(
                    documentUri,
                    (documentUri) => this.provider.Create(workspace, documentUri, modelLookup.ToImmutableDictionary(), configuration),
                    (documentUri, prevContext) =>
                {
                    var sourceDependencies = removedFiles
                                             .SelectMany(x => prevContext.Compilation.SourceFileGrouping.GetFilesDependingOn(x))
                                             .ToImmutableHashSet();

                    // check for semantic models that we can safely reuse from the previous compilation
                    foreach (var sourceFile in prevContext.Compilation.SourceFileGrouping.SourceFiles)
                    {
                        if (!modelLookup.ContainsKey(sourceFile) && !sourceDependencies.Contains(sourceFile))
                        {
                            // if we have a file with no dependencies on the modified file(s), we can reuse the previous model
                            modelLookup[sourceFile] = prevContext.Compilation.GetSemanticModel(sourceFile);
                        }
                    }

                    var configuration = reloadBicepConfig
                            ? this.GetConfigurationSafely(documentUri.ToUri(), out configurationDiagnostic)
                            : prevContext.Compilation.Configuration;

                    return(this.provider.Create(workspace, documentUri, modelLookup.ToImmutableDictionary(), configuration));
                });

                foreach (var sourceFile in context.Compilation.SourceFileGrouping.SourceFiles)
                {
                    // store all the updated models as other compilations may be able to reuse them
                    modelLookup[sourceFile] = context.Compilation.GetSemanticModel(sourceFile);
                }

                // this completes immediately
                this.scheduler.RequestModuleRestore(this, documentUri, context.Compilation.SourceFileGrouping.ModulesToRestore, configuration);

                var output = workspace.UpsertSourceFiles(context.Compilation.SourceFileGrouping.SourceFiles);

                // convert all the diagnostics to LSP diagnostics
                var diagnostics = GetDiagnosticsFromContext(context).ToDiagnostics(context.LineStarts);

                if (configurationDiagnostic is not null)
                {
                    diagnostics = diagnostics.Append(configurationDiagnostic);
                }

                // publish all the diagnostics
                this.PublishDocumentDiagnostics(documentUri, version, diagnostics);

                return(output);
            }
            catch (Exception exception)
            {
                // this is a fatal error likely due to a code defect

                // publish a single fatal error diagnostic to tell the user something horrible has occurred
                // TODO: Tell user how to create an issue on GitHub.
                var fatalError = new Diagnostic
                {
                    Range = new Range
                    {
                        Start = new Position(0, 0),
                        End   = new Position(1, 0),
                    },
                    Severity = DiagnosticSeverity.Error,
                    Message  = exception.Message,
                    Code     = new DiagnosticCode("Fatal")
                };

                this.PublishDocumentDiagnostics(documentUri, version, fatalError.AsEnumerable());

                return(ImmutableArray <ISourceFile> .Empty, ImmutableArray <ISourceFile> .Empty);
            }
        }