mogular / powerquery-formatter-examples

9 stars 1 forks source link

Enhancement #4

Closed C00P5 closed 4 years ago

C00P5 commented 4 years ago

Not really a bug but an enhancement. If the source code has already been edited with comments "//" or "/ /", it would be nice to have these remain after parsing the editor.

UliPlabst commented 4 years ago

Hey, that would indeed be a great feature and the reason I did not yet implement it is because we are using the official powerquery-parser. What we receive from this library is the AST of your query and we traverse the AST and format the code accordingly. Unfortunately the comments are not part of the Ast. They are available however, but I will have to match the comments to the node that the comment belongs to by myself. Unfortunately this is not a trivial task and I didn't have time yet to implement it. I will update you as soon as I have time to implement this. Thanks for your suggestion.

UliPlabst commented 4 years ago

Ok so I had some spare time yesterday in the evening and I looked into this. I found a very basic way of supporting comments: Line comments (with "//") will be always one whitespace after the last node and inline comments ("/ /") will be always seperated with one whitespace from the node to the left and to the right. It would be nice to be able to align all line comments e.g. to the same column. Unfortunately that would require some more work so maybe I will implement this in the future.
You can also now toggle includeComments in the options section in the formatter to configure whether comments should be included. Please let me know if this is already sufficient for you or if any problems occur.

C00P5 commented 4 years ago

Well done and thanks. I tried a couple and it seems to keep the comments in the formatted PQ.

Even if a line space is inserted before the comment (even two line spaces) the comment runs on at the end of the previous line. I could live with that. Thanks again.

UliPlabst commented 4 years ago

You're welcome.
I see, I didn't think about lines that only contain comments. I just uploaded a patch which seems to be working.
I put in this query:

let
  MyFunc = (netValue as number /*test*/) => 
    let /* asd */
//tests
      MwSt = 0.19, //tests
/* testing */
      valueAfterTax /* asd */ = netValue * (1 + MwSt) //test
    in //tst
//iss
/*asd*/
//asd

//asd
      valueAfterTax
in
//test
  MyFunc
//test

I get out this

let
  MyFunc = (netValue as number /*test*/ ) => 
    let /* asd */ 
      //tests
      MwSt = 0.19, //tests
      /* testing */
      valueAfterTax /* asd */  = netValue * (1 + MwSt) //test
    in //tst
      //iss
      /*asd*/
      //asd
      //asd
      valueAfterTax
in
  //test
  MyFunc
//test

So I remove all empty lines but preserve newlines after comments. I also indent the comment to the next most node.
I also count inline comments to the line character count, so if you have a line

  valueAfterTax /* aaaaaaaaa*/  = netValue * (1 + MwSt) //test

and you add many more as to the comment so that it will exceed the line length it will force the expression to break. On the other hand line comments do not affect the break behavior at the moment.
I'm not sure if I thought of all the edge-cases but all it seems to be working with all test-cases that I have right now. If you encounter any issues let me know.

C00P5 commented 4 years ago

It worked brilliantly. Thanks from DownUnder

