private void BackpatchUnreferencedDeclarations(string referencesFolder) { string declarationMapFile = Path.Combine(ProjectDestinationFolder, Constants.DeclarationMap + ".txt"); if (!File.Exists(declarationMapFile)) { return; } Log.Write("Backpatching unreferenced declarations in " + this.AssemblyId); var symbolIDToListOfLocationsMap = ReadSymbolIDToListOfLocationsMap(declarationMapFile); ProjectGenerator.GenerateRedirectFile( this.SolutionFinalizer.SolutionDestinationFolder, this.ProjectDestinationFolder, symbolIDToListOfLocationsMap.ToDictionary( kvp => kvp.Key, kvp => kvp.Value.Select(t => t.Item1.Replace('\\', '/')))); var locationsToPatch = new Dictionary <string, List <long> >(); GetLocationsToPatch(referencesFolder, locationsToPatch, symbolIDToListOfLocationsMap); Patch(locationsToPatch); }
public DocumentGenerator( ProjectGenerator projectGenerator, Document document) { this.projectGenerator = projectGenerator; this.Document = document; }
public void Generate(IEnumerable <string> typeScriptFiles) { if (typeScriptFiles == null || !typeScriptFiles.Any()) { return; } declarations = new List <string>(); references = new Dictionary <string, List <Reference> >(StringComparer.OrdinalIgnoreCase); SymbolIDToListOfLocationsMap = new Dictionary <string, List <Tuple <string, long> > >(); var list = new List <string>(); string libFile = null; foreach (var file in typeScriptFiles) { if (!alreadyProcessed.Contains(file)) { if (libFile == null && string.Equals(Path.GetFileName(file), "lib.d.ts", StringComparison.OrdinalIgnoreCase)) { libFile = file; } else { list.Add(file); } } } if (libFile == null) { libFile = Path.Combine(Common.Paths.BaseAppFolder, "TypeScriptSupport", "lib.d.ts"); } try { GenerateCore(list, libFile); } catch (Exception ex) { Log.Exception(ex, "Error when generating TypeScript files"); return; } ProjectGenerator.GenerateReferencesDataFilesToAssembly( Paths.SolutionDestinationFolder, Constants.TypeScriptFiles, references); declarations.Sort(); Serialization.WriteDeclaredSymbols( ProjectDestinationFolder, declarations); ProjectGenerator.GenerateSymbolIDToListOfDeclarationLocationsMap( ProjectDestinationFolder, SymbolIDToListOfLocationsMap); }
/// <returns>true if only part of the solution was processed and the method needs to be called again, false if all done</returns> public bool Generate(HashSet <string> processedAssemblyList = null, Folder <Project> solutionExplorerRoot = null) { if (solution == null) { // we failed to open the solution earlier; just return Log.Message("Solution is null: " + this.ProjectFilePath); return(false); } var allProjects = solution.Projects.ToArray(); if (allProjects.Length == 0) { Log.Exception("Solution " + this.ProjectFilePath + " has 0 projects - this is suspicious"); } var projectsToProcess = allProjects .Where(p => processedAssemblyList == null || !processedAssemblyList.Contains(p.AssemblyName)) .ToArray(); var currentBatch = projectsToProcess .ToArray(); foreach (var project in currentBatch) { try { CurrentAssemblyName = project.AssemblyName; var generator = new ProjectGenerator(this, project); generator.Generate().GetAwaiter().GetResult(); File.AppendAllText(Paths.ProcessedAssemblies, project.AssemblyName + Environment.NewLine, Encoding.UTF8); if (processedAssemblyList != null) { processedAssemblyList.Add(project.AssemblyName); } } finally { CurrentAssemblyName = null; } } new TypeScriptSupport().Generate(typeScriptFiles, SolutionDestinationFolder); if (currentBatch.Length > 1) { AddProjectsToSolutionExplorer( solutionExplorerRoot, currentBatch); } return(currentBatch.Length < projectsToProcess.Length); }
private string ProcessPropertyName( string lineText, int lineNumber, int startPositionOnLine, string text, bool isRootProject, bool isUsage) { var propertyName = text.Trim(); var leadingTriviaWidth = text.IndexOf(propertyName, StringComparison.Ordinal); var trailingTriviaWidth = text.Length - propertyName.Length - leadingTriviaWidth; if (propertyName.IndexOfAny(complexCharsInProperties) != -1) { return(Markup.HtmlEscape(text)); } if (propertyName.IndexOfAny(Path.GetInvalidFileNameChars()) != -1) { Log.Exception(string.Format("Invalid property name {0} in project {1}", propertyName, this.sourceXmlFilePath)); return(Markup.HtmlEscape(text)); } var href = "/" + Constants.MSBuildPropertiesAssembly + "/" + Constants.ReferencesFileName + "/" + propertyName + ".html"; text = string.Format( "{2}<a href=\"{1}\" target=\"n\" class=\"msbuildlink\">{0}</a>{3}", propertyName, href, text.Substring(0, leadingTriviaWidth), text.Substring(text.Length - trailingTriviaWidth)); ProjectGenerator.AddReference( destinationHtmlFilePath, lineText, startPositionOnLine, propertyName.Length, lineNumber, isRootProject ? ProjectGenerator.AssemblyName : Constants.MSBuildFiles, Constants.MSBuildPropertiesAssembly, null, propertyName, isUsage ? ReferenceKind.MSBuildPropertyUsage : ReferenceKind.MSBuildPropertyAssignment); return(text); }
private string ProcessItemName( string lineText, int lineNumber, int startPositionOnLine, string text, bool isRootProject, bool isUsage) { var itemName = text.Trim(); var leadingTriviaWidth = text.IndexOf(itemName); var trailingTriviaWidth = text.Length - itemName.Length - leadingTriviaWidth; if (itemName.IndexOfAny(complexCharsInProperties) != -1) { return(Markup.HtmlEscape(text)); } var href = "/" + Constants.MSBuildItemsAssembly + "/" + Constants.ReferencesFileName + "/" + itemName + ".html"; text = string.Format( "{2}<a href=\"{1}\" target=\"n\" class=\"msbuildlink\">{0}</a>{3}", itemName, href, text.Substring(0, leadingTriviaWidth), text.Substring(text.Length - trailingTriviaWidth)); ProjectGenerator.AddReference( destinationHtmlFilePath, lineText, startPositionOnLine, itemName.Length, lineNumber, isRootProject ? ProjectGenerator.AssemblyName : Constants.MSBuildFiles, Constants.MSBuildItemsAssembly, null, itemName, isUsage ? ReferenceKind.MSBuildItemUsage : ReferenceKind.MSBuildItemAssignment); return(text); }
private string ProcessTaskName( string lineText, int lineNumber, int startPositionOnLine, string text, string taskName, bool isRootProject, bool isUsage) { var trimmedText = text.Trim(); var leadingTriviaWidth = text.IndexOf(trimmedText, StringComparison.Ordinal); var trailingTriviaWidth = text.Length - trimmedText.Length - leadingTriviaWidth; var href = "/" + Constants.MSBuildTasksAssembly + "/" + Constants.ReferencesFileName + "/" + taskName + ".html"; text = string.Format( "{2}<a href=\"{1}\" target=\"n\" class=\"msbuildlink\">{0}</a>{3}", trimmedText, href, text.Substring(0, leadingTriviaWidth), text.Substring(text.Length - trailingTriviaWidth)); ProjectGenerator.AddReference( destinationHtmlFilePath, lineText, startPositionOnLine, trimmedText.Length, lineNumber, isRootProject ? ProjectGenerator.AssemblyName : Constants.MSBuildFiles, Constants.MSBuildTasksAssembly, null, taskName, isUsage ? ReferenceKind.MSBuildTaskUsage : ReferenceKind.MSBuildTaskDeclaration); return(text); }
public XamlSupport(ProjectGenerator projectGenerator) { this.projectGenerator = projectGenerator; }
private void GenerateRange( StringBuilder sb, ClassifiedRange range, string destinationFilePath, Dictionary <string, int> localSymbolIdMap) { var html = range.text; html = Markup.HtmlEscape(html); var localRelativePath = destinationFilePath.Substring( Path.Combine( Paths.SolutionDestinationFolder, Constants.TypeScriptFiles).Length + 1); localRelativePath = localRelativePath.Substring(0, localRelativePath.Length - ".html".Length); string classAttributeValue = GetSpanClass(range.classification); HtmlElementInfo hyperlinkInfo = GenerateLinks(range, destinationFilePath, localSymbolIdMap); if (hyperlinkInfo == null) { if (classAttributeValue == null) { sb.Append(html); return; } if (classAttributeValue == "k") { sb.Append("<b>").Append(html).Append("</b>"); return; } } var elementName = "span"; if (hyperlinkInfo != null) { elementName = hyperlinkInfo.Name; } sb.Append("<").Append(elementName); bool overridingClassAttributeSpecified = false; if (hyperlinkInfo != null) { foreach (var attribute in hyperlinkInfo.Attributes) { const string typeScriptFilesR = "/TypeScriptFiles/R/"; if (attribute.Key == "href" && attribute.Value.StartsWith(typeScriptFilesR, StringComparison.Ordinal)) { var streamPosition = sb.Length + 7 + typeScriptFilesR.Length; // exact offset into <a href="HERE ProjectGenerator.AddDeclaredSymbolToRedirectMap( SymbolIDToListOfLocationsMap, attribute.Value.Substring(typeScriptFilesR.Length, 16), localRelativePath, streamPosition); } AddAttribute(sb, attribute.Key, attribute.Value); if (attribute.Key == "class") { overridingClassAttributeSpecified = true; } } } if (!overridingClassAttributeSpecified) { AddAttribute(sb, "class", classAttributeValue); } sb.Append('>'); sb.Append(html); sb.Append("</").Append(elementName).Append(">"); }
private static void GenerateLooseFilesProject(string projectName, string solutionDestinationPath) { var projectGenerator = new ProjectGenerator(projectName, solutionDestinationPath); projectGenerator.GenerateNonProjectFolder(); }
/// <returns>true if only part of the solution was processed and the method needs to be called again, false if all done</returns> public bool Generate(HashSet<string> processedAssemblyList = null, Folder<Project> solutionExplorerRoot = null) { if (solution == null) { // we failed to open the solution earlier; just return Log.Message("Solution is null: " + this.ProjectFilePath); return false; } var allProjects = solution.Projects.ToArray(); if (allProjects.Length == 0) { Log.Exception("Solution " + this.ProjectFilePath + " has 0 projects - this is suspicious"); } var projectsToProcess = allProjects .Where(p => processedAssemblyList == null || !processedAssemblyList.Contains(p.AssemblyName)) .ToArray(); var currentBatch = projectsToProcess .ToArray(); foreach (var project in currentBatch) { try { CurrentAssemblyName = project.AssemblyName; var generator = new ProjectGenerator(this, project); generator.Generate().GetAwaiter().GetResult(); File.AppendAllText(Paths.ProcessedAssemblies, project.AssemblyName + Environment.NewLine, Encoding.UTF8); if (processedAssemblyList != null) { processedAssemblyList.Add(project.AssemblyName); } } finally { CurrentAssemblyName = null; } } new TypeScriptSupport().Generate(typeScriptFiles, SolutionDestinationFolder); if (currentBatch.Length > 1) { AddProjectsToSolutionExplorer( solutionExplorerRoot, currentBatch); } return currentBatch.Length < projectsToProcess.Length; }
public XmlSupport(ProjectGenerator generator) { ProjectGenerator = generator; }
public MSBuildSupport(ProjectGenerator projectGenerator) { this.projectGenerator = projectGenerator; }
public MSBuildSupport(ProjectGenerator projectGenerator) : base(projectGenerator) { }
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); } } }
private string ProcessAttributeValue(ClassifiedRange range, string text, bool isRootProject) { var node = range.Node; var attributeSyntax = node.GetParent(2) as XmlAttributeSyntax; if (attributeSyntax != null) { var parentElement = attributeSyntax.ParentElement; if (parentElement?.Name == "Output" && (attributeSyntax.Name == "ItemName" || attributeSyntax.Name == "PropertyName") && !text.Contains("%")) { if (attributeSyntax.Name == "ItemName") { return(ProcessItemName( range.LineText, range.LineNumber + 1, range.Column, text, isRootProject, isUsage: false)); } else { return(ProcessPropertyName( range.LineText, range.LineNumber + 1, range.Column, text, isRootProject, isUsage: false)); } } if (parentElement?.Name == "Target") { if (attributeSyntax.Name == "Name") { return(ProcessTargetName( range.LineText, range.LineNumber + 1, range.Column, text, isRootProject, isUsage: false)); } if (attributeSyntax.Name == "DependsOnTargets" || attributeSyntax.Name == "BeforeTargets" || attributeSyntax.Name == "AfterTargets") { return(ProcessExpressions(range, text, isRootProject, ProcessSemicolonSeparatedList)); } } if (parentElement?.Name == "CallTarget" && attributeSyntax.Name == "Targets") { return(ProcessExpressions(range, text, isRootProject, ProcessSemicolonSeparatedList)); } if (parentElement?.Name == "UsingTask" && attributeSyntax.Name == "TaskName") { var taskName = attributeSyntax.Value; var assemblyFileAttribute = parentElement.Attributes.FirstOrDefault(a => a.Name == "AssemblyFile"); var assemblyNameAttribute = parentElement.Attributes.FirstOrDefault(a => a.Name == "AssemblyName"); string assemblyName = null; if (assemblyFileAttribute != null && !string.IsNullOrWhiteSpace(assemblyFileAttribute.Value)) { var assemblyFilePath = assemblyFileAttribute.Value; assemblyFilePath = project.ExpandString(assemblyFilePath); assemblyName = Path.GetFileNameWithoutExtension(assemblyFilePath); } else if (assemblyNameAttribute != null && !string.IsNullOrWhiteSpace(assemblyNameAttribute.Value)) { assemblyName = assemblyNameAttribute.Value; assemblyName = project.ExpandString(assemblyName); int comma = assemblyName.IndexOf(','); if (comma > -1) { assemblyName = assemblyName.Substring(0, comma); } } if (assemblyName != null) { var symbolId = SymbolIdService.GetId("T:" + taskName); ProjectGenerator.AddReference( destinationHtmlFilePath, range.LineText, range.Column, taskName.Length, range.LineNumber, isRootProject ? ProjectGenerator.AssemblyName : Constants.MSBuildFiles, assemblyName, null, symbolId, ReferenceKind.Instantiation); var url = string.Format("/{0}/A.html#{1}", assemblyName, symbolId); var result = string.Format("<a href=\"{0}\" class=\"msbuildlink\">{1}</a>", url, text); return(result); } } } return(ProcessExpressions(range, text, isRootProject)); }