Skip to content

Latest commit

 

History

History
161 lines (121 loc) · 14.7 KB

PX1099.md

File metadata and controls

161 lines (121 loc) · 14.7 KB

PX1099

This document describes the PX1099 diagnostic.

Summary

Code Short Description Type Code Fix
PX1099 The API reported by the diagnostic should not be used with the Acumatica Framework. Warning Unavailable

Diagnostic Description

The PX1099 diagnostic detects APIs that should not be used with the Acumatica Framework. Each banned API may have its own reason for being banned. The next section provides an example of a banned API with the Math.Round overloads that do not specify a method for rounding a midpoint.

Banned Math.Round Overloads

By default, the System.Math.Round method uses Banker's rounding, an algorithm that rounds the midpoint to the nearest even number. This means that 12.5 will be rounded to 12 and 13.5 to 14. This behavior is not compatible with Microsoft Excel rounding, which by default uses midpoint rounding away from zero. This behavior also surprises many developers, who expect midpoint rounding away from zero which is better known.

On the other hand, Banker's rounding to even has its own advantages. The midpoint rounding away from zero on average has a bigger rounding error than Banker's rounding because more numbers are rounded up than down. With the away-from-zero rounding, the rounding error from multiple operations will be bigger on average.

You can use either type of rounding, but it is important to understand which one is used in the code and to be consistent and explicit with it. Thus, the PX1099 diagnostic forbids the Math.Round method overloads that do not specify a method for rounding a midpoint.

Example of Incorrect Code

In the following example, a forbidden overload of the System.Math.Round is used.

public class MyGraph : PXGraph<MyGraph>
{
	public virtual decimal CalculateCuryAmount(decimal amount, decimal curyRate, int precision)
	{
		// The rounding used by default will be Banker's Rounding, which rounds the midpoint to the nearest even number. This behavior can be unexpected for developers who are used to rounding away from zero.
		return Math.Round(amount * curyRate, precision);   
	}
}

Example of Correct Code

This example shows how to specify the Math.Round method with the MidpointRounding.AwayFromZero parameter to round the midpoint away from zero.

public class MyGraph : PXGraph<MyGraph>
{
	public virtual decimal CalculateCuryAmount(decimal amount, decimal curyRate, int precision)
	{
		return Math.Round(amount * curyRate, precision, MidpointRounding.AwayFromZero);   
	}
}

Analysis Overview

The main idea of the PX1099 analysis is that all API usages in the checked code are checked against a list of forbidden APIs. The API is reported if any of the following criteria is met:

  • The API itself is in the list of banned APIs.
  • A namespace containing an API is in the list of banned APIs.
  • One of the types contains an API is in the list of banned APIs. In case of nested types, the API is banned if any of containing types is in the list of banned APIs.
  • The API is a type and one of its base types is in the list of banned APIs.
  • The API is a method, property or event; also it is an override of a base type member, and one of the overridden members is in the list of banned APIs.

The diagnostic also supports a list of allowed APIs that are not reported even if they are recognized as forbidden. For example, the analysis reports the System.Environment type and all its members as forbidden. However, the System.Environment.NewLine property is allowed and is not reported by the PX1099 diagnostic. The list of allowed APIs makes it possible to avoid frequently reported false positives and to configure analysis more granularly.

Diagnostic Settings

The PX1099 diagnostic provides advanced configuration options that you can use to customize the diagnostic behavior. You can disable the PX1099 diagnostic or configure custom files with banned and allowed APIs. You can find the PX1099 settings in the following Acuminator section of Visual Studio settings: Tools -> Options -> Acuminator -> Banned API. Banned API settings

The following settings are available:

  • Enable PX1099 diagnostic for banned APIs: Enables or disables the PX1099 diagnostic. By default, the diagnostic is enabled.
  • Banned APIs File: Specifies the path to the file with banned APIs.
  • Allowed APIs File: Specifies the path to the file with allowed APIs.

Banned and Allowed APIs

Acuminator comes with default lists of banned and allowed APIs. These files are deployed by Acuminator on your machine in the <My Documents Folder>\Acuminator\Acumatica Banned API folder. The Banned APIs File and Allowed APIs File settings are initially set to these files. You can modify these files to customize the list of banned and allowed APIs.

Note, that clearing the Banned APIs File and Allowed APIs File settings in Visual Studio will not prevent the PX1099 diagnostic from running. The diagnostic will use the default lists of banned and allowed APIs that are embedded in the Acuminator assemblies. To disable the PX1099 diagnostic, you need to set the Enable PX1099 diagnostic for banned APIs setting to false.

Default Banned APIs

The following table shows the default banned APIs that are included in the Acuminator.

