-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Formatting analyzer #28873
Formatting analyzer #28873
Conversation
src/Features/Core/Portable/Formatting/AbstractFormattingDiagnosticAnalyzer.cs
Outdated
Show resolved
Hide resolved
src/Features/Core/Portable/Formatting/AbstractFormattingDiagnosticAnalyzer.cs
Outdated
Show resolved
Hide resolved
src/Features/Core/Portable/Formatting/AbstractFormattingDiagnosticAnalyzer.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/CSharpAnalyzerDriver/CSharpDeclarationComputer.cs
Outdated
Show resolved
Hide resolved
src/Features/Core/Portable/Formatting/AbstractFormattingDiagnosticAnalyzer.cs
Outdated
Show resolved
Hide resolved
src/Features/Core/Portable/Formatting/AbstractFormattingDiagnosticAnalyzer.cs
Outdated
Show resolved
Hide resolved
src/Features/Core/Portable/Formatting/AbstractFormattingDiagnosticAnalyzer.cs
Outdated
Show resolved
Hide resolved
Right now, it's hard to tell the effect this would have due to the noisiness of the "trailing whitespace" diagnostics. would it be possible to not have those, and then see what sort of impact this would normally be expected to have? |
src/Features/Core/Portable/Formatting/AbstractFormattingDiagnosticAnalyzer.cs
Outdated
Show resolved
Hide resolved
why are we not just suppressing at the project level... having a million line-suppressions just means we have so much noise that interferes with seeing what actually benefits here. |
I'm on a bug hunt, looking for bugs in the formatter and bugs in the Suppress Message feature. Turns out this analyzer is quite good at revealing both. |
if a fix for this analyzer will fix one diagnostic, then I think reporting diagnostic per change seems right. if a fix for this analyzer will fix whole document, then I think reporting diagnostic per document seems right. |
Agreed. That's a good way to think about it. |
I'm leaning towards implementing the simple fix as fixing all squiggles on the line where invoked, and the Fix All in Document runs |
6753d80
to
ea59c4f
Compare
There may be. I'm not certain. Look at the base classes and their public/protected helpers.
I agree. The original test harness validated this. However, when the rewrite of all the implementations of these analyzers changed, these were changed to be less strict in what they checked (i think to make the porting over easier). But it means they're less effective in terms of validating the experience is working properly. If you wanted to tighten the check, that would be fine with me. I expect you'd have to go update a whole swath of tests. But i think that would be totally fine to do (and i'd be willing to review for you).
You'd have to write a helper for that. |
ea59c4f
to
017b1cc
Compare
options = options.WithChangedOption(FormattingOptions.AllowConcurrent, false); | ||
var resultTask = GetFormattedTextChangesAsync(node, workspace, options, cancellationToken); | ||
Debug.Assert(resultTask.IsCompleted); | ||
return resultTask.WaitAndGetResult_CanCallOnBackground(cancellationToken); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jasonmalinowski Please make sure to review the new pattern in this method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like this deserves a comment. Is there a concern here about blocking a thread on a parallelized algorithm?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the one who calls this API should set the option, not the API itself set the option.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a concern here about blocking a thread on a parallelized algorithm?
Yes, the analyzer runs in parallel on the thread pool. It would be easy for it to starve the system.
the one who calls this API should set the option
The asynchronous form of this method provides opportunistic parallelization, if desired.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, i'm somewhat ok with this change. But it would def need to be applied a bit uniformly. We could also consider deprecating this guy. It always worries me when we expose sync entrypoints that immediately block on the async version.
It should also be a warning to us for future API development. It's likely we'll need to default things to being async so we don't end up hurting ourselves here later. A good example of that is around the discussions of Options. Options present a synchronous API, but need to block on async work. If we then make Options async, it virally hits entrypoints like this (which are currently fine being synchronous).
If we had settled on these being async from teh start, we wouldn't have these problems cropping up over time as more core parts of our system become async.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But it would def need to be applied a bit uniformly.
Implementing this for the rest of the synchronous Formatter
methods. It's so ugly it makes me sad but implementing the synchronous form all-the-way-down was a huge amount of work and mostly duplicated code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so the thing i'm missing is: how do you know the returned task iscomplete?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh, i see. because you pass AllowConcurrent: false. gotcha.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: my preference wouldjust be deprecate these methods as we do this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The diagnostic analyzer code paths are synchronous, and rely on the new synchronous behavior of these methods to avoid thread pool starvation in projects with very large files.
src/Features/Core/Portable/Formatting/FormattingCodeFixProvider.cs
Outdated
Show resolved
Hide resolved
src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerManager.AnalyzerExecutionContext.cs
Outdated
Show resolved
Hide resolved
src/Workspaces/Core/Portable/CodeFixes/FixAllOccurrences/FixAllContext.DiagnosticProvider.cs
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The core analyzer/fixer changes LGTM.
I would still request adding a unit test to guard the reflection based code and also let someone from @dotnet/roslyn-infrastructure review the changes to Packages.props.
5d10084
to
8a88bc9
Compare
{ | ||
OptionSet options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); | ||
|
||
// The in-IDE workspace supports .editorconfig without special handling. However, the AdhocWorkspace used |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this a test-only code? If so, can it be refactored into a test-only method?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not strictly test-only code. It's addressing a limitation of the workspace which would naturally go away once we switch the code to using the new .editorconfig support in the compiler.
It could be considered test-only code from the perspective that removing the code would not produce a failure inside the IDE, but it could still produce failures in tools like AnalyzerRunner.
analyzer.InitializeWorker(context); | ||
} | ||
|
||
private static Assembly HandleAssemblyResolve(object sender, ResolveEventArgs args) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where is the bug link tracking the removal of this? Can't imagine this is part of the long term solution here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
➡️ #30472
@@ -8,16 +8,17 @@ | |||
<RootNamespace>Microsoft.CodeAnalysis.CSharp</RootNamespace> | |||
<TargetFramework>netstandard1.3</TargetFramework> | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="$(MicrosoftCodeAnalysisCSharpFixedVersion)" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we referencing a package here instead of the corresponding source project? Feel like we need a good explanation here. This is extremely odd and I'm not going to be the last person confused by this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm interested in understanding this too. If there's a good reason, it's not obvious.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All the hacks for this package exist so we can get feedback from users about the behavior of this analyzer in developer and CI scenarios. To accomplish that, it is installable in and works with 15.7 plus.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Signing off on the infrastructure side of the change. The core followup item is #30472
test windows_release_vs-integration_prtest |
Approved to merge when ready |
test windows_release_vs-integration_prtest |
Hi guys! |
@MarcoRossignoli I moved your comment to #30541 👍 |
No description provided.