private static DiagnosticData CreateLiveDiagnostic(DiagnosticDescriptor descriptor, DiagnosticData diagnostic) { return new DiagnosticData( descriptor.Id, descriptor.Category, diagnostic.Message, descriptor.MessageFormat.ToString(DiagnosticData.USCultureInfo), diagnostic.Severity, descriptor.DefaultSeverity, descriptor.IsEnabledByDefault, diagnostic.WarningLevel, descriptor.CustomTags.ToImmutableArray(), diagnostic.Properties, diagnostic.Workspace, diagnostic.ProjectId, diagnostic.DocumentId, diagnostic.HasTextSpan ? diagnostic.TextSpan : (TextSpan?)null, diagnostic.MappedFilePath, diagnostic.MappedStartLine, diagnostic.MappedStartColumn, diagnostic.MappedEndLine, diagnostic.MappedEndColumn, diagnostic.OriginalFilePath, diagnostic.OriginalStartLine, diagnostic.OriginalStartColumn, diagnostic.OriginalEndLine, diagnostic.OriginalEndColumn, descriptor.Title.ToString(CultureInfo.CurrentUICulture), descriptor.Description.ToString(CultureInfo.CurrentUICulture), descriptor.HelpLinkUri); }
private DiagnosticData UpdatePosition(DiagnosticData diagnostic, SyntaxTree tree, int delta) { Debug.Assert(diagnostic.AdditionalLocations == null || diagnostic.AdditionalLocations.Count == 0); var newDiagnosticLocation = UpdateDiagnosticLocation(diagnostic.DataLocation, tree, delta); return new DiagnosticData( diagnostic.Id, diagnostic.Category, diagnostic.Message, diagnostic.ENUMessageForBingSearch, diagnostic.Severity, diagnostic.DefaultSeverity, diagnostic.IsEnabledByDefault, diagnostic.WarningLevel, diagnostic.CustomTags, diagnostic.Properties, diagnostic.Workspace, diagnostic.ProjectId, newDiagnosticLocation, additionalLocations: diagnostic.AdditionalLocations, description: diagnostic.Description, helpLink: diagnostic.HelpLink, isSuppressed: diagnostic.IsSuppressed); }
private static IEnumerable <DiagnosticData> GetDiagnosticData(Document document, SyntaxTree tree, TextSpan?span, IEnumerable <Diagnostic> diagnostics) { return(diagnostics != null?diagnostics.Where(dx => ShouldIncludeDiagnostic(dx, tree, span)).Select(d => DiagnosticData.Create(document, d)) : null); }
public void AddError(ProjectId key, DiagnosticData diagnostic) { AddError(_projectMap, key, diagnostic); }
internal static DiagnosticTableItem Create(Workspace workspace, DiagnosticData data) { GetProjectNameAndGuid(workspace, data.ProjectId, out var projectName, out var projectGuid); return(new DiagnosticTableItem(workspace, data, projectName, projectGuid, projectNames: Array.Empty <string>(), projectGuids: Array.Empty <Guid>())); }
public async ValueTask <ImmutableArray <Diagnostic> > GetDocumentDiagnosticsAsync(Document document, Document designTimeDocument, ActiveStatementSpanProvider activeStatementSpanProvider, CancellationToken cancellationToken) { var client = await RemoteHostClient.TryGetClientAsync(Workspace, cancellationToken).ConfigureAwait(false); if (client == null) { var diagnostics = await GetLocalService().GetDocumentDiagnosticsAsync(document, activeStatementSpanProvider, cancellationToken).ConfigureAwait(false); if (designTimeDocument != document) { diagnostics = diagnostics.SelectAsArray(diagnostic => RemapLocation(designTimeDocument, DiagnosticData.Create(diagnostic, document.Project))); } return(diagnostics); } var diagnosticData = await client.TryInvokeAsync <IRemoteEditAndContinueService, ImmutableArray <DiagnosticData> >( document.Project.Solution, (service, solutionInfo, callbackId, cancellationToken) => service.GetDocumentDiagnosticsAsync(solutionInfo, callbackId, document.Id, cancellationToken), callbackTarget : new ActiveStatementSpanProviderCallback(activeStatementSpanProvider), cancellationToken).ConfigureAwait(false); if (!diagnosticData.HasValue) { return(ImmutableArray <Diagnostic> .Empty); } var project = document.Project; using var _ = ArrayBuilder <Diagnostic> .GetInstance(out var result); foreach (var data in diagnosticData.Value) { Debug.Assert(data.DataLocation != null); Diagnostic diagnostic; // Workaround for solution crawler not supporting mapped locations to make Razor work. // We pretend the diagnostic is in the original document, but use the mapped line span. // Razor will ignore the column (which will be off because #line directives can't currently map columns) and only use the line number. if (designTimeDocument != document && data.DataLocation.IsMapped) { diagnostic = RemapLocation(designTimeDocument, data); } else { diagnostic = await data.ToDiagnosticAsync(document.Project, cancellationToken).ConfigureAwait(false); } result.Add(diagnostic); } return(result.ToImmutable()); }
public static bool IsNotConfigurableDiagnostic(DiagnosticData diagnostic) { return(HasCustomTag(diagnostic.CustomTags, WellKnownDiagnosticTags.NotConfigurable)); }
static bool IsDocumentDiagnostic(DiagnosticData d) => d.DataLocation != null && d.HasTextSpan;
public void ReportDiagnostics(Solution solution, ProjectId?projectId, IEnumerable <Diagnostic> diagnostics) { RoslynDebug.Assert(solution != null); var updateEvent = DiagnosticsUpdated; if (updateEvent == null) { return; } using var _1 = ArrayBuilder <DiagnosticData> .GetInstance(out var documentDiagnosticData); using var _2 = ArrayBuilder <DiagnosticData> .GetInstance(out var nonDocumentDiagnosticData); var workspace = solution.Workspace; var options = solution.Options; var project = (projectId != null) ? solution.GetProject(projectId) : null; foreach (var diagnostic in diagnostics) { var document = solution.GetDocument(diagnostic.Location.SourceTree); if (document != null) { documentDiagnosticData.Add(DiagnosticData.Create(diagnostic, document)); } else if (project != null) { nonDocumentDiagnosticData.Add(DiagnosticData.Create(diagnostic, project)); } else { nonDocumentDiagnosticData.Add(DiagnosticData.Create(diagnostic, options)); } } if (documentDiagnosticData.Count > 0) { foreach (var(documentId, diagnosticData) in documentDiagnosticData.ToDictionary(data => data.DocumentId)) { var diagnosticGroupId = (this, documentId, projectId); updateEvent(this, DiagnosticsUpdatedArgs.DiagnosticsCreated( diagnosticGroupId, workspace, solution, projectId, documentId: documentId, diagnostics: diagnosticData)); } } if (nonDocumentDiagnosticData.Count > 0) { var diagnosticGroupId = (this, projectId); updateEvent(this, DiagnosticsUpdatedArgs.DiagnosticsCreated( diagnosticGroupId, workspace, solution, projectId, documentId: null, diagnostics: nonDocumentDiagnosticData.ToImmutable())); } }
public async Task AnalyzeSyntaxAsync(Document document, CancellationToken cancellationToken) { // if closed file diagnostic is off and document is not opened, then don't do anything if (!CheckOptions(document)) { 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 MiscUpdateArgsId(document.Id), _workspace, document.Project.Solution, document.Project.Id, document.Id, diagnosticData)); }
protected override IErrorTag CreateTag(Workspace workspace, DiagnosticData diagnostic) => new ErrorTag( PredefinedErrorTypeNames.HintedSuggestion, CreateToolTipContent(workspace, diagnostic));
protected internal override bool IncludeDiagnostic(DiagnosticData diagnostic) => diagnostic.Severity == DiagnosticSeverity.Info;
private void AddError <T>(Dictionary <T, HashSet <DiagnosticData> > map, T key, DiagnosticData diagnostic) { var errors = GetErrorSet(map, key); errors.Add(diagnostic); }
protected override bool ShouldIncludeDiagnostic(DiagnosticData diagnostic) { return _diagnosticIds == null || _diagnosticIds.Contains(diagnostic.Id); }
public static bool IsCompilerDiagnostic(DiagnosticData diagnostic) { return(HasCustomTag(diagnostic.CustomTags, WellKnownDiagnosticTags.Compiler)); }
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.ENUMessageForBingSearch, diagnostic.Severity, diagnostic.DefaultSeverity, diagnostic.IsEnabledByDefault, diagnostic.WarningLevel, diagnostic.CustomTags, diagnostic.Properties, diagnostic.Workspace, diagnostic.ProjectId, diagnostic.DocumentId, newSpan, mappedFilePath: mappedLineInfo.GetMappedFilePathIfExist(), 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); }
public static bool IsSynthesizedExternalSourceDiagnostic(DiagnosticData diagnostic) { return(HasCustomTag(diagnostic.CustomTags, SynthesizedExternalSourceDiagnosticTag)); }
protected virtual bool ShouldIncludeDiagnostic(DiagnosticData diagnostic) => true;
private bool ShouldInclude(DiagnosticData diagnostic) { return(diagnostic.DocumentId == _document.Id && _range.IntersectsWith(diagnostic.GetTextSpan()) && (_includeSuppressedDiagnostics || !diagnostic.IsSuppressed) && (_diagnosticId == null || _diagnosticId == diagnostic.Id)); }
protected override DiagnosticTag[] ConvertTags(DiagnosticData diagnosticData) { // All workspace diagnostics are potential duplicates given that they can be overridden by the diagnostics // produced by document diagnostics. return(ConvertTags(diagnosticData, potentialDuplicate: true)); }
/// <summary> /// Reports diagnostics. /// </summary> /// <returns>Returns ids of documents that belong to <paramref name="projectId"/> and containing one or more diagnostics.</returns> public ImmutableArray <DocumentId> ReportDiagnostics(object errorId, Solution solution, ProjectId projectId, IEnumerable <Diagnostic> diagnostics) { Debug.Assert(errorId != null); Debug.Assert(solution != null); Debug.Assert(projectId != null); var updateEvent = DiagnosticsUpdated; var documentIds = PooledHashSet <DocumentId> .GetInstance(); var documentDiagnosticData = ArrayBuilder <DiagnosticData> .GetInstance(); var projectDiagnosticData = ArrayBuilder <DiagnosticData> .GetInstance(); var project = solution.GetProject(projectId); foreach (var diagnostic in diagnostics) { var documentOpt = solution.GetDocument(diagnostic.Location.SourceTree); if (documentOpt != null) { if (updateEvent != null) { documentDiagnosticData.Add(DiagnosticData.Create(documentOpt, diagnostic)); } // only add documents from the current project: if (documentOpt.Project.Id == projectId) { documentIds.Add(documentOpt.Id); } } else if (updateEvent != null) { projectDiagnosticData.Add(DiagnosticData.Create(project, diagnostic)); } } foreach (var documentDiagnostics in documentDiagnosticData.ToDictionary(data => data.DocumentId)) { updateEvent(this, DiagnosticsUpdatedArgs.DiagnosticsCreated( errorId, solution.Workspace, solution, projectId, documentId: documentDiagnostics.Key, diagnostics: documentDiagnostics.Value)); } if (projectDiagnosticData.Count > 0) { updateEvent(this, DiagnosticsUpdatedArgs.DiagnosticsCreated( errorId, solution.Workspace, solution, projectId, documentId: null, diagnostics: projectDiagnosticData.ToImmutable())); } var result = documentIds.AsImmutableOrEmpty(); documentDiagnosticData.Free(); projectDiagnosticData.Free(); documentIds.Free(); return(result); }
private static DiagnosticData CreateLiveDiagnostic(DiagnosticDescriptor descriptor, DiagnosticData diagnostic) { return(new DiagnosticData( descriptor.Id, descriptor.Category, diagnostic.Message, descriptor.GetBingHelpMessage(), diagnostic.Severity, descriptor.DefaultSeverity, descriptor.IsEnabledByDefault, diagnostic.WarningLevel, descriptor.CustomTags.ToImmutableArray(), diagnostic.Properties, diagnostic.Workspace, diagnostic.ProjectId, diagnostic.DataLocation, diagnostic.AdditionalLocations, descriptor.Title.ToString(CultureInfo.CurrentUICulture), descriptor.Description.ToString(CultureInfo.CurrentUICulture), descriptor.HelpLinkUri, isSuppressed: diagnostic.IsSuppressed)); }
protected internal override ITagSpan <IErrorTag> CreateTagSpan(bool isLiveUpdate, SnapshotSpan span, DiagnosticData data) { var errorTag = CreateErrorTag(data); if (errorTag == null) { return(null); } // Live update squiggles have to be at least 1 character long. var minimumLength = isLiveUpdate ? 1 : 0; var adjustedSpan = AdjustSnapshotSpan(span, minimumLength); if (adjustedSpan.Length == 0) { return(null); } return(new TagSpan <IErrorTag>(adjustedSpan, errorTag)); }
public void AddError(DocumentId key, DiagnosticData diagnostic) { AddError(_documentMap, key, diagnostic); }
static bool DataHasTag(DiagnosticData desc, string tag) { return(desc.CustomTags.Any(c => CultureInfo.InvariantCulture.CompareInfo.Compare(c, tag) == 0)); }
private void AddError <T>(Dictionary <T, Dictionary <DiagnosticData, int> > map, T key, DiagnosticData diagnostic) { var errors = GetErrorSet(map, key); AddError(errors, diagnostic); }
private void AddDiagnostics( ref Dictionary <DocumentId, List <DiagnosticData> > lazyLocals, SyntaxTree tree, IEnumerable <Diagnostic> diagnostics) { foreach (var diagnostic in diagnostics) { // REVIEW: what is our plan for additional locations? switch (diagnostic.Location.Kind) { case LocationKind.ExternalFile: { // TODO: currently additional file location is not supported. break; } case LocationKind.None: { _lazyOthers = _lazyOthers ?? new List <DiagnosticData>(); _lazyOthers.Add(DiagnosticData.Create(Project, diagnostic)); break; } case LocationKind.SourceFile: { if (tree != null && diagnostic.Location.SourceTree == tree) { var document = GetDocument(diagnostic); if (document != null) { // local diagnostics to a file lazyLocals = lazyLocals ?? new Dictionary <DocumentId, List <DiagnosticData> >(); lazyLocals.GetOrAdd(document.Id, _ => new List <DiagnosticData>()).Add(DiagnosticData.Create(document, diagnostic)); AddDocumentToSet(document); } } else if (diagnostic.Location.SourceTree != null) { var document = Project.GetDocument(diagnostic.Location.SourceTree); if (document != null) { // non local diagnostics to a file _lazyNonLocals = _lazyNonLocals ?? new Dictionary <DocumentId, List <DiagnosticData> >(); _lazyNonLocals.GetOrAdd(document.Id, _ => new List <DiagnosticData>()).Add(DiagnosticData.Create(document, diagnostic)); AddDocumentToSet(document); } } else { // non local diagnostics without location _lazyOthers = _lazyOthers ?? new List <DiagnosticData>(); _lazyOthers.Add(DiagnosticData.Create(Project, diagnostic)); } break; } case LocationKind.MetadataFile: case LocationKind.XmlFile: { // something we don't care continue; } default: { Contract.Fail("should not reach"); break; } } } }
private bool CanReuseDiagnostic(DiagnosticData diagnostic) { // We can't reuse diagnostics that contain additional locations. It's too // difficult to ensure that all the locations will be moved to the right return diagnostic.AdditionalLocations == null || diagnostic.AdditionalLocations.Count == 0; }
private void AddExternalDiagnostics( ref Dictionary <DocumentId, List <DiagnosticData> > lazyLocals, DocumentId documentId, IEnumerable <Diagnostic> diagnostics) { Contract.ThrowIfTrue(Project.SupportsCompilation); foreach (var diagnostic in diagnostics) { // REVIEW: what is our plan for additional locations? switch (diagnostic.Location.Kind) { case LocationKind.ExternalFile: { var diagnosticDocumentId = GetExternalDocumentId(diagnostic); if (documentId == diagnosticDocumentId) { var document = Project.GetDocument(diagnosticDocumentId); if (document != null) { // local diagnostics to a file lazyLocals = lazyLocals ?? new Dictionary <DocumentId, List <DiagnosticData> >(); lazyLocals.GetOrAdd(document.Id, _ => new List <DiagnosticData>()).Add(DiagnosticData.Create(document, diagnostic)); AddDocumentToSet(document); } } else if (diagnosticDocumentId != null) { var document = Project.GetDocument(diagnosticDocumentId); if (document != null) { // non local diagnostics to a file _lazyNonLocals = _lazyNonLocals ?? new Dictionary <DocumentId, List <DiagnosticData> >(); _lazyNonLocals.GetOrAdd(document.Id, _ => new List <DiagnosticData>()).Add(DiagnosticData.Create(document, diagnostic)); AddDocumentToSet(document); } } else { // non local diagnostics without location _lazyOthers = _lazyOthers ?? new List <DiagnosticData>(); _lazyOthers.Add(DiagnosticData.Create(Project, diagnostic)); } break; } case LocationKind.None: { _lazyOthers = _lazyOthers ?? new List <DiagnosticData>(); _lazyOthers.Add(DiagnosticData.Create(Project, diagnostic)); break; } case LocationKind.SourceFile: case LocationKind.MetadataFile: case LocationKind.XmlFile: { // something we don't care continue; } default: { Contract.Fail("should not reach"); break; } } } }
private bool ShouldIncludeSuppressedDiagnostic(DiagnosticData diagnostic) { return IncludeSuppressedDiagnostics || !diagnostic.IsSuppressed; }
public FirstDiagnosticResult(bool partialResult, bool hasFix, DiagnosticData diagnostic) { this.PartialResult = partialResult; this.HasFix = hasFix; this.Diagnostic = diagnostic; }
private bool ShouldIncludeSuppressedDiagnostic(DiagnosticData diagnostic) => IncludeSuppressedDiagnostics || !diagnostic.IsSuppressed;
private static DiagnosticData CreateLiveDiagnostic(DiagnosticDescriptor descriptor, DiagnosticData diagnostic) { return new DiagnosticData( descriptor.Id, descriptor.Category, diagnostic.Message, descriptor.MessageFormat.ToString(DiagnosticData.USCultureInfo), diagnostic.Severity, descriptor.DefaultSeverity, descriptor.IsEnabledByDefault, diagnostic.WarningLevel, descriptor.CustomTags.ToImmutableArray(), diagnostic.Properties, diagnostic.Workspace, diagnostic.ProjectId, diagnostic.DataLocation, diagnostic.AdditionalLocations, descriptor.Title.ToString(CultureInfo.CurrentUICulture), descriptor.Description.ToString(CultureInfo.CurrentUICulture), descriptor.HelpLinkUri, isSuppressed: diagnostic.IsSuppressed); }
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); }