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

Feat: ignore pattern for max-line-length #3099

Merged
merged 12 commits into from
Oct 31, 2017

Conversation

DanielKucal
Copy link
Contributor

@DanielKucal DanielKucal commented Aug 4, 2017

PR checklist

Overview of change:

We can pass a regexp (as a string) to max-line-length rule to ignore some lines, e.g. long imports. Example usage:

{
  "rules": {
    "max-line-length": [true, {"limit": 120, "ignore-pattern": "^import [^,]+ from |^export | implements "}],
  } 
}

will ignore the following lines:

import { SomeLongInterfaceName } from '../../../nested/directory/structure/target';
class MyClass implements SomeLongInterfaceName, OnInit, OnDestroy, OnViewChange {}
export { MyClass, SomeLongInterfaceName };

CHANGELOG.md entry:

[new-rule-option], [enhancement] allow to define ignore pattern for max-line-length rule

@ajafff
Copy link
Contributor

ajafff commented Aug 5, 2017

Please help me get rid of the Additional parameters are not allowed message.

The schema used by vscode, webstorm etc. to validate your config comes from schemastore.org. It's updated by PR to their repository.

@@ -49,15 +56,18 @@ export class Rule extends Lint.Rules.AbstractRule {
}

public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
return this.applyWithFunction(sourceFile, walk, this.ruleArguments[0]);
return this.applyWithFunction(sourceFile, walk, this.ruleArguments);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Parse the ruleArguments before passing it to applyWithFunction

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean something like this?

    public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
        const options = {
            ignorePattern: this.ruleArguments[1] && new RegExp(this.ruleArguments[1]),
            limit: parseInt(this.ruleArguments[0], 10),
        };
        return this.applyWithFunction(sourceFile, walk, options);
    }

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that's what I had in mind.

optionsDescription: Lint.Utils.dedent`It can take up to 2 arguments, but only first one is required:

* integer indicating the max length of lines.
* string defining ignore pattern, being parsed by \`new RegExp()\`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider to make this an object. That makes it easier to add new options in the future without requiring strict ordering of options.

Copy link
Contributor Author

@DanielKucal DanielKucal Aug 6, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean object including the first number parameter this way?

"max-line-length": [true, {
  limit: 120,
  ignorePattern: "^import "
}],

Can it accept number or object (like number|object) to avoid breaking change?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should accept number|object. That's exactly what I meant.

@DanielKucal
Copy link
Contributor Author

Hey @ajafff, can you ensure I understood you correctly?

@osu5nc
Copy link

osu5nc commented Sep 5, 2017

@DanielKucal @ajafff Is this pull request still being looked at? I see there are some conflicts that need to be resolved before this can be merged.

@navels
Copy link

navels commented Sep 25, 2017

would love to see this resolved

@DanielKucal
Copy link
Contributor Author

Unfortunately I'm currently unable to make the request changes and resolve conflicts because of issues described in #3244...

@sgiradoa-psl
Copy link

sgiradoa-psl commented Oct 24, 2017

@DanielKucal Seems like #3244 was closed. How are things on your side?

@DanielKucal
Copy link
Contributor Author

@sgiradoa-psl, am looking for some time to finish this

const lineRanges = getLineRanges(ctx.sourceFile);
for (let i = 0; i < lines.length; i++) {
if (ignorePattern && ignorePattern.test(lines[i])) { continue; }
if (lineRanges[i].contentLength <= limit) { continue; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider moving this condition one line up to avoid regex matching if the line is not too long

function walk(ctx: Lint.WalkContext<{limit: number; ignorePattern: RegExp | undefined}>) {
const limit = ctx.options.limit;
const ignorePattern = ctx.options.ignorePattern;
const lines = (ctx.sourceFile && ctx.sourceFile.text.split("\n") || []);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please avoid this array by using ctx.sourceFile.text.substr(line.pos, line.contentLength) in the loop below

@@ -29,12 +28,41 @@ export class Rule extends Lint.Rules.AbstractRule {
Limiting the length of a line of code improves code readability.
It also makes comparing code side-by-side easier and improves compatibility with
various editors, IDEs, and diff viewers.`,
optionsDescription: "An integer indicating the max length of lines.",
optionsDescription: Lint.Utils.dedent`
It can take up to 2 arguments, but only the first one is required:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the description needs an update to the new options format

return this.applyWithFunction(sourceFile, walk, this.ruleArguments[0] as number);
const argument = this.ruleArguments[0];
const options = {
ignorePattern: (typeof argument === "object") ? new RegExp(argument["ignore-pattern"]) : undefined,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you also need to check if argument["ignore-pattern"] is present because new RegExp(undefined) matches everything

const lines = (ctx.sourceFile && ctx.sourceFile.text.split("\n") || []);
const lineRanges = getLineRanges(ctx.sourceFile);
for (let i = 0; i < lines.length; i++) {
if (ignorePattern && ignorePattern.test(lines[i])) { continue; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess the linter complains about ignorePattern &&
please amend to ignorePattern !== undefined &&

@DanielKucal
Copy link
Contributor Author

DanielKucal commented Oct 31, 2017

Hey @ajafff, thanks for your comments, I've made the request changes. The Circle CI test seems to fail due to not found binary for npm-run-all. Let me know if something still needs improvement, thanks in advance.

Copy link
Contributor

@ajafff ajafff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, I only found two style nits.

I just fixed the CI failures on master. This should be good to go after merging master into your branch.

return super.isEnabled() && this.ruleArguments[0] as number > 0;
const argument: any = this.ruleArguments[0];
const numberGreaterThan0: boolean = (Number(argument) > 0);
const limitGreaterTHan0: boolean = (argument instanceof Object && argument.limit > 0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/THan/Than/

@@ -45,19 +79,31 @@ export class Rule extends Lint.Rules.AbstractRule {
}

public isEnabled(): boolean {
return super.isEnabled() && this.ruleArguments[0] as number > 0;
const argument: any = this.ruleArguments[0];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can omit the : any and : boolean type annotations.

Copy link
Contributor Author

@DanielKucal DanielKucal Oct 31, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thought linter is complaining about infererred types

@ajafff
Copy link
Contributor

ajafff commented Oct 31, 2017

@DanielKucal almost done. There are some lint errors that need to be fixed. Use yarn verify locally to make sure you fixed them.

/home/ubuntu/tslint/src/rules/maxLineLengthRule.ts
ERROR: 84:66  no-unsafe-any  Unsafe use of expression of type 'any'.
ERROR: 84:66  no-unsafe-any  Unsafe use of expression of type 'any'.
ERROR: 92:28  no-unsafe-any  Unsafe use of expression of type 'any'.
ERROR: 93:62  no-unsafe-any  Unsafe use of expression of type 'any'.
ERROR: 94:28  no-unsafe-any  Unsafe use of expression of type 'any'.
ERROR: 94:28  no-unsafe-any  Unsafe use of expression of type 'any'.

Copy link
Contributor

@ajafff ajafff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still LGTM

@ajafff ajafff merged commit d1caf11 into palantir:master Oct 31, 2017
@ajafff
Copy link
Contributor

ajafff commented Oct 31, 2017

Thanks @DanielKucal

@sgiradoa-psl
Copy link

Can someone tell me when or how I can use this? I have the latest version of tslint and is not there. 😞

@ajafff
Copy link
Contributor

ajafff commented Nov 30, 2017

@sgiradoa-psl this change will be part of the next release

@vinayakpatil
Copy link

@ajafff Will this be available anytime soon? I don't see this in 5.8.0

@MartinJohns
Copy link

@ajafff It might be useful to add this issue to the milestone in which you plan to release this feature.

@adidahiya
Copy link
Contributor

@MartinJohns it'll be in the next release, but we don't have strict release schedules right now. I know it's been a long time since the last release. I'm going through PRs now and will try to ship a minor release this week.

@MartinJohns
Copy link

MartinJohns commented Jan 9, 2018

The release schedule is not what I was pointing at, but just generally showing in what version the issue will ship. You could utilize the milestones feature and add the issues there, then it would quickly be visible what feature will ship with that version - just without a due date.

For example: https://github.com/palantir/tslint/milestone/43?closed=1 - and I can see all issues that will ship with version 5.9.

@adidahiya
Copy link
Contributor

Sure, the milestone link would be nice to have, and we'll try to do it for some PRs / issues, but since it requires manual work it might not happen all the time. It should be easy enough for users to go to the project's root README and see the latest version on NPM and infer what the next release will be.

IMO the best thing is to click through to the commit where a PR was merged:

image

then check its tags to see where it was released:

image

@adidahiya adidahiya added this to the TSLint v5.9 milestone Jan 9, 2018
HyphnKnight pushed a commit to HyphnKnight/tslint that referenced this pull request Apr 9, 2018
@ekilah
Copy link

ekilah commented Aug 9, 2018

for people arriving here via google, two things:

  1. the syntax is not as pictured in the original PR submission above. the correct syntax is:
{
  "rules": {
    "max-line-length": [true, {"limit": 120, "ignore-pattern": "your regex here"}],
  } 
}
  1. (just to help others) Here's an example of a pattern I used to fix an issue where single-import import lines were fighting with prettier (see Prettier exceeds the maximum line length on single-import imports prettier/prettier#2564):
{
  "rules": {
    "max-line-length": [true, {"limit": 120, "ignore-pattern": "^import [^,]+ from"}],
  } 
}

@DanielKucal
Copy link
Contributor Author

Thanks @ekilah, I've updated first post to avoid confusing.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants