forked from microsoft/TypeScript
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdeprecate.ts
73 lines (63 loc) · 3.48 KB
/
deprecate.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import {
Debug,
DeprecationOptions,
formatStringFromArgs,
noop,
Version,
version,
} from "./_namespaces/ts.js";
export let enableDeprecationWarnings = true;
export function setEnableDeprecationWarnings(value: boolean) {
enableDeprecationWarnings = value;
}
let typeScriptVersion: Version | undefined;
function getTypeScriptVersion() {
return typeScriptVersion ?? (typeScriptVersion = new Version(version));
}
function formatDeprecationMessage(name: string, error: boolean | undefined, errorAfter: Version | undefined, since: Version | undefined, message: string | undefined) {
let deprecationMessage = error ? "DeprecationError: " : "DeprecationWarning: ";
deprecationMessage += `'${name}' `;
deprecationMessage += since ? `has been deprecated since v${since}` : "is deprecated";
deprecationMessage += error ? " and can no longer be used." : errorAfter ? ` and will no longer be usable after v${errorAfter}.` : ".";
deprecationMessage += message ? ` ${formatStringFromArgs(message, [name])}` : "";
return deprecationMessage;
}
function createErrorDeprecation(name: string, errorAfter: Version | undefined, since: Version | undefined, message: string | undefined) {
const deprecationMessage = formatDeprecationMessage(name, /*error*/ true, errorAfter, since, message);
return () => {
throw new TypeError(deprecationMessage);
};
}
function createWarningDeprecation(name: string, errorAfter: Version | undefined, since: Version | undefined, message: string | undefined) {
let hasWrittenDeprecation = false;
return () => {
if (enableDeprecationWarnings && !hasWrittenDeprecation) {
Debug.log.warn(formatDeprecationMessage(name, /*error*/ false, errorAfter, since, message));
hasWrittenDeprecation = true;
}
};
}
export function createDeprecation(name: string, options: DeprecationOptions & { error: true; }): () => never;
export function createDeprecation(name: string, options?: DeprecationOptions): () => void;
export function createDeprecation(name: string, options: DeprecationOptions = {}) {
const version = typeof options.typeScriptVersion === "string" ? new Version(options.typeScriptVersion) : options.typeScriptVersion ?? getTypeScriptVersion();
const errorAfter = typeof options.errorAfter === "string" ? new Version(options.errorAfter) : options.errorAfter;
const warnAfter = typeof options.warnAfter === "string" ? new Version(options.warnAfter) : options.warnAfter;
const since = typeof options.since === "string" ? new Version(options.since) : options.since ?? warnAfter;
const error = options.error || errorAfter && version.compareTo(errorAfter) >= 0;
const warn = !warnAfter || version.compareTo(warnAfter) >= 0;
return error ? createErrorDeprecation(name, errorAfter, since, options.message) :
warn ? createWarningDeprecation(name, errorAfter, since, options.message) :
noop;
}
function wrapFunction<F extends (...args: any[]) => any>(deprecation: () => void, func: F): F {
return function (this: unknown) {
deprecation();
// eslint-disable-next-line prefer-rest-params
return func.apply(this, arguments);
} as F;
}
export function deprecate<F extends (...args: any[]) => any>(func: F, options?: DeprecationOptions): F {
const deprecation = createDeprecation(options?.name ?? Debug.getFunctionName(func), options);
return wrapFunction(deprecation, func);
}