You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The rule uses attributes, so we can know about it before instantiating one, and it's also neater and more declarative
The abstract class can provide convenience methods that simplify invocation, helpfully transform inputs, and even can do diagnostic suppression before a diagnostic record object is allocated
A rule can be generic in its settings object and then allow for those settings to be injected through the constructor based on a deserialised settings object. This adds boilerplate, but allows the object configuration to be totally up to the implementer based on their settings definition (which can be defined next to the rule) and their constructor logic
However, some downsides of the current implementation are:
Allowing the same class to implement a rule and, say, a formatter is harder with the abstract class vs an interface (and interfaces should generally be preferred when possible)
Using a protected method to emit diagnostics means there's no type check for rules that will never emit a diagnostic
We force constructor injection. This is so you can use settings in your rule at the correct time from the code's perspective (e.g. default property values will work, unlike today), but it means more boilerplate for implementers.
I would very much like to keep the feature where we don't allocate an object for suppressed diagnostics, and it has the advantage that there's one fewer classes for an implementer to think about. Some convenience functions can be preserved with extension methods on interfaces, but some cannot.
So an example alternate implementation might look like:
But the main issue there is we lose the elegance of (1) making it easier to construct diagnostics, particularly passing in rule metadata automatically, and (2) being able to filter diagnostics before they are created.
So another alternative would be:
publicinterfaceIScriptRule{voidAnalyzeScript(IDiagnosticEmitterdiagnosticEmitter,Astast,IReadOnlyList<Token>tokens,stringscriptFilePath);}// This could be something like an abstract class instead// But ideally something we could shift the core implementation of if we needed topublicinterfaceIDiagnosticEmitter{// Rule required so that diagnostics know what rule they came from// But we trust the caller -- it would be possible to instantiate another rule and pass it in, but this is undesirable// Also having to pass `this` is something of an anti-patternvoidEmitDiagnostic(IScriptRulerule,Astast,IReadOnlyList<Token>tokens,stringscriptFilePath);}publicstaticclassDiagnosticEmitterExtensions{// Convenience methods}
Basically, the abstract class approach makes life better for both the framework and for rule implementers, but has the big downside that multiple inheritance is impossible... OTOH, there are other ways to do something like take a rule and turn it into a formatter, and single-inheritance generally promotes good cohesion...
The text was updated successfully, but these errors were encountered:
For those that want to implement their own rules in a .NET language, is the expectation that a PSA2 reference assembly would be published on NuGet? I’m more curious about the experience as a rule author maintaining an assembly containing rules than the specifics of the actual API. Ideally I’d have something to reference that would support rules for both 5.1 and Core and that would be loosely coupled to the exact version of PSA2 loaded at runtime.
is the expectation that a PSA2 reference assembly would be published on NuGet?
Yes that's the plan and primary driver for PSScriptAnalyzer 2, to enable NuGet-based hosting of it (mainly for the PowerShell extension for VSCode). It won't be a reference assembly, it will be the real thing. But there are no plans for a reference assembly currently.
Uh oh!
There was an error while loading. Please reload this page.
PSSA2 provides a new way to specify rules, which you can see here:
PSScriptAnalyzer/ScriptAnalyzer2/Builtin/Rules/AvoidEmptyCatchBlock.cs
Lines 12 to 48 in 9ee8c0f
That is based on the following implementation:
PSScriptAnalyzer/ScriptAnalyzer2/Rules/Rule.cs
Lines 12 to 91 in 9ee8c0f
This is nice because:
However, some downsides of the current implementation are:
I would very much like to keep the feature where we don't allocate an object for suppressed diagnostics, and it has the advantage that there's one fewer classes for an implementer to think about. Some convenience functions can be preserved with extension methods on interfaces, but some cannot.
So an example alternate implementation might look like:
But the main issue there is we lose the elegance of (1) making it easier to construct diagnostics, particularly passing in rule metadata automatically, and (2) being able to filter diagnostics before they are created.
So another alternative would be:
Basically, the abstract class approach makes life better for both the framework and for rule implementers, but has the big downside that multiple inheritance is impossible... OTOH, there are other ways to do something like take a rule and turn it into a formatter, and single-inheritance generally promotes good cohesion...
The text was updated successfully, but these errors were encountered: