Exemplo n.º 1
0
        public async Task GenerateForCompilationAsync(Compilation compilation, string projectPath, HostLanguageServices languageServices, GeneratorOptions options)
        {
            var projectVertex = new Graph.LsifProject(kind: GetLanguageKind(compilation.Language), new Uri(projectPath), _idFactory);

            _lsifJsonWriter.Write(projectVertex);
            _lsifJsonWriter.Write(new Event(Event.EventKind.Begin, projectVertex.GetId(), _idFactory));

            var documentIds = new ConcurrentBag <Id <Graph.LsifDocument> >();

            // We create a ResultSetTracker to track all top-level symbols in the project. We don't want all writes to immediately go to
            // the JSON file -- we support parallel processing, so we'll accumulate them and then apply at once to avoid a lot
            // of contention on shared locks.
            var topLevelSymbolsWriter           = new BatchingLsifJsonWriter(_lsifJsonWriter);
            var topLevelSymbolsResultSetTracker = new SymbolHoldingResultSetTracker(topLevelSymbolsWriter, compilation, _idFactory);

            // Disable navigation hints in quick info as computing them both takes too long, and they're never
            // even emitted in the final lsif hover information.
            options = options with
            {
                SymbolDescriptionOptions = options.SymbolDescriptionOptions with
                {
                    QuickInfoOptions = options.SymbolDescriptionOptions.QuickInfoOptions with
                    {
                        IncludeNavigationHintsInQuickInfo = false
                    }
                }
            };

            var tasks = new List <Task>();

            foreach (var syntaxTree in compilation.SyntaxTrees)
            {
                tasks.Add(Task.Run(async() =>
                {
                    var semanticModel = compilation.GetSemanticModel(syntaxTree);

                    // We generate the document contents into an in-memory copy, and then write that out at once at the end. This
                    // allows us to collect everything and avoid a lot of fine-grained contention on the write to the single
                    // LSIF file. Because of the rule that vertices must be written before they're used by an edge, we'll flush any top-
                    // level symbol result sets made first, since the document contents will point to that. Parallel calls to CopyAndEmpty
                    // are allowed and might flush other unrelated stuff at the same time, but there's no harm -- the "causality" ordering
                    // is preserved.
                    var documentWriter = new BatchingLsifJsonWriter(_lsifJsonWriter);
                    var documentId     = await GenerateForDocumentAsync(semanticModel, languageServices, options, topLevelSymbolsResultSetTracker, documentWriter, _idFactory);
                    topLevelSymbolsWriter.FlushToUnderlyingAndEmpty();
                    documentWriter.FlushToUnderlyingAndEmpty();

                    documentIds.Add(documentId);
                }));
            }

            await Task.WhenAll(tasks);

            _lsifJsonWriter.Write(Edge.Create("contains", projectVertex.GetId(), documentIds.ToArray(), _idFactory));

            _lsifJsonWriter.Write(new Event(Event.EventKind.End, projectVertex.GetId(), _idFactory));
        }
Exemplo n.º 2
0
        public void GenerateForCompilation(Compilation compilation, string projectPath, HostLanguageServices languageServices, OptionSet options)
        {
            var projectVertex = new Graph.LsifProject(kind: GetLanguageKind(compilation.Language), new Uri(projectPath), _idFactory);

            _lsifJsonWriter.Write(projectVertex);
            _lsifJsonWriter.Write(new Event(Event.EventKind.Begin, projectVertex.GetId(), _idFactory));

            var documentIds = new ConcurrentBag <Id <Graph.LsifDocument> >();

            // We create a ResultSetTracker to track all top-level symbols in the project. We don't want all writes to immediately go to
            // the JSON file -- we support parallel processing, so we'll accumulate them and then apply at once to avoid a lot
            // of contention on shared locks.
            var topLevelSymbolsWriter           = new BatchingLsifJsonWriter(_lsifJsonWriter);
            var topLevelSymbolsResultSetTracker = new SymbolHoldingResultSetTracker(topLevelSymbolsWriter, compilation, _idFactory);

            Parallel.ForEach(compilation.SyntaxTrees, syntaxTree =>
            {
                var semanticModel = compilation.GetSemanticModel(syntaxTree);

                // We generate the document contents into an in-memory copy, and then write that out at once at the end. This
                // allows us to collect everything and avoid a lot of fine-grained contention on the write to the single
                // LSIF file. Becasue of the rule that vertices must be written before they're used by an edge, we'll flush any top-
                // level symbol result sets made first, since the document contents will point to that. Parallel calls to CopyAndEmpty
                // are allowed and might flush other unrelated stuff at the same time, but there's no harm -- the "causality" ordering
                // is preserved.
                var documentWriter = new BatchingLsifJsonWriter(_lsifJsonWriter);
                var documentId     = GenerateForDocument(semanticModel, languageServices, options, topLevelSymbolsResultSetTracker, documentWriter, _idFactory);
                topLevelSymbolsWriter.FlushToUnderlyingAndEmpty();
                documentWriter.FlushToUnderlyingAndEmpty();

                documentIds.Add(documentId);
            });

            _lsifJsonWriter.Write(Edge.Create("contains", projectVertex.GetId(), documentIds.ToArray(), _idFactory));

            _lsifJsonWriter.Write(new Event(Event.EventKind.End, projectVertex.GetId(), _idFactory));
        }