Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add cwd to rule context #17106

Merged
merged 5 commits into from Apr 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/src/extend/custom-rules.md
Expand Up @@ -125,6 +125,7 @@ The `context` object has the following properties:

* `id`: (`string`) The rule ID.
* `filename`: (`string`) The filename associated with the source.
* `cwd`: (`string`) The `cwd` option passed to the [Linter](../integrate/nodejs-api#linter). It is a path to a directory that should be considered the current working directory.
* `options`: (`array`) An array of the [configured options](../use/configure/rules) for this rule. This array does not include the rule severity (see the [dedicated section](#accessing-options-passed-to-a-rule)).
* `settings`: (`object`) The [shared settings](../use/configure/configuration-files#adding-shared-settings) from the configuration.
* `parserPath`: (`string`) The name of the `parser` from the configuration.
Expand All @@ -134,7 +135,7 @@ The `context` object has the following properties:
Additionally, the `context` object has the following methods:

* `getAncestors()`: (**Deprecated:** Use `SourceCode#getAncestors(node)` instead.) Returns an array of the ancestors of the currently-traversed node, starting at the root of the AST and continuing through the direct parent of the current node. This array does not include the currently-traversed node itself.
* `getCwd()`: Returns the `cwd` option passed to the [Linter](../integrate/nodejs-api#linter). It is a path to a directory that should be considered the current working directory.
* `getCwd()`: (**Deprecated:** Use `context.cwd` instead.) Returns the `cwd` option passed to the [Linter](../integrate/nodejs-api#linter). It is a path to a directory that should be considered the current working directory.
* `getDeclaredVariables(node)`: (**Deprecated:** Use `SourceCode#getDeclaredVariables(node)` instead.) Returns a list of [variables](./scope-manager-interface#variable-interface) declared by the given node. This information can be used to track references to variables.
* If the node is a `VariableDeclaration`, all variables declared in the declaration are returned.
* If the node is a `VariableDeclarator`, all variables declared in the declarator are returned.
Expand Down
4 changes: 2 additions & 2 deletions docs/src/integrate/nodejs-api.md
Expand Up @@ -510,7 +510,7 @@ The `Linter` object does the actual evaluation of the JavaScript code. It doesn'

The `Linter` is a constructor, and you can create a new instance by passing in the options you want to use. The available options are:

* `cwd` - Path to a directory that should be considered as the current working directory. It is accessible to rules by calling `context.getCwd()` (see [The Context Object](../extend/custom-rules#the-context-object)). If `cwd` is `undefined`, it will be normalized to `process.cwd()` if the global `process` object is defined (for example, in the Node.js runtime) , or `undefined` otherwise.
* `cwd` - Path to a directory that should be considered as the current working directory. It is accessible to rules from `context.cwd` or by calling `context.getCwd()` (see [The Context Object](../extend/custom-rules#the-context-object)). If `cwd` is `undefined`, it will be normalized to `process.cwd()` if the global `process` object is defined (for example, in the Node.js runtime) , or `undefined` otherwise.

For example:

Expand All @@ -520,7 +520,7 @@ const linter1 = new Linter({ cwd: 'path/to/project' });
const linter2 = new Linter();
```

In this example, rules run on `linter1` will get `path/to/project` when calling `context.getCwd()`.
In this example, rules run on `linter1` will get `path/to/project` from `context.cwd` or when calling `context.getCwd()`.
Those run on `linter2` will get `process.cwd()` if the global `process` object is defined or `undefined` otherwise (e.g. on the browser <https://eslint.org/demo>).

### Linter#verify
Expand Down
1 change: 1 addition & 0 deletions lib/linter/linter.js
Expand Up @@ -951,6 +951,7 @@ function runRules(sourceCode, configuredRules, ruleMapper, parserName, languageO
getAncestors: () => sourceCode.getAncestors(currentNode),
getDeclaredVariables: node => sourceCode.getDeclaredVariables(node),
getCwd: () => cwd,
cwd,
getFilename: () => filename,
filename,
getPhysicalFilename: () => physicalFilename || filename,
Expand Down
94 changes: 91 additions & 3 deletions tests/lib/linter/linter.js
Expand Up @@ -3947,7 +3947,8 @@ var a = "test2";
linterWithOption.defineRule("checker", {
create(context) {
spy = sinon.spy(() => {
assert.strictEqual(context.getCwd(), cwd);
snitin315 marked this conversation as resolved.
Show resolved Hide resolved
assert.strictEqual(context.getCwd(), context.cwd);
assert.strictEqual(context.cwd, cwd);
});
return { Program: spy };
}
Expand All @@ -3965,7 +3966,8 @@ var a = "test2";
create(context) {

spy = sinon.spy(() => {
assert.strictEqual(context.getCwd(), process.cwd());
assert.strictEqual(context.getCwd(), context.cwd);
assert.strictEqual(context.cwd, process.cwd());
});
return { Program: spy };
}
Expand All @@ -3982,7 +3984,8 @@ var a = "test2";
create(context) {

spy = sinon.spy(() => {
assert.strictEqual(context.getCwd(), process.cwd());
assert.strictEqual(context.getCwd(), context.cwd);
assert.strictEqual(context.cwd, process.cwd());
});
return { Program: spy };
}
Expand Down Expand Up @@ -11020,6 +11023,91 @@ describe("Linter with FlatConfigArray", () => {
});
});

describe("context.cwd", () => {
const code = "a;\nb;";
const baseConfig = { rules: { "test/checker": "error" } };

it("should get cwd correctly in the context", () => {
const cwd = "cwd";
const linterWithOption = new Linter({ cwd, configType: "flat" });
let spy;
const config = {
plugins: {
test: {
rules: {
checker: {
create(context) {
spy = sinon.spy(() => {
assert.strictEqual(context.cwd, cwd);
});
return { Program: spy };
}
}
}
}
},
...baseConfig
};

linterWithOption.verify(code, config);
assert(spy && spy.calledOnce);
});

it("should assign process.cwd() to it if cwd is undefined", () => {

const linterWithOption = new Linter({ configType: "flat" });
let spy;
const config = {
plugins: {
test: {
rules: {
checker: {
create(context) {

spy = sinon.spy(() => {
assert.strictEqual(context.getCwd(), context.cwd);
assert.strictEqual(context.cwd, process.cwd());
});
return { Program: spy };
}
}
}
}
},
...baseConfig
};

linterWithOption.verify(code, config);
assert(spy && spy.calledOnce);
});

it("should assign process.cwd() to it if the option is undefined", () => {
let spy;
const config = {
plugins: {
test: {
rules: {
checker: {
create(context) {

spy = sinon.spy(() => {
assert.strictEqual(context.getCwd(), context.cwd);
assert.strictEqual(context.cwd, process.cwd());
});
return { Program: spy };
}
}
}
}
},
...baseConfig
};

linter.verify(code, config);
assert(spy && spy.calledOnce);
});
});

});

describe("Rule Severity", () => {
Expand Down