public async Task<AnalysisData> GetDocumentBodyAnalysisDataAsync(
                DiagnosticAnalyzer provider, ProviderId providerId, VersionArgument versions, DiagnosticAnalyzerDriver analyzerDriver,
                SyntaxNode root, SyntaxNode member, int memberId, bool supportsSemanticInSpan, MemberRangeMap.MemberRanges ranges)
            {
                try
                {
                    var document = analyzerDriver.Document;
                    var cancellationToken = analyzerDriver.CancellationToken;

                    var state = AnalyzersAndState.GetOrCreateDiagnosticState(StateType.Document, providerId, provider, document.Project.Id, document.Project.Language);
                    var existingData = await state.TryGetExistingDataAsync(document, cancellationToken).ConfigureAwait(false);

                    ImmutableArray<DiagnosticData> diagnosticData;
                    if (supportsSemanticInSpan && CanUseDocumentState(existingData, ranges.TextVersion, versions.DataVersion))
                    {
                        var memberDxData = await GetSemanticDiagnosticsAsync(providerId, provider, analyzerDriver).ConfigureAwait(false);

                        diagnosticData = _owner.UpdateDocumentDiagnostics(existingData, ranges.Ranges, memberDxData.AsImmutableOrEmpty(), root.SyntaxTree, member, memberId);
                        ValidateMemberDiagnostics(providerId, provider, document, root, diagnosticData);
                    }
                    else
                    {
                        // if we can't re-use existing document state, only option we have is updating whole document state here.
                        var dx = await GetSemanticDiagnosticsAsync(providerId, provider, analyzerDriver).ConfigureAwait(false);
                        diagnosticData = dx.AsImmutableOrEmpty();
                    }

                    return new AnalysisData(versions.TextVersion, versions.DataVersion, GetExistingItems(existingData), diagnosticData);
                }
                catch (Exception e) when (FatalError.ReportUnlessCanceled(e))
                {
                    throw ExceptionUtilities.Unreachable;
                }
            }
            public static void Cache(DiagnosticAnalyzer analyzer, object key, CacheEntry entry)
            {
                AssertKey(key);

                // add new cache entry
                var analyzerMap = s_map.GetOrAdd(analyzer, _ => new ConcurrentDictionary<object, CacheEntry>(concurrencyLevel: 2, capacity: 10));
                analyzerMap[key] = entry;
            }
예제 #3
0
 public MemberRanges GetSavedMemberRange(DiagnosticAnalyzer analyzer, Document document)
 {
     var data = _map.GetOrAdd(document.Id, s_createMap);
     lock (data)
     {
         return GetSavedMemberRange_NoLock(data, analyzer, document);
     }
 }
            public StateSet(string language, DiagnosticAnalyzer analyzer, string errorSourceName)
            {
                _language = language;
                _analyzer = analyzer;
                _errorSourceName = errorSourceName;

                _state = CreateDiagnosticStates(language, analyzer);
            }
            /// <summary>
            /// Get the unique state name for the given {type, analyzer} tuple.
            /// Note that this name is used by the underlying persistence stream of the corresponding <see cref="DiagnosticState"/> to Read/Write diagnostic data into the stream.
            /// If any two distinct {type, analyzer} tuples have the same diagnostic state name, we will end up sharing the persistence stream between them, leading to duplicate/missing/incorrect diagnostic data.
            /// </summary>
            private static ValueTuple<string, VersionStamp> GetNameAndVersion(DiagnosticAnalyzer analyzer, StateType type)
            {
                Contract.ThrowIfNull(analyzer);

                // Get the unique ID for given diagnostic analyzer.
                // note that we also put version stamp so that we can detect changed analyzer.
                var tuple = analyzer.GetAnalyzerIdAndVersion();
                return ValueTuple.Create(UserDiagnosticsPrefixTableName + "_" + type.ToString() + "_" + tuple.Item1, tuple.Item2);
            }
예제 #6
0
        public void Touch(DiagnosticAnalyzer analyzer, Document document, VersionStamp version)
        {
            // only touch and updateMemberRange methods are allowed to update the dictionaries
            var data = _map.GetOrAdd(document.Id, s_createMap);

            lock (data)
            {
                Touch_NoLock(data, analyzer, document, version);
            }
        }
                public StateSet GetOrCreateStateSet(Project project, DiagnosticAnalyzer analyzer)
                {
                    var map = GetOrCreateAnalyzerMap(project);
                    if (map.TryGetValue(analyzer, out var set))
                    {
                        return set;
                    }

                    return null;
                }
예제 #8
0
        public static void LogAnalyzerCrashCount(DiagnosticAnalyzer analyzer, Exception ex, LogAggregator logAggregator, ProjectId projectId)
        {
            if (logAggregator == null || analyzer == null || ex == null || ex is OperationCanceledException)
            {
                return;
            }

            // TODO: once we create description manager, pass that into here.
            bool telemetry = DiagnosticAnalyzerLogger.AllowsTelemetry(null, analyzer, projectId);
            var tuple = ValueTuple.Create(telemetry, analyzer.GetType(), ex.GetType());
            logAggregator.IncreaseCount(tuple);
        }
                public StateSet GetOrCreateStateSet(string language, DiagnosticAnalyzer analyzer)
                {
                    var map = GetAnalyzerMap(language);

                    StateSet set;
                    if (map.TryGetValue(analyzer, out set))
                    {
                        return set;
                    }

                    return null;
                }
            public static bool TryGetValue(DiagnosticAnalyzer analyzer, object key, out CacheEntry entry)
            {
                AssertKey(key);

                entry = default(CacheEntry);
                if (!s_map.TryGetValue(analyzer, out var analyzerMap) ||
                    !analyzerMap.TryGetValue(key, out entry))
                {
                    return false;
                }

                return true;
            }
예제 #11
0
            public AnalyzerInfo(DiagnosticAnalyzer analyzer, AnalyzerActions analyzerActions, bool telemetry)
            {
                CLRType = analyzer.GetType();
                Telemetry = telemetry;

                Counts[0] = analyzerActions.CodeBlockEndActionsCount;
                Counts[1] = analyzerActions.CodeBlockStartActionsCount;
                Counts[2] = analyzerActions.CompilationEndActionsCount;
                Counts[3] = analyzerActions.CompilationStartActionsCount;
                Counts[4] = analyzerActions.SemanticModelActionsCount;
                Counts[5] = analyzerActions.SymbolActionsCount;
                Counts[6] = analyzerActions.SyntaxNodeActionsCount;
                Counts[7] = analyzerActions.SyntaxTreeActionsCount;
            }
예제 #12
0
        public void UpdateAnalyzerTypeCount(DiagnosticAnalyzer analyzer, ActionCounts analyzerActions, Project projectOpt)
        {
            var telemetry = DiagnosticAnalyzerLogger.AllowsTelemetry(_owner, analyzer, projectOpt?.Id);

            ImmutableInterlocked.AddOrUpdate(
                ref _analyzerInfoMap,
                analyzer.GetType(),
                addValue: new AnalyzerInfo(analyzer, analyzerActions, telemetry),
                updateValueFactory: (k, ai) =>
                {
                    ai.SetAnalyzerTypeCount(analyzerActions);
                    return ai;
                });
        }
            public static void Remove(DiagnosticAnalyzer analyzer, object key)
            {
                AssertKey(key);
                // remove the entry
                if (!s_map.TryGetValue(analyzer, out var analyzerMap))
                {
                    return;
                }

                analyzerMap.TryRemove(key, out var entry);

                if (analyzerMap.IsEmpty)
                {
                    s_map.TryRemove(analyzer, out analyzerMap);
                }
            }
예제 #14
0
        public static bool IsCompilerAnalyzer(DiagnosticAnalyzer analyzer)
        {
            // TODO: find better way.
            var typeString = analyzer.GetType().ToString();
            if (typeString == CSharpCompilerAnalyzerTypeName)
            {
                return true;
            }

            if (typeString == VisualBasicCompilerAnalyzerTypeName)
            {
                return true;
            }

            return false;
        }
            private static DiagnosticState[] CreateDiagnosticStates(string language, DiagnosticAnalyzer analyzer)
            {
                var states = new DiagnosticState[s_stateTypeCount];

                for (int stateType = 0; stateType < s_stateTypeCount; stateType++)
                {
                    var nameAndVersion = GetNameAndVersion(analyzer, (StateType)stateType);

                    var name = nameAndVersion.Item1;
                    var version = nameAndVersion.Item2;

                    states[stateType] = new DiagnosticState(name, version, language);
                }

                return states;
            }
                    public DiagnosticAnalyzerMap(HostAnalyzerManager analyzerManager, string language, ImmutableDictionary<DiagnosticAnalyzer, StateSet> analyzerMap)
                    {
                        // hold directly on to compiler analyzer
                        _compilerAnalyzer = analyzerManager.GetCompilerDiagnosticAnalyzer(language);

                        // in test case, we might not have the compiler analyzer.
                        if (_compilerAnalyzer == null)
                        {
                            _map = analyzerMap;
                            return;
                        }

                        _compilerStateSet = analyzerMap[_compilerAnalyzer];

                        // hold rest of analyzers
                        _map = analyzerMap.Remove(_compilerAnalyzer);
                    }
예제 #17
0
        public void UpdateMemberRange(
            DiagnosticAnalyzer analyzer, Document document, VersionStamp newVersion, int memberId, TextSpan span, MemberRanges oldRanges)
        {
            // only touch and updateMemberRange methods are allowed to update the dictionaries
            var data = _map.GetOrAdd(document.Id, s_createMap);

            lock (data)
            {
                // now update member range map
                UpdateMemberRange_NoLock(data, document, newVersion, memberId, span, oldRanges.TextVersion);

                // save analyzer version information
                Touch_NoLock(data, analyzer, document, newVersion);

                ValidateMemberRangeMap(document, newVersion);
            }
        }
        private bool SupportAnalysisKind(DiagnosticAnalyzer analyzer, string language, AnalysisKind kind)
        {
            // compiler diagnostic analyzer always support all kinds
            if (HostAnalyzerManager.IsCompilerDiagnosticAnalyzer(language, analyzer))
            {
                return true;
            }

            switch (kind)
            {
                case AnalysisKind.Syntax:
                    return analyzer.SupportsSyntaxDiagnosticAnalysis();
                case AnalysisKind.Semantic:
                    return analyzer.SupportsSemanticDiagnosticAnalysis();
                default:
                    return Contract.FailWithReturn<bool>("shouldn't reach here");
            }
        }
            public StateSet(string language, DiagnosticAnalyzer analyzer, string errorSourceName)
            {
                _language = language;
                _analyzer = analyzer;
                _errorSourceName = errorSourceName;

                var nameAndVersion = GetNameAndVersion(_analyzer);
                _analyzerVersion = nameAndVersion.Item2;

                _stateName = nameAndVersion.Item1;

                _syntaxStateName = _stateName + ".Syntax";
                _semanticStateName = _stateName + ".Semantic";
                _nonLocalStateName = _stateName + ".NonLocal";

                _activeFileStates = new ConcurrentDictionary<DocumentId, ActiveFileState>(concurrencyLevel: 2, capacity: 10);
                _projectStates = new ConcurrentDictionary<ProjectId, ProjectState>(concurrencyLevel: 2, capacity: 1);
            }
            public static void Remove(DiagnosticAnalyzer analyzer, object key)
            {
                AssertKey(key);

                // remove the entry
                ConcurrentDictionary<object, CacheEntry> analyzerMap;
                if (!s_map.TryGetValue(analyzer, out analyzerMap))
                {
                    return;
                }

                CacheEntry entry;
                analyzerMap.TryRemove(key, out entry);

                if (analyzerMap.IsEmpty)
                {
                    s_map.TryRemove(analyzer, out analyzerMap);
                }
            }
