summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.eslintignore4
-rw-r--r--.eslintrc.json23
-rw-r--r--.gitignore6
-rw-r--r--azure-pipelines.yml60
-rw-r--r--benching/example.ts2
-rw-r--r--benching/mod.ts22
-rw-r--r--benching/test.ts8
-rw-r--r--bytes/bytes.ts2
-rw-r--r--colors/mod.ts4
-rw-r--r--datetime/mod.ts18
-rw-r--r--datetime/test.ts2
-rwxr-xr-xexamples/gist.ts4
-rw-r--r--examples/ws.ts4
-rw-r--r--io/bufio.ts2
-rw-r--r--io/bufio_test.ts26
-rw-r--r--io/ioutil_test.ts2
-rw-r--r--io/writers_test.ts2
-rw-r--r--log/handlers.ts16
-rw-r--r--log/handlers_test.ts1
-rw-r--r--log/logger.ts30
-rw-r--r--log/logger_test.ts2
-rw-r--r--log/mod.ts39
-rw-r--r--log/test.ts4
-rw-r--r--media_types/mod.ts24
-rw-r--r--multipart/formfile.ts7
-rw-r--r--multipart/multipart.ts380
-rw-r--r--multipart/multipart_test.ts1
-rwxr-xr-xprettier/main.ts6
-rw-r--r--prettier/main_test.ts6
-rw-r--r--prettier/prettier.ts1
-rw-r--r--prettier/util.ts2
-rw-r--r--testing/diff.ts97
-rw-r--r--testing/format.ts303
-rw-r--r--testing/format_test.ts27
-rw-r--r--testing/mod.ts101
-rw-r--r--testing/pretty.ts8
-rw-r--r--testing/pretty_test.ts6
-rw-r--r--testing/test.ts2
-rw-r--r--textproto/mod.ts22
-rw-r--r--textproto/test.ts2
-rw-r--r--tsconfig.json15
41 files changed, 689 insertions, 604 deletions
diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 000000000..9f113730f
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1,4 @@
+/flags/
+/fs/
+/http/
+/ws/
diff --git a/.eslintrc.json b/.eslintrc.json
new file mode 100644
index 000000000..43405e21e
--- /dev/null
+++ b/.eslintrc.json
@@ -0,0 +1,23 @@
+{
+ "root": true,
+ "parser": "@typescript-eslint/parser",
+ "parserOptions": {
+ "project": "./tsconfig.json"
+ },
+ "plugins": ["@typescript-eslint"],
+ "extends": [
+ "plugin:@typescript-eslint/recommended",
+ "prettier",
+ "prettier/@typescript-eslint"
+ ],
+ "rules": {
+ "@typescript-eslint/array-type": ["error", "array-simple"],
+ "@typescript-eslint/explicit-member-accessibility": ["off"],
+ "@typescript-eslint/no-non-null-assertion": ["off"],
+ "@typescript-eslint/no-parameter-properties": ["off"],
+ "@typescript-eslint/no-unused-vars": [
+ "error",
+ { "argsIgnorePattern": "^_" }
+ ]
+ }
+}
diff --git a/.gitignore b/.gitignore
index b2941c3c2..bb7de9d00 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
.DS_Store
.idea
-tsconfig.json
-deno.d.ts \ No newline at end of file
+deno.d.ts
+node_modules
+package.json
+package-lock.json
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 2d6f318a4..861159e84 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -1,31 +1,39 @@
variables:
- DENO_VERSION: 'v0.3.1'
+ DENO_VERSION: "v0.3.1"
+ TS_VERSION: "3.2.1"
+# TODO DRY up the jobs
+# TODO Try to get eslint to run under Deno, like prettier
jobs:
+ - job: "Linux"
+ pool:
+ vmImage: "Ubuntu-16.04"
+ steps:
+ - script: npm install eslint typescript@$(TS_VERSION) @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint-config-prettier
+ - script: curl -L https://deno.land/x/install/install.sh | sh -s $(DENO_VERSION)
+ - script: echo '##vso[task.prependpath]$(HOME)/.deno/bin/'
+ - script: npx eslint **/*.ts
+ - script: deno format.ts --allow-run --allow-write --allow-read --check
+ - script: deno test.ts --allow-run --allow-net --allow-write --allow-read
-- job: 'Linux'
- pool:
- vmImage: 'Ubuntu-16.04'
- steps:
- - script: curl -L https://deno.land/x/install/install.sh | sh -s $(DENO_VERSION)
- - script: echo '##vso[task.prependpath]$(HOME)/.deno/bin/'
- - script: deno test.ts --allow-run --allow-net --allow-write --allow-read
- - script: deno format.ts --allow-run --allow-write --allow-read --check
+ - job: "Mac"
+ pool:
+ vmImage: "macOS-10.13"
+ steps:
+ - script: npm -g install eslint typescript@$(TS_VERSION) @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint-config-prettier
+ - script: curl -L https://deno.land/x/install/install.sh | sh -s $(DENO_VERSION)
+ - script: echo '##vso[task.prependpath]$(HOME)/.deno/bin/'
+ - script: eslint **/*.ts
+ - script: deno format.ts --allow-run --allow-write --allow-read --check
+ - script: deno test.ts --allow-run --allow-net --allow-write --allow-read
-- job: 'Mac'
- pool:
- vmImage: 'macOS-10.13'
- steps:
- - script: curl -L https://deno.land/x/install/install.sh | sh -s $(DENO_VERSION)
- - script: echo '##vso[task.prependpath]$(HOME)/.deno/bin/'
- - script: deno test.ts --allow-run --allow-net --allow-write --allow-read
- - script: deno format.ts --allow-run --allow-write --allow-read --check
-
-- job: 'Windows'
- pool:
- vmImage: 'vs2017-win2016'
- steps:
- - powershell: iwr https://deno.land/x/install/install.ps1 -out install.ps1; .\install.ps1 $(DENO_VERSION)
- - bash: echo "##vso[task.prependpath]C:\Users\VssAdministrator\.deno\\bin"
- - bash: deno.exe test.ts --allow-run --allow-net --allow-write --allow-read
- - bash: deno.exe format.ts --allow-run --allow-write --allow-read --check
+ - job: "Windows"
+ pool:
+ vmImage: "vs2017-win2016"
+ steps:
+ - bash: npm install eslint typescript@$(TS_VERSION) @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint-config-prettier
+ - powershell: iwr https://deno.land/x/install/install.ps1 -out install.ps1; .\install.ps1 $(DENO_VERSION)
+ - bash: echo "##vso[task.prependpath]C:\Users\VssAdministrator\.deno\\bin"
+ - bash: npx eslint **/*.ts
+ - bash: deno.exe format.ts --allow-run --allow-write --allow-read --check
+ - bash: deno.exe test.ts --allow-run --allow-net --allow-write --allow-read
diff --git a/benching/example.ts b/benching/example.ts
index 1018dd9e1..1563379bf 100644
--- a/benching/example.ts
+++ b/benching/example.ts
@@ -14,7 +14,7 @@ bench({
runs: 100,
func(b: BenchmarkTimer) {
b.start();
- for (let i: number = 0; i < 1e6; i++);
+ for (let i = 0; i < 1e6; i++);
b.stop();
}
});
diff --git a/benching/mod.ts b/benching/mod.ts
index 4d2f5d41e..6fa442d03 100644
--- a/benching/mod.ts
+++ b/benching/mod.ts
@@ -14,10 +14,10 @@ export interface BenchmarkTimer {
}
/** Defines a benchmark through a named function. */
-export type BenchmarkFunction = {
+export interface BenchmarkFunction {
(b: BenchmarkTimer): void | Promise<void>;
name: string;
-};
+}
/** Defines a benchmark definition with configurable runs. */
export interface BenchmarkDefinition {
@@ -69,7 +69,7 @@ function createBenchmarkTimer(clock: BenchmarkClock): BenchmarkTimer {
};
}
-const candidates: Array<BenchmarkDefinition> = [];
+const candidates: BenchmarkDefinition[] = [];
/** Registers a benchmark as a candidate for the runBenchmarks executor. */
export function bench(
@@ -95,27 +95,27 @@ export async function runBenchmarks({
skip = /^\s*$/
}: BenchmarkRunOptions = {}): Promise<void> {
// Filtering candidates by the "only" and "skip" constraint
- const benchmarks: Array<BenchmarkDefinition> = candidates.filter(
+ const benchmarks: BenchmarkDefinition[] = candidates.filter(
({ name }) => only.test(name) && !skip.test(name)
);
// Init main counters and error flag
- const filtered: number = candidates.length - benchmarks.length;
- let measured: number = 0;
- let failed: boolean = false;
+ const filtered = candidates.length - benchmarks.length;
+ let measured = 0;
+ let failed = false;
// Setting up a shared benchmark clock and timer
const clock: BenchmarkClock = { start: NaN, stop: NaN };
- const b: BenchmarkTimer = createBenchmarkTimer(clock);
+ const b = createBenchmarkTimer(clock);
// Iterating given benchmark definitions (await-in-loop)
console.log(
"running",
benchmarks.length,
`benchmark${benchmarks.length === 1 ? " ..." : "s ..."}`
);
- for (const { name, runs, func } of benchmarks) {
+ for (const { name, runs = 0, func } of benchmarks) {
// See https://github.com/denoland/deno/pull/1452 about groupCollapsed
console.groupCollapsed(`benchmark ${name} ... `);
// Trying benchmark.func
- let result: string;
+ let result = "";
try {
if (runs === 1) {
// b is a benchmark timer interfacing an unset (NaN) benchmark clock
@@ -126,7 +126,7 @@ export async function runBenchmarks({
} else if (runs > 1) {
// Averaging runs
let pendingRuns = runs;
- let totalMs: number = 0;
+ let totalMs = 0;
// Would be better 2 not run these serially
while (true) {
// b is a benchmark timer interfacing an unset (NaN) benchmark clock
diff --git a/benching/test.ts b/benching/test.ts
index 81cbc5e6f..34f7b00d2 100644
--- a/benching/test.ts
+++ b/benching/test.ts
@@ -6,19 +6,19 @@ import "example.ts";
test(async function benching() {
bench(function forIncrementX1e9(b: BenchmarkTimer) {
b.start();
- for (let i: number = 0; i < 1e9; i++);
+ for (let i = 0; i < 1e9; i++);
b.stop();
});
bench(function forDecrementX1e9(b: BenchmarkTimer) {
b.start();
- for (let i: number = 1e9; i > 0; i--);
+ for (let i = 1e9; i > 0; i--);
b.stop();
});
bench(async function forAwaitFetchDenolandX10(b: BenchmarkTimer) {
b.start();
- for (let i: number = 0; i < 10; i++) {
+ for (let i = 0; i < 10; i++) {
await fetch("https://deno.land/");
}
b.stop();
@@ -36,7 +36,7 @@ test(async function benching() {
runs: 100,
func(b: BenchmarkTimer) {
b.start();
- for (let i: number = 0; i < 1e6; i++);
+ for (let i = 0; i < 1e6; i++);
b.stop();
}
});
diff --git a/bytes/bytes.ts b/bytes/bytes.ts
index ef333288e..080ec4445 100644
--- a/bytes/bytes.ts
+++ b/bytes/bytes.ts
@@ -22,7 +22,7 @@ export function bytesFindIndex(a: Uint8Array, pat: Uint8Array): number {
}
/** Find last index of binary pattern from a. If not found, then return -1 **/
-export function bytesFindLastIndex(a: Uint8Array, pat: Uint8Array) {
+export function bytesFindLastIndex(a: Uint8Array, pat: Uint8Array): number {
const e = pat[pat.length - 1];
for (let i = a.length - 1; i >= 0; i--) {
if (a[i] !== e) continue;
diff --git a/colors/mod.ts b/colors/mod.ts
index 7a45905ce..d0b4bc320 100644
--- a/colors/mod.ts
+++ b/colors/mod.ts
@@ -9,7 +9,7 @@ interface Code {
let enabled = !noColor;
-export function setEnabled(value: boolean) {
+export function setEnabled(value: boolean): void {
if (noColor) {
return;
}
@@ -29,7 +29,7 @@ function code(open: number, close: number): Code {
};
}
-function run(str: string, code: Code) {
+function run(str: string, code: Code): string {
return enabled
? `${code.open}${str.replace(code.regexp, code.open)}${code.close}`
: str;
diff --git a/datetime/mod.ts b/datetime/mod.ts
index f30fc89c9..96ed3a860 100644
--- a/datetime/mod.ts
+++ b/datetime/mod.ts
@@ -13,13 +13,13 @@ export function parseDate(dateStr: string, format: DateFormat): Date {
if (format === "mm-dd-yyyy") {
const datePattern = /^(\d{2})-(\d{2})-(\d{4})$/;
- [, m, d, y] = datePattern.exec(dateStr);
+ [, m, d, y] = datePattern.exec(dateStr)!;
} else if (format === "dd-mm-yyyy") {
const datePattern = /^(\d{2})-(\d{2})-(\d{4})$/;
- [, d, m, y] = datePattern.exec(dateStr);
+ [, d, m, y] = datePattern.exec(dateStr)!;
} else if (format === "yyyy-mm-dd") {
const datePattern = /^(\d{4})-(\d{2})-(\d{2})$/;
- [, y, m, d] = datePattern.exec(dateStr);
+ [, y, m, d] = datePattern.exec(dateStr)!;
} else {
throw new Error("Invalid date format!");
}
@@ -50,22 +50,22 @@ export function parseDateTime(
if (format === "mm-dd-yyyy hh:mm") {
const datePattern = /^(\d{2})-(\d{2})-(\d{4}) (\d{2}):(\d{2})$/;
- [, m, d, y, ho, mi] = datePattern.exec(datetimeStr);
+ [, m, d, y, ho, mi] = datePattern.exec(datetimeStr)!;
} else if (format === "dd-mm-yyyy hh:mm") {
const datePattern = /^(\d{2})-(\d{2})-(\d{4}) (\d{2}):(\d{2})$/;
- [, d, m, y, ho, mi] = datePattern.exec(datetimeStr);
+ [, d, m, y, ho, mi] = datePattern.exec(datetimeStr)!;
} else if (format === "yyyy-mm-dd hh:mm") {
const datePattern = /^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2})$/;
- [, y, m, d, ho, mi] = datePattern.exec(datetimeStr);
+ [, y, m, d, ho, mi] = datePattern.exec(datetimeStr)!;
} else if (format === "hh:mm mm-dd-yyyy") {
const datePattern = /^(\d{2}):(\d{2}) (\d{2})-(\d{2})-(\d{4})$/;
- [, ho, mi, m, d, y] = datePattern.exec(datetimeStr);
+ [, ho, mi, m, d, y] = datePattern.exec(datetimeStr)!;
} else if (format === "hh:mm dd-mm-yyyy") {
const datePattern = /^(\d{2}):(\d{2}) (\d{2})-(\d{2})-(\d{4})$/;
- [, ho, mi, d, m, y] = datePattern.exec(datetimeStr);
+ [, ho, mi, d, m, y] = datePattern.exec(datetimeStr)!;
} else if (format === "hh:mm yyyy-mm-dd") {
const datePattern = /^(\d{2}):(\d{2}) (\d{4})-(\d{2})-(\d{2})$/;
- [, ho, mi, y, m, d] = datePattern.exec(datetimeStr);
+ [, ho, mi, y, m, d] = datePattern.exec(datetimeStr)!;
} else {
throw new Error("Invalid datetime format!");
}
diff --git a/datetime/test.ts b/datetime/test.ts
index 3329e9cd1..7182c27c4 100644
--- a/datetime/test.ts
+++ b/datetime/test.ts
@@ -31,6 +31,7 @@ test(function parseDateTime() {
test(function invalidParseDateTimeFormatThrows() {
try {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
(datetime as any).parseDateTime("2019-01-01 00:00", "x-y-z");
assert(false, "no exception was thrown");
} catch (e) {
@@ -55,6 +56,7 @@ test(function parseDate() {
test(function invalidParseDateFormatThrows() {
try {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
(datetime as any).parseDate("2019-01-01", "x-y-z");
assert(false, "no exception was thrown");
} catch (e) {
diff --git a/examples/gist.ts b/examples/gist.ts
index 8ce68a946..f64f69226 100755
--- a/examples/gist.ts
+++ b/examples/gist.ts
@@ -9,7 +9,7 @@ function pathBase(p: string): string {
return parts[parts.length - 1];
}
-async function main() {
+async function main(): Promise<void> {
const token = env()["GIST_TOKEN"];
if (!token) {
console.error("GIST_TOKEN environmental variable not set.");
@@ -46,7 +46,7 @@ async function main() {
headers: [
["Content-Type", "application/json"],
["User-Agent", "Deno-Gist"],
- ["Authorization", "token " + token]
+ ["Authorization", `token ${token}`]
],
body
});
diff --git a/examples/ws.ts b/examples/ws.ts
index bc2a7bd0b..f25a15687 100644
--- a/examples/ws.ts
+++ b/examples/ws.ts
@@ -6,7 +6,7 @@ import {
isWebSocketPingEvent
} from "https://deno.land/x/ws/mod.ts";
-async function main() {
+async function main(): Promise<void> {
console.log("websocket server is running on 0.0.0.0:8080");
for await (const req of serve("0.0.0.0:8080")) {
if (req.url === "/ws") {
@@ -22,7 +22,7 @@ async function main() {
// binary message
console.log("ws:Binary", ev);
} else if (isWebSocketPingEvent(ev)) {
- const [_, body] = ev;
+ const [, body] = ev;
// ping
console.log("ws:Ping", body);
} else if (isWebSocketCloseEvent(ev)) {
diff --git a/io/bufio.ts b/io/bufio.ts
index 05e6b0a0c..33cddea2b 100644
--- a/io/bufio.ts
+++ b/io/bufio.ts
@@ -211,7 +211,7 @@ export class BufReader implements Reader {
* delim.
* For simple uses, a Scanner may be more convenient.
*/
- async readString(delim: string): Promise<string> {
+ async readString(_delim: string): Promise<string> {
throw new Error("Not implemented");
}
diff --git a/io/bufio_test.ts b/io/bufio_test.ts
index 0a261daea..41151b681 100644
--- a/io/bufio_test.ts
+++ b/io/bufio_test.ts
@@ -6,7 +6,7 @@
const { Buffer } = Deno;
import { Reader, ReadResult } from "deno";
import { test, assert, assertEqual } from "../testing/mod.ts";
-import { BufReader, BufState, BufWriter } from "./bufio.ts";
+import { BufReader, BufWriter } from "./bufio.ts";
import * as iotest from "./iotest.ts";
import { charCode, copyBytes, stringsReader } from "./util.ts";
@@ -34,7 +34,10 @@ test(async function bufioReaderSimple() {
assert.equal(s, data);
});
-type ReadMaker = { name: string; fn: (r: Reader) => Reader };
+interface ReadMaker {
+ name: string;
+ fn: (r: Reader) => Reader;
+}
const readMakers: ReadMaker[] = [
{ name: "full", fn: r => r },
@@ -44,18 +47,6 @@ const readMakers: ReadMaker[] = [
// { name: "timeout", fn: r => new iotest.TimeoutReader(r) },
];
-function readLines(b: BufReader): string {
- let s = "";
- while (true) {
- let s1 = b.readString("\n");
- if (s1 == null) {
- break; // EOF
- }
- s += s1;
- }
- return s;
-}
-
// Call read to accumulate the text of a file
async function reads(buf: BufReader, m: number): Promise<string> {
const b = new Uint8Array(1000);
@@ -71,7 +62,10 @@ async function reads(buf: BufReader, m: number): Promise<string> {
return decoder.decode(b.subarray(0, nb));
}
-type NamedBufReader = { name: string; fn: (r: BufReader) => Promise<string> };
+interface NamedBufReader {
+ name: string;
+ fn: (r: BufReader) => Promise<string>;
+}
const bufreaders: NamedBufReader[] = [
{ name: "1", fn: (b: BufReader) => reads(b, 1) },
@@ -187,6 +181,7 @@ async function testReadLine(input: Uint8Array): Promise<void> {
if (err == "EOF") {
break;
}
+ // eslint-disable-next-line @typescript-eslint/restrict-plus-operands
let want = testOutput.subarray(done, done + line.byteLength);
assertEqual(
line,
@@ -290,6 +285,7 @@ test(async function bufioWriter() {
const data = new Uint8Array(8192);
for (let i = 0; i < data.byteLength; i++) {
+ // eslint-disable-next-line @typescript-eslint/restrict-plus-operands
data[i] = charCode(" ") + (i % (charCode("~") - charCode(" ")));
}
diff --git a/io/ioutil_test.ts b/io/ioutil_test.ts
index 168aad52a..08d0d677e 100644
--- a/io/ioutil_test.ts
+++ b/io/ioutil_test.ts
@@ -1,7 +1,7 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
const { Buffer } = Deno;
import { Reader, ReadResult } from "deno";
-import { assert, assertEqual, runTests, test } from "../testing/mod.ts";
+import { assert, assertEqual, test } from "../testing/mod.ts";
import {
copyN,
readInt,
diff --git a/io/writers_test.ts b/io/writers_test.ts
index 94c58417d..ba4d7ed89 100644
--- a/io/writers_test.ts
+++ b/io/writers_test.ts
@@ -7,7 +7,7 @@ import { copyN } from "./ioutil.ts";
test(async function ioStringWriter() {
const w = new StringWriter("base");
const r = new StringReader("0123456789");
- const n = await copyN(w, r, 4);
+ await copyN(w, r, 4);
assert.equal(w.toString(), "base0123");
await copy(w, r);
assert.equal(w.toString(), "base0123456789");
diff --git a/log/handlers.ts b/log/handlers.ts
index 96d8c056f..c1f664cc0 100644
--- a/log/handlers.ts
+++ b/log/handlers.ts
@@ -24,7 +24,7 @@ export class BaseHandler {
this.formatter = options.formatter || DEFAULT_FORMATTER;
}
- handle(logRecord: LogRecord) {
+ handle(logRecord: LogRecord): void {
if (this.level > logRecord.level) return;
const msg = this.format(logRecord);
@@ -48,9 +48,9 @@ export class BaseHandler {
});
}
- log(msg: string) {}
- async setup() {}
- async destroy() {}
+ log(_msg: string): void {}
+ async setup(): Promise<void> {}
+ async destroy(): Promise<void> {}
}
export class ConsoleHandler extends BaseHandler {
@@ -77,7 +77,7 @@ export class ConsoleHandler extends BaseHandler {
return msg;
}
- log(msg: string) {
+ log(msg: string): void {
console.log(msg);
}
}
@@ -86,7 +86,7 @@ export abstract class WriterHandler extends BaseHandler {
protected _writer: Writer;
private _encoder = new TextEncoder();
- log(msg: string) {
+ log(msg: string): void {
this._writer.write(this._encoder.encode(msg + "\n"));
}
}
@@ -104,13 +104,13 @@ export class FileHandler extends WriterHandler {
this._filename = options.filename;
}
- async setup() {
+ async setup(): Promise<void> {
// open file in append mode - write only
this._file = await open(this._filename, "a");
this._writer = this._file;
}
- async destroy() {
+ async destroy(): Promise<void> {
await this._file.close();
}
}
diff --git a/log/handlers_test.ts b/log/handlers_test.ts
index 52eca16ea..7dc4e2089 100644
--- a/log/handlers_test.ts
+++ b/log/handlers_test.ts
@@ -1,6 +1,5 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
import { assertEqual, test } from "../testing/mod.ts";
-import { LogRecord, Logger } from "./logger.ts";
import { LogLevel, getLevelName, getLevelByName } from "./levels.ts";
import { BaseHandler } from "./handlers.ts";
diff --git a/log/logger.ts b/log/logger.ts
index 678d5ed94..d92c34a58 100644
--- a/log/logger.ts
+++ b/log/logger.ts
@@ -4,6 +4,7 @@ import { BaseHandler } from "./handlers.ts";
export interface LogRecord {
msg: string;
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
args: any[];
datetime: Date;
level: number;
@@ -13,6 +14,7 @@ export interface LogRecord {
export class Logger {
level: number;
levelName: string;
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
handlers: any[];
constructor(levelName: string, handlers?: BaseHandler[]) {
@@ -22,7 +24,8 @@ export class Logger {
this.handlers = handlers || [];
}
- _log(level: number, msg: string, ...args: any[]) {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ _log(level: number, msg: string, ...args: any[]): void {
if (this.level > level) return;
// TODO: it'd be a good idea to make it immutable, so
@@ -41,23 +44,28 @@ export class Logger {
});
}
- debug(msg: string, ...args: any[]) {
- return this._log(LogLevel.DEBUG, msg, ...args);
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ debug(msg: string, ...args: any[]): void {
+ this._log(LogLevel.DEBUG, msg, ...args);
}
- info(msg: string, ...args: any[]) {
- return this._log(LogLevel.INFO, msg, ...args);
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ info(msg: string, ...args: any[]): void {
+ this._log(LogLevel.INFO, msg, ...args);
}
- warning(msg: string, ...args: any[]) {
- return this._log(LogLevel.WARNING, msg, ...args);
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ warning(msg: string, ...args: any[]): void {
+ this._log(LogLevel.WARNING, msg, ...args);
}
- error(msg: string, ...args: any[]) {
- return this._log(LogLevel.ERROR, msg, ...args);
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ error(msg: string, ...args: any[]): void {
+ this._log(LogLevel.ERROR, msg, ...args);
}
- critical(msg: string, ...args: any[]) {
- return this._log(LogLevel.CRITICAL, msg, ...args);
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ critical(msg: string, ...args: any[]): void {
+ this._log(LogLevel.CRITICAL, msg, ...args);
}
}
diff --git a/log/logger_test.ts b/log/logger_test.ts
index a2275a00b..8ff328c48 100644
--- a/log/logger_test.ts
+++ b/log/logger_test.ts
@@ -53,7 +53,7 @@ test(function customHandler() {
test(function logFunctions() {
let handler: TestHandler;
- const doLog = (level: string) => {
+ const doLog = (level: string): void => {
handler = new TestHandler(level);
let logger = new Logger(level, [handler]);
logger.debug("foo");
diff --git a/log/mod.ts b/log/mod.ts
index 96dc81ff1..ef5ca5a89 100644
--- a/log/mod.ts
+++ b/log/mod.ts
@@ -36,8 +36,8 @@ const DEFAULT_CONFIG: LogConfig = {
};
const state = {
- handlers: new Map(),
- loggers: new Map(),
+ handlers: new Map<string, BaseHandler>(),
+ loggers: new Map<string, Logger>(),
config: DEFAULT_CONFIG
};
@@ -48,18 +48,7 @@ export const handlers = {
FileHandler
};
-export const debug = (msg: string, ...args: any[]) =>
- getLogger("default").debug(msg, ...args);
-export const info = (msg: string, ...args: any[]) =>
- getLogger("default").info(msg, ...args);
-export const warning = (msg: string, ...args: any[]) =>
- getLogger("default").warning(msg, ...args);
-export const error = (msg: string, ...args: any[]) =>
- getLogger("default").error(msg, ...args);
-export const critical = (msg: string, ...args: any[]) =>
- getLogger("default").critical(msg, ...args);
-
-export function getLogger(name?: string) {
+export function getLogger(name?: string): Logger {
if (!name) {
return state.loggers.get("default");
}
@@ -73,11 +62,27 @@ export function getLogger(name?: string) {
return state.loggers.get(name);
}
-export function getHandler(name: string) {
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export const debug = (msg: string, ...args: any[]): void =>
+ getLogger("default").debug(msg, ...args);
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export const info = (msg: string, ...args: any[]): void =>
+ getLogger("default").info(msg, ...args);
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export const warning = (msg: string, ...args: any[]): void =>
+ getLogger("default").warning(msg, ...args);
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export const error = (msg: string, ...args: any[]): void =>
+ getLogger("default").error(msg, ...args);
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export const critical = (msg: string, ...args: any[]): void =>
+ getLogger("default").critical(msg, ...args);
+
+export function getHandler(name: string): BaseHandler {
return state.handlers.get(name);
}
-export async function setup(config: LogConfig) {
+export async function setup(config: LogConfig): Promise<void> {
state.config = {
handlers: { ...DEFAULT_CONFIG.handlers, ...config.handlers },
loggers: { ...DEFAULT_CONFIG.loggers, ...config.loggers }
@@ -106,7 +111,7 @@ export async function setup(config: LogConfig) {
for (const loggerName in loggers) {
const loggerConfig = loggers[loggerName];
const handlerNames = loggerConfig.handlers || [];
- const handlers = [];
+ const handlers: BaseHandler[] = [];
handlerNames.forEach(handlerName => {
if (state.handlers.has(handlerName)) {
diff --git a/log/test.ts b/log/test.ts
index 918368b97..3599247bd 100644
--- a/log/test.ts
+++ b/log/test.ts
@@ -1,8 +1,6 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
import { assertEqual, test } from "../testing/mod.ts";
import * as log from "./mod.ts";
-import { BaseHandler } from "./handlers.ts";
-import { LogRecord } from "./logger.ts";
import { LogLevel } from "./levels.ts";
import "./handlers_test.ts";
@@ -18,7 +16,7 @@ import "./logger_test.ts";
class TestHandler extends log.handlers.BaseHandler {
public messages: string[] = [];
- log(msg: string) {
+ log(msg: string): void {
this.messages.push(msg);
}
}
diff --git a/media_types/mod.ts b/media_types/mod.ts
index 3b74427ba..b7c75fb22 100644
--- a/media_types/mod.ts
+++ b/media_types/mod.ts
@@ -42,7 +42,7 @@ export const types = new Map<string, string>();
function populateMaps(
extensions: Map<string, string[]>,
types: Map<string, string>
-) {
+): void {
const preference = ["nginx", "apache", undefined, "iana"];
for (const type of Object.keys(db)) {
@@ -98,6 +98,17 @@ export function charset(type: string): string | undefined {
}
}
+/** Given an extension, lookup the appropriate media type for that extension.
+ * Likely you should be using `contentType()` though instead.
+ */
+export function lookup(path: string): string | undefined {
+ const extension = extname("x." + path)
+ .toLowerCase()
+ .substr(1);
+
+ return types.get(extension);
+}
+
/** Given an extension or media type, return the full `Content-Type` header
* string. Returns `undefined` if not resolvable.
*/
@@ -136,14 +147,3 @@ export function extension(type: string): string | undefined {
return exts[0];
}
-
-/** Given an extension, lookup the appropriate media type for that extension.
- * Likely you should be using `contentType()` though instead.
- */
-export function lookup(path: string): string | undefined {
- const extension = extname("x." + path)
- .toLowerCase()
- .substr(1);
-
- return types.get(extension);
-}
diff --git a/multipart/formfile.ts b/multipart/formfile.ts
index b1b63eb15..8bbdcffbc 100644
--- a/multipart/formfile.ts
+++ b/multipart/formfile.ts
@@ -1,7 +1,7 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
/** FormFile object */
-export type FormFile = {
+export interface FormFile {
/** filename */
filename: string;
/** content-type header value of file */
@@ -12,10 +12,11 @@ export type FormFile = {
content?: Uint8Array;
/** temporal file path. Set if file size is bigger than specified max-memory size at reading form */
tempfile?: string;
-};
+}
/** Type guard for FormFile */
-export function isFormFile(x): x is FormFile {
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export function isFormFile(x: any): x is FormFile {
return (
typeof x === "object" &&
x.hasOwnProperty("filename") &&
diff --git a/multipart/multipart.ts b/multipart/multipart.ts
index 70874ed85..68785c7c6 100644
--- a/multipart/multipart.ts
+++ b/multipart/multipart.ts
@@ -17,7 +17,7 @@ import { TextProtoReader } from "../textproto/mod.ts";
import { encoder } from "../strings/strings.ts";
import * as path from "../fs/path.ts";
-function randomBoundary() {
+function randomBoundary(): string {
let boundary = "--------------------------";
for (let i = 0; i < 24; i++) {
boundary += Math.floor(Math.random() * 10).toString(16);
@@ -25,6 +25,185 @@ function randomBoundary() {
return boundary;
}
+export function matchAfterPrefix(
+ a: Uint8Array,
+ prefix: Uint8Array,
+ bufState: BufState
+): number {
+ if (a.length === prefix.length) {
+ if (bufState) {
+ return 1;
+ }
+ return 0;
+ }
+ const c = a[prefix.length];
+ if (
+ c === " ".charCodeAt(0) ||
+ c === "\t".charCodeAt(0) ||
+ c === "\r".charCodeAt(0) ||
+ c === "\n".charCodeAt(0) ||
+ c === "-".charCodeAt(0)
+ ) {
+ return 1;
+ }
+ return -1;
+}
+
+export function scanUntilBoundary(
+ buf: Uint8Array,
+ dashBoundary: Uint8Array,
+ newLineDashBoundary: Uint8Array,
+ total: number,
+ state: BufState
+): [number, BufState] {
+ if (total === 0) {
+ if (bytesHasPrefix(buf, dashBoundary)) {
+ switch (matchAfterPrefix(buf, dashBoundary, state)) {
+ case -1:
+ return [dashBoundary.length, null];
+ case 0:
+ return [0, null];
+ case 1:
+ return [0, "EOF"];
+ }
+ if (bytesHasPrefix(dashBoundary, buf)) {
+ return [0, state];
+ }
+ }
+ }
+ const i = bytesFindIndex(buf, newLineDashBoundary);
+ if (i >= 0) {
+ switch (matchAfterPrefix(buf.slice(i), newLineDashBoundary, state)) {
+ case -1:
+ // eslint-disable-next-line @typescript-eslint/restrict-plus-operands
+ return [i + newLineDashBoundary.length, null];
+ case 0:
+ return [i, null];
+ case 1:
+ return [i, "EOF"];
+ }
+ }
+ if (bytesHasPrefix(newLineDashBoundary, buf)) {
+ return [0, state];
+ }
+ const j = bytesFindLastIndex(buf, newLineDashBoundary.slice(0, 1));
+ if (j >= 0 && bytesHasPrefix(newLineDashBoundary, buf.slice(j))) {
+ return [j, null];
+ }
+ return [buf.length, state];
+}
+
+let i = 0;
+
+class PartReader implements Reader, Closer {
+ n: number = 0;
+ total: number = 0;
+ bufState: BufState = null;
+ index = i++;
+
+ constructor(private mr: MultipartReader, public readonly headers: Headers) {}
+
+ async read(p: Uint8Array): Promise<ReadResult> {
+ const br = this.mr.bufReader;
+ const returnResult = (nread: number, bufState: BufState): ReadResult => {
+ if (bufState && bufState !== "EOF") {
+ throw bufState;
+ }
+ return { nread, eof: bufState === "EOF" };
+ };
+ if (this.n === 0 && !this.bufState) {
+ const [peek] = await br.peek(br.buffered());
+ const [n, state] = scanUntilBoundary(
+ peek,
+ this.mr.dashBoundary,
+ this.mr.newLineDashBoundary,
+ this.total,
+ this.bufState
+ );
+ this.n = n;
+ this.bufState = state;
+ if (this.n === 0 && !this.bufState) {
+ // eslint-disable-next-line @typescript-eslint/restrict-plus-operands
+ const [, state] = await br.peek(peek.length + 1);
+ this.bufState = state;
+ if (this.bufState === "EOF") {
+ this.bufState = new RangeError("unexpected eof");
+ }
+ }
+ }
+ if (this.n === 0) {
+ return returnResult(0, this.bufState);
+ }
+
+ let n = 0;
+ if (p.byteLength > this.n) {
+ n = this.n;
+ }
+ const buf = p.slice(0, n);
+ const [nread] = await this.mr.bufReader.readFull(buf);
+ p.set(buf);
+ this.total += nread;
+ this.n -= nread;
+ if (this.n === 0) {
+ return returnResult(n, this.bufState);
+ }
+ return returnResult(n, null);
+ }
+
+ close(): void {}
+
+ private contentDisposition: string;
+ private contentDispositionParams: { [key: string]: string };
+
+ private getContentDispositionParams(): { [key: string]: string } {
+ if (this.contentDispositionParams) return this.contentDispositionParams;
+ const cd = this.headers.get("content-disposition");
+ const params = {};
+ const comps = cd.split(";");
+ this.contentDisposition = comps[0];
+ comps
+ .slice(1)
+ .map(v => v.trim())
+ .map(kv => {
+ const [k, v] = kv.split("=");
+ if (v) {
+ const s = v.charAt(0);
+ const e = v.charAt(v.length - 1);
+ if ((s === e && s === '"') || s === "'") {
+ params[k] = v.substr(1, v.length - 2);
+ } else {
+ params[k] = v;
+ }
+ }
+ });
+ return (this.contentDispositionParams = params);
+ }
+
+ get fileName(): string {
+ return this.getContentDispositionParams()["filename"];
+ }
+
+ get formName(): string {
+ const p = this.getContentDispositionParams();
+ if (this.contentDisposition === "form-data") {
+ return p["name"];
+ }
+ return "";
+ }
+}
+
+function skipLWSPChar(u: Uint8Array): Uint8Array {
+ const ret = new Uint8Array(u.length);
+ const sp = " ".charCodeAt(0);
+ const ht = "\t".charCodeAt(0);
+ let j = 0;
+ for (let i = 0; i < u.length; i++) {
+ if (u[i] === sp || u[i] === ht) continue;
+ ret[j++] = u[i];
+ }
+ return ret.slice(0, j);
+}
+
/** Reader for parsing multipart/form-data */
export class MultipartReader {
readonly newLine = encoder.encode("\r\n");
@@ -125,7 +304,7 @@ export class MultipartReader {
break;
}
if (state) {
- throw new Error("aa" + state.toString());
+ throw new Error(`aa${state.toString()}`);
}
if (this.isBoundaryDelimiterLine(line)) {
this.partsRead++;
@@ -155,7 +334,7 @@ export class MultipartReader {
}
}
- private isFinalBoundary(line: Uint8Array) {
+ private isFinalBoundary(line: Uint8Array): boolean {
if (!bytesHasPrefix(line, this.dashBoundaryDash)) {
return false;
}
@@ -163,7 +342,7 @@ export class MultipartReader {
return rest.length === 0 || bytesEqual(skipLWSPChar(rest), this.newLine);
}
- private isBoundaryDelimiterLine(line: Uint8Array) {
+ private isBoundaryDelimiterLine(line: Uint8Array): boolean {
if (!bytesHasPrefix(line, this.dashBoundary)) {
return false;
}
@@ -172,183 +351,6 @@ export class MultipartReader {
}
}
-function skipLWSPChar(u: Uint8Array): Uint8Array {
- const ret = new Uint8Array(u.length);
- const sp = " ".charCodeAt(0);
- const ht = "\t".charCodeAt(0);
- let j = 0;
- for (let i = 0; i < u.length; i++) {
- if (u[i] === sp || u[i] === ht) continue;
- ret[j++] = u[i];
- }
- return ret.slice(0, j);
-}
-
-let i = 0;
-
-class PartReader implements Reader, Closer {
- n: number = 0;
- total: number = 0;
- bufState: BufState = null;
- index = i++;
-
- constructor(private mr: MultipartReader, public readonly headers: Headers) {}
-
- async read(p: Uint8Array): Promise<ReadResult> {
- const br = this.mr.bufReader;
- const returnResult = (nread: number, bufState: BufState): ReadResult => {
- if (bufState && bufState !== "EOF") {
- throw bufState;
- }
- return { nread, eof: bufState === "EOF" };
- };
- if (this.n === 0 && !this.bufState) {
- const [peek] = await br.peek(br.buffered());
- const [n, state] = scanUntilBoundary(
- peek,
- this.mr.dashBoundary,
- this.mr.newLineDashBoundary,
- this.total,
- this.bufState
- );
- this.n = n;
- this.bufState = state;
- if (this.n === 0 && !this.bufState) {
- const [_, state] = await br.peek(peek.length + 1);
- this.bufState = state;
- if (this.bufState === "EOF") {
- this.bufState = new RangeError("unexpected eof");
- }
- }
- }
- if (this.n === 0) {
- return returnResult(0, this.bufState);
- }
-
- let n = 0;
- if (p.byteLength > this.n) {
- n = this.n;
- }
- const buf = p.slice(0, n);
- const [nread] = await this.mr.bufReader.readFull(buf);
- p.set(buf);
- this.total += nread;
- this.n -= nread;
- if (this.n === 0) {
- return returnResult(n, this.bufState);
- }
- return returnResult(n, null);
- }
-
- close(): void {}
-
- private contentDisposition: string;
- private contentDispositionParams: { [key: string]: string };
-
- private getContentDispositionParams() {
- if (this.contentDispositionParams) return this.contentDispositionParams;
- const cd = this.headers.get("content-disposition");
- const params = {};
- const comps = cd.split(";");
- this.contentDisposition = comps[0];
- comps
- .slice(1)
- .map(v => v.trim())
- .map(kv => {
- const [k, v] = kv.split("=");
- if (v) {
- const s = v.charAt(0);
- const e = v.charAt(v.length - 1);
- if ((s === e && s === '"') || s === "'") {
- params[k] = v.substr(1, v.length - 2);
- } else {
- params[k] = v;
- }
- }
- });
- return (this.contentDispositionParams = params);
- }
-
- get fileName(): string {
- return this.getContentDispositionParams()["filename"];
- }
-
- get formName(): string {
- const p = this.getContentDispositionParams();
- if (this.contentDisposition === "form-data") {
- return p["name"];
- }
- return "";
- }
-}
-
-export function scanUntilBoundary(
- buf: Uint8Array,
- dashBoundary: Uint8Array,
- newLineDashBoundary: Uint8Array,
- total: number,
- state: BufState
-): [number, BufState] {
- if (total === 0) {
- if (bytesHasPrefix(buf, dashBoundary)) {
- switch (matchAfterPrefix(buf, dashBoundary, state)) {
- case -1:
- return [dashBoundary.length, null];
- case 0:
- return [0, null];
- case 1:
- return [0, "EOF"];
- }
- if (bytesHasPrefix(dashBoundary, buf)) {
- return [0, state];
- }
- }
- }
- const i = bytesFindIndex(buf, newLineDashBoundary);
- if (i >= 0) {
- switch (matchAfterPrefix(buf.slice(i), newLineDashBoundary, state)) {
- case -1:
- return [i + newLineDashBoundary.length, null];
- case 0:
- return [i, null];
- case 1:
- return [i, "EOF"];
- }
- }
- if (bytesHasPrefix(newLineDashBoundary, buf)) {
- return [0, state];
- }
- const j = bytesFindLastIndex(buf, newLineDashBoundary.slice(0, 1));
- if (j >= 0 && bytesHasPrefix(newLineDashBoundary, buf.slice(j))) {
- return [j, null];
- }
- return [buf.length, state];
-}
-
-export function matchAfterPrefix(
- a: Uint8Array,
- prefix: Uint8Array,
- bufState: BufState
-): number {
- if (a.length === prefix.length) {
- if (bufState) {
- return 1;
- }
- return 0;
- }
- const c = a[prefix.length];
- if (
- c === " ".charCodeAt(0) ||
- c === "\t".charCodeAt(0) ||
- c === "\r".charCodeAt(0) ||
- c === "\n".charCodeAt(0) ||
- c === "-".charCodeAt(0)
- ) {
- return 1;
- }
- return -1;
-}
-
class PartWriter implements Writer {
closed = false;
private readonly partHeader: string;
@@ -389,9 +391,9 @@ class PartWriter implements Writer {
}
}
-function checkBoundary(b: string) {
+function checkBoundary(b: string): string {
if (b.length < 1 || b.length > 70) {
- throw new Error("invalid boundary length: " + b.length);
+ throw new Error(`invalid boundary length: ${b.length}`);
}
const end = b.length - 1;
for (let i = 0; i < end; i++) {
@@ -407,7 +409,7 @@ function checkBoundary(b: string) {
export class MultipartWriter {
private readonly _boundary: string;
- get boundary() {
+ get boundary(): string {
return this._boundary;
}
@@ -462,12 +464,16 @@ export class MultipartWriter {
return this.createPart(h);
}
- async writeField(field: string, value: string) {
+ async writeField(field: string, value: string): Promise<void> {
const f = await this.createFormField(field);
await f.write(encoder.encode(value));
}
- async writeFile(field: string, filename: string, file: Reader) {
+ async writeFile(
+ field: string,
+ filename: string,
+ file: Reader
+ ): Promise<void> {
const f = await this.createFormFile(field, filename);
await copy(f, file);
}
@@ -477,7 +483,7 @@ export class MultipartWriter {
}
/** Close writer. No additional data can be writen to stream */
- async close() {
+ async close(): Promise<void> {
if (this.isClosed) {
throw new Error("multipart: writer is closed");
}
diff --git a/multipart/multipart_test.ts b/multipart/multipart_test.ts
index a87db60d7..b4c0f761d 100644
--- a/multipart/multipart_test.ts
+++ b/multipart/multipart_test.ts
@@ -13,7 +13,6 @@ import { FormFile, isFormFile } from "./formfile.ts";
import { StringWriter } from "../io/writers.ts";
const e = new TextEncoder();
-const d = new TextDecoder();
const boundary = "--abcde";
const dashBoundary = e.encode("--" + boundary);
const nlDashBoundary = e.encode("\r\n--" + boundary);
diff --git a/prettier/main.ts b/prettier/main.ts
index 70c225086..286cba58c 100755
--- a/prettier/main.ts
+++ b/prettier/main.ts
@@ -2,7 +2,7 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
// This script formats the given source files. If the files are omitted, it
// formats the all files in the repository.
-const { args, platform, readAll, lstat, exit, run, readFile, writeFile } = Deno;
+const { args, readAll, lstat, exit, readFile, writeFile } = Deno;
import { xrun } from "./util.ts";
import { parse } from "../flags/mod.ts";
import { prettier, prettierPlugins } from "./prettier.ts";
@@ -67,7 +67,7 @@ async function getSourceFiles(args: string[]): Promise<string[]> {
}
// Filters out the files which contains any pattern in the given ignoreList.
-function filterIgnoreList(files: string[], ignoreList: string[]) {
+function filterIgnoreList(files: string[], ignoreList: string[]): string[] {
return files.filter(path =>
ignoreList.every(pattern => !path.includes(pattern))
);
@@ -203,7 +203,7 @@ async function formatSourceFiles(
exit(0);
}
-async function main(opts) {
+async function main(opts): Promise<void> {
const { help, ignore, check, _: args } = opts;
if (help) {
diff --git a/prettier/main_test.ts b/prettier/main_test.ts
index 165081e00..b6c0489ee 100644
--- a/prettier/main_test.ts
+++ b/prettier/main_test.ts
@@ -5,7 +5,9 @@ const { readAll } = Deno;
const decoder = new TextDecoder();
-async function run(args: string[]) {
+async function run(
+ args: string[]
+): Promise<{ stdout: string; code: number | undefined }> {
const p = xrun({ args, stdout: "piped" });
const stdout = decoder.decode(await readAll(p.stdout));
@@ -33,7 +35,7 @@ function normalizeOutput(output: string): string {
.join("\n");
}
-async function clearTestdataChanges() {
+async function clearTestdataChanges(): Promise<void> {
await xrun({ args: ["git", "checkout", testdata] }).status();
}
diff --git a/prettier/prettier.ts b/prettier/prettier.ts
index 67099c5ca..98f36a78d 100644
--- a/prettier/prettier.ts
+++ b/prettier/prettier.ts
@@ -5,6 +5,7 @@ import "./vendor/parser_babylon.js";
import "./vendor/parser_markdown.js";
// TODO: provide decent type declarions for these
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
const { prettier, prettierPlugins } = window as any;
export { prettier, prettierPlugins };
diff --git a/prettier/util.ts b/prettier/util.ts
index 0be583f75..425cbfe96 100644
--- a/prettier/util.ts
+++ b/prettier/util.ts
@@ -2,7 +2,7 @@
const { platform, run } = Deno;
// Runs a command in cross-platform way
-export function xrun(opts) {
+export function xrun(opts): Deno.Process {
return run({
...opts,
args: platform.os === "win" ? ["cmd.exe", "/c", ...opts.args] : opts.args
diff --git a/testing/diff.ts b/testing/diff.ts
index a1385b88a..4fab75e4a 100644
--- a/testing/diff.ts
+++ b/testing/diff.ts
@@ -15,7 +15,7 @@ const REMOVED = 1;
const COMMON = 2;
const ADDED = 3;
-function createCommon<T>(A: T[], B: T[], reverse?: boolean) {
+function createCommon<T>(A: T[], B: T[], reverse?: boolean): T[] {
const common = [];
if (A.length === 0 || B.length === 0) return [];
for (let i = 0; i < Math.min(A.length, B.length); i += 1) {
@@ -30,13 +30,55 @@ function createCommon<T>(A: T[], B: T[], reverse?: boolean) {
return common;
}
-export default function diff<T>(A: T[], B: T[]): DiffResult<T>[] {
+export default function diff<T>(A: T[], B: T[]): Array<DiffResult<T>> {
+ const prefixCommon = createCommon(A, B);
+ const suffixCommon = createCommon(
+ A.slice(prefixCommon.length),
+ B.slice(prefixCommon.length),
+ true
+ ).reverse();
+ A = suffixCommon.length
+ ? A.slice(prefixCommon.length, -suffixCommon.length)
+ : A.slice(prefixCommon.length);
+ B = suffixCommon.length
+ ? B.slice(prefixCommon.length, -suffixCommon.length)
+ : B.slice(prefixCommon.length);
+ const swapped = B.length > A.length;
+ [A, B] = swapped ? [B, A] : [A, B];
+ const M = A.length;
+ const N = B.length;
+ if (!M && !N && !suffixCommon.length && !prefixCommon.length) return [];
+ if (!N) {
+ return [
+ ...prefixCommon.map(c => ({ type: "common" as DiffType, value: c })),
+ ...A.map(a => ({
+ type: (swapped ? "added" : "removed") as DiffType,
+ value: a
+ })),
+ ...suffixCommon.map(c => ({ type: "common" as DiffType, value: c }))
+ ];
+ }
+ const offset = N;
+ const delta = M - N;
+ const size = M + N + 1;
+ const fp = new Array(size).fill({ y: -1 });
+ // INFO: This buffer is used to save memory and improve performance.
+ // The first half is used to save route and last half is used to save diff type.
+ // This is because, when I kept new uint8array area to save type, performance worsened.
+ const routes = new Uint32Array((M * N + size + 1) * 2);
+ const diffTypesPtrOffset = routes.length / 2;
+ let ptr = 0;
+ let p = -1;
+
function backTrace<T>(
A: T[],
B: T[],
current: FarthestPoint,
swapped: boolean
- ) {
+ ): Array<{
+ type: DiffType;
+ value: T;
+ }> {
const M = A.length;
const N = B.length;
const result = [];
@@ -74,8 +116,7 @@ export default function diff<T>(A: T[], B: T[]): DiffResult<T>[] {
slide: FarthestPoint,
down: FarthestPoint,
k: number,
- M: number,
- N: number
+ M: number
): FarthestPoint {
if (slide && slide.y === -1 && (down && down.y === -1))
return { y: 0, id: 0 };
@@ -102,14 +143,14 @@ export default function diff<T>(A: T[], B: T[]): DiffResult<T>[] {
k: number,
slide: FarthestPoint,
down: FarthestPoint,
- offset: number,
+ _offset: number,
A: T[],
B: T[]
- ) {
+ ): FarthestPoint {
const M = A.length;
const N = B.length;
- if (k < -N || M < k) return { y: -1 };
- const fp = createFP(slide, down, k, M, N);
+ if (k < -N || M < k) return { y: -1, id: -1 };
+ const fp = createFP(slide, down, k, M);
while (fp.y + k < M && fp.y < N && A[fp.y + k] === B[fp.y]) {
const prev = fp.id;
ptr++;
@@ -121,44 +162,6 @@ export default function diff<T>(A: T[], B: T[]): DiffResult<T>[] {
return fp;
}
- const prefixCommon = createCommon(A, B);
- const suffixCommon = createCommon(
- A.slice(prefixCommon.length),
- B.slice(prefixCommon.length),
- true
- ).reverse();
- A = suffixCommon.length
- ? A.slice(prefixCommon.length, -suffixCommon.length)
- : A.slice(prefixCommon.length);
- B = suffixCommon.length
- ? B.slice(prefixCommon.length, -suffixCommon.length)
- : B.slice(prefixCommon.length);
- const swapped = B.length > A.length;
- [A, B] = swapped ? [B, A] : [A, B];
- const M = A.length;
- const N = B.length;
- if (!M && !N && !suffixCommon.length && !prefixCommon.length) return [];
- if (!N) {
- return [
- ...prefixCommon.map(c => ({ type: "common" as DiffType, value: c })),
- ...A.map(a => ({
- type: (swapped ? "added" : "removed") as DiffType,
- value: a
- })),
- ...suffixCommon.map(c => ({ type: "common" as DiffType, value: c }))
- ];
- }
- const offset = N;
- const delta = M - N;
- const size = M + N + 1;
- const fp = new Array(size).fill({ y: -1 });
- // INFO: This buffer is used to save memory and improve performance.
- // The first half is used to save route and last half is used to save diff type.
- // This is because, when I kept new uint8array area to save type, performance worsened.
- const routes = new Uint32Array((M * N + size + 1) * 2);
- const diffTypesPtrOffset = routes.length / 2;
- let ptr = 0;
- let p = -1;
while (fp[delta + offset].y < N) {
p = p + 1;
for (let k = -p; k < delta; ++k) {
diff --git a/testing/format.ts b/testing/format.ts
index 8434db1c2..9a8b02ac6 100644
--- a/testing/format.ts
+++ b/testing/format.ts
@@ -6,6 +6,7 @@
* LICENSE file in the root directory of this source tree.
*
*/
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type Refs = any[];
export type Optional<T> = { [K in keyof T]?: T[K] };
@@ -32,7 +33,7 @@ export interface Config {
}
export type Printer = (
- val: any,
+ val: unknown,
config: Config,
indentation: string,
depth: number,
@@ -66,12 +67,15 @@ interface BasicValueOptions {
* Explicitly comparing typeof constructor to function avoids undefined as name
* when mock identity-obj-proxy returns the key as the value for any key.
*/
-const getConstructorName = (val: new (...args: any[]) => any) =>
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+const getConstructorName = (val: new (...args: any[]) => any): string =>
(typeof val.constructor === "function" && val.constructor.name) || "Object";
/* global window */
/** Is val is equal to global window object? Works even if it does not exist :) */
-const isWindow = (val: any) => typeof window !== "undefined" && val === window;
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+const isWindow = (val: any): val is Window =>
+ typeof window !== "undefined" && val === window;
const SYMBOL_REGEXP = /^Symbol\((.*)\)(.*)$/;
@@ -116,11 +120,12 @@ function printError(val: Error): string {
* data-types in JS.
*/
function printBasicValue(
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
val: any,
{ printFunctionName, escapeRegex, escapeString }: BasicValueOptions
): string | null {
if (val === true || val === false) {
- return "" + val;
+ return String(val);
}
if (val === undefined) {
return "undefined";
@@ -136,9 +141,9 @@ function printBasicValue(
}
if (typeOf === "string") {
if (escapeString) {
- return '"' + val.replace(/"|\\/g, "\\$&") + '"';
+ return `"${val.replace(/"|\\/g, "\\$&")}"`;
}
- return '"' + val + '"';
+ return `"${val}"`;
}
if (typeOf === "function") {
return printFunction(val, printFunctionName);
@@ -185,95 +190,8 @@ function printBasicValue(
return null;
}
-/**
- * Handles more complex objects ( such as objects with circular references.
- * maps and sets etc )
- */
-function printComplexValue(
- val: any,
- config: Config,
- indentation: string,
- depth: number,
- refs: Refs,
- hasCalledToJSON?: boolean
-): string {
- if (refs.indexOf(val) !== -1) {
- return "[Circular]";
- }
- refs = refs.slice();
- refs.push(val);
-
- const hitMaxDepth = ++depth > config.maxDepth;
- const { min, callToJSON } = config;
-
- if (
- callToJSON &&
- !hitMaxDepth &&
- val.toJSON &&
- typeof val.toJSON === "function" &&
- !hasCalledToJSON
- ) {
- return printer(val.toJSON(), config, indentation, depth, refs, true);
- }
-
- const toStringed = toString.call(val);
- if (toStringed === "[object Arguments]") {
- return hitMaxDepth
- ? "[Arguments]"
- : (min ? "" : "Arguments ") +
- "[" +
- printListItems(val, config, indentation, depth, refs, printer) +
- "]";
- }
- if (isToStringedArrayType(toStringed)) {
- return hitMaxDepth
- ? "[" + val.constructor.name + "]"
- : (min ? "" : val.constructor.name + " ") +
- "[" +
- printListItems(val, config, indentation, depth, refs, printer) +
- "]";
- }
- if (toStringed === "[object Map]") {
- return hitMaxDepth
- ? "[Map]"
- : "Map {" +
- printIteratorEntries(
- val.entries(),
- config,
- indentation,
- depth,
- refs,
- printer,
- " => "
- ) +
- "}";
- }
- if (toStringed === "[object Set]") {
- return hitMaxDepth
- ? "[Set]"
- : "Set {" +
- printIteratorValues(
- val.values(),
- config,
- indentation,
- depth,
- refs,
- printer
- ) +
- "}";
- }
-
- // Avoid failure to serialize global window object in jsdom test environment.
- // For example, not even relevant if window is prop of React element.
- return hitMaxDepth || isWindow(val)
- ? "[" + getConstructorName(val) + "]"
- : (min ? "" : getConstructorName(val) + " ") +
- "{" +
- printObjectProperties(val, config, indentation, depth, refs, printer) +
- "}";
-}
-
function printer(
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
val: any,
config: Config,
indentation: string,
@@ -285,6 +203,7 @@ function printer(
if (basicResult !== null) {
return basicResult;
}
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
return printComplexValue(
val,
config,
@@ -295,30 +214,44 @@ function printer(
);
}
-const getConfig = (options: Options): Config => ({
- ...options,
- indent: options.min ? "" : createIndent(options.indent),
- spacingInner: options.min ? " " : "\n",
- spacingOuter: options.min ? "" : "\n"
-});
+/**
+ * Return items (for example, of an array)
+ * with spacing, indentation, and comma
+ * without surrounding punctuation (for example, brackets)
+ */
+function printListItems(
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ list: any,
+ config: Config,
+ indentation: string,
+ depth: number,
+ refs: Refs,
+ printer: Printer
+): string {
+ let result = "";
-function createIndent(indent: number): string {
- return new Array(indent + 1).join(" ");
-}
+ if (list.length) {
+ result += config.spacingOuter;
-const getKeysOfEnumerableProperties = (object: {}) => {
- const keys: Array<string | symbol> = Object.keys(object).sort();
+ const indentationNext = indentation + config.indent;
- if (Object.getOwnPropertySymbols) {
- Object.getOwnPropertySymbols(object).forEach(symbol => {
- if (Object.getOwnPropertyDescriptor(object, symbol)!.enumerable) {
- keys.push(symbol);
+ for (let i = 0; i < list.length; i++) {
+ result +=
+ indentationNext +
+ printer(list[i], config, indentationNext, depth, refs);
+
+ if (i < list.length - 1) {
+ result += "," + config.spacingInner;
+ } else if (!config.min) {
+ result += ",";
}
- });
+ }
+
+ result += config.spacingOuter + indentation;
}
- return keys;
-};
+ return result;
+}
/**
* Return entries (for example, of a map)
@@ -326,6 +259,7 @@ const getKeysOfEnumerableProperties = (object: {}) => {
* without surrounding punctuation (for example, braces)
*/
function printIteratorEntries(
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
iterator: any,
config: Config,
indentation: string,
@@ -384,6 +318,7 @@ function printIteratorEntries(
* without surrounding punctuation (braces or brackets)
*/
function printIteratorValues(
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
iterator: Iterator<any>,
config: Config,
indentation: string,
@@ -419,43 +354,19 @@ function printIteratorValues(
return result;
}
-/**
- * Return items (for example, of an array)
- * with spacing, indentation, and comma
- * without surrounding punctuation (for example, brackets)
- */
-function printListItems(
- list: any,
- config: Config,
- indentation: string,
- depth: number,
- refs: Refs,
- printer: Printer
-): string {
- let result = "";
-
- if (list.length) {
- result += config.spacingOuter;
-
- const indentationNext = indentation + config.indent;
-
- for (let i = 0; i < list.length; i++) {
- result +=
- indentationNext +
- printer(list[i], config, indentationNext, depth, refs);
+const getKeysOfEnumerableProperties = (object: {}): Array<string | symbol> => {
+ const keys: Array<string | symbol> = Object.keys(object).sort();
- if (i < list.length - 1) {
- result += "," + config.spacingInner;
- } else if (!config.min) {
- result += ",";
+ if (Object.getOwnPropertySymbols) {
+ Object.getOwnPropertySymbols(object).forEach(symbol => {
+ if (Object.getOwnPropertyDescriptor(object, symbol)!.enumerable) {
+ keys.push(symbol);
}
- }
-
- result += config.spacingOuter + indentation;
+ });
}
- return result;
-}
+ return keys;
+};
/**
* Return properties of an object
@@ -505,10 +416,112 @@ function printObjectProperties(
}
/**
+ * Handles more complex objects ( such as objects with circular references.
+ * maps and sets etc )
+ */
+function printComplexValue(
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ val: any,
+ config: Config,
+ indentation: string,
+ depth: number,
+ refs: Refs,
+ hasCalledToJSON?: boolean
+): string {
+ if (refs.indexOf(val) !== -1) {
+ return "[Circular]";
+ }
+ refs = refs.slice();
+ refs.push(val);
+
+ const hitMaxDepth = ++depth > config.maxDepth;
+ const { min, callToJSON } = config;
+
+ if (
+ callToJSON &&
+ !hitMaxDepth &&
+ val.toJSON &&
+ typeof val.toJSON === "function" &&
+ !hasCalledToJSON
+ ) {
+ return printer(val.toJSON(), config, indentation, depth, refs, true);
+ }
+
+ const toStringed = toString.call(val);
+ if (toStringed === "[object Arguments]") {
+ return hitMaxDepth
+ ? "[Arguments]"
+ : (min ? "" : "Arguments ") +
+ "[" +
+ printListItems(val, config, indentation, depth, refs, printer) +
+ "]";
+ }
+ if (isToStringedArrayType(toStringed)) {
+ return hitMaxDepth
+ ? `[${val.constructor.name}]`
+ : (min ? "" : `${val.constructor.name} `) +
+ "[" +
+ printListItems(val, config, indentation, depth, refs, printer) +
+ "]";
+ }
+ if (toStringed === "[object Map]") {
+ return hitMaxDepth
+ ? "[Map]"
+ : "Map {" +
+ printIteratorEntries(
+ val.entries(),
+ config,
+ indentation,
+ depth,
+ refs,
+ printer,
+ " => "
+ ) +
+ "}";
+ }
+ if (toStringed === "[object Set]") {
+ return hitMaxDepth
+ ? "[Set]"
+ : "Set {" +
+ printIteratorValues(
+ val.values(),
+ config,
+ indentation,
+ depth,
+ refs,
+ printer
+ ) +
+ "}";
+ }
+
+ // Avoid failure to serialize global window object in jsdom test environment.
+ // For example, not even relevant if window is prop of React element.
+ return hitMaxDepth || isWindow(val)
+ ? "[" + getConstructorName(val) + "]"
+ : (min ? "" : getConstructorName(val) + " ") +
+ "{" +
+ printObjectProperties(val, config, indentation, depth, refs, printer) +
+ "}";
+}
+
+// TODO this is better done with `.padStart()`
+function createIndent(indent: number): string {
+ return new Array(indent + 1).join(" ");
+}
+
+const getConfig = (options: Options): Config => ({
+ ...options,
+ indent: options.min ? "" : createIndent(options.indent),
+ spacingInner: options.min ? " " : "\n",
+ spacingOuter: options.min ? "" : "\n"
+});
+
+/**
* Returns a presentation string of your `val` object
* @param val any potential JavaScript object
* @param options Custom settings
*/
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function format(val: any, options: Optional<Options> = {}): string {
const opts = Object.keys(DEFAULT_OPTIONS).reduce(
(acc: Options, k: keyof Options) => {
diff --git a/testing/format_test.ts b/testing/format_test.ts
index 3e6da4480..7ca0235a5 100644
--- a/testing/format_test.ts
+++ b/testing/format_test.ts
@@ -9,17 +9,19 @@
import { test, assertEqual } from "./mod.ts";
import { format } from "./format.ts";
-function returnArguments(..._args: Array<unknown>) {
+// eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/no-explicit-any
+function returnArguments(...args: any[]): IArguments {
return arguments;
}
-function MyObject(value: unknown) {
+function MyObject(value: unknown): void {
// @ts-ignore
this.name = value;
}
class MyArray<T> extends Array<T> {}
+// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
const createVal = () => [
{
id: "8658c1d0-9eda-4a90-95e1-8001e8eb6036",
@@ -32,6 +34,7 @@ const createVal = () => [
}
];
+// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
const createExpected = () =>
[
"Array [",
@@ -58,7 +61,7 @@ test({
test({
name: "prints an empty array",
fn() {
- const val: any[] = [];
+ const val: unknown[] = [];
assertEqual(format(val), "Array []");
}
});
@@ -151,7 +154,7 @@ test({
name: "prints an anonymous callback function",
fn() {
let val;
- function f(cb: () => void) {
+ function f(cb: () => void): void {
val = cb;
}
// tslint:disable-next-line:no-empty
@@ -164,7 +167,7 @@ test({
name: "prints an anonymous assigned function",
fn() {
// tslint:disable-next-line:no-empty
- const val = () => {};
+ const val = (): void => {};
const formatted = format(val);
assertEqual(
formatted === "[Function anonymous]" || formatted === "[Function val]",
@@ -177,7 +180,7 @@ test({
name: "prints a named function",
fn() {
// tslint:disable-next-line:no-empty
- const val = function named() {};
+ const val = function named(): void {};
assertEqual(format(val), "[Function named]");
}
});
@@ -185,7 +188,7 @@ test({
test({
name: "prints a named generator function",
fn() {
- const val = function* generate() {
+ const val = function* generate(): IterableIterator<number> {
yield 1;
yield 2;
yield 3;
@@ -198,7 +201,7 @@ test({
name: "can customize function names",
fn() {
// tslint:disable-next-line:no-empty
- const val = function named() {};
+ const val = function named(): void {};
assertEqual(
format(val, {
printFunctionName: false
@@ -248,6 +251,7 @@ test({
test({
name: "prints a map with non-string keys",
fn() {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const val = new Map<any, any>([
[false, "boolean"],
["false", "string"],
@@ -373,6 +377,7 @@ test({
test({
name: "prints an object with properties and symbols",
fn() {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const val: any = {};
val[Symbol("symbol1")] = "value2";
val[Symbol("symbol2")] = "value3";
@@ -388,7 +393,7 @@ test({
name:
"prints an object without non-enumerable properties which have string key",
fn() {
- const val: any = {
+ const val = {
enumerable: true
};
const key = "non-enumerable";
@@ -404,7 +409,7 @@ test({
name:
"prints an object without non-enumerable properties which have symbol key",
fn() {
- const val: any = {
+ const val = {
enumerable: true
};
const key = Symbol("non-enumerable");
@@ -609,6 +614,7 @@ test({
test({
name: "prints circular references",
fn() {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const val: any = {};
val.prop = val;
assertEqual(format(val), 'Object {\n "prop": [Circular],\n}');
@@ -787,6 +793,7 @@ test({
name: "calls toJSON on Sets",
fn() {
const set = new Set([1]);
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
(set as any).toJSON = () => "map";
assertEqual(format(set), '"map"');
}
diff --git a/testing/mod.ts b/testing/mod.ts
index 41ae61bea..c1bf2015b 100644
--- a/testing/mod.ts
+++ b/testing/mod.ts
@@ -3,9 +3,37 @@
import { green, red } from "../colors/mod.ts";
interface Constructor {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
new (...args: any[]): any;
}
+export function equal(c: unknown, d: unknown): boolean {
+ const seen = new Map();
+ return (function compare(a: unknown, b: unknown) {
+ if (Object.is(a, b)) {
+ return true;
+ }
+ if (a && typeof a === "object" && b && typeof b === "object") {
+ if (seen.get(a) === b) {
+ return true;
+ }
+ if (Object.keys(a || {}).length !== Object.keys(b || {}).length) {
+ return false;
+ }
+ const merged = { ...a, ...b };
+ for (const key in merged) {
+ type Key = keyof typeof merged;
+ if (!compare(a && a[key as Key], b && b[key as Key])) {
+ return false;
+ }
+ }
+ seen.set(a, b);
+ return true;
+ }
+ return false;
+ })(c, d);
+}
+
const assertions = {
/** Make an assertion, if not `true`, then throw. */
assert(expr: boolean, msg = ""): void {
@@ -78,6 +106,7 @@ const assertions = {
* Forcefully throws a failed assertion
*/
fail(msg?: string): void {
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
assert(false, `Failed assertion${msg ? `: ${msg}` : "."}`);
},
@@ -163,33 +192,6 @@ export const assert = assertions.assert as Assert;
*/
export const assertEqual = assert.equal;
-export function equal(c: unknown, d: unknown): boolean {
- const seen = new Map();
- return (function compare(a: unknown, b: unknown) {
- if (Object.is(a, b)) {
- return true;
- }
- if (a && typeof a === "object" && b && typeof b === "object") {
- if (seen.get(a) === b) {
- return true;
- }
- if (Object.keys(a || {}).length !== Object.keys(b || {}).length) {
- return false;
- }
- const merged = { ...a, ...b };
- for (const key in merged) {
- type Key = keyof typeof merged;
- if (!compare(a && a[key as Key], b && b[key as Key])) {
- return false;
- }
- }
- seen.set(a, b);
- return true;
- }
- return false;
- })(c, d);
-}
-
export type TestFunction = () => void | Promise<void>;
export interface TestDefinition {
@@ -203,14 +205,20 @@ let filterRegExp: RegExp | null;
const tests: TestDefinition[] = [];
let filtered = 0;
-const ignored = 0;
-const measured = 0;
// Must be called before any test() that needs to be filtered.
export function setFilter(s: string): void {
filterRegExp = new RegExp(s, "i");
}
+function filter(name: string): boolean {
+ if (filterRegExp) {
+ return filterRegExp.test(name);
+ } else {
+ return true;
+ }
+}
+
export function test(t: TestDefinition | TestFunction): void {
const fn: TestFunction = typeof t === "function" ? t : t.fn;
const name: string = t.name;
@@ -225,21 +233,8 @@ export function test(t: TestDefinition | TestFunction): void {
}
}
-function filter(name: string): boolean {
- if (filterRegExp) {
- return filterRegExp.test(name);
- } else {
- return true;
- }
-}
-
-function red_failed() {
- return red("FAILED");
-}
-
-function green_ok() {
- return green("ok");
-}
+const RED_FAILED = red("FAILED");
+const GREEN_OK = green("ok");
interface TestStats {
filtered: number;
@@ -261,7 +256,7 @@ interface TestResults {
cases: Map<number, TestResult>;
}
-function createTestResults(tests: Array<TestDefinition>): TestResults {
+function createTestResults(tests: TestDefinition[]): TestResults {
return tests.reduce(
(acc: TestResults, { name }: TestDefinition, i: number): TestResults => {
acc.keys.set(name, i);
@@ -274,10 +269,10 @@ function createTestResults(tests: Array<TestDefinition>): TestResults {
function report(result: TestResult): void {
if (result.ok) {
- console.log(`test ${result.name} ... ${green_ok()}`);
+ console.log(`test ${result.name} ... ${GREEN_OK}`);
} else if (result.error) {
console.error(
- `test ${result.name} ... ${red_failed()}\n${result.error.stack}`
+ `test ${result.name} ... ${RED_FAILED}\n${result.error.stack}`
);
} else {
console.log(`test ${result.name} ... unresolved`);
@@ -302,7 +297,7 @@ function printResults(
}
// Attempting to match the output of Rust's test runner.
console.log(
- `\ntest result: ${stats.failed ? red_failed() : green_ok()}. ` +
+ `\ntest result: ${stats.failed ? RED_FAILED : GREEN_OK}. ` +
`${stats.passed} passed; ${stats.failed} failed; ` +
`${stats.ignored} ignored; ${stats.measured} measured; ` +
`${stats.filtered} filtered out\n`
@@ -342,7 +337,7 @@ async function createTestCase(
function initTestCases(
stats: TestStats,
results: TestResults,
- tests: Array<TestDefinition>
+ tests: TestDefinition[]
): Array<Promise<void>> {
return tests.map(createTestCase.bind(null, stats, results));
}
@@ -350,7 +345,7 @@ function initTestCases(
async function runTestsParallel(
stats: TestStats,
results: TestResults,
- tests: Array<TestDefinition>
+ tests: TestDefinition[]
): Promise<void> {
try {
await Promise.all(initTestCases(stats, results, tests));
@@ -362,7 +357,7 @@ async function runTestsParallel(
async function runTestsSerial(
stats: TestStats,
- tests: Array<TestDefinition>
+ tests: TestDefinition[]
): Promise<void> {
for (const { fn, name } of tests) {
// See https://github.com/denoland/deno/pull/1452
@@ -371,10 +366,10 @@ async function runTestsSerial(
try {
await fn();
stats.passed++;
- console.log("...", green_ok());
+ console.log("...", GREEN_OK);
console.groupEnd();
} catch (err) {
- console.log("...", red_failed());
+ console.log("...", RED_FAILED);
console.groupEnd();
console.error(err.stack);
stats.failed++;
diff --git a/testing/pretty.ts b/testing/pretty.ts
index aa90f2469..b27b3ccd7 100644
--- a/testing/pretty.ts
+++ b/testing/pretty.ts
@@ -15,7 +15,7 @@ function createStr(v: unknown): string {
}
}
-function createColor(diffType: DiffType) {
+function createColor(diffType: DiffType): (s: string) => string {
switch (diffType) {
case "added":
return (s: string) => green(bold(s));
@@ -26,7 +26,7 @@ function createColor(diffType: DiffType) {
}
}
-function createSign(diffType: DiffType) {
+function createSign(diffType: DiffType): string {
switch (diffType) {
case "added":
return "+ ";
@@ -37,7 +37,7 @@ function createSign(diffType: DiffType) {
}
}
-function buildMessage(diffResult: ReadonlyArray<DiffResult<string>>) {
+function buildMessage(diffResult: ReadonlyArray<DiffResult<string>>): string[] {
const messages = [];
messages.push("");
messages.push("");
@@ -55,7 +55,7 @@ function buildMessage(diffResult: ReadonlyArray<DiffResult<string>>) {
return messages;
}
-export function assertEqual(actual: unknown, expected: unknown) {
+export function assertEqual(actual: unknown, expected: unknown): void {
if (equal(actual, expected)) {
return;
}
diff --git a/testing/pretty_test.ts b/testing/pretty_test.ts
index f3b087aff..89b35c088 100644
--- a/testing/pretty_test.ts
+++ b/testing/pretty_test.ts
@@ -4,7 +4,7 @@ import { test, assert } from "./mod.ts";
import { red, green, white, gray, bold } from "../colors/mod.ts";
import { assertEqual } from "./pretty.ts";
-const createHeader = () => [
+const createHeader = (): string[] => [
"",
"",
` ${gray(bold("[Diff]"))} ${red(bold("Left"))} / ${green(bold("Right"))}`,
@@ -12,8 +12,8 @@ const createHeader = () => [
""
];
-const added = (s: string) => green(bold(s));
-const removed = (s: string) => red(bold(s));
+const added: (s: string) => string = (s: string): string => green(bold(s));
+const removed: (s: string) => string = (s: string): string => red(bold(s));
test({
name: "pass case",
diff --git a/testing/test.ts b/testing/test.ts
index 0d79c2218..7182a5783 100644
--- a/testing/test.ts
+++ b/testing/test.ts
@@ -35,8 +35,6 @@ test(function testingAssertEqual() {
});
test(function testingAssertFail() {
- let didThrow = false;
-
assert.throws(assert.fail, Error, "Failed assertion.");
assert.throws(
() => {
diff --git a/textproto/mod.ts b/textproto/mod.ts
index ee7647296..28eac4609 100644
--- a/textproto/mod.ts
+++ b/textproto/mod.ts
@@ -22,6 +22,17 @@ export class ProtocolError extends Error {
}
}
+export function append(a: Uint8Array, b: Uint8Array): Uint8Array {
+ if (a == null) {
+ return b;
+ } else {
+ const output = new Uint8Array(a.length + b.length);
+ output.set(a, 0);
+ output.set(b, a.length);
+ return output;
+ }
+}
+
export class TextProtoReader {
constructor(readonly r: BufReader) {}
@@ -137,14 +148,3 @@ export class TextProtoReader {
return [line, null];
}
}
-
-export function append(a: Uint8Array, b: Uint8Array): Uint8Array {
- if (a == null) {
- return b;
- } else {
- const output = new Uint8Array(a.length + b.length);
- output.set(a, 0);
- output.set(b, a.length);
- return output;
- }
-}
diff --git a/textproto/test.ts b/textproto/test.ts
index 0f8bee227..b6a4c93c9 100644
--- a/textproto/test.ts
+++ b/textproto/test.ts
@@ -92,7 +92,7 @@ test(async function textprotoAppend() {
test(async function textprotoReadEmpty() {
let r = reader("");
- let [m, err] = await r.readMIMEHeader();
+ let [, err] = await r.readMIMEHeader();
// Should not crash!
assertEqual(err, "EOF");
});
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 000000000..5a8dca33d
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,15 @@
+{
+ "compilerOptions": {
+ "allowJs": true,
+ "baseUrl": ".",
+ "module": "esnext",
+ "moduleResolution": "node",
+ "noEmit": true,
+ "noLib": true,
+ "pretty": true,
+ "resolveJsonModule": true,
+ "strict": true,
+ "target": "esnext"
+ },
+ "include": ["./**/*.ts"]
+}