Add SimplifyObjectCreation analyzer#52077
Conversation
| MyBase.New( | ||
| diagnosticId:=IDEDiagnosticIds.SimplifyObjectCreationDiagnosticId, | ||
| enforceOnBuild:=EnforceOnBuildValues.SimplifyObjectCreation, | ||
| [option]:=Nothing, |
There was a problem hiding this comment.
This should have an option
There was a problem hiding this comment.
The day where this isn't needed anymore can't get here soon enough
There was a problem hiding this comment.
For the option to be useful, it needs to be involved in code generation. Otherwise, setting severity should be enough. Anything I'm missing?
There was a problem hiding this comment.
yeah, we need an option so that people can configure this from the UI. for example, stating that they want this, and what severity this should be.
There was a problem hiding this comment.
@CyrusNajmabadi Won't @jmarolf's PR (#51069) address this in a more global way (for all analyzers)?
I'll add an option for now, but may jump into discord to get more information.
| Dim root = Await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(False) | ||
| For Each diagnostic In diagnostics | ||
| Dim node = DirectCast(root.FindNode(diagnostic.Location.SourceSpan, getInnermostNodeForTie:=True), VariableDeclaratorSyntax) | ||
| Dim asNewClause = SyntaxFactory.AsNewClause(node.AsClause.AsKeyword, DirectCast(node.Initializer.Value, NewExpressionSyntax)) |
There was a problem hiding this comment.
In the analyzer you check for Object creation. Here you cast to New expression. (I'm not at computer), is this safe?
There was a problem hiding this comment.
@CyrusNajmabadi Nice catch! I think the cast may fail. Will come up with a test and fix that.
There was a problem hiding this comment.
The cast doesn't fail since an ObjectCreationExpressionSyntax derives from NewExpressionSyntax (i.e, it's always safe to cast an ObjectCreationExpressionSyntax to its base type. However, the analyzer is missing cases.
There was a problem hiding this comment.
@CyrusNajmabadi The syntactic simplification of an expression like Dim result As C() = New C() { } (i.e, ArrayCreationExpression) will be different since Dim result As New C() { } isn't allowed by the language. Let me know if you want me to handle this or keep it simple and only catch ObjectCreationExpressionSyntax.
There was a problem hiding this comment.
just keep it simple. make sure we have tests and whatnot.
|
Needs an option, and update to tools|options for vb. But it's otherwise ready to go in :-) |
| No editorconfig based code style option | ||
|
|
||
| # IDE0131 | ||
| No editorconfig based code style option |
There was a problem hiding this comment.
we would want an editorconfig value for this. otherwise people can't disable the hint. or, alternatively, some projects might want to make it an error if you use the old form and not the new form.
|
|
||
| Dim symbolInfo = context.SemanticModel.GetTypeInfo(objectCreation, cancellationToken) | ||
| If symbolInfo.Type IsNot Nothing AndAlso symbolInfo.Type.Equals(symbolInfo.ConvertedType, SymbolEqualityComparer.Default) Then | ||
| context.ReportDiagnostic(Diagnostic.Create(Descriptor, variableDeclarator.GetLocation())) |
There was a problem hiding this comment.
i think this loses the value of hte style option. i.e. the severity.
There was a problem hiding this comment.
@CyrusNajmabadi Can you elaborate more on this?
There was a problem hiding this comment.
i think this loses the value of hte style option. i.e. the severity.
Aren't these actively being deprecated? The form used in this PR does account for the standard dotnet_diagnostic.*.severity option.
There was a problem hiding this comment.
Could you clarify how that works? How did the diagnostic know what severity the user has set this particular option to?
There was a problem hiding this comment.
I think this happens around the following, not sure enough:
https://github.com/dotnet/roslyn/blob/1cca63b5d8ea170f8d8e88e1574aa3ebe354c23b/src/Compilers/Core/Portable/Diagnostic/DiagnosticDescriptor.cs#L213-L224
roslyn/src/Compilers/CSharp/Portable/Compilation/CSharpDiagnosticFilter.cs
Lines 195 to 215 in 79f65d8
roslyn/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerDriver.cs
Lines 1924 to 1946 in 92b6499
There was a problem hiding this comment.
I do not understand why some of these anlayzers are using this form, and some are using DiagnosticHelper.Create. Can you please use DiagnosticHelper.Create to be consistent with the rest of the analyzers in this domain. If that approach is incorrect we cna fix them all up together.
@sharwell @mavasani to advise. Note: this is one of the reasons i really dislike making pattern changes in a piecemeal fashion. I cannot go and look and see what is the right way to do something because we aren't consistent in our own codebase.
There was a problem hiding this comment.
@mavasani can you verify that all the above is correct? That it's fine for an anlyzer to just create the Diagnostic and not pass the severity. If so, i'm fine with this piece.
There was a problem hiding this comment.
We have 2 core scenarios here to consider, let me elaborate:
- Command line builds - This scenario will have no impact on whether we use
DiagnosticHelper.Create(..., Notification.Severity, ...)orDiagnostic.Create(...), with the latter ignoringNotification.Severityfrom the code style option. - IDE background analysis - This scenario will have different user experience based on the chosen approach. Using
DiagnosticHelper.Create(..., Notification.Severity, ...)would ensure the option severity set in Tools/Option or via the:severitysyntax in editorconfig will be respected. UsingDiagnostic.Create(...)would lead to this severity setting being ignored even in the IDE. We normally useDiagnostic.Create(...)for reporting analyzer diagnostics only when the IDE analyzer does not have corresponding code style option where:severitycan be specified.
Overall it proves the point that we were just discussing at the design meeting - determining the reported severity of diagnostics should not be determined by the analyzers, but instead better for analyzer driver to do the right thing. I think it is fine to leave it in Dev16 and we can hopefully fix the core issue properly in the compiler/analyzer driver layer in Dev17 so users and analyzer authors have the minimal overhead for getting the most intuitive functionality.
There was a problem hiding this comment.
I see. This code is incorrect then. @Youssef1313 can you revise this to address this issue?
There was a problem hiding this comment.
Overall it proves the point that we were just discussing at the design meeting - determining the reported severity of diagnostics should not be determined by the analyzers, but instead better for analyzer driver to do the right thing.
I'm fine with that. My general point is that that should still be done in a way taht is palatable to the person who owns the editorconfig file. :)
| Inherits CustomCodeActions.DocumentChangeAction | ||
|
|
||
| Friend Sub New(title As String, createChangedDocument As Func(Of CancellationToken, Task(Of Document))) | ||
| MyBase.New(title, createChangedDocument, NameOf(VisualBasicCodeFixesResources.Simplify_object_creation)) |
There was a problem hiding this comment.
pass title for equivalence key?
There was a problem hiding this comment.
@CyrusNajmabadi It was suggested by @sharwell to pass NameOf(resource) as equivalence key. I don't know if it matters.
There was a problem hiding this comment.
Non-localized equivalence keys may make it easier to use equivalence keys in the future for configuring/disabling specific code actions.
There was a problem hiding this comment.
that won't seem to work anyways as we use the title in tons of code actions today. i woudl rather us just be consistent everywhere. if and when we have a need to make changes for future work, we can then change everything togehter. Being inconsistent here is worse, to me, because it means no one can know for certain what is going on and any particular PR has to deal with trying to rationalize what pattern should be used where.
There was a problem hiding this comment.
@CyrusNajmabadi The situation is already inconsistent unfortunately. There exist usage of both patterns already 😕
So I think we should go to whatever helps in the future. We can also create an analyzer that makes sure equivalence keys are compile-time constants.
| Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.SimplifyObjectCreation | ||
| Public Class SimplifyObjectCreationTests | ||
| <Fact> | ||
| Public Async Function SimplifyObjectCreation() As Task |
There was a problem hiding this comment.
is there a fix-all test?
There was a problem hiding this comment.
@CyrusNajmabadi See SimplifyObjectCreation_MultipleDeclarators.
CyrusNajmabadi
left a comment
There was a problem hiding this comment.
lgtm if feedback is addressed. Thanks!
|
@CyrusNajmabadi Anything left here? |
|
lgtm, thanks! |
Fixes #45166