예제 #21
0
        private void Touch_NoLock(DictionaryData data, DiagnosticAnalyzer analyzer, Document document, VersionStamp version)
        {
            VersionStamp oldVersion;
            if (data.VersionMap.TryGetValue(analyzer, out oldVersion))
            {
                DecreaseVersion_NoLock(data, document.Id, oldVersion);
            }

            IncreaseVersion_NoLock(data, document.Id, version);
            data.VersionMap[analyzer] = version;

            ImmutableArray<TextSpan> range;
            if (this.TryCreateOrGetMemberRange_NoLock(data, document, version, out range))
            {
                data.MemberRangeMap[version] = range;
            }

            ValidateVersionTracking();
        }
            public LatestDiagnosticsForSpanGetter(
                DiagnosticIncrementalAnalyzer owner, Document document, SyntaxNode root, TextSpan range, bool blockForData, List<DiagnosticData> diagnostics, CancellationToken cancellationToken)
            {
                _owner = owner;

                _document = document;
                _compilerAnalyzer = _owner.HostAnalyzerManager.GetCompilerDiagnosticAnalyzer(_document.Project.Language);

                _range = range;
                _blockForData = blockForData;
                _cancellationToken = cancellationToken;

                Diagnostics = diagnostics;

                // Share the diagnostic analyzer driver across all analyzers.
                var fullSpan = root?.FullSpan;

                _spanBasedDriver = new DiagnosticAnalyzerDriver(_document, _range, root, _owner, _cancellationToken);
                _documentBasedDriver = new DiagnosticAnalyzerDriver(_document, fullSpan, root, _owner, _cancellationToken);
                _projectDriver = new DiagnosticAnalyzerDriver(_document.Project, _owner, _cancellationToken);
            }
            public async Task<AnalysisData> GetDocumentAnalysisDataAsync(
                DiagnosticAnalyzer provider, ProviderId providerId, VersionArgument versions, DiagnosticAnalyzerDriver analyzerDrvier)
            {
                try
                {
                    var document = analyzerDrvier.Document;
                    var cancellationToken = analyzerDrvier.CancellationToken;

                    var state = AnalyzersAndState.GetOrCreateDiagnosticState(StateType.Document, providerId, provider, document.Project.Id, document.Project.Language);
                    var existingData = await state.TryGetExistingDataAsync(document, cancellationToken).ConfigureAwait(false);

                    if (CheckSemanticVersions(document, existingData, versions))
                    {
                        return existingData;
                    }

                    var diagnosticData = await GetSemanticDiagnosticsAsync(providerId, provider, analyzerDrvier).ConfigureAwait(false);
                    return new AnalysisData(versions.TextVersion, versions.DataVersion, GetExistingItems(existingData), diagnosticData.AsImmutableOrEmpty());
                }
                catch (Exception e) when (FatalError.ReportUnlessCanceled(e))
                {
                    throw ExceptionUtilities.Unreachable;
                }
            }
 private Task <IEnumerable <DiagnosticData> > GetSyntaxDiagnosticsAsync(DiagnosticAnalyzer analyzer, CancellationToken cancellationToken)
 {
     return(_owner._executor.ComputeDiagnosticsAsync(_analyzerDriverOpt, _document, analyzer, AnalysisKind.Syntax, _range, cancellationToken));
 }
        /// <summary>
        /// Given an analyzer and a collection of documents to apply it to, run the analyzer and gather an array of
        /// diagnostics found. The returned diagnostics are then ordered by location in the source documents.
        /// </summary>
        /// <param name="analyzer">The analyzer to run on the documents.</param>
        /// <param name="documents">The <see cref="Document"/>s that the analyzer will be run on.</param>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/> that the task will observe.</param>
        /// <returns>A collection of <see cref="Diagnostic"/>s that surfaced in the source code, sorted by
        /// <see cref="Diagnostic.Location"/>.</returns>
        protected static async Task <ImmutableArray <Diagnostic> > GetSortedDiagnosticsFromDocumentsAsync(DiagnosticAnalyzer analyzer, Document[] documents, CancellationToken cancellationToken)
        {
            var projects = new HashSet <Project>();

            foreach (var document in documents)
            {
                projects.Add(document.Project);
            }

            var diagnostics = ImmutableArray.CreateBuilder <Diagnostic>();

            foreach (var project in projects)
            {
                var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);

                var compilationWithAnalyzers = compilation.WithAnalyzers(ImmutableArray.Create(analyzer), null, cancellationToken);
                var compilerDiagnostics      = compilation.GetDiagnostics(cancellationToken);
                var compilerErrors           = compilerDiagnostics.Where(i => i.Severity == DiagnosticSeverity.Error);
                var diags = await compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync().ConfigureAwait(false);

                foreach (var diag in diags.Concat(compilerErrors))
                {
                    if (diag.Location == Location.None || diag.Location.IsInMetadata)
                    {
                        diagnostics.Add(diag);
                    }
                    else
                    {
                        for (int i = 0; i < documents.Length; i++)
                        {
                            var document = documents[i];
                            var tree     = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);

                            if (tree == diag.Location.SourceTree)
                            {
                                diagnostics.Add(diag);
                            }
                        }
                    }
                }
            }

            var results = SortDistinctDiagnostics(diagnostics);

            return(results.ToImmutableArray());
        }
            private async Task <IEnumerable <DiagnosticData> > GetProjectDiagnosticsAsync(DiagnosticAnalyzer analyzer, CancellationToken cancellationToken)
            {
                if (_projectResultCache == null)
                {
                    // execute whole project as one shot and cache the result.
                    var forceAnalyzerRun = true;
                    var analysisResult   = await _owner._executor.GetProjectAnalysisDataAsync(_analyzerDriverOpt, _project, _stateSets, forceAnalyzerRun, cancellationToken).ConfigureAwait(false);

                    _projectResultCache = analysisResult.Result;
                }

                if (!_projectResultCache.TryGetValue(analyzer, out var result))
                {
                    return(ImmutableArray <DiagnosticData> .Empty);
                }

                return(GetResult(result, AnalysisKind.NonLocal, _document.Id));
            }
예제 #27
0
        /// <summary>
        /// General method that gets a collection of actual diagnostics found in the source after the analyzer is run,
        /// then verifies each of them.
        /// </summary>
        /// <param name="sources">An array of strings to create source documents from to run the analyzers on</param>
        /// <param name="language">The language of the classes represented by the source strings</param>
        /// <param name="analyzer">The analyzer to be run on the source code</param>
        /// <param name="expected">DiagnosticResults that should appear after the analyzer is run on the sources</param>
        private static async Task VerifyDiagnosticsAsync(string[] sources, string language, DiagnosticAnalyzer analyzer, params DiagnosticResult[] expected)
        {
            var diagnostics = await GetSortedDiagnosticsAsync(sources, language, analyzer).ConfigureAwait(false);

            VerifyDiagnosticResults(diagnostics, analyzer, expected);
        }
예제 #28
0
        private async Task <Diagnostic[]> GetSortedDiagnostics(DiagnosticAnalyzer analyzer)
        {
            var documents = await GetDocuments().ConfigureAwait(false);

            return(await GetSortedDiagnosticsFromDocuments(analyzer, documents, compileSolution : true).ConfigureAwait(false));
        }
