feat: add the semantic version to TSLanguage, and expose an API for retrieving it

This commit is contained in:
Amaan Qureshi 2025-01-21 01:59:24 -05:00
parent f0222107b8
commit 8bb1448a6f
24 changed files with 371 additions and 77 deletions

View file

@ -12,6 +12,8 @@
"ts_language_symbol_type",
"ts_language_name",
"ts_language_version",
"ts_language_abi_version",
"ts_language_metadata",
"ts_language_next_state",
"ts_node_field_name_for_child_wasm",
"ts_node_field_name_for_named_child_wasm",

View file

@ -110,6 +110,17 @@ static TSInputEdit unmarshal_edit() {
return edit;
}
static void marshal_language_metadata(const TSLanguageMetadata *metadata) {
if (metadata == NULL) {
TRANSFER_BUFFER[0] = 0;
return;
}
TRANSFER_BUFFER[0] = (const void*)3;
TRANSFER_BUFFER[1] = (const void*)(uint32_t)metadata->major_version;
TRANSFER_BUFFER[2] = (const void*)(uint32_t)metadata->minor_version;
TRANSFER_BUFFER[3] = (const void*)(uint32_t)metadata->patch_version;
}
/********************/
/* Section - Parser */
/********************/
@ -242,6 +253,11 @@ int ts_language_type_is_visible_wasm(const TSLanguage *self, TSSymbol typeId) {
return symbolType <= TSSymbolTypeAnonymous;
}
void ts_language_metadata_wasm(const TSLanguage *self) {
const TSLanguageMetadata *metadata = ts_language_metadata(self);
marshal_language_metadata(metadata);
}
void ts_language_supertypes_wasm(const TSLanguage *self) {
uint32_t length;
const TSSymbol *supertypes = ts_language_supertypes(self, &length);

View file

@ -72,6 +72,8 @@ interface WasmModule {
_ts_language_symbol_count(_0: number): number;
_ts_language_state_count(_0: number): number;
_ts_language_version(_0: number): number;
_ts_language_abi_version(_0: number): number;
_ts_language_metadata(_0: number): number;
_ts_language_name(_0: number): number;
_ts_language_field_count(_0: number): number;
_ts_language_next_state(_0: number, _1: number, _2: number): number;

View file

@ -1,10 +1,17 @@
import { C, INTERNAL, Internal, assertInternal, SIZE_OF_INT, SIZE_OF_SHORT } from './constants';
import { LookaheadIterator } from './lookahead_iterator';
import { unmarshalLanguageMetadata } from './marshal';
import { TRANSFER_BUFFER } from './parser';
import { Query } from './query';
const LANGUAGE_FUNCTION_REGEX = /^tree_sitter_\w+$/;
export class LanguageMetadata {
readonly major_version: number;
readonly minor_version: number;
readonly patch_version: number;
}
/**
* An opaque object that defines how to parse a particular language.
* The code for each `Language` is generated by the Tree-sitter CLI.
@ -46,7 +53,7 @@ export class Language {
}
}
/**
* Gets the name of the language.
*/
@ -57,11 +64,33 @@ export class Language {
}
/**
* @deprecated since version 0.25.0, use {@link Language#abiVersion} instead
* Gets the version of the language.
*/
get version(): number {
return C._ts_language_version(this[0]);
}
/**
* Gets the ABI version of the language.
*/
get abiVersion(): number {
return C._ts_language_abi_version(this[0]);
}
/**
* Get the metadata for this language. This information is generated by the
* CLI, and relies on the language author providing the correct metadata in
* the language's `tree-sitter.json` file.
*/
get metadata(): LanguageMetadata | null {
C._ts_language_metadata(this[0]);
const length = C.getValue(TRANSFER_BUFFER, 'i32');
const address = C.getValue(TRANSFER_BUFFER + SIZE_OF_INT, 'i32');
if (length === 0) return null;
return unmarshalLanguageMetadata(address);
}
/**
* Gets the number of fields in the language.
*/

View file

@ -5,6 +5,7 @@ import { Tree } from "./tree";
import { Query, QueryCapture, type QueryMatch } from "./query";
import { TreeCursor } from "./tree_cursor";
import { TRANSFER_BUFFER } from "./parser";
import { LanguageMetadata } from "./language";
/**
* @internal
@ -161,3 +162,16 @@ export function marshalEdit(edit: Edit, address = TRANSFER_BUFFER) {
C.setValue(address, edit.oldEndIndex, 'i32'); address += SIZE_OF_INT;
C.setValue(address, edit.newEndIndex, 'i32'); address += SIZE_OF_INT;
}
/**
* @internal
*
* Unmarshals a {@link LanguageMetadata} from the transfer buffer.
*/
export function unmarshalLanguageMetadata(address: number): LanguageMetadata {
const result = {} as LanguageMetadata;
result.major_version = C.getValue(address, 'i32'); address += SIZE_OF_INT;
result.minor_version = C.getValue(address, 'i32'); address += SIZE_OF_INT;
result.field_count = C.getValue(address, 'i32');
return result;
}

View file

@ -12,7 +12,7 @@ describe('Language', () => {
describe('.name, .version', () => {
it('returns the name and version of the language', () => {
expect(JavaScript.name).toBe('javascript');
expect(JavaScript.version).toBe(15);
expect(JavaScript.abiVersion).toBe(15);
});
});