Skip to content
Closed
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
3 changes: 3 additions & 0 deletions apps/oxlint/src-js/generated/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@ export const DATA_POINTER_POS_32 = 536870902;
export const IS_TS_FLAG_POS = 2147483612;
export const PROGRAM_OFFSET = 0;
export const SOURCE_LEN_OFFSET = 16;
export const SOURCE_TYPE_OFFSET = 124;
export const SOURCE_TYPE_LANGUAGE_OFFSET = 0;
export const SOURCE_TYPE_VARIANT_OFFSET = 2;
34 changes: 33 additions & 1 deletion apps/oxlint/src-js/plugins/source_code.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { DATA_POINTER_POS_32, SOURCE_LEN_OFFSET } from "../generated/constants.ts";
import {
DATA_POINTER_POS_32,
SOURCE_LEN_OFFSET,
SOURCE_TYPE_OFFSET,
SOURCE_TYPE_LANGUAGE_OFFSET,
SOURCE_TYPE_VARIANT_OFFSET,
} from "../generated/constants.ts";

// We use the deserializer which removes `ParenthesizedExpression`s from AST,
// and with `range`, `loc`, and `parent` properties on AST nodes, to match ESLint
Expand Down Expand Up @@ -66,6 +72,32 @@ export function initSourceText(): void {
sourceText = textDecoder.decode(buffer.subarray(0, sourceByteLen));
}

/**
* Check if the current source is JSX/TSX.
* Reads the `SourceType.variant` (LanguageVariant) from the Program in the buffer.
* @returns `true` if the source is JSX or TSX
*/
export function isJsxSource(): boolean {
debugAssertIsNonNull(buffer);
const { uint32 } = buffer,
programPos = uint32[DATA_POINTER_POS_32],
sourceTypePos = programPos + SOURCE_TYPE_OFFSET;
return buffer[sourceTypePos + SOURCE_TYPE_VARIANT_OFFSET] === 1;
}

/**
* Check if the current source is TypeScript.
* Reads the `SourceType.language` (Language) from the Program in the buffer.
* @returns `true` if the source is TypeScript or TypeScript Definition
*/
export function isTypescriptSource(): boolean {
debugAssertIsNonNull(buffer);
const { uint32 } = buffer,
programPos = uint32[DATA_POINTER_POS_32],
sourceTypePos = programPos + SOURCE_TYPE_OFFSET;
return buffer[sourceTypePos + SOURCE_TYPE_LANGUAGE_OFFSET] >= 1;
}

/**
* Deserialize AST from buffer.
*/
Expand Down
24 changes: 21 additions & 3 deletions apps/oxlint/src-js/plugins/tokens_parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import { createRequire } from "node:module";
import { filePath } from "./context.ts";
import { getNodeLoc } from "./location.ts";
import { sourceText } from "./source_code.ts";
import { isJsxSource, isTypescriptSource, sourceText } from "./source_code.ts";
import { debugAssert, debugAssertIsNonNull } from "../utils/asserts.ts";

import type * as ts from "typescript";
Expand Down Expand Up @@ -51,6 +51,8 @@ export function parseTokens(): Token[] {
tsSyntaxKind = tsModule.SyntaxKind;
}

const scriptKind = getScriptKind();

// Parse source text into TypeScript AST
const tsAst = tsModule.createSourceFile(
filePath,
Expand All @@ -62,8 +64,7 @@ export function parseTokens(): Token[] {
setExternalModuleIndicator: undefined,
},
true, // `setParentNodes`
// TODO: Use `TS` or `TSX` depending on source type
tsModule.ScriptKind.TSX,
scriptKind,
);

// Check that TypeScript hasn't altered source text.
Expand Down Expand Up @@ -267,3 +268,20 @@ function hasJSXAncestor(node: ts.Node | undefined): boolean {
function isJSXTokenKind(kind: ts.SyntaxKind): boolean {
return kind >= tsSyntaxKind.JsxElement && kind <= tsSyntaxKind.JsxAttribute;
}

/**
* Determine TypeScript ScriptKind based on source type from the buffer.
* Reads the JSX flag from `SourceType.variant` and TypeScript flag from metadata.
*
* @returns Appropriate ScriptKind for the file
*/
function getScriptKind(): ts.ScriptKind {
debugAssertIsNonNull(tsModule);
const isJsx = isJsxSource();
const isTs = isTypescriptSource();

if (isTs) {
return isJsx ? tsModule.ScriptKind.TSX : tsModule.ScriptKind.TS;
}
return isJsx ? tsModule.ScriptKind.JSX : tsModule.ScriptKind.JS;
}
8 changes: 8 additions & 0 deletions apps/oxlint/test/fixtures/tokens/files/generic_arrow.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const obj = {
fn: <T>(arg: T): T => {
return arg;
},
};

// A comment after the object
export { obj };
Loading
Loading