Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/mpsuesser/effect-oxlint/llms.txt

Use this file to discover all available pages before exploring further.

The SourceCode module provides effectful wrappers around every method on oxlint’s SourceCode object. Instead of accessing ctx.sourceCode directly and handling null returns, each function reads from the RuleContext service and returns an Effect<T, never, RuleContext> that you can yield* inside a visitor handler. Nullable results are lifted to Option — empty arrays stay as empty arrays.

withSourceCode pattern

Internally every function in this module uses the same withSourceCode helper:
const withSourceCode = <A>(
  fn: (sc: OxlintSourceCode) => A
): Effect.Effect<A, never, RuleContext> =>
  Effect.service(RuleContext).pipe(Effect.map((ctx) => fn(ctx.sourceCode)));
You can use the same pattern to compose multiple queries without repeating the context lookup:
import { RuleContext } from 'effect-oxlint';
import * as Effect from 'effect/Effect';

const myQuery = Effect.service(RuleContext).pipe(
  Effect.map((ctx) => {
    const text = ctx.sourceCode.getText(node);
    const tokens = ctx.sourceCode.getTokens(node);
    return { text, tokens };
  })
);

Source text

getText

export const getText = (): Effect.Effect<string, never, RuleContext>
Returns the full source text of the file being linted.
const text = yield* SourceCode.getText();

getNodeText

export const getNodeText = (
  node: ESTree.Node,
  beforeCount?: number,
  afterCount?: number
): Effect.Effect<string, never, RuleContext>
Returns the source text that spans the given node. Pass beforeCount and afterCount to include additional characters before and after the node’s range.
node
ESTree.Node
required
The AST node whose source text you want.
beforeCount
number
Number of characters to include before the node’s start offset.
afterCount
number
Number of characters to include after the node’s end offset.
const text = yield* SourceCode.getNodeText(node);
const withContext = yield* SourceCode.getNodeText(node, 10, 10);

getLines

export const getLines = (): Effect.Effect<ReadonlyArray<string>, never, RuleContext>
Returns all source lines as a ReadonlyArray<string>.

Ancestry

getAncestors

export const getAncestors = (
  node: ESTree.Node
): Effect.Effect<ReadonlyArray<ESTree.Node>, never, RuleContext>
Returns the ancestor nodes of node ordered from innermost to outermost. The result array does not include the node itself.
oxlint’s upstream getAncestors types the return as Node[] where Node is the base Span interface. The wrapper casts to ReadonlyArray<ESTree.Node> at the FFI boundary — the runtime values are always full ESTree nodes.

Location and range

getLocFromIndex

export const getLocFromIndex = (
  offset: number
): Effect.Effect<LineColumn, never, RuleContext>
Converts a 0-based source offset to a { line, column } location.

getIndexFromLoc

export const getIndexFromLoc = (
  loc: LineColumn
): Effect.Effect<number, never, RuleContext>
Converts a { line, column } location to a 0-based source offset.

getRange

export const getRange = (
  nodeOrToken: ESTree.Node | Token | Comment
): Effect.Effect<Range, never, RuleContext>
Returns the [start, end] range tuple for a node, token, or comment.

getNodeByRangeIndex

export const getNodeByRangeIndex = (
  offset: number
): Effect.Effect<Option.Option<ESTree.Node>, never, RuleContext>
Finds the smallest AST node that spans the given 0-based source offset. Returns Option.none() when no node covers that position.

Token queries

getFirstToken

export const getFirstToken = (
  node: ESTree.Node
): Effect.Effect<Option.Option<Token>, never, RuleContext>
Returns the first token of a node, or Option.none() if the node has no tokens.

getLastToken

export const getLastToken = (
  node: ESTree.Node
): Effect.Effect<Option.Option<Token>, never, RuleContext>
Returns the last token of a node, or Option.none() if the node has no tokens.

getTokens

export const getTokens = (
  node: ESTree.Node
): Effect.Effect<ReadonlyArray<Token>, never, RuleContext>
Returns all tokens belonging to a node.

getTokenBefore

export const getTokenBefore = (
  nodeOrToken: ESTree.Node | Token | Comment
): Effect.Effect<Option.Option<Token>, never, RuleContext>
Returns the token immediately before the given node, token, or comment, or Option.none() if there is none.

getTokenAfter

export const getTokenAfter = (
  nodeOrToken: ESTree.Node | Token | Comment
): Effect.Effect<Option.Option<Token>, never, RuleContext>
Returns the token immediately after the given node, token, or comment, or Option.none() if there is none.

getTokensBetween

export const getTokensBetween = (
  left: ESTree.Node | Token | Comment,
  right: ESTree.Node | Token | Comment
): Effect.Effect<ReadonlyArray<Token>, never, RuleContext>
Returns all tokens found between left and right.

getFirstTokenBetween

export const getFirstTokenBetween = (
  left: ESTree.Node | Token | Comment,
  right: ESTree.Node | Token | Comment
): Effect.Effect<Option.Option<Token>, never, RuleContext>
Returns the first token between left and right, or Option.none() if there are none.

getTokenByRangeStart

export const getTokenByRangeStart = (
  offset: number
): Effect.Effect<Option.Option<Token>, never, RuleContext>
Looks up the token whose range start equals the given 0-based offset. Returns Option.none() when no token starts at that position.

Comment queries

getAllComments

export const getAllComments = (): Effect.Effect<ReadonlyArray<Comment>, never, RuleContext>
Returns every comment node in the file.

getCommentsBefore

export const getCommentsBefore = (
  nodeOrToken: ESTree.Node | Token | Comment
): Effect.Effect<ReadonlyArray<Comment>, never, RuleContext>
Returns all comments that appear immediately before nodeOrToken.

getCommentsAfter

export const getCommentsAfter = (
  nodeOrToken: ESTree.Node | Token | Comment
): Effect.Effect<ReadonlyArray<Comment>, never, RuleContext>
Returns all comments that appear immediately after nodeOrToken.

getCommentsInside

export const getCommentsInside = (
  node: ESTree.Node
): Effect.Effect<ReadonlyArray<Comment>, never, RuleContext>
Returns all comments that appear inside node.

getJSDocComment

export const getJSDocComment = (
  node: ESTree.Node
): Effect.Effect<Option.Option<Comment>, never, RuleContext>
Returns the JSDoc comment for a node if one exists, otherwise Option.none().
getJSDocComment is deprecated upstream. Prefer getCommentsBefore and filter for block comments starting with /** instead.

commentsExistBetween

export const commentsExistBetween = (
  left: ESTree.Node | Token | Comment,
  right: ESTree.Node | Token | Comment
): Effect.Effect<boolean, never, RuleContext>
Returns true if at least one comment exists between left and right.

Scope queries

getScope

export const getScope = (
  node: ESTree.Node
): Effect.Effect<Scope, never, RuleContext>
Returns the lexical Scope for a node. Combine with the Scope module to walk up the scope chain or look up variables.

getDeclaredVariables

export const getDeclaredVariables = (
  node: ESTree.Node
): Effect.Effect<ReadonlyArray<Variable>, never, RuleContext>
Returns the variables declared by a node (e.g. the bindings introduced by a VariableDeclaration).

isGlobalReference

export const isGlobalReference = (
  node: ESTree.Node
): Effect.Effect<boolean, never, RuleContext>
Returns true when node is a reference to a global variable.

markVariableAsUsed

export const markVariableAsUsed = (
  name: string,
  refNode?: ESTree.Node
): Effect.Effect<boolean, never, RuleContext>
Marks the named variable as used in the scope of refNode (or the current scope when omitted). Returns true on success. This is typically used to suppress no-unused-vars false positives.

Spacing

isSpaceBetween

export const isSpaceBetween = (
  first: ESTree.Node | Token | Comment,
  second: ESTree.Node | Token | Comment
): Effect.Effect<boolean, never, RuleContext>
Returns true when there is at least one whitespace character between first and second.

Usage example

The following visitor handler combines several queries to inspect the text and tokens of a detected node:
import { Diagnostic, Rule, SourceCode } from 'effect-oxlint';
import * as Effect from 'effect/Effect';
import * as Option from 'effect/Option';

const noSemiRule = Rule.define({
  name: 'check-semicolon',
  meta: Rule.meta({ type: 'layout', description: 'Enforce semicolons' }),
  create: function* () {
    return {
      ExpressionStatement: (node) =>
        Effect.gen(function* () {
          const lastToken = yield* SourceCode.getLastToken(node);

          if (Option.isNone(lastToken)) return;
          if (lastToken.value.value !== ';') {
            const before = yield* SourceCode.getTokenBefore(lastToken.value);
            yield* Effect.log(`Missing semicolon after token: ${Option.getOrElse(before, () => ({ value: '?' })).value}`);
          }
        })
    };
  }
});

Build docs developers (and LLMs) love