Rollup merge of #136161 - notriddle:typescript, r=GuillaumeGomez
rustdoc: add nobuild typescript checking to our JS By nobuild, I mean that the type annotations are all [in comments], not in the "native" typescript syntax. This is a bit uglier, but it lets you rapid-prototype without tsc, works with all the native browser debugging tools, and keeps Node out of Rust's bootstrap chain. [in comments]: https://news.ycombinator.com/item?id=35892250 This pull request mostly just adds ts-ignore annotations and type declarations. To actually take good advantage of typescript, we'll want to "burn down" this pile of unsafe code until we eventually have a version with almost none of these. This PR also adds tsc to the mingw-check Dockerfile, so that it can't fall out of date like the Closure annotations did. https://rust-lang.zulipchat.com/#narrow/channel/266220-t-rustdoc/topic/typescript r? `@GuillaumeGomez` `@lolbinarycat`
This commit is contained in:
commit
3cc6ea2ac6
11 changed files with 1658 additions and 682 deletions
|
@ -29,7 +29,7 @@ ENV PATH="/node/bin:${PATH}"
|
|||
|
||||
# Install es-check
|
||||
# Pin its version to prevent unrelated CI failures due to future es-check versions.
|
||||
RUN npm install es-check@6.1.1 eslint@8.6.0 -g
|
||||
RUN npm install es-check@6.1.1 eslint@8.6.0 typescript@5.7.3 -g
|
||||
|
||||
COPY scripts/sccache.sh /scripts/
|
||||
RUN sh /scripts/sccache.sh
|
||||
|
@ -68,4 +68,5 @@ ENV SCRIPT \
|
|||
es-check es2019 ../src/librustdoc/html/static/js/*.js && \
|
||||
eslint -c ../src/librustdoc/html/static/.eslintrc.js ../src/librustdoc/html/static/js/*.js && \
|
||||
eslint -c ../src/tools/rustdoc-js/.eslintrc.js ../src/tools/rustdoc-js/tester.js && \
|
||||
eslint -c ../src/tools/rustdoc-gui/.eslintrc.js ../src/tools/rustdoc-gui/tester.js
|
||||
eslint -c ../src/tools/rustdoc-gui/.eslintrc.js ../src/tools/rustdoc-gui/tester.js && \
|
||||
tsc --project ../src/librustdoc/html/static/js/tsconfig.json
|
||||
|
|
|
@ -3,13 +3,9 @@
|
|||
These JavaScript files are incorporated into the rustdoc binary at build time,
|
||||
and are minified and written to the filesystem as part of the doc build process.
|
||||
|
||||
We use the [Closure Compiler](https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compiler)
|
||||
We use the [TypeScript Compiler](https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html)
|
||||
dialect of JSDoc to comment our code and annotate params and return types.
|
||||
To run a check:
|
||||
|
||||
./x.py doc library/std
|
||||
npm i -g google-closure-compiler
|
||||
google-closure-compiler -W VERBOSE \
|
||||
build/<YOUR PLATFORM>/doc/{search-index*.js,crates*.js} \
|
||||
src/librustdoc/html/static/js/{search.js,main.js,storage.js} \
|
||||
--externs src/librustdoc/html/static/js/externs.js >/dev/null
|
||||
npm i -g typescript
|
||||
tsc --project tsconfig.json
|
||||
|
|
|
@ -1,270 +0,0 @@
|
|||
// This file contains type definitions that are processed by the Closure Compiler but are
|
||||
// not put into the JavaScript we include as part of the documentation. It is used for
|
||||
// type checking. See README.md in this directory for more info.
|
||||
|
||||
/* eslint-disable */
|
||||
let searchState;
|
||||
function initSearch(searchIndex){}
|
||||
|
||||
/**
|
||||
* @typedef {{
|
||||
* name: string,
|
||||
* id: number|null,
|
||||
* fullPath: Array<string>,
|
||||
* pathWithoutLast: Array<string>,
|
||||
* pathLast: string,
|
||||
* generics: Array<QueryElement>,
|
||||
* bindings: Map<number, Array<QueryElement>>,
|
||||
* }}
|
||||
*/
|
||||
let QueryElement;
|
||||
|
||||
/**
|
||||
* @typedef {{
|
||||
* pos: number,
|
||||
* totalElems: number,
|
||||
* typeFilter: (null|string),
|
||||
* userQuery: string,
|
||||
* isInBinding: (null|string),
|
||||
* }}
|
||||
*/
|
||||
let ParserState;
|
||||
|
||||
/**
|
||||
* @typedef {{
|
||||
* original: string,
|
||||
* userQuery: string,
|
||||
* typeFilter: number,
|
||||
* elems: Array<QueryElement>,
|
||||
* args: Array<QueryElement>,
|
||||
* returned: Array<QueryElement>,
|
||||
* foundElems: number,
|
||||
* totalElems: number,
|
||||
* literalSearch: boolean,
|
||||
* hasReturnArrow: boolean,
|
||||
* corrections: Array<{from: string, to: integer}> | null,
|
||||
* typeFingerprint: Uint32Array,
|
||||
* error: Array<string> | null,
|
||||
* }}
|
||||
*/
|
||||
let ParsedQuery;
|
||||
|
||||
/**
|
||||
* @typedef {{
|
||||
* crate: string,
|
||||
* desc: string,
|
||||
* id: number,
|
||||
* name: string,
|
||||
* normalizedName: string,
|
||||
* parent: (Object|null|undefined),
|
||||
* path: string,
|
||||
* ty: (Number|null|number),
|
||||
* type: FunctionSearchType?
|
||||
* }}
|
||||
*/
|
||||
let Row;
|
||||
|
||||
/**
|
||||
* @typedef {{
|
||||
* in_args: Array<Object>,
|
||||
* returned: Array<Object>,
|
||||
* others: Array<Object>,
|
||||
* query: ParsedQuery,
|
||||
* }}
|
||||
*/
|
||||
let ResultsTable;
|
||||
|
||||
/**
|
||||
* @typedef {Map<String, ResultObject>}
|
||||
*/
|
||||
let Results;
|
||||
|
||||
/**
|
||||
* @typedef {{
|
||||
* desc: string,
|
||||
* displayPath: string,
|
||||
* fullPath: string,
|
||||
* href: string,
|
||||
* id: number,
|
||||
* lev: number,
|
||||
* name: string,
|
||||
* normalizedName: string,
|
||||
* parent: (Object|undefined),
|
||||
* path: string,
|
||||
* ty: number,
|
||||
* type: FunctionSearchType?,
|
||||
* displayType: Promise<Array<Array<string>>>|null,
|
||||
* displayTypeMappedNames: Promise<Array<[string, Array<string>]>>|null,
|
||||
* }}
|
||||
*/
|
||||
let ResultObject;
|
||||
|
||||
/**
|
||||
* A pair of [inputs, outputs], or 0 for null. This is stored in the search index.
|
||||
* The JavaScript deserializes this into FunctionSearchType.
|
||||
*
|
||||
* Numeric IDs are *ONE-indexed* into the paths array (`p`). Zero is used as a sentinel for `null`
|
||||
* because `null` is four bytes while `0` is one byte.
|
||||
*
|
||||
* An input or output can be encoded as just a number if there is only one of them, AND
|
||||
* it has no generics. The no generics rule exists to avoid ambiguity: imagine if you had
|
||||
* a function with a single output, and that output had a single generic:
|
||||
*
|
||||
* fn something() -> Result<usize, usize>
|
||||
*
|
||||
* If output was allowed to be any RawFunctionType, it would look like thi
|
||||
*
|
||||
* [[], [50, [3, 3]]]
|
||||
*
|
||||
* The problem is that the above output could be interpreted as either a type with ID 50 and two
|
||||
* generics, or it could be interpreted as a pair of types, the first one with ID 50 and the second
|
||||
* with ID 3 and a single generic parameter that is also ID 3. We avoid this ambiguity by choosing
|
||||
* in favor of the pair of types interpretation. This is why the `(number|Array<RawFunctionType>)`
|
||||
* is used instead of `(RawFunctionType|Array<RawFunctionType>)`.
|
||||
*
|
||||
* The output can be skipped if it's actually unit and there's no type constraints. If thi
|
||||
* function accepts constrained generics, then the output will be unconditionally emitted, and
|
||||
* after it will come a list of trait constraints. The position of the item in the list will
|
||||
* determine which type parameter it is. For example:
|
||||
*
|
||||
* [1, 2, 3, 4, 5]
|
||||
* ^ ^ ^ ^ ^
|
||||
* | | | | - generic parameter (-3) of trait 5
|
||||
* | | | - generic parameter (-2) of trait 4
|
||||
* | | - generic parameter (-1) of trait 3
|
||||
* | - this function returns a single value (type 2)
|
||||
* - this function takes a single input parameter (type 1)
|
||||
*
|
||||
* Or, for a less contrived version:
|
||||
*
|
||||
* [[[4, -1], 3], [[5, -1]], 11]
|
||||
* -^^^^^^^---- ^^^^^^^ ^^
|
||||
* | | | - generic parameter, roughly `where -1: 11`
|
||||
* | | | since -1 is the type parameter and 11 the trait
|
||||
* | | - function output 5<-1>
|
||||
* | - the overall function signature is something like
|
||||
* | `fn(4<-1>, 3) -> 5<-1> where -1: 11`
|
||||
* - function input, corresponds roughly to 4<-1>
|
||||
* 4 is an index into the `p` array for a type
|
||||
* -1 is the generic parameter, given by 11
|
||||
*
|
||||
* If a generic parameter has multiple trait constraints, it gets wrapped in an array, just like
|
||||
* function inputs and outputs:
|
||||
*
|
||||
* [-1, -1, [4, 3]]
|
||||
* ^^^^^^ where -1: 4 + 3
|
||||
*
|
||||
* If a generic parameter's trait constraint has generic parameters, it gets wrapped in the array
|
||||
* even if only one exists. In other words, the ambiguity of `4<3>` and `4 + 3` is resolved in
|
||||
* favor of `4 + 3`:
|
||||
*
|
||||
* [-1, -1, [[4, 3]]]
|
||||
* ^^^^^^^^ where -1: 4 + 3
|
||||
*
|
||||
* [-1, -1, [5, [4, 3]]]
|
||||
* ^^^^^^^^^^^ where -1: 5, -2: 4 + 3
|
||||
*
|
||||
* If a generic parameter has no trait constraints (like in Rust, the `Sized` constraint i
|
||||
* implied and a fake `?Sized` constraint used to note its absence), it will be filled in with 0.
|
||||
*
|
||||
* @typedef {(
|
||||
* 0 |
|
||||
* [(number|Array<RawFunctionType>)] |
|
||||
* [(number|Array<RawFunctionType>), (number|Array<RawFunctionType>)] |
|
||||
* Array<(number|Array<RawFunctionType>)>
|
||||
* )}
|
||||
*/
|
||||
let RawFunctionSearchType;
|
||||
|
||||
/**
|
||||
* A single function input or output type. This is either a single path ID, or a pair of
|
||||
* [path ID, generics].
|
||||
*
|
||||
* Numeric IDs are *ONE-indexed* into the paths array (`p`). Zero is used as a sentinel for `null`
|
||||
* because `null` is four bytes while `0` is one byte.
|
||||
*
|
||||
* @typedef {number | [number, Array<RawFunctionType>]}
|
||||
*/
|
||||
let RawFunctionType;
|
||||
|
||||
/**
|
||||
* @typedef {{
|
||||
* inputs: Array<FunctionType>,
|
||||
* output: Array<FunctionType>,
|
||||
* where_clause: Array<Array<FunctionType>>,
|
||||
* }}
|
||||
*/
|
||||
let FunctionSearchType;
|
||||
|
||||
/**
|
||||
* @typedef {{
|
||||
* id: (null|number),
|
||||
* ty: number,
|
||||
* generics: Array<FunctionType>,
|
||||
* bindings: Map<integer, Array<FunctionType>>,
|
||||
* }}
|
||||
*/
|
||||
let FunctionType;
|
||||
|
||||
/**
|
||||
* The raw search data for a given crate. `n`, `t`, `d`, `i`, and `f`
|
||||
* are arrays with the same length. `q`, `a`, and `c` use a sparse
|
||||
* representation for compactness.
|
||||
*
|
||||
* `n[i]` contains the name of an item.
|
||||
*
|
||||
* `t[i]` contains the type of that item
|
||||
* (as a string of characters that represent an offset in `itemTypes`).
|
||||
*
|
||||
* `d[i]` contains the description of that item.
|
||||
*
|
||||
* `q` contains the full paths of the items. For compactness, it is a set of
|
||||
* (index, path) pairs used to create a map. If a given index `i` is
|
||||
* not present, this indicates "same as the last index present".
|
||||
*
|
||||
* `i[i]` contains an item's parent, usually a module. For compactness,
|
||||
* it is a set of indexes into the `p` array.
|
||||
*
|
||||
* `f` contains function signatures, or `0` if the item isn't a function.
|
||||
* More information on how they're encoded can be found in rustc-dev-guide
|
||||
*
|
||||
* Functions are themselves encoded as arrays. The first item is a list of
|
||||
* types representing the function's inputs, and the second list item is a list
|
||||
* of types representing the function's output. Tuples are flattened.
|
||||
* Types are also represented as arrays; the first item is an index into the `p`
|
||||
* array, while the second is a list of types representing any generic parameters.
|
||||
*
|
||||
* b[i] contains an item's impl disambiguator. This is only present if an item
|
||||
* is defined in an impl block and, the impl block's type has more than one associated
|
||||
* item with the same name.
|
||||
*
|
||||
* `a` defines aliases with an Array of pairs: [name, offset], where `offset`
|
||||
* points into the n/t/d/q/i/f arrays.
|
||||
*
|
||||
* `doc` contains the description of the crate.
|
||||
*
|
||||
* `p` is a list of path/type pairs. It is used for parents and function parameters.
|
||||
* The first item is the type, the second is the name, the third is the visible path (if any) and
|
||||
* the fourth is the canonical path used for deduplication (if any).
|
||||
*
|
||||
* `r` is the canonical path used for deduplication of re-exported items.
|
||||
* It is not used for associated items like methods (that's the fourth element
|
||||
* of `p`) but is used for modules items like free functions.
|
||||
*
|
||||
* `c` is an array of item indices that are deprecated.
|
||||
* @typedef {{
|
||||
* doc: string,
|
||||
* a: Object,
|
||||
* n: Array<string>,
|
||||
* t: string,
|
||||
* d: Array<string>,
|
||||
* q: Array<[number, string]>,
|
||||
* i: Array<number>,
|
||||
* f: string,
|
||||
* p: Array<[number, string] | [number, string, number] | [number, string, number, number]>,
|
||||
* b: Array<[number, String]>,
|
||||
* c: Array<number>,
|
||||
* r: Array<[number, number]>,
|
||||
* }}
|
||||
*/
|
||||
let RawSearchIndexCrate;
|
File diff suppressed because it is too large
Load diff
387
src/librustdoc/html/static/js/rustdoc.d.ts
vendored
Normal file
387
src/librustdoc/html/static/js/rustdoc.d.ts
vendored
Normal file
|
@ -0,0 +1,387 @@
|
|||
// This file contains type definitions that are processed by the TypeScript Compiler but are
|
||||
// not put into the JavaScript we include as part of the documentation. It is used for
|
||||
// type checking. See README.md in this directory for more info.
|
||||
|
||||
/* eslint-disable */
|
||||
declare global {
|
||||
interface Window {
|
||||
/** Make the current theme easy to find */
|
||||
currentTheme: HTMLLinkElement|null;
|
||||
/** Used by the popover tooltip code. */
|
||||
RUSTDOC_TOOLTIP_HOVER_MS: number;
|
||||
/** Used by the popover tooltip code. */
|
||||
RUSTDOC_TOOLTIP_HOVER_EXIT_MS: number;
|
||||
/** Search engine data used by main.js and search.js */
|
||||
searchState: rustdoc.SearchState;
|
||||
/** Global option, with a long list of "../"'s */
|
||||
rootPath: string|null;
|
||||
/**
|
||||
* Currently opened crate.
|
||||
* As a multi-page application, we know this never changes once set.
|
||||
*/
|
||||
currentCrate: string|null;
|
||||
}
|
||||
interface HTMLElement {
|
||||
/** Used by the popover tooltip code. */
|
||||
TOOLTIP_FORCE_VISIBLE: boolean|undefined,
|
||||
/** Used by the popover tooltip code */
|
||||
TOOLTIP_HOVER_TIMEOUT: Timeout|undefined,
|
||||
}
|
||||
}
|
||||
|
||||
export = rustdoc;
|
||||
|
||||
declare namespace rustdoc {
|
||||
interface SearchState {
|
||||
rustdocToolbar: HTMLElement|null;
|
||||
loadingText: string;
|
||||
input: HTMLInputElement|null;
|
||||
title: string;
|
||||
titleBeforeSearch: string;
|
||||
timeout: number|null;
|
||||
currentTab: number;
|
||||
focusedByTab: [number|null, number|null, number|null];
|
||||
clearInputTimeout: function;
|
||||
outputElement: function(): HTMLElement|null;
|
||||
focus: function();
|
||||
defocus: function();
|
||||
showResults: function(HTMLElement|null|undefined);
|
||||
removeQueryParameters: function();
|
||||
hideResults: function();
|
||||
getQueryStringParams: function(): Object.<any, string>;
|
||||
origPlaceholder: string;
|
||||
setup: function();
|
||||
setLoadingSearch: function();
|
||||
descShards: Map<string, SearchDescShard[]>;
|
||||
loadDesc: function({descShard: SearchDescShard, descIndex: number}): Promise<string|null>;
|
||||
loadedDescShard: function(string, number, string);
|
||||
isDisplayed: function(): boolean,
|
||||
}
|
||||
|
||||
interface SearchDescShard {
|
||||
crate: string;
|
||||
promise: Promise<string[]>|null;
|
||||
resolve: function(string[])|null;
|
||||
shard: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* A single parsed "atom" in a search query. For example,
|
||||
*
|
||||
* std::fmt::Formatter, Write -> Result<()>
|
||||
* ┏━━━━━━━━━━━━━━━━━━ ┌──── ┏━━━━━┅┅┅┅┄┄┄┄┄┄┄┄┄┄┄┄┄┄┐
|
||||
* ┃ │ ┗ QueryElement { ┊
|
||||
* ┃ │ name: Result ┊
|
||||
* ┃ │ generics: [ ┊
|
||||
* ┃ │ QueryElement ┘
|
||||
* ┃ │ name: ()
|
||||
* ┃ │ ]
|
||||
* ┃ │ }
|
||||
* ┃ └ QueryElement {
|
||||
* ┃ name: Write
|
||||
* ┃ }
|
||||
* ┗ QueryElement {
|
||||
* name: Formatter
|
||||
* pathWithoutLast: std::fmt
|
||||
* }
|
||||
*/
|
||||
interface QueryElement {
|
||||
name: string,
|
||||
id: number|null,
|
||||
fullPath: Array<string>,
|
||||
pathWithoutLast: Array<string>,
|
||||
pathLast: string,
|
||||
normalizedPathLast: string,
|
||||
generics: Array<QueryElement>,
|
||||
bindings: Map<number, Array<QueryElement>>,
|
||||
typeFilter: number|null,
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as QueryElement, but bindings and typeFilter support strings
|
||||
*/
|
||||
interface ParserQueryElement {
|
||||
name: string,
|
||||
id: number|null,
|
||||
fullPath: Array<string>,
|
||||
pathWithoutLast: Array<string>,
|
||||
pathLast: string,
|
||||
normalizedPathLast: string,
|
||||
generics: Array<ParserQueryElement>,
|
||||
bindings: Map<string, Array<ParserQueryElement>>,
|
||||
bindingName: {name: string, generics: ParserQueryElement[]}|null,
|
||||
typeFilter: string|null,
|
||||
}
|
||||
|
||||
/**
|
||||
* Intermediate parser state. Discarded when parsing is done.
|
||||
*/
|
||||
interface ParserState {
|
||||
pos: number;
|
||||
length: number;
|
||||
totalElems: number;
|
||||
genericsElems: number;
|
||||
typeFilter: (null|string);
|
||||
userQuery: string;
|
||||
isInBinding: (null|{name: string, generics: ParserQueryElement[]});
|
||||
}
|
||||
|
||||
/**
|
||||
* A complete parsed query.
|
||||
*/
|
||||
interface ParsedQuery<T> {
|
||||
userQuery: string,
|
||||
elems: Array<T>,
|
||||
returned: Array<T>,
|
||||
foundElems: number,
|
||||
totalElems: number,
|
||||
literalSearch: boolean,
|
||||
hasReturnArrow: boolean,
|
||||
correction: string|null,
|
||||
proposeCorrectionFrom: string|null,
|
||||
proposeCorrectionTo: string|null,
|
||||
typeFingerprint: Uint32Array,
|
||||
error: Array<string> | null,
|
||||
}
|
||||
|
||||
/**
|
||||
* An entry in the search index database.
|
||||
*/
|
||||
interface Row {
|
||||
crate: string,
|
||||
descShard: SearchDescShard,
|
||||
id: number,
|
||||
name: string,
|
||||
normalizedName: string,
|
||||
word: string,
|
||||
parent: ({ty: number, name: string, path: string, exactPath: string}|null|undefined),
|
||||
path: string,
|
||||
ty: number,
|
||||
type?: FunctionSearchType
|
||||
}
|
||||
|
||||
/**
|
||||
* The viewmodel for the search engine results page.
|
||||
*/
|
||||
interface ResultsTable {
|
||||
in_args: Array<ResultObject>,
|
||||
returned: Array<ResultObject>,
|
||||
others: Array<ResultObject>,
|
||||
query: ParsedQuery,
|
||||
}
|
||||
|
||||
type Results = Map<String, ResultObject>;
|
||||
|
||||
/**
|
||||
* An annotated `Row`, used in the viewmodel.
|
||||
*/
|
||||
interface ResultObject {
|
||||
desc: string,
|
||||
displayPath: string,
|
||||
fullPath: string,
|
||||
href: string,
|
||||
id: number,
|
||||
dist: number,
|
||||
path_dist: number,
|
||||
name: string,
|
||||
normalizedName: string,
|
||||
word: string,
|
||||
index: number,
|
||||
parent: (Object|undefined),
|
||||
path: string,
|
||||
ty: number,
|
||||
type?: FunctionSearchType,
|
||||
paramNames?: string[],
|
||||
displayType: Promise<Array<Array<string>>>|null,
|
||||
displayTypeMappedNames: Promise<Array<[string, Array<string>]>>|null,
|
||||
item: Row,
|
||||
dontValidate?: boolean,
|
||||
}
|
||||
|
||||
/**
|
||||
* A pair of [inputs, outputs], or 0 for null. This is stored in the search index.
|
||||
* The JavaScript deserializes this into FunctionSearchType.
|
||||
*
|
||||
* Numeric IDs are *ONE-indexed* into the paths array (`p`). Zero is used as a sentinel for `null`
|
||||
* because `null` is four bytes while `0` is one byte.
|
||||
*
|
||||
* An input or output can be encoded as just a number if there is only one of them, AND
|
||||
* it has no generics. The no generics rule exists to avoid ambiguity: imagine if you had
|
||||
* a function with a single output, and that output had a single generic:
|
||||
*
|
||||
* fn something() -> Result<usize, usize>
|
||||
*
|
||||
* If output was allowed to be any RawFunctionType, it would look like thi
|
||||
*
|
||||
* [[], [50, [3, 3]]]
|
||||
*
|
||||
* The problem is that the above output could be interpreted as either a type with ID 50 and two
|
||||
* generics, or it could be interpreted as a pair of types, the first one with ID 50 and the second
|
||||
* with ID 3 and a single generic parameter that is also ID 3. We avoid this ambiguity by choosing
|
||||
* in favor of the pair of types interpretation. This is why the `(number|Array<RawFunctionType>)`
|
||||
* is used instead of `(RawFunctionType|Array<RawFunctionType>)`.
|
||||
*
|
||||
* The output can be skipped if it's actually unit and there's no type constraints. If thi
|
||||
* function accepts constrained generics, then the output will be unconditionally emitted, and
|
||||
* after it will come a list of trait constraints. The position of the item in the list will
|
||||
* determine which type parameter it is. For example:
|
||||
*
|
||||
* [1, 2, 3, 4, 5]
|
||||
* ^ ^ ^ ^ ^
|
||||
* | | | | - generic parameter (-3) of trait 5
|
||||
* | | | - generic parameter (-2) of trait 4
|
||||
* | | - generic parameter (-1) of trait 3
|
||||
* | - this function returns a single value (type 2)
|
||||
* - this function takes a single input parameter (type 1)
|
||||
*
|
||||
* Or, for a less contrived version:
|
||||
*
|
||||
* [[[4, -1], 3], [[5, -1]], 11]
|
||||
* -^^^^^^^---- ^^^^^^^ ^^
|
||||
* | | | - generic parameter, roughly `where -1: 11`
|
||||
* | | | since -1 is the type parameter and 11 the trait
|
||||
* | | - function output 5<-1>
|
||||
* | - the overall function signature is something like
|
||||
* | `fn(4<-1>, 3) -> 5<-1> where -1: 11`
|
||||
* - function input, corresponds roughly to 4<-1>
|
||||
* 4 is an index into the `p` array for a type
|
||||
* -1 is the generic parameter, given by 11
|
||||
*
|
||||
* If a generic parameter has multiple trait constraints, it gets wrapped in an array, just like
|
||||
* function inputs and outputs:
|
||||
*
|
||||
* [-1, -1, [4, 3]]
|
||||
* ^^^^^^ where -1: 4 + 3
|
||||
*
|
||||
* If a generic parameter's trait constraint has generic parameters, it gets wrapped in the array
|
||||
* even if only one exists. In other words, the ambiguity of `4<3>` and `4 + 3` is resolved in
|
||||
* favor of `4 + 3`:
|
||||
*
|
||||
* [-1, -1, [[4, 3]]]
|
||||
* ^^^^^^^^ where -1: 4 + 3
|
||||
*
|
||||
* [-1, -1, [5, [4, 3]]]
|
||||
* ^^^^^^^^^^^ where -1: 5, -2: 4 + 3
|
||||
*
|
||||
* If a generic parameter has no trait constraints (like in Rust, the `Sized` constraint i
|
||||
* implied and a fake `?Sized` constraint used to note its absence), it will be filled in with 0.
|
||||
*/
|
||||
type RawFunctionSearchType =
|
||||
0 |
|
||||
[(number|Array<RawFunctionType>)] |
|
||||
[(number|Array<RawFunctionType>), (number|Array<RawFunctionType>)] |
|
||||
Array<(number|Array<RawFunctionType>)>
|
||||
;
|
||||
|
||||
/**
|
||||
* A single function input or output type. This is either a single path ID, or a pair of
|
||||
* [path ID, generics].
|
||||
*
|
||||
* Numeric IDs are *ONE-indexed* into the paths array (`p`). Zero is used as a sentinel for `null`
|
||||
* because `null` is four bytes while `0` is one byte.
|
||||
*/
|
||||
type RawFunctionType = number | [number, Array<RawFunctionType>];
|
||||
|
||||
/**
|
||||
* The type signature entry in the decoded search index.
|
||||
* (The "Raw" objects are encoded differently to save space in the JSON).
|
||||
*/
|
||||
interface FunctionSearchType {
|
||||
inputs: Array<FunctionType>,
|
||||
output: Array<FunctionType>,
|
||||
where_clause: Array<Array<FunctionType>>,
|
||||
}
|
||||
|
||||
/**
|
||||
* A decoded function type, made from real objects.
|
||||
* `ty` will be negative for generics, positive for types, and 0 for placeholders.
|
||||
*/
|
||||
interface FunctionType {
|
||||
id: null|number,
|
||||
ty: number|null,
|
||||
name?: string,
|
||||
path: string|null,
|
||||
exactPath: string|null,
|
||||
unboxFlag: boolean,
|
||||
generics: Array<FunctionType>,
|
||||
bindings: Map<number, Array<FunctionType>>,
|
||||
};
|
||||
|
||||
interface HighlightedFunctionType extends FunctionType {
|
||||
generics: HighlightedFunctionType[],
|
||||
bindings: Map<number, HighlightedFunctionType[]>,
|
||||
highlighted?: boolean;
|
||||
}
|
||||
|
||||
interface FingerprintableType {
|
||||
id: number|null;
|
||||
generics: FingerprintableType[];
|
||||
bindings: Map<number, FingerprintableType[]>;
|
||||
};
|
||||
|
||||
/**
|
||||
* The raw search data for a given crate. `n`, `t`, `d`, `i`, and `f`
|
||||
* are arrays with the same length. `q`, `a`, and `c` use a sparse
|
||||
* representation for compactness.
|
||||
*
|
||||
* `n[i]` contains the name of an item.
|
||||
*
|
||||
* `t[i]` contains the type of that item
|
||||
* (as a string of characters that represent an offset in `itemTypes`).
|
||||
*
|
||||
* `d[i]` contains the description of that item.
|
||||
*
|
||||
* `q` contains the full paths of the items. For compactness, it is a set of
|
||||
* (index, path) pairs used to create a map. If a given index `i` is
|
||||
* not present, this indicates "same as the last index present".
|
||||
*
|
||||
* `i[i]` contains an item's parent, usually a module. For compactness,
|
||||
* it is a set of indexes into the `p` array.
|
||||
*
|
||||
* `f` contains function signatures, or `0` if the item isn't a function.
|
||||
* More information on how they're encoded can be found in rustc-dev-guide
|
||||
*
|
||||
* Functions are themselves encoded as arrays. The first item is a list of
|
||||
* types representing the function's inputs, and the second list item is a list
|
||||
* of types representing the function's output. Tuples are flattened.
|
||||
* Types are also represented as arrays; the first item is an index into the `p`
|
||||
* array, while the second is a list of types representing any generic parameters.
|
||||
*
|
||||
* b[i] contains an item's impl disambiguator. This is only present if an item
|
||||
* is defined in an impl block and, the impl block's type has more than one associated
|
||||
* item with the same name.
|
||||
*
|
||||
* `a` defines aliases with an Array of pairs: [name, offset], where `offset`
|
||||
* points into the n/t/d/q/i/f arrays.
|
||||
*
|
||||
* `doc` contains the description of the crate.
|
||||
*
|
||||
* `p` is a list of path/type pairs. It is used for parents and function parameters.
|
||||
* The first item is the type, the second is the name, the third is the visible path (if any) and
|
||||
* the fourth is the canonical path used for deduplication (if any).
|
||||
*
|
||||
* `r` is the canonical path used for deduplication of re-exported items.
|
||||
* It is not used for associated items like methods (that's the fourth element
|
||||
* of `p`) but is used for modules items like free functions.
|
||||
*
|
||||
* `c` is an array of item indices that are deprecated.
|
||||
*/
|
||||
type RawSearchIndexCrate = {
|
||||
doc: string,
|
||||
a: Object,
|
||||
n: Array<string>,
|
||||
t: string,
|
||||
D: string,
|
||||
e: string,
|
||||
q: Array<[number, string]>,
|
||||
i: string,
|
||||
f: string,
|
||||
p: Array<[number, string] | [number, string, number] | [number, string, number, number] | [number, string, number, number, string]>,
|
||||
b: Array<[number, String]>,
|
||||
c: string,
|
||||
r: Array<[number, number]>,
|
||||
P: Array<[number, string]>,
|
||||
};
|
||||
|
||||
type VlqData = VlqData[] | number;
|
||||
}
|
|
@ -1,5 +1,8 @@
|
|||
/* global addClass, hasClass, removeClass, onEachLazy */
|
||||
|
||||
// Eventually fix this.
|
||||
// @ts-nocheck
|
||||
|
||||
"use strict";
|
||||
|
||||
(function() {
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -3,6 +3,9 @@
|
|||
/* global addClass, removeClass, onEach, onEachLazy */
|
||||
/* global MAIN_ID, getVar, getSettingsButton, getHelpButton */
|
||||
|
||||
// Eventually fix this.
|
||||
// @ts-nocheck
|
||||
|
||||
"use strict";
|
||||
|
||||
(function() {
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
/* global addClass, onEachLazy, removeClass, browserSupportsHistoryApi */
|
||||
/* global updateLocalStorage, getVar */
|
||||
|
||||
// Eventually fix this.
|
||||
// @ts-nocheck
|
||||
|
||||
"use strict";
|
||||
|
||||
(function() {
|
||||
|
|
|
@ -5,15 +5,28 @@
|
|||
// the page, so we don't see major layout changes during the load of the page.
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* @import * as rustdoc from "./rustdoc.d.ts";
|
||||
*/
|
||||
|
||||
const builtinThemes = ["light", "dark", "ayu"];
|
||||
const darkThemes = ["dark", "ayu"];
|
||||
window.currentTheme = document.getElementById("themeStyle");
|
||||
window.currentTheme = (function() {
|
||||
const currentTheme = document.getElementById("themeStyle");
|
||||
return currentTheme instanceof HTMLLinkElement ? currentTheme : null;
|
||||
})();
|
||||
|
||||
const settingsDataset = (function() {
|
||||
const settingsElement = document.getElementById("default-settings");
|
||||
return settingsElement && settingsElement.dataset ? settingsElement.dataset : null;
|
||||
})();
|
||||
|
||||
/**
|
||||
* Get a configuration value. If it's not set, get the default.
|
||||
*
|
||||
* @param {string} settingName
|
||||
* @returns
|
||||
*/
|
||||
function getSettingValue(settingName) {
|
||||
const current = getCurrentValue(settingName);
|
||||
if (current === null && settingsDataset !== null) {
|
||||
|
@ -29,17 +42,39 @@ function getSettingValue(settingName) {
|
|||
|
||||
const localStoredTheme = getSettingValue("theme");
|
||||
|
||||
/**
|
||||
* Check if a DOM Element has the given class set.
|
||||
* If `elem` is null, returns false.
|
||||
*
|
||||
* @param {HTMLElement|null} elem
|
||||
* @param {string} className
|
||||
* @returns {boolean}
|
||||
*/
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function hasClass(elem, className) {
|
||||
return elem && elem.classList && elem.classList.contains(className);
|
||||
return !!elem && !!elem.classList && elem.classList.contains(className);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a class to a DOM Element. If `elem` is null,
|
||||
* does nothing. This function is idempotent.
|
||||
*
|
||||
* @param {HTMLElement|null} elem
|
||||
* @param {string} className
|
||||
*/
|
||||
function addClass(elem, className) {
|
||||
if (elem && elem.classList) {
|
||||
elem.classList.add(className);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a class from a DOM Element. If `elem` is null,
|
||||
* does nothing. This function is idempotent.
|
||||
*
|
||||
* @param {HTMLElement|null} elem
|
||||
* @param {string} className
|
||||
*/
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function removeClass(elem, className) {
|
||||
if (elem && elem.classList) {
|
||||
|
@ -49,8 +84,8 @@ function removeClass(elem, className) {
|
|||
|
||||
/**
|
||||
* Run a callback for every element of an Array.
|
||||
* @param {Array<?>} arr - The array to iterate over
|
||||
* @param {function(?)} func - The callback
|
||||
* @param {Array<?>} arr - The array to iterate over
|
||||
* @param {function(?): boolean|undefined} func - The callback
|
||||
*/
|
||||
function onEach(arr, func) {
|
||||
for (const elem of arr) {
|
||||
|
@ -67,8 +102,8 @@ function onEach(arr, func) {
|
|||
* or a "live" NodeList while modifying it can be very slow.
|
||||
* https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection
|
||||
* https://developer.mozilla.org/en-US/docs/Web/API/NodeList
|
||||
* @param {NodeList<?>|HTMLCollection<?>} lazyArray - An array to iterate over
|
||||
* @param {function(?)} func - The callback
|
||||
* @param {NodeList|HTMLCollection} lazyArray - An array to iterate over
|
||||
* @param {function(?): boolean} func - The callback
|
||||
*/
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function onEachLazy(lazyArray, func) {
|
||||
|
@ -77,6 +112,15 @@ function onEachLazy(lazyArray, func) {
|
|||
func);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a configuration value. This uses localstorage,
|
||||
* with a `rustdoc-` prefix, to avoid clashing with other
|
||||
* web apps that may be running in the same domain (for example, mdBook).
|
||||
* If localStorage is disabled, this function does nothing.
|
||||
*
|
||||
* @param {string} name
|
||||
* @param {string} value
|
||||
*/
|
||||
function updateLocalStorage(name, value) {
|
||||
try {
|
||||
window.localStorage.setItem("rustdoc-" + name, value);
|
||||
|
@ -85,6 +129,15 @@ function updateLocalStorage(name, value) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a configuration value. If localStorage is disabled,
|
||||
* this function returns null. If the setting was never
|
||||
* changed by the user, it also returns null; if you want to
|
||||
* be able to use a default value, call `getSettingValue` instead.
|
||||
*
|
||||
* @param {string} name
|
||||
* @returns {string|null}
|
||||
*/
|
||||
function getCurrentValue(name) {
|
||||
try {
|
||||
return window.localStorage.getItem("rustdoc-" + name);
|
||||
|
@ -93,19 +146,29 @@ function getCurrentValue(name) {
|
|||
}
|
||||
}
|
||||
|
||||
// Get a value from the rustdoc-vars div, which is used to convey data from
|
||||
// Rust to the JS. If there is no such element, return null.
|
||||
const getVar = (function getVar(name) {
|
||||
/**
|
||||
* Get a value from the rustdoc-vars div, which is used to convey data from
|
||||
* Rust to the JS. If there is no such element, return null.
|
||||
*
|
||||
* @param {string} name
|
||||
* @returns {string|null}
|
||||
*/
|
||||
function getVar(name) {
|
||||
const el = document.querySelector("head > meta[name='rustdoc-vars']");
|
||||
return el ? el.attributes["data-" + name].value : null;
|
||||
});
|
||||
return el ? el.getAttribute("data-" + name) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the current theme.
|
||||
* @param {string|null} newThemeName
|
||||
* @param {boolean} saveTheme
|
||||
*/
|
||||
function switchTheme(newThemeName, saveTheme) {
|
||||
const themeNames = getVar("themes").split(",").filter(t => t);
|
||||
const themeNames = (getVar("themes") || "").split(",").filter(t => t);
|
||||
themeNames.push(...builtinThemes);
|
||||
|
||||
// Ensure that the new theme name is among the defined themes
|
||||
if (themeNames.indexOf(newThemeName) === -1) {
|
||||
if (newThemeName === null || themeNames.indexOf(newThemeName) === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -118,7 +181,7 @@ function switchTheme(newThemeName, saveTheme) {
|
|||
document.documentElement.setAttribute("data-theme", newThemeName);
|
||||
|
||||
if (builtinThemes.indexOf(newThemeName) !== -1) {
|
||||
if (window.currentTheme) {
|
||||
if (window.currentTheme && window.currentTheme.parentNode) {
|
||||
window.currentTheme.parentNode.removeChild(window.currentTheme);
|
||||
window.currentTheme = null;
|
||||
}
|
||||
|
@ -130,7 +193,10 @@ function switchTheme(newThemeName, saveTheme) {
|
|||
// rendering, but if we are done, it would blank the page.
|
||||
if (document.readyState === "loading") {
|
||||
document.write(`<link rel="stylesheet" id="themeStyle" href="${newHref}">`);
|
||||
window.currentTheme = document.getElementById("themeStyle");
|
||||
window.currentTheme = (function() {
|
||||
const currentTheme = document.getElementById("themeStyle");
|
||||
return currentTheme instanceof HTMLLinkElement ? currentTheme : null;
|
||||
})();
|
||||
} else {
|
||||
window.currentTheme = document.createElement("link");
|
||||
window.currentTheme.rel = "stylesheet";
|
||||
|
@ -179,11 +245,13 @@ const updateTheme = (function() {
|
|||
return updateTheme;
|
||||
})();
|
||||
|
||||
// @ts-ignore
|
||||
if (getSettingValue("use-system-theme") !== "false" && window.matchMedia) {
|
||||
// update the preferred dark theme if the user is already using a dark theme
|
||||
// See https://github.com/rust-lang/rust/pull/77809#issuecomment-707875732
|
||||
if (getSettingValue("use-system-theme") === null
|
||||
&& getSettingValue("preferred-dark-theme") === null
|
||||
&& localStoredTheme !== null
|
||||
&& darkThemes.indexOf(localStoredTheme) >= 0) {
|
||||
updateLocalStorage("preferred-dark-theme", localStoredTheme);
|
||||
}
|
||||
|
|
15
src/librustdoc/html/static/js/tsconfig.json
Normal file
15
src/librustdoc/html/static/js/tsconfig.json
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2023",
|
||||
"module": "esnext",
|
||||
"rootDir": "./",
|
||||
"allowJs": true,
|
||||
"checkJs": true,
|
||||
"noEmit": true,
|
||||
"strict": true,
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"typeAcquisition": {
|
||||
"include": ["./rustdoc.d.ts"]
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue