Skip to content

Commit

Permalink
Add tests and fix issues.
Browse files Browse the repository at this point in the history
  • Loading branch information
dsherret committed Jun 30, 2024
1 parent 4d9c736 commit 39e5b8b
Show file tree
Hide file tree
Showing 8 changed files with 180 additions and 20 deletions.
13 changes: 11 additions & 2 deletions common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ export interface Formatter {
* Gets the plugin info.
*/
getPluginInfo(): PluginInfo;
/**
* Gets what files the plugin matches based on the current configuration.
*/
getFileMatchingInfo(): FileMatchingInfo;
/**
* Gets the license text of the plugin.
*/
Expand Down Expand Up @@ -72,8 +76,13 @@ export interface PluginInfo {
name: string;
version: string;
configKey: string;
fileExtensions: string[];
fileNames: string[];
helpUrl: string;
configSchemaUrl: string;
updateUrl?: string;
}

/** Information about how the current config matches files. */
export interface FileMatchingInfo {
fileExtensions: string[] | undefined;
fileNames: string[];
}
5 changes: 4 additions & 1 deletion deno.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{
"name": "@dprint/formatter",
"version": "0.0.0",
"tasks": {
"build:npm": "deno run -A ./scripts/build_npm.ts"
},
Expand All @@ -8,5 +10,6 @@
"imports": {
"@deno/dnt": "jsr:@deno/dnt@^0.41.2",
"@std/assert": "jsr:@std/assert@^0.226.0"
}
},
"exports": "./mod.ts"
}
5 changes: 5 additions & 0 deletions deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import * as v4 from "./v4.ts";

export type {
ConfigurationDiagnostic,
FileMatchingInfo,
FormatRequest,
Formatter,
GlobalConfiguration,
Expand Down
105 changes: 101 additions & 4 deletions mod_test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { assertEquals } from "@std/assert";
import { createFromBuffer, createStreaming, Formatter, GlobalConfiguration } from "./mod.ts";
import { assert, assertEquals } from "@std/assert";
import { createFromBuffer, createStreaming, type Formatter, type GlobalConfiguration } from "./mod.ts";

Deno.test("it should create streaming", async () => {
const formatter = await createStreaming(
Expand Down Expand Up @@ -68,11 +68,13 @@ function runGeneralJsonFormatterTests(formatter: Formatter) {
name: "dprint-plugin-json",
version: "0.13.0",
configKey: "json",
fileExtensions: ["json", "jsonc"],
fileNames: [],
helpUrl: "https://dprint.dev/plugins/json",
configSchemaUrl: "https://plugins.dprint.dev/schemas/json-0.13.0.json",
});
assertEquals(formatter.getFileMatchingInfo(), {
fileExtensions: ["json", "jsonc"],
fileNames: [],
});
assertEquals(formatter.getResolvedConfig(), {
"array.preferSingleLine": true,
"commentLine.forceSpaceAfterSlashes": true,
Expand Down Expand Up @@ -101,3 +103,98 @@ function runGeneralJsonFormatterTests(formatter: Formatter) {
`{\n "test": [1, 2]\n}\n`,
);
}

Deno.test("should support v4", () => {
// this plugin file's code is here: https://github.com/dprint/dprint/blob/main/crates/test-plugin/src/lib.rs
const formatter = createFromBuffer(
Deno.readFileSync(new URL("./test/test_plugin_v4.wasm", import.meta.url)),
);

formatter.setConfig({}, { "ending": "formatted_wasm" });
{
const result = formatter.formatText({
filePath: "test.txt",
fileText: `test`,
});
assertEquals(result, `test_formatted_wasm`);
}
formatter.setConfig({}, { "ending": "other" });
{
const result = formatter.formatText({
filePath: "test.txt",
fileText: `test`,
});
assertEquals(result, `test_other`);
}
// these will trigger fd_write
{
const result = formatter.formatText({
filePath: "test.txt",
fileText: `stderr: hi on stderr`,
});
assertEquals(result, `stderr: hi on stderr_other`);
}
{
const result = formatter.formatText({
filePath: "test.txt",
fileText: `stdout: hi on stdout`,
});
assertEquals(result, `stdout: hi on stdout_other`);
}

assertEquals(formatter.getPluginInfo(), {
name: "test-plugin",
version: "0.2.0",
configKey: "test-plugin",
helpUrl: "https://dprint.dev/plugins/test",
configSchemaUrl: "https://plugins.dprint.dev/test/schema.json",
updateUrl: "https://plugins.dprint.dev/dprint/test-plugin/latest.json",
});
assertEquals(formatter.getFileMatchingInfo(), {
fileExtensions: ["txt"],
fileNames: [],
});

// some special config in this plugin
formatter.setConfig({}, { "file_extensions": ["asdf"], "file_names": ["some_name"] });
assertEquals(formatter.getFileMatchingInfo(), {
fileExtensions: ["asdf"],
fileNames: ["some_name"],
});

assertEquals(formatter.getLicenseText().substring(0, 15), "The MIT License");

// test out host formatting
{
const result = formatter.formatText({
filePath: "file.txt",
fileText: "plugin: text",
}, (request) => {
return request.fileText + "_host";
});
assertEquals(result, "plugin: text_host_formatted");
}
// test host formatting with plugin config
{
const result = formatter.formatText({
filePath: "file.txt",
fileText: "plugin-config: text",
}, (request) => {
assertEquals(request.overrideConfig, { "ending": "custom_config" });
return request.fileText + "_host";
});
assertEquals(result, "plugin-config: text_host_formatted");
}
// now try range formatting with host formatting
{
const result = formatter.formatText({
filePath: "file.txt",
fileText: "plugin-range: text",
bytesRange: [0, 5],
}, (request) => {
assertEquals(request.bytesRange, [0, 5]);
return request.fileText + "_host";
});
assertEquals(result, "plugin-range: text_host_formatted");
}
});
Binary file added test/test_plugin_v4.wasm
Binary file not shown.
15 changes: 14 additions & 1 deletion v3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,12 +134,25 @@ export function createFromInstance(
const length = get_resolved_config();
return JSON.parse(receiveString(wasmInstance, length));
},
getFileMatchingInfo() {
const length = get_plugin_info();
const pluginInfo = JSON.parse(receiveString(wasmInstance, length)) as PluginInfo;
return {
// deno-lint-ignore no-explicit-any
fileExtensions: (pluginInfo as any).fileExtensions ?? [],
// deno-lint-ignore no-explicit-any
fileNames: (pluginInfo as any).fileNames ?? [],
};
},
getPluginInfo() {
const length = get_plugin_info();
const pluginInfo = JSON.parse(
receiveString(wasmInstance, length),
) as PluginInfo;
pluginInfo.fileNames = pluginInfo.fileNames ?? [];
// deno-lint-ignore no-explicit-any
delete (pluginInfo as any).fileNames;
// deno-lint-ignore no-explicit-any
delete (pluginInfo as any).fileExtensions;
return pluginInfo;
},
getLicenseText() {
Expand Down
56 changes: 44 additions & 12 deletions v4.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { FormatRequest, Formatter, GlobalConfiguration, Host, PluginInfo } from "./common.ts";
import { FileMatchingInfo } from "./mod.ts";

const decoder = new TextDecoder();
const encoder = new TextEncoder();
Expand All @@ -22,16 +23,44 @@ export function createHost(): Host {
createImportObject(): WebAssembly.Imports {
let sharedBuffer = new Uint8Array(0);

const resetSharedBuffer = (length: number) => {
sharedBuffer = new Uint8Array(length);
};

return {
env: {
"fd_write": (
fd: number,
iovsPtr: number,
iovsLen: number,
nwrittenPtr: number,
) => {
let totalWritten = 0;
// deno-lint-ignore no-explicit-any
const wasmMemoryBuffer = (instance.exports.memory as any).buffer;
const dataView = new DataView(wasmMemoryBuffer);

for (let i = 0; i < iovsLen; i++) {
const iovsOffset = iovsPtr + i * 8;
const iovecBufPtr = dataView.getUint32(iovsOffset, true);
const iovecBufLen = dataView.getUint32(iovsOffset + 4, true);

const buf = new Uint8Array(wasmMemoryBuffer, iovecBufPtr, iovecBufLen);

if (fd === 1) {
Deno.stdout.writeSync(buf);
} else if (fd === 2) {
Deno.stderr.writeSync(buf);
} else {
return 1; // not supported fd
}

totalWritten += iovecBufLen;
}

dataView.setUint32(nwrittenPtr, totalWritten, true);

return 0; // success
},
},
dprint: {
"host_has_cancelled": () => 0,
"host_clear_bytes": (length: number) => {
resetSharedBuffer(length);
},
"host_write_buffer": (pointer: number) => {
getWasmBufferAtPointer(instance, pointer, sharedBuffer.length).set(sharedBuffer);
},
Expand Down Expand Up @@ -104,6 +133,7 @@ export function createFromInstance(
format_range,
get_error_text,
get_plugin_info,
get_config_file_matching,
get_resolved_config,
get_config_diagnostics,
get_license_text,
Expand All @@ -127,11 +157,13 @@ export function createFromInstance(
const length = get_resolved_config(configId);
return JSON.parse(receiveString(length));
},
getFileMatchingInfo() {
const length = get_config_file_matching(configId);
return JSON.parse(receiveString(length)) as FileMatchingInfo;
},
getPluginInfo() {
const length = get_plugin_info();
const pluginInfo = JSON.parse(receiveString(length)) as PluginInfo;
pluginInfo.fileNames = pluginInfo.fileNames ?? [];
return pluginInfo;
return JSON.parse(receiveString(length)) as PluginInfo;
},
getLicenseText() {
const length = get_license_text();
Expand All @@ -155,8 +187,8 @@ export function createFromInstance(

sendString(request.fileText);
const responseCode = request.bytesRange != null
? format_range(request.bytesRange[0], request.bytesRange[1])
: format();
? format_range(configId, request.bytesRange[0], request.bytesRange[1])
: format(configId);
switch (responseCode) {
case 0: // no change
return request.fileText;
Expand Down

0 comments on commit 39e5b8b

Please sign in to comment.