Skip to content

Commit

Permalink
feat: #527 - Adding namespace with quotes defaults to ambient module.
Browse files Browse the repository at this point in the history
Previously this would use the namespace keyword, which would cause multiple child nodes to be inserted into the AST rather than one namespace declaration. That would lead to surprises.
  • Loading branch information
dsherret committed Feb 2, 2019
1 parent be63ddd commit fadeeea
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { CodeBlockWriter } from "../../codeBlockWriter";
import { NamespaceDeclarationKind } from "../../compiler";
import * as errors from "../../errors";
import { StructurePrinterFactory } from "../../factories";
import { ArrayUtils } from "../../utils";
import { ArrayUtils, StringUtils, ObjectUtils, setValueIfUndefined } from "../../utils";
import { NamespaceDeclarationStructure } from "../../structures";
import { FactoryStructurePrinter } from "../FactoryStructurePrinter";
import { BlankLineFormattingStructuresPrinter } from "../formatting";
Expand All @@ -18,6 +19,8 @@ export class NamespaceDeclarationStructurePrinter extends FactoryStructurePrinte
}

printText(writer: CodeBlockWriter, structure: NamespaceDeclarationStructure) {
structure = this.validateAndGetStructure(structure);

this.factory.forJSDoc().printDocs(writer, structure.docs);
this.factory.forModifierableNode().printText(writer, structure);
if (structure.declarationKind == null || structure.declarationKind !== NamespaceDeclarationKind.Global)
Expand All @@ -41,4 +44,19 @@ export class NamespaceDeclarationStructurePrinter extends FactoryStructurePrinte
if (!ArrayUtils.isNullOrEmpty(structures))
writer.conditionalBlankLine(!writer.isAtStartOfFirstLineOfBlock());
}

private validateAndGetStructure(structure: NamespaceDeclarationStructure) {
const name = structure.name.trim();
if (!StringUtils.startsWith(name, "'") && !StringUtils.startsWith(name, `"`))
return structure;

if (structure.declarationKind === NamespaceDeclarationKind.Namespace)
throw new errors.InvalidOperationError(`Cannot print a namespace with quotes for namespace with name ${structure.name}. ` +
`Use ${nameof.full(NamespaceDeclarationKind.Module)} instead.`);

structure = ObjectUtils.clone(structure);
setValueIfUndefined(structure, "hasDeclareKeyword", true);
setValueIfUndefined(structure, "declarationKind", NamespaceDeclarationKind.Module);
return structure;
}
}
20 changes: 20 additions & 0 deletions src/tests/compiler/ast/statement/statementedNode/namespaceTests.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { expect } from "chai";
import { NamespaceDeclaration, StatementedNode, Node, NamespaceDeclarationKind } from "../../../../../compiler";
import * as errors from "../../../../../errors";
import { NamespaceDeclarationStructure } from "../../../../../structures";
import { getInfoFromText } from "../../../testHelpers";

Expand Down Expand Up @@ -104,6 +105,25 @@ describe(nameof(StatementedNode), () => {
declarationKind: NamespaceDeclarationKind.Global // priority
}], "global {\n}\n");
});

it("should default to ambient module when specifying single quotes", () => {
doTest("", 0, [{ name: "'Identifier'" }], "declare module 'Identifier' {\n}\n");
});

it("should default to ambient module when specifying double quotes", () => {
doTest("", 0, [{ name: `"Identifier"` }], `declare module "Identifier" {\n}\n`);
});

it("should default to ambient module when specifying quotes, but respect hasDeclareKeyword", () => {
doTest("", 0, [{ name: `"Identifier"`, hasDeclareKeyword: false }], `module "Identifier" {\n}\n`);
});

it("should throw when specifying quotes and a namespace declaration kind of namespace", () => {
const { sourceFile } = getInfoFromText("");
expect(() => sourceFile.insertNamespaces(0, [{ name: `"Identifier"`, declarationKind: NamespaceDeclarationKind.Namespace }]))
.to.throw(errors.InvalidOperationError, `Cannot print a namespace with quotes for namespace with name "Identifier". ` +
`Use NamespaceDeclarationKind.Module instead.`);
});
});

describe(nameof<StatementedNode>(n => n.insertNamespace), () => {
Expand Down

0 comments on commit fadeeea

Please sign in to comment.