dangmai / prettier-plugin-apex

Code formatter for the Apex Programming Language
https://apex.dangmai.net
MIT License
256 stars 44 forks source link

Apex files not formatting #339

Closed miguelriverarios closed 3 years ago

miguelriverarios commented 3 years ago

Apex (.cls) files are not formatting on paste, on save, via the package.json command, or via the terminal commands. I do have editor.formatOnSave and editor.formatOnPaste enabled on vscode. I also have editor.defaultFormatter set to "esbenp.prettier-vscode".

The package.json script is:

"prettier --write \"**/*.{cls,cmp,component,css,html,js,json,md,page,trigger,xml,yaml,yml}\""

I'm using the project generated via the SFDX Create Project palette command, which generates most of the boiler plate code needed to get this up-and-running as far as I can tell. When starting a new project, I run 'yarn install' and all dependencies appear to load correctly. The native prettier plugin works fine on other file types (js, html, etc), but when I work in an apex file, I get the following error:


["INFO" - 10:11:34 AM] Formatting c:\Users\Miguel Rivera Rios\Documents\Jobs\Open Road Alliance\Scripts\Salesforce\CustomLightningFieldLayoutsLWC\force-app\main\default\classes\FieldSetsTest.cls
["INFO" - 10:11:34 AM] Using ignore file (if present) at c:\Users\Miguel Rivera Rios\Documents\Jobs\Open Road Alliance\Scripts\Salesforce\CustomLightningFieldLayoutsLWC\.prettierignore
["INFO" - 10:11:34 AM] Loaded module 'prettier@2.2.1' from 'c:\Users\Miguel Rivera Rios\Documents\Jobs\Open Road Alliance\Scripts\Salesforce\CustomLightningFieldLayoutsLWC\node_modules\prettier\index.js'
["INFO" - 10:11:34 AM] File Info:
{
  "ignored": false,
  "inferredParser": "apex"
}
["INFO" - 10:11:35 AM] Detected local configuration (i.e. .prettierrc or .editorconfig), VS Code configuration will not be used
["INFO" - 10:11:35 AM] Using config file at 'c:\Users\Miguel Rivera Rios\Documents\Jobs\Open Road Alliance\Scripts\Salesforce\CustomLightningFieldLayoutsLWC\.prettierrc'
["INFO" - 10:11:35 AM] Prettier Options:
{
  "filepath": "c:\\Users\\Miguel Rivera Rios\\Documents\\Jobs\\Open Road Alliance\\Scripts\\Salesforce\\CustomLightningFieldLayoutsLWC\\force-app\\main\\default\\classes\\FieldSetsTest.cls",
  "parser": "apex",
  "trailingComma": "none"
}
["ERROR" - 10:11:35 AM] Error formatting document.
Error: 
    at parseTextWithSpawn (c:\Users\Miguel Rivera Rios\Documents\Jobs\Open Road Alliance\Scripts\Salesforce\CustomLightningFieldLayoutsLWC\node_modules\prettier-plugin-apex\src\parser.js:36:11)
    at Object.parse (c:\Users\Miguel Rivera Rios\Documents\Jobs\Open Road Alliance\Scripts\Salesforce\CustomLightningFieldLayoutsLWC\node_modules\prettier-plugin-apex\src\parser.js:489:21)
    at Object.parse (c:\Users\Miguel Rivera Rios\Documents\Jobs\Open Road Alliance\Scripts\Salesforce\CustomLightningFieldLayoutsLWC\node_modules\prettier\index.js:13625:19)
    at coreFormat (c:\Users\Miguel Rivera Rios\Documents\Jobs\Open Road Alliance\Scripts\Salesforce\CustomLightningFieldLayoutsLWC\node_modules\prettier\index.js:14899:14)
    at format (c:\Users\Miguel Rivera Rios\Documents\Jobs\Open Road Alliance\Scripts\Salesforce\CustomLightningFieldLayoutsLWC\node_modules\prettier\index.js:15131:14)
    at c:\Users\Miguel Rivera Rios\Documents\Jobs\Open Road Alliance\Scripts\Salesforce\CustomLightningFieldLayoutsLWC\node_modules\prettier\index.js:57542:12
    at Object.format (c:\Users\Miguel Rivera Rios\Documents\Jobs\Open Road Alliance\Scripts\Salesforce\CustomLightningFieldLayoutsLWC\node_modules\prettier\index.js:57562:12)
    at t.default.<anonymous> (c:\Users\Miguel Rivera Rios\.vscode\extensions\esbenp.prettier-vscode-5.8.0\dist\extension.js:1:17599)
    at Generator.next (<anonymous>)
    at s (c:\Users\Miguel Rivera Rios\.vscode\extensions\esbenp.prettier-vscode-5.8.0\dist\extension.js:1:11597)