예제 #29
0
        /// <summary>
        /// General method that gets a collection of actual diagnostics found in the source after the analyzer is run,
        /// then verifies each of them.
        /// </summary>
        /// <param name="sources">An array of strings to create source documents from to run the analyzers on</param>
        /// <param name="analyzer">The analyzer to be run on the source code</param>
        /// <param name="expected">DiagnosticResults that should appear after the analyzer is run on the sources</param>
        private void VerifyDiagnostics(string[] sources, DiagnosticAnalyzer analyzer, params DiagnosticResult[] expected)
        {
            var diagnostics = GetSortedDiagnostics(sources, analyzer);

            VerifyDiagnosticResults(diagnostics, analyzer, expected);
        }
            private async Task <IEnumerable <DiagnosticData> > GetCompilerSemanticDiagnosticsAsync(DiagnosticAnalyzer analyzer, CancellationToken cancellationToken)
            {
                var model = await _document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

                VerifyDiagnostics(model);

                var root = await _document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

                var adjustedSpan = AdjustSpan(_document, root, _range);
                var diagnostics  = model.GetDeclarationDiagnostics(adjustedSpan, cancellationToken).Concat(model.GetMethodBodyDiagnostics(adjustedSpan, cancellationToken));

                return(_owner._executor.ConvertToLocalDiagnostics(_document, diagnostics, _range));
            }
 /// <summary>
 ///     Given classes in the form of strings, their language, and an IDiagnosticAnlayzer to apply to it, return the
 ///     diagnostics found in the string after converting it to a document.
 /// </summary>
 /// <param name="sources">Classes in the form of strings</param>
 /// <param name="language">The language the source classes are in</param>
 /// <param name="analyzer">The analyzer to be run on the sources</param>
 /// <returns>An IEnumerable of Diagnostics that surfaced in the source code, sorted by Location</returns>
 private static Diagnostic[] GetSortedDiagnostics(string[] sources, string language, DiagnosticAnalyzer analyzer)
 {
     return(GetSortedDiagnosticsFromDocuments(analyzer, GetDocuments(sources, language)));
 }
 private static string GetProjectLogMessage(Project project, DiagnosticAnalyzer analyzer)
 {
     return string.Format("project: {0}, {1}", project.FilePath ?? project.Name, analyzer.ToString());
 }
        private static async Task<IEnumerable<DiagnosticData>> GetProjectDiagnosticsAsync(DiagnosticAnalyzerDriver userDiagnosticDriver, DiagnosticAnalyzer analyzer)
        {
            using (Logger.LogBlock(FunctionId.Diagnostics_ProjectDiagnostic, GetProjectLogMessage, userDiagnosticDriver.Project, analyzer, userDiagnosticDriver.CancellationToken))
            {
                try
                {
                    Contract.ThrowIfNull(analyzer);

                    var diagnostics = await userDiagnosticDriver.GetProjectDiagnosticsAsync(analyzer).ConfigureAwait(false);
                    return GetDiagnosticData(userDiagnosticDriver.Project, diagnostics);
                }
                catch (Exception e) when (FatalError.ReportUnlessCanceled(e))
                {
                    throw ExceptionUtilities.Unreachable;
                }
            }
        }
예제 #34
0
        private async Task VerifyDiagnostics(DiagnosticAnalyzer analyzer, IList <DiagnosticResult> expected)
        {
            var diagnostics = await GetSortedDiagnostics(analyzer).ConfigureAwait(false);

            VerifyDiagnosticResults(diagnostics, analyzer, expected);
        }
 /// <summary>
 /// Given classes in the form of strings, their language, and an <see cref="DiagnosticAnalyzer"/> to apply to
 /// it, return the <see cref="Diagnostic"/>s found in the string after converting it to a
 /// <see cref="Document"/>.
 /// </summary>
 /// <param name="sources">Classes in the form of strings.</param>
 /// <param name="language">The language the source classes are in. Values may be taken from the
 /// <see cref="LanguageNames"/> class.</param>
 /// <param name="analyzer">The analyzer to be run on the sources.</param>
 /// <param name="cancellationToken">The <see cref="CancellationToken"/> that the task will observe.</param>
 /// <returns>A collection of <see cref="Diagnostic"/>s that surfaced in the source code, sorted by
 /// <see cref="Diagnostic.Location"/>.</returns>
 private static Task <ImmutableArray <Diagnostic> > GetSortedDiagnosticsAsync(string[] sources, string language, DiagnosticAnalyzer analyzer, CancellationToken cancellationToken)
 {
     return(GetSortedDiagnosticsFromDocumentsAsync(analyzer, GetDocuments(sources, language), cancellationToken));
 }
예제 #36
0
        /// <summary>
        /// General method that gets a collection of actual diagnostics found in the source after the analyzer is run,
        /// then verifies each of them.
        /// </summary>
        /// <param name="sources">An array of strings to create source documents from to run the analyzers on</param>
        /// <param name="language">The language of the classes represented by the source strings</param>
        /// <param name="analyzer">The analyzer to be run on the source code</param>
        /// <param name="expected">DiagnosticResults that should appear after the analyzer is run on the sources</param>
        private void VerifyDiagnostics(string[] sources, string language, DiagnosticAnalyzer analyzer, params DiagnosticResult[] expected)
        {
            var diagnostics = GetSortedDiagnostics(sources, language, analyzer, parseOptions: null, compilationOptions: null);

            VerifyDiagnosticResults(diagnostics, analyzer, expected);
        }
