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;
        }
Beispiel #3
0
        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);
            }
Beispiel #9
0
        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));
            }
        }
Beispiel #10
0
        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));
            }
        }
Beispiel #11
0
        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;
        }
Beispiel #12
0
        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;
        }
Beispiel #13
0
 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));
Beispiel #16
0
        /// <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);
 }
Beispiel #18
0
 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;
        }
Beispiel #20
0
 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);
Beispiel #22
0
        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));
 }
Beispiel #26
0
 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));
            }
Beispiel #28
0
        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);
        }
Beispiel #35
0
        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));
        }