["INFO" - 10:11:35 AM] Formatting completed in 116.501ms.

I found a similar issue posted on the main prettier page. The solution offered was to verify that the JAVA_HOME environment variable was pointing to a updated version of java. I've tried changing this to a few different instances, but it doesn't seem to resolve anything. At the moment, I have it pointing to the same Java instance from my vs code user settings (C:\Program Files\AdoptOpenJDK\jdk-11.0.6.10-hotspot). I also see on this site that I needed to add %JAVA_HOME%/bin to the path variable, so I did that, but it doesn't seem to have made a difference.

According to the error stack, the issue is somewhere around here in the parser.js source file:

serializedAst = parseTextWithSpawn(
      sourceCode,
      options.parser === "apex-anonymous",
    );

Let me know if I've done anything wrong or if you need additional information. Below are some additional configuration details.

VS Code User Settings

  "salesforcedx-vscode-apex.java.home": "C:\\Program Files\\AdoptOpenJDK\\jdk-11.0.6.10-hotspot",
  "terminal.integrated.shell.windows": "C:\\Program Files\\Git\\bin\\bash.exe",
  "editor.formatOnPaste": true,
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "salesforcedx-vscode-core.retrieve-test-code-coverage": true

.prettierrc

{
  "trailingComma": "none",
  "overrides": [
    {
      "files": "**/lwc/**/*.html",
      "options": { "parser": "lwc" }
    },
    {
      "files": "*.{cmp,page,component}",
      "options": { "parser": "html" }
    }
  ]
}

Additional information (please fill this out):

dangmai commented 3 years ago

Hi, thanks for opening the bug report. A couple of questions before we dive deeper:

  1. Is your source code valid Apex code? I know this sounds trivial, but a lot of bug requests turn out to be invalid Apex code. Easiest way to test this is to save it to a Salesforce environment, if it saves successfully then it's valid.
  2. Does this happen on one file or all files? If it's just one file, is it possible for you to share that file with me so I can check it on my computer?
  3. Does your code use any new Apex feature? It's possible that a new feature was released that I wasn't aware of, and the library doesn't have support for it yet.

Once we are sure that it's not the Apex content that's the problem, then we can look at Java issues. I use AdoptOpenJDK 11 as well, and Prettier Apex runs fine on my computer.

miguelriverarios commented 3 years ago

Hello and thanks for the quick reply.

1) Totally understand why you would ask, and yes. I've been ignoring this bug for a while, so I've already uploaded this code into my production environment and it works as expected. I also tested it out in some scratch orgs and everything seemed fine.

2) Seems to occur across files and projects, but I wouldn't be surprised if I've somehow messed up my vscode settings. You can see some of the files here I'm experiencing the issues with all the apex files in that folder, but if you want to test it out, the simplest one might be the RelatedObjects file.

3) Um I don't think I'm using any new features. I'm building a lightning web component for use in the lightning app builder, so it's possible that some of the VisualEditor classes are new, but I think I'm doing basic stuff.

Let me know if you need anything else.

dangmai commented 3 years ago

I cloned your project and on my PC Prettier Apex has no problem formatting the files, so we can remove Apex file content as a possible root cause. At this point I'm very much leaning towards local configs that somehow stop Prettier Apex from working. Can you paste the results for the following commands (you can run this in your project directory):

yarn list prettier
yarn list prettier-plugin-apex
echo %JAVA_HOME%
java -version
miguelriverarios commented 3 years ago

$ yarn list prettier; yarn list prettier-plugin-apex; echo %JAVA_HOME%; java -version;

yarn list v1.22.10
warning Filtering by arguments is deprecated. Please use the pattern option instead.
└─ prettier@2.2.1
Done in 0.60s.

yarn list v1.22.10
warning Filtering by arguments is deprecated. Please use the pattern option instead.
└─ prettier-plugin-apex@1.8.0
Done in 0.59s.

%JAVA_HOME%

openjdk version "11.0.6" 2020-01-14
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.6+10)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.6+10, mixed mode)

I generally use git bash as my default terminal in vscode. I noticed that it doesn't resolve environment variables (ie the result of echo %JAVA_HOME% is %JAVA_HOME%), but if I switch to cmd in vscode I get the expanded path: C:\Program Files\AdoptOpenJDK\jdk-11.0.6.10-hotspot

dangmai commented 3 years ago

Thank you for the output, they do look fine to me. My hunch is telling me that Git Bash may be the issue here, possibly because of the way it resolves paths (and possibly because OpenJDK was not compiled for that environment). A very quick way to check if that's the case is to run these commands (assuming you have the same script in your package.json) in both Git Bash and CMD, and see if one works and the other doesn't:

# Delete node-modules first before running these for both environments
yarn
yarn run prettier
miguelriverarios commented 3 years ago

I tried those commands in git bash and cmd and I get the same errors (I did try deleting node_modules before running in each environment). Just to confirm, that script is prepopulated from sfdx and looks like this:

"prettier": "prettier --write \"**/*.{cls,cmp,component,css,html,js,json,md,page,trigger,xml,yaml,yml}\"",

The error output is the same from both terminals: cmd:

config\project-scratch-def.json 40ms
force-app\main\default\aura\.eslintrc.json 6ms
force-app\main\default\classes\FieldSets.cls
[error] force-app\main\default\classes\FieldSets.cls: Error
[error]     at parseTextWithSpawn (C:\Users\Miguel Rivera Rios\Documents\Jobs\Open Road Alliance\Scripts\Salesforce\CustomLightningFieldLayoutsLWC\node_modules\prettier-plugin-apex\src\parser.js:36:11) 
[error]     at Object.parse (C:\Users\Miguel Rivera Rios\Documents\Jobs\Open Road Alliance\Scripts\Salesforce\CustomLightningFieldLayoutsLWC\node_modules\prettier-plugin-apex\src\parser.js:489:21)      
[error]     at Object.parse (C:\Users\Miguel Rivera Rios\Documents\Jobs\Open Road Alliance\Scripts\Salesforce\CustomLightningFieldLayoutsLWC\node_modules\prettier\index.js:13625:19)
[error]     at coreFormat (C:\Users\Miguel Rivera Rios\Documents\Jobs\Open Road Alliance\Scripts\Salesforce\CustomLightningFieldLayoutsLWC\node_modules\prettier\index.js:14899:14)
[error]     at format (C:\Users\Miguel Rivera Rios\Documents\Jobs\Open Road Alliance\Scripts\Salesforce\CustomLightningFieldLayoutsLWC\node_modules\prettier\index.js:15131:14)
[error]     at Object.args [as formatWithCursor] (C:\Users\Miguel Rivera Rios\Documents\Jobs\Open Road Alliance\Scripts\Salesforce\CustomLightningFieldLayoutsLWC\node_modules\prettier\index.js:57542:12)
[error]     at format (C:\Users\Miguel Rivera Rios\Documents\Jobs\Open Road Alliance\Scripts\Salesforce\CustomLightningFieldLayoutsLWC\node_modules\prettier\bin-prettier.js:15883:14)
[error]     at Object.formatFiles (C:\Users\Miguel Rivera Rios\Documents\Jobs\Open Road Alliance\Scripts\Salesforce\CustomLightningFieldLayoutsLWC\node_modules\prettier\bin-prettier.js:16067:16)        
[error]     at Object.run (C:\Users\Miguel Rivera Rios\Documents\Jobs\Open Road Alliance\Scripts\Salesforce\CustomLightningFieldLayoutsLWC\node_modules\prettier\bin-prettier.js:16538:14)
[error]     at Object.<anonymous> (C:\Users\Miguel Rivera Rios\Documents\Jobs\Open Road Alliance\Scripts\Salesforce\CustomLightningFieldLayoutsLWC\node_modules\prettier\bin-prettier.js:16553:5)

git bash:

