waldo1001 / crs-al-language-extension

Make working with the (Dynamics NAV / 365) AL Language easier and more efficient.
MIT License
34 stars 43 forks source link

Rename on Save can produce garbage code #111

Closed marknitek closed 5 years ago

marknitek commented 5 years ago

We use OnSaveAlFileACtion = Rename on our projects.

Sometimes (seems like its getting worse now the code base has grown) we get very weird results after saving and renaming the file.

The problem arises when we save al files converted by txt2al and crs has to "normalize" or "fix" the content. I have seen such functionality in the code (SaveAutoFixesToFile()) i guess its to rename fields actions etc? The result is that randomly content is inserted in the al file, and some code can be "lost" which is very very very bad... I have some screenshots of the result but i can not directly reproduce it every time. But i think it could be related to the state when the AL Compiler loses track due to to many issues in the code?

Examples:

Left is original converted al file right is the file saved in vs code after the "normalization" Btw it got rid of the documentaiton trigger, which is ok for me but also unexpected! I was able to reproduce that specific one 2 times out of 5 tries if the window reloads after save I think it does not happen (never) if the window is not reloaded. The Window Reload seems to happen if the al compiler still "works" but if it gives up the window does not reload after save. image

Another example of code from a collegue, marked in yellow the garbage content inserted randomly to the file (seems like its mostly spaces?) image

As i said i had an example that removed content from the code, but i have no screenshot of that one

waldo1001 commented 5 years ago

If you can share the files with me, I would be able to debug?

marknitek commented 5 years ago

Here is a Report that causes the issue. The Report is a copy of a standard CH report with a few modifications.

But i cannot reproduce the issue in a fresh al project (no other files) It seems like it happens only for projects with a lot of .al files. At least we have 2 of them that have the issue. They both contain several 100 files

But i think i have found a way to reproduce:

Result: Code inserted at and of file: image

AL Language Extension Stack Trace

Unbehandelte Ausnahme: System.NullReferenceException: Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt.
   bei Microsoft.Dynamics.Nav.EditorServices.Protocol.LanguageServer.DiagnosticsProvider.<GetDocumentDiagnostics>d__2.MoveNext() in F:\a\35\s\source\Prod\Microsoft.Dynamics.Nav.EditorServices.Protocol\LanguageServer\DiagnosticsProvider.cs:Zeile 124.
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
   bei System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   bei Microsoft.Dynamics.Nav.DiagnosticService.<GetAndEmitPartialDiagnostics>d__43.MoveNext() in F:\a\35\s\source\Prod\Microsoft.Dynamics.Nav.EditorServices.Protocol\LanguageServer\DiagnosticService.cs:Zeile 334.
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
   bei System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   bei Microsoft.Dynamics.Nav.DiagnosticService.<ListenForBufferChanges>d__37.MoveNext() in F:\a\35\s\source\Prod\Microsoft.Dynamics.Nav.EditorServices.Protocol\LanguageServer\DiagnosticService.cs:Zeile 250.
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
   bei System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   bei System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   bei System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
   bei System.Threading.ThreadPoolWorkQueue.Dispatch()
[Info  - 10:30:02] Connection to server got closed. Server will restart.
[Error - 10:30:02] Request textDocument/documentSymbol failed.
Error: Connection got disposed.
    at Object.dispose (C:\Users\m.niederberger\.vscode\extensions\ms-dynamics-smb.al-2.1.109895\node_modules\vscode-jsonrpc\lib\main.js:825:25)
...

Report Object

