Skip to content

Commit

Permalink
feat: #710 - Manipulation error now throws a custom error object.
Browse files Browse the repository at this point in the history
  • Loading branch information
dsherret committed Nov 16, 2019
1 parent e6b8dad commit a8881d7
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 22 deletions.
4 changes: 2 additions & 2 deletions packages/common/lib/ts-morph-common.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ export declare namespace errors {
}
/** Thrown when there is a problem with a provided argument. */
class ArgumentError extends BaseError {
constructor(argName: string, message: string, prototype?: any);
constructor(argName: string, message: string);
}
/** Thrown when an argument is null or whitespace. */
class ArgumentNullOrWhitespaceError extends ArgumentError {
Expand All @@ -343,7 +343,7 @@ export declare namespace errors {
/** Thrown when a file or directory path was not found. */
class PathNotFoundError extends BaseError {
readonly path: string;
constructor(path: string, prefix?: string, prototype?: any);
constructor(path: string, prefix?: string);
readonly code: "ENOENT";
}
/** Thrown when a directory was not found. */
Expand Down
29 changes: 13 additions & 16 deletions packages/common/src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,48 +6,45 @@ export namespace errors {
/** Base error class. */
export abstract class BaseError extends Error {
/** @private */
constructor(public readonly message: string, prototype: any) {
constructor(public readonly message: string) {
super(message);

this.message = message;

// workaround for extending error to work in ES5 :(
Object.setPrototypeOf(this, prototype);
}
}

/** Thrown when there is a problem with a provided argument. */
export class ArgumentError extends BaseError {
constructor(argName: string, message: string, prototype: any = ArgumentError.prototype) {
super(`Argument Error (${argName}): ${message}`, prototype);
constructor(argName: string, message: string) {
super(`Argument Error (${argName}): ${message}`);
}
}

/** Thrown when an argument is null or whitespace. */
export class ArgumentNullOrWhitespaceError extends ArgumentError {
constructor(argName: string) {
super(argName, "Cannot be null or whitespace.", ArgumentNullOrWhitespaceError.prototype);
super(argName, "Cannot be null or whitespace.");
}
}

/** Thrown when an argument is out of range. */
export class ArgumentOutOfRangeError extends ArgumentError {
constructor(argName: string, value: number, range: [number, number]) {
super(argName, `Range is ${range[0]} to ${range[1]}, but ${value} was provided.`, ArgumentOutOfRangeError.prototype);
super(argName, `Range is ${range[0]} to ${range[1]}, but ${value} was provided.`);
}
}

/** Thrown when an argument does not match an expected type. */
export class ArgumentTypeError extends ArgumentError {
constructor(argName: string, expectedType: string, actualType: string) {
super(argName, `Expected type '${expectedType}', but was '${actualType}'.`, ArgumentTypeError.prototype);
super(argName, `Expected type '${expectedType}', but was '${actualType}'.`);
}
}

/** Thrown when a file or directory path was not found. */
export class PathNotFoundError extends BaseError {
constructor(public readonly path: string, prefix = "Path", prototype: any = PathNotFoundError.prototype) {
super(`${prefix} not found: ${path}`, prototype);
constructor(public readonly path: string, prefix = "Path") {
super(`${prefix} not found: ${path}`);
}

readonly code: "ENOENT" = "ENOENT";
Expand All @@ -56,35 +53,35 @@ export namespace errors {
/** Thrown when a directory was not found. */
export class DirectoryNotFoundError extends PathNotFoundError {
constructor(dirPath: string) {
super(dirPath, "Directory", DirectoryNotFoundError.prototype);
super(dirPath, "Directory");
}
}

/** Thrown when a file was not found. */
export class FileNotFoundError extends PathNotFoundError {
constructor(filePath: string) {
super(filePath, "File", FileNotFoundError.prototype);
super(filePath, "File");
}
}

/** Thrown when an action was taken that is not allowed. */
export class InvalidOperationError extends BaseError {
constructor(message: string) {
super(message, InvalidOperationError.prototype);
super(message);
}
}

/** Thrown when a certain behaviour or feature has not been implemented. */
export class NotImplementedError extends BaseError {
constructor(message = "Not implemented.") {
super(message, NotImplementedError.prototype);
super(message);
}
}

/** Thrown when an operation is not supported. */
export class NotSupportedError extends BaseError {
constructor(message: string) {
super(message, NotSupportedError.prototype);
super(message);
}
}

Expand Down
10 changes: 10 additions & 0 deletions packages/ts-morph/lib/ts-morph.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1977,6 +1977,16 @@ export declare class TypeGuards {
static isUpdateExpression(node: Node): node is UpdateExpression;
}

/**
* Occurs when there is a problem doing a manipulation.
*/
export declare class ManipulationError extends errors.InvalidOperationError {
readonly filePath: string;
readonly oldText: string;
readonly newText: string;
constructor(filePath: string, oldText: string, newText: string, errorMessage: string);
}

/**
* Functions for writing code.
*/
Expand Down
1 change: 1 addition & 0 deletions packages/ts-morph/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export { SourceFileReferencingNodes } from "./utils/references/SourceFileReferen
export { CompilerOptionsFromTsConfigOptions, CompilerOptionsFromTsConfigResult,
getCompilerOptionsFromTsConfig } from "./utils/tsconfig/getCompilerOptionsFromTsConfig";
export { TypeGuards } from "./utils";
export { ManipulationError } from "./manipulation";
import { Writers } from "./structurePrinters/Writers";
/** @deprecated Use `Writers`. */
const WriterFunctions = Writers;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { errors } from "@ts-morph/common";

/** Occurs when there is a problem doing a manipulation. */
export class ManipulationError extends errors.InvalidOperationError {
constructor(
public readonly filePath: string,
public readonly oldText: string,
public readonly newText: string,
errorMessage: string
) {
super(errorMessage);
}
}
19 changes: 15 additions & 4 deletions packages/ts-morph/src/manipulation/manipulations/doManipulation.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
/* barrel:ignore */
import { errors } from "@ts-morph/common";
import { SourceFile, Diagnostic } from "../../compiler";
import { Project, ProjectOptions } from "../../Project";
import { errors } from "@ts-morph/common";
import { NodeHandler } from "../nodeHandlers";
import { TextManipulator } from "../textManipulators";
import { ManipulationError } from "./ManipulationError";

export function doManipulation(sourceFile: SourceFile, textManipulator: TextManipulator, nodeHandler: NodeHandler, newFilePath?: string) {
sourceFile._firePreModified();
const newFileText = textManipulator.getNewText(sourceFile.getFullText());
const oldFileText = sourceFile.getFullText();
const newFileText = textManipulator.getNewText(oldFileText);
try {
const replacementSourceFile = sourceFile._context.compilerFactory.createCompilerSourceFileFromText(
newFilePath || sourceFile.getFilePath(),
Expand All @@ -24,14 +26,23 @@ export function doManipulation(sourceFile: SourceFile, textManipulator: TextMani
+ "Stack: " + err.stack;

if (diagnostics.length > 0) {
throw new errors.InvalidOperationError(
throwError(
"Manipulation error: " + "A syntax error was inserted." + "\n\n"
+ sourceFile._context.project.formatDiagnosticsWithColorAndContext(diagnostics, { newLineChar: "\n" })
+ "\n" + errorDetails
);
}

throw new errors.InvalidOperationError("Manipulation error: " + errorDetails);
throwError("Manipulation error: " + errorDetails);

function throwError(message: string): never {
throw new ManipulationError(
sourceFile.getFilePath(),
oldFileText,
newFileText,
message
);
}
}
}

Expand Down
1 change: 1 addition & 0 deletions packages/ts-morph/src/manipulation/manipulations/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from "./insertion";
export * from "./move";
export * from "./removal";
export * from "./replaction";
export * from "./ManipulationError";

0 comments on commit a8881d7

Please sign in to comment.