config\project-scratch-def.json 46ms
force-app\main\default\aura\.eslintrc.json 4ms
force-app\main\default\classes\FieldSets.cls
[error] force-app\main\default\classes\FieldSets.cls: Error
[error]     at parseTextWithSpawn (C:\Users\Miguel Rivera Rios\Documents\Jobs\Open Road Alliance\Scripts\Salesforce\CustomLightningFieldLayoutsLWC\node_modules\prettier-plugin-apex\src\parser.js:36:11) 
[error]     at Object.parse (C:\Users\Miguel Rivera Rios\Documents\Jobs\Open Road Alliance\Scripts\Salesforce\CustomLightningFieldLayoutsLWC\node_modules\prettier-plugin-apex\src\parser.js:489:21)      
[error]     at Object.parse (C:\Users\Miguel Rivera Rios\Documents\Jobs\Open Road Alliance\Scripts\Salesforce\CustomLightningFieldLayoutsLWC\node_modules\prettier\index.js:13625:19)
[error]     at coreFormat (C:\Users\Miguel Rivera Rios\Documents\Jobs\Open Road Alliance\Scripts\Salesforce\CustomLightningFieldLayoutsLWC\node_modules\prettier\index.js:14899:14)
[error]     at format (C:\Users\Miguel Rivera Rios\Documents\Jobs\Open Road Alliance\Scripts\Salesforce\CustomLightningFieldLayoutsLWC\node_modules\prettier\index.js:15131:14)
[error]     at Object.args [as formatWithCursor] (C:\Users\Miguel Rivera Rios\Documents\Jobs\Open Road Alliance\Scripts\Salesforce\CustomLightningFieldLayoutsLWC\node_modules\prettier\index.js:57542:12)
[error]     at format (C:\Users\Miguel Rivera Rios\Documents\Jobs\Open Road Alliance\Scripts\Salesforce\CustomLightningFieldLayoutsLWC\node_modules\prettier\bin-prettier.js:15883:14)
[error]     at Object.formatFiles (C:\Users\Miguel Rivera Rios\Documents\Jobs\Open Road Alliance\Scripts\Salesforce\CustomLightningFieldLayoutsLWC\node_modules\prettier\bin-prettier.js:16067:16)        
[error]     at Object.run (C:\Users\Miguel Rivera Rios\Documents\Jobs\Open Road Alliance\Scripts\Salesforce\CustomLightningFieldLayoutsLWC\node_modules\prettier\bin-prettier.js:16538:14)
[error]     at Object.<anonymous> (C:\Users\Miguel Rivera Rios\Documents\Jobs\Open Road Alliance\Scripts\Salesforce\CustomLightningFieldLayoutsLWC\node_modules\prettier\bin-prettier.js:16553:5)

I got one error stack per apex file, but just showing the first chunk from each terminal.

dangmai commented 3 years ago

This is indeed pretty bizarre, thank you for helping me debug this deeper. Can you run this in either environment (from your project directory)?

node_modules\prettier-plugin-apex\vendor\apex-ast-serializer\bin\apex-ast-serializer.bat -f json -i -p -l force-app\main\default\classes\FieldSets.cls

If Java can be invoked correctly, it will print out a JSON tree for the entire Apex AST class (it will be very long).

ClayChipps commented 3 years ago

I was having this same error, and thanks to that command you just sent @dangmai, I figured it out for myself. I had the directory nested too deep and the path was too long, throwing a windows error when trying to run the .bat file. I am guessing the plugin was having the same issue when trying to run it in VSCode. In either case, thank you, helped solve my problem!

dangmai commented 3 years ago

I'm glad to hear that @ctchipps, hopefully it's the same underlying issue for OP as well :)

miguelriverarios commented 3 years ago

Wow thanks. When I tried to run that command in git bash, I got:

node_modulesprettier-plugin-apexvendorapex-ast-serializerbinapex-ast-serializer.bat: command not found

But when I tried in cmd, I got:

The input line is too long.
The syntax of the command is incorrect.

Which to be honest would have meant nothing to me without @ctchipps comment. But I just moved my project up a few levels in folder structure (I just manually copied and pasted it) and I am able to format the apex files when I'm in the new folder (the only difference being it's location). I'll re-organize files on my system, so I don't run into this issue going forward.

Thanks for your support.

dangmai commented 3 years ago

I'm glad to hear that your issue is resolved! This is definitely a quirk from the Windows platform, but I'll try to see if there's a way to know that it's going to happen before actually invoking the bat file, and have more meaningful error messages.