Skip to content

Commit

Permalink
Merge pull request #1498 from nemnandor/master
Browse files Browse the repository at this point in the history
fix: Referencer, Name conflicts, Mapped unions, etc.
  • Loading branch information
WoH authored Nov 10, 2023
2 parents 19f6463 + c1eea73 commit 0afe154
Show file tree
Hide file tree
Showing 7 changed files with 4,548 additions and 517 deletions.
20 changes: 12 additions & 8 deletions packages/cli/src/metadataGeneration/exceptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export class GenerateMetadataError extends Error {
}

export class GenerateMetaDataWarning {
constructor(private message: string, private node: Node | TypeNode, private onlyCurrent = false) {}
constructor(private message: string, private node: Node | TypeNode, private onlyCurrent = false) { }

toString() {
return `Warning: ${this.message}\n${prettyLocationOfNode(this.node)}\n${prettyTroubleCause(this.node, this.onlyCurrent)}`;
Expand All @@ -20,19 +20,23 @@ export class GenerateMetaDataWarning {

export function prettyLocationOfNode(node: Node | TypeNode) {
const sourceFile = node.getSourceFile();
const token = node.getFirstToken() || node.parent.getFirstToken();
const start = token ? `:${sourceFile.getLineAndCharacterOfPosition(token.getStart()).line + 1}` : '';
const end = token ? `:${sourceFile.getLineAndCharacterOfPosition(token.getEnd()).line + 1}` : '';
const normalizedPath = normalize(`${sourceFile.fileName}${start}${end}`);
return `At: ${normalizedPath}.`;
if (sourceFile) {
const token = node.getFirstToken() || node.parent.getFirstToken();
const start = token ? `:${sourceFile.getLineAndCharacterOfPosition(token.getStart()).line + 1}` : '';
const end = token ? `:${sourceFile.getLineAndCharacterOfPosition(token.getEnd()).line + 1}` : '';
const normalizedPath = normalize(`${sourceFile.fileName}${start}${end}`);
return `At: ${normalizedPath}.`;
} else {
return `At unknown position...`;
}
}

export function prettyTroubleCause(node: Node | TypeNode, onlyCurrent = false) {
let name: string;
if (onlyCurrent || !node.parent) {
name = node.pos !== -1 ? node.getText() : (node as any).name.text;
name = node.pos !== -1 ? node.getText() : ((node as any).name?.text || '<unknown name>');
} else {
name = node.parent.pos !== -1 ? node.parent.getText() : (node as any).parent.name.text;
name = node.parent.pos !== -1 ? node.parent.getText() : ((node as any).parent.name?.text || '<unknown name>');
}
return `This was caused by '${name}'`;
}
35 changes: 26 additions & 9 deletions packages/cli/src/metadataGeneration/metadataGenerator.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import { Config, Tsoa } from '@tsoa/runtime';
import { minimatch } from 'minimatch';
import { createProgram, forEachChild, isClassDeclaration, type ClassDeclaration, type CompilerOptions, type Program, type TypeChecker } from 'typescript';
import { getDecorators } from '../utils/decoratorUtils';
import { importClassesFromDirectories } from '../utils/importClassesFromDirectories';
import { ControllerGenerator } from './controllerGenerator';
import { GenerateMetadataError } from './exceptions';
import { Config, Tsoa } from '@tsoa/runtime';
import { TypeResolver } from './typeResolver';
import { getDecorators } from '../utils/decoratorUtils';
import { type TypeChecker, type Program, type ClassDeclaration, type CompilerOptions, createProgram, forEachChild, isClassDeclaration } from 'typescript';

export class MetadataGenerator {
public readonly controllerNodes = new Array<ClassDeclaration>();
public readonly typeChecker: TypeChecker;
private readonly program: Program;
private referenceTypeMap: Tsoa.ReferenceTypeMap = {};
private circularDependencyResolvers = new Array<(referenceTypes: Tsoa.ReferenceTypeMap) => void>();
private modelDefinitionPosMap: { [name: string]: Array<{ fileName: string; pos: number }> } = {};
private expressionOrigNameMap: Record<string, string> = {};

constructor(
entryFile: string,
Expand All @@ -35,7 +36,6 @@ export class MetadataGenerator {

this.checkForMethodSignatureDuplicates(controllers);
this.checkForPathParamSignatureDuplicates(controllers);
this.circularDependencyResolvers.forEach(c => c(this.referenceTypeMap));

return {
controllers,
Expand Down Expand Up @@ -214,17 +214,34 @@ export class MetadataGenerator {

public AddReferenceType(referenceType: Tsoa.ReferenceType) {
if (!referenceType.refName) {
return;
throw new Error('no reference type name found');
}
this.referenceTypeMap[decodeURIComponent(referenceType.refName)] = referenceType;
this.referenceTypeMap[referenceType.refName] = referenceType;
}

public GetReferenceType(refName: string) {
return this.referenceTypeMap[refName];
}

public OnFinish(callback: (referenceTypes: Tsoa.ReferenceTypeMap) => void) {
this.circularDependencyResolvers.push(callback);
public CheckModelUnicity(refName: string, positions: Array<{ fileName: string; pos: number }>) {
if (!this.modelDefinitionPosMap[refName]) {
this.modelDefinitionPosMap[refName] = positions;
} else {
const origPositions = this.modelDefinitionPosMap[refName];
if (!(origPositions.length === positions.length && positions.every(pos => origPositions.find(origPos => pos.pos === origPos.pos && pos.fileName === origPos.fileName)))) {
throw new Error(`Found 2 different model definitions for model ${refName}: orig: ${JSON.stringify(origPositions)}, act: ${JSON.stringify(positions)}`);
}
}
}

public CheckExpressionUnicity(formattedRefName: string, refName: string) {
if (!this.expressionOrigNameMap[formattedRefName]) {
this.expressionOrigNameMap[formattedRefName] = refName;
} else {
if (this.expressionOrigNameMap[formattedRefName] !== refName) {
throw new Error(`Found 2 different type expressions for formatted name "${formattedRefName}": orig: "${this.expressionOrigNameMap[formattedRefName]}", act: "${refName}"`);
}
}
}

private buildControllers() {
Expand Down
Loading

0 comments on commit 0afe154

Please sign in to comment.