GithubHelp home page GithubHelp logo

stefanmaron / businesscentral.lintercop Goto Github PK

View Code? Open in Web Editor NEW
68.0 9.0 25.0 662 KB

Community driven code linter for AL (MS Dynamics 365 Business Central)

Home Page: https://stefanmaron.com

License: MIT License

C# 99.88% Smalltalk 0.12%
msdyn365bc al businesscentral linter clean-code

businesscentral.lintercop's Issues

System.IndexOutOfRangeException

Hi,

I have just installed the extension i VS Code, and enabled the code analyzer.

I'm getting the following exception, this goes both for existing projects, and a brand new one created with AL:Go

Analyzer 'BusinessCentral.LinterCop.Design.Rule0012DoNotUseObjectIdInSystemFunctions' threw an exception of type 'System.IndexOutOfRangeException' with message 'System.IndexOutOfRangeException: Index was outside the bounds of the array. at System.Collections.Immutable.ImmutableArray1.get_Item(Int32 index) at BusinessCentral.LinterCop.Design.Rule0012DoNotUseObjectIdInSystemFunctions.CheckForObjectIdsEventSubscribers(SymbolAnalysisContext context) at Microsoft.Dynamics.Nav.CodeAnalysis.Diagnostics.AnalyzerExecutor.<>c__DisplayClass49_2.<ExecuteSymbolActionsCore>b__0() in D:\a\1\s\source\Prod\Microsoft.Dynamics.Nav.CodeAnalysis\DiagnosticAnalyzer\AnalyzerExecutor.cs:line 656 at Microsoft.Dynamics.Nav.CodeAnalysis.Diagnostics.AnalyzerExecutor.ExecuteAndCatchIfThrows_NoLock(DiagnosticAnalyzer analyzer, Action analyze, Nullable1 info) in D:\a\1\s\source\Prod\Microsoft.Dynamics.Nav.CodeAnalysis\DiagnosticAnalyzer\AnalyzerExecutor.cs:line 1078'

[LC0017] Analyzer crashes with InvalidCastException

I am getting the following error after upgrading to the latest version of the LinterCop in one of my projects:

