private void PerformScanBackground( ) { var token = _cancellationTokenSource.Token; SolutionBindContainer?sbc = null; try { //const int max = 100; //for (var cc = 0; cc <= max; cc++) //{ // if (token.IsCancellationRequested) // { // return; // } // Thread.Sleep(100); // Progress = ((float)cc) / max; //} if (_buildStatusContainer.BuildIsInProgress) { _outputPane !.OutputStringThreadSafe($"Dpdt scanning is cancelled due to build/cleanup is in progress{Environment.NewLine}"); return; } _outputPane !.OutputStringThreadSafe($"Dpdt scanning is started{Environment.NewLine}"); var componentModel = (IComponentModel)Package.GetGlobalService(typeof(SComponentModel)); var workspace = (Workspace)componentModel.GetService <VisualStudioWorkspace>(); if (workspace == null) { return; } if (!workspace.CurrentSolution.Projects.Any()) { return; } sbc = new SolutionBindContainer(); var index = -1; var projectCount = workspace.CurrentSolution.Projects.Count(); foreach (var project in workspace.CurrentSolution.Projects) { Progress = ((float)(++index)) / projectCount; if (token.IsCancellationRequested) { _outputPane !.OutputStringThreadSafe($" Dpdt scanning is cancelled{Environment.NewLine}"); break; } if (_buildStatusContainer.BuildIsInProgress) { _outputPane !.OutputStringThreadSafe($" Dpdt scanning is cancelled due to build/cleanup is in progress{Environment.NewLine}"); break; } if (project == null) { continue; } if (!project.SupportsCompilation) { continue; } if (project.Language != "C#") { continue; } var letsgo = false; foreach (var reference in project.AnalyzerReferences) { //surrogate marker for nuget Dpdt.Injector has installed to the project if (reference.Display == "DpdtInject.Generator") { letsgo = true; break; } } if (!letsgo) { _outputPane !.OutputStringThreadSafe($" {project.Name}: Project skipped due to absense of Dpdt package installed{Environment.NewLine}"); continue; } var swt = Stopwatch.StartNew(); Compilation?compilation = null; ThreadHelper.JoinableTaskFactory.Run( async() => { try { compilation = await project.GetCompilationAsync(token); } catch (OperationCanceledException ope) { //ok } catch (Exception excp) { LogVS(excp); } }); //first check for cancellation... if (token.IsCancellationRequested) { _outputPane !.OutputStringThreadSafe($" Dpdt scanning is cancelled{Environment.NewLine}"); break; } //..next for compilation errors, because both will result with compilation == null if (compilation == null) { continue; } _outputPane !.OutputStringThreadSafe($" {project.Name}: compilation taken {swt.Elapsed}{Environment.NewLine}"); var diag = compilation.GetDiagnostics(); var errors = diag.Where(j => j.Severity == DiagnosticSeverity.Error).ToList(); if (errors.Count > 0) { var errorMessage = string.Join( Environment.NewLine, errors.Select(j => j.ToString()) ); //DpdtPackage.ShowMessageBox( // "Error has been found", // errorMessage // ); _outputPane !.OutputStringThreadSafe($" {project.Name}: compilation error {Environment.NewLine}"); _outputPane !.OutputStringThreadSafe(" " + errorMessage); _outputPane !.OutputStringThreadSafe(Environment.NewLine); //do not skip this project analysis, it may be partially fine //continue; } swt.Restart(); var meta = new BuiltinMeta(); if (!meta.TryExtract(compilation, out var projectXml)) { continue; } sbc.Append(projectXml !); _outputPane !.OutputStringThreadSafe($" {project.Name}: Binding extraction taken {swt.Elapsed}{Environment.NewLine}"); _outputPane !.OutputStringThreadSafe($" {project.Name}: Found {projectXml.TotalBindingCount} binding{Environment.NewLine}"); if (token.IsCancellationRequested) { _outputPane !.OutputStringThreadSafe($" Dpdt scanning is cancelled{Environment.NewLine}"); break; } } } catch (Exception excp) { LogVS(excp); _outputPane !.OutputStringThreadSafe($" Dpdt scanning failed: {excp.Message}{Environment.NewLine}"); _outputPane !.OutputStringThreadSafe($" Dpdt scanning failed: {excp.StackTrace}{Environment.NewLine}"); } finally { if (sbc != null) { this.SolutionBindContainer = sbc; } _outputPane !.OutputStringThreadSafe($"Dpdt scanning is finished{Environment.NewLine}"); // CodeLenses usually only live as long as the document is open so we just refresh all the connected ones. //they will show actual status CodeLensConnectionHandler.RefreshAllCodeLensDataPointsAsync() .FileAndForget(nameof(PerformScanBackground)) ; BindingListViewModel.RefreshAction?.Invoke(); Progress = 1f; IsFinished = true; } }
private void DoGenerateXml( ITypeInfoContainer typeInfoContainer, IReadOnlyList <ClusterMethodBindings> clusterMethodBindings ) { if (typeInfoContainer is null) { throw new ArgumentNullException(nameof(typeInfoContainer)); } if (clusterMethodBindings is null) { throw new ArgumentNullException(nameof(clusterMethodBindings)); } #region create xml representation var clusterXmls = new List <ClusterBindContainerXml>(); foreach (var clusterMethodBinding in clusterMethodBindings) { var clusterType = clusterMethodBinding.ClusterType; var clusterTypeXml = clusterType.ToXml(); var methodBindXmls = new List <MethodBindContainerXml>(); foreach (var methodBinding in clusterMethodBinding.MethodBindings) { var methodDeclaration = methodBinding.Item1; var methodDeclarationXml = new MethodDeclarationInfoXml( methodDeclaration.ToXml(), methodDeclaration.Identifier.Text ); var methodBindXml = new MethodBindContainerXml( clusterTypeXml, methodDeclarationXml, methodBinding.Item2.ConvertAll( bc => new BindingXml( bc.UniqueUnstableIdentifier.ToString(), bc.TargetRepresentation, bc.BindFromTypes.ConvertAll(s => s.ToXml()).ToArray(), bc.BindToType.ToXml(), bc.ConstructorArguments.ToXml(), bc.Scope.ToString(), (int)bc.Scope, bc.IsConditional, bc.IsConventional, bc.ExpressionNode.ToXml() ) ).ToArray() ); methodBindXmls.Add(methodBindXml); } var clusterXml = new ClusterBindContainerXml( clusterTypeXml, methodBindXmls.ToArray() ); clusterXmls.Add(clusterXml); } var projectXml = new ProjectBindContainerXml( clusterXmls.ToArray() ); #endregion var meta = new BuiltinMeta(); meta.Store( typeInfoContainer, projectXml ); }