Ejemplo n.º 1
0
        /// <summary>
        /// Loads the Q# data structures in a referenced assembly given the Uri to that assembly,
        /// and returns the loaded content as out parameter.
        /// Returns false if some of the content could not be loaded successfully,
        /// possibly because the referenced assembly has been compiled with an older compiler version.
        /// If onDeserializationException is specified, invokes the given action on any exception thrown during deserialization.
        /// Throws the corresponding exceptions if the information cannot be extracted.
        /// </summary>
        /// <exception cref="FileNotFoundException"><paramref name="asm"/> does not exist.</exception>
        /// <exception cref="ArgumentException"><paramref name="asm"/> is not an absolute file URI.</exception>
        public static bool LoadReferencedAssembly(Uri asm, out References.Headers headers, bool ignoreDllResources = false, Action <Exception>?onDeserializationException = null)
        {
            var id = CompilationUnitManager.GetFileId(asm);

            if (!File.Exists(asm.LocalPath))
            {
                throw new FileNotFoundException($"The file '{asm.LocalPath}' given to the assembly loader does not exist.");
            }

            using var stream       = File.OpenRead(asm.LocalPath);
            using var assemblyFile = new PEReader(stream);
            if (ignoreDllResources || !FromResource(assemblyFile, out var compilation, onDeserializationException))
            {
                PerformanceTracking.TaskStart(PerformanceTracking.Task.HeaderAttributesLoading);
                var attributes = LoadHeaderAttributes(assemblyFile);
                PerformanceTracking.TaskEnd(PerformanceTracking.Task.HeaderAttributesLoading);
                PerformanceTracking.TaskStart(PerformanceTracking.Task.ReferenceHeadersCreation);
                headers = new References.Headers(id, attributes);
                PerformanceTracking.TaskEnd(PerformanceTracking.Task.ReferenceHeadersCreation);
                return(ignoreDllResources || !attributes.Any()); // just means we have no references
            }
            PerformanceTracking.TaskStart(PerformanceTracking.Task.ReferenceHeadersCreation);
            headers = new References.Headers(id, compilation?.Namespaces ?? ImmutableArray <QsNamespace> .Empty);
            PerformanceTracking.TaskEnd(PerformanceTracking.Task.ReferenceHeadersCreation);
            return(true);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Compiles the given code.
        /// If the operations defined in this code are already defined
        /// in existing Snippets, those Snippets are skipped.
        /// If successful, this updates the AssemblyInfo
        /// with the new operations found in the Snippet.
        /// If errors are found during compilation, a `CompilationErrorsException` is triggered
        /// with the list of errors found.
        /// If successful, the list of snippets is updated to include those that were part of the
        /// compilation and it will return a new Snippet with the warnings and Q# elements
        /// reported by the compiler.
        /// </summary>
        public Snippet Compile(string code)
        {
            if (string.IsNullOrWhiteSpace(code))
            {
                throw new ArgumentNullException(nameof(code));
            }

            var duration = Stopwatch.StartNew();

            // We add exactly one line of boilerplate code at the beginning of each snippet,
            // so tell the logger to subtract one from all displayed line numbers.
            var logger = new QSharpLogger(Logger, lineNrOffset: -1);

            try
            {
                var snippets = SelectSnippetsToCompile(code).ToArray();
                var assembly = Compiler.BuildSnippets(snippets, _metadata.Value, logger, Path.Combine(Workspace.CacheFolder, "__snippets__.dll"));

                if (logger.HasErrors)
                {
                    throw new CompilationErrorsException(logger.Errors.ToArray());
                }

                foreach (var entry in Compiler.IdentifyOpenedNamespaces(code))
                {
                    Compiler.AutoOpenNamespaces[entry.Key] = entry.Value;
                }

                // populate the original snippet with the results of the compilation:
                Snippet populate(Snippet s) =>
                new Snippet()
                {
                    id       = string.IsNullOrWhiteSpace(s.id) ? Guid.NewGuid().ToString() : s.id,
                    code     = s.code,
                    warnings = logger.Logs
                               .Where(m => m.Source == CompilationUnitManager.GetFileId(s.Uri).Value)
                               .Select(logger.Format)
                               .ToArray(),
                    Elements = assembly?.SyntaxTree?
                               .SelectMany(ns => ns.Elements)
                               .Where(c => c.SourceFile() == CompilationUnitManager.GetFileId(s.Uri).Value)
                               .ToArray()
                };

                AssemblyInfo = assembly;
                Items        = snippets.Select(populate).ToArray();

                return(Items.Last());
            }
            finally
            {
                duration.Stop();
                var status   = logger.HasErrors ? "error" : "ok";
                var errorIds = logger.ErrorIds.ToArray();
                SnippetCompiled?.Invoke(this, new SnippetCompiledEventArgs(status, errorIds, Compiler.AutoOpenNamespaces.Keys.ToArray(), duration.Elapsed));
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Compiles the given code.
        /// If the operations defined in this code are already defined
        /// in existing Snippets, those Snippets are skipped.
        /// If successful, this updates the AssemblyInfo
        /// with the new operations found in the Snippet.
        /// If errors are found during compilation, a `CompilationErrorsException` is triggered
        /// with the list of errors found.
        /// If successful, the list of snippets is updated to include those that were part of the
        /// compilation and it will return a new Snippet with the warnings and Q# elements
        /// reported by the compiler.
        /// </summary>
        public Snippet Compile(string code)
        {
            if (string.IsNullOrWhiteSpace(code))
            {
                throw new ArgumentNullException(nameof(code));
            }

            var duration = Stopwatch.StartNew();
            var logger   = new QSharpLogger(Logger);

            try
            {
                var snippets = SelectSnippetsToCompile(code).ToArray();
                var assembly = Compiler.BuildSnippets(snippets, _metadata.Value, logger, Path.Combine(Workspace.CacheFolder, "__snippets__.dll"));

                if (logger.HasErrors)
                {
                    throw new CompilationErrorsException(logger.Errors.ToArray());
                }

                // populate the original snippet with the results of the compilation:
                Snippet populate(Snippet s) =>
                new Snippet()
                {
                    id       = string.IsNullOrWhiteSpace(s.id) ? Guid.NewGuid().ToString() : s.id,
                    code     = s.code,
                    warnings = logger.Logs
                               .Where(m => m.Source == CompilationUnitManager.GetFileId(s.Uri).Value)
                               .Select(logger.Format)
                               .ToArray(),
                    Elements = assembly?.SyntaxTree?
                               .SelectMany(ns => ns.Elements)
                               .Where(c => c.SourceFile() == CompilationUnitManager.GetFileId(s.Uri).Value)
                               .ToArray()
                };

                AssemblyInfo = assembly;
                Items        = snippets.Select(populate).ToArray();

                return(Items.Last());
            }
            finally
            {
                duration.Stop();
                var status   = logger.HasErrors ? "error" : "ok";
                var errorIds = logger.ErrorIds.ToArray();
                SnippetCompiled?.Invoke(this, new SnippetCompiledEventArgs(status, errorIds, duration.Elapsed));
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Returns the workspace edit that describes the changes to be done if the symbol at the given position - if any - is renamed to the given name.
        /// Returns null if no symbol exists at the specified position,
        /// or if some parameters are unspecified (null),
        /// or if the specified position is not a valid position within the file.
        /// </summary>
        public static WorkspaceEdit?Rename(this FileContentManager file, CompilationUnit compilation, Position position, string newName)
        {
            if (newName == null || file == null)
            {
                return(null);
            }
            var found = file.TryGetReferences(compilation, position, out var declLocation, out var locations);

            if (!found)
            {
                return(null);
            }

            if (declLocation != null)
            {
                locations = new[] { declLocation }.Concat(locations);
            }
            var changes = locations.ToLookup(loc => loc.Uri, loc => new TextEdit {
                Range = loc.Range, NewText = newName
            });

            return(new WorkspaceEdit
            {
                DocumentChanges = changes
                                  .Select(change => new TextDocumentEdit
                {
                    TextDocument = new VersionedTextDocumentIdentifier {
                        Uri = change.Key, Version = 1
                    },                                                                                        // setting version to null here won't work in VS Code ...
                    Edits = change.ToArray()
                })
                                  .ToArray(),

                Changes = changes.ToDictionary(
                    items => CompilationUnitManager.GetFileId(items.Key),
                    items => items.ToArray())
            });
        }