PRI Essentials - CodeAnalyzers
Known Issues
- implement translator method doesn't do well with nullables
Changes since 1.10
- Added check (PRd1002) for comparaing string identifier to
null
, for prefer string.IsNullOrWhiteSpace
- fixed issue with translator method generation where multiple of the same enum mapping methods were created.
- Added support for multiple identifiers in field declarations
- Added support for XML comments on enums
- Fixed a couple places where only one XML diagnostic would be raise instead of multiple.
- Fixed spelling error in consider lazy initializer for readonly properties description.
Changes since 1.8
- added rules for recommended practices relating to ASP.NET: [PRr1000](#asp.net-get-actions-should-return-http-compilant-results-prr1000], PRr1010, and PRr1011 (see below)
- expanded transient verb list: (added "patch" and "try")
- now not warning that XML comments are missing when
iheritdoc
element is used.
- removed transient verb warnings for interface implmentation methods.
changes since 1.7
- Added PRd1001 diagnostics: consider
Async<T>
lazy initialization for complex property expression body or initializer.
- Fixes creation of generic
cref
s in XML documents so they link to an open generic and not a constructed generic.
Changes since 1.6
- Fixes for a couple
NullReferenceException
s
Changes since 1.5
- attempt to fix AD0001 error involving
FileNotFoundException
s for referenced DLLs by the analyzer
Changes since 1.4
- fixed detection of
.ctor
(and other special methods) when warning about the lack of leading transitive verbs.
- support for disabling rules in .editorconfig.
Features
- Check use of ASP.NET
StatusCode
method to be HTTP-compliant (like StatusCode(StatusCodes.Status100Continue, obj)
when status 100 should have no content) See PRr1011
- Check use of ASP.NET
StatusCode
method to prefer specific ASP.NET action result method (like Ok()
instead of StatusCode.Status200Ok
) See PRr1010
- Detect and bulk-fix missing XML comments
- Automatically generate English sentence-structured XML comment elements by parsing camel-cased identifiers.
- Check English verb usage within certain methods' and properties' names See details.
- Support easier DTO usage and adapter implementations by generating translation methods.
Analyzers Overview
ID |
Description |
Code Fix? |
Bulk Fix? |
Category |
Default Severity |
PRr1010 |
Prefer Specific ASP.NET Action Result Method Over StatusCode |
No |
N/A |
Recommended Practices |
Info |
PRr1011 |
Use of ASP.NET StatusCode Method Should be HTTP-compliant |
No |
N/A |
Recommended Practices |
Warning |
PRr1000 |
ASP.NET GET Actions Should Return HTTP-compilant Results |
No |
N/A |
Recommended Practices |
Warning |
PRm1000 |
Xml Comments Not Present |
Yes |
Yes |
Maintainability |
Warning |
PRm1001 |
Xml Comments Not Complete |
Yes |
Yes |
Maintainability |
Warning |
PRm1010 |
Method Name Should Have Leading Transitive Verb |
No |
N/A |
Maintainability |
Warning |
PRm1011 |
Boolean Property Name Should Have Leading Future Tense Able |
No |
N/A |
Maintainability |
Warning |
PRd1000 |
Translator Method Not Implemented |
Yes |
Yes |
Design |
Warning |
PRd1001 |
Read only properties may be lazy initialized. |
Yes |
Yes |
Design |
Information |
PRd1002 |
Prefer 'string.IsNullOrWhiteSpace' to validate string values. |
Yes |
Yes |
Design |
Information |
Prefer Specific ASP.NET Action Result Method Over StatusCode
(PRr1010)
This rule provides information about convenience methods that can be more clear about expressing intent than using StatusCode
.
To disable: #pragma warning disable PRr1010
(and #pragma warning restore PRr1010
to restore.)
The following are the specific diagnotics this rule will generate:
Prefer Ok()
over StatusCode(StatusCodes.StatusCode200OK)
Convenience methods can provide a clearer means of expressing intent. Convenience methods often provide scenario-specific type-safety making it more likely to implement HTTP-compliant interfaces.
Prefer Ok(obj)
over StatusCode(StatusCodes.StatusCode200OK, obj)
Convenience methods can provide a clearer means of expressing intent. Convenience methods often provide scenario-specific type-safety making it more likely to implement HTTP-compliant interfaces.
The convenience method Created
limits arguments to string or Uri types ensuring that a 201 Created response is correctly implemented. Created
also has an extra parameter to support response content.
Prefer Created(uri)
over StatusCode(StatusCodes.Status201Created, uri)
The convenience method Created
limits arguments to string or Uri types ensuring that a 201 Created response is correctly implemented. Created
also has an extra parameter to support response content.
Prefer Accepted()
over StatusCode(StatusCodes.Status202Accepted)
Convenience methods can provide a clearer means of expressing intent. Convenience methods often provide scenario-specific type-safety making it more likely to implement HTTP-compliant interfaces.
Prefer Accepted(obj)
over StatusCode(StatusCodes.Status202Accepted, obj)
Convenience methods can provide a clearer means of expressing intent. Convenience methods often provide scenario-specific type-safety making it more likely to implement HTTP-compliant interfaces.
Prefer NoContent()
over StatusCode(StatusCodes.Status204NoContent)
NoContent() does not have an overload that takes another argument making it much more likely that content is not accidently passed as a result like StatusCode(StatusCodes.Status204NoContent, "my content")
would.
RedirectPermanent
ensures that the 301 response is compliant by also producing a Location
header, unlike StatusCode
alone.
Redirect
ensures that the 302 response is compliant by also producing a Location
header, unlike StatusCode
alone.
RedirectPreserveMethod
ensures that the 307 response is compliant by also producing a Location
header, unlike StatusCode
alone.
RedirectPermanentPreserveMethod
ensures that the 308 response is compliant by also producing a Location
header, unlike StatusCode
alone.
Prefer BadRequest()
over StatusCode(StatusCodes.Status400BadRequest)
Convenience methods can provide a clearer means of expressing intent. Convenience methods often provide scenario-specific type-safety making it more likely to implement HTTP-compliant interfaces.
Prefer BadRequest(obj)
over StatusCode(StatusCodes.Status400BadRequest, obj)
Convenience methods can provide a clearer means of expressing intent. Convenience methods often provide scenario-specific type-safety making it more likely to implement HTTP-compliant interfaces.
Prefer ValidationProblem(ModelState)
over StatusCode(StatusCodes.Status400BadRequest, ModelState)
ValidationProblem(ModelState)
produces an application/problem+json
result with the ModelState
, StatusCode(StatusCodes.Status400BadRequest, ModelState)
does not.
Prefer NotFound()
over StatusCode(StatusCodes.Status404NotFound)
Convenience methods can provide a clearer means of expressing intent. Convenience methods often provide scenario-specific type-safety making it more likely to implement HTTP-compliant interfaces.
Prefer NotFound(obj)
over StatusCode(StatusCodes.Status404NotFound, obj)
Convenience methods can provide a clearer means of expressing intent. Convenience methods often provide scenario-specific type-safety making it more likely to implement HTTP-compliant interfaces.
Prefer Conflict()
over StatusCode(StatusCodes.Status409Conflict)
Convenience methods can provide a clearer means of expressing intent. Convenience methods often provide scenario-specific type-safety making it more likely to implement HTTP-compliant interfaces.
Prefer Conflict(ModelState)
over StatusCode(StatusCodes.Status409Conflict, ModelState)
Convenience methods can provide a clearer means of expressing intent. Convenience methods often provide scenario-specific type-safety making it more likely to implement HTTP-compliant interfaces.
Prefer UnprocessableEntity()
over StatusCode(StatusCodes.Status422UnprocessableEntity, ModelState)
Convenience methods can provide a clearer means of expressing intent. Convenience methods often provide scenario-specific type-safety making it more likely to implement HTTP-compliant interfaces.
Prefer UnprocessableEntity(ModelState)
over StatusCode(StatusCodes.Status422UnprocessableEntity, ModelState)
Convenience methods can provide a clearer means of expressing intent. Convenience methods often provide scenario-specific type-safety making it more likely to implement HTTP-compliant interfaces.
Prefer UnprocessableEntity(obj)
over StatusCode(StatusCodes.Status422UnprocessableEntity, obj)
Convenience methods can provide a clearer means of expressing intent. Convenience methods often provide scenario-specific type-safety making it more likely to implement HTTP-compliant interfaces.
Known Issues
Code fixes are planned for this rule but not yet completed.
Use of ASP.NET 'StatusCode' Method Should be HTTP-compliant (PRr1011)
This rule validates that the StatusCode
method is used correctly for the given status code.
To disable: #pragma warning disable PRr1011
(and #pragma warning restore PRr1011
to restore.)
The following are the specific diagnostics this rule will generate:
Use of StatusCode
should be HTTP-compliant. StatusCode(StatusCodes.Status100Continue, obj)
is unexpected. Status code '100' response should not have content.
An object should not be passed to StatusCode
for StatusCodes.Status100Continue
. A 100 Continue response should not have content. rfc9110 section 6.4.1
Use of StatusCode
should be HTTP-compliant. StatusCode(StatusCodes.Status204NoContent, ""content"")
is unexpected. tatus code '204' response should not have content.
An object should not be passed to StatusCode
for StatusCodes.Status204NoContent
. A 204 No Content response should not have content. rfc9110 section 6.4.1
Use of StatusCode
should be HTTP-compliant. StatusCode(StatusCodes.Status301MovedPermanently)
is unexpected. Status code '301' response should have content with a hyperlink to the different URI(s).
An object should be passed to StatusCode
for StatusCodes.Status301MovedPermanently
. A 301 Moved Permamently response should contain a short hypertext note with a hyperlink to the new URI(s)..rfc9110 section 15.4.2
Use of StatusCode
should be HTTP-compliant. StatusCode(StatusCodes.Status302Found)
is unexpected. Status code '302' response should have content with a hyperlink to the different URI(s).
An object should be passed to StatusCode
for StatusCodes.Status302Found
. A 302 Found response should contain a short hypertext note with a hyperlink to the new URI(s).rfc9110 section 15.4.3
Use of StatusCode
should be HTTP-compliant. StatusCode(StatusCodes.Status304NotModified, ""content"")
is unexpected. Status code '304' response should not have content.
An object should not be passed to StatusCode
for StatusCodes.Status304NotModified
. A 304 Not Modified response should not have content. rfc9110 section 6.4.1
Use of StatusCode
should be HTTP-compliant. StatusCode(StatusCodes.Status307TemporaryRedirect)
is unexpected. Status code '307' response should have content with a hyperlink to the different URI(s).
An object should not be passed to StatusCode
for StatusCodes.Status307TemporaryRedirect
. A 307 Temporary Redirect response should contain a short hypertext note with a hyperlink to the different URI(s).rfc9110 section 15.4.8
Use of StatusCode
should be HTTP-compliant. StatusCode(StatusCodes.Status308PermanentRedirect)
is unexpected. Status code '308' response should have content with a hyperlink to the different URI(s).
An object should not be passed to StatusCode
for StatusCodes.Status308PermanentRedirect
. A 308 Permanent Redirect response should contain a short hypertext note with a hyperlink to the different URI(s). rfc9110 section 15.4.9
Use of StatusCode
should be HTTP-compliant. StatusCode(StatusCodes.Status200OK, ""content"")
is unexpected. 'HEAD' response should not have content.
An object should not be passed to StatusCode
when implementing HTTP HEAD methods. The response to HEAD should have no content rfc9110 section
Use of StatusCode
should be HTTP-compliant. `` is unexpected. .
ASP.NET GET Actions Should Return HTTP-compilant Results (PRr1000)
This rule validates that the StatusCode
method is used correctly for the given status code with GET actions.
To disable: #pragma warning disable PRr1000
(and #pragma warning restore PRr1000
to restore.)
The following are the specific diagnostics this rule will generate:
BaseController
method NoContent
is not a recommended result for an HTTP GET method
An HTTP GET response should include a selected representation of the target resource. A representation may be of zero length, but the response should be 200 OK instead of 204 No Content. rfc9110 section 9.3.1
Translator Method Not Implemented Rule
A translator method is a method that takes a single complex type parameter (not string
, int
, etc.)
parameter and returns a complex type (translates the parameter to an instance of the return type.)
This analyzer warns if it detects an unimplemented translator method (the body only throws a
NotImplementedException
exception). To trigger the rule and make the code fix available,
implement code similar to the following:
using System;
using Domain;
using Dtos;
namespace MyNamespace
{
/// <summary>
/// A DTO translator
/// </summary>
public static class DtoTranslator
{
/// <summary>
/// Translate an account DTO to an account domain object
/// </summary>
/// <returns cref="Account">Account</returns>
/// <param name="accountDto" cref="AccountDto"></param>
public static Account Translate(AccountDto accountDto)
{
throw new NotImplementedException();
}
}
}
A translator method aims to convert the parameter into an instance of the return
type by instantiating the returned type and initializing its writable properties with
the parameter's properties that match by name.
The code fix implements an unimplemented translator method's body (replacing the
throw new NotImplementedException
).
The code fix supports the following types in translation:
- simple type
- enum: generating a switch statement, matching enum element names (commenting where elements do not match)
- collection: creating a new collection of the same type, populating it with the members of the source collection
- complex types: initialization through recursive translation
If the type of the name-matched property does not match the destination's type, the following conversions are applied where applicable (in priority order):
- simple assignment if the types are the same
- assigning the result of
ToString()
if the destination type is string
- assigning the result of
Parse()
if Parse
returns the same type as the destination type.
- initializing a new destination type with the properties of the source type
- assigning the result of an applicable
IConvertible
implementation.
To disable: #pragma warning disable PRd1000
(and #pragma warning restore PRd1000
to restore.)
This analyzer warns for public methods, fields (including events), and properties without XML comments.
To disable: #pragma warning disable PRm1000
(and #pragma warning restore PRm1000
to restore.)
The code fix creates new XML comments populating the summary by splitting the member name
by case change to generate an English sentence-structured comment.
Properties include the value
element, non-void
methods include the returns
element,
and parameterized methods include the param
element for each method parameter.
Known Issues
Multiple member field or event variables declared on the same line do not cause a warning.
Public methods, fields (including events), and properties that have XML comments but are
missing summary
, returns
, or param
cause a warning from the analyzer.
To disable: #pragma warning disable PRm1001
(and #pragma warning restore PRm1001
to restore.)
The code fix creates new XML comments, populating summary
by splitting the member name by
case change. (e.g., OpenFile
results in an Open file
summary
.)
Method Name Should Have Leading Transitive Verb Rule
Methods that do not start with an English transitive verb cause a warning of this rule.
To disable: #pragma warning disable PRm1010
(and #pragma warning restore PRm1010
to restore.)
Best practices suggest that a method implements a type's behavior and that the
method's name describes that behavior.
A transitive verb is a verb that refers to a direct object. If the method name is simply a transitive verb,
the assumption is that the verb refers to its implementation type. If the method name is a phrase, the
assumption is that the referred object is the noun within that phrase (that may or may not be the implementation type).
Boolean Property Name Should Have Leading Future Tense 'Able' Rule
Properties of type bool
(System.Boolean
) that don't begin with a future tense form of the verb
able cause a warning of this rule. Future tense forms of the verb able include “Is,”
“Are,” “Was,” “Were,” “Has,” or “Had,” or “Can.”