report 3010545 "DTA Payment Journal"
{
    // version NAVCH13.00,LEP13.0.0.0
    DefaultLayout = RDLC;
    RDLCLayout = './DTA Payment Journal.rdlc';

    Caption = 'DTA Payment Journal';

    dataset
    {
        dataitem("Gen. Journal Line";Table81)
        {
            DataItemTableView = SORTING(Journal Template Name,Journal Batch Name,Posting Date,Clearing,Debit Bank);
            column(JournalBatchName_GenJournalLine;"Journal Batch Name")
            {
            }
            column(PageNumber;CurrReport.PAGENO)
            {
            }
            column(TodayFormatted;FORMAT(TODAY,0,4))
            {
            }
            column(CompanyName;COMPANYPROPERTY.DISPLAYNAME)
            {
            }
            column(intLayout;intLayout)
            {
            }
            column(AccountNo_GenJournalLine;"Account No.")
            {
            }
            column(VendorLedgerEntryDueDate;FORMAT(VendorLedgerEntry."Due Date"))
            {
            }
            column(AppliestoDocNo_GenJournalLine;"Applies-to Doc. No.")
            {
            }
            column(CurrencyCode_GenJournalLine;"Currency Code")
            {
            }
            column(Amount_GenJournalLine;Amount)
            {
            }
            column(CashDiscAmtFC;CashDiscAmtFC)
            {
            }
            column(CashDeductAmt;CashDeductAmt)
            {
            }
            column(AgeDays;AgeDays)
            {
            }
            column(CashDiscDays;CashDiscDays)
            {
            }
            column(DueDays;DueDays)
            {
            }
            column(OpenRemAmtFC;OpenRemAmtFC)
            {
            }
            column(RestAfterPmt;RestAfterPmt)
            {
            }
            column(VendorName;Vendor.Name)
            {
            }
            column(PmtToleranceAmount;PmtToleranceAmount)
            {
            }
            column(VendorBankAccountPaymentForm;VendorBankAccount."Payment Form")
            {
                OptionCaption = 'ESR,ESR+,Post Payment Domestic,Bank Payment Domestic,Cash Outpayment Order Domestic,Post Payment Abroad,Bank Payment Abroad,SWIFT Payment Abroad,Cash Outpayment Order Abroad';
                OptionMembers = ESR,"ESR+","Post Payment Domestic","Bank Payment Domestic","Cash Outpayment Order Domestic","Post Payment Abroad","Bank Payment Abroad","SWIFT Payment Abroad","Cash Outpayment Order Abroad";
            }
            column(xAcc;xAcc)
            {
            }
            column(xTxt;xTxt)
            {
            }
            column(BankCode_GenJournalLine;"Recipient Bank Account")
            {
            }
            column(DebitBank_GenJournalLine;"Debit Bank")
            {
            }
            column(VendorLedgerEntryExternalDocumentNo;VendorLedgerEntry."External Document No.")
            {
            }
            column(TotalVendorTxt;TotalVendorTxt)
            {
            }
            column(AmountLCY_GenJournalLine;"Amount (LCY)")
            {
            }
            column(GenJournalLineTotalBankDebitBank;Text006Msg + ' ' + "Debit Bank" )
            {
            }
            column(GlSetupLCYCode;GLSetup."LCY Code")
            {
            }
            column(n;n)
            {
            }
            column(LargestAmt;LargestAmt)
            {
            }
            column(PostingDate_GenJournalLine;FORMAT("Posting Date"))
            {
            }
            column(TotalPaymentGlSetupLCYCode;STRSUBSTNO(Text007Lbl,GLSetup."LCY Code"))
            {
            }
            column(LargestAmtGlSetupLCYCode;STRSUBSTNO(Text008Lbl,GLSetup."LCY Code"))
            {
            }
            column(BatchNameCaption;BatchNameCaptionLbl)
            {
            }
            column(PageCaption;PageCaptionLbl)
            {
            }
            column(DTAPaymentJournalCaption;DTAPaymentJournalCaptionLbl)
            {
            }
            column(PaymentCaption;PaymentCaptionLbl)
            {
            }
            column(AgeCaption;AgeCaptionLbl)
            {
            }
            column(PossCaption;PossCaptionLbl)
            {
            }
            column(DeduCaption;DeduCaptionLbl)
            {
            }
            column(VendorCaption;VendorCaptionLbl)
            {
            }
            column(CashDiscCaption;CashDiscCaptionLbl)
            {
            }
            column(BeforePmtCaption;BeforePmtCaptionLbl)
            {
            }
            column(RestAfterPmtCaption;RestAfterPmtCaptionLbl)
            {
            }
            column(OpenRemAmountCaption;OpenRemAmountCaptionLbl)
            {
            }
            column(ApplicationCaption;ApplicationCaptionLbl)
            {
            }
            column(DateDaysCaption;DateDaysCaptionLbl)
            {
            }
            column(DueCaption;DueCaptionLbl)
            {
            }
            column(CashDiscDaysCaption;CashDiscDaysCaptionLbl)
            {
            }
            column(ToleranceCaption;ToleranceCaptionLbl)
            {
            }
            column(CurrencyCodeCaption_GenJournalLine;FIELDCAPTION("Currency Code"))
            {
            }
            column(BankCaption;BankCaptionLbl)
            {
            }
            column(ReferenceCommentCaption;ReferenceCommentCaptionLbl)
            {
            }
            column(PaymentTypeCaption;PaymentTypeCaptionLbl)
            {
            }
            column(AccountCaption;AccountCaptionLbl)
            {
            }
            column(DebitBankCaption;DebitBankCaptionLbl)
            {
            }
            column(ExternalDocumentCaption;ExternalDocumentCaptionLbl)
            {
            }
            column(VendorBankCaption;VendorBankCaptionLbl)
            {
            }
            column(NoOfPaymentsCaption;NoOfPaymentsCaptionLbl)
            {
            }
            column(PostingDateCaption;PostingDateCaptionLbl)
            {
            }
            column(LineNo_GenJournalLine;"Line No.")
            {
            }
            column(Clearing_GenJournalLine;Clearing)
            {
            }
            column(CurrencyCodeArray_1;CurrencyCodeArray[1])
            {
            }
            column(CurrencyCodeArray_2;CurrencyCodeArray[2])
            {
            }
            column(CurrencyCodeArray_3;CurrencyCodeArray[3])
            {
            }
            column(CurrencySumArray_1;CurrencySumArray[1])
            {
            }
            column(CurrencySumArray_2;CurrencySumArray[2])
            {
            }
            column(CurrencySumArray_3;CurrencySumArray[3])
            {
            }
            column(AccountSearchName;"Account Search Name")
            {
            }

            trigger OnAfterGetRecord()
            begin
                IF ("Account No." = '') AND (Amount = 0) THEN
                  CurrReport.SKIP;

                IF oldAccNo <> "Account No." THEN BEGIN
                  oldAccNo := "Account No.";
                  NoOfLinesPerVendor := 0;
                END;

                AgeDays := 0;
                CashDiscDays := 0;
                DueDays := 0;
                CashDeductAmt := 0;
                RestAfterPmt := 0;
                PmtToleranceAmount := 0;
                xTxt := '';
                xAcc := '';
                CLEAR(VendorLedgerEntry);
                CLEAR(VendorBankAccount);
                Vendor.GET("Account No.");

                // Vendor Entries
                IF "Applies-to Doc. No." = '' THEN
                  xTxt := Text000Err
                ELSE BEGIN
                  VendorLedgerEntry.SETCURRENTKEY("Document No.");
                  VendorLedgerEntry.SETRANGE("Document Type","Applies-to Doc. Type");
                  VendorLedgerEntry.SETRANGE("Document No.","Applies-to Doc. No.");
                  VendorLedgerEntry.SETRANGE("Vendor No.","Account No.");
                  // LEPCH-1205
                  VendorLedgerEntry.SETFILTER("Currency Code",'=%1',"Currency Code");
                  // LEPCH-1205 END
                  IF NOT VendorLedgerEntry.FINDFIRST THEN
                    xTxt := Text001Err
                  ELSE BEGIN
                    IF NOT VendorLedgerEntry.Open THEN
                      xTxt := Text002Err;

                    VendorLedgerEntry.CALCFIELDS("Remaining Amount");

                    // Calc day for age, due date and cash disc.
                    IF VendorLedgerEntry."Posting Date" > 0D THEN
                      AgeDays := "Posting Date" - VendorLedgerEntry."Posting Date";
                    IF VendorLedgerEntry."Pmt. Discount Date" > 0D THEN
                      CashDiscDays := VendorLedgerEntry."Pmt. Discount Date" - "Posting Date";
                    IF VendorLedgerEntry."Due Date" > 0D THEN
                      DueDays := VendorLedgerEntry."Due Date" - "Posting Date";

                    OpenRemAmtFC := -VendorLedgerEntry."Remaining Amount";
                    CashDiscAmtFC := -VendorLedgerEntry."Remaining Pmt. Disc. Possible";

                    // Open entry and remaining for multicurrency. Convert to pmt currency
                    IF VendorLedgerEntry."Currency Code" <> "Currency Code" THEN BEGIN
                      OpenRemAmtFC :=
                        CurrencyExchangeRate.ExchangeAmtFCYToFCY(
                          "Posting Date",VendorLedgerEntry."Currency Code","Currency Code",-VendorLedgerEntry."Remaining Amount");
                      CashDiscAmtFC :=
                        CurrencyExchangeRate.ExchangeAmtFCYToFCY(
                          "Posting Date",VendorLedgerEntry."Currency Code","Currency Code",-VendorLedgerEntry."Original Pmt. Disc. Possible");
                    END;

                    IF (VendorLedgerEntry."Pmt. Discount Date" >= "Posting Date") OR
                       ((VendorLedgerEntry."Pmt. Disc. Tolerance Date" >= "Posting Date") AND
                        VendorLedgerEntry."Accepted Pmt. Disc. Tolerance")
                    THEN
                      CashDeductAmt := -VendorLedgerEntry."Remaining Pmt. Disc. Possible";

                    PmtToleranceAmount := -VendorLedgerEntry."Accepted Payment Tolerance";

                    // Calc rest after pmt (and evtl. cash disc)
                    RestAfterPmt := OpenRemAmtFC - Amount - CashDeductAmt - PmtToleranceAmount;
                    IF RestAfterPmt > 0 THEN BEGIN
                      RestAfterPmt := RestAfterPmt + CashDeductAmt;
                      CashDeductAmt := 0;
                    END;
                  END;
                END;

                // Vendor Bank Account
                IF "Recipient Bank Account" = '' THEN
                  xTxt := Text003Err
                ELSE
                  IF NOT VendorBankAccount.GET("Account No.","Recipient Bank Account") THEN
                    xTxt := Text004Err;

                IF xTxt = '' THEN
                  CASE VendorBankAccount."Payment Form" OF
                    VendorBankAccount."Payment Form"::ESR,VendorBankAccount."Payment Form"::"ESR+":
                      BEGIN
                        xAcc := VendorBankAccount."ESR Account No.";
                        xTxt := VendorLedgerEntry."Reference No.";
                      END;
                    VendorBankAccount."Payment Form"::"Post Payment Domestic":
                      BEGIN
                        IF VendorBankAccount.IBAN <> '' THEN
                          xAcc := DTAMgt.IBANDELCHR(VendorBankAccount.IBAN)
                        ELSE
                          xAcc := VendorBankAccount."Giro Account No.";
                      END;
                    VendorBankAccount."Payment Form"::"Bank Payment Domestic":
                      IF VendorBankAccount.IBAN <> '' THEN
                        xAcc := DTAMgt.IBANDELCHR(VendorBankAccount.IBAN)
                      ELSE BEGIN
                        xTxt := VendorBankAccount."Clearing No.";
                        xAcc := VendorBankAccount."Bank Account No.";
                      END;
                    VendorBankAccount."Payment Form"::"Post Payment Abroad":
                      BEGIN
                        IF VendorBankAccount.IBAN <> '' THEN
                          xAcc := DTAMgt.IBANDELCHR(VendorBankAccount.IBAN)
                        ELSE
                          xAcc := VendorBankAccount."Bank Account No.";
                      END;
                    VendorBankAccount."Payment Form"::"Bank Payment Abroad":
                      IF VendorBankAccount.IBAN <> '' THEN
                        xAcc := DTAMgt.IBANDELCHR(VendorBankAccount.IBAN)
                      ELSE BEGIN
                        xTxt := VendorBankAccount."Bank Identifier Code";
                        xAcc := VendorBankAccount."Bank Account No.";
                      END;
                    VendorBankAccount."Payment Form"::"SWIFT Payment Abroad":
                      IF VendorBankAccount.IBAN <> '' THEN
                        xAcc := DTAMgt.IBANDELCHR(VendorBankAccount.IBAN)
                      ELSE BEGIN
                        xTxt := VendorBankAccount."SWIFT Code";
                        xAcc := VendorBankAccount."Bank Account No.";
                      END;
                  END;

                n := n + 1;
                IF "Amount (LCY)" > LargestAmt THEN
                  LargestAmt := "Amount (LCY)";

                NoOfLinesPerVendor := NoOfLinesPerVendor + 1;
                // LEP7.00
                // IF NoOfLinesPerVendor > 1 THEN
                IF NoOfLinesPerVendor > 0 THEN
                // LEP7.00 END
                  TotalVendorTxt := Text005Msg + ' ' + "Account No." + ' ' + Vendor.Name;

                // LEP7.00 - A0054
                IF "Currency Code" <> '' THEN BEGIN
                  CurrencySumArray[FindCurrencyArrayNo("Currency Code")] += Amount;
                END;
                // LEP7.00 - A0054 END
            end;

            trigger OnPreDataItem()
            begin
                SETRANGE("Account Type","Account Type"::Vendor);
                SETRANGE("Document Type","Document Type"::Payment);

                intLayout := Layout;
                oldAccNo := '';

                // LEP7.00
                IF Sorting = 1 THEN
                  SETCURRENTKEY("Account Search Name");
                // LEP7.00 END
            end;
        }
    }

    requestpage
    {
        SaveValues = true;

        layout
        {
            area(content)
            {
                group(Options)
                {
                    Caption = 'Options';
                    field(Layout;Layout)
                    {
                        ApplicationArea = Basic,Suite;
                        Caption = 'Layout';
                        OptionCaption = 'Amounts,Bank';
                        ToolTip = 'Specifies the layout of the report. Layout options include Amounts and Bank.';
                    }
                    field(Sorting;Sorting)
                    {
                        Caption = 'Sorting';
                        OptionCaption = 'by Vendor No.,by Vendor Search Name';
                    }
                }
            }
        }

        actions
        {
        }
    }

    labels
    {
    }

    trigger OnPreReport()
    begin
        GLSetup.GET;
    end;

    var
        Text000Err: Label 'No application number';
        Text001Err: Label 'Vendor entry not found';
        Text002Err: Label 'Vendor entry not open';
        Text003Err: Label 'Bankcode not defined';
        Text004Err: Label 'Vendor bank not found';
        Text005Msg: Label 'Total vendor';
        Text006Msg: Label 'Total bank';
        Text007Lbl: Label 'Total Payment in %1';
        Text008Lbl: Label 'Largest Amount in %1';
        VendorBankAccount: Record "288";
        VendorLedgerEntry: Record "25";
        CurrencyExchangeRate: Record "330";
        GLSetup: Record "98";
        Vendor: Record "23";
        DTAMgt: Codeunit "3010541";
        n: Integer;
        "Layout": Option Amounts,Bank;
        xTxt: Text[40];
        xAcc: Text;
        LargestAmt: Decimal;
        TotalVendorTxt: Text[80];
        NoOfLinesPerVendor: Integer;
        AgeDays: Integer;
        CashDiscDays: Integer;
        DueDays: Integer;
        OpenRemAmtFC: Decimal;
        CashDiscAmtFC: Decimal;
        CashDeductAmt: Decimal;
        PmtToleranceAmount: Decimal;
        RestAfterPmt: Decimal;
        intLayout: Integer;
        oldAccNo: Code[20];
        BatchNameCaptionLbl: Label 'Batch Name';
        PageCaptionLbl: Label 'Page';
        DTAPaymentJournalCaptionLbl: Label 'DTA - Payment Journal';
        PaymentCaptionLbl: Label 'Payment';
        AgeCaptionLbl: Label 'Age';
        PossCaptionLbl: Label 'Poss.';
        DeduCaptionLbl: Label 'Dedu.';
        VendorCaptionLbl: Label 'Vendor';
        CashDiscCaptionLbl: Label 'Cash Disc.';
        BeforePmtCaptionLbl: Label 'before Pmt.';
        RestAfterPmtCaptionLbl: Label 'after Pmt.';
        OpenRemAmountCaptionLbl: Label 'Open Rem. Amount';
        ApplicationCaptionLbl: Label 'Application';
        DateDaysCaptionLbl: Label 'Date / Days';
        DueCaptionLbl: Label 'Due';
        CashDiscDaysCaptionLbl: Label 'C Dis.';
        ToleranceCaptionLbl: Label 'Tolerance';
        BankCaptionLbl: Label 'Bank';
        ReferenceCommentCaptionLbl: Label 'Reference / Comment';
        PaymentTypeCaptionLbl: Label 'Pmt. Type';
        AccountCaptionLbl: Label 'Account';
        DebitBankCaptionLbl: Label 'Debit Bank';
        ExternalDocumentCaptionLbl: Label 'Ext. Doc.';
        VendorBankCaptionLbl: Label 'Vendor Bank';
        NoOfPaymentsCaptionLbl: Label 'No. of payments';
        PostingDateCaptionLbl: Label 'Posting Date';
        "----LEP": Integer;
        Sorting: Option;
        CurrencyCodeArray: array [100] of Code[20];
        CurrencySumArray: array [100] of Decimal;

    procedure FindCurrencyArrayNo(_CurrencyCode: Code[20]): Integer
    var
        i: Integer;
    begin
        // BASIS041 - A0054
        FOR i := 1 TO 100 DO BEGIN
          IF CurrencyCodeArray[i] = _CurrencyCode THEN
            EXIT(i);
          IF CurrencyCodeArray[i] = '' THEN BEGIN
            CurrencyCodeArray[i] := _CurrencyCode;
            EXIT(i);
          END;
        END;
        // BASIS041 - A0054 END
    end;
}
waldo1001 commented 5 years ago

Can I have your crs-settings?

waldo1001 commented 5 years ago

Are you sure it's because of my extension? I tested the report - all fine. And the stacktrace is referring to the code analysis of the al extension ... ?

The "autofixes" is basically going to add prefixes, and fix the object name. I don't see this failing "sometimes" - should fail always (or never) ;-).

I'm going to keep this open until I'm able to repro (I have a few ideas to test this out on big projects)

marknitek commented 5 years ago

settings.json:

{
    "al.codeAnalyzers": [
        "${AppSourceCop}",
        "${CodeCop}",
        "${UICop}"
    ],
    "al.enableCodeAnalysis": true,
    "al.ruleSetPath": "./.vscode/logico.ruleset.json",

    "CRS.ObjectNamePrefix": "LOG BASE ",
    "CRS.OnSaveAlFileAction": "Rename"
}

Ok it happens even if the code analysis error/crash does not happen...

I'am not sure what exactly causes it, but if i set OnSaveAlFileAction to DoNothing the file does not get corrupted on save. I'am totally with you that is should work/fail always or never. It's indeed a very strange behaviour.

Could it be that the crs autofixes conflict with the format document that happens on save?

marknitek commented 5 years ago

I tried saving by using the command Save without Formating Ctrl+K Ctrl+Shift+S (stupid default shortcut btw...) and i think now it does not happen anymore.

I can also disable format on save, that seems to work too, but then i loose formating ability completly (which i dont want to). => Format Document command stops doing anything

settings.json (workspace)

    "[al]": {
        "editor.formatOnSave": false
    }

The Editor sometimes does not reload after rename (the old file(name) stays open and is marked as deleted by vs code), but i could live with that.

So the question is why do they both not work together in some situations? Timing Issue of async method executions? parallel fs write?

marknitek commented 5 years ago

Ok its definitly NOT a CRS issue! At least not just, its a weird combination, but read on...

I can force the behaviour manually by triggering format document! Instead of saving the document i trigger the format document at that point where i assume the issue will arise. That is when the al extension stops working and only would recover when reloading the window. At this point the AL formating is broken

I assume this has something to do with it (non existing reference at the end of the file): image

=> Indirectly it has to do with crs since i think crs rename on save can break the al language extension, because when i turn it off the al language extension works without issues therefore the formating works flawless too. The mentioned error in the al language code analysis only happens when RenameOnSave is enabled

waldo1001 commented 5 years ago

I'm going to close this issue - if you encounter it again, or can point me in a very direct direction (may be by uploading a repro-app), then let's open it again ...