DiagnosticIncrementalAnalyzer_GetDiagnostics.cs 23.1 KB
Newer Older
H
Heejae Chang 已提交
1 2
// Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.

H
Heejae Chang 已提交
3
using System.Collections.Generic;
H
Heejae Chang 已提交
4 5 6 7 8 9 10 11
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis.Diagnostics.EngineV2
{
H
Heejae Chang 已提交
12
    internal partial class DiagnosticIncrementalAnalyzer
H
Heejae Chang 已提交
13 14 15
    {
        public override Task<ImmutableArray<DiagnosticData>> GetSpecificCachedDiagnosticsAsync(Solution solution, object id, bool includeSuppressedDiagnostics = false, CancellationToken cancellationToken = default(CancellationToken))
        {
H
Heejae Chang 已提交
16
            return new IDECachedDiagnosticGetter(this, solution, id, includeSuppressedDiagnostics).GetSpecificDiagnosticsAsync(cancellationToken);
H
Heejae Chang 已提交
17 18
        }

H
Heejae Chang 已提交
19
        public override Task<ImmutableArray<DiagnosticData>> GetCachedDiagnosticsAsync(Solution solution, ProjectId projectId, DocumentId documentId, bool includeSuppressedDiagnostics = false, CancellationToken cancellationToken = default(CancellationToken))
H
Heejae Chang 已提交
20
        {
H
Heejae Chang 已提交
21
            return new IDECachedDiagnosticGetter(this, solution, projectId, documentId, includeSuppressedDiagnostics).GetDiagnosticsAsync(cancellationToken);
H
Heejae Chang 已提交
22 23
        }

H
Heejae Chang 已提交
24
        public override Task<ImmutableArray<DiagnosticData>> GetSpecificDiagnosticsAsync(Solution solution, object id, bool includeSuppressedDiagnostics = false, CancellationToken cancellationToken = default(CancellationToken))
H
Heejae Chang 已提交
25
        {
H
Heejae Chang 已提交
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
            return new IDELatestDiagnosticGetter(this, solution, id, includeSuppressedDiagnostics).GetSpecificDiagnosticsAsync(cancellationToken);
        }

        public override Task<ImmutableArray<DiagnosticData>> GetDiagnosticsAsync(Solution solution, ProjectId projectId, DocumentId documentId, bool includeSuppressedDiagnostics = false, CancellationToken cancellationToken = default(CancellationToken))
        {
            return new IDELatestDiagnosticGetter(this, solution, projectId, documentId, includeSuppressedDiagnostics).GetDiagnosticsAsync(cancellationToken);
        }

        public override Task<ImmutableArray<DiagnosticData>> GetDiagnosticsForIdsAsync(Solution solution, ProjectId projectId, DocumentId documentId, ImmutableHashSet<string> diagnosticIds, bool includeSuppressedDiagnostics = false, CancellationToken cancellationToken = default(CancellationToken))
        {
            return new IDELatestDiagnosticGetter(this, diagnosticIds, solution, projectId, documentId, includeSuppressedDiagnostics).GetDiagnosticsAsync(cancellationToken);
        }

        public override Task<ImmutableArray<DiagnosticData>> GetProjectDiagnosticsForIdsAsync(Solution solution, ProjectId projectId, ImmutableHashSet<string> diagnosticIds, bool includeSuppressedDiagnostics = false, CancellationToken cancellationToken = default(CancellationToken))
        {
            return new IDELatestDiagnosticGetter(this, diagnosticIds, solution, projectId, includeSuppressedDiagnostics).GetProjectDiagnosticsAsync(cancellationToken);
        }

        private abstract class DiagnosticGetter
        {
            protected readonly DiagnosticIncrementalAnalyzer Owner;

H
Heejae Chang 已提交
48 49 50
            protected readonly Solution CurrentSolution;
            protected readonly ProjectId CurrentProjectId;
            protected readonly DocumentId CurrentDocumentId;
H
Heejae Chang 已提交
51 52 53 54 55 56 57 58 59 60 61 62
            protected readonly object Id;
            protected readonly bool IncludeSuppressedDiagnostics;

            private ImmutableArray<DiagnosticData>.Builder _builder;

            public DiagnosticGetter(
                DiagnosticIncrementalAnalyzer owner,
                Solution solution,
                ProjectId projectId,
                DocumentId documentId,
                object id,
                bool includeSuppressedDiagnostics)
H
Heejae Chang 已提交
63
            {
H
Heejae Chang 已提交
64
                Owner = owner;
H
Heejae Chang 已提交
65
                CurrentSolution = solution;
H
Heejae Chang 已提交
66

H
Heejae Chang 已提交
67 68
                CurrentDocumentId = documentId;
                CurrentProjectId = projectId;
H
Heejae Chang 已提交
69 70 71 72 73 74 75 76

                Id = id;
                IncludeSuppressedDiagnostics = includeSuppressedDiagnostics;

                // try to retrieve projectId/documentId from id if possible.
                var argsId = id as LiveDiagnosticUpdateArgsId;
                if (argsId != null)
                {
H
Heejae Chang 已提交
77 78
                    CurrentDocumentId = CurrentDocumentId ?? argsId.Key as DocumentId;
                    CurrentProjectId = CurrentProjectId ?? (argsId.Key as ProjectId) ?? CurrentDocumentId.ProjectId;
H
Heejae Chang 已提交
79 80 81
                }

                _builder = null;
H
Heejae Chang 已提交
82 83
            }

H
Heejae Chang 已提交
84 85
            protected StateManager StateManager => this.Owner._stateManager;

H
Heejae Chang 已提交
86 87
            protected Project CurrentProject => CurrentSolution.GetProject(CurrentProjectId);
            protected Document CurrentDocument => CurrentSolution.GetDocument(CurrentDocumentId);
H
Heejae Chang 已提交
88 89 90 91

            protected virtual bool ShouldIncludeDiagnostic(DiagnosticData diagnostic) => true;

            protected ImmutableArray<DiagnosticData> GetDiagnosticData()
H
Heejae Chang 已提交
92
            {
H
Heejae Chang 已提交
93
                return _builder != null ? _builder.ToImmutableArray() : ImmutableArray<DiagnosticData>.Empty;
H
Heejae Chang 已提交
94 95
            }

H
Heejae Chang 已提交
96 97
            protected abstract Task<ImmutableArray<DiagnosticData>?> GetDiagnosticsAsync(StateSet stateSet, Project project, DocumentId documentId, AnalysisKind kind, CancellationToken cancellationToken);
            protected abstract Task AppendDiagnosticsAsync(Project project, DocumentId targetDocumentId, IEnumerable<DocumentId> documentIds, CancellationToken cancellationToken);
H
Heejae Chang 已提交
98

H
Heejae Chang 已提交
99 100
            public async Task<ImmutableArray<DiagnosticData>> GetSpecificDiagnosticsAsync(CancellationToken cancellationToken)
            {
H
Heejae Chang 已提交
101
                if (CurrentSolution == null)
H
Heejae Chang 已提交
102 103 104 105 106 107 108 109 110 111
                {
                    return ImmutableArray<DiagnosticData>.Empty;
                }

                var argsId = Id as LiveDiagnosticUpdateArgsId;
                if (argsId == null)
                {
                    return ImmutableArray<DiagnosticData>.Empty;
                }

H
Heejae Chang 已提交
112
                if (CurrentProject == null)
H
Heejae Chang 已提交
113 114 115 116 117
                {
                    // when we return cached result, make sure we at least return something that exist in current solution
                    return ImmutableArray<DiagnosticData>.Empty;
                }

H
Heejae Chang 已提交
118
                var stateSet = this.StateManager.GetOrCreateStateSet(CurrentProject, argsId.Analyzer);
H
Heejae Chang 已提交
119 120 121 122 123
                if (stateSet == null)
                {
                    return ImmutableArray<DiagnosticData>.Empty;
                }

H
Heejae Chang 已提交
124
                var diagnostics = await GetDiagnosticsAsync(stateSet, CurrentProject, CurrentDocumentId, (AnalysisKind)argsId.Kind, cancellationToken).ConfigureAwait(false);
H
Heejae Chang 已提交
125 126 127 128 129 130 131 132 133 134
                if (diagnostics == null)
                {
                    // Document or project might have been removed from the solution.
                    return ImmutableArray<DiagnosticData>.Empty;
                }

                return FilterSuppressedDiagnostics(diagnostics.Value);
            }

            public async Task<ImmutableArray<DiagnosticData>> GetDiagnosticsAsync(CancellationToken cancellationToken)
H
Heejae Chang 已提交
135
            {
H
Heejae Chang 已提交
136
                if (CurrentSolution == null)
H
Heejae Chang 已提交
137 138 139 140
                {
                    return ImmutableArray<DiagnosticData>.Empty;
                }

H
Heejae Chang 已提交
141
                if (CurrentProjectId != null)
H
Heejae Chang 已提交
142
                {
H
Heejae Chang 已提交
143
                    if (CurrentProject == null)
H
Heejae Chang 已提交
144 145 146 147
                    {
                        return GetDiagnosticData();
                    }

H
Heejae Chang 已提交
148
                    var documentIds = CurrentDocumentId != null ? SpecializedCollections.SingletonEnumerable(CurrentDocumentId) : CurrentProject.DocumentIds;
H
Heejae Chang 已提交
149 150

                    // return diagnostics specific to one project or document
H
Heejae Chang 已提交
151
                    await AppendDiagnosticsAsync(CurrentProject, CurrentDocumentId, documentIds, cancellationToken).ConfigureAwait(false);
H
Heejae Chang 已提交
152 153 154
                    return GetDiagnosticData();
                }

H
Heejae Chang 已提交
155
                await AppendDiagnosticsAsync(CurrentSolution, cancellationToken).ConfigureAwait(false);
H
Heejae Chang 已提交
156
                return GetDiagnosticData();
H
Heejae Chang 已提交
157 158
            }

H
Heejae Chang 已提交
159
            protected async Task AppendDiagnosticsAsync(Solution solution, CancellationToken cancellationToken)
H
Heejae Chang 已提交
160
            {
H
Heejae Chang 已提交
161 162
                // PERF: should run this concurrently? analyzer driver itself is already running concurrently.
                DocumentId nullTargetDocumentId = null;
163 164 165

                var tasks = new Task[solution.ProjectIds.Count];
                var index = 0;
H
Heejae Chang 已提交
166
                foreach (var project in solution.Projects)
H
Heejae Chang 已提交
167
                {
168 169 170 171
                    var localProject = project;
                    tasks[index++] = Task.Run(
                        () => AppendDiagnosticsAsync(
                            localProject, nullTargetDocumentId, localProject.DocumentIds, cancellationToken: cancellationToken), cancellationToken);
H
Heejae Chang 已提交
172
                }
173 174

                await Task.WhenAll(tasks).ConfigureAwait(false);
H
Heejae Chang 已提交
175 176
            }

H
Heejae Chang 已提交
177
            protected void AppendDiagnostics(IEnumerable<DiagnosticData> items)
H
Heejae Chang 已提交
178
            {
H
Heejae Chang 已提交
179 180 181 182 183 184 185 186 187 188 189 190 191 192
                if (items == null)
                {
                    return;
                }

                if (_builder == null)
                {
                    Interlocked.CompareExchange(ref _builder, ImmutableArray.CreateBuilder<DiagnosticData>(), null);
                }

                lock (_builder)
                {
                    _builder.AddRange(items.Where(ShouldIncludeSuppressedDiagnostic).Where(ShouldIncludeDiagnostic));
                }
H
Heejae Chang 已提交
193 194
            }

H
Heejae Chang 已提交
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
            private bool ShouldIncludeSuppressedDiagnostic(DiagnosticData diagnostic)
            {
                return IncludeSuppressedDiagnostics || !diagnostic.IsSuppressed;
            }

            private ImmutableArray<DiagnosticData> FilterSuppressedDiagnostics(ImmutableArray<DiagnosticData> diagnostics)
            {
                if (IncludeSuppressedDiagnostics || diagnostics.IsDefaultOrEmpty)
                {
                    return diagnostics;
                }

                // create builder only if there is suppressed diagnostics
                ImmutableArray<DiagnosticData>.Builder builder = null;
                for (int i = 0; i < diagnostics.Length; i++)
                {
                    var diagnostic = diagnostics[i];
                    if (diagnostic.IsSuppressed)
                    {
                        if (builder == null)
                        {
                            builder = ImmutableArray.CreateBuilder<DiagnosticData>();
                            for (int j = 0; j < i; j++)
                            {
                                builder.Add(diagnostics[j]);
                            }
                        }
                    }
                    else if (builder != null)
                    {
                        builder.Add(diagnostic);
                    }
                }

                return builder != null ? builder.ToImmutable() : diagnostics;
            }
H
Heejae Chang 已提交
231 232
        }

H
Heejae Chang 已提交
233
        private class IDECachedDiagnosticGetter : DiagnosticGetter
H
Heejae Chang 已提交
234
        {
H
Heejae Chang 已提交
235 236 237 238 239 240 241 242 243 244 245 246 247
            public IDECachedDiagnosticGetter(DiagnosticIncrementalAnalyzer owner, Solution solution, object id, bool includeSuppressedDiagnostics) :
                base(owner, solution, projectId: null, documentId: null, id: id, includeSuppressedDiagnostics: includeSuppressedDiagnostics)
            {
            }

            public IDECachedDiagnosticGetter(DiagnosticIncrementalAnalyzer owner, Solution solution, ProjectId projectId, DocumentId documentId, bool includeSuppressedDiagnostics) :
                base(owner, solution, projectId, documentId, id: null, includeSuppressedDiagnostics: includeSuppressedDiagnostics)
            {
            }

            protected override async Task AppendDiagnosticsAsync(Project project, DocumentId targetDocumentId, IEnumerable<DocumentId> documentIds, CancellationToken cancellationToken)
            {
                // when we return cached result, make sure we at least return something that exist in current solution
H
Heejae Chang 已提交
248
                if (project == null)
H
Heejae Chang 已提交
249 250 251 252
                {
                    return;
                }

H
Heejae Chang 已提交
253
                foreach (var stateSet in StateManager.GetStateSets(project.Id))
H
Heejae Chang 已提交
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
                {
                    foreach (var documentId in documentIds)
                    {
                        AppendDiagnostics(await GetDiagnosticsAsync(stateSet, project, documentId, AnalysisKind.Syntax, cancellationToken).ConfigureAwait(false));
                        AppendDiagnostics(await GetDiagnosticsAsync(stateSet, project, documentId, AnalysisKind.Semantic, cancellationToken).ConfigureAwait(false));
                        AppendDiagnostics(await GetDiagnosticsAsync(stateSet, project, documentId, AnalysisKind.NonLocal, cancellationToken).ConfigureAwait(false));
                    }

                    if (targetDocumentId == null)
                    {
                        // include project diagnostics if there is no target document
                        AppendDiagnostics(await GetProjectDiagnosticsAsync(stateSet, project, targetDocumentId, AnalysisKind.NonLocal, cancellationToken).ConfigureAwait(false));
                    }
                }
            }

            protected override async Task<ImmutableArray<DiagnosticData>?> GetDiagnosticsAsync(StateSet stateSet, Project project, DocumentId documentId, AnalysisKind kind, CancellationToken cancellationToken)
            {
                cancellationToken.ThrowIfCancellationRequested();

                var activeFileDiagnostics = GetActiveFileDiagnostics(stateSet, documentId, kind);
                if (activeFileDiagnostics.HasValue)
                {
                    return activeFileDiagnostics.Value;
                }

                var projectDiagnostics = await GetProjectDiagnosticsAsync(stateSet, project, documentId, kind, cancellationToken).ConfigureAwait(false);
                if (projectDiagnostics.HasValue)
                {
                    return projectDiagnostics.Value;
                }

                return null;
            }

            private ImmutableArray<DiagnosticData>? GetActiveFileDiagnostics(StateSet stateSet, DocumentId documentId, AnalysisKind kind)
            {
H
Heejae Chang 已提交
291
                if (documentId == null || kind == AnalysisKind.NonLocal)
H
Heejae Chang 已提交
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317
                {
                    return null;
                }

                ActiveFileState state;
                if (!stateSet.TryGetActiveFileState(documentId, out state))
                {
                    return null;
                }

                return state.GetAnalysisData(kind).Items;
            }

            private async Task<ImmutableArray<DiagnosticData>?> GetProjectDiagnosticsAsync(
                StateSet stateSet, Project project, DocumentId documentId, AnalysisKind kind, CancellationToken cancellationToken)
            {
                ProjectState state;
                if (!stateSet.TryGetProjectState(project.Id, out state))
                {
                    // never analyzed this project yet.
                    return null;
                }

                if (documentId != null)
                {
                    // file doesn't exist in current solution
H
Heejae Chang 已提交
318
                    var document = project.Solution.GetDocument(documentId);
H
Heejae Chang 已提交
319 320 321 322 323 324 325 326 327 328 329 330 331
                    if (document == null)
                    {
                        return null;
                    }

                    var result = await state.GetAnalysisDataAsync(document, avoidLoadingData: false, cancellationToken: cancellationToken).ConfigureAwait(false);
                    return GetResult(result, kind, documentId);
                }

                Contract.ThrowIfFalse(kind == AnalysisKind.NonLocal);
                var nonLocalResult = await state.GetProjectAnalysisDataAsync(project, avoidLoadingData: false, cancellationToken: cancellationToken).ConfigureAwait(false);
                return nonLocalResult.Others;
            }
H
Heejae Chang 已提交
332 333
        }

H
Heejae Chang 已提交
334
        private class IDELatestDiagnosticGetter : DiagnosticGetter
H
Heejae Chang 已提交
335
        {
H
Heejae Chang 已提交
336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362
            private readonly ImmutableHashSet<string> _diagnosticIds;

            public IDELatestDiagnosticGetter(DiagnosticIncrementalAnalyzer owner, Solution solution, object id, bool includeSuppressedDiagnostics) :
                base(owner, solution, projectId: null, documentId: null, id: id, includeSuppressedDiagnostics: includeSuppressedDiagnostics)
            {
                _diagnosticIds = null;
            }

            public IDELatestDiagnosticGetter(DiagnosticIncrementalAnalyzer owner, Solution solution, ProjectId projectId, DocumentId documentId, bool includeSuppressedDiagnostics) :
                base(owner, solution, projectId, documentId, id: null, includeSuppressedDiagnostics: includeSuppressedDiagnostics)
            {
                _diagnosticIds = null;
            }

            public IDELatestDiagnosticGetter(DiagnosticIncrementalAnalyzer owner, ImmutableHashSet<string> diagnosticIds, Solution solution, ProjectId projectId, bool includeSuppressedDiagnostics) :
                this(owner, diagnosticIds, solution, projectId, documentId: null, includeSuppressedDiagnostics: includeSuppressedDiagnostics)
            {
            }

            public IDELatestDiagnosticGetter(DiagnosticIncrementalAnalyzer owner, ImmutableHashSet<string> diagnosticIds, Solution solution, ProjectId projectId, DocumentId documentId, bool includeSuppressedDiagnostics) :
                base(owner, solution, projectId, documentId, id: null, includeSuppressedDiagnostics: includeSuppressedDiagnostics)
            {
                _diagnosticIds = diagnosticIds;
            }

            public async Task<ImmutableArray<DiagnosticData>> GetProjectDiagnosticsAsync(CancellationToken cancellationToken)
            {
H
Heejae Chang 已提交
363
                if (CurrentSolution == null)
H
Heejae Chang 已提交
364 365 366 367 368 369
                {
                    return GetDiagnosticData();
                }

                DocumentId nullTargetDocumentId = null;

H
Heejae Chang 已提交
370
                if (CurrentProjectId != null)
H
Heejae Chang 已提交
371
                {
H
Heejae Chang 已提交
372
                    await AppendDiagnosticsAsync(CurrentProject, nullTargetDocumentId, SpecializedCollections.EmptyEnumerable<DocumentId>(), cancellationToken).ConfigureAwait(false);
H
Heejae Chang 已提交
373 374 375
                    return GetDiagnosticData();
                }

H
Heejae Chang 已提交
376
                await AppendDiagnosticsAsync(CurrentSolution, cancellationToken).ConfigureAwait(false);
H
Heejae Chang 已提交
377 378 379 380 381 382 383 384 385 386 387
                return GetDiagnosticData();
            }

            protected override bool ShouldIncludeDiagnostic(DiagnosticData diagnostic)
            {
                return _diagnosticIds == null || _diagnosticIds.Contains(diagnostic.Id);
            }

            protected override async Task AppendDiagnosticsAsync(Project project, DocumentId targetDocumentId, IEnumerable<DocumentId> documentIds, CancellationToken cancellationToken)
            {
                // when we return cached result, make sure we at least return something that exist in current solution
H
Heejae Chang 已提交
388
                if (project == null)
H
Heejae Chang 已提交
389 390 391 392 393 394 395 396
                {
                    return;
                }

                // get analyzers that are not suppressed.
                // REVIEW: IsAnalyzerSuppressed call seems can be quite expensive in certain condition. is there any other way to do this?
                var stateSets = StateManager.GetOrCreateStateSets(project).Where(s => ShouldIncludeStateSet(project, s)).ToImmutableArrayOrEmpty();

397
                var analyzerDriverOpt = await Owner._compilationManager.CreateAnalyzerDriverAsync(project, stateSets, IncludeSuppressedDiagnostics, cancellationToken).ConfigureAwait(false);
H
Heejae Chang 已提交
398

H
Heejae Chang 已提交
399
                var result = await Owner._executor.GetProjectAnalysisDataAsync(analyzerDriverOpt, project, stateSets, cancellationToken).ConfigureAwait(false);
H
Heejae Chang 已提交
400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441

                foreach (var stateSet in stateSets)
                {
                    var analysisResult = result.GetResult(stateSet.Analyzer);

                    foreach (var documentId in documentIds)
                    {
                        AppendDiagnostics(GetResult(analysisResult, AnalysisKind.Syntax, documentId));
                        AppendDiagnostics(GetResult(analysisResult, AnalysisKind.Semantic, documentId));
                        AppendDiagnostics(GetResult(analysisResult, AnalysisKind.NonLocal, documentId));
                    }

                    if (targetDocumentId == null)
                    {
                        // include project diagnostics if there is no target document
                        AppendDiagnostics(analysisResult.Others);
                    }
                }
            }

            private bool ShouldIncludeStateSet(Project project, StateSet stateSet)
            {
                // REVIEW: this can be expensive. any way to do this cheaper?
                var diagnosticService = Owner.Owner;
                if (diagnosticService.IsAnalyzerSuppressed(stateSet.Analyzer, project))
                {
                    return false;
                }

                if (_diagnosticIds != null && diagnosticService.GetDiagnosticDescriptors(stateSet.Analyzer).All(d => !_diagnosticIds.Contains(d.Id)))
                {
                    return false;
                }

                return true;
            }

            protected override async Task<ImmutableArray<DiagnosticData>?> GetDiagnosticsAsync(StateSet stateSet, Project project, DocumentId documentId, AnalysisKind kind, CancellationToken cancellationToken)
            {
                cancellationToken.ThrowIfCancellationRequested();

                var stateSets = SpecializedCollections.SingletonCollection(stateSet);
442
                var analyzerDriverOpt = await Owner._compilationManager.CreateAnalyzerDriverAsync(project, stateSets, IncludeSuppressedDiagnostics, cancellationToken).ConfigureAwait(false);
H
Heejae Chang 已提交
443 444 445

                if (documentId != null)
                {
H
Heejae Chang 已提交
446
                    var document = project.Solution.GetDocument(documentId);
H
Heejae Chang 已提交
447 448 449 450 451 452 453
                    Contract.ThrowIfNull(document);

                    switch (kind)
                    {
                        case AnalysisKind.Syntax:
                        case AnalysisKind.Semantic:
                            {
H
Heejae Chang 已提交
454
                                var result = await Owner._executor.GetDocumentAnalysisDataAsync(analyzerDriverOpt, document, stateSet, kind, cancellationToken).ConfigureAwait(false);
H
Heejae Chang 已提交
455 456 457 458
                                return result.Items;
                            }
                        case AnalysisKind.NonLocal:
                            {
H
Heejae Chang 已提交
459
                                var nonLocalDocumentResult = await Owner._executor.GetProjectAnalysisDataAsync(analyzerDriverOpt, project, stateSets, cancellationToken).ConfigureAwait(false);
H
Heejae Chang 已提交
460 461 462 463 464 465 466 467 468
                                var analysisResult = nonLocalDocumentResult.GetResult(stateSet.Analyzer);
                                return GetResult(analysisResult, AnalysisKind.NonLocal, documentId);
                            }
                        default:
                            return Contract.FailWithReturn<ImmutableArray<DiagnosticData>?>("shouldn't reach here");
                    }
                }

                Contract.ThrowIfFalse(kind == AnalysisKind.NonLocal);
H
Heejae Chang 已提交
469
                var projectResult = await Owner._executor.GetProjectAnalysisDataAsync(analyzerDriverOpt, project, stateSets, cancellationToken).ConfigureAwait(false);
H
Heejae Chang 已提交
470 471
                return projectResult.GetResult(stateSet.Analyzer).Others;
            }
H
Heejae Chang 已提交
472 473 474
        }
    }
}