[{
	"resource": "/c:/[redacted]/app.json",
	"owner": "_generated_diagnostic_collection_name_#0",
	"code": "AD0001",
	"severity": 4,
	"message": "Analyzer 'BusinessCentral.LinterCop.Design.Rule0017WriteToFlowField' threw an exception of type 'System.InvalidCastException' with message 'System.InvalidCastException: Unable to cast object of type 'Microsoft.Dynamics.Nav.CodeAnalysis.BoundTextIndexAccess' to type 'Microsoft.Dynamics.Nav.CodeAnalysis.IFieldAccess'.
   at BusinessCentral.LinterCop.Design.Rule0017WriteToFlowField.CheckForWriteToFlowField(OperationAnalysisContext context)
   at Microsoft.Dynamics.Nav.CodeAnalysis.Diagnostics.AnalyzerExecutor.<>c__DisplayClass53_1.<ExecuteOperationAction>b__1() in D:\a\1\s\source\Prod\Microsoft.Dynamics.Nav.CodeAnalysis\DiagnosticAnalyzer\AnalyzerExecutor.cs:line 764
   at Microsoft.Dynamics.Nav.CodeAnalysis.Diagnostics.AnalyzerExecutor.ExecuteAndCatchIfThrows_NoLock(DiagnosticAnalyzer analyzer, Action analyze, Nullable`1 info) in D:\a\1\s\source\Prod\Microsoft.Dynamics.Nav.CodeAnalysis\DiagnosticAnalyzer\AnalyzerExecutor.cs:line 1100'",
	"source": "AL",
	"startLineNumber": 1,
	"startColumn": 1,
	"endLineNumber": 1,
	"endColumn": 1
}]

Please let me know if you need any files uploaded to troubleshoot this, I can't really make out what the issue is here.

EDIT: It should be noted that this happens with one specific project after upgrading. I cannot reproduce this in any of my other projects.

LC0013 - improvements

Really nice to find all those places where a NotBlank has been missed! ๐Ÿ‘

But two things:

  • I think that an explicit NotBlank = false should suppress this warning. In that way we could allow blank PK for the setup tables. Right now I get a lot of warnings about NotBlank is missing from all setup tables, and I want to avoid pragmas as long as possible and rather have explicit declarations...
  • A small spelling error: "Tables with a single field PK sould have NotBlank set to true" are missing an "h" in "should" :)

Exclude 'Obsoleted' objects from all LinterCop rules

We've quit some objects (incl. upgrade tables) that have been marked with an ObsoleteState and thus deserve no further attention from being maintained. It would be nice if (all?) LinterCop rules could fully ignore any object marked with ObsoleteState.

image

LC0013 threw an exception of type 'System.InvalidCastException'

Hi @StefanMaron,

Rule LC0013 raises the following error for us:

Analyzer 'BusinessCentral.LinterCop.Design.Rule0013CheckForNotBlankOnSingleFieldPrimaryKeys' threw an exception of type 'System.InvalidCastException' with message 'System.InvalidCastException: Unable to cast object of type 'Microsoft.Dynamics.Nav.CodeAnalysis.Symbols.SourceTableExtensionTypeSymbol' to type 'Microsoft.Dynamics.Nav.CodeAnalysis.ITableTypeSymbol'.
   at BusinessCentral.LinterCop.Design.Rule0013CheckForNotBlankOnSingleFieldPrimaryKeys.CheckForSingleFieldPrimaryKeysNotBlank(SymbolAnalysisContext context)
   at Microsoft.Dynamics.Nav.CodeAnalysis.Diagnostics.AnalyzerExecutor.<>c__DisplayClass49_2.<ExecuteSymbolActionsCore>b__0() in D:\a\1\s\source\Prod\Microsoft.Dynamics.Nav.CodeAnalysis\DiagnosticAnalyzer\AnalyzerExecutor.cs:line 656
   at Microsoft.Dynamics.Nav.CodeAnalysis.Diagnostics.AnalyzerExecutor.ExecuteAndCatchIfThrows_NoLock(DiagnosticAnalyzer analyzer, Action analyze, Nullable`1 info) in D:\a\1\s\source\Prod\Microsoft.Dynamics.Nav.CodeAnalysis\DiagnosticAnalyzer\AnalyzerExecutor.cs:line 1100'

This can be reproduced with an app with a table extension on the Item table, e.g.:

tableextension 50100 ItemExt extends Item
{
    fields
    {
        field(50100; MyField; Code[20])
        {
            Caption = 'MyField';
            DataClassification = CustomerContent;
        }
    }
}

Table Objects temporary not with prim. key auto. Increment

Discussed in #22

Originally posted by KristofKlein September 25, 2021
A table object can be set - per definition - to be temporary only.

It behaves as a normal table object while it gets designed. But not while runtime! We found out, that it allows you to define a primary key with auto increment. But since the auto increment is a feature that the SQL server executes it is actually not working for temp tables (like in CAL).
So It would be nice to get a hint, that it is not possible to use an auto. inc. ...or guide into the direction to use a number sequence instead?

LC0003 Do not use an Object ID for properties - False positive on AccessByPermission = TableData

Hi @StefanMaron,
It seems like rule LC0003 gives a false positive on the AccessByPermission for the following sample:

action("Reservation Entries")
{
    AccessByPermission = TableData Item = R;
    ApplicationArea = Reservation;
    Caption = 'Reservation Entries';
    Image = ReservationLedger;
    ToolTip = 'View all reservations that are made for the item, either manually or automatically.';

    trigger OnAction()
    begin
        Rec.ShowReservationEntries(true);
    end;
}

sample_LC0003_false_positive

Could you have a look?

Thank you for the code analyzer and extension! :)

Check that all undocumented procedures has internal access modifier

This warning will push developers to make sure all public extension API is documented or to make sure that it is not public. It's even more important for AppSource apps as all public procedures are locked for future modifications if they are public so will act as an additional notification to set internal access modifier if it's not intended to be an app public API.

LC0015 False positives on temporary tables

LC0015 warns on tables with TableType = Temporary.

A user does not need permissions to write or read data in temporary tables, so I believe that LC0015 should skip the warning if there are no PermissionSet with TableData for that table.

The PTE0004 rule works in that way already.

CurrXmlPort vs. currXmlPort False Positives

Hi @StefanMaron,
It appears that with the new release LC0005 can't decide if it wants to have currXMLPort or CurrXmlPort. Could you resolve this? Perhaps accept both while we are at it? ๐Ÿ˜Š (simply because CurrXmlPort looks better, more consistent ๐Ÿ˜‡)

image

nextmajor false positives

When using AL Language extension from nextmajor (v9.0.582246) BC.LinterCop starts to flood me with false positives.

These are the ones I seen so far:

  • LC0002 - Comments is not detected
  • LC0003 - Complains on an Option parameter
  • LC0005 - Says that "Option" has wrong casing, it should be "Option" ๐Ÿ˜…
  • LC0010 - Maintainability index is 0 for all functions
  • LC0012 - Complains on RecRef.Open(MyRecord.MyFieldNo)
  • LC0014 - Says that PermissionSet names with 19 characters are longer than 30 chars

It's not urgent yet, but it might be something to start looking into. :)

Wrong Warning for Permissions in Object (e.g. Report)

I have the following in my codeunit and receive a wrong warning for permission declaration.

warning LC0003: Do not use an Object ID for properties or variables declaration. Use "tabledata "PRI-KA Entry" = R,
tabledata "Incoming Document" = RIM,
tabledata "Incoming Document Attachment" = RIMD" instead.

  report 50000 "PRI-KA Process Entries"
{
    Caption = 'Process ntries';
    UsageCategory = None;
    ProcessingOnly = true;
    Permissions = tabledata "PRI-KA Entry" = R,
     tabledata "Incoming Document" = RIM,
     tabledata "Incoming Document Attachment" = RIMD;

    dataset
    {
        dataitem(Entry; "PRI-KA Entry")
        {
            trigger OnAfterGetRecord()
            begin
                
            end;
        }
    }
}

LC0005 [Enhancement] Additional keyword casing checks to include

Hi @StefanMaron,
Here are some examples for which LC0005 could raise warnings for keyword-casing in a future release ๐Ÿ˜Š:

image

    AcTions
    {
        ArEa(ProceSsing)
        {
            AcTion(MyAction)
            {
                APPLICATIONAREA = All;
                ImaGe = Approval;

                TrigGer OnActiOn()
                begin
                    PaGe.RunModal(Page::"Customer Card");
                    Page.RunMOdal(Page::"Item Card");
                end;
            }

[Feature Request] Ignore LinterCop on selected files

I do not know if this is even possible, so just close it as "won't fix" if it isn't. ๐Ÿ™‚

I would really like to start using LinterCop on all our AppSource apps. But when activating LinterCop on a project with very old code, we get flooded with warnings.

Activating LinterCop with a "big bang" where we just sit down and go through thousands of warnings will not happen anytime soon, it will just take too much of the time we do not currently have.
Activating one rule at a time will still cause a lot of warnings to get through, depending on the rule of course. This will also limit the gain of using LinterCop...

This creates a big hurdle for us to start adopting LinterCop, and I assume that most ISVs will experience the same hurdle.

So here's my feature request for solving above:
Add a new setting to LinterCop.json, IgnoreFiles or similar, that is an array of glob patterns.
When running LinterCop on an .al file this setting is checked to see if the warnings in that file should be ignored.

In this way I can structure, and re-structure, my .al files in a way that makes LinterCop to be active in the files that I actively work on and in the files that has already been fixed to comply with all the rules.

Thoughts? Is it even technically possible?

Thanks,
Johannes

Document all rules

(a spin off from #48)

I believe that all the rules deserves their own .md file that documents them.

Our goal with this is actually to don't have any use of your CodeCop, because all code is perfect already ๐Ÿ˜‰

This documentation would help developers to understand why a warning appears and what to do to resolve them (and avoid them in the future).

As inspiration for headers in these files (not all for every rule, but one or more per rule):

  • Description
  • Bad code example
  • Good code example
  • Reason for the rule
  • How to fix this diagnostic?
  • Code examples triggering the rule
  • Code examples not triggering the rule

Microsoft is using all of above in different rule descriptions on MS Docs.

How about cyclomatic complexity?

@StefanMaron, as per the short discussion on you blog I am posting this question here: how about cyclomatic complexity? Or in other words: what became of this feature that was part of the AL Lint VS Code extension? Or is it in there and I do not understand how to get it triggered (btw: not expecting it as LinterCop is a cop)?

BTW: see #47, where I note thta the read.me is a bit sparse on telling what LinterCop is actually doing.

Issue with downloader gives unhelpful error.

I'm getting the error Cannot read property 'trim' of undefined under Runtime Status in vscode.

If I run the DownloadFile.ps1 directly I get some more errors ...

Invoke-RestMethod : The request was aborted: Could not create SSL/TLS secure channel.
At C:\Users\User\.vscode\extensions\stefanmaron.businesscentral-lintercop-0.1.0\DownloadFile.ps1:7 char:18
+ ... stRelease = Invoke-RestMethod -Uri "https://api.github.com/repos/Stef ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebExc
   eption
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

The machine I'm running on is a Windows Server 2016, the actual problem is that admin needs to set the below to allow Powershell to use TLS1.2.

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v2.0.50727]
"SystemDefaultTlsVersions"=dword:00000001
 
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v2.0.50727]
"SystemDefaultTlsVersions"=dword:00000001 

Now the PS1 script runs fine standalone, but I'm still getting the message.

It seems there's another issue ...

C:\Users\User\.vscode\extensions\stefanmaron.businesscentral-lintercop-0.1.0\DownloadFile.ps1 : Cannot dot-source
this command because it was defined in a different language mode. To invoke this command without importing its
contents, omit the '.' operator.
At line:1 char:1
+ . C:\Users\User\.vscode\extensions\stefanmaron.businesscentral-lint ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [DownloadFile.ps1], NotSupportedException
    + FullyQualifiedErrorId : DotSourceNotSupported,DownloadFile.ps1

Omitting the . operator makes it work.

Perhaps it would be best to do the download using Javacript within VSCode?

Settings to configure warnings and errors

Right now, the linter is creating warnings. Is there some way to make them errors or even better, can we define which issues should be errors and which should be warnings?

Preview release of dll

The auto deployment of the Linter Cop DLL is really neat!

But when deploying fixes it might be a bit to easy to deploy a fix with regression issues or that a new rule that is not yet 100% perfect creates zillions of new warnings that will just confuse users until they understand the rule completely.

So I suggest that a new boolean setting is added to the VSCode extension, Install Preview releases, or similar.
If this setting is active, the dll should be downloaded from another location - to where you deploy preview versions of the dll.

In that way you can get things tested out by a group of volunteers and get feedback before deploying to all users.

I would always have the preview release installed... ๐Ÿ˜‰

Thoughts?

LC0005 False positives/inconsistencies on XmlPort vs. Xmlport

Hi @StefanMaron,

This one is a bit tricky. Microsoft is being inconsistent in the AL Language for the casing of XmlPort.

  1. For variable declarations they expect XmlPort:

    var
        MyXmlPort: Xmlport "Export Contact";

    image

  2. For when you use IntelliSense to type a statement it suggests Xmlport:
    image

  3. But then when you hover over the following, it is expected to be written as XmlPort:

           XmlPort.Export(Xmlport::"Export Contact", MyOutStream);
           Xmlport.Export(XmlPort::"Export Contact", MyOutStream);

    image

    But note that for the first part of these statements, the LC0005 code analyzer doesn't even mind. ;)

    And when you would write it like this (which looks the best) and hover over it, then it 'suggests' Xmlport once more:

    XmlPort.Export(XmlPort::"Export Contact", MyOutStream);

    image

How do you think the LC0005 code should handle this? Should it allow both, or should we approach it differently?

LC0003 and LC0005 - False positives on DotNet variables

Hi @StefanMaron,

Ran into one more scenario where both LC0003 and LC0005 give a false positive. Which is for a DotNet variable declaration.
For example:

MyXMLDocument: DotNet XmlDocument;

(p.s., I am aware that there is an XmlDocument object type in AL, but this is just an example I ran into ๐Ÿ˜‰)

LC0012 reporting false positives for all event subscribers

Hi @StefanMaron,

Running into issues with rule LC0012 which reports a problem for any event subscriber.

Example:

    [EventSubscriber(ObjectType::Codeunit, Codeunit::"Guided Experience", 'OnRegisterAssistedSetup', '', false, false)]
    local procedure CodeunitGuidedExperience_OnRegisterAssistedSetup()
    begin
        /// ... some statement that invokes a procedure
    end;
Wrong Parameter detected. Select the correct object with "ObjectType::Codeunit;Codeunit::"Guided Experience"::" instead.

LC0005 False Positives of casing

The LC0005 rule is really great! It helped me to find a lot of casing issues.

But the last update introduced a few false positives.

I at least found three of them (maybe there are more):

  • Action datatype
  • Interface datatype
  • Page datatype

All those datatypes should begin with a capital letter, but LC0005 now thinks it should be all lowercase.

The following repro gets three warnings:

    procedure MyProcedure(MyAction: Action)
    var
        MyInterface: Interface "Price Asset";
        CustomerCard: Page "Customer Card";
    begin
    end;

The common thing with those keywords is that they all are both data types and another keyword. Don't know if that's the cause, though...

  • action is used in pages.
  • interface and page is object types.

[LC0016] False positive on system parts

The newly introduced rule gives a warning of a missing caption on system parts, such as Links, while I'm pretty sure those are already added by the application. Manually-added normal page parts such as factboxes are properly detected by the rule.

LC0005 False positive on DotNet datatypes (N.B. Allow aliases)

Hi @StefanMaron,
I reported this one earlier to you via a DM, but I think you might have missed it in the final release.
The following variable/parameter declaration gives a false positive:

var vXMLNode: DotNet XmlNode

The alias is XmlNode which should be allowed, and is preferred.

It would also be fine for me to skip DotNet variables completely though.

[LC0016] CaptionClass

Following code results in a LC0016 warning for the label control, although the text is set through the CaptionClass property.

group(Instructions)
            {
                ShowCaption = false;
                Visible = not _OpenClicked;
                Editable = false;

                label(InstructionText)
                {
                    ApplicationArea = All;
                    CaptionClass = GetInstructionText();
                    Style = Strong;
                    StyleExpr = true;
                }

LC0003 fails on lower case object names

Reading the message

Do not use an Object ID for properties or variables declaration. Use NVT Electronic Document Setup instead.

image

I would expect an object ID being used, that needs replacements.

image

However, the object name is used, but the casing is not respected (it should have been written as 'NVT Electronic Document Setup' instead). For me this seems like an invalid candidate for the LC0003 rule and fits more the LC0005 rule (which we've excluded)

LC0015 and eXecute permissions on Tables

The LC0015 rule warns if you are missing the execute (X) permissions on pages, codeunits etc., which is great!

But for tables it seems as if only the TableData is being checked.

I think that the execute permissions on Table should be checked as well, so that both TableData and Table must be defined in at least one PermissionSet for each object in the extension.

LC0015 warns about "Record MyTable" instead of "TableData MyTable"

Here's another thing I found when using LC0015:

In the warning for LC0015 it prints warning LC0015: The application object Record My Table is not covered by any permission set in the extension. when the TableData for the table is not included in any PermissionSet.

I would suggest to change the warning to warning LC0015: The application object TableData "My Table" is not covered by any permission set in the extension.

So two changes:

  1. TableData instead of Table (if it's not the Table that we mean, if #127 is implemented ;-))
  2. Add double quotes around the object name. This would make it easier to copy & paste the warnings and generate the missing permissions in a PermissionSet object.

Now I'm done adding issues for today. ;-)
Keep up the good work and have a great weekend!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.