Skip to content
This repository was archived by the owner on Jan 12, 2024. It is now read-only.

Commit deca80d

Browse files
authored
Fix errors with exception handling during compilation and tests (#492)
* Fix error handling in compilation loader/manager * Show original exceptions in tests
1 parent d602131 commit deca80d

File tree

3 files changed

+73
-58
lines changed

3 files changed

+73
-58
lines changed

src/QsCompiler/CompilationManager/CompilationUnitManager.cs

Lines changed: 48 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -702,8 +702,18 @@ public IEnumerable<QsNamespace> GetSyntaxTree() =>
702702
/// Note: this method waits for all currently running or queued tasks to finish
703703
/// before constructing the Compilation object by calling FlushAndExecute.
704704
/// </summary>
705-
public Compilation Build() =>
706-
this.FlushAndExecute(() => new Compilation(this));
705+
public Compilation Build() => this.FlushAndExecute(() =>
706+
{
707+
try
708+
{
709+
return new Compilation(this);
710+
}
711+
catch (Exception ex)
712+
{
713+
LogException(ex);
714+
return null;
715+
}
716+
});
707717

708718
/// <summary>
709719
/// Class used to accumulate all information about the state of a compilation unit in immutable form.
@@ -843,46 +853,42 @@ public IEnumerable<NonNullable<string>> SymbolsDefinedInNamespace(NonNullable<st
843853

844854
internal Compilation(CompilationUnitManager manager)
845855
{
846-
try
847-
{
848-
this.BuiltCompilation = manager.CompilationUnit.Build();
849-
this.SourceFiles = manager.FileContentManagers.Keys.ToImmutableHashSet();
850-
this.References = manager.CompilationUnit.Externals.Declarations.Keys.ToImmutableHashSet();
851-
852-
this.FileContent = this.SourceFiles
853-
.Select(file => (file, manager.FileContentManagers[file].GetLines().Select(line => line.Text).ToImmutableArray()))
854-
.ToImmutableDictionary(tuple => tuple.Item1, tuple => tuple.Item2);
855-
this.Tokenization = this.SourceFiles
856-
.Select(file => (file, manager.FileContentManagers[file].GetTokenizedLines().Select(line => line.Select(frag => frag.Copy()).ToImmutableArray()).ToImmutableArray()))
857-
.ToImmutableDictionary(tuple => tuple.Item1, tuple => tuple.Item2);
858-
this.SyntaxTree = this.BuiltCompilation.Namespaces.ToImmutableDictionary(ns => ns.Name);
859-
860-
this.OpenDirectivesForEachFile = this.SyntaxTree.Keys.ToImmutableDictionary(
861-
nsName => nsName,
862-
nsName => manager.CompilationUnit.GetOpenDirectives(nsName));
863-
this.NamespaceDeclarations = this.SourceFiles
864-
.Select(file => (file, manager.FileContentManagers[file].NamespaceDeclarationTokens().Select(t => t.GetFragmentWithClosingComments()).ToImmutableArray()))
865-
.ToImmutableDictionary(tuple => tuple.Item1, tuple => tuple.Item2);
866-
this.Callables = this.SyntaxTree.Values.GlobalCallableResolutions();
867-
this.Types = this.SyntaxTree.Values.GlobalTypeResolutions();
868-
869-
this.ScopeDiagnostics = this.SourceFiles
870-
.Select(file => (file, manager.FileContentManagers[file].CurrentScopeDiagnostics()))
871-
.ToImmutableDictionary(tuple => tuple.Item1, tuple => tuple.Item2);
872-
this.SyntaxDiagnostics = this.SourceFiles
873-
.Select(file => (file, manager.FileContentManagers[file].CurrentSyntaxDiagnostics()))
874-
.ToImmutableDictionary(tuple => tuple.Item1, tuple => tuple.Item2);
875-
this.ContextDiagnostics = this.SourceFiles
876-
.Select(file => (file, manager.FileContentManagers[file].CurrentContextDiagnostics()))
877-
.ToImmutableDictionary(tuple => tuple.Item1, tuple => tuple.Item2);
878-
this.HeaderDiagnostics = this.SourceFiles
879-
.Select(file => (file, manager.FileContentManagers[file].CurrentHeaderDiagnostics()))
880-
.ToImmutableDictionary(tuple => tuple.Item1, tuple => tuple.Item2);
881-
this.SemanticDiagnostics = this.SourceFiles
882-
.Select(file => (file, manager.FileContentManagers[file].CurrentSemanticDiagnostics()))
883-
.ToImmutableDictionary(tuple => tuple.Item1, tuple => tuple.Item2);
884-
}
885-
catch (Exception ex) { manager.LogException(ex); }
856+
this.BuiltCompilation = manager.CompilationUnit.Build();
857+
this.SourceFiles = manager.FileContentManagers.Keys.ToImmutableHashSet();
858+
this.References = manager.CompilationUnit.Externals.Declarations.Keys.ToImmutableHashSet();
859+
860+
this.FileContent = this.SourceFiles
861+
.Select(file => (file, manager.FileContentManagers[file].GetLines().Select(line => line.Text).ToImmutableArray()))
862+
.ToImmutableDictionary(tuple => tuple.Item1, tuple => tuple.Item2);
863+
this.Tokenization = this.SourceFiles
864+
.Select(file => (file, manager.FileContentManagers[file].GetTokenizedLines().Select(line => line.Select(frag => frag.Copy()).ToImmutableArray()).ToImmutableArray()))
865+
.ToImmutableDictionary(tuple => tuple.Item1, tuple => tuple.Item2);
866+
this.SyntaxTree = this.BuiltCompilation.Namespaces.ToImmutableDictionary(ns => ns.Name);
867+
868+
this.OpenDirectivesForEachFile = this.SyntaxTree.Keys.ToImmutableDictionary(
869+
nsName => nsName,
870+
nsName => manager.CompilationUnit.GetOpenDirectives(nsName));
871+
this.NamespaceDeclarations = this.SourceFiles
872+
.Select(file => (file, manager.FileContentManagers[file].NamespaceDeclarationTokens().Select(t => t.GetFragmentWithClosingComments()).ToImmutableArray()))
873+
.ToImmutableDictionary(tuple => tuple.Item1, tuple => tuple.Item2);
874+
this.Callables = this.SyntaxTree.Values.GlobalCallableResolutions();
875+
this.Types = this.SyntaxTree.Values.GlobalTypeResolutions();
876+
877+
this.ScopeDiagnostics = this.SourceFiles
878+
.Select(file => (file, manager.FileContentManagers[file].CurrentScopeDiagnostics()))
879+
.ToImmutableDictionary(tuple => tuple.Item1, tuple => tuple.Item2);
880+
this.SyntaxDiagnostics = this.SourceFiles
881+
.Select(file => (file, manager.FileContentManagers[file].CurrentSyntaxDiagnostics()))
882+
.ToImmutableDictionary(tuple => tuple.Item1, tuple => tuple.Item2);
883+
this.ContextDiagnostics = this.SourceFiles
884+
.Select(file => (file, manager.FileContentManagers[file].CurrentContextDiagnostics()))
885+
.ToImmutableDictionary(tuple => tuple.Item1, tuple => tuple.Item2);
886+
this.HeaderDiagnostics = this.SourceFiles
887+
.Select(file => (file, manager.FileContentManagers[file].CurrentHeaderDiagnostics()))
888+
.ToImmutableDictionary(tuple => tuple.Item1, tuple => tuple.Item2);
889+
this.SemanticDiagnostics = this.SourceFiles
890+
.Select(file => (file, manager.FileContentManagers[file].CurrentSemanticDiagnostics()))
891+
.ToImmutableDictionary(tuple => tuple.Item1, tuple => tuple.Item2);
886892
}
887893
}
888894
}

src/QsCompiler/Compiler/CompilationLoader.cs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -871,23 +871,29 @@ private References LoadAssemblies(IEnumerable<string> refs, bool loadTestNames,
871871
/// </summary>
872872
private bool SerializeSyntaxTree(MemoryStream ms)
873873
{
874+
void LogError() => this.LogAndUpdate(
875+
ref this.CompilationStatus.Serialization, ErrorCode.SerializationFailed, Enumerable.Empty<string>());
876+
874877
if (ms == null) throw new ArgumentNullException(nameof(ms));
875-
bool ErrorAndReturn()
878+
this.CompilationStatus.Serialization = 0;
879+
if (this.CompilationOutput == null)
876880
{
877-
this.LogAndUpdate(ref this.CompilationStatus.Serialization, ErrorCode.SerializationFailed, Enumerable.Empty<string>());
881+
LogError();
878882
return false;
879883
}
880-
this.CompilationStatus.Serialization = 0;
881-
if (this.CompilationOutput == null) ErrorAndReturn();
882884

883885
using var writer = new BsonDataWriter(ms) { CloseOutput = false };
884886
var fromSources = this.CompilationOutput.Namespaces.Select(ns => FilterBySourceFile.Apply(ns, s => s.Value.EndsWith(".qs")));
885887
var compilation = new QsCompilation(fromSources.ToImmutableArray(), this.CompilationOutput.EntryPoints);
886-
try { Json.Serializer.Serialize(writer, compilation); }
888+
try
889+
{
890+
Json.Serializer.Serialize(writer, compilation);
891+
}
887892
catch (Exception ex)
888893
{
889894
this.LogAndUpdate(ref this.CompilationStatus.Serialization, ex);
890-
ErrorAndReturn();
895+
LogError();
896+
return false;
891897
}
892898
return true;
893899
}

src/QsCompiler/Tests.Compiler/TestUtils/SetupVerificationTests.fs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -90,15 +90,18 @@ type CompilerTests (compilation : CompilationUnitManager.Compilation) =
9090
if other.Any() then NotImplementedException "unknown diagnostics item to verify" |> raise
9191

9292

93-
static member Compile (srcFolder, files, ?references, ?capabilities) =
93+
static member Compile (srcFolder, fileNames, ?references, ?capabilities) =
9494
let references = defaultArg references []
9595
let capabilities = defaultArg capabilities RuntimeCapabilities.Unknown
96-
let compileFiles (files : IEnumerable<_>) =
97-
let mgr = new CompilationUnitManager((fun ex -> failwith ex.Message), capabilities = capabilities)
98-
files.ToImmutableDictionary(Path.GetFullPath >> Uri, File.ReadAllText)
99-
|> CompilationUnitManager.InitializeFileManagers
100-
|> mgr.AddOrUpdateSourceFilesAsync
101-
|> ignore
102-
mgr.UpdateReferencesAsync(new References(ProjectManager.LoadReferencedAssemblies(references))) |> ignore
103-
mgr.Build()
104-
files |> Seq.map (fun file -> Path.Combine (srcFolder, file)) |> compileFiles
96+
let paths = fileNames |> Seq.map (fun file -> Path.Combine (srcFolder, file) |> Path.GetFullPath)
97+
let mutable exceptions = []
98+
use manager = new CompilationUnitManager ((fun e -> exceptions <- e :: exceptions), capabilities = capabilities)
99+
paths.ToImmutableDictionary (Uri, File.ReadAllText)
100+
|> CompilationUnitManager.InitializeFileManagers
101+
|> manager.AddOrUpdateSourceFilesAsync
102+
|> ignore
103+
references |> ProjectManager.LoadReferencedAssemblies |> References |> manager.UpdateReferencesAsync |> ignore
104+
let compilation = manager.Build ()
105+
if not <| List.isEmpty exceptions
106+
then exceptions |> List.rev |> AggregateException |> raise
107+
compilation

0 commit comments

Comments
 (0)