diff --git a/.editorconfig b/.editorconfig index 4d71709247d6fa7fe48b897193092d0effa362be..48fd8a1348fd388d341cdbd58d034dbb4dee2894 100644 --- a/.editorconfig +++ b/.editorconfig @@ -231,6 +231,8 @@ dotnet_diagnostic.IDE0005.severity = warning # IDE0011: Add braces csharp_prefer_braces = when_multiline:warning +# NOTE: We need the below severity entry for Add Braces due to https://github.com/dotnet/roslyn/issues/44201 +dotnet_diagnostic.IDE0011.severity = warning # IDE0035: Remove unreachable code dotnet_diagnostic.IDE0035.severity = warning diff --git a/src/Compilers/CSharp/CSharpAnalyzerDriver/CSharpDeclarationComputer.cs b/src/Compilers/CSharp/CSharpAnalyzerDriver/CSharpDeclarationComputer.cs index b930a860512b701bffae79d5a523f5ce65499aa9..369a958180fc9adcd484f1017cc0509442af5f5a 100644 --- a/src/Compilers/CSharp/CSharpAnalyzerDriver/CSharpDeclarationComputer.cs +++ b/src/Compilers/CSharp/CSharpAnalyzerDriver/CSharpDeclarationComputer.cs @@ -72,7 +72,11 @@ private static bool InvalidLevel(int? level) case SyntaxKind.NamespaceDeclaration: { var ns = (NamespaceDeclarationSyntax)node; - foreach (var decl in ns.Members) ComputeDeclarations(model, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken); + foreach (var decl in ns.Members) + { + ComputeDeclarations(model, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken); + } + var declInfo = GetDeclarationInfo(model, node, getSymbol, cancellationToken); builder.Add(declInfo); @@ -94,7 +98,11 @@ private static bool InvalidLevel(int? level) case SyntaxKind.InterfaceDeclaration: { var t = (TypeDeclarationSyntax)node; - foreach (var decl in t.Members) ComputeDeclarations(model, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken); + foreach (var decl in t.Members) + { + ComputeDeclarations(model, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken); + } + var attributes = GetAttributes(t.AttributeLists).Concat(GetTypeParameterListAttributes(t.TypeParameterList)); builder.Add(GetDeclarationInfo(model, node, getSymbol, attributes, cancellationToken)); return; @@ -103,7 +111,11 @@ private static bool InvalidLevel(int? level) case SyntaxKind.EnumDeclaration: { var t = (EnumDeclarationSyntax)node; - foreach (var decl in t.Members) ComputeDeclarations(model, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken); + foreach (var decl in t.Members) + { + ComputeDeclarations(model, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken); + } + var attributes = GetAttributes(t.AttributeLists); builder.Add(GetDeclarationInfo(model, node, getSymbol, attributes, cancellationToken)); return; @@ -133,7 +145,10 @@ private static bool InvalidLevel(int? level) var t = (EventDeclarationSyntax)node; if (t.AccessorList != null) { - foreach (var decl in t.AccessorList.Accessors) ComputeDeclarations(model, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken); + foreach (var decl in t.AccessorList.Accessors) + { + ComputeDeclarations(model, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken); + } } var attributes = GetAttributes(t.AttributeLists); builder.Add(GetDeclarationInfo(model, node, getSymbol, attributes, cancellationToken)); @@ -170,7 +185,10 @@ private static bool InvalidLevel(int? level) var t = (PropertyDeclarationSyntax)node; if (t.AccessorList != null) { - foreach (var decl in t.AccessorList.Accessors) ComputeDeclarations(model, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken); + foreach (var decl in t.AccessorList.Accessors) + { + ComputeDeclarations(model, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken); + } } if (t.ExpressionBody != null) @@ -259,7 +277,10 @@ private static bool InvalidLevel(int? level) case SyntaxKind.CompilationUnit: { var t = (CompilationUnitSyntax)node; - foreach (var decl in t.Members) ComputeDeclarations(model, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken); + foreach (var decl in t.Members) + { + ComputeDeclarations(model, decl, shouldSkip, getSymbol, builder, newLevel, cancellationToken); + } if (t.AttributeLists.Any()) { diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/DefiniteAssignment.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/DefiniteAssignment.cs index 9777e930a58cff878bc6d0563ed23b27c847f3f2..8a016b98fbfe436b45f9051733f08a23b540e1ce 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/DefiniteAssignment.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/DefiniteAssignment.cs @@ -1879,6 +1879,7 @@ public override BoundNode VisitAddressOfOperator(BoundAddressOfOperator node) return null; } +#nullable enable protected override void WriteArgument(BoundExpression arg, RefKind refKind, MethodSymbol method) { if (refKind == RefKind.Ref) @@ -1895,11 +1896,12 @@ protected override void WriteArgument(BoundExpression arg, RefKind refKind, Meth // we assume that external method may write and/or read all of its fields (recursively). // Strangely, the native compiler requires the "ref", even for reference types, to exhibit // this behavior. - if (refKind != RefKind.None && ((object)method == null || method.IsExtern)) + if (refKind != RefKind.None && ((object)method == null || method.IsExtern) && arg.Type is TypeSymbol type) { - MarkFieldsUsed(arg.Type); + MarkFieldsUsed(type); } } +#nullable restore protected void CheckAssigned(BoundExpression expr, SyntaxNode node) { @@ -1936,6 +1938,7 @@ protected void CheckAssigned(BoundExpression expr, SyntaxNode node) } } +#nullable enable private void MarkFieldsUsed(TypeSymbol type) { switch (type.TypeKind) @@ -1951,9 +1954,7 @@ private void MarkFieldsUsed(TypeSymbol type) return; } - var namedType = (NamedTypeSymbol)type; - var assembly = type.ContainingAssembly as SourceAssemblySymbol; - if ((object)assembly == null) + if (!(type.ContainingAssembly is SourceAssemblySymbol assembly)) { return; // could be retargeting assembly } @@ -1961,6 +1962,7 @@ private void MarkFieldsUsed(TypeSymbol type) var seen = assembly.TypesReferencedInExternalMethods; if (seen.Add(type)) { + var namedType = (NamedTypeSymbol)type; foreach (var symbol in namedType.GetMembersUnordered()) { if (symbol.Kind != SymbolKind.Field) @@ -1976,6 +1978,7 @@ private void MarkFieldsUsed(TypeSymbol type) return; } } +#nullable restore public override BoundNode VisitBaseReference(BoundBaseReference node) { diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/RefLocalsAndReturnsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/RefLocalsAndReturnsTests.cs index 3f013fea47d8052d90761f05b5b33989e88da34c..6afe8b1dc881bfb12f0b969a658effd83861820b 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/RefLocalsAndReturnsTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/RefLocalsAndReturnsTests.cs @@ -990,6 +990,19 @@ void M() Diagnostic(ErrorCode.ERR_RefLocalOrParamExpected, "P").WithLocation(8, 9)); } + [Fact, WorkItem(44153, "https://github.com/dotnet/roslyn/issues/44153")] + public void RefErrorProperty() + { + CreateCompilation(@" +public class C { + public ref ERROR Prop => throw null!; +} +").VerifyEmitDiagnostics( + // (3,16): error CS0246: The type or namespace name 'ERROR' could not be found (are you missing a using directive or an assembly reference?) + // public ref ERROR Prop => throw null!; + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "ERROR").WithArguments("ERROR").WithLocation(3, 16)); + } + [Fact] public void RefReadonlyOnlyIn72() { diff --git a/src/EditorFeatures/Core/FindUsages/IRemoteFindUsagesService.cs b/src/EditorFeatures/Core/FindUsages/IRemoteFindUsagesService.cs index 58dbfc471bcf7abd88b53337cee57413c52b9c1a..01fb1dcb8c309574eb7684ccf6b1c544fb07ea68 100644 --- a/src/EditorFeatures/Core/FindUsages/IRemoteFindUsagesService.cs +++ b/src/EditorFeatures/Core/FindUsages/IRemoteFindUsagesService.cs @@ -163,7 +163,7 @@ internal class SerializableSourceReferenceItem { public int DefinitionId; public SerializableDocumentSpan SourceSpan; - public SymbolUsageInfo SymbolUsageInfo; + public SerializableSymbolUsageInfo SymbolUsageInfo; public (string Key, string Value)[] AdditionalProperties; public static SerializableSourceReferenceItem Dehydrate( @@ -173,7 +173,7 @@ internal class SerializableSourceReferenceItem { DefinitionId = definitionId, SourceSpan = SerializableDocumentSpan.Dehydrate(item.SourceSpan), - SymbolUsageInfo = item.SymbolUsageInfo, + SymbolUsageInfo = SerializableSymbolUsageInfo.Dehydrate(item.SymbolUsageInfo), AdditionalProperties = item.AdditionalProperties.Select(kvp => (kvp.Key, kvp.Value)).ToArray(), }; } @@ -183,7 +183,7 @@ public SourceReferenceItem Rehydrate(Solution solution, DefinitionItem definitio return new SourceReferenceItem( definition, SourceSpan.Rehydrate(solution), - SymbolUsageInfo, + SymbolUsageInfo.Rehydrate(), AdditionalProperties.ToImmutableDictionary(t => t.Key, t => t.Value)); } } diff --git a/src/Features/CSharp/Portable/ConvertLinq/CSharpConvertLinqQueryToForEachProvider.cs b/src/Features/CSharp/Portable/ConvertLinq/CSharpConvertLinqQueryToForEachProvider.cs index 70843bcef93367377433becd0af27cdf32576b0c..c2c5c7e55dfd3c1ef1c15729ac60ef2d0b16b382 100644 --- a/src/Features/CSharp/Portable/ConvertLinq/CSharpConvertLinqQueryToForEachProvider.cs +++ b/src/Features/CSharp/Portable/ConvertLinq/CSharpConvertLinqQueryToForEachProvider.cs @@ -98,8 +98,10 @@ public bool TryConvert(out DocumentUpdateInfo documentUpdateInfo) { if (!documentUpdateInfo.Source.IsParentKind(SyntaxKind.Block) && documentUpdateInfo.Destinations.Length > 1) - + { documentUpdateInfo = new DocumentUpdateInfo(documentUpdateInfo.Source, SyntaxFactory.Block(documentUpdateInfo.Destinations)); + } + return true; } diff --git a/src/Features/CSharp/Portable/DisambiguateSameVariable/CSharpDisambiguateSameVariableCodeFixProvider.cs b/src/Features/CSharp/Portable/DisambiguateSameVariable/CSharpDisambiguateSameVariableCodeFixProvider.cs index 374a18fb62e53c375e5af26538a8b5653d98f8a8..a26952fcbfaf0c94e813a540a2a574c760b64ba0 100644 --- a/src/Features/CSharp/Portable/DisambiguateSameVariable/CSharpDisambiguateSameVariableCodeFixProvider.cs +++ b/src/Features/CSharp/Portable/DisambiguateSameVariable/CSharpDisambiguateSameVariableCodeFixProvider.cs @@ -155,7 +155,9 @@ where m.IsAccessibleWithin(enclosingType) { if (!CanFix(semanticModel, diagnostic, cancellationToken, out var nameNode, out var matchingMember, out _)) + { continue; + } var newNameNode = matchingMember.Name.ToIdentifierName(); var newExpr = (ExpressionSyntax)newNameNode; diff --git a/src/Features/CSharp/Portable/IntroduceVariable/CSharpIntroduceVariableService_IntroduceLocal.cs b/src/Features/CSharp/Portable/IntroduceVariable/CSharpIntroduceVariableService_IntroduceLocal.cs index 5d24c1e094fdfef03b025396c00e3a9819c8418b..6ce0acb981c169b366f26566efa888a87d670598 100644 --- a/src/Features/CSharp/Portable/IntroduceVariable/CSharpIntroduceVariableService_IntroduceLocal.cs +++ b/src/Features/CSharp/Portable/IntroduceVariable/CSharpIntroduceVariableService_IntroduceLocal.cs @@ -419,8 +419,10 @@ private int GetFirstStatementAffectedIndex(SyntaxNode innermostCommonBlock, ISet var nextStatementLeading = nextStatement.GetLeadingTrivia(); var precedingEndOfLine = nextStatementLeading.LastOrDefault(t => t.Kind() == SyntaxKind.EndOfLineTrivia); if (precedingEndOfLine == default) + { return oldStatements.ReplaceRange( nextStatement, new[] { newStatement, nextStatement }); + } var endOfLineIndex = nextStatementLeading.IndexOf(precedingEndOfLine) + 1; diff --git a/src/Features/CSharp/Portable/ReverseForStatement/CSharpReverseForStatementCodeRefactoringProvider.cs b/src/Features/CSharp/Portable/ReverseForStatement/CSharpReverseForStatementCodeRefactoringProvider.cs index 20390a88919c5424470b38783c7dc1d6cb18987d..dd06b42fb65b9a8f9dccb79bdd2174fc2f2fb19d 100644 --- a/src/Features/CSharp/Portable/ReverseForStatement/CSharpReverseForStatementCodeRefactoringProvider.cs +++ b/src/Features/CSharp/Portable/ReverseForStatement/CSharpReverseForStatementCodeRefactoringProvider.cs @@ -53,7 +53,9 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte if (declaration == null || declaration.Variables.Count != 1 || forStatement.Incrementors.Count != 1) + { return; + } var variable = declaration.Variables[0]; var after = forStatement.Incrementors[0]; diff --git a/src/Features/Core/Portable/ConflictMarkerResolution/AbstractConflictMarkerCodeFixProvider.cs b/src/Features/Core/Portable/ConflictMarkerResolution/AbstractConflictMarkerCodeFixProvider.cs index eebe4a0a83f1f937873dc962fefd975aff188df8..920e1f741ca6ded9ed879eb5f11a7bbd1ce6664e 100644 --- a/src/Features/Core/Portable/ConflictMarkerResolution/AbstractConflictMarkerCodeFixProvider.cs +++ b/src/Features/Core/Portable/ConflictMarkerResolution/AbstractConflictMarkerCodeFixProvider.cs @@ -93,7 +93,9 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) // issue there. if (startTrivia.RawKind == _syntaxKinds.ConflictMarkerTrivia || middleTrivia.RawKind == _syntaxKinds.ConflictMarkerTrivia) + { return false; + } } return true; diff --git a/src/Features/Core/Portable/Diagnostics/DiagnosticAnalyzerService.cs b/src/Features/Core/Portable/Diagnostics/DiagnosticAnalyzerService.cs index 87ae59a11961d2315ed3043a50206178c2149c32..d0b1593c678c2eaedc1a184135dc00aecc282738 100644 --- a/src/Features/Core/Portable/Diagnostics/DiagnosticAnalyzerService.cs +++ b/src/Features/Core/Portable/Diagnostics/DiagnosticAnalyzerService.cs @@ -131,7 +131,7 @@ public Task> GetDiagnosticsAsync(Solution solutio return SpecializedTasks.EmptyImmutableArray(); } - public async Task ForceAnalyzeAsync(Solution solution, ProjectId? projectId = null, CancellationToken cancellationToken = default) + public async Task ForceAnalyzeAsync(Solution solution, Action onProjectAnalyzed, ProjectId? projectId = null, CancellationToken cancellationToken = default) { if (_map.TryGetValue(solution.Workspace, out var analyzer)) { @@ -141,6 +141,7 @@ public async Task ForceAnalyzeAsync(Solution solution, ProjectId? projectId = nu if (project != null) { await analyzer.ForceAnalyzeProjectAsync(project, cancellationToken).ConfigureAwait(false); + onProjectAnalyzed(project); } } else @@ -149,8 +150,11 @@ public async Task ForceAnalyzeAsync(Solution solution, ProjectId? projectId = nu var index = 0; foreach (var project in solution.Projects) { - tasks[index++] = Task.Run( - () => analyzer.ForceAnalyzeProjectAsync(project, cancellationToken)); + tasks[index++] = Task.Run(async () => + { + await analyzer.ForceAnalyzeProjectAsync(project, cancellationToken).ConfigureAwait(false); + onProjectAnalyzed(project); + }); } await Task.WhenAll(tasks).ConfigureAwait(false); diff --git a/src/Features/Core/Portable/Diagnostics/IDiagnosticAnalyzerService.cs b/src/Features/Core/Portable/Diagnostics/IDiagnosticAnalyzerService.cs index af93211a5910adf13d8996c4ab6f73e29d8ae1fb..497ed10b6b4d3bd8fed5b7c527574e14ce67cff8 100644 --- a/src/Features/Core/Portable/Diagnostics/IDiagnosticAnalyzerService.cs +++ b/src/Features/Core/Portable/Diagnostics/IDiagnosticAnalyzerService.cs @@ -43,7 +43,7 @@ internal interface IDiagnosticAnalyzerService /// /// Force computes diagnostics and raises diagnostic events for the given project or solution. all diagnostics returned should be up-to-date with respect to the given project or solution. /// - Task ForceAnalyzeAsync(Solution solution, ProjectId? projectId = null, CancellationToken cancellationToken = default); + Task ForceAnalyzeAsync(Solution solution, Action onProjectAnalyzed, ProjectId? projectId = null, CancellationToken cancellationToken = default); /// /// True if given project has any diagnostics diff --git a/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/RegexCharClass.cs b/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/RegexCharClass.cs index 1aecfdc775cf4f7c729b8c4a44e755602f4f8c91..22959a36a667d8f525aa1ce8daa69164667aed41 100644 --- a/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/RegexCharClass.cs +++ b/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions/RegexCharClass.cs @@ -269,7 +269,9 @@ private static bool CharInClassInternal(char ch, string set, int start, int mySe // reverse this check. Debug.Assert((SETSTART & 0x1) == 1, "If SETSTART is not odd, the calculation below this will be reversed"); if ((min & 0x1) == (start & 0x1)) + { return true; + } else { if (myCategoryLength == 0) @@ -302,7 +304,9 @@ private static bool CharInCategory(char ch, string set, int start, int mySetLeng if (curcat == SpaceConst) { if (char.IsWhiteSpace(ch)) + { return true; + } else { i++; @@ -320,7 +324,9 @@ private static bool CharInCategory(char ch, string set, int start, int mySetLeng if (curcat == NotSpaceConst) { if (!char.IsWhiteSpace(ch)) + { return true; + } else { i++; diff --git a/src/VisualStudio/Core/Def/Implementation/Diagnostics/VisualStudioDiagnosticAnalyzerService.cs b/src/VisualStudio/Core/Def/Implementation/Diagnostics/VisualStudioDiagnosticAnalyzerService.cs index b90aeffad7aadaf6b87a78f2e1ee5414088f45dc..073c30c9f4765f1f17ecdad5f46521e550397a61 100644 --- a/src/VisualStudio/Core/Def/Implementation/Diagnostics/VisualStudioDiagnosticAnalyzerService.cs +++ b/src/VisualStudio/Core/Def/Implementation/Diagnostics/VisualStudioDiagnosticAnalyzerService.cs @@ -199,29 +199,30 @@ public void RunAnalyzers(IVsHierarchy? hierarchy) string? projectOrSolutionName = project?.Name ?? PathUtilities.GetFileName(solution.FilePath); // Add a message to VS status bar that we are running code analysis. - var statusMessage = projectOrSolutionName != null - ? string.Format(ServicesVSResources.Running_code_analysis_for_0, projectOrSolutionName) - : ServicesVSResources.Running_code_analysis_for_Solution; var statusBar = _serviceProvider?.GetService(typeof(SVsStatusbar)) as IVsStatusbar; - statusBar?.SetText(statusMessage); + var totalProjectCount = project != null ? 1 : (uint)solution.ProjectIds.Count; + var statusBarUpdater = statusBar != null ? + new StatusBarUpdater(statusBar, _threadingContext, projectOrSolutionName, totalProjectCount) : + null; // Force complete analyzer execution in background. var asyncToken = _listener.BeginAsyncOperation($"{nameof(VisualStudioDiagnosticAnalyzerService)}_{nameof(RunAnalyzers)}"); Task.Run(async () => { - await _diagnosticService.ForceAnalyzeAsync(solution, project?.Id, CancellationToken.None).ConfigureAwait(false); - - // If user has disabled live analyzer execution for any project(s), i.e. set RunAnalyzersDuringLiveAnalysis = false, - // then ForceAnalyzeAsync will not cause analyzers to execute. - // We explicitly fetch diagnostics for such projects and report these as "Host" diagnostics. - HandleProjectsWithDisabledAnalysis(); + try + { + var onProjectAnalyzed = statusBarUpdater != null ? statusBarUpdater.OnProjectAnalyzed : (Action)((Project _) => { }); + await _diagnosticService.ForceAnalyzeAsync(solution, onProjectAnalyzed, project?.Id, CancellationToken.None).ConfigureAwait(false); - // Add a message to VS status bar that we completed executing code analysis. - await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(); - var notificationMesage = projectOrSolutionName != null - ? string.Format(ServicesVSResources.Code_analysis_completed_for_0, projectOrSolutionName) - : ServicesVSResources.Code_analysis_completed_for_Solution; - statusBar?.SetText(notificationMesage); + // If user has disabled live analyzer execution for any project(s), i.e. set RunAnalyzersDuringLiveAnalysis = false, + // then ForceAnalyzeAsync will not cause analyzers to execute. + // We explicitly fetch diagnostics for such projects and report these as "Host" diagnostics. + HandleProjectsWithDisabledAnalysis(); + } + finally + { + statusBarUpdater?.Dispose(); + } }).CompletesAsyncOperation(asyncToken); return; @@ -348,5 +349,94 @@ private bool IsBuildActive() } } } + + private sealed class StatusBarUpdater : IDisposable + { + private readonly IVsStatusbar _statusBar; + private readonly IThreadingContext _threadingContext; + private readonly uint _totalProjectCount; + private readonly string _statusMessageWhileRunning; + private readonly string _statusMesageOnCompleted; + private readonly string _statusMesageOnTerminated; + private readonly Timer _timer; + + private int _analyzedProjectCount; + private bool _disposed; + private uint _statusBarCookie; + + public StatusBarUpdater(IVsStatusbar statusBar, IThreadingContext threadingContext, string? projectOrSolutionName, uint totalProjectCount) + { + Contract.ThrowIfFalse(threadingContext.HasMainThread); + _statusBar = statusBar; + _threadingContext = threadingContext; + _totalProjectCount = totalProjectCount; + + _statusMessageWhileRunning = projectOrSolutionName != null + ? string.Format(ServicesVSResources.Running_code_analysis_for_0, projectOrSolutionName) + : ServicesVSResources.Running_code_analysis_for_Solution; + _statusMesageOnCompleted = projectOrSolutionName != null + ? string.Format(ServicesVSResources.Code_analysis_completed_for_0, projectOrSolutionName) + : ServicesVSResources.Code_analysis_completed_for_Solution; + _statusMesageOnTerminated = projectOrSolutionName != null + ? string.Format(ServicesVSResources.Code_analysis_terminated_before_completion_for_0, projectOrSolutionName) + : ServicesVSResources.Code_analysis_terminated_before_completion_for_Solution; + + // Set the initial status bar progress and text. + _statusBar.Progress(ref _statusBarCookie, fInProgress: 1, _statusMessageWhileRunning, nComplete: 0, nTotal: totalProjectCount); + _statusBar.SetText(_statusMessageWhileRunning); + + // Create a timer to periodically update the status message while running analysis. + _timer = new Timer(new TimerCallback(UpdateStatusOnTimer), new AutoResetEvent(false), + dueTime: TimeSpan.FromSeconds(5), period: TimeSpan.FromSeconds(5)); + } + + internal void OnProjectAnalyzed(Project _) + { + Interlocked.Increment(ref _analyzedProjectCount); + UpdateStatusCore(); + } + + // Add a message to VS status bar that we are running code analysis. + private void UpdateStatusOnTimer(object state) + => UpdateStatusCore(); + + public void Dispose() + { + _timer.Dispose(); + _disposed = true; + UpdateStatusCore(); + } + + private void UpdateStatusCore() + { + _threadingContext.JoinableTaskFactory.RunAsync(async () => + { + await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(); + + string message; + int fInProgress; + var analyzedProjectCount = (uint)_analyzedProjectCount; + if (analyzedProjectCount == _totalProjectCount) + { + message = _statusMesageOnCompleted; + fInProgress = 0; + } + else if (_disposed) + { + message = _statusMesageOnTerminated; + fInProgress = 0; + } + else + { + message = _statusMessageWhileRunning; + fInProgress = 1; + } + + // Update the status bar progress and text. + _statusBar.Progress(ref _statusBarCookie, fInProgress, message, analyzedProjectCount, _totalProjectCount); + _statusBar.SetText(message); + }); + } + } } } diff --git a/src/VisualStudio/Core/Def/Implementation/Watson/WatsonReporter.cs b/src/VisualStudio/Core/Def/Implementation/Watson/WatsonReporter.cs index 3d598821b4101857b3fdd46f3ebb6730dad701ed..7f328328180ef44568ad885aa8aa950ad252c1c7 100644 --- a/src/VisualStudio/Core/Def/Implementation/Watson/WatsonReporter.cs +++ b/src/VisualStudio/Core/Def/Implementation/Watson/WatsonReporter.cs @@ -93,16 +93,19 @@ public static void ReportNonFatal(Exception exception) exceptionObject: exception, gatherEventDetails: faultUtility => { - // add current process dump - faultUtility.AddProcessDump(currentProcess.Id); - - // add ServiceHub log files: - foreach (var path in CollectServiceHubLogFilePaths()) + if (faultUtility is FaultEvent { IsIncludedInWatsonSample: true }) { - faultUtility.AddFile(path); + // add ServiceHub log files: + foreach (var path in CollectServiceHubLogFilePaths()) + { + faultUtility.AddFile(path); + } } - // Returning "0" signals that we should send data to Watson; any other value will cancel the Watson report. + // Returning "0" signals that, if sampled, we should send data to Watson. + // Any other value will cancel the Watson report. We never want to trigger a process dump manually, + // we'll let TargetedNotifications determine if a dump should be collected. + // See https://aka.ms/roslynnfwdocs for more details return 0; }); diff --git a/src/VisualStudio/Core/Def/ServicesVSResources.resx b/src/VisualStudio/Core/Def/ServicesVSResources.resx index e32bb13a3b71b8c717dbe7655bfe437f9652ab2e..afcfbaf0f8e8c532e873a2d093a0814f8bfedb65 100644 --- a/src/VisualStudio/Core/Def/ServicesVSResources.resx +++ b/src/VisualStudio/Core/Def/ServicesVSResources.resx @@ -1344,6 +1344,12 @@ I agree to all of the foregoing: Code analysis completed for Solution. + + Code analysis terminated before completion for '{0}'. + + + Code analysis terminated before completion for Solution. + Background analysis scope: diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf index d199bed06b19e34e8bb69b6efd168e275776d4f4..2b4e696a41de138f76180fcbdca2fa658b777762 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.cs.xlf @@ -122,6 +122,16 @@ Dokončila se analýza kódu pro řešení. + + Code analysis terminated before completion for '{0}'. + Code analysis terminated before completion for '{0}'. + + + + Code analysis terminated before completion for Solution. + Code analysis terminated before completion for Solution. + + Colorize regular expressions Obarvit regulární výrazy diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf index 4082320d477cf2b57172a4b3aac2ecd52ee2e907..9f40b40c57c90738b2d967f9db88d666474cde3b 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.de.xlf @@ -122,6 +122,16 @@ Die Codeanalyse für die Projektmappe wurde abgeschlossen. + + Code analysis terminated before completion for '{0}'. + Code analysis terminated before completion for '{0}'. + + + + Code analysis terminated before completion for Solution. + Code analysis terminated before completion for Solution. + + Colorize regular expressions Reguläre Ausdrücke farbig hervorheben diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf index 13ca1750ad6def8566e1618282ff4e7a254501d2..078f8441351222e2ee5bde40d5447d6afbdb7113 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.es.xlf @@ -122,6 +122,16 @@ El análisis de código se ha completado para la solución. + + Code analysis terminated before completion for '{0}'. + Code analysis terminated before completion for '{0}'. + + + + Code analysis terminated before completion for Solution. + Code analysis terminated before completion for Solution. + + Colorize regular expressions Colorear expresiones regulares diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf index f6a5ffa0869d6307f53a7401660d77cc282823f2..cdf9da2a5c04797d64b3fb5e7f718e3e48789f91 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.fr.xlf @@ -122,6 +122,16 @@ Analyse du code effectuée pour la solution. + + Code analysis terminated before completion for '{0}'. + Code analysis terminated before completion for '{0}'. + + + + Code analysis terminated before completion for Solution. + Code analysis terminated before completion for Solution. + + Colorize regular expressions Coloriser les expressions régulières diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf index 0a9c6ded5b5ba3cb5a11c3ba7b1dac81846e6fea..d1a00cd67d2eab7a2105d870661d0851688f82f1 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.it.xlf @@ -122,6 +122,16 @@ Analisi codice completata per la soluzione. + + Code analysis terminated before completion for '{0}'. + Code analysis terminated before completion for '{0}'. + + + + Code analysis terminated before completion for Solution. + Code analysis terminated before completion for Solution. + + Colorize regular expressions Colora espressioni regolari diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf index f9fbc799b498ab1cb6824c3fc0a19d7952bc4e02..1490adfd2d5f2c8436621c92714441af2a20e386 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ja.xlf @@ -122,6 +122,16 @@ ソリューションのコード分析が完了しました。 + + Code analysis terminated before completion for '{0}'. + Code analysis terminated before completion for '{0}'. + + + + Code analysis terminated before completion for Solution. + Code analysis terminated before completion for Solution. + + Colorize regular expressions 正規表現をカラー化 diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf index 590948605229bcfedb7713b4e628654bdd6241cd..ee403020bad5ba04b37d13652127c4c4b1e46273 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ko.xlf @@ -122,6 +122,16 @@ 솔루션에 대한 코드 분석이 완료되었습니다. + + Code analysis terminated before completion for '{0}'. + Code analysis terminated before completion for '{0}'. + + + + Code analysis terminated before completion for Solution. + Code analysis terminated before completion for Solution. + + Colorize regular expressions 정규식 색 지정 diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf index fffa631f393509498db9b25e511a5adfac04aa19..6f55c48766b980ac1d79091ed049ba0e3266a5c9 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pl.xlf @@ -122,6 +122,16 @@ Ukończono analizę kodu dla rozwiązania. + + Code analysis terminated before completion for '{0}'. + Code analysis terminated before completion for '{0}'. + + + + Code analysis terminated before completion for Solution. + Code analysis terminated before completion for Solution. + + Colorize regular expressions Koloruj wyrażenia regularne diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf index 654e37c865692ad1187d2b319f2592d296280f81..42a71dc4e0f4fec9521047ea739a44849fb5d98e 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.pt-BR.xlf @@ -122,6 +122,16 @@ Análise de código concluída para a Solução. + + Code analysis terminated before completion for '{0}'. + Code analysis terminated before completion for '{0}'. + + + + Code analysis terminated before completion for Solution. + Code analysis terminated before completion for Solution. + + Colorize regular expressions Colorir expressões regulares diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf index bee4ec9a687567f0bce90f202fccfed3e37ceb1d..c70b48ebe93796a4bfa0f278b58920113e2c38b2 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.ru.xlf @@ -122,6 +122,16 @@ Анализ кода для решения выполнен. + + Code analysis terminated before completion for '{0}'. + Code analysis terminated before completion for '{0}'. + + + + Code analysis terminated before completion for Solution. + Code analysis terminated before completion for Solution. + + Colorize regular expressions Выделить регулярные выражения цветом diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf index a04fb04637fb1ba962c62cd1508ff43e4245d958..9ccb0f8e2284f30337927b7982528acf21cc3530 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.tr.xlf @@ -122,6 +122,16 @@ Çözüm için kod analizi tamamlandı. + + Code analysis terminated before completion for '{0}'. + Code analysis terminated before completion for '{0}'. + + + + Code analysis terminated before completion for Solution. + Code analysis terminated before completion for Solution. + + Colorize regular expressions Normal ifadeleri renklendir diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf index d35b7079dc55b53bd9b946d30b113ac32c80cc24..53a1ad5d94ab5d9a17c3e099d21f1968ac5bbc01 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hans.xlf @@ -122,6 +122,16 @@ 解决方案的代码分析已完成。 + + Code analysis terminated before completion for '{0}'. + Code analysis terminated before completion for '{0}'. + + + + Code analysis terminated before completion for Solution. + Code analysis terminated before completion for Solution. + + Colorize regular expressions 为正规表达式着色 diff --git a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf index 460e875d4bf90f445e7fd13a03ec0f906aec1e45..a20376a6e8a39c39b33cecf88c916f6c089b86ce 100644 --- a/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf +++ b/src/VisualStudio/Core/Def/xlf/ServicesVSResources.zh-Hant.xlf @@ -122,6 +122,16 @@ 解決方案的程式碼分析已完成。 + + Code analysis terminated before completion for '{0}'. + Code analysis terminated before completion for '{0}'. + + + + Code analysis terminated before completion for Solution. + Code analysis terminated before completion for Solution. + + Colorize regular expressions 為規則運算式添加色彩 diff --git a/src/VisualStudio/Core/Test/Diagnostics/ExternalDiagnosticUpdateSourceTests.vb b/src/VisualStudio/Core/Test/Diagnostics/ExternalDiagnosticUpdateSourceTests.vb index c0b1f83161ada3a7897095c50ab319aaa7abfccc..781c62b0ec1e96bf35010fbf9ec37a518b8f1df2 100644 --- a/src/VisualStudio/Core/Test/Diagnostics/ExternalDiagnosticUpdateSourceTests.vb +++ b/src/VisualStudio/Core/Test/Diagnostics/ExternalDiagnosticUpdateSourceTests.vb @@ -508,7 +508,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.Diagnostics Throw New NotImplementedException() End Function - Public Function ForceAnalyzeAsync(solution As Solution, Optional projectId As ProjectId = Nothing, Optional cancellationToken As CancellationToken = Nothing) As Task Implements IDiagnosticAnalyzerService.ForceAnalyzeAsync + Public Function ForceAnalyzeAsync(solution As Solution, onProjectAnalyzed As Action(Of Project), Optional projectId As ProjectId = Nothing, Optional cancellationToken As CancellationToken = Nothing) As Task Implements IDiagnosticAnalyzerService.ForceAnalyzeAsync Throw New NotImplementedException() End Function End Class diff --git a/src/Workspaces/Core/Portable/Rename/ConflictEngine/RenamedSpansTracker.cs b/src/Workspaces/Core/Portable/Rename/ConflictEngine/RenamedSpansTracker.cs index 5ab06e6c9a00f3f7411c5038f770f1590740f10f..77fb7dc4592cd9f1de8efb33167d30e1ef3b6696 100644 --- a/src/Workspaces/Core/Portable/Rename/ConflictEngine/RenamedSpansTracker.cs +++ b/src/Workspaces/Core/Portable/Rename/ConflictEngine/RenamedSpansTracker.cs @@ -237,8 +237,10 @@ internal async Task SimplifyAsync(Solution solution, IEnumerable>(); foreach (var (docId, spans) in _documentToComplexifiedSpansMap) + { builder.Add(docId, spans.SelectAsArray( s => new ComplexifiedSpan(s.OriginalSpan, s.NewSpan, s.ModifiedSubSpans.ToImmutableArray()))); + } return builder.ToImmutable(); } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Formatting/Rules/AnchorIndentationFormattingRule.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Formatting/Rules/AnchorIndentationFormattingRule.cs index eea37402aec5c8aa1716343ff9466c32aa2114dd..51f9d0ba84632d5a6adc11783be2e75b58fed295 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Formatting/Rules/AnchorIndentationFormattingRule.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Formatting/Rules/AnchorIndentationFormattingRule.cs @@ -68,7 +68,7 @@ public override void AddAnchorIndentationOperations(List list, SyntaxN case ImplicitArrayCreationExpressionSyntax implicitArrayCreation when implicitArrayCreation.Initializer != null: SetAlignmentBlockOperation(list, implicitArrayCreation.NewKeyword, implicitArrayCreation.Initializer.OpenBraceToken, implicitArrayCreation.Initializer.CloseBraceToken, IndentBlockOption.RelativeToFirstTokenOnBaseTokenLine); return; - case CSharpSyntaxNode syntaxNode when syntaxNode.IsKind(SyntaxKind.SwitchExpression): - SetAlignmentBlockOperation( - list, - syntaxNode.GetFirstToken(), - syntaxNode.ChildNodesAndTokens().First(child => child.IsKind(SyntaxKind.OpenBraceToken)).AsToken(), - syntaxNode.ChildNodesAndTokens().Last(child => child.IsKind(SyntaxKind.CloseBraceToken)).AsToken(), - IndentBlockOption.RelativeToFirstTokenOnBaseTokenLine); + case SwitchExpressionSyntax switchExpression: + SetAlignmentBlockOperation(list, switchExpression.GetFirstToken(), switchExpression.OpenBraceToken, switchExpression.CloseBraceToken, IndentBlockOption.RelativeToFirstTokenOnBaseTokenLine); return; } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SelectedMembers/AbstractSelectedMembers.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SelectedMembers/AbstractSelectedMembers.cs index ccd3678475cfceb61b08b104a26ea62034411308..c9a91e86f6ca25e05a085f60c5e8bce08c7224f3 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SelectedMembers/AbstractSelectedMembers.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Services/SelectedMembers/AbstractSelectedMembers.cs @@ -102,7 +102,9 @@ void AddSelectedFieldOrPropertyDeclarations(TMemberDeclarationSyntax member) { if (!(member is TFieldDeclarationSyntax) && !(member is TPropertyDeclarationSyntax)) + { return; + } // first, check if entire member is selected. If so, we definitely include this member. if (textSpan.Contains(member.Span))