Skip to content

Commit

Permalink
fix: #362 - SyntaxList.insertChildText(...) would throw when not inse…
Browse files Browse the repository at this point in the history
…rting to the child syntax list.
  • Loading branch information
dsherret committed Jul 14, 2018
1 parent 869980e commit 738fb47
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 45 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
},
"dependencies": {
"@dsherret/to-absolute-glob": "^2.0.2",
"code-block-writer": "^7.2.0",
"code-block-writer": "^7.2.1",
"fs-extra": "^6.0.1",
"glob-parent": "^3.1.0",
"globby": "^8.0.1",
Expand Down
50 changes: 18 additions & 32 deletions src/compiler/common/SyntaxList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,42 +7,19 @@ import { Node } from "./Node";
export class SyntaxList extends Node<ts.SyntaxList> {
/**
* Adds text at the end of the current children.
* @param text - Text to insert.
* @param textOrWriterFunction - Text to add or function that provides a writer to write with.
* @returns The children that were added.
*/
addChildText(text: string): Node[];
/**
* Adds text at the end of the current children.
* @param writer - Write the text using the provided writer.
* @returns The children that were added.
*/
addChildText(writer: WriterFunction): Node[];
/**
* @internal
*/
addChildText(textOrWriterFunction: string | WriterFunction): Node[];
addChildText(textOrWriterFunction: string | WriterFunction) {
return this.insertChildText(this.getChildCount(), textOrWriterFunction);
}

/**
* Inserts text at the specified child index.
* @param index - Child index to insert at.
* @param text - Text to insert.
* @returns The children that were inserted.
*/
insertChildText(index: number, text: string): Node[];
/**
* Inserts text at the specified child index.
* @param index - Child index to insert at.
* @param writer - Write the text using the provided writer.
* @param textOrWriterFunction - Text to insert or function that provides a writer to write with.
* @returns The children that were inserted.
*/
insertChildText(index: number, writer: WriterFunction): Node[];
/**
* @internal
*/
insertChildText(index: number, textOrWriterFunction: string | WriterFunction): Node[];
insertChildText(index: number, textOrWriterFunction: string | WriterFunction) {
// get index
const initialChildCount = this.getChildCount();
Expand All @@ -51,20 +28,29 @@ export class SyntaxList extends Node<ts.SyntaxList> {
index = verifyAndGetIndex(index, initialChildCount);

// get text
let insertText = getTextFromStringOrWriter(parent.getWriterWithChildIndentation(), textOrWriterFunction);
const isInline = this !== parent.getChildSyntaxList();
let insertText = getTextFromStringOrWriter(isInline ? parent.getWriterWithQueuedChildIndentation() : parent.getWriterWithChildIndentation(), textOrWriterFunction);

if (insertText.length === 0)
return [];

if (index === 0 && TypeGuards.isSourceFile(parent)) {
if (!StringUtils.endsWith(insertText, newLineKind))
insertText += newLineKind;
if (isInline) {
if (index === 0)
insertText += " ";
else
insertText = " " + insertText;
}
else {
if (index === 0 && TypeGuards.isSourceFile(parent)) {
if (!StringUtils.endsWith(insertText, newLineKind))
insertText += newLineKind;
}
else
insertText = newLineKind + insertText;
}
else
insertText = newLineKind + insertText;

// insert
const insertPos = getInsertPosFromIndex(index, parent, this.getChildren());
const insertPos = getInsertPosFromIndex(index, this, this.getChildren());
insertIntoParentTextRange({
insertPos,
newText: insertText,
Expand Down
23 changes: 14 additions & 9 deletions src/manipulation/helpers/getInsertPosFromIndex.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Node } from "../../compiler";
import { Node, SyntaxList } from "../../compiler";
import { Chars } from "../../constants";
import { SyntaxKind } from "../../typescript";
import { TypeGuards } from "../../utils";
Expand All @@ -7,22 +7,27 @@ import { getPosAtStartOfLineOrNonWhitespace } from "../textSeek";
/**
* Gets the insert pos from an index.
*/
export function getInsertPosFromIndex(index: number, parent: Node, children: Node[]) {
export function getInsertPosFromIndex(index: number, syntaxList: SyntaxList, children: Node[]) {
if (index === 0) {
const parent = syntaxList.getParentOrThrow();
if (TypeGuards.isSourceFile(parent))
return parent.getFullText()[0] === Chars.BOM ? 1 : 0;
else if (TypeGuards.isCaseClause(parent) || TypeGuards.isDefaultClause(parent)) {
const block = parent.getFirstChildIfKind(SyntaxKind.Block);
const colonToken = parent.getFirstChildByKindOrThrow(SyntaxKind.ColonToken);
return colonToken.getEnd();
}
else {
const parentContainer = getParentContainer(parent);
const openBraceToken = parentContainer.getFirstChildByKindOrThrow(SyntaxKind.OpenBraceToken);
return openBraceToken.getEnd();
}
}

return children[index - 1].getEnd();
const isInline = syntaxList !== parent.getChildSyntaxList();
if (isInline)
return syntaxList.getStart();

const parentContainer = getParentContainer(parent);
const openBraceToken = parentContainer.getFirstChildByKindOrThrow(SyntaxKind.OpenBraceToken);
return openBraceToken.getEnd();
}
else
return children[index - 1].getEnd();
}

export function getEndPosFromIndex(index: number, parent: Node, children: Node[], fullText: string) {
Expand Down
2 changes: 1 addition & 1 deletion src/manipulation/manipulations/insertion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ export interface InsertIntoBracesOrSourceFileOptions<TStructure> {
export function insertIntoBracesOrSourceFile<TStructure = {}>(opts: InsertIntoBracesOrSourceFileOptions<TStructure>) {
const {parent, index, children} = opts;
const fullText = parent.sourceFile.getFullText();
const insertPos = getInsertPosFromIndex(index, parent, children);
const insertPos = getInsertPosFromIndex(index, parent.getChildSyntaxListOrThrow(), children);
const endPos = getEndPosFromIndex(index, parent, children, fullText);
const replacingLength = endPos - insertPos;
const newText = getNewText();
Expand Down
37 changes: 35 additions & 2 deletions src/tests/compiler/common/syntaxListTests.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,52 @@
import { expect } from "chai";
import { Node, SyntaxList } from "../../../compiler";
import { SyntaxKind } from "../../../typescript";
import { getInfoFromText } from "../testHelpers";

describe(nameof(SyntaxList), () => {
describe(nameof<SyntaxList>(s => s.insertChildText), () => {
// most of these tests are in StatementedNode
it("should add a class member", () => {
it("should insert a class member", () => {
const {sourceFile, firstChild} = getInfoFromText("class MyClass {\n}\n");
firstChild.getChildSyntaxListOrThrow().addChildText(writer => {
firstChild.getChildSyntaxListOrThrow().insertChildText(0, writer => {
writer.write("get myNumber()").block(() => {
writer.writeLine("return 5;");
});
});
expect(sourceFile.getFullText()).to.equal("class MyClass {\n get myNumber() {\n return 5;\n }\n}\n");
});

it("should insert inline at the start", () => {
const { sourceFile, firstChild } = getInfoFromText(`abstract class MyClass {}`);
const syntaxList = firstChild.getFirstChildByKindOrThrow(SyntaxKind.SyntaxList);
syntaxList.insertChildText(0, "export");

expect(sourceFile.getFullText()).to.equal(`export abstract class MyClass {}`);
});

it("should insert inline in the middle", () => {
const { sourceFile, firstChild } = getInfoFromText(`export declare class MyClass {}`);
const syntaxList = firstChild.getFirstChildByKindOrThrow(SyntaxKind.SyntaxList);
syntaxList.insertChildText(1, "abstract");

expect(sourceFile.getFullText()).to.equal(`export abstract declare class MyClass {}`);
});

it("should insert inline at the end", () => {
const { sourceFile, firstChild } = getInfoFromText(`export class MyClass {}`);
const syntaxList = firstChild.getFirstChildByKindOrThrow(SyntaxKind.SyntaxList);
syntaxList.insertChildText(1, "abstract");

expect(sourceFile.getFullText()).to.equal(`export abstract class MyClass {}`);
});

it("should indent on next line in case someone adds a newline", () => {
const { sourceFile, firstChild } = getInfoFromText(`export class MyClass {}`);
const syntaxList = firstChild.getFirstChildByKindOrThrow(SyntaxKind.SyntaxList);
syntaxList.insertChildText(1, "\nabstract");

expect(sourceFile.getFullText()).to.equal(`export \n abstract class MyClass {}`);
});
});

describe(nameof<SyntaxList>(s => s.addChildText), () => {
Expand Down
4 changes: 4 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,10 @@ code-block-writer@^7.2.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/code-block-writer/-/code-block-writer-7.2.0.tgz#17a57b080e64898a82e3045df7a472baec9f220e"

code-block-writer@^7.2.1:
version "7.2.1"
resolved "https://registry.yarnpkg.com/code-block-writer/-/code-block-writer-7.2.1.tgz#c03073518fdb98d4d1a5bb46dcd60137958b5a3a"

code-point-at@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
Expand Down

0 comments on commit 738fb47

Please sign in to comment.