TypeScript: Incorrect (potentially) indentation of function arguments spanning multiple lines

From @nomaed on October 14, 2016 10:40

  • VSCode Version: 1.6.1
  • OS Version: macOS Sierra 10.12

Steps to Reproduce:

  • Write a function (or a method) with several arguments (I did it with JavaScript and TypeScript files, but I believe any would work).
function myFunc(arg1, arg2, arg3, ...args) {
}
  • Split arguments to several lines by hitting Enter before arguments
function myFunc(arg1,
arg2,
arg3,
...args) {
}

Auto-formatting produces this result:

function myFunc(arg1,
    arg2,
    arg3,
    ...args) {
}

I would expect to see this result instead though:

function myFunc(arg1,
                arg2,
                arg3,
                ...args) {
}

Also, when manually formatting the arguments to appear in the same column (note: this is also the default/recommended setting in tslint and maybe other linters), then further lines will start with wrong indentation:

function myFunc(arg1,
                arg2,
                arg3,
                ...args) {
                    console.log('huh...');
}

vscode-multi-line-args-indent

Copied from original issue: Microsoft/vscode#13748

About this issue

  • Original URL
  • State: open
  • Created 8 years ago
  • Reactions: 33
  • Comments: 25

Commits related to this issue

Most upvoted comments

My prefered style for large method/function signatures:

class Example {
    public method(
        arg1: string,
        arg2: number,
        arg3: boolean
    ): ReturnType {
        const result = doSomething();
        return new ReturnType(result);
    }
}

It would be best to provide a configuration so a user can choose which way to go.

This is still an open issue in VS code 1.30.1 - the TS autoformatter removes leading whitespace, even if the tslint config is:

 "rules": {
    "align": [
      true,
      "parameters",
      "arguments",
      "statements",
      "members",
      "elements"
    ],

The comments above RE “I prefer a single tab indent when continuing the parameter list on a newline” aren’t particularly useful - this is still a bug.

Maybe I am missing something, but my project has the following tslint.json file:

{
    "defaultSeverity": "error",
    "extends": [
        "tslint:recommended"
    ],
    "jsRules": {},
    "rules": {
        "quotemark": [
            "single"
        ],
        "no-console": [
            false
        ],
        "arrow-parens": false,
        "no-string-literal": false,
        "no-namespace": [
            "allow-declarations"
        ],
        "interface-name": [
            "never-prefix"
        ],
        "no-trailing-whitespace": [true, "ignore-comments"]
    },
    "rulesDirectory": []
}

And TSLint does complain about parameters not being aligned after I auto format (using default settings, I am pretty sure since I am not overriding anything with typescript.format). I know I can turn off TSLint’s rule, but I would prefer to control settings for this… I find what seems the default to not be the most readable option: screen shot 2017-08-22 at 2 03 33 pm

I’d like to add that the current indentation rule appear to work incorrectly when combined wth multiple nesting levels. In a naked VSCode install, auto format produces this:

this.client
      .getContinents()
      .subscribe(
      x => this.continents = x,
      e => this.errorMessage = e
      );

instead of:

this.client
      .getContinents()
      .subscribe(
          x => this.continents = x,
          e => this.errorMessage = e
      );

FWIW, we have been using prettier now for a couple of years. Really helped with this and other code formatting consistency issues across our teams/products.

In case no. 3, the return type indent once is decreasing readability. So I prefer my option no. 2 but it’s sensitive to function rename - we have to indent all again.

@19majkel94 Option no. 2 probably. Return type (at last the semicolon) is immediately following the args closing parenthesis, so to make it appear in a new line, the closing parenthesis should be moved down too.

I think that these should all be valid:

/**
* #1
 * If first arg is on the same line as the function decl/name,
 * all args are lined up with the first one.
 */
function funcName(arg1: string,
─────────────────┤arg2: number,
─────────────────┤arg3: any): ReturnType {
⇢   console.log('Hello world');
}

/**
 * #2
 * If first arg is newlined, it is double-indented so it remains 1 indent 
 * level in front of impl., and all args are lined up.
 */
function funcName(
⇢   ⇢   arg1: string,
⇢   ⇢   arg2: number,
⇢   ⇢   arg3: any): ReturnType {
⇢   console.log('Hello world');
}

/**
 * #3
 * In case first arg is newlined like in #2, allow closing parenthesis
 * to be newlined too (outdent once) with return type following it
 */
function funcName(
⇢   ⇢   arg1: string,
⇢   ⇢   arg2: number,
⇢   ⇢   arg3: any
⇢   ): ReturnType {
⇢   console.log('Hello world');
}

The reason why I don’t like the way it is now is that the argument aren’t aligned and it’s decreasing readability.