object IPreviewPaneService.GetPreviewPane(DiagnosticData diagnostic, string language, string projectType, IList<object> previewContent) { var title = diagnostic?.Message; if (string.IsNullOrWhiteSpace(title)) { if (previewContent == null) { // Bail out in cases where there is nothing to put in the header section // of the preview pane and no preview content (i.e. no diff view) either. return null; } return new PreviewPane( severityIcon: null, id: null, title: null, description: null, helpLink: null, helpLinkToolTipText: null, previewContent: previewContent, logIdVerbatimInTelemetry: false); } var helpLinkToolTipText = string.Empty; Uri helpLink = GetHelpLink(diagnostic, language, projectType, out helpLinkToolTipText); return new PreviewPane( severityIcon: GetSeverityIconForDiagnostic(diagnostic), id: diagnostic.Id, title: title, description: diagnostic.Description.ToString(CultureInfo.CurrentUICulture), helpLink: helpLink, helpLinkToolTipText: helpLinkToolTipText, previewContent: previewContent, logIdVerbatimInTelemetry: diagnostic.CustomTags.Contains(WellKnownDiagnosticTags.Telemetry)); }
private static Image GetSeverityIconForDiagnostic(DiagnosticData diagnostic) { ImageMoniker? moniker = null; switch (diagnostic.Severity) { case DiagnosticSeverity.Error: moniker = KnownMonikers.StatusError; break; case DiagnosticSeverity.Warning: moniker = KnownMonikers.StatusWarning; break; case DiagnosticSeverity.Info: moniker = KnownMonikers.StatusInformation; break; case DiagnosticSeverity.Hidden: moniker = KnownMonikers.StatusHidden; break; } if (moniker.HasValue) { return new CrispImage { Moniker = moniker.Value }; } return null; }
public static Uri CreateBingQueryUri(DiagnosticData diagnostic) { var errorCode = diagnostic.Id; var title = diagnostic.ENUMessageForBingSearch; diagnostic.Workspace.GetLanguageAndProjectType(diagnostic.ProjectId, out var language, out var projectType); return CreateBingQueryUri(errorCode, title, language, projectType); }
public object GetPreviewPane(DiagnosticData diagnostic, string language, string projectType, IReadOnlyList<object> previewContents) { var contents = previewContents ?? SpecializedCollections.EmptyEnumerable<object>(); foreach (var content in contents.OfType<IDisposable>()) { content.Dispose(); } // test only mock object return new Grid(); }
private void RaiseAnalyzerChangedWarning(ProjectId projectId, string analyzerPath) { string message = string.Format(ServicesVSResources.WRN_AnalyzerChangedMessage, analyzerPath); DiagnosticData data = new DiagnosticData( IDEDiagnosticIds.AnalyzerChangedId, ServicesVSResources.ErrorCategory, message, ServicesVSResources.WRN_AnalyzerChangedMessage, severity: DiagnosticSeverity.Warning, isEnabledByDefault: true, warningLevel: 0, workspace: _workspace, projectId: projectId, title: ServicesVSResources.WRN_AnalyzerChangedTitle); _updateSource.UpdateDiagnosticsForProject(projectId, Tuple.Create(s_analyzerChangedErrorId, analyzerPath), SpecializedCollections.SingletonEnumerable(data)); }
private static Uri GetHelpLink(DiagnosticData diagnostic, string language, string projectType, out string helpLinkToolTipText) { var isBing = false; helpLinkToolTipText = string.Empty; if (!BrowserHelper.TryGetUri(diagnostic.HelpLink, out var helpLink)) { // We use the ENU version of the message for bing search. helpLink = BrowserHelper.CreateBingQueryUri(diagnostic.Id, diagnostic.ENUMessageForBingSearch, language, projectType); isBing = true; } // We make sure not to use Uri.AbsoluteUri for the url displayed in the tooltip so that the url displayed in the tooltip stays human readable. if (helpLink != null) { helpLinkToolTipText = string.Format(ServicesVSResources.Get_help_for_0_1_2_3, diagnostic.Id, isBing ? ServicesVSResources.from_Bing : null, Environment.NewLine, helpLink); } return helpLink; }
public void ReportAnalyzerDiagnostic(DiagnosticAnalyzer analyzer, DiagnosticData diagnosticData, Project project) { if (diagnosticData.Workspace != this.Workspace) { return; } bool raiseDiagnosticsUpdated = true; var dxs = ImmutableInterlocked.AddOrUpdate(ref _analyzerHostDiagnosticsMap, analyzer, ImmutableHashSet.Create(diagnosticData), (a, existing) => { var newDiags = existing.Add(diagnosticData); raiseDiagnosticsUpdated = newDiags.Count > existing.Count; return newDiags; }); if (raiseDiagnosticsUpdated) { RaiseDiagnosticsUpdated(MakeCreatedArgs(analyzer, dxs, project)); } }
private DiagnosticData UpdatePosition(DiagnosticData diagnostic, SyntaxTree tree, int delta) { var start = Math.Min(Math.Max(diagnostic.TextSpan.Start + delta, 0), tree.Length); var newSpan = new TextSpan(start, start >= tree.Length ? 0 : diagnostic.TextSpan.Length); var mappedLineInfo = tree.GetMappedLineSpan(newSpan); var originalLineInfo = tree.GetLineSpan(newSpan); return new DiagnosticData( diagnostic.Id, diagnostic.Category, diagnostic.Message, diagnostic.MessageFormat, diagnostic.Severity, diagnostic.DefaultSeverity, diagnostic.IsEnabledByDefault, diagnostic.WarningLevel, diagnostic.CustomTags, diagnostic.Workspace, diagnostic.ProjectId, diagnostic.DocumentId, newSpan, mappedFilePath: mappedLineInfo.HasMappedPath ? mappedLineInfo.Path : null, mappedStartLine: mappedLineInfo.StartLinePosition.Line, mappedStartColumn: mappedLineInfo.StartLinePosition.Character, mappedEndLine: mappedLineInfo.EndLinePosition.Line, mappedEndColumn: mappedLineInfo.EndLinePosition.Character, originalFilePath: originalLineInfo.Path, originalStartLine: originalLineInfo.StartLinePosition.Line, originalStartColumn: originalLineInfo.StartLinePosition.Character, originalEndLine: originalLineInfo.EndLinePosition.Line, originalEndColumn: originalLineInfo.EndLinePosition.Character, description: diagnostic.Description, helpLink: diagnostic.HelpLink); }
protected void UpdateRuleSetError(IRuleSetFile ruleSetFile) { if (this.HostDiagnosticUpdateSource == null) { return; } if (ruleSetFile == null || ruleSetFile.GetException() == null) { this.HostDiagnosticUpdateSource.ClearDiagnosticsForProject(this.Id, RuleSetErrorId); } else { string message = string.Format(ServicesVSResources.ERR_CantReadRulesetFileMessage, ruleSetFile.FilePath, ruleSetFile.GetException().Message); var data = new DiagnosticData( id: IDEDiagnosticIds.ErrorReadingRulesetId, category: ServicesVSResources.ErrorCategory, message: message, enuMessageForBingSearch: ServicesVSResources.ERR_CantReadRulesetFileMessage, severity: DiagnosticSeverity.Error, isEnabledByDefault: true, warningLevel: 0, workspace: this.Workspace, projectId: this.Id, title: ServicesVSResources.ERR_CantReadRulesetFileTitle); this.HostDiagnosticUpdateSource.UpdateDiagnosticsForProject(this.Id, RuleSetErrorId, SpecializedCollections.SingletonEnumerable(data)); } }
protected void UpdateRuleSetError(IRuleSetFile ruleSetFile) { if (this.HostDiagnosticUpdateSource == null) { return; } if (ruleSetFile == null || ruleSetFile.GetException() == null) { this.HostDiagnosticUpdateSource.ClearDiagnosticsForProject(this.Id, RuleSetErrorId); } else { string id = ServicesVSResources.ERR_CantReadRulesetFileId; string category = ServicesVSResources.ErrorCategory; string message = string.Format(ServicesVSResources.ERR_CantReadRulesetFileMessage, ruleSetFile.FilePath, ruleSetFile.GetException().Message); DiagnosticData data = new DiagnosticData(id, category, message, ServicesVSResources.ERR_CantReadRulesetFileMessage, DiagnosticSeverity.Error, DiagnosticSeverity.Error, true, 0, ImmutableArray<string>.Empty, this.Workspace, this.Id); this.HostDiagnosticUpdateSource.UpdateDiagnosticsForProject(this.Id, RuleSetErrorId, SpecializedCollections.SingletonEnumerable(data)); } }
private async Task<bool> ContainsAnyFix(Document document, DiagnosticData diagnostic, CancellationToken cancellationToken) { // TODO: We don't return true here if the only available fixes are suppressions. // This is to avoid the problem where lightbulb would show up for every green warning // squiggle in the editor thereby diluting the promise of the light bulb from // "I have a fix" to "I have some action". This is temporary until the editor team exposes // some mechanism (e.g. a faded out lightbulb) that would allow us to say "I have an action // but not a fix". ImmutableArray<CodeFixProvider> workspaceFixers = ImmutableArray<CodeFixProvider>.Empty; List<CodeFixProvider> projectFixers = null; Lazy<ImmutableDictionary<DiagnosticId, ImmutableArray<CodeFixProvider>>> fixerMap; bool hasAnySharedFixer = _workspaceFixersMap.TryGetValue(document.Project.Language, out fixerMap) && fixerMap.Value.TryGetValue(diagnostic.Id, out workspaceFixers); var hasAnyProjectFixer = GetProjectFixers(document.Project).TryGetValue(diagnostic.Id, out projectFixers); if (!hasAnySharedFixer && !hasAnyProjectFixer) { return false; } var allFixers = ImmutableArray<CodeFixProvider>.Empty; if (hasAnySharedFixer) { allFixers = workspaceFixers; } if (hasAnyProjectFixer) { allFixers = allFixers.AddRange(projectFixers); } var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var dx = diagnostic.ToDiagnostic(tree); var extensionManager = document.Project.Solution.Workspace.Services.GetService<IExtensionManager>(); var fixes = new List<CodeFix>(); var context = new CodeFixContext(document, dx, // TODO: Can we share code between similar lambdas that we pass to this API in BatchFixAllProvider.cs, CodeFixService.cs and CodeRefactoringService.cs? (a, d) => { // Serialize access for thread safety - we don't know what thread the fix provider will call this delegate from. lock (fixes) { fixes.Add(new CodeFix(a, d)); } }, verifyArguments: false, cancellationToken: cancellationToken); // we do have fixer. now let's see whether it actually can fix it foreach (var fixer in allFixers) { await extensionManager.PerformActionAsync(fixer, () => fixer.RegisterCodeFixesAsync(context) ?? SpecializedTasks.EmptyTask).ConfigureAwait(false); if (!fixes.Any()) { continue; } return true; } return false; }
private async Task<bool> ContainsAnyFix(Document document, DiagnosticData diagnostic, bool considerSuppressionFixes, CancellationToken cancellationToken) { ImmutableArray<CodeFixProvider> workspaceFixers = ImmutableArray<CodeFixProvider>.Empty; List<CodeFixProvider> projectFixers = null; Lazy<ImmutableDictionary<DiagnosticId, ImmutableArray<CodeFixProvider>>> fixerMap; bool hasAnySharedFixer = _workspaceFixersMap.TryGetValue(document.Project.Language, out fixerMap) && fixerMap.Value.TryGetValue(diagnostic.Id, out workspaceFixers); var hasAnyProjectFixer = GetProjectFixers(document.Project).TryGetValue(diagnostic.Id, out projectFixers); // TODO (https://github.com/dotnet/roslyn/issues/4932): Don't restrict CodeFixes in Interactive if (hasAnySharedFixer && document.Project.Solution.Workspace.Kind == WorkspaceKind.Interactive) { workspaceFixers = workspaceFixers.WhereAsArray(IsInteractiveCodeFixProvider); hasAnySharedFixer = workspaceFixers.Any(); } Lazy<ISuppressionFixProvider> lazySuppressionProvider = null; var hasSuppressionFixer = considerSuppressionFixes && _suppressionProvidersMap.TryGetValue(document.Project.Language, out lazySuppressionProvider) && lazySuppressionProvider.Value != null; if (!hasAnySharedFixer && !hasAnyProjectFixer && !hasSuppressionFixer) { return false; } var allFixers = ImmutableArray<CodeFixProvider>.Empty; if (hasAnySharedFixer) { allFixers = workspaceFixers; } if (hasAnyProjectFixer) { allFixers = allFixers.AddRange(projectFixers); } var dx = await diagnostic.ToDiagnosticAsync(document.Project, cancellationToken).ConfigureAwait(false); if (hasSuppressionFixer && lazySuppressionProvider.Value.CanBeSuppressedOrUnsuppressed(dx)) { return true; } var fixes = new List<CodeFix>(); var context = new CodeFixContext(document, dx, // TODO: Can we share code between similar lambdas that we pass to this API in BatchFixAllProvider.cs, CodeFixService.cs and CodeRefactoringService.cs? (action, applicableDiagnostics) => { // Serialize access for thread safety - we don't know what thread the fix provider will call this delegate from. lock (fixes) { fixes.Add(new CodeFix(document.Project, action, applicableDiagnostics)); } }, verifyArguments: false, cancellationToken: cancellationToken); var extensionManager = document.Project.Solution.Workspace.Services.GetService<IExtensionManager>(); // we do have fixer. now let's see whether it actually can fix it foreach (var fixer in allFixers) { await extensionManager.PerformActionAsync(fixer, () => fixer.RegisterCodeFixesAsync(context) ?? SpecializedTasks.EmptyTask).ConfigureAwait(false); if (!fixes.Any()) { continue; } return true; } return false; }
public static bool IsNotConfigurableDiagnostic(DiagnosticData diagnostic) { return HasCustomTag(diagnostic.CustomTags, WellKnownDiagnosticTags.NotConfigurable); }
private void RaiseAnalyzerChangedWarning(ProjectId projectId, string analyzerPath) { string id = ServicesVSResources.WRN_AnalyzerChangedId; string category = ServicesVSResources.ErrorCategory; string message = string.Format(ServicesVSResources.WRN_AnalyzerChangedMessage, analyzerPath); DiagnosticData data = new DiagnosticData( id, category, message, ServicesVSResources.WRN_AnalyzerChangedMessage, severity: DiagnosticSeverity.Warning, defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true, warningLevel: 0, customTags: ImmutableArray<string>.Empty, workspace: _workspace, projectId: projectId); _updateSource.UpdateDiagnosticsForProject(projectId, Tuple.Create(s_analyzerChangedErrorId, analyzerPath), SpecializedCollections.SingletonEnumerable(data)); }
protected internal override ImmutableArray <DiagnosticDataLocation> GetLocationsToTag(DiagnosticData diagnosticData) { // If there are 'unnecessary' locations specified in the property bag, use those instead of the main diagnostic location. if (TryGetUnnecessaryLocationIndices(diagnosticData, out var unnecessaryIndices)) { using var _ = PooledObjects.ArrayBuilder <DiagnosticDataLocation> .GetInstance(out var locationsToTag); foreach (var index in GetLocationIndices(unnecessaryIndices)) { locationsToTag.Add(diagnosticData.AdditionalLocations[index]); } return(locationsToTag.ToImmutable()); } // Default to the base implementation for the diagnostic data return(base.GetLocationsToTag(diagnosticData));
/// <summary> /// Check whether given <see cref="DiagnosticData"/> belong to compiler diagnostic analyzer /// </summary> public bool IsCompilerDiagnostic(string language, DiagnosticData diagnostic) { var map = GetHostDiagnosticAnalyzersPerReference(language); HashSet<string> idMap; DiagnosticAnalyzer compilerAnalyzer; if (_compilerDiagnosticAnalyzerMap.TryGetValue(language, out compilerAnalyzer) && _compilerDiagnosticAnalyzerDescriptorMap.TryGetValue(compilerAnalyzer, out idMap) && idMap.Contains(diagnostic.Id)) { return true; } return false; }
public bool IsSynthesizedNonRoslynDiagnostic(DiagnosticData diagnostic) { var tags = diagnostic.CustomTags; return tags != null && tags.Contains(SynthesizedFxCopDiagnostic); }
public static bool IsSynthesizedExternalSourceDiagnostic(DiagnosticData diagnostic) { return HasCustomTag(diagnostic.CustomTags, SynthesizedExternalSourceDiagnosticTag); }
private DiagnosticData CreateDiagnostic(ProjectId projectId, AnalyzerDependencyConflict conflict) { string message = string.Format( ServicesVSResources.WRN_AnalyzerDependencyConflictMessage, conflict.AnalyzerFilePath1, conflict.AnalyzerFilePath2, conflict.Identity.ToString()); DiagnosticData data = new DiagnosticData( IDEDiagnosticIds.AnalyzerDependencyConflictId, FeaturesResources.ErrorCategory, message, ServicesVSResources.WRN_AnalyzerDependencyConflictMessage, severity: DiagnosticSeverity.Warning, defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true, warningLevel: 0, customTags: ImmutableArray<string>.Empty, properties: ImmutableDictionary<string, string>.Empty, workspace: _workspace, projectId: projectId, title: ServicesVSResources.WRN_AnalyzerDependencyConflictTitle); return data; }
public DiagnosticTaskItem(DiagnosticData diagnostic) { _diagnostic = diagnostic; }
protected internal override ITagSpan <ClassificationTag> CreateTagSpan(Workspace workspace, bool isLiveUpdate, SnapshotSpan span, DiagnosticData data) => new TagSpan <ClassificationTag>(span, _classificationTag);
private static async Task VerifyTextSpanAsync(string code, int startLine, int startColumn, int endLine, int endColumn, TextSpan span) { using (var workspace = new TestWorkspace(TestExportProvider.ExportProviderWithCSharpAndVisualBasic)) { var document = workspace.CurrentSolution.AddProject("TestProject", "TestProject", LanguageNames.CSharp).AddDocument("TestDocument", code); var data = new DiagnosticData( "test1", "Test", "test1 message", "test1 message format", DiagnosticSeverity.Info, false, 1, workspace, document.Project.Id, new DiagnosticDataLocation(document.Id, null, "originalFile1", startLine, startColumn, endLine, endColumn)); var text = await document.GetTextAsync(); var actual = data.GetExistingOrCalculatedTextSpan(text); Assert.Equal(span, actual); } }
/// <summary> /// Gets <see cref="DiagnosticData"/> objects for selected error list entries. /// For remove suppression, the method also returns selected external source diagnostics. /// </summary> public async Task<ImmutableArray<DiagnosticData>> GetSelectedItemsAsync(bool isAddSuppression, CancellationToken cancellationToken) { var builder = ImmutableArray.CreateBuilder<DiagnosticData>(); Dictionary<string, Project> projectNameToProjectMapOpt = null; Dictionary<Project, ImmutableDictionary<string, Document>> filePathToDocumentMapOpt = null; foreach (var entryHandle in _tableControl.SelectedEntries) { cancellationToken.ThrowIfCancellationRequested(); DiagnosticData diagnosticData = null; int index; var roslynSnapshot = GetEntriesSnapshot(entryHandle, out index); if (roslynSnapshot != null) { diagnosticData = roslynSnapshot.GetItem(index)?.Primary; } else if (!isAddSuppression) { // For suppression removal, we also need to handle FxCop entries. bool isSuppressedEntry; if (!IsNonRoslynEntrySupportingSuppressionState(entryHandle, out isSuppressedEntry) || !isSuppressedEntry) { continue; } string errorCode = null, category = null, message = null, filePath = null, projectName = null; int line = -1; // FxCop only supports line, not column. DiagnosticDataLocation location = null; if (entryHandle.TryGetValue(StandardTableColumnDefinitions.ErrorCode, out errorCode) && !string.IsNullOrEmpty(errorCode) && entryHandle.TryGetValue(StandardTableColumnDefinitions.ErrorCategory, out category) && !string.IsNullOrEmpty(category) && entryHandle.TryGetValue(StandardTableColumnDefinitions.Text, out message) && !string.IsNullOrEmpty(message) && entryHandle.TryGetValue(StandardTableColumnDefinitions.ProjectName, out projectName) && !string.IsNullOrEmpty(projectName)) { if (projectNameToProjectMapOpt == null) { projectNameToProjectMapOpt = new Dictionary<string, Project>(); foreach (var p in _workspace.CurrentSolution.Projects) { projectNameToProjectMapOpt[p.Name] = p; } } cancellationToken.ThrowIfCancellationRequested(); Project project; if (!projectNameToProjectMapOpt.TryGetValue(projectName, out project)) { // bail out continue; } Document document = null; var hasLocation = (entryHandle.TryGetValue(StandardTableColumnDefinitions.DocumentName, out filePath) && !string.IsNullOrEmpty(filePath)) && (entryHandle.TryGetValue(StandardTableColumnDefinitions.Line, out line) && line >= 0); if (hasLocation) { if (string.IsNullOrEmpty(filePath) || line < 0) { // bail out continue; } ImmutableDictionary<string, Document> filePathMap; filePathToDocumentMapOpt = filePathToDocumentMapOpt ?? new Dictionary<Project, ImmutableDictionary<string, Document>>(); if (!filePathToDocumentMapOpt.TryGetValue(project, out filePathMap)) { filePathMap = await GetFilePathToDocumentMapAsync(project, cancellationToken).ConfigureAwait(false); filePathToDocumentMapOpt[project] = filePathMap; } if (!filePathMap.TryGetValue(filePath, out document)) { // bail out continue; } var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var linePosition = new LinePosition(line, 0); var linePositionSpan = new LinePositionSpan(start: linePosition, end: linePosition); var textSpan = (await tree.GetTextAsync(cancellationToken).ConfigureAwait(false)).Lines.GetTextSpan(linePositionSpan); location = new DiagnosticDataLocation(document.Id, textSpan, filePath, originalStartLine: linePosition.Line, originalStartColumn: linePosition.Character, originalEndLine: linePosition.Line, originalEndColumn: linePosition.Character); } Contract.ThrowIfNull(project); Contract.ThrowIfFalse((document != null) == (location != null)); // Create a diagnostic with correct values for fields we care about: id, category, message, isSuppressed, location // and default values for the rest of the fields (not used by suppression fixer). diagnosticData = new DiagnosticData( id: errorCode, category: category, message: message, enuMessageForBingSearch: message, severity: DiagnosticSeverity.Warning, defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true, warningLevel: 1, isSuppressed: isSuppressedEntry, title: message, location: location, customTags: SuppressionHelpers.SynthesizedExternalSourceDiagnosticCustomTags, properties: ImmutableDictionary<string, string>.Empty, workspace: _workspace, projectId: project.Id); } } if (IsEntryWithConfigurableSuppressionState(diagnosticData)) { builder.Add(diagnosticData); } } return builder.ToImmutable(); }
/// <summary> /// Returns true if an entry's suppression state can be modified. /// </summary> /// <returns></returns> private static bool IsEntryWithConfigurableSuppressionState(DiagnosticData entry) { // Compiler diagnostics with severity 'Error' are not configurable. // Additionally, diagnostics coming from build are from a snapshot (as opposed to live diagnostics) and cannot be configured. return entry != null && !SuppressionHelpers.IsNotConfigurableDiagnostic(entry) && !entry.IsBuildDiagnostic(); }
public bool IsCompilerDiagnostic(string language, DiagnosticData diagnostic) { return(_hostAnalyzerManager.IsCompilerDiagnostic(language, diagnostic)); }
public static bool IsCompilerDiagnostic(DiagnosticData diagnostic) { return HasCustomTag(diagnostic.CustomTags, WellKnownDiagnosticTags.Compiler); }
public async Task AnalyzeSyntaxAsync(Document document, InvocationReasons reasons, CancellationToken cancellationToken) { // right now, there is no way to observe diagnostics for closed file. if (!_workspace.IsDocumentOpen(document.Id) || !_workspace.Options.GetOption(InternalRuntimeDiagnosticOptions.Syntax)) { return; } var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var diagnostics = tree.GetDiagnostics(cancellationToken); Contract.Requires(document.Project.Solution.Workspace == _workspace); var diagnosticData = diagnostics == null ? ImmutableArray <DiagnosticData> .Empty : diagnostics.Select(d => DiagnosticData.Create(document, d)).ToImmutableArrayOrEmpty(); _service.RaiseDiagnosticsUpdated( DiagnosticsUpdatedArgs.DiagnosticsCreated(new DefaultUpdateArgsId(_workspace.Kind, Syntax, document.Id), _workspace, document.Project.Solution, document.Project.Id, document.Id, diagnosticData)); }
public static bool TryCreate(DiagnosticDescriptor descriptor, string[] messageArguments, ProjectId projectId, Workspace workspace, out DiagnosticData diagnosticData, CancellationToken cancellationToken = default(CancellationToken)) { diagnosticData = null; var project = workspace.CurrentSolution.GetProject(projectId); if (project == null) { return false; } var diagnostic = Diagnostic.Create(descriptor, Location.None, messageArguments); if (project.SupportsCompilation) { // Get diagnostic with effective severity. // Additionally, if the diagnostic was suppressed by a source suppression, effectiveDiagnostics will have a diagnostic with IsSuppressed = true. var compilation = project.GetCompilationAsync(cancellationToken).WaitAndGetResult(cancellationToken); var effectiveDiagnostics = CompilationWithAnalyzers.GetEffectiveDiagnostics(SpecializedCollections.SingletonEnumerable(diagnostic), compilation); if (effectiveDiagnostics == null || effectiveDiagnostics.IsEmpty()) { // Rule is disabled by compilation options. return false; } diagnostic = effectiveDiagnostics.Single(); } diagnosticData = diagnostic.ToDiagnosticData(project); return true; }
internal void CreateDiagnosticAndFireEvents(Location location) { var document = _workspace.CurrentSolution.Projects.Single().Documents.Single(); _diagnostic = DiagnosticData.Create(document, Diagnostic.Create(DiagnosticId, "MockCategory", "MockMessage", DiagnosticSeverity.Error, DiagnosticSeverity.Error, isEnabledByDefault: true, warningLevel: 0, location: location)); DiagnosticsUpdated?.Invoke(this, DiagnosticsUpdatedArgs.DiagnosticsCreated( this, _workspace, _workspace.CurrentSolution, GetProjectId(), GetDocumentId(), ImmutableArray.Create(_diagnostic))); }
private void OnAnalyzerLoadError(object sender, AnalyzerLoadFailureEventArgs e) { string id; string message; string messageFormat; switch (e.ErrorCode) { case AnalyzerLoadFailureEventArgs.FailureErrorCode.UnableToLoadAnalyzer: id = _language == LanguageNames.CSharp ? WRN_UnableToLoadAnalyzerIdCS : WRN_UnableToLoadAnalyzerIdVB; messageFormat = ServicesVSResources.WRN_UnableToLoadAnalyzer; message = string.Format(ServicesVSResources.WRN_UnableToLoadAnalyzer, _fullPath, e.Exception.Message); break; case AnalyzerLoadFailureEventArgs.FailureErrorCode.UnableToCreateAnalyzer: id = _language == LanguageNames.CSharp ? WRN_AnalyzerCannotBeCreatedIdCS : WRN_AnalyzerCannotBeCreatedIdVB; messageFormat = ServicesVSResources.WRN_AnalyzerCannotBeCreated; message = string.Format(ServicesVSResources.WRN_AnalyzerCannotBeCreated, e.TypeName, _fullPath, e.Exception.Message); break; case AnalyzerLoadFailureEventArgs.FailureErrorCode.NoAnalyzers: id = _language == LanguageNames.CSharp ? WRN_NoAnalyzerInAssemblyIdCS : WRN_NoAnalyzerInAssemblyIdVB; messageFormat = ServicesVSResources.WRN_NoAnalyzerInAssembly; message = string.Format(ServicesVSResources.WRN_NoAnalyzerInAssembly, _fullPath); break; case AnalyzerLoadFailureEventArgs.FailureErrorCode.None: default: return; } DiagnosticData data = new DiagnosticData( id, ServicesVSResources.ErrorCategory, message, messageFormat, severity: DiagnosticSeverity.Warning, defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true, warningLevel: 0, customTags: ImmutableArray<string>.Empty, workspace: _workspace, projectId: _projectId); _analyzerLoadErrors = _analyzerLoadErrors ?? new List<DiagnosticData>(); _analyzerLoadErrors.Add(data); _hostDiagnosticUpdateSource.UpdateDiagnosticsForProject(_projectId, this, _analyzerLoadErrors); }
public TestDiagnosticUpdateSource(bool support, DiagnosticData[] diagnosticData) { _support = support; _diagnosticData = (diagnosticData ?? Array.Empty<DiagnosticData>()).ToImmutableArray(); }
/// <summary> /// Returns true if an entry's suppression state can be modified. /// </summary> /// <returns></returns> private static bool IsEntryWithConfigurableSuppressionState(DiagnosticData entry) { return entry != null && !SuppressionHelpers.IsNotConfigurableDiagnostic(entry); }
private DiagnosticData CreateDiagnostic(ProjectId projectId, MissingAnalyzerDependency missingDependency) { string id = ServicesVSResources.WRN_MissingAnalyzerReferenceId; string category = ServicesVSResources.ErrorCategory; string message = string.Format( ServicesVSResources.WRN_MissingAnalyzerReferenceMessage, missingDependency.AnalyzerPath, missingDependency.DependencyIdentity.ToString()); DiagnosticData data = new DiagnosticData( id, category, message, ServicesVSResources.WRN_MissingAnalyzerReferenceMessage, severity: DiagnosticSeverity.Warning, defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true, warningLevel: 0, customTags: ImmutableArray<string>.Empty, properties: ImmutableDictionary<string, string>.Empty, workspace: _workspace, projectId: projectId); return data; }
private static void AssertDiagnostics(DiagnosticData item1, DiagnosticData item2) { Assert.Equal(item1.Id, item2.Id); Assert.Equal(item1.Category, item2.Category); Assert.Equal(item1.Message, item2.Message); Assert.Equal(item1.ENUMessageForBingSearch, item2.ENUMessageForBingSearch); Assert.Equal(item1.Severity, item2.Severity); Assert.Equal(item1.IsEnabledByDefault, item2.IsEnabledByDefault); Assert.Equal(item1.WarningLevel, item2.WarningLevel); Assert.Equal(item1.DefaultSeverity, item2.DefaultSeverity); Assert.Equal(item1.CustomTags.Count, item2.CustomTags.Count); for (var j = 0; j < item1.CustomTags.Count; j++) { Assert.Equal(item1.CustomTags[j], item2.CustomTags[j]); } Assert.Equal(item1.Properties.Count, item2.Properties.Count); Assert.True(item1.Properties.SetEquals(item2.Properties)); Assert.Equal(item1.Workspace, item2.Workspace); Assert.Equal(item1.ProjectId, item2.ProjectId); Assert.Equal(item1.DocumentId, item2.DocumentId); Assert.Equal(item1.HasTextSpan, item2.HasTextSpan); if (item1.HasTextSpan) { Assert.Equal(item1.TextSpan, item2.TextSpan); } Assert.Equal(item1.DataLocation?.MappedFilePath, item2.DataLocation?.MappedFilePath); Assert.Equal(item1.DataLocation?.MappedStartLine, item2.DataLocation?.MappedStartLine); Assert.Equal(item1.DataLocation?.MappedStartColumn, item2.DataLocation?.MappedStartColumn); Assert.Equal(item1.DataLocation?.MappedEndLine, item2.DataLocation?.MappedEndLine); Assert.Equal(item1.DataLocation?.MappedEndColumn, item2.DataLocation?.MappedEndColumn); Assert.Equal(item1.DataLocation?.OriginalFilePath, item2.DataLocation?.OriginalFilePath); Assert.Equal(item1.DataLocation?.OriginalStartLine, item2.DataLocation?.OriginalStartLine); Assert.Equal(item1.DataLocation?.OriginalStartColumn, item2.DataLocation?.OriginalStartColumn); Assert.Equal(item1.DataLocation?.OriginalEndLine, item2.DataLocation?.OriginalEndLine); Assert.Equal(item1.DataLocation?.OriginalEndColumn, item2.DataLocation?.OriginalEndColumn); Assert.Equal(item1.Description, item2.Description); Assert.Equal(item1.HelpLink, item2.HelpLink); }
public async Task <IEnumerable <DiagnosticData> > ComputeDiagnosticsAsync(DiagnosticAnalyzer analyzer, CancellationToken cancellationToken) { Contract.ThrowIfFalse(AnalysisScope.Analyzers.Contains(analyzer)); var textDocument = AnalysisScope.TextDocument; var span = AnalysisScope.Span; var kind = AnalysisScope.Kind; var document = textDocument as Document; RoslynDebug.Assert(document != null || kind == AnalysisKind.Syntax, "We only support syntactic analysis for non-source documents"); var loadDiagnostic = await textDocument.State.GetLoadDiagnosticAsync(cancellationToken).ConfigureAwait(false); if (analyzer == FileContentLoadAnalyzer.Instance) { return(loadDiagnostic != null? SpecializedCollections.SingletonEnumerable(DiagnosticData.Create(loadDiagnostic, textDocument)) : SpecializedCollections.EmptyEnumerable <DiagnosticData>()); } if (loadDiagnostic != null) { return(SpecializedCollections.EmptyEnumerable <DiagnosticData>()); } ImmutableArray <Diagnostic> diagnostics; if (analyzer is DocumentDiagnosticAnalyzer documentAnalyzer) { if (document == null) { return(SpecializedCollections.EmptyEnumerable <DiagnosticData>()); } diagnostics = await AnalyzerHelper.ComputeDocumentDiagnosticAnalyzerDiagnosticsAsync( documentAnalyzer, document, kind, _compilationWithAnalyzers?.Compilation, cancellationToken).ConfigureAwait(false); return(diagnostics.ConvertToLocalDiagnostics(textDocument, span)); } // quick optimization to reduce allocations. if (_compilationWithAnalyzers == null || !analyzer.SupportAnalysisKind(kind)) { if (kind == AnalysisKind.Syntax) { Logger.Log(FunctionId.Diagnostics_SyntaxDiagnostic, (r, d, a, k) => $"Driver: {r != null}, {d.Id}, {d.Project.Id}, {a}, {k}", _compilationWithAnalyzers, textDocument, analyzer, kind); } return(SpecializedCollections.EmptyEnumerable <DiagnosticData>()); } // if project is not loaded successfully then, we disable semantic errors for compiler analyzers var isCompilerAnalyzer = analyzer.IsCompilerAnalyzer(); if (kind != AnalysisKind.Syntax && isCompilerAnalyzer) { var isEnabled = await textDocument.Project.HasSuccessfullyLoadedAsync(cancellationToken).ConfigureAwait(false); Logger.Log(FunctionId.Diagnostics_SemanticDiagnostic, (a, d, e) => $"{a}, ({d.Id}, {d.Project.Id}), Enabled:{e}", analyzer, textDocument, isEnabled); if (!isEnabled) { return(SpecializedCollections.EmptyEnumerable <DiagnosticData>()); } } switch (kind) { case AnalysisKind.Syntax: if (document != null) { var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); if (tree == null) { return(SpecializedCollections.EmptyEnumerable <DiagnosticData>()); } diagnostics = await GetSyntaxDiagnosticsAsync(tree, analyzer, isCompilerAnalyzer, cancellationToken).ConfigureAwait(false); if (diagnostics.IsDefaultOrEmpty) { Logger.Log(FunctionId.Diagnostics_SyntaxDiagnostic, (d, a, t) => $"{d.Id}, {d.Project.Id}, {a}, {t.Length}", document, analyzer, tree); return(SpecializedCollections.EmptyEnumerable <DiagnosticData>()); } } else { // Currently, we only support analysis for additional documents. In future, we may support analyzer config documents. if (textDocument.Kind != TextDocumentKind.AdditionalDocument) { return(SpecializedCollections.EmptyEnumerable <DiagnosticData>()); } diagnostics = await GetAdditionalDocumentDiagnosticsAsync((AdditionalDocument)textDocument, analyzer, isCompilerAnalyzer, cancellationToken).ConfigureAwait(false); } break; case AnalysisKind.Semantic: var model = await document !.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (model == null) { return(SpecializedCollections.EmptyEnumerable <DiagnosticData>()); } diagnostics = await GetSemanticDiagnosticsAsync(model, analyzer, isCompilerAnalyzer, cancellationToken).ConfigureAwait(false); break; default: throw ExceptionUtilities.UnexpectedValue(kind); } if (diagnostics.IsEmpty) { return(SpecializedCollections.EmptyEnumerable <DiagnosticData>()); } var skippedAnalyzerInfo = textDocument.Project.GetSkippedAnalyzersInfo(_analyzerInfoCache); if (skippedAnalyzerInfo.FilteredDiagnosticIdsForAnalyzers.TryGetValue(analyzer, out var filteredIds)) { diagnostics = diagnostics.Filter(filteredIds); } Debug.Assert(diagnostics.Length == CompilationWithAnalyzers.GetEffectiveDiagnostics(diagnostics, _compilationWithAnalyzers.Compilation).Count()); return(diagnostics.ConvertToLocalDiagnostics(textDocument, span)); }