Rename Red Knot (#17820)
|
@ -1,5 +1,5 @@
|
|||
**.md
|
||||
ruff/dist
|
||||
ruff/ruff_wasm
|
||||
knot/dist
|
||||
knot/red_knot_wasm
|
||||
ty/dist
|
||||
ty/ty_wasm
|
|
@ -5,8 +5,8 @@ In-browser playground for Ruff. Available [https://play.ruff.rs/](https://play.r
|
|||
## Getting started
|
||||
|
||||
Install the NPM dependencies with `npm install`, and run, and run the development server with
|
||||
`npm start --workspace ruff-playground` or `npm start --workspace knot-playground`.
|
||||
You may need to restart the server after making changes to Ruff or Red Knot to re-build the WASM
|
||||
`npm start --workspace ruff-playground` or `npm start --workspace ty-playground`.
|
||||
You may need to restart the server after making changes to Ruff or ty to re-build the WASM
|
||||
module.
|
||||
|
||||
To run the datastore, which is based
|
||||
|
@ -37,4 +37,4 @@ additional inspiration from the [Biome Playground](https://biomejs.dev/playgroun
|
|||
### Stack overflows
|
||||
|
||||
If you see stack overflows in the playground, build the WASM module in release mode:
|
||||
`npm run --workspace knot-playground build:wasm`.
|
||||
`npm run --workspace ty-playground build:wasm`.
|
||||
|
|
67
playground/package-lock.json
generated
|
@ -8,7 +8,7 @@
|
|||
"name": "playground",
|
||||
"version": "0.0.0",
|
||||
"workspaces": [
|
||||
"knot",
|
||||
"ty",
|
||||
"ruff",
|
||||
"shared"
|
||||
],
|
||||
|
@ -30,9 +30,10 @@
|
|||
"wasm-pack": "^0.13.1"
|
||||
}
|
||||
},
|
||||
"knot": {
|
||||
"name": "knot-playground",
|
||||
"ty": {
|
||||
"name": "ty-playground",
|
||||
"version": "0.0.0",
|
||||
"extraneous": true,
|
||||
"dependencies": {
|
||||
"@monaco-editor/react": "^4.7.0",
|
||||
"classnames": "^2.5.1",
|
||||
|
@ -42,7 +43,7 @@
|
|||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"react-resizable-panels": "^2.1.7",
|
||||
"red_knot_wasm": "file:red_knot_wasm",
|
||||
"ty_wasm": "file:ty_wasm",
|
||||
"shared": "0.0.0",
|
||||
"smol-toml": "^1.3.1"
|
||||
},
|
||||
|
@ -50,8 +51,9 @@
|
|||
"vite-plugin-static-copy": "^2.3.0"
|
||||
}
|
||||
},
|
||||
"knot/red_knot_wasm": {
|
||||
"ty/ty_wasm": {
|
||||
"version": "0.0.0",
|
||||
"extraneous": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@esbuild/aix-ppc64": {
|
||||
|
@ -4078,10 +4080,6 @@
|
|||
"json-buffer": "3.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/knot-playground": {
|
||||
"resolved": "knot",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/levn": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
|
||||
|
@ -4991,10 +4989,6 @@
|
|||
"node": ">=8.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/red_knot_wasm": {
|
||||
"resolved": "knot/red_knot_wasm",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/reflect.getprototypeof": {
|
||||
"version": "1.0.10",
|
||||
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
|
||||
|
@ -5641,6 +5635,14 @@
|
|||
"strip-bom": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ty_wasm": {
|
||||
"resolved": "ty/ty_wasm",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/ty-playground": {
|
||||
"resolved": "ty",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/type-check": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
||||
|
@ -5881,9 +5883,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/vite-plugin-static-copy": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/vite-plugin-static-copy/-/vite-plugin-static-copy-2.3.0.tgz",
|
||||
"integrity": "sha512-LLKwhhHetGaCnWz4mas4qqjjguDka6/6b4+SeIohRroj8aCE7QTfiZECfPecslFQkWZ3HdQuq5kOPmWZjNYlKA==",
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/vite-plugin-static-copy/-/vite-plugin-static-copy-2.3.1.tgz",
|
||||
"integrity": "sha512-EfsPcBm3ewg3UMG8RJaC0ADq6/qnUZnokXx4By4+2cAcipjT9i0Y0owIJGqmZI7d6nxk4qB1q5aXOwNuSyPdyA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
@ -6037,9 +6039,9 @@
|
|||
"license": "ISC"
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "8.18.1",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz",
|
||||
"integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==",
|
||||
"version": "8.18.2",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.2.tgz",
|
||||
"integrity": "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
|
@ -6094,7 +6096,7 @@
|
|||
}
|
||||
},
|
||||
"ruff/ruff_wasm": {
|
||||
"version": "0.11.4",
|
||||
"version": "0.11.8",
|
||||
"license": "MIT"
|
||||
},
|
||||
"shared": {
|
||||
|
@ -6105,6 +6107,31 @@
|
|||
"react": "^19.0.0",
|
||||
"react-resizable-panels": "^2.1.7"
|
||||
}
|
||||
},
|
||||
"ty": {
|
||||
"name": "ty-playground",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@monaco-editor/react": "^4.7.0",
|
||||
"classnames": "^2.5.1",
|
||||
"lz-string": "^1.5.0",
|
||||
"monaco-editor": "^0.52.2",
|
||||
"pyodide": "^0.27.4",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"react-resizable-panels": "^2.1.7",
|
||||
"shared": "0.0.0",
|
||||
"smol-toml": "^1.3.1",
|
||||
"ty_wasm": "file:ty_wasm"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite-plugin-static-copy": "^2.3.0"
|
||||
}
|
||||
},
|
||||
"ty/ty_wasm": {
|
||||
"name": "ty_wasm",
|
||||
"version": "0.0.0",
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,15 +5,15 @@
|
|||
"type": "module",
|
||||
"scripts": {
|
||||
"check": "npm run dev:wasm && npm run lint && npm run tsc",
|
||||
"dev:wasm": "npm run dev:wasm --workspace knot-playground && npm run dev:wasm --workspace ruff-playground",
|
||||
"dev:build": "npm run dev:build --workspace knot-playground && npm run dev:build --workspace ruff-playground",
|
||||
"dev:wasm": "npm run dev:wasm --workspace ty-playground && npm run dev:wasm --workspace ruff-playground",
|
||||
"dev:build": "npm run dev:build --workspace ty-playground && npm run dev:build --workspace ruff-playground",
|
||||
"fmt": "prettier --cache -w .",
|
||||
"fmt:check": "prettier --cache --check .",
|
||||
"lint": "eslint --cache --ext .ts,.tsx ruff/src knot/src",
|
||||
"lint": "eslint --cache --ext .ts,.tsx ruff/src ty/src",
|
||||
"tsc": "tsc"
|
||||
},
|
||||
"workspaces": [
|
||||
"knot",
|
||||
"ty",
|
||||
"ruff",
|
||||
"shared"
|
||||
],
|
||||
|
|
|
@ -16,6 +16,10 @@
|
|||
"noEmit": true,
|
||||
"jsx": "react-jsx"
|
||||
},
|
||||
"include": ["ruff/src", "knot/src"],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
"include": ["ruff/src", "ty/src"],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.node.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -5,5 +5,5 @@
|
|||
"moduleResolution": "Node",
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"include": ["ruff/vite.config.ts", "knot/vite.config.ts"]
|
||||
"include": ["ruff/vite.config.ts", "ty/vite.config.ts"]
|
||||
}
|
||||
|
|
|
@ -9,18 +9,18 @@
|
|||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
|
||||
<meta name="msapplication-TileColor" content="#d7ff64" />
|
||||
<meta name="theme-color" content="#ffffff" />
|
||||
<title>Playground | Red Knot</title>
|
||||
<title>Playground | ty</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="An in-browser playground for Red Knot, an extremely fast Python type-checker written in Rust."
|
||||
content="An in-browser playground for ty, an extremely fast Python type-checker written in Rust."
|
||||
/>
|
||||
<meta name="keywords" content="ruff, python, rust, webassembly, wasm" />
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:site" content="@astral_sh" />
|
||||
<meta property="og:title" content="Playground | Ruff" />
|
||||
<meta property="og:title" content="Playground | ty" />
|
||||
<meta
|
||||
property="og:description"
|
||||
content="An in-browser playground for Ruff, an extremely fast Python type-checker written in Rust."
|
||||
content="An in-browser playground for ty, an extremely fast Python type-checker written in Rust."
|
||||
/>
|
||||
<meta property="og:url" content="https://play.ruff.rs" />
|
||||
<meta property="og:image" content="/Astral.png" />
|
|
@ -1,13 +1,13 @@
|
|||
{
|
||||
"name": "knot-playground",
|
||||
"name": "ty-playground",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"prebuild": "npm run build:wasm",
|
||||
"build": "vite build",
|
||||
"build:wasm": "wasm-pack build ../../crates/red_knot_wasm --target web --out-dir ../../playground/knot/red_knot_wasm",
|
||||
"dev:wasm": "wasm-pack build ../../crates/red_knot_wasm --dev --target web --out-dir ../../playground/knot/red_knot_wasm",
|
||||
"build:wasm": "wasm-pack build ../../crates/ty_wasm --target web --out-dir ../../playground/ty/ty_wasm",
|
||||
"dev:wasm": "wasm-pack build ../../crates/ty_wasm --dev --target web --out-dir ../../playground/ty/ty_wasm",
|
||||
"predev:build": "npm run dev:wasm",
|
||||
"dev:build": "vite build",
|
||||
"prestart": "npm run dev:wasm",
|
||||
|
@ -23,9 +23,9 @@
|
|||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"react-resizable-panels": "^2.1.7",
|
||||
"red_knot_wasm": "file:red_knot_wasm",
|
||||
"shared": "0.0.0",
|
||||
"smol-toml": "^1.3.1"
|
||||
"smol-toml": "^1.3.1",
|
||||
"ty_wasm": "file:ty_wasm"
|
||||
},
|
||||
"overrides": {
|
||||
"@monaco-editor/react": {
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 2 KiB After Width: | Height: | Size: 2 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
@ -13,7 +13,7 @@ import {
|
|||
Theme,
|
||||
VerticalResizeHandle,
|
||||
} from "shared";
|
||||
import type { Workspace } from "red_knot_wasm";
|
||||
import type { Workspace } from "ty_wasm";
|
||||
import { Panel, PanelGroup } from "react-resizable-panels";
|
||||
import { Files, isPythonFile } from "./Files";
|
||||
import SecondarySideBar from "./SecondarySideBar";
|
|
@ -1,4 +1,4 @@
|
|||
import type { Severity, Range, TextRange } from "red_knot_wasm";
|
||||
import type { Severity, Range, TextRange } from "ty_wasm";
|
||||
import classNames from "classnames";
|
||||
import { Theme } from "shared";
|
||||
import { useMemo } from "react";
|
|
@ -18,11 +18,11 @@ import {
|
|||
import { useCallback, useEffect, useRef } from "react";
|
||||
import { Theme } from "shared";
|
||||
import {
|
||||
Range as KnotRange,
|
||||
Range as TyRange,
|
||||
Severity,
|
||||
type Workspace,
|
||||
Position as KnotPosition,
|
||||
} from "red_knot_wasm";
|
||||
Position as TyPosition,
|
||||
} from "ty_wasm";
|
||||
|
||||
import IStandaloneCodeEditor = editor.IStandaloneCodeEditor;
|
||||
import { FileId, ReadonlyFiles } from "../Playground";
|
||||
|
@ -194,7 +194,7 @@ class PlaygroundServer
|
|||
|
||||
const inlayHints = workspace.inlayHints(
|
||||
selectedHandle,
|
||||
iRangeToKnotRange(range),
|
||||
MonacoRangeToTyRange(range),
|
||||
);
|
||||
|
||||
if (inlayHints.length === 0) {
|
||||
|
@ -300,7 +300,7 @@ class PlaygroundServer
|
|||
|
||||
const hover = workspace.hover(
|
||||
selectedHandle,
|
||||
new KnotPosition(position.lineNumber, position.column),
|
||||
new TyPosition(position.lineNumber, position.column),
|
||||
);
|
||||
|
||||
if (hover == null) {
|
||||
|
@ -308,7 +308,7 @@ class PlaygroundServer
|
|||
}
|
||||
|
||||
return {
|
||||
range: knotRangeToIRange(hover.range),
|
||||
range: tyRangeToMonacoRange(hover.range),
|
||||
contents: [{ value: hover.markdown, isTrusted: true }],
|
||||
};
|
||||
}
|
||||
|
@ -334,7 +334,7 @@ class PlaygroundServer
|
|||
|
||||
const links = workspace.gotoTypeDefinition(
|
||||
selectedHandle,
|
||||
new KnotPosition(position.lineNumber, position.column),
|
||||
new TyPosition(position.lineNumber, position.column),
|
||||
);
|
||||
|
||||
return (
|
||||
|
@ -343,16 +343,16 @@ class PlaygroundServer
|
|||
const targetSelection =
|
||||
link.selection_range == null
|
||||
? undefined
|
||||
: knotRangeToIRange(link.selection_range);
|
||||
: tyRangeToMonacoRange(link.selection_range);
|
||||
|
||||
const originSelection =
|
||||
link.origin_selection_range == null
|
||||
? undefined
|
||||
: knotRangeToIRange(link.origin_selection_range);
|
||||
: tyRangeToMonacoRange(link.origin_selection_range);
|
||||
|
||||
return {
|
||||
uri: Uri.parse(link.path),
|
||||
range: knotRangeToIRange(link.full_range),
|
||||
range: tyRangeToMonacoRange(link.full_range),
|
||||
targetSelectionRange: targetSelection,
|
||||
originSelectionRange: originSelection,
|
||||
} as languages.LocationLink;
|
||||
|
@ -450,7 +450,7 @@ class PlaygroundServer
|
|||
}
|
||||
}
|
||||
|
||||
function knotRangeToIRange(range: KnotRange): IRange {
|
||||
function tyRangeToMonacoRange(range: TyRange): IRange {
|
||||
return {
|
||||
startLineNumber: range.start.line,
|
||||
startColumn: range.start.column,
|
||||
|
@ -459,9 +459,9 @@ function knotRangeToIRange(range: KnotRange): IRange {
|
|||
};
|
||||
}
|
||||
|
||||
function iRangeToKnotRange(range: IRange): KnotRange {
|
||||
return new KnotRange(
|
||||
new KnotPosition(range.startLineNumber, range.startColumn),
|
||||
new KnotPosition(range.endLineNumber, range.endColumn),
|
||||
function MonacoRangeToTyRange(range: IRange): TyRange {
|
||||
return new TyRange(
|
||||
new TyPosition(range.startLineNumber, range.startColumn),
|
||||
new TyPosition(range.endLineNumber, range.endColumn),
|
||||
);
|
||||
}
|
|
@ -2,7 +2,7 @@ import { Icons, Theme } from "shared";
|
|||
import classNames from "classnames";
|
||||
import { useState } from "react";
|
||||
import { FileId } from "../Playground";
|
||||
import { type FileHandle } from "red_knot_wasm";
|
||||
import { type FileHandle } from "ty_wasm";
|
||||
|
||||
export interface Props {
|
||||
// The file names
|
|
@ -10,13 +10,13 @@ import {
|
|||
useState,
|
||||
} from "react";
|
||||
import { ErrorMessage, Header, setupMonaco, useTheme } from "shared";
|
||||
import { FileHandle, PositionEncoding, Workspace } from "red_knot_wasm";
|
||||
import { FileHandle, PositionEncoding, Workspace } from "ty_wasm";
|
||||
import { persist, persistLocal, restore } from "./Editor/persist";
|
||||
import { loader } from "@monaco-editor/react";
|
||||
import knotSchema from "../../../knot.schema.json";
|
||||
import tySchema from "../../../ty.schema.json";
|
||||
import Chrome, { formatError } from "./Editor/Chrome";
|
||||
|
||||
export const SETTINGS_FILE_NAME = "knot.json";
|
||||
export const SETTINGS_FILE_NAME = "ty.json";
|
||||
|
||||
export default function Playground() {
|
||||
const [theme, setTheme] = useTheme();
|
||||
|
@ -224,13 +224,13 @@ def with_style(line, word, style):
|
|||
output += "-" * len(word)
|
||||
|
||||
|
||||
print(with_style("Red Knot is a fast type checker for Python.", "fast", "underlined"))
|
||||
print(with_style("ty is a fast type checker for Python.", "fast", "underlined"))
|
||||
`;
|
||||
|
||||
const DEFAULT_WORKSPACE = {
|
||||
files: {
|
||||
"main.py": DEFAULT_PROGRAM,
|
||||
"knot.json": DEFAULT_SETTINGS,
|
||||
"ty.json": DEFAULT_SETTINGS,
|
||||
},
|
||||
current: "main.py",
|
||||
};
|
||||
|
@ -268,7 +268,7 @@ interface FilesState {
|
|||
* The database file handles by file id.
|
||||
*
|
||||
* Files without a file handle are well-known files that are only handled by the
|
||||
* playground (e.g. knot.json)
|
||||
* playground (e.g. ty.json)
|
||||
*/
|
||||
handles: Readonly<{ [id: FileId]: FileHandle | null }>;
|
||||
|
||||
|
@ -451,14 +451,14 @@ export interface InitializedPlayground {
|
|||
|
||||
// Run once during startup. Initializes monaco, loads the wasm file, and restores the previous editor state.
|
||||
async function startPlayground(): Promise<InitializedPlayground> {
|
||||
const red_knot = await import("../red_knot_wasm");
|
||||
await red_knot.default();
|
||||
const ty = await import("../ty_wasm");
|
||||
await ty.default();
|
||||
const monaco = await loader.init();
|
||||
|
||||
setupMonaco(monaco, {
|
||||
uri: "https://raw.githubusercontent.com/astral-sh/ruff/main/knot.schema.json",
|
||||
fileMatch: ["knot.json"],
|
||||
schema: knotSchema,
|
||||
uri: "https://raw.githubusercontent.com/astral-sh/ruff/main/ty.schema.json",
|
||||
fileMatch: ["ty.json"],
|
||||
schema: tySchema,
|
||||
});
|
||||
|
||||
const restored = await restore();
|
||||
|
@ -483,7 +483,7 @@ function updateOptions(
|
|||
workspace?.updateOptions(settings);
|
||||
setError(null);
|
||||
} catch (error) {
|
||||
setError(`Failed to update 'knot.json' options: ${formatError(error)}`);
|
||||
setError(`Failed to update 'ty.json' options: ${formatError(error)}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -520,8 +520,17 @@ function restoreWorkspace(
|
|||
) {
|
||||
let hasSettings = false;
|
||||
|
||||
for (const [name, content] of Object.entries(state.files)) {
|
||||
// eslint-disable-next-line prefer-const
|
||||
for (let [name, content] of Object.entries(state.files)) {
|
||||
let handle = null;
|
||||
|
||||
if (
|
||||
name === "knot.json" &&
|
||||
!Object.keys(state.files).includes(SETTINGS_FILE_NAME)
|
||||
) {
|
||||
name = SETTINGS_FILE_NAME;
|
||||
}
|
||||
|
||||
if (name === SETTINGS_FILE_NAME) {
|
||||
updateOptions(workspace, content, setError);
|
||||
hasSettings = true;
|
||||
|
@ -536,8 +545,11 @@ function restoreWorkspace(
|
|||
updateOptions(workspace, null, setError);
|
||||
}
|
||||
|
||||
const selected =
|
||||
state.current === "knot.json" ? SETTINGS_FILE_NAME : state.current;
|
||||
|
||||
dispatchFiles({
|
||||
type: "selectFileByName",
|
||||
name: state.current,
|
||||
name: selected,
|
||||
});
|
||||
}
|