/// <see cref="AddIncludesRecursively_ManualParsing(IncludeGraph, string, string, IEnumerable{string})"/> public static void AddIncludesRecursively_ManualParsing(this IncludeGraph graph, string filename, IEnumerable <string> includeDirectories, IEnumerable <string> nonParseDirectories) { var graphItem = graph.CreateOrGetItem(filename, out bool isNewGraphItem); if (!isNewGraphItem) { return; } ParseIncludesRecursively(graph, graphItem, File.ReadAllText(filename), includeDirectories, nonParseDirectories); }
private static void ResetPendingCompilationInfo() { string reasonForFailure; VSUtils.VCUtils.SetCompilerSetting_ShowIncludes(documentBeingCompiled.ProjectItem?.ContainingProject, showIncludeSettingBefore, out reasonForFailure); onCompleted = null; documentBeingCompiled = null; graphBeingExtended = null; VSUtils.GetDTE().Events.BuildEvents.OnBuildDone -= OnBuildConfigFinished; }
private static async Task ResetPendingCompilationInfo() { await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); try { VSUtils.VCUtils.SetCompilerSetting_ShowIncludes(documentBeingCompiled.ProjectItem?.ContainingProject, showIncludeSettingBefore); } catch (VCQueryFailure) { } onCompleted = null; documentBeingCompiled = null; graphBeingExtended = null; VSUtils.GetDTE().Events.BuildEvents.OnBuildDone -= OnBuildConfigFinished; }
static public DGMLGraph ToDGMLGraph(this IncludeGraph graph, bool folderGrouping, bool expandGroups) { var uniqueTransitiveChildrenMap = FindUniqueChildren(graph.GraphItems); DGMLGraph dgmlGraph = new DGMLGraph(); foreach (GraphItem node in graph.GraphItems) { dgmlGraph.Nodes.Add(new DGMLGraph.Node { Id = node.AbsoluteFilename, Label = node.FormattedName, Background = null, NumIncludes = node.Includes.Count, NumUniqueTransitiveChildren = uniqueTransitiveChildrenMap[node].Count, }); foreach (Include include in node.Includes) { dgmlGraph.Links.Add(new DGMLGraph.Link { Source = node.AbsoluteFilename, Target = include.IncludedFile?.AbsoluteFilename ?? null }); } } if (folderGrouping) { // Reusing a ViewModel datastructure is arguably a bit ugly, but it matches exactly what we want. // TODO: Consider splitting functionallity out. var folderGroupingRoot = new FolderIncludeTreeViewItem_Root(graph.GraphItems, null); foreach (var child in folderGroupingRoot.Children) { AddFolderGroupingRecursive(dgmlGraph, child, null, expandGroups); } } return(dgmlGraph); }
private static void ParseIncludesRecursively(IncludeGraph graph, IncludeGraph.GraphItem parentItem, string fileContent, IEnumerable <string> includeDirectories, IEnumerable <string> nonParseDirectories) { string currentDirectory = Path.GetDirectoryName(parentItem.AbsoluteFilename); var includeDirectoriesPlusLocal = includeDirectories.Prepend(currentDirectory); var includes = Formatter.IncludeLineInfo.ParseIncludes(fileContent, Formatter.ParseOptions.KeepOnlyValidIncludes); foreach (var includeLine in includes) { // Try to resolve the include (may fail) string resolvedInclude = includeLine.TryResolveInclude(includeDirectoriesPlusLocal, out bool successfullyResolved); // Create a link to the file in any case now even if resolving was unsuccessful. var includedFile = graph.CreateOrGetItem_AbsoluteNormalizedPath(resolvedInclude, out bool isNewGraphItem); if (successfullyResolved && isNewGraphItem && !nonParseDirectories.Any(x => resolvedInclude.StartsWith(x))) { bool successReadingFile = true; try { fileContent = File.ReadAllText(resolvedInclude); } catch { successReadingFile = false; Output.Instance.WriteLine("Unable to read included file: '{0}'", resolvedInclude); } if (successReadingFile) { ParseIncludesRecursively(graph, includedFile, fileContent, includeDirectories, nonParseDirectories); } } parentItem.Includes.Add(new IncludeGraph.Include { IncludeLine = includeLine, IncludedFile = includedFile }); } }
/// <summary> /// Parses a given source file using cl.exe with the /showIncludes option and adds the output to the original graph. /// </summary> /// <remarks> /// If this is the first file, the graph is necessarily a tree after this operation. /// </remarks> /// <returns>true if successful, false otherwise.</returns> public static async Task <bool> AddIncludesRecursively_ShowIncludesCompilation(this IncludeGraph graph, Document document, OnCompleteCallback onCompleted) { var canPerformShowIncludeCompilation = await CanPerformShowIncludeCompilation(document); if (!canPerformShowIncludeCompilation.Result) { await Output.Instance.ErrorMsg(canPerformShowIncludeCompilation.Reason); return(false); } try { var dte = VSUtils.GetDTE(); if (dte == null) { await Output.Instance.ErrorMsg("Failed to acquire dte object."); return(false); } try { await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); showIncludeSettingBefore = VSUtils.VCUtils.GetCompilerSetting_ShowIncludes(document.ProjectItem?.ContainingProject); VSUtils.VCUtils.SetCompilerSetting_ShowIncludes(document.ProjectItem?.ContainingProject, true); } catch (VCQueryFailure queryFailure) { await Output.Instance.ErrorMsg("Can't compile with show includes: {0}.", queryFailure.Message); return(false); } // Only after we're through all early out error cases, set static compilation infos. dte.Events.BuildEvents.OnBuildDone += OnBuildConfigFinished; CompilationBasedGraphParser.onCompleted = onCompleted; CompilationBasedGraphParser.documentBeingCompiled = document; CompilationBasedGraphParser.graphBeingExtended = graph; // Even with having the config changed and having compile force==true, we still need to make a dummy change in order to enforce recompilation of this file. { document.Activate(); var documentTextView = VSUtils.GetCurrentTextViewHost(); var textBuffer = documentTextView.TextView.TextBuffer; using (var edit = textBuffer.CreateEdit()) { edit.Insert(0, " "); edit.Apply(); } using (var edit = textBuffer.CreateEdit()) { edit.Replace(new Microsoft.VisualStudio.Text.Span(0, 1), ""); edit.Apply(); } } await VSUtils.VCUtils.CompileSingleFile(document); } catch (Exception e) { await ResetPendingCompilationInfo(); await Output.Instance.ErrorMsg("Compilation of file '{0}' with /showIncludes failed: {1}.", document.FullName, e); return(false); } return(true); }
/// <summary> /// Parses a given source file using cl.exe with the /showIncludes option and adds the output to the original graph. /// </summary> /// <remarks> /// If this is the first file, the graph is necessarily a tree after this operation. /// </remarks> /// <returns>true if successful, false otherwise.</returns> public static bool AddIncludesRecursively_ShowIncludesCompilation(this IncludeGraph graph, Document document, OnCompleteCallback onCompleted) { if (!CanPerformShowIncludeCompilation(document, out string reasonForFailure)) { Output.Instance.ErrorMsg(reasonForFailure); return(false); } try { var dte = VSUtils.GetDTE(); if (dte == null) { Output.Instance.ErrorMsg("Failed to acquire dte object."); return(false); } { bool?setting = VSUtils.VCUtils.GetCompilerSetting_ShowIncludes(document.ProjectItem?.ContainingProject, out reasonForFailure); if (!setting.HasValue) { Output.Instance.ErrorMsg("Can't compile with show includes: {0}.", reasonForFailure); return(false); } else { showIncludeSettingBefore = setting.Value; } VSUtils.VCUtils.SetCompilerSetting_ShowIncludes(document.ProjectItem?.ContainingProject, true, out reasonForFailure); if (!string.IsNullOrEmpty(reasonForFailure)) { Output.Instance.ErrorMsg("Can't compile with show includes: {0}.", reasonForFailure); return(false); } } // Only after we're through all early out error cases, set static compilation infos. dte.Events.BuildEvents.OnBuildDone += OnBuildConfigFinished; CompilationBasedGraphParser.onCompleted = onCompleted; CompilationBasedGraphParser.documentBeingCompiled = document; CompilationBasedGraphParser.graphBeingExtended = graph; // Even with having the config changed and having compile force==true, we still need to make a dummy change in order to enforce recompilation of this file. { document.Activate(); var documentTextView = VSUtils.GetCurrentTextViewHost(); var textBuffer = documentTextView.TextView.TextBuffer; using (var edit = textBuffer.CreateEdit()) { edit.Insert(0, " "); edit.Apply(); } using (var edit = textBuffer.CreateEdit()) { edit.Replace(new Microsoft.VisualStudio.Text.Span(0, 1), ""); edit.Apply(); } } VSUtils.VCUtils.CompileSingleFile(document); } catch (Exception e) { ResetPendingCompilationInfo(); Output.Instance.ErrorMsg("Compilation of file '{0}' with /showIncludes failed: {1}.", document.FullName, e); return(false); } return(true); }