Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions napi/oxlint2/src-js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,14 @@ async function loadPluginImpl(path) {
registeredPluginPaths.add(path);

// TODO: Use a validation library to assert the shape of the plugin, and of rules
const pluginName = plugin.meta.name;
let ruleId = registeredRules.length;
const ruleNames = [];
const ret = {
name: plugin.meta.name,
offset: ruleId,
ruleNames,
};
const ret = { name: pluginName, offset: ruleId, ruleNames };

for (const [ruleName, rule] of Object.entries(plugin.rules)) {
ruleNames.push(ruleName);
registeredRules.push({ rule, context: new Context(ruleId) });
registeredRules.push({ rule, context: new Context(ruleId, `${pluginName}/${ruleName}`) });
ruleId++;
}

Expand All @@ -75,15 +72,19 @@ async function loadPluginImpl(path) {
class Context {
// Rule ID. Index into `registeredRules` array.
#ruleId;
// Full rule name, including plugin name e.g. `my-plugin/my-rule`.
id;
// Absolute path of file being linted. Set before calling `rule`'s `create` method.
physicalFilename;

/**
* @constructor
* @param {number} ruleId - Rule ID
* @param {string} fullRuleName - Rule name, in form `<plugin>/<rule>`
*/
constructor(ruleId) {
constructor(ruleId, fullRuleName) {
this.#ruleId = ruleId;
this.id = fullRuleName;
}

/**
Expand Down
30 changes: 30 additions & 0 deletions napi/oxlint2/test/__snapshots__/e2e.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,36 @@ Found 20 warnings and 20 errors.
Finished in Xms on 20 files using X threads."
`;

exports[`oxlint2 CLI > should receive data via \`context\` 1`] = `
"
x context-plugin(log-context): id: context-plugin/log-context
,-[files/1.js:1:1]
1 | let x;
: ^
\`----

x context-plugin(log-context): physicalFilename: files/1.js
,-[files/1.js:1:1]
1 | let x;
: ^
\`----

x context-plugin(log-context): id: context-plugin/log-context
,-[files/2.js:1:1]
1 | let y;
: ^
\`----

x context-plugin(log-context): physicalFilename: files/2.js
,-[files/2.js:1:1]
1 | let y;
: ^
\`----

Found 0 warnings and 4 errors.
Finished in Xms on 2 files using X threads."
`;

exports[`oxlint2 CLI > should report an error if a custom plugin cannot be loaded 1`] = `
"Failed to parse configuration file.

Expand Down
9 changes: 9 additions & 0 deletions napi/oxlint2/test/e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,13 @@ describe('oxlint2 CLI', () => {
expect(exitCode).toBe(1);
expect(normalizeOutput(stdout)).toMatchSnapshot();
});

it('should receive data via `context`', async () => {
const { stdout, exitCode } = await runOxlint(
'test/fixtures/context_properties',
);

expect(exitCode).toBe(1);
expect(normalizeOutput(stdout)).toMatchSnapshot();
});
});
8 changes: 8 additions & 0 deletions napi/oxlint2/test/fixtures/context_properties/.oxlintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"plugins": ["./test_plugin"],
"categories": {"correctness": "off"},
"rules": {
"context-plugin/log-context": "error"
},
"ignorePatterns": ["test_plugin"]
}
1 change: 1 addition & 0 deletions napi/oxlint2/test/fixtures/context_properties/files/1.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
let x;
1 change: 1 addition & 0 deletions napi/oxlint2/test/fixtures/context_properties/files/2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
let y;
32 changes: 32 additions & 0 deletions napi/oxlint2/test/fixtures/context_properties/test_plugin/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { dirname, sep } from 'node:path';

const SPAN = { start: 0, end: 0 };

const PARENT_DIR_PATH_LEN = dirname(import.meta.dirname).length + 1;

const relativePath = sep === '/'
? path => path.slice(PARENT_DIR_PATH_LEN)
: path => path.slice(PARENT_DIR_PATH_LEN).replace(/\\/g, '/');

export default {
meta: {
name: "context-plugin",
},
rules: {
"log-context": {
create(context) {
context.report({
message: `id: ${context.id}`,
node: SPAN,
});

context.report({
message: `physicalFilename: ${relativePath(context.physicalFilename)}`,
node: SPAN,
});

return {};
},
},
},
};
Loading