let   // Import AU ArTrnDetails db   AUSource = Sql.Database("sqlserver.xxxxxx.local", "EncoreCompanyR"),   AUdbo_ArTrnDetail = AUSource{[Schema = "dbo", Item = "ArTrnDetail"]}[Data],   AUChangeDateTimeToDate = Table.TransformColumnTypes(AUdbo_ArTrnDetail, {     {"InvoiceDate", type date}   }),   AUFilterDatesPerParameter = Table.SelectRows(AUChangeDateTimeToDate, each [InvoiceDate]     >= StartTableDates),   AURemovedOtherColumns = Table.SelectColumns(AUFilterDatesPerParameter, {     "TrnYear",      "TrnMonth",      "Invoice",      "InvoiceDate",      "Branch",      "Salesperson",      "Customer",      "StockCode",      "Area",      "ProductClass",      "Warehouse",      "CustomerClass",      "QtyInvoiced",      "NetSalesValue",      "CostValue",      "GlYear",      "GlPeriod",      "PostCurrency",      "PostConvRate"   }),   AURemoveICSales = Table.SelectRows(     AURemovedOtherColumns,      each  not Text.StartsWith([Branch], "9")   ),   AUCleanStkCodes = Table.SelectRows(     AURemoveICSales,      each  not Text.Contains([StockCode], "Pric") and [StockCode] <> " "   ),   // Import EU ArTrnDetails db   EUSource = Sql.Database("sqlserver.xxxxxx.local", "SysproCompanyE"),   EUdbo_ArTrnDetail = EUSource{[Schema = "dbo", Item = "ArTrnDetail"]}[Data],   EUChangeDateTimeToDate = Table.TransformColumnTypes(EUdbo_ArTrnDetail, {     {"InvoiceDate", type date}   }),   EUFilterDatesPerParameter = Table.SelectRows(EUChangeDateTimeToDate, each [InvoiceDate]     >= StartTableDates),   EURemovedOtherColumns = Table.SelectColumns(EUFilterDatesPerParameter, {     "TrnYear",      "TrnMonth",      "Invoice",      "InvoiceDate",      "Branch",      "Salesperson",      "Customer",      "StockCode",      "Area",      "ProductClass",      "Warehouse",      "CustomerClass",      "QtyInvoiced",      "NetSalesValue",      "CostValue",      "GlYear",      "GlPeriod",      "PostCurrency",      "PostConvRate"   }),   EURemoveICSales = Table.SelectRows(     EURemovedOtherColumns,      each  not Text.StartsWith([Branch], "9")   ),   EUCleanStkCodes = Table.SelectRows(     EURemoveICSales,      each  not Text.Contains([StockCode], "Pric") and [StockCode] <> " "   ),   // Import US ArTrnDetails db   USSource = Sql.Database("sqlserver.xxxxxx.local", "SysproCompanyU"),   USdbo_ArTrnDetail = USSource{[Schema = "dbo", Item = "ArTrnDetail"]}[Data],   USChangeDateTimeToDate = Table.TransformColumnTypes(USdbo_ArTrnDetail, {     {"InvoiceDate", type date}   }),   USFilterDatesPerParameter = Table.SelectRows(USChangeDateTimeToDate, each [InvoiceDate]     >= StartTableDates),   USRemovedOtherColumns = Table.SelectColumns(USFilterDatesPerParameter, {     "TrnYear",      "TrnMonth",      "Invoice",      "InvoiceDate",      "Branch",      "Salesperson",      "Customer",      "StockCode",      "Area",      "ProductClass",      "Warehouse",      "CustomerClass",      "QtyInvoiced",      "NetSalesValue",      "CostValue",      "GlYear",      "GlPeriod",      "PostCurrency",      "PostConvRate"   }),   USRemoveICSales = Table.SelectRows(     USRemovedOtherColumns,      each  not Text.StartsWith([Branch], "9")   ),   USCleanStkCodes = Table.SelectRows(     USRemoveICSales,      each  not Text.Contains([StockCode], "Pric") and [StockCode] <> " "   ),   // Import SI ArTrnDetails db   SISource = Sql.Database("sqlserver.xxxxxx.local", "SysproCompanyS"),   SIdbo_ArTrnDetail = SISource{[Schema = "dbo", Item = "ArTrnDetail"]}[Data],   SIChangeDateTimeToDate = Table.TransformColumnTypes(SIdbo_ArTrnDetail, {     {"InvoiceDate", type date}   }),   SIFilterDatesPerParameter = Table.SelectRows(SIChangeDateTimeToDate, each [InvoiceDate]     >= StartTableDates),   SIRemovedOtherColumns = Table.SelectColumns(SIFilterDatesPerParameter, {     "TrnYear",      "TrnMonth",      "Invoice",      "InvoiceDate",      "Branch",      "Salesperson",      "Customer",      "StockCode",      "Area",      "ProductClass",      "Warehouse",      "CustomerClass",      "QtyInvoiced",      "NetSalesValue",      "CostValue",      "GlYear",      "GlPeriod",      "PostCurrency",      "PostConvRate"   }),   SIRemoveICSales = Table.SelectRows(     SIRemovedOtherColumns,      each  not Text.StartsWith([Branch], "9")   ),   SICleanStkCodes = Table.SelectRows(     SIRemoveICSales,      each  not Text.Contains([StockCode], "Pric") and [StockCode] <> " "   ),   // Combine above queries   CombineAll = Table.Combine({AUCleanStkCodes, EUCleanStkCodes, USCleanStkCodes, SICleanStkCodes}),   //Merge Salesperson data   LinkSalePersonNameTable = Table.NestedJoin(     CombineAll,      {"Branch", "Salesperson"},      SalSalesperson,      {"Branch", "Salesperson"},      "SalSalesperson",      JoinKind.LeftOuter   ),   ShowSalesPersonName = Table.ExpandTableColumn(     LinkSalePersonNameTable,      "SalSalesperson",      {"Name"},      {"SalespersonName"}   ),   RemoveSalepersonCode = Table.RemoveColumns(ShowSalesPersonName, {"Salesperson"}),   // Merge Foreign Exchange data   TempChgGlYearToText = Table.TransformColumnTypes(RemoveSalepersonCode, {{"GlYear", type text}}),   MergeAUDFx = Table.NestedJoin(     TempChgGlYearToText,      {"Branch", "GlYear"},      CurrencyAUDBase,      {"CompanyCode", "SYSPROYear"},      "CurrencyAUDBase",      JoinKind.LeftOuter   ),   SelectCurrencyAUDBase = Table.ExpandTableColumn(MergeAUDFx, "CurrencyAUDBase", {"AUDFx"}, {     "AUDFx"   }),   MergeEURFx = Table.NestedJoin(     SelectCurrencyAUDBase,      {"Branch", "GlYear"},      CurrencyEURBase,      {"CompanyCode", "SYSPROYear"},      "CurrencyEURBase",      JoinKind.LeftOuter   ),   SelectCurrencyEURBase = Table.ExpandTableColumn(MergeEURFx, "CurrencyEURBase", {"EURFx"}, {     "EURFx"   }),   MergeUSDFx = Table.NestedJoin(     SelectCurrencyEURBase,      {"Branch", "GlYear"},      CurrencyUSDBase,      {"CompanyCode", "SYSPROYear"},      "CurrencyUSDBase",      JoinKind.LeftOuter   ),   SelectCurrencyUSDBase = Table.ExpandTableColumn(MergeUSDFx, "CurrencyUSDBase", {"USDFx"}, {     "USDFx"   }),   // Create FEx values from Base Ccy values   CreateNetSaleAUD = Table.AddColumn(SelectCurrencyUSDBase, "NetSaleAUD", each Number.Round(     [NetSalesValue] / [AUDFx],      2   )),   CreateNetSaleEUR = Table.AddColumn(CreateNetSaleAUD, "NetSaleEUR", each Number.Round(     [NetSalesValue] / [EURFx],      2   )),   CreateNetSaleUSD = Table.AddColumn(CreateNetSaleEUR, "NetSaleUSD", each Number.Round(     [NetSalesValue] / [USDFx],      2   )),   CreateNetCostAUD = Table.AddColumn(CreateNetSaleUSD, "NetCostAUD", each Number.Round(     [CostValue] / [AUDFx],      2   )),   CreateNetCostEUR = Table.AddColumn(CreateNetCostAUD, "NetCostEUR", each Number.Round(     [CostValue] / [EURFx],      2   )),   CreateNetCostUSD = Table.AddColumn(CreateNetCostEUR, "NetCostUSD", each Number.Round(     [CostValue] / [USDFx],      2   )),   ChangedType = Table.TransformColumnTypes(CreateNetCostUSD, {     {"NetSaleAUD", type number},      {"NetSaleEUR", type number},      {"NetSaleUSD", type number},      {"NetCostAUD", type number},      {"NetCostEUR", type number},      {"NetCostUSD", type number},      {"GlYear", type number}   }),   // Clean tables of redundant Columns   FinalSalesDetails = Table.RemoveColumns(ChangedType, {     "PostCurrency",      "PostConvRate",      "AUDFx",      "EURFx",      "USDFx"   }) in   FinalSalesDetails

UliPlabst commented 4 years ago

Cool, you're welcome. Greetings from Germany.