Skip to content
This repository has been archived by the owner on Mar 25, 2021. It is now read-only.

New rule request: no-padding (no empty lines as first or last child in a block) #3969

Closed
brunolm opened this issue Jun 17, 2018 · 6 comments
Closed

Comments

@brunolm
Copy link

brunolm commented Jun 17, 2018

New Rule Request: no-padding

Disallow empty lines as first or last child in a block.

"no-padding": true

Examples

class Foo {
          ~       // <-- no-padding
  constructor() {}
                  // <-- no-padding
}
~
class Foo {
  constructor() {}
                  // <-- no-padding
}
~
class Foo {
          ~       // <-- no-padding
  constructor() {}
}
const hero = {
             ~  // <-- no-padding
  id: 1,
                // <-- no-padding
}
~
const heroes = [
               ~   // <-- no-padding
  { id: 1 },
  { id: 2 },
                   // <-- no-padding
]
~

Source draft

// tslint:disable:max-classes-per-file no-magic-numbers
import * as Lint from 'tslint';
import { getNextToken } from 'tsutils';
import * as ts from 'typescript';

export class Rule extends Lint.Rules.AbstractRule {
  public static failureMessage = 'padding space not allowed';

  public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
    return this.applyWithWalker(new NoPaddingWalker(sourceFile, this.getOptions()));
  }
}

class NoPaddingWalker extends Lint.RuleWalker {
  static openPattern = /^[\[{]\n\s*\n/;
  static closePattern = /\n\s*\n\s*[\]}]$/;

  protected visitArrayLiteralExpression(node: ts.ArrayLiteralExpression): void {
    this.checkBlock(node);

    super.visitArrayLiteralExpression(node);
  }

  protected visitBlock(node: ts.Block): void {
    this.checkBlock(node);

    super.visitBlock(node);
  }

  protected visitClassDeclaration(node: ts.ClassDeclaration): void {
    const children = node.getChildren();

    children.reduce((current, next) => {
      if (!current) {
        return next;
      }

      if (current.kind === ts.SyntaxKind.FirstPunctuation) {
        const nextToken = getNextToken(next);

        const text = current.getText();
        const nextFullText = next.getFullText();
        const afterNextText = nextToken.getFullText();

        this.checkBlock(next, `${text}${nextFullText}${afterNextText}`);
      }

      return next;
    });

    super.visitClassDeclaration(node);
  }

  protected visitObjectLiteralExpression(node: ts.ObjectLiteralExpression): void {
    this.checkBlock(node);

    super.visitObjectLiteralExpression(node);
  }

  private checkBlock(node: ts.Node, fullText?: string): void {
    const text = fullText || node.getText();

    const isOpenInvalid = NoPaddingWalker.openPattern.test(text);
    const isCloseInvalid = NoPaddingWalker.closePattern.test(text);

    if (isOpenInvalid) {
      const start = fullText ? node.getFullStart() - 1 : node.getStart();

      this.addFailureAt(start, 3, Rule.failureMessage);
    }

    if (isCloseInvalid) {
      const nodeEnd = node.getEnd();
      const start = fullText ? getNextToken(node).getStart() : nodeEnd - 1;

      this.addFailureAt(start, 1, Rule.failureMessage);
    }
  }
}

Preview

no-padding-tslint

@brunolm brunolm changed the title New rule: no-padding (no empty lines as first or last child in a block) New rule request: no-padding (no empty lines as first or last child in a block) Jun 17, 2018
@giladgray
Copy link

@brunolm does the whitespace rule capture this? if not, that's the place for these rules.

https://palantir.github.io/tslint/rules/whitespace/

also, i use prettier with tslint which definitely fixes whitespace like this.

@brunolm
Copy link
Author

brunolm commented Jun 18, 2018

hmm, whitespace doesn't seem to do that exactly. Unless I don't know how to configure it properly.

But yeah, using prettier is an option, I even researched how to do it before a commit, so there's no way to forget it.

npm i -D lint-staged husky@^1.0.0-rc.9 prettier

package.json

"husky": {
   "hooks": {
     "pre-commit": "lint-staged"
   }
 },
 "lint-staged": {
   "*.{ts,tsx}": [
     "prettier --write",
     "git add"
   ]
 },

@michaelcm
Copy link

Just checking if there is a way to do this with tslint yet, or if the best option is still prettier?

@adidahiya
Copy link
Contributor

the best option for all code formatting functionality, IMO, is to use prettier. tslint is de-prioritizing formatting-related rules: #3592

@JimLynchCodes
Copy link

Personally, I would like a tslint rule that enforces one empty line after a class / function signature... is this possible?

@adidahiya
Copy link
Contributor

@JimLynchCodes see #4534

@palantir palantir locked as resolved and limited conversation to collaborators Jun 21, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants