vscode-clang-format icon indicating copy to clipboard operation
vscode-clang-format copied to clipboard

Set -assume-filename based on VSCode language associations

Open metafeather opened this issue 7 years ago • 12 comments

AFAIK there is currently not a way to map file extensions to the languages that clang-format supports when using this extension.

For example, I use the extension '.es6' for some javascript files to disambiguate with '.js' files written in ES5 style.

Clang Format supports a command line flag -assume-filename which is currently being set directly:

https://github.com/xaverh/vscode-clang-format-provider/blob/master/src/extension.ts#L191

I have not found a way to override this by use of the style rules or existing extension settings.

As a solutions I would suggest:

  1. Simple option: expose the arguments array as a VSCode setting, to be merged with the defaults. This could then be switched at run time by VSCodes existing mechanism to use settings based on the VSCode language associations
  2. Directly use the VSCode language associations to map custom filename extensions onto clang-format supported ones, e.g. .es6 > Javascript -> .js and set -assume-filename accordingly

metafeather avatar Mar 27 '17 14:03 metafeather

I really need this as well!

clang-format and this extension for Visual Studio Code is perfect. However I need to be able to map "*.cls" to Java-formatting. (For the Salesforce Apex language).

Uncrustify supports this, but I prefer clang-format over Uncrustify.

I'd rather not use the built-in VSCode language associations, since "Apex" is its own language, but is syntactically the same as Java.

dimitrisuls avatar Apr 19 '17 09:04 dimitrisuls

OK, as a first step, I exposed -assume-filename= as an option clang-format.assumeFilename. I am not quite sure how to handle the mapping of the custom filename extensions. I guess it would be best to pass the original filename + an added default file name extension (like .java for Java etc.) to -assume-filename=? Or would it be better to then just pass a “dummy name” with an appropriate extension. Since I personally don't use that feature in particular I'm open for suggestions.

xaverh avatar Apr 19 '17 23:04 xaverh

@xaverh Thanks that helps! Now it formats my ".cls"-files when I configure "clang-format.assumeFilename": "ClassName.java",

However I still have to associate the Apex-files to Java. Since the Format Document command isn't available for Apex-files.

    "files.associations": {
        "*.cls": "java"
    }

Could you enable the Format Document command for Apex-files as well please?

dimitrisuls avatar Apr 20 '17 07:04 dimitrisuls

This could be added here I suppose:

https://github.com/xaverh/vscode-clang-format-provider/blob/master/src/clangMode.ts#L6

dimitrisuls avatar Apr 20 '17 07:04 dimitrisuls

This would be one way to do this. But this also requires new configuration options in package.json. The way this is currently implemented is that there is a set of three options for each language, clang-format can operate on. In my opinion it's not very reasonable to add more of there for every possible language currently not supported. Also -assume-filename as it is now, should really be a separate option for each language. Since the present approach does not scale very well, I guess it would be smarter to put the configuration in a datastructure like this:

"clang-format.languages": {
  "javascript": {
    "enable": true,
    "extensions": [
      "*.js",
      "*.es6",
      "*.es2017"
    ],
    "style" : ""
  },
  "apex" : {
    "extensions": [
      "*.apex"
    ],
    "assumeFilename": [
      "DummyFilename.java"
    ]
  }
}

Additionally the existing activationEvents are no longer sufficient then. Since "activationEvents": ["*"] has the potential to break a lot of stuff, an option could be to additionally trigger the extension by "activationEvents": ["workspaceContains:.clang-format"]

I hope this can be done without breaking to many existing configurations and I also have to figure out reasonable defaults for users who don't configure this extension at all but I think this would be a step in the right direction.

xaverh avatar Apr 20 '17 09:04 xaverh

Sounds good :).

I'm not sure if "activationEvents": ["workspaceContains:.clang-format"] is a good idea? Currently we don't use that file. We have a single config-file, not in the workspace.

I suppose there's no endless languages to be supported? They could just be added to the package.json?

dimitrisuls avatar Apr 20 '17 14:04 dimitrisuls

Well, "activationEvents" is how Visual Studio Code knows whether of not it has to load the extension at all. Thus, it cannot be influenced by the configuration within the extension. Right now, it loads the extension like this:

    "activationEvents": [
        "onLanguage:cpp",
        "onLanguage:c",
        "onLanguage:objective-c",
        "onLanguage:objective-cpp",
        "onLanguage:java",
        "onLanguage:javascript",
        "onLanguage:typescript",
        "onLanguage:proto"
]

Adding "workspaceContains:.clang-format" to the existing list would not require you to have this file if you are using one of the languages above but would load the extension if there is a .clang-format file but not one of the above languages.

At the moment, formatting with this extension is initialized in two steps:

  1. If the language is one of the languages that triggers the activation, the extension gets loaded.
  2. If the user has not expressly deactivated formatting for the language, the extension connects to vscode.executeFormatDocumentProvider etc.

Therefore, loading the extension for every language, no matter what, (i.e. "activationEvents": ["*"]) is not a good idea, since it would require users to deactivate the extension for languages not even targetted by clang-format (eg. Python, Go, C#, ...) and failing to do so could break existing formatters for these languages (cf. #35 etc.)

Since there is currently no fully-fledged Apex language service extension to break, I could activate clang-format by default for Apex.

Other (also additional) approaches could be to either define an additional file name that triggers the extension if a file is present (like .clang-format.dummy) or to tie it to a command (I am not sure to which command though).

xaverh avatar Apr 20 '17 15:04 xaverh

I put Apex into the list of languages the extension automatically launches with. But this still needs a proper future-proof solution soon.

xaverh avatar Apr 20 '17 17:04 xaverh

Thanks a lot for adding Apex as supported language!

I understand the activationEvents is "static". The .clang-format-file is a good fallback-option for languages not initially supported by the plugin, I agree.

It's probably not even possible to implement it dynamically as you said earlier? Via a user-config:

"clang-format.languages": {
  "javascript": {
    "enable": true,
    "extensions": [
      "*.js",
      "*.es6",
      "*.es2017"
    ],
    "style" : ""
  },
  "apex" : {
    "extensions": [
      "*.apex"
    ],
    "assumeFilename": [
      "DummyFilename.java"
    ]
  }
}

dimitrisuls avatar Apr 21 '17 07:04 dimitrisuls

activationEvent is indeed static. It could theoretically be set to ["*"] which means always (except the user manually disabled the extension for the given workspace in the extensions side bar). The dynamic implementation would be that the extension is running but not doing anything. This is what currently happens if you have the extension installed, "clang-format.language.javascript.enable": false and you have a JavaScript file open. This is more or less hack for a situation like e.g. a ReactNative project where you want your Obj-C and Java code formatted with clang-format and your JavaScript code ignored (because you are using e.g. standardjs).

xaverh avatar Apr 21 '17 09:04 xaverh

I see.

I suppose you could use the ["*"] and disable it for all languages except the enabled ones in the user-config (or default-config).

Your call :).

But already thanks a lot for helping me and my team out so quickly!

dimitrisuls avatar Apr 21 '17 10:04 dimitrisuls

I realize this is an old topic but it seems to be fixed with the built in files.associations setting. When I added my desired file type association it invoked the formatter properly. E.g. for arduino I added the setting:

"files.associations": {
    "*.ino": "cpp"
}

impala454 avatar Sep 27 '20 04:09 impala454