Skip to content

Commit

Permalink
feat: add cwd to rule context (#17106)
Browse files Browse the repository at this point in the history
* feat: add `cwd` to rule context

* docs: add more context.cwd references

* tests: add asertions for context.getCwd()

* docs: apply suggestions from code review

Co-authored-by: Francesco Trotta <github@fasttime.org>

* chore: update test assestion for context.getCwd()

---------

Co-authored-by: Francesco Trotta <github@fasttime.org>
  • Loading branch information
snitin315 and fasttime committed Apr 29, 2023
1 parent 52018f2 commit 0df4d4f
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 6 deletions.
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);
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

0 comments on commit 0df4d4f

Please sign in to comment.