Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support symlinked packages #125

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ node_modules/
lib/
test/*.js
.idea
*.tgz
.vscode/
4 changes: 2 additions & 2 deletions src/transform-inline/transform-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ function transformDecorator(node: ts.Decorator, parameterType: ts.Type, paramete
if (
signature !== undefined
&& signature.declaration !== undefined
&& path.resolve(signature.declaration.getSourceFile().fileName) === path.resolve(path.join(__dirname, '..', '..', 'index.d.ts'))
&& VisitorUtils.getCanonicalPath(path.resolve(signature.declaration.getSourceFile().fileName), visitorContext) === path.resolve(path.join(__dirname, '..', '..', 'index.d.ts'))
&& node.expression.arguments.length <= 1
) {
const arrowFunction: ts.Expression = createArrowFunction(parameterType, parameterName, optional, visitorContext);
Expand Down Expand Up @@ -102,7 +102,7 @@ export function transformNode(node: ts.Node, visitorContext: PartialVisitorConte
if (
signature !== undefined
&& signature.declaration !== undefined
&& path.resolve(signature.declaration.getSourceFile().fileName) === path.resolve(path.join(__dirname, '..', '..', 'index.d.ts'))
&& VisitorUtils.getCanonicalPath(path.resolve(signature.declaration.getSourceFile().fileName), visitorContext) === path.resolve(path.join(__dirname, '..', '..', 'index.d.ts'))
&& node.typeArguments !== undefined
&& node.typeArguments.length === 1
) {
Expand Down
3 changes: 2 additions & 1 deletion src/transform-inline/transformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ export default function transformer(program: ts.Program, options?: { [Key: strin
emitDetailedErrors: getEmitDetailedErrors(options)
},
typeMapperStack: [],
previousTypeReference: null
previousTypeReference: null,
canonicalPaths: new Map()
};
return (context: ts.TransformationContext) => (file: ts.SourceFile) => transformNodeAndChildren(file, program, context, visitorContext);
}
Expand Down
1 change: 1 addition & 0 deletions src/transform-inline/visitor-context.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ export interface PartialVisitorContext {
options: Options;
typeMapperStack: Map<ts.Type, ts.Type>[];
previousTypeReference: ts.Type | null;
canonicalPaths: Map<string, string>;
}
10 changes: 9 additions & 1 deletion src/transform-inline/visitor-utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import * as ts from 'typescript';
import * as fs from 'fs';
import { ModifierFlags } from 'typescript';
import * as tsutils from 'tsutils/typeguard/3.0';
import { VisitorContext } from './visitor-context';
import { PartialVisitorContext, VisitorContext } from './visitor-context';
import { Reason } from '../../index';

/**
Expand Down Expand Up @@ -731,3 +732,10 @@ export function getIntrinsicName(type: ts.Type): string | undefined {
// Using internal TypeScript API, hacky.
return (type as { intrinsicName?: string }).intrinsicName;
}

export function getCanonicalPath(path: string, context: PartialVisitorContext): string {
if (!context.canonicalPaths.has(path)) {
context.canonicalPaths.set(path, fs.realpathSync(path));
}
return context.canonicalPaths.get(path)!;
}
152 changes: 152 additions & 0 deletions test-fixtures/issue-104.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AsyncMethods = void 0;
const index_1 = require("../index");
let AsyncMethods = class AsyncMethods {
asyncMethod(body) {
return __awaiter(this, void 0, void 0, function* () {
return true;
});
}
asyncMethodNoExplicitReturn(body) {
return __awaiter(this, void 0, void 0, function* () {
return true;
});
}
promiseReturnMethod(body) {
return Promise.resolve(true);
}
asyncOverride(body) {
return __awaiter(this, void 0, void 0, function* () {
return true;
});
}
promiseOrOtherReturnMethod(body) {
return Promise.resolve(true);
}
};
__decorate([
__param(0, index_1.AssertType(object => { var path = ["body"]; function _string(object) { ; if (typeof object !== "string")
return { message: "validation failed at " + path.join(".") + ": expected a string", path: path.slice(), reason: { type: "string" } };
else
return null; } function _0(object) { ; if (typeof object !== "object" || object === null || Array.isArray(object))
return { message: "validation failed at " + path.join(".") + ": expected an object", path: path.slice(), reason: { type: "object" } }; {
if ("test" in object) {
path.push("test");
var error = _string(object["test"]);
path.pop();
if (error)
return error;
}
else
return { message: "validation failed at " + path.join(".") + ": expected 'test' in object", path: path.slice(), reason: { type: "missing-property", property: "test" } };
} return null; } return _0(object); })),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", Promise)
], AsyncMethods.prototype, "asyncMethod", null);
__decorate([
__param(0, index_1.AssertType(object => { var path = ["body"]; function _string(object) { ; if (typeof object !== "string")
return { message: "validation failed at " + path.join(".") + ": expected a string", path: path.slice(), reason: { type: "string" } };
else
return null; } function _0(object) { ; if (typeof object !== "object" || object === null || Array.isArray(object))
return { message: "validation failed at " + path.join(".") + ": expected an object", path: path.slice(), reason: { type: "object" } }; {
if ("test" in object) {
path.push("test");
var error = _string(object["test"]);
path.pop();
if (error)
return error;
}
else
return { message: "validation failed at " + path.join(".") + ": expected 'test' in object", path: path.slice(), reason: { type: "missing-property", property: "test" } };
} return null; } return _0(object); })),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", Promise)
], AsyncMethods.prototype, "asyncMethodNoExplicitReturn", null);
__decorate([
__param(0, index_1.AssertType(object => { var path = ["body"]; function _string(object) { ; if (typeof object !== "string")
return { message: "validation failed at " + path.join(".") + ": expected a string", path: path.slice(), reason: { type: "string" } };
else
return null; } function _0(object) { ; if (typeof object !== "object" || object === null || Array.isArray(object))
return { message: "validation failed at " + path.join(".") + ": expected an object", path: path.slice(), reason: { type: "object" } }; {
if ("test" in object) {
path.push("test");
var error = _string(object["test"]);
path.pop();
if (error)
return error;
}
else
return { message: "validation failed at " + path.join(".") + ": expected 'test' in object", path: path.slice(), reason: { type: "missing-property", property: "test" } };
} return null; } return _0(object); })),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", Promise)
], AsyncMethods.prototype, "promiseReturnMethod", null);
__decorate([
__param(0, index_1.AssertType(object => { var path = ["body"]; function _string(object) { ; if (typeof object !== "string")
return { message: "validation failed at " + path.join(".") + ": expected a string", path: path.slice(), reason: { type: "string" } };
else
return null; } function _0(object) { ; if (typeof object !== "object" || object === null || Array.isArray(object))
return { message: "validation failed at " + path.join(".") + ": expected an object", path: path.slice(), reason: { type: "object" } }; {
if ("test" in object) {
path.push("test");
var error = _string(object["test"]);
path.pop();
if (error)
return error;
}
else
return { message: "validation failed at " + path.join(".") + ": expected 'test' in object", path: path.slice(), reason: { type: "missing-property", property: "test" } };
} return null; } return _0(object); }, { async: false })),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", Promise)
], AsyncMethods.prototype, "asyncOverride", null);
__decorate([
__param(0, index_1.AssertType(object => { var path = ["body"]; function _string(object) { ; if (typeof object !== "string")
return { message: "validation failed at " + path.join(".") + ": expected a string", path: path.slice(), reason: { type: "string" } };
else
return null; } function _0(object) { ; if (typeof object !== "object" || object === null || Array.isArray(object))
return { message: "validation failed at " + path.join(".") + ": expected an object", path: path.slice(), reason: { type: "object" } }; {
if ("test" in object) {
path.push("test");
var error = _string(object["test"]);
path.pop();
if (error)
return error;
}
else
return { message: "validation failed at " + path.join(".") + ": expected 'test' in object", path: path.slice(), reason: { type: "missing-property", property: "test" } };
} return null; } return _0(object); })),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", Object)
], AsyncMethods.prototype, "promiseOrOtherReturnMethod", null);
AsyncMethods = __decorate([
index_1.ValidateClass()
], AsyncMethods);
exports.AsyncMethods = AsyncMethods;
21 changes: 13 additions & 8 deletions test/issue-16.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ describe('visitor', () => {
emitDetailedErrors: 'auto'
},
typeMapperStack: [],
previousTypeReference: null
previousTypeReference: null,
canonicalPaths: new Map()
};

function visitNodeAndChildren(node: ts.Node) {
Expand All @@ -68,7 +69,8 @@ describe('visitor', () => {
emitDetailedErrors: 'auto'
},
typeMapperStack: [],
previousTypeReference: null
previousTypeReference: null,
canonicalPaths: new Map()
};

function visitNodeAndChildren(node: ts.Node) {
Expand Down Expand Up @@ -99,8 +101,9 @@ describe('visitor', () => {
emitDetailedErrors: 'auto'
},
typeMapperStack: [],
previousTypeReference: null
};
previousTypeReference: null,
canonicalPaths: new Map()
};

function visitNodeAndChildren(node: ts.Node) {
ts.forEachChild(transformNode(node, visitorContext), visitNodeAndChildren);
Expand Down Expand Up @@ -129,8 +132,9 @@ describe('visitor', () => {
emitDetailedErrors: 'auto'
},
typeMapperStack: [],
previousTypeReference: null
};
previousTypeReference: null,
canonicalPaths: new Map()
};

function visitNodeAndChildren(node: ts.Node) {
ts.forEachChild(transformNode(node, visitorContext), visitNodeAndChildren);
Expand Down Expand Up @@ -159,8 +163,9 @@ describe('visitor', () => {
emitDetailedErrors: 'auto'
},
typeMapperStack: [],
previousTypeReference: null
};
previousTypeReference: null,
canonicalPaths: new Map()
};

function visitNodeAndChildren(node: ts.Node) {
ts.forEachChild(transformNode(node, visitorContext), visitNodeAndChildren);
Expand Down
5 changes: 3 additions & 2 deletions test/issue-27.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ describe('visitor', () => {
emitDetailedErrors: 'auto'
},
typeMapperStack: [],
previousTypeReference: null
};
previousTypeReference: null,
canonicalPaths: new Map()
};

function visitNodeAndChildren(node: ts.Node) {
ts.forEachChild(transformNode(node, visitorContext), visitNodeAndChildren);
Expand Down
5 changes: 3 additions & 2 deletions test/issue-3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ describe('visitor', () => {
emitDetailedErrors: 'auto'
},
typeMapperStack: [],
previousTypeReference: null
};
previousTypeReference: null,
canonicalPaths: new Map()
};

function visitNodeAndChildren(node: ts.Node) {
ts.forEachChild(transformNode(node, visitorContext), visitNodeAndChildren);
Expand Down
3 changes: 2 additions & 1 deletion test/issue-31.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ function createVisitorContext(program: Program, optionsDict: PartialVisitorConte
compilerOptions: program.getCompilerOptions(),
options: optionsDict,
typeMapperStack: [],
previousTypeReference: null
previousTypeReference: null,
canonicalPaths: new Map()
};
}

Expand Down
10 changes: 6 additions & 4 deletions test/issue-50.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ describe('visitor', () => {
emitDetailedErrors: 'auto'
},
typeMapperStack: [],
previousTypeReference: null
};
previousTypeReference: null,
canonicalPaths: new Map()
};

function visitNodeAndChildren(node: ts.Node) {
ts.forEachChild(transformNode(node, visitorContext), visitNodeAndChildren);
Expand Down Expand Up @@ -70,8 +71,9 @@ describe('visitor', () => {
emitDetailedErrors: 'auto'
},
typeMapperStack: [],
previousTypeReference: null
};
previousTypeReference: null,
canonicalPaths: new Map()
};

function visitNodeAndChildren(node: ts.Node) {
ts.forEachChild(transformNode(node, visitorContext), visitNodeAndChildren);
Expand Down
15 changes: 9 additions & 6 deletions test/issue-52.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ describe('visitor', () => {
emitDetailedErrors: 'auto'
},
typeMapperStack: [],
previousTypeReference: null
};
previousTypeReference: null,
canonicalPaths: new Map()
};

function visitNodeAndChildren(node: ts.Node) {
ts.forEachChild(transformNode(node, visitorContext), visitNodeAndChildren);
Expand Down Expand Up @@ -70,8 +71,9 @@ describe('visitor', () => {
emitDetailedErrors: 'auto'
},
typeMapperStack: [],
previousTypeReference: null
};
previousTypeReference: null,
canonicalPaths: new Map()
};

function visitNodeAndChildren(node: ts.Node) {
ts.forEachChild(transformNode(node, visitorContext), visitNodeAndChildren);
Expand Down Expand Up @@ -100,8 +102,9 @@ describe('visitor', () => {
emitDetailedErrors: 'auto'
},
typeMapperStack: [],
previousTypeReference: null
};
previousTypeReference: null,
canonicalPaths: new Map()
};

function visitNodeAndChildren(node: ts.Node) {
ts.forEachChild(transformNode(node, visitorContext), visitNodeAndChildren);
Expand Down