diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 00000000..d41fa1af --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,15 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "type": "npm", + "script": "tslint", + "group": "build", + "problemMatcher": [ + "$tslint5" + ] + } + ] +} \ No newline at end of file diff --git a/src/CompressedJSON.ts b/src/CompressedJSON.ts index 23968920..877a4289 100644 --- a/src/CompressedJSON.ts +++ b/src/CompressedJSON.ts @@ -285,7 +285,7 @@ export class CompressedJSON { if (defined(this._ctx).currentNumberIsDouble === undefined) { throw "Number ended but not started"; } - const numberTag = defined(this._ctx).currentNumberIsDouble ? Tag.Double : Tag.Integer; + const numberTag = defined(this._ctx).currentNumberIsDouble !== undefined ? Tag.Double : Tag.Integer; this.popContext(); this.commitValue(makeValue(numberTag, 0)); }; diff --git a/src/ConvenienceRenderer.ts b/src/ConvenienceRenderer.ts index f0a29f03..403d110b 100644 --- a/src/ConvenienceRenderer.ts +++ b/src/ConvenienceRenderer.ts @@ -105,7 +105,7 @@ export abstract class ConvenienceRenderer extends Renderer { } protected unionNeedsName(u: UnionType): boolean { - return !nullableFromUnion(u); + return nullableFromUnion(u) === null; } protected setUpNaming(): Namespace[] { @@ -368,7 +368,7 @@ export abstract class ConvenienceRenderer extends Renderer { predicate?: (t: Type) => boolean ): void => { let topLevels: Collection; - if (predicate) { + if (predicate !== undefined) { topLevels = this.topLevels.filter(predicate); } else { topLevels = this.topLevels; diff --git a/src/DateTime.ts b/src/DateTime.ts index 0c7ad017..bae4b52e 100644 --- a/src/DateTime.ts +++ b/src/DateTime.ts @@ -33,7 +33,7 @@ const TIME = /^(\d\d):(\d\d):(\d\d)(\.\d+)?(z|[+-]\d\d:\d\d)?$/i; export function isDate(str: string) { // full-date from http://tools.ietf.org/html/rfc3339#section-5.6 const matches = str.match(DATE); - if (!matches) return false; + if (matches === null) return false; const month = +matches[2]; const day = +matches[3]; @@ -42,7 +42,7 @@ export function isDate(str: string) { export function isTime(str: string): boolean { const matches = str.match(TIME); - if (!matches) return false; + if (matches === null) return false; const hour = +matches[1]; const minute = +matches[2]; diff --git a/src/DeclarationIR.ts b/src/DeclarationIR.ts index 59351f5e..ee7900ee 100644 --- a/src/DeclarationIR.ts +++ b/src/DeclarationIR.ts @@ -172,7 +172,7 @@ export function declarationsForGraph( } const fullGraph = typeGraph.makeGraph(false, childrenOfType); - //fs.writeFileSync("graph.dot", fullGraph.makeDot(t => !(t instanceof PrimitiveType), nodeTitle)); + // fs.writeFileSync("graph.dot", fullGraph.makeDot(t => !(t instanceof PrimitiveType), nodeTitle)); processGraph(fullGraph, true); return new DeclarationIR(List(declarations), forwardedTypes); diff --git a/src/GraphQL.ts b/src/GraphQL.ts index b87d111b..d072457f 100644 --- a/src/GraphQL.ts +++ b/src/GraphQL.ts @@ -1,5 +1,7 @@ "use strict"; +/* tslint:disable:strict-boolean-expressions */ + import { List, Map, OrderedSet, OrderedMap } from "immutable"; import { removeNullFromUnion, UnionType } from "./Type"; diff --git a/src/Language/CPlusPlus.ts b/src/Language/CPlusPlus.ts index a68d383c..fff7044f 100644 --- a/src/Language/CPlusPlus.ts +++ b/src/Language/CPlusPlus.ts @@ -331,10 +331,10 @@ class CPlusPlusRenderer extends ConvenienceRenderer { }; private variantType = (u: UnionType, inJsonNamespace: boolean): Sourcelike => { - const [hasNull, nonNulls] = removeNullFromUnion(u); + const [maybeNull, nonNulls] = removeNullFromUnion(u); assert(nonNulls.size >= 2, "Variant not needed for less than two types."); const variant = this.cppTypeInOptional(nonNulls, inJsonNamespace, true); - if (!hasNull) { + if (maybeNull === null) { return variant; } return [optionalType, "<", variant, ">"]; @@ -379,7 +379,7 @@ class CPlusPlusRenderer extends ConvenienceRenderer { enumType => [this.ourQualifier(inJsonNamespace), this.nameForNamedType(enumType)], unionType => { const nullable = nullableFromUnion(unionType); - if (!nullable) return [this.ourQualifier(inJsonNamespace), this.nameForNamedType(unionType)]; + if (nullable === null) return [this.ourQualifier(inJsonNamespace), this.nameForNamedType(unionType)]; return [optionalType, "<", this.cppType(nullable, false, inJsonNamespace, withIssues), ">"]; } ); @@ -401,8 +401,8 @@ class CPlusPlusRenderer extends ConvenienceRenderer { () => { this.forEachClassProperty(c, "none", (name, json, t) => { if (t instanceof UnionType) { - const [hasNull, nonNulls] = removeNullFromUnion(t); - if (hasNull) { + const [maybeNull, nonNulls] = removeNullFromUnion(t); + if (maybeNull !== null) { this.emitLine( "_x.", name, @@ -590,7 +590,11 @@ class CPlusPlusRenderer extends ConvenienceRenderer { } this.forEachDeclaration("interposing", decl => this.emitDeclaration(decl)); if (this._justTypes) return; - this.forEachTopLevel("leading", this.emitTopLevelTypedef, t => !this.namedTypeToNameForTopLevel(t)); + this.forEachTopLevel( + "leading", + this.emitTopLevelTypedef, + t => this.namedTypeToNameForTopLevel(t) === undefined + ); this.emitMultiline(` inline json get_untyped(const json &j, const char *property) { if (j.find(property) != j.end()) { diff --git a/src/Language/CSharp.ts b/src/Language/CSharp.ts index 32077c44..30409199 100644 --- a/src/Language/CSharp.ts +++ b/src/Language/CSharp.ts @@ -164,7 +164,7 @@ class CSharpRenderer extends ConvenienceRenderer { } protected unionNeedsName(u: UnionType): boolean { - return !nullableFromUnion(u); + return nullableFromUnion(u) === null; } protected namedTypeToNameForTopLevel(type: Type): Type | undefined { @@ -210,7 +210,7 @@ class CSharpRenderer extends ConvenienceRenderer { enumType => this.nameForNamedType(enumType), unionType => { const nullable = nullableFromUnion(unionType); - if (nullable) return this.nullableCSType(nullable); + if (nullable !== null) return this.nullableCSType(nullable); return this.nameForNamedType(unionType); }, { @@ -299,7 +299,7 @@ class CSharpRenderer extends ConvenienceRenderer { let partial: string; let typeKind: string; const definedType = this.namedTypeToNameForTopLevel(t); - if (definedType) { + if (definedType !== undefined) { partial = "partial "; typeKind = definedType instanceof ClassType ? "class" : "struct"; } else { @@ -378,7 +378,7 @@ class CSharpRenderer extends ConvenienceRenderer { const emitDeserializer = (tokenType: string, kind: TypeKind): void => { const t = u.findMember(kind); - if (!t) return; + if (t === undefined) return; tokenCase(tokenType); this.indent(() => emitDeserializeType(t)); @@ -386,9 +386,9 @@ class CSharpRenderer extends ConvenienceRenderer { const emitDoubleDeserializer = (): void => { const t = u.findMember("double"); - if (!t) return; + if (t === undefined) return; - if (!u.findMember("integer")) tokenCase("Integer"); + if (u.findMember("integer") === undefined) tokenCase("Integer"); tokenCase("Float"); this.indent(() => emitDeserializeType(t)); }; @@ -438,7 +438,7 @@ class CSharpRenderer extends ConvenienceRenderer { this.ensureBlankLine(); this.emitLine("switch (reader.TokenType)"); this.emitBlock(() => { - if (hasNull) emitNullDeserializer(); + if (hasNull !== null) emitNullDeserializer(); emitDeserializer("Integer", "integer"); emitDoubleDeserializer(); emitDeserializer("Boolean", "bool"); @@ -459,7 +459,7 @@ class CSharpRenderer extends ConvenienceRenderer { this.emitLine("return;"); }); }); - if (hasNull) { + if (hasNull !== null) { this.emitLine("writer.WriteNull();"); } else { this.emitLine('throw new Exception("Union must not be null");'); diff --git a/src/Language/Elm.ts b/src/Language/Elm.ts index d84ae780..e2dca438 100644 --- a/src/Language/Elm.ts +++ b/src/Language/Elm.ts @@ -134,7 +134,7 @@ function requiredOrOptional(t: Type): RequiredOrOptional { if (t.kind === "null") { return optional(" ()"); } - if (t instanceof UnionType && nullableFromUnion(t)) { + if (t instanceof UnionType && nullableFromUnion(t) !== null) { return optional(" Nothing"); } return { reqOrOpt: "Jpipe.required", fallback: "" }; @@ -175,7 +175,7 @@ class ElmRenderer extends ConvenienceRenderer { protected topLevelDependencyNames(t: Type, topLevelName: Name): DependencyName[] { const encoder = new DependencyName(lowerNamingFunction, lookup => `${lookup(topLevelName)}_to_string`); let decoder: DependencyName | undefined = undefined; - if (!this.namedTypeToNameForTopLevel(t)) { + if (this.namedTypeToNameForTopLevel(t) === undefined) { decoder = new DependencyName(lowerNamingFunction, lookup => lookup(topLevelName)); } this._topLevelDependents = this._topLevelDependents.set(topLevelName, { encoder, decoder }); @@ -252,7 +252,7 @@ class ElmRenderer extends ConvenienceRenderer { enumType => singleWord(this.nameForNamedType(enumType)), unionType => { const nullable = nullableFromUnion(unionType); - if (nullable) return multiWord("Maybe", parenIfNeeded(this.elmType(nullable, withIssues))); + if (nullable !== null) return multiWord("Maybe", parenIfNeeded(this.elmType(nullable, withIssues))); return singleWord(this.nameForNamedType(unionType)); } ); @@ -282,7 +282,8 @@ class ElmRenderer extends ConvenienceRenderer { enumType => singleWord(this.decoderNameForNamedType(enumType)), unionType => { const nullable = nullableFromUnion(unionType); - if (nullable) return multiWord("Jdec.nullable", parenIfNeeded(this.decoderNameForType(nullable))); + if (nullable !== null) + return multiWord("Jdec.nullable", parenIfNeeded(this.decoderNameForType(nullable))); return singleWord(this.decoderNameForNamedType(unionType)); } ); @@ -309,7 +310,8 @@ class ElmRenderer extends ConvenienceRenderer { enumType => singleWord(this.encoderNameForNamedType(enumType)), unionType => { const nullable = nullableFromUnion(unionType); - if (nullable) return multiWord("makeNullableEncoder", parenIfNeeded(this.encoderNameForType(nullable))); + if (nullable !== null) + return multiWord("makeNullableEncoder", parenIfNeeded(this.encoderNameForType(nullable))); return singleWord(this.encoderNameForNamedType(unionType)); } ); @@ -364,7 +366,7 @@ class ElmRenderer extends ConvenienceRenderer { private emitTopLevelFunctions = (t: Type, topLevelName: Name): void => { const { encoder, decoder } = defined(this._topLevelDependents.get(topLevelName)); - if (!this.namedTypeToNameForTopLevel(t)) { + if (this.namedTypeToNameForTopLevel(t) === undefined) { this.emitLine(defined(decoder), " : Jdec.Decoder ", topLevelName); this.emitLine(defined(decoder), " = ", this.decoderNameForType(t).source); this.ensureBlankLine(); @@ -564,7 +566,7 @@ import Dict exposing (Dict, map, toList)`); this.forEachTopLevel( "leading-and-interposing", this.emitTopLevelDefinition, - t => !this.namedTypeToNameForTopLevel(t) + t => this.namedTypeToNameForTopLevel(t) === undefined ); this.forEachNamedType( "leading-and-interposing", diff --git a/src/Language/Golang.ts b/src/Language/Golang.ts index 7430b3ce..a443886e 100644 --- a/src/Language/Golang.ts +++ b/src/Language/Golang.ts @@ -159,7 +159,7 @@ class GoRenderer extends ConvenienceRenderer { enumType => this.nameForNamedType(enumType), unionType => { const nullable = nullableFromUnion(unionType); - if (nullable) return this.nullableGoType(nullable, withIssues); + if (nullable !== null) return this.nullableGoType(nullable, withIssues); return this.nameForNamedType(unionType); } ); @@ -167,7 +167,7 @@ class GoRenderer extends ConvenienceRenderer { private emitTopLevel = (t: Type, name: Name): void => { const unmarshalName = defined(this._topLevelUnmarshalNames.get(name)); - if (!this.namedTypeToNameForTopLevel(t)) { + if (this.namedTypeToNameForTopLevel(t) === undefined) { this.emitLine("type ", name, " ", this.goType(t)); } @@ -207,7 +207,7 @@ class GoRenderer extends ConvenienceRenderer { private emitUnion = (u: UnionType, unionName: Name): void => { const [hasNull, nonNulls] = removeNullFromUnion(u); - const isNullableArg = hasNull ? "true" : "false"; + const isNullableArg = hasNull !== null ? "true" : "false"; const ifMember: ( kind: TypeKind, @@ -215,7 +215,7 @@ class GoRenderer extends ConvenienceRenderer { f: (t: Type, fieldName: Name, goType: Sourcelike) => T ) => T | U = (kind, ifNotMember, f) => { const maybeType = u.findMember(kind); - if (!maybeType) return ifNotMember; + if (maybeType === undefined) return ifNotMember; return f(maybeType, this.nameForUnionMember(u, maybeType), this.goType(maybeType)); }; @@ -311,7 +311,7 @@ class GoRenderer extends ConvenienceRenderer { this.forEachTopLevel( "leading-and-interposing", this.emitTopLevel, - t => !this._justTypes || !this.namedTypeToNameForTopLevel(t) + t => !this._justTypes || this.namedTypeToNameForTopLevel(t) === undefined ); this.forEachClass("leading-and-interposing", this.emitClass); this.forEachEnum("leading-and-interposing", this.emitEnum); diff --git a/src/Language/Java.ts b/src/Language/Java.ts index 6906d86d..110c89be 100644 --- a/src/Language/Java.ts +++ b/src/Language/Java.ts @@ -208,7 +208,7 @@ class JavaRenderer extends ConvenienceRenderer { } protected unionNeedsName(u: UnionType): boolean { - return !nullableFromUnion(u); + return nullableFromUnion(u) === null; } protected namedTypeToNameForTopLevel(type: Type): Type | undefined { @@ -289,7 +289,7 @@ class JavaRenderer extends ConvenienceRenderer { enumType => this.nameForNamedType(enumType), unionType => { const nullable = nullableFromUnion(unionType); - if (nullable) return this.javaType(true, nullable, withIssues); + if (nullable !== null) return this.javaType(true, nullable, withIssues); return this.nameForNamedType(unionType); } ); @@ -302,7 +302,7 @@ class JavaRenderer extends ConvenienceRenderer { return "Map"; } else if (t instanceof UnionType) { const nullable = nullableFromUnion(t); - if (nullable) return this.javaTypeWithoutGenerics(true, nullable); + if (nullable !== null) return this.javaTypeWithoutGenerics(true, nullable); return this.nameForNamedType(t); } else { return this.javaType(reference, t); @@ -366,7 +366,7 @@ class JavaRenderer extends ConvenienceRenderer { const emitDeserializer = (tokenTypes: string[], kind: TypeKind): void => { const t = u.findMember(kind); - if (!t) return; + if (t === undefined) return; for (const tokenType of tokenTypes) { tokenCase(tokenType); @@ -376,9 +376,9 @@ class JavaRenderer extends ConvenienceRenderer { const emitDoubleSerializer = (): void => { const t = u.findMember("double"); - if (!t) return; + if (t === undefined) return; - if (!u.findMember("integer")) tokenCase("VALUE_NUMBER_INT"); + if (u.findMember("integer") === undefined) tokenCase("VALUE_NUMBER_INT"); tokenCase("VALUE_NUMBER_FLOAT"); this.indent(() => emitDeserializeType(t)); }; @@ -412,7 +412,7 @@ class JavaRenderer extends ConvenienceRenderer { () => { this.emitLine(unionName, " value = new ", unionName, "();"); this.emitLine("switch (jsonParser.getCurrentToken()) {"); - if (maybeNull) emitNullDeserializer(); + if (maybeNull !== null) emitNullDeserializer(); emitDeserializer(["VALUE_NUMBER_INT"], "integer"); emitDoubleSerializer(); emitDeserializer(["VALUE_TRUE", "VALUE_FALSE"], "bool"); @@ -444,7 +444,7 @@ class JavaRenderer extends ConvenienceRenderer { this.emitLine("return;"); }); }); - if (maybeNull) { + if (maybeNull !== null) { this.emitLine("jsonGenerator.writeNull();"); } else { this.emitLine('throw new IOException("', unionName, ' must not be null");'); diff --git a/src/Language/SimpleTypes.ts b/src/Language/SimpleTypes.ts index f7ac00a1..7bed5570 100644 --- a/src/Language/SimpleTypes.ts +++ b/src/Language/SimpleTypes.ts @@ -127,7 +127,7 @@ class SimpleTypesRenderer extends ConvenienceRenderer { enumType => this.nameForNamedType(enumType), unionType => { const nullable = nullableFromUnion(unionType); - if (nullable) return ["Maybe<", this.sourceFor(nullable), ">"]; + if (nullable !== null) return ["Maybe<", this.sourceFor(nullable), ">"]; if (this.inlineUnions) { const children = unionType.children.map((c: Type) => this.sourceFor(c)); diff --git a/src/Language/Swift.ts b/src/Language/Swift.ts index 7f6e2861..103489a1 100644 --- a/src/Language/Swift.ts +++ b/src/Language/Swift.ts @@ -227,7 +227,7 @@ class SwiftRenderer extends ConvenienceRenderer { private readonly _useClasses: boolean, private readonly _dense: boolean, private readonly _version: Version, - private readonly _convenienceInitializers: Boolean + private readonly _convenienceInitializers: boolean ) { super(graph, leadingComments); } @@ -309,7 +309,7 @@ class SwiftRenderer extends ConvenienceRenderer { enumType => this.nameForNamedType(enumType), unionType => { const nullable = nullableFromUnion(unionType); - if (nullable) return [this.swiftType(nullable, withIssues), "?"]; + if (nullable !== null) return [this.swiftType(nullable, withIssues), "?"]; return this.nameForNamedType(unionType); } ); @@ -362,7 +362,7 @@ class SwiftRenderer extends ConvenienceRenderer { if (!this._justTypes) { protocols.push("Codable"); } - return protocols.length ? ": " + protocols.join(", ") : ""; + return protocols.length > 0 ? ": " + protocols.join(", ") : ""; }; getEnumPropertyGroups = (c: ClassType) => { @@ -415,7 +415,9 @@ class SwiftRenderer extends ConvenienceRenderer { }; this.forEachClassProperty(c, "none", (name, _, t) => { - lastType = lastType || t; + if (lastType === undefined) { + lastType = t; + } if (t.equals(lastType) && lastNames.length < MAX_SAMELINE_PROPERTIES) { lastNames.push(name); } else { @@ -567,7 +569,7 @@ var json: String? { this.forEachUnionMember(u, nonNulls, "none", null, (name, t) => { this.emitLine("case ", name, "(", this.swiftType(t), ")"); }); - if (maybeNull) { + if (maybeNull !== null) { this.emitLine("case ", this.nameForUnionMember(u, maybeNull)); } @@ -576,14 +578,14 @@ var json: String? { this.emitBlock("init(from decoder: Decoder) throws", () => { this.emitLine("let container = try decoder.singleValueContainer()"); const boolMember = u.findMember("bool"); - if (boolMember) renderUnionCase(boolMember); + if (boolMember !== undefined) renderUnionCase(boolMember); const integerMember = u.findMember("integer"); - if (integerMember) renderUnionCase(integerMember); + if (integerMember !== undefined) renderUnionCase(integerMember); nonNulls.forEach(t => { if (t.kind === "bool" || t.kind === "integer") return; renderUnionCase(t); }); - if (maybeNull) { + if (maybeNull !== null) { this.emitBlock("if container.decodeNil()", () => { this.emitLine("self = .", this.nameForUnionMember(u, maybeNull)); this.emitLine("return"); @@ -599,7 +601,7 @@ var json: String? { this.emitLine("case .", name, "(let x):"); this.indent(() => this.emitLine("try container.encode(x)")); }); - if (maybeNull) { + if (maybeNull !== null) { this.emitLine("case .", this.nameForUnionMember(u, maybeNull), ":"); this.indent(() => this.emitLine("try container.encodeNil()")); } @@ -909,7 +911,11 @@ class JSONAny: Codable { protected emitSourceStructure(): void { this.renderHeader(); - this.forEachTopLevel("leading", this.renderTopLevelAlias, t => !this.namedTypeToNameForTopLevel(t)); + this.forEachTopLevel( + "leading", + this.renderTopLevelAlias, + t => this.namedTypeToNameForTopLevel(t) === undefined + ); this.forEachNamedType( "leading-and-interposing", diff --git a/src/Language/TypeScript.ts b/src/Language/TypeScript.ts index fc1798e5..11adaded 100644 --- a/src/Language/TypeScript.ts +++ b/src/Language/TypeScript.ts @@ -170,7 +170,7 @@ class TypeScriptRenderer extends ConvenienceRenderer { mapType => ["{ [key: string]: ", this.sourceFor(mapType.values), " }"], enumType => this.nameForNamedType(enumType), unionType => { - if (this._inlineUnions || nullableFromUnion(unionType)) { + if (this._inlineUnions || nullableFromUnion(unionType) !== null) { const children = unionType.children.map(this.sourceFor); return intercalate(" | ", children).toArray(); } else { @@ -231,8 +231,11 @@ class TypeScriptRenderer extends ConvenienceRenderer { this.emitBlock(["export interface ", className], "", () => { const table: Sourcelike[][] = []; this.forEachClassProperty(c, "none", (name, _jsonName, t) => { - const nullable = t instanceof UnionType && nullableFromUnion(t); - table.push([[name, nullable ? "?" : "", ": "], [this.sourceFor(nullable || t), ";"]]); + const nullable = t instanceof UnionType ? nullableFromUnion(t) : null; + table.push([ + [name, nullable !== null ? "?" : "", ": "], + [this.sourceFor(nullable !== null ? nullable : t), ";"] + ]); }); this.emitTable(table); }); diff --git a/src/Naming.ts b/src/Naming.ts index 31f92aca..6a1424c3 100644 --- a/src/Naming.ts +++ b/src/Naming.ts @@ -24,7 +24,7 @@ export class Namespace { this.additionalForbidden = additionalForbidden; this._children = OrderedSet(); this._members = OrderedSet(); - if (parent) { + if (parent !== undefined) { this._parent = parent; parent.addChild(this); } @@ -60,7 +60,7 @@ export class Namespace { hashCode(): number { let hash = stringHash(this._name); - if (this._parent) { + if (this._parent !== undefined) { hash += this._parent.hashCode(); } return hash | 0; @@ -371,7 +371,7 @@ class NamingContext { return false; } }); - return !!conflicting; + return conflicting !== undefined; }; assign = (named: Name, namedNamespace: Namespace, name: string): void => { diff --git a/src/Renderer.ts b/src/Renderer.ts index fb42fe87..32f694bd 100644 --- a/src/Renderer.ts +++ b/src/Renderer.ts @@ -119,7 +119,7 @@ export abstract class Renderer { }; private changeIndent(offset: number): void { - if (!this._lastNewline) { + if (this._lastNewline === undefined) { return panic("Cannot change indent for the first line"); } this._lastNewline.indentationChange += offset; diff --git a/src/Source.ts b/src/Source.ts index a3a5e864..bf3c3cd7 100644 --- a/src/Source.ts +++ b/src/Source.ts @@ -6,7 +6,7 @@ import { List, Map, Range } from "immutable"; import { AnnotationData } from "./Annotation"; import { Name } from "./Naming"; -import { intercalate, defined, assertNever, panic, assert } from "./Support"; +import { intercalate, defined, assertNever, panic, assert, withDefault } from "./Support"; import { RenderResult } from "./Renderer"; export type Source = @@ -206,19 +206,17 @@ export function serializeRenderResult( indentNeeded = indent; break; case "sequence": - source.sequence.forEach((s: Source) => serializeToStringArray(s)); + source.sequence.forEach(s => serializeToStringArray(s)); break; case "table": const t = source.table; - const widths = t - .map((l: List) => l.map((s: Source) => sourceLineLength(s, names)).toList()) - .toList(); + const widths = t.map(l => l.map(s => sourceLineLength(s, names)).toList()).toList(); const numRows = t.size; if (numRows === 0) break; - const numColumns = defined(t.map((l: List) => l.size).max()); + const numColumns = defined(t.map(l => l.size).max()); if (numColumns === 0) break; const columnWidths = defined( - Range(0, numColumns).map((i: number) => widths.map((l: List) => l.get(i) || 0).max()) + Range(0, numColumns).map(i => widths.map(l => withDefault(l.get(i), 0)).max()) ); for (let y = 0; y < numRows; y++) { indentIfNeeded(); @@ -226,8 +224,8 @@ export function serializeRenderResult( const rowWidths = defined(widths.get(y)); for (let x = 0; x < numColumns; x++) { const colWidth = defined(columnWidths.get(x)); - const src = row.get(x) || { kind: "text", text: "" }; - const srcWidth = rowWidths.get(x) || 0; + const src = withDefault(row.get(x), { kind: "text", text: "" }); + const srcWidth = withDefault(rowWidths.get(x), 0); serializeToStringArray(src); if (x < numColumns - 1 && srcWidth < colWidth) { currentLine.push(_.repeat(" ", colWidth - srcWidth)); diff --git a/src/Strings.ts b/src/Strings.ts index acad9ba9..887cce42 100644 --- a/src/Strings.ts +++ b/src/Strings.ts @@ -49,7 +49,7 @@ export function utf16ConcatMap(mapper: (utf16Unit: number) => string): (s: strin let i = 0; while (i < s.length) { const cc = s.charCodeAt(i); - if (!charNoEscapeMap[cc]) { + if (charNoEscapeMap[cc] !== 1) { if (cs === null) cs = []; cs.push(s.substring(start, i)); @@ -90,7 +90,7 @@ export function utf32ConcatMap(mapper: (codePoint: number) => string): (s: strin let i = 0; while (i < s.length) { let cc = s.charCodeAt(i); - if (!charNoEscapeMap[cc]) { + if (charNoEscapeMap[cc] !== 1) { if (cs === null) cs = []; cs.push(s.substring(start, i)); diff --git a/src/Support.ts b/src/Support.ts index 8e2c26ce..0845a8c4 100644 --- a/src/Support.ts +++ b/src/Support.ts @@ -72,3 +72,10 @@ export function repeatedCall(n: number, producer: () => T): T[] { } return arr; } + +export function withDefault(x: T | null | undefined, theDefault: T): T { + if (x !== null && x !== undefined) { + return x; + } + return theDefault; +} diff --git a/src/TargetLanguage.ts b/src/TargetLanguage.ts index 15c9d9f8..f52869cf 100644 --- a/src/TargetLanguage.ts +++ b/src/TargetLanguage.ts @@ -81,10 +81,12 @@ export abstract class TargetLanguage { get stringTypeMapping(): StringTypeMapping { const partial = this.partialStringTypeMapping; + /* tslint:disable:strict-boolean-expressions */ return { date: partial.date || "string", time: partial.time || "string", dateTime: partial.dateTime || "string" }; + /* tslint:enable */ } } diff --git a/src/Type.ts b/src/Type.ts index 80ce9593..3c81aa97 100644 --- a/src/Type.ts +++ b/src/Type.ts @@ -1,7 +1,7 @@ "use strict"; import { OrderedSet, OrderedMap, Collection } from "immutable"; -import { defined, panic, assert } from "./Support"; +import { defined, panic, assert, assertNever } from "./Support"; import { TypeRef, TypeReconstituter } from "./TypeBuilder"; import { TypeNames } from "./TypeNames"; @@ -445,7 +445,7 @@ export function unionCasesEqual( export function removeNullFromUnion(t: UnionType): [PrimitiveType | null, OrderedSet] { const nullType = t.findMember("null"); - if (!nullType) { + if (nullType === undefined) { return [null, t.members]; } return [nullType as PrimitiveType, t.members.filterNot(isNull).toOrderedSet()]; @@ -463,7 +463,7 @@ export function removeNullFromType(t: Type): [PrimitiveType | null, OrderedSet): SeparatedNamed export function directlyReachableSingleNamedType(type: Type): Type | undefined { const definedTypes = type.directlyReachableTypes(t => { - if ((!(t instanceof UnionType) && isNamedType(t)) || (t instanceof UnionType && !nullableFromUnion(t))) { + if ( + (!(t instanceof UnionType) && isNamedType(t)) || + (t instanceof UnionType && nullableFromUnion(t) === null) + ) { return OrderedSet([t]); } return null; @@ -549,8 +552,8 @@ export function matchTypeExhaustive( time: timeType, "date-time": dateTimeType }[t.kind]; - if (f) return f(t); - return panic(`Unsupported PrimitiveType: ${t.kind}`); + if (f !== undefined) return f(t); + return assertNever(f); } else if (t instanceof ArrayType) return arrayType(t); else if (t instanceof ClassType) return classType(t); else if (t instanceof MapType) return mapType(t); @@ -581,6 +584,7 @@ export function matchType( if (stringTypeMatchers === undefined) { stringTypeMatchers = {}; } + /* tslint:disable:strict-boolean-expressions */ return matchTypeExhaustive( t, typeNotSupported, @@ -599,6 +603,7 @@ export function matchType( stringTypeMatchers.timeType || typeNotSupported, stringTypeMatchers.dateTimeType || typeNotSupported ); + /* tslint:enable */ } export function matchCompoundType( diff --git a/src/TypeBuilder.ts b/src/TypeBuilder.ts index da97449e..e685753a 100644 --- a/src/TypeBuilder.ts +++ b/src/TypeBuilder.ts @@ -207,7 +207,7 @@ export abstract class TypeBuilder { return this.getUnionType(typeNames, OrderedSet([tref, nullType])); } const [maybeNull, nonNulls] = removeNullFromUnion(t); - if (maybeNull) return tref; + if (maybeNull !== null) return tref; return this.getUnionType(typeNames, nonNulls.map(nn => nn.typeRef).add(nullType)); }; diff --git a/src/TypeGraph.ts b/src/TypeGraph.ts index ac015e91..16a6ba74 100644 --- a/src/TypeGraph.ts +++ b/src/TypeGraph.ts @@ -173,7 +173,7 @@ export class TypeGraph { types = types.push(t); } - const children = childrenOfType ? childrenOfType(t) : t.children; + const children = childrenOfType !== undefined ? childrenOfType(t) : t.children; children.forEach(addFromType); if (!topDown && required) { diff --git a/src/cli.ts b/src/cli.ts index 5aeba60a..2a4a2b84 100755 --- a/src/cli.ts +++ b/src/cli.ts @@ -24,7 +24,7 @@ import { urlsFromURLGrammar } from "./URLGrammar"; import { Annotation } from "./Source"; import { IssueAnnotationData } from "./Annotation"; import { Readable } from "stream"; -import { panic, assert, defined } from "./Support"; +import { panic, assert, defined, withDefault } from "./Support"; import { introspectServer } from "./GraphQLIntrospection"; import { getStream } from "./get-stream/index"; @@ -178,7 +178,7 @@ async function samplesFromDirectory(dataDir: string): Promise { function inferLang(options: Partial): string { // Output file extension determines the language if language is undefined - if (options.out) { + if (options.out !== undefined) { let extension = path.extname(options.out); if (extension === "") { throw new Error("Please specify a language (--lang) or an output file extension."); @@ -191,14 +191,14 @@ function inferLang(options: Partial): string { function inferTopLevel(options: Partial): string { // Output file name determines the top-level if undefined - if (options.out) { + if (options.out !== undefined) { let extension = path.extname(options.out); let without = path.basename(options.out).replace(extension, ""); return without; } // Source determines the top-level if undefined - if (options.src && options.src.length === 1) { + if (options.src !== undefined && options.src.length === 1) { let src = options.src[0]; let extension = path.extname(src); let without = path.basename(src).replace(extension, ""); @@ -218,9 +218,10 @@ function inferOptions(opts: Partial): CLIOptions { srcLang = "graphql"; } else { assert(srcLang !== "graphql", "Please specify a GraphQL schema with --graphql-schema or --graphql-introspect"); - srcLang = srcLang || "json"; + srcLang = withDefault(srcLang, "json"); } + /* tslint:disable:strict-boolean-expressions */ return { src: opts.src || [], srcLang: srcLang, @@ -241,6 +242,7 @@ function inferOptions(opts: Partial): CLIOptions { graphqlServerHeader: opts.graphqlServerHeader, template: opts.template }; + /* tslint:enable */ } const optionDefinitions: OptionDefinition[] = [ @@ -439,7 +441,7 @@ function parseOptions(definitions: OptionDefinition[], argv: string[], partial: definitions.forEach(o => { if (!(o.name in opts)) return; const v = opts[o.name]; - if (o.renderer) options.rendererOptions[o.name] = v; + if (o.renderer !== undefined) options.rendererOptions[o.name] = v; else { const k = _.lowerFirst( o.name @@ -502,7 +504,7 @@ function splitAndWriteJava(dir: string, str: string) { } async function getSources(options: CLIOptions): Promise { - if (options.srcUrls) { + if (options.srcUrls !== undefined) { const json = JSON.parse(fs.readFileSync(options.srcUrls, "utf8")); const jsonMap = urlsFromURLGrammar(json); const topLevels = Object.getOwnPropertyNames(jsonMap); @@ -555,7 +557,10 @@ export async function main(args: string[] | Partial) { let schemaString: string | undefined = undefined; let wroteSchemaToFile = false; if (options.graphqlIntrospect !== undefined) { - schemaString = await introspectServer(options.graphqlIntrospect, options.graphqlServerHeader || []); + schemaString = await introspectServer( + options.graphqlIntrospect, + withDefault(options.graphqlServerHeader, []) + ); if (options.graphqlSchema !== undefined) { fs.writeFileSync(options.graphqlSchema, schemaString); wroteSchemaToFile = true; @@ -629,7 +634,7 @@ export async function main(args: string[] | Partial) { const { lines, annotations } = await run.run(); const output = lines.join("\n"); - if (options.out) { + if (options.out !== undefined) { if (options.lang === "java") { splitAndWriteJava(path.dirname(options.out), output); } else { diff --git a/src/index.ts b/src/index.ts index 436d0eea..2996c5f7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -29,7 +29,7 @@ const stringToStream = require("string-to-stream"); export function getTargetLanguage(name: string): TargetLanguage { const language = targetLanguages.languageNamed(name); - if (language) { + if (language !== undefined) { return language; } throw new Error(`'${name}' is not yet supported as an output language.`); diff --git a/tslint.json b/tslint.json index b6e8e4c3..82e63e4d 100644 --- a/tslint.json +++ b/tslint.json @@ -46,12 +46,12 @@ "no-string-literal": true, "no-switch-case-fall-through": true, "no-trailing-whitespace": false, - "no-unsafe-any": true, + "no-unsafe-any": false, "no-unused-expression": true, - "no-use-before-declare": true, + "no-use-before-declare": false, "no-unused-variable": true, "no-var-keyword": true, - "no-void-expression": true, + "no-void-expression": false, "strict-boolean-expressions": true, "one-line": [ true,