예제 #37
0
        /// <summary>
        /// General method that gets a collection of actual diagnostics found in the source after the analyzer is run,
        /// then verifies each of them.
        /// </summary>
        /// <param name="sources">An array of strings to create source documents from to run the analyzers on</param>
        /// <param name="language">The language of the classes represented by the source strings</param>
        /// <param name="analyzer">The analyzer to be run on the source code</param>
        /// <param name="expected">DiagnosticResults that should appear after the analyzer is run on the sources</param>
        private void VerifyDiagnostics(string[] sources, string language, DiagnosticAnalyzer analyzer, params DiagnosticResult[] expected)
        {
            var diagnostics = GetSortedDiagnostics(workspace, sources, language, analyzer);

            VerifyDiagnosticResults(diagnostics, analyzer, expected);
        }
예제 #38
0
        /// <summary>
        /// Checks each of the actual Diagnostics found and compares them with the corresponding DiagnosticResult in the array of expected results.
        /// Diagnostics are considered equal only if the DiagnosticResultLocation, Id, Severity, and Message of the DiagnosticResult match the actual diagnostic.
        /// </summary>
        /// <param name="actualResults">The Diagnostics found by the compiler after running the analyzer on the source code</param>
        /// <param name="analyzer">The analyzer that was being run on the sources</param>
        /// <param name="expectedResults">Diagnostic Results that should have appeared in the code</param>
        private static void VerifyDiagnosticResults(IEnumerable <Diagnostic> actualResults, DiagnosticAnalyzer analyzer, params DiagnosticResult[] expectedResults)
        {
            int expectedCount = expectedResults.Length;
            int actualCount   = actualResults.Count();

            if (expectedCount != actualCount)
            {
                string diagnosticsOutput = actualResults.Any() ? FormatDiagnostics(analyzer, actualResults.ToArray()) : "    NONE.";

                Assert.True(false,
                            string.Format("Mismatch between number of diagnostics returned, expected \"{0}\" actual \"{1}\"\r\n\r\nDiagnostics:\r\n{2}\r\n", expectedCount, actualCount, diagnosticsOutput));
            }

            for (int i = 0; i < expectedResults.Length; i++)
            {
                var actual   = actualResults.ElementAt(i);
                var expected = expectedResults[i];

                if (expected.Line == -1 && expected.Column == -1)
                {
                    if (actual.Location != Location.None)
                    {
                        Assert.True(false,
                                    string.Format("Expected:\nA project diagnostic with No location\nActual:\n{0}",
                                                  FormatDiagnostics(analyzer, actual)));
                    }
                }
                else
                {
                    VerifyDiagnosticLocation(analyzer, actual, actual.Location, expected.Locations.First());
                    var additionalLocations = actual.AdditionalLocations.ToArray();

                    if (additionalLocations.Length != expected.Locations.Length - 1)
                    {
                        Assert.True(false,
                                    string.Format("Expected {0} additional locations but got {1} for Diagnostic:\r\n    {2}\r\n",
                                                  expected.Locations.Length - 1, additionalLocations.Length,
                                                  FormatDiagnostics(analyzer, actual)));
                    }

                    for (int j = 0; j < additionalLocations.Length; ++j)
                    {
                        VerifyDiagnosticLocation(analyzer, actual, additionalLocations[j], expected.Locations[j + 1]);
                    }
                }

                if (actual.Id != expected.Id)
                {
                    Assert.True(false,
                                string.Format("Expected diagnostic id to be \"{0}\" was \"{1}\"\r\n\r\nDiagnostic:\r\n    {2}\r\n",
                                              expected.Id, actual.Id, FormatDiagnostics(analyzer, actual)));
                }

                if (actual.Severity != expected.Severity)
                {
                    Assert.True(false,
                                string.Format("Expected diagnostic severity to be \"{0}\" was \"{1}\"\r\n\r\nDiagnostic:\r\n    {2}\r\n",
                                              expected.Severity, actual.Severity, FormatDiagnostics(analyzer, actual)));
                }

                if (actual.GetMessage() != expected.Message)
                {
                    Assert.True(false,
                                string.Format("Expected diagnostic message to be \"{0}\" was \"{1}\"\r\n\r\nDiagnostic:\r\n    {2}\r\n",
                                              expected.Message, actual.GetMessage(), FormatDiagnostics(analyzer, actual)));
                }
            }
        }
예제 #39
0
        private static void VerifyDiagnosticResults(IEnumerable <Diagnostic> actualResults, DiagnosticAnalyzer analyzer, IList <DiagnosticResult> expectedResults)
        {
            var expectedCount = expectedResults.Count;
            var actualCount   = actualResults.Count();

            if (expectedCount != actualCount)
            {
                var diagnosticsOutput = actualResults.Any() ? FormatDiagnostics(analyzer, actualResults.ToArray()) : "    NONE.";

                Assert.True(false, $"Mismatch between number of diagnostics returned, expected \"{expectedCount}\" actual \"{actualCount}\"\r\n\r\nDiagnostics:\r\n{diagnosticsOutput}\r\n");
            }

            for (var i = 0; i < expectedResults.Count; i++)
            {
                var actual   = actualResults.ElementAt(i);
                var expected = expectedResults[i];

                if (expected.Line == -1 && expected.Column == -1)
                {
                    if (actual.Location != Location.None)
                    {
                        Assert.True(false,
                                    string.Format(CultureInfo.InvariantCulture, "Expected:\nA project diagnostic with No location\nActual:\n{0}",
                                                  FormatDiagnostics(analyzer, actual)));
                    }
                }
                else
                {
                    VerifyDiagnosticLocation(analyzer, actual, actual.Location, expected.Locations[0]);
                    var additionalLocations = actual.AdditionalLocations.ToArray();

                    if (additionalLocations.Length != expected.Locations.Count - 1)
                    {
                        Assert.True(false,
                                    string.Format(CultureInfo.InvariantCulture,
                                                  "Expected {0} additional locations but got {1} for Diagnostic:\r\n    {2}\r\n",
                                                  expected.Locations.Count - 1, additionalLocations.Length,
                                                  FormatDiagnostics(analyzer, actual)));
                    }

                    for (var j = 0; j < additionalLocations.Length; ++j)
                    {
                        VerifyDiagnosticLocation(analyzer, actual, additionalLocations[j], expected.Locations[j + 1]);
                    }
                }

                if (expected.Id != null && !string.Equals(actual.Id, expected.Id, StringComparison.Ordinal))
                {
                    Assert.True(false,
                                string.Format(CultureInfo.InvariantCulture, "Expected diagnostic id to be \"{0}\" was \"{1}\"\r\n\r\nDiagnostic:\r\n    {2}\r\n",
                                              expected.Id, actual.Id, FormatDiagnostics(analyzer, actual)));
                }

                if (expected.Severity != null && actual.Severity != expected.Severity)
                {
                    Assert.True(false,
                                string.Format(CultureInfo.InvariantCulture, "Expected diagnostic severity to be \"{0}\" was \"{1}\"\r\n\r\nDiagnostic:\r\n    {2}\r\n",
                                              expected.Severity, actual.Severity, FormatDiagnostics(analyzer, actual)));
                }

                if (expected.Message != null && !string.Equals(actual.GetMessage(), expected.Message, StringComparison.Ordinal))
                {
                    Assert.True(false,
                                string.Format(CultureInfo.InvariantCulture, "Expected diagnostic message to be \"{0}\" was \"{1}\"\r\n\r\nDiagnostic:\r\n    {2}\r\n",
                                              expected.Message, actual.GetMessage(), FormatDiagnostics(analyzer, actual)));
                }
            }
        }
예제 #40
0
 /// <summary>
 /// General method that gets a collection of actual diagnostics found in the source after the analyzer is run,
 /// then verifies each of them.
 /// </summary>
 /// <param name="sources">An array of strings to create source documents from to run the analyzers on</param>
 /// <param name="language">The language of the classes represented by the source strings</param>
 /// <param name="analyzer">The analyzer to be run on the source code</param>
 /// <param name="expected">DiagnosticResults that should appear after the analyzer is run on the sources</param>
 private static void VerifyDiagnostics(string[] sources, string language, DiagnosticAnalyzer analyzer, params DiagnosticResult[] expected)
 {
     Diagnostic[] diagnostics = GetSortedDiagnostics(sources, language, analyzer);
     VerifyDiagnosticResults(diagnostics, analyzer, expected);
 }
        private static bool ShouldRunAnalyzerForStateType(DiagnosticAnalyzer analyzer, StateType stateTypeId,
            ImmutableHashSet<string> diagnosticIds = null, Func<DiagnosticAnalyzer, ImmutableArray<DiagnosticDescriptor>> getDescriptors = null)
        {
            if (diagnosticIds != null && getDescriptors(analyzer).All(d => !diagnosticIds.Contains(d.Id)))
            {
                return false;
            }

            switch (stateTypeId)
            {
                case StateType.Syntax:
                    return analyzer.SupportsSyntaxDiagnosticAnalysis();

                case StateType.Document:
                    return analyzer.SupportsSemanticDiagnosticAnalysis();

                case StateType.Project:
                    return analyzer.SupportsProjectDiagnosticAnalysis();

                default:
                    throw ExceptionUtilities.Unreachable;
            }
        }
            private static string GetBuildToolName(HostAnalyzerManager analyzerManager, string language, DiagnosticAnalyzer analyzer)
            {
                var packageName = analyzerManager.GetDiagnosticAnalyzerPackageName(language, analyzer);
                if (packageName == null)
                {
                    return null;
                }

                if (packageName == RoslynLanguageServices)
                {
                    return PredefinedBuildTools.Live;
                }

                return $"{analyzer.GetAnalyzerAssemblyName()} [{packageName}]";
            }
 private static string GetSemanticLogMessage(Document document, TextSpan? span, DiagnosticAnalyzer analyzer)
 {
     return string.Format("semantic: {0}, {1}, {2}", document.FilePath ?? document.Name, span.HasValue ? span.Value.ToString() : "Full", analyzer.ToString());
 }
예제 #44
0
        /// <summary>
        /// Verifies that <paramref name="solution"/> produces no diagnostics when analyzed with <paramref name="analyzer"/>.
        /// </summary>
        /// <param name="analyzer">The <see cref="DiagnosticAnalyzer"/> to check <paramref name="solution"/> with.</param>
        /// <param name="solution">The <see cref="Solution"/> for which no errors or warnings are expected.</param>
        public static void NoAnalyzerDiagnostics(DiagnosticAnalyzer analyzer, Solution solution)
        {
            var diagnostics = Analyze.GetDiagnostics(analyzer, solution);

            NoDiagnostics(diagnostics);
        }
        private bool ShouldRunForFullProject(DiagnosticAnalyzer analyzer, Project project)
        {
            // PERF: Don't query descriptors for compiler analyzer, always execute it.
            if (HostAnalyzerManager.IsCompilerDiagnosticAnalyzer(project.Language, analyzer))
            {
                return true;
            }

            // most of analyzers, number of descriptor is quite small, so this should be cheap.
            return Owner.GetDiagnosticDescriptors(analyzer).Any(d => GetEffectiveSeverity(d, project.CompilationOptions) != ReportDiagnostic.Hidden);
        }
            private async Task <IEnumerable <DiagnosticData> > GetCompilerSyntaxDiagnosticsAsync(DiagnosticAnalyzer analyzer, CancellationToken cancellationToken)
            {
                var root = await _document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

                var diagnostics = root.GetDiagnostics();

                return(_owner._executor.ConvertToLocalDiagnostics(_document, diagnostics, _range));
            }
            /// <summary>
            /// Return <see cref="StateSet"/> for the given <see cref="DiagnosticAnalyzer"/> in the context of <see cref="Project"/>.
            /// This will either return already created <see cref="StateSet"/> for the specific snapshot of <see cref="Project"/> or
            /// It will create new <see cref="StateSet"/> for the <see cref="Project"/>.
            /// This will not have any side effect.
            /// </summary>
            public StateSet GetOrCreateStateSet(Project project, DiagnosticAnalyzer analyzer)
            {
                var stateSet = _hostStates.GetOrCreateStateSet(project.Language, analyzer);
                if (stateSet != null)
                {
                    return stateSet;
                }

                return _projectStates.GetOrCreateStateSet(project, analyzer);
            }
예제 #48
0
        public async Task InProperty(DiagnosticAnalyzer analyzer)
        {
            var fooCode = @"
namespace RoslynSandbox
{
    using System;
    using System.ComponentModel;
    using System.Drawing;
    using System.Runtime.CompilerServices;

    public class Foo
    {
        private Point point;
        private double h1;

        public event PropertyChangedEventHandler PropertyChanged;

        public int Value1 => this.Value1;

        public int Value2 => Value2;

        public int Value3 => this.Value1;

        public int Value4
        {
            get
            {
                return this.Value4;
            }

            set
            {
                if (value == this.Value4)
                {
                    return;
                }

                this.Value4 = value;
                this.OnPropertyChanged();
            }
        }

        public int Value5
        {
            get => this.Value5;
            set
            {
                if (value == this.Value5)
                {
                    return;
                }

                this.Value5 = value;
                this.OnPropertyChanged();
            }
        }

        public int Value6
        {
            get => this.Value5;
            set
            {
                if (value == this.Value5)
                {
                    return;
                }

                this.Value5 = value;
                this.OnPropertyChanged();
            }
        }

        public int X
        {
            get => this.X;
            set
            {
                if (value == this.point.X)
                {
                    return;
                }

                this.point = new Point(value, this.point.Y);
                this.OnPropertyChanged();
            }
        }

        public int Y
        {
            get
            {
                return this.Y;
            }

            set
            {
                if (value == this.point.Y)
                {
                    return;
                }

                this.point = new Point(this.point.X, value);
                this.OnPropertyChanged();
            }
        }

        public double H1
        {
            get => this.h1;
            set
            {
                if (value.Equals(this.h1))
                {
                    return;
                }

                this.h1 = value;
                this.OnPropertyChanged();
                this.OnPropertyChanged(nameof(this.Height));
                this.OnPropertyChanged(nameof(this.Height2));
            }
        }

        public double Height
        {
            get
            {
                return this.Height;
            }
        }

        public double Height2
        {
            get
            {
                return Math.Min(this.Height2, this.H1);
            }
        }

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}";
            await Analyze.GetDiagnosticsAsync(analyzer, new[] { fooCode }, AnalyzerAssert.MetadataReferences).ConfigureAwait(false);
        }