public async Task Generate()
        {
            if (Configuration.CalculateRoslynSemantics)
            {
                this.Text = await Document.GetTextAsync();

                this.Root = await Document.GetSyntaxRootAsync();

                this.SemanticModel = await Document.GetSemanticModelAsync();

                this.SemanticFactsService = WorkspaceHacks.GetSemanticFactsService(this.Document);
                this.SyntaxFactsService   = WorkspaceHacks.GetSyntaxFactsService(this.Document);

                var semanticFactsServiceType = SemanticFactsService.GetType();
                var isWrittenTo = semanticFactsServiceType.GetMethod("IsWrittenTo");
                this.isWrittenToDelegate = (Func <SemanticModel, SyntaxNode, CancellationToken, bool>)
                                           Delegate.CreateDelegate(typeof(Func <SemanticModel, SyntaxNode, CancellationToken, bool>), SemanticFactsService, isWrittenTo);

                var syntaxFactsServiceType = SyntaxFactsService.GetType();
                var getBindableParent      = syntaxFactsServiceType.GetMethod("GetBindableParent");
                this.getBindableParentDelegate = (Func <SyntaxToken, SyntaxNode>)
                                                 Delegate.CreateDelegate(typeof(Func <SyntaxToken, SyntaxNode>), SyntaxFactsService, getBindableParent);

                this.DeclaredSymbols = new HashSet <ISymbol>();

                Interlocked.Increment(ref projectGenerator.DocumentCount);
                Interlocked.Add(ref projectGenerator.LinesOfCode, Text.Lines.Count);
                Interlocked.Add(ref projectGenerator.BytesOfCode, Text.Length);
            }

            CalculateDocumentDestinationPath();
            CalculateRelativePathToRoot();

            // add the file itself as a "declared symbol", so that clicking on document in search
            // results redirects to the document
            ProjectGenerator.AddDeclaredSymbolToRedirectMap(
                this.projectGenerator.SymbolIDToListOfLocationsMap,
                SymbolIdService.GetId(this.Document),
                documentRelativeFilePathWithoutHtmlExtension,
                0);

            if (File.Exists(documentDestinationFilePath))
            {
                // someone already generated this file, likely a shared linked file from elsewhere
                return;
            }

            this.classifier = new Classification();

            Log.Write(documentDestinationFilePath);

            try
            {
                var directoryName = Path.GetDirectoryName(documentDestinationFilePath);
                var sanitized     = Paths.SanitizeFolder(directoryName);
                if (directoryName != sanitized)
                {
                    Log.Exception("Illegal characters in path: " + directoryName + " Project: " + this.projectGenerator.AssemblyName);
                }

                if (Configuration.CreateFoldersOnDisk)
                {
                    Directory.CreateDirectory(directoryName);
                }
            }
            catch (PathTooLongException)
            {
                // there's one case where a path is too long - we don't care enough about it
                return;
            }

            if (Configuration.WriteDocumentsToDisk)
            {
                using (var streamWriter = new StreamWriter(
                           documentDestinationFilePath,
                           append: false,
                           encoding: Encoding.UTF8))
                {
                    await GenerateHtml(streamWriter);
                }
            }
            else
            {
                using (var memoryStream = new MemoryStream())
                    using (var streamWriter = new StreamWriter(memoryStream))
                    {
                        await GeneratePre(streamWriter);
                    }
            }
        }
Пример #2
0
        public static Solution LoadMetadataAsSourceSolution(string assemblyFilePath)
        {
            try
            {
                using (Disposable.Timing("Metadata as source: " + assemblyFilePath))
                {
                    var assemblyName = Path.GetFileNameWithoutExtension(assemblyFilePath);

                    var solution          = new AdhocWorkspace(WorkspaceHacks.Pack).CurrentSolution;
                    var workspace         = solution.Workspace;
                    var project           = solution.AddProject(assemblyName, assemblyName, LanguageNames.CSharp);
                    var metadataReference = CreateReferenceFromFilePath(assemblyFilePath);

                    var referencePaths = MetadataReading.GetReferencePaths(metadataReference);
                    foreach (var referencePath in referencePaths)
                    {
                        project = project.AddMetadataReference(CreateReferenceFromFilePath(referencePath));
                    }

                    var             projectWithReference   = project.AddMetadataReference(metadataReference);
                    var             compilation            = projectWithReference.GetCompilationAsync().ConfigureAwait(false).GetAwaiter().GetResult();
                    var             assemblyOrModuleSymbol = compilation.GetAssemblyOrModuleSymbol(metadataReference);
                    IAssemblySymbol assemblySymbol         = assemblyOrModuleSymbol as IAssemblySymbol;
                    IModuleSymbol   moduleSymbol           = assemblyOrModuleSymbol as IModuleSymbol;
                    if (moduleSymbol != null && assemblySymbol == null)
                    {
                        assemblySymbol = moduleSymbol.ContainingAssembly;
                    }

                    var assemblyAttributes         = MetadataReading.GetAssemblyAttributes(assemblySymbol);
                    var assemblyAttributesFileText = MetadataReading.GetAssemblyAttributesFileText(
                        LanguageNames.CSharp,
                        assemblyFilePath.Substring(0, 3),
                        assemblyAttributes);

                    INamespaceSymbol namespaceSymbol = null;
                    if (assemblySymbol != null)
                    {
                        namespaceSymbol = assemblySymbol.GlobalNamespace;
                    }
                    else if (moduleSymbol != null)
                    {
                        namespaceSymbol = moduleSymbol.GlobalNamespace;
                    }

                    var types = GetTypes(namespaceSymbol)
                                .OfType <INamedTypeSymbol>()
                                .Where(t => t.CanBeReferencedByName);

                    var tempDocument            = projectWithReference.AddDocument("temp", SourceText.From(""), null);
                    var metadataAsSourceService = WorkspaceHacks.GetMetadataAsSourceService(tempDocument);
                    if (addSourceToAsync == null)
                    {
                        addSourceToAsync = ReflectAddSourceToAsync(metadataAsSourceService);
                    }

                    var texts = new Dictionary <INamedTypeSymbol, string>();

                    Parallel.ForEach(
                        types,
                        new ParallelOptions
                    {
                        MaxDegreeOfParallelism = Environment.ProcessorCount
                    },
                        type =>
                    {
                        try
                        {
                            string text = "";

                            if (Configuration.GenerateMetadataAsSourceBodies)
                            {
                                var document = addSourceToAsync(
                                    tempDocument,
                                    type,
                                    CancellationToken.None).Result;
                                text = document.GetTextAsync().Result.ToString();
                            }

                            lock (texts)
                            {
                                texts.Add(type, text);
                            }
                        }
                        catch (Exception ex)
                        {
                            Log.Exception(ex, "Error when adding a MAS document to texts: " + assemblyFilePath);
                        }
                    });

                    HashSet <string> existingFileNames = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

                    foreach (var kvp in texts)
                    {
                        var tempProject = AddDocument(project, kvp, existingFileNames);

                        // tempProject can be null if the document was in an unutterable namespace
                        // we want to skip such documents
                        if (tempProject != null)
                        {
                            project = tempProject;
                        }
                    }

                    project = project.AddDocument(
                        "AssemblyAttributes.cs",
                        assemblyAttributesFileText).Project;

                    solution = project.Solution;
                    return(solution);
                }
            }
            catch (Exception ex)
            {
                Log.Exception(ex, "Failed to run metadata as source for: " + assemblyFilePath);
                return(null);
            }
        }