API Name API Type API Ban Type Ban Reason
System.Math.Round(double) Method General Math.Round uses Banker's Rounding by default, which rounds to the closest even number. Usually, this is not the desired rounding behavior. Use the Math.Round overload with the MidpointRounding parameter to explicitly specify the desired rounding behavior.
System.Math.Round(decimal) Method General Math.Round uses Banker's Rounding by default, which rounds to the closest even number. Usually, this is not the desired rounding behavior. Use the Math.Round overload with the MidpointRounding parameter to explicitly specify the desired rounding behavior.
System.Math.Round(double, int) Method General Math.Round uses Banker's Rounding by default, which rounds to the closest even number. Usually, this is not the desired rounding behavior. Use the Math.Round overload with the MidpointRounding parameter to explicitly specify the desired rounding behavior.
System.Math.Round(decimal, int) Method General Math.Round uses Banker's Rounding by default, which rounds to the closest even number. Usually, this is not the desired rounding behavior. Use the Math.Round overload with the MidpointRounding parameter to explicitly specify the desired rounding behavior.
System.Data.Entity Namespace ISV Use of the System.Data.Entity namespace is forbidden in Acumatica customization projects.
System.Data.SqlClient Namespace ISV Use of the System.Data.SqlClient namespace is forbidden in Acumatica customization projects.
System.AppDomain Type ISV Use of the AppDomain type is forbidden in Acumatica customization projects.
System.Diagnostics.ProcessStartInfo Type ISV Use of the ProcessStartInfo type is forbidden in Acumatica customization projects.
System.Environment Type ISV Use of the Environment type is forbidden in Acumatica customization projects.
System.IO.File Type ISV Use of the File type is forbidden in Acumatica customization projects.
System.GC Type ISV Access to garbage collector is forbidden in Acumatica customization projects.
System.OperatingSystem Type ISV Use of the OperatingSystem type is forbidden in Acumatica customization projects.
System.Reflection.MethodInfo Type ISV Use of reflection is forbidden in Acumatica customization projects.
PX.Common.WebConfig Type ISV Access to the WebConfig type is forbidden in Acumatica customization projects.
System.Threading.Tasks.Parallel Type General Use of the Parallel type is forbidden in Acumatica because it may lead to deadlocks and a loss of Acumatica synchronization context. It also prevents Acumatica request profiler and resource governor from correctly managing system resources.
System.Linq.ParallelEnumerable.AsParallel all overloads Method General Use of Parallel LINQ is forbidden in Acumatica because it may lead to deadlocks and a loss of Acumatica synchronization context. It also prevents Acumatica request profiler and resource governor from correctly managing system resources.
System.Threading.Tasks.Task.Run all overloads Method General Use of the Task.Run method is forbidden in Acumatica because it may lead to deadlocks and a loss of Acumatica synchronization context. It also prevents Acumatica request profiler and resource governor from correctly managing system resources.
System.Threading.Tasks.Task.Run<TResult> all overloads Method General Use of the Task.Run method is forbidden in Acumatica because it may lead to deadlocks and a loss of Acumatica synchronization context. It also prevents Acumatica request profiler and resource governor from correctly managing system resources.
System.Threading.Tasks.Task.Start all overloads Method General Use of the Task.Start method is forbidden in Acumatica because it may lead to deadlocks and a loss of Acumatica synchronization context. It also prevents Acumatica request profiler and resource governor from correctly managing system resources.
System.Threading.Tasks.Task.ConfigureAwait(bool) Method General Use of the Task.ConfigureAwait method is forbidden in Acumatica because it may lead to deadlocks and a loss of Acumatica synchronization context. It also prevents Acumatica request profiler and resource governor from correctly managing system resources.
System.Threading.Tasks.Task<TResult>.ConfigureAwait(bool) Method General Use of the Task.ConfigureAwait method is forbidden in Acumatica because it may lead to deadlocks and a loss of Acumatica synchronization context. It also prevents Acumatica request profiler and resource governor from correctly managing system resources.

You can also find the latest version of this list in the Acuminator GitHub repository: https://github.com/Acumatica/Acuminator/blob/dev/src/Acuminator/Acuminator.Utilities/BannedApi/Data/BannedApis.txt

Default Allowed APIs

The following table shows the default allowed APIs that are included in the Acuminator.

API Name API Type
System.Environment.NewLine Property

You can also find the latest version of the white list in the Acuminator GitHub repository: https://github.com/Acumatica/Acuminator/blob/dev/src/Acuminator/Acuminator.Utilities/BannedApi/Data/AllowedApis.txt

API Format

The records in the file with banned APIs have the same API format. Each API record is represented by a single line in the file and consists of the following three parts separated by a whitespace:

  1. A mandatory API identifier.
  2. A mandatory API ban type that indicates for whom API is banned. There are two available values:
    • General indicates that the API is banned for all developers.
    • ISV indicates that the API is banned for ISV developers only.
  3. An optional API ban reason. This is a string that explains why the API is banned.

The API identifier is based on the DocID format, which was chosen due to its convenience. For more information, see https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/xmldoc/#id-strings. This format is widely used by .Net technology, and Roslyn already has built-in functionality to generate DocID for APIs. However, the DocID format has been enhanced in Acuminator to store more information about the API as follows:

  • In the full API name, the namespace part is separated from the containing type names with a special hyphen (-) separator. Acuminator uses the separator to deduce which part of the API name is the namespace. This capability is impossible in the standard DocID format. An example of an API name with a namespace is shown in the following string.
    T:System-Environment
  • If the full API name includes nested types, then their names are separated by a plus sign (+) to simplify the parsing of the API name into parts, as shown in the following example.
    T:Microsoft.AspNet.Mvc.ModelBinding-ModelStateDictionary+PrefixEnumerable

The file with allowed APIs has the same format as the file with banned APIs. However, the "API Ban Type" part, while being mandatory is ignored by Acuminator. We recommend that you always set this type to General. The API ban reason in the file with allowed APIs is not used by Acuminator and should be omitted.

Related Articles