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
2 changes: 1 addition & 1 deletion packages/core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -895,7 +895,7 @@ interface InlineConfigElement {
/**
* Generic options for the `SourceCodeBase` type.
*/
interface SourceCodeBaseTypeOptions {
export interface SourceCodeBaseTypeOptions {
LangOptions: LanguageOptions;
RootNode: unknown;
SyntaxElementWithLoc: unknown;
Expand Down
27 changes: 16 additions & 11 deletions packages/plugin-kit/src/source-code.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,17 @@

/** @typedef {import("@eslint/core").VisitTraversalStep} VisitTraversalStep */
/** @typedef {import("@eslint/core").CallTraversalStep} CallTraversalStep */
/** @typedef {import("@eslint/core").TextSourceCode} TextSourceCode */
/** @typedef {import("@eslint/core").TraversalStep} TraversalStep */
/** @typedef {import("@eslint/core").SourceLocation} SourceLocation */
/** @typedef {import("@eslint/core").SourceLocationWithOffset} SourceLocationWithOffset */
/** @typedef {import("@eslint/core").SourceRange} SourceRange */
/** @typedef {import("@eslint/core").Directive} IDirective */
/** @typedef {import("@eslint/core").DirectiveType} DirectiveType */
/** @typedef {import("@eslint/core").SourceCodeBaseTypeOptions} SourceCodeBaseTypeOptions */
/**
* @typedef {import("@eslint/core").TextSourceCode<Options>} TextSourceCode<Options>
* @template {SourceCodeBaseTypeOptions} [Options=SourceCodeBaseTypeOptions]
*/

//-----------------------------------------------------------------------------
// Helpers
Expand Down Expand Up @@ -212,7 +216,8 @@ export class Directive {

/**
* Source Code Base Object
* @implements {TextSourceCode}
* @template {SourceCodeBaseTypeOptions & {SyntaxElementWithLoc: object}} [Options=SourceCodeBaseTypeOptions & {SyntaxElementWithLoc: object}]
* @implements {TextSourceCode<Options>}
*/
export class TextSourceCodeBase {
/**
Expand All @@ -223,7 +228,7 @@ export class TextSourceCodeBase {

/**
* The AST of the source code.
* @type {object}
* @type {Options['RootNode']}
*/
ast;

Expand All @@ -237,7 +242,7 @@ export class TextSourceCodeBase {
* Creates a new instance.
* @param {Object} options The options for the instance.
* @param {string} options.text The source code text.
* @param {object} options.ast The root AST node.
* @param {Options['RootNode']} options.ast The root AST node.
* @param {RegExp} [options.lineEndingPattern] The pattern to match lineEndings in the source code.
*/
constructor({ text, ast, lineEndingPattern = /\r?\n/u }) {
Expand All @@ -248,7 +253,7 @@ export class TextSourceCodeBase {

/**
* Returns the loc information for the given node or token.
* @param {object} nodeOrToken The node or token to get the loc information for.
* @param {Options['SyntaxElementWithLoc']} nodeOrToken The node or token to get the loc information for.
* @returns {SourceLocation} The loc information for the node or token.
*/
getLoc(nodeOrToken) {
Expand All @@ -267,7 +272,7 @@ export class TextSourceCodeBase {

/**
* Returns the range information for the given node or token.
* @param {object} nodeOrToken The node or token to get the range information for.
* @param {Options['SyntaxElementWithLoc']} nodeOrToken The node or token to get the range information for.
* @returns {SourceRange} The range information for the node or token.
*/
getRange(nodeOrToken) {
Expand All @@ -290,8 +295,8 @@ export class TextSourceCodeBase {
/* eslint-disable no-unused-vars -- Required to complete interface. */
/**
* Returns the parent of the given node.
* @param {object} node The node to get the parent of.
* @returns {object|undefined} The parent of the node.
* @param {Options['SyntaxElementWithLoc']} node The node to get the parent of.
* @returns {Options['SyntaxElementWithLoc']|undefined} The parent of the node.
*/
getParent(node) {
throw new Error("Not implemented.");
Expand All @@ -300,8 +305,8 @@ export class TextSourceCodeBase {

/**
* Gets all the ancestors of a given node
* @param {object} node The node
* @returns {Array<object>} All the ancestor nodes in the AST, not including the provided node, starting
* @param {Options['SyntaxElementWithLoc']} node The node
* @returns {Array<Options['SyntaxElementWithLoc']>} All the ancestor nodes in the AST, not including the provided node, starting
* from the root node at index 0 and going inwards to the parent node.
* @throws {TypeError} When `node` is missing.
*/
Expand All @@ -325,7 +330,7 @@ export class TextSourceCodeBase {

/**
* Gets the source code for the given node.
* @param {object} [node] The AST node to get the text for.
* @param {Options['SyntaxElementWithLoc']} [node] The AST node to get the text for.
* @param {number} [beforeCount] The number of characters before the node to retrieve.
* @param {number} [afterCount] The number of characters after the node to retrieve.
* @returns {string} The text representing the AST node.
Expand Down
69 changes: 69 additions & 0 deletions packages/plugin-kit/tests/types/types.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,82 @@ const sourceCode = new TestTextSourceCode({
ast: { foo: "ABC", bar: 123 },
});
sourceCode.ast satisfies { foo: string; bar: number };
sourceCode.text satisfies string;
sourceCode.lines satisfies string[];
sourceCode.getAncestors({}) satisfies object[];
sourceCode.getLoc({}) satisfies SourceLocation;
sourceCode.getParent({}) satisfies object | undefined;
sourceCode.getRange({}) satisfies SourceRange;
sourceCode.getText() satisfies string;
sourceCode.getText({}, 0, 1) satisfies string;

// TextSourceCodeBase (with options)
interface CustomOptions {
LangOptions: { option1: string; option2: boolean };
RootNode: { type: string };
SyntaxElementWithLoc: { value: string };
ConfigNode: { config: string };
}
class TestTextSourceCodeWithOptions extends TextSourceCodeBase<CustomOptions> {
declare ast: CustomOptions["RootNode"];

constructor({
text,
ast,
}: {
text: string;
ast: CustomOptions["RootNode"];
}) {
super({ text, ast });
}
}

/* eslint-disable no-new -- Needed to test the constructor. */
new TestTextSourceCodeWithOptions({
// @ts-expect-error Wrong type should be caught
text: 1,
// @ts-expect-error Wrong type should be caught
ast: { type: true },
});
new TestTextSourceCodeWithOptions({
// @ts-expect-error Wrong type should be caught
text: true,
// @ts-expect-error Wrong type should be caught
ast: { unknown: true },
});
/* eslint-enable no-new -- Constructor test ends here. */

const sourceCodeWithOptions = new TestTextSourceCodeWithOptions({
text: "text",
ast: { type: "customRootNode" },
});
sourceCodeWithOptions.ast satisfies {
type: string;
} satisfies CustomOptions["RootNode"];
sourceCodeWithOptions.text satisfies string;
sourceCodeWithOptions.lines satisfies string[];
sourceCodeWithOptions.getAncestors({ value: "" }) satisfies {
value: string;
}[] satisfies CustomOptions["SyntaxElementWithLoc"][];
sourceCodeWithOptions.getLoc({ value: "" }) satisfies SourceLocation;
sourceCodeWithOptions.getParent({ value: "" }) satisfies
| { value: string }
| undefined satisfies CustomOptions["SyntaxElementWithLoc"] | undefined;
sourceCodeWithOptions.getRange({ value: "" }) satisfies SourceRange;
sourceCodeWithOptions.getText() satisfies string;
sourceCodeWithOptions.getText({ value: "" }, 0, 1) satisfies string;

// @ts-expect-error Wrong type should be caught
sourceCodeWithOptions.getAncestors({});
// @ts-expect-error Wrong type should be caught
sourceCodeWithOptions.getLoc({});
// @ts-expect-error Wrong type should be caught
sourceCodeWithOptions.getParent({});
// @ts-expect-error Wrong type should be caught
sourceCodeWithOptions.getRange({});
// @ts-expect-error Wrong type should be caught
sourceCodeWithOptions.getText({}, 0, 1);

// VisitNodeStep
class TestVisitNodeStep extends VisitNodeStep {
constructor({ target, phase }: { target: object; phase: 1 | 2 }) {
Expand Down