Skip to content

Commit 432008c

Browse files
committed
feat: Support for TypeScript 4.3
1 parent ec17e83 commit 432008c

File tree

28 files changed

+326
-471
lines changed

28 files changed

+326
-471
lines changed

.prettierignore

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,3 @@ dist
55
package-lock.json
66
src/test/**/specs*.json
77
src/test/renderer/specs
8-
9-
# Temporarily ignored until Prettier 2.3
10-
examples/basic/src/classes.ts
11-
src/test/converter/class/class.ts

examples/basic/src/classes.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ class InternalClass<TTT extends keyof BaseClass> {
208208
* from BaseClass.
209209
*/
210210
export class SubClassA extends BaseClass implements PrintNameInterface {
211-
public name: string;
211+
public declare name: string;
212212

213213
/**
214214
* This is a simple interface function.
@@ -269,7 +269,7 @@ export class SubClassA extends BaseClass implements PrintNameInterface {
269269
* The constructor of the original class should be overwritten.
270270
*/
271271
export class SubClassB extends BaseClass {
272-
public name: string;
272+
public declare name: string;
273273

274274
constructor(name: string) {
275275
super(name);
@@ -323,4 +323,4 @@ export class GenericClass<T extends BaseClass> {
323323
export class NonGenericClass extends GenericClass<SubClassB> {}
324324

325325
// TS 4.2
326-
export type AbstractMe = abstract new () => NonGenericClass
326+
export type AbstractMe = abstract new () => NonGenericClass;

examples/basic/src/mixin.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,15 @@ export const Mixin2 = <T extends AnyConstructor<Mixin1Type & Base>>(base: T) =>
5656
class Mixin2 extends base {
5757
property2 = "init";
5858

59-
method2(arg: Mixin2): Mixin2[] {
60-
return [arg, this];
59+
method2(arg: Mixin2Type): Mixin2Type {
60+
return arg;
6161
}
6262
};
6363

6464
/**
6565
* The "instance type" of the Mixin2 using the interface notation (supports recursive type definition)
6666
*/
67-
export interface Mixin2 extends Mixin<typeof Mixin2> {}
67+
export interface Mixin2Type extends Mixin<typeof Mixin2> {}
6868

6969
/**
7070
* The "mixin function" of the Mixin3

package-lock.json

Lines changed: 147 additions & 125 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,29 +23,29 @@
2323
"handlebars": "^4.7.7",
2424
"lodash": "^4.17.21",
2525
"lunr": "^2.3.9",
26-
"marked": "^2.0.3",
26+
"marked": "^2.0.7",
2727
"minimatch": "^3.0.0",
2828
"progress": "^2.0.3",
2929
"shiki": "^0.9.3",
3030
"typedoc-default-themes": "^0.12.10"
3131
},
3232
"peerDependencies": {
33-
"typescript": "4.0.x || 4.1.x || 4.2.x"
33+
"typescript": "4.0.x || 4.1.x || 4.2.x || 4.3.x"
3434
},
3535
"devDependencies": {
36-
"@types/lodash": "^4.14.168",
36+
"@types/lodash": "^4.14.170",
3737
"@types/lunr": "^2.3.3",
38-
"@types/marked": "^2.0.2",
38+
"@types/marked": "^2.0.3",
3939
"@types/minimatch": "3.0.4",
4040
"@types/mocha": "^8.2.2",
41-
"@types/node": "^15.0.1",
42-
"@typescript-eslint/eslint-plugin": "^4.22.0",
43-
"@typescript-eslint/parser": "^4.22.0",
44-
"eslint": "^7.25.0",
45-
"mocha": "^8.3.2",
41+
"@types/node": "^15.12.1",
42+
"@typescript-eslint/eslint-plugin": "^4.26.0",
43+
"@typescript-eslint/parser": "^4.26.0",
44+
"eslint": "^7.28.0",
45+
"mocha": "^8.4.0",
4646
"nyc": "^15.1.0",
47-
"prettier": "^2.2.1",
48-
"typescript": "^4.2.4"
47+
"prettier": "2.2.1",
48+
"typescript": "^4.3.2"
4949
},
5050
"files": [
5151
"bin",

src/lib/converter/context.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ export class Context {
7878
* /** We should use this comment *&#47;
7979
* export * as Mod from "./mod"
8080
* ```
81-
* Will be removed in 0.21.
81+
* Will be removed in 0.22.
8282
* @internal
8383
*/
8484
exportSymbol?: ts.Symbol;
@@ -288,6 +288,7 @@ const builtInSymbolRegExp = /^__@(\w+)$/;
288288
const uniqueSymbolRegExp = /^__@(.*)@\d+$/;
289289

290290
function getHumanName(name: string) {
291+
// TS 4.0, 4.1, 4.2 - well known symbols are treated specially.
291292
let match = builtInSymbolRegExp.exec(name);
292293
if (match) {
293294
return `[Symbol.${match[1]}]`;

src/lib/converter/factories/comment.ts

Lines changed: 35 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,7 @@ import * as ts from "typescript";
22
import { toArray } from "lodash";
33

44
import { Comment, CommentTag } from "../../models/comments/index";
5-
6-
/**
7-
* Return the parsed comment of the given TypeScript node.
8-
*
9-
* @param node The node whose comment should be returned.
10-
* @return The parsed comment as a [[Comment]] instance or undefined if no comment is present.
11-
*/
12-
export function createComment(node: ts.Node): Comment | undefined {
13-
const comment = getRawComment(node);
14-
if (!comment) {
15-
return;
16-
}
17-
18-
return parseComment(comment);
19-
}
5+
import { Logger } from "../../utils";
206

217
/**
228
* Check whether the given module declaration is the topmost.
@@ -88,13 +74,24 @@ function getJSDocCommentRanges(node: ts.Node, text: string): ts.CommentRange[] {
8874
);
8975
}
9076

77+
export function getJsDocCommentText(comment: ts.JSDocTag["comment"]) {
78+
if (typeof comment === "string") {
79+
return comment;
80+
}
81+
82+
return comment?.map((val) => val.text).join("");
83+
}
84+
9185
/**
9286
* Return the raw comment string for the given node.
9387
*
9488
* @param node The node whose comment should be resolved.
9589
* @returns The raw comment string or undefined if no comment could be found.
9690
*/
97-
export function getRawComment(node: ts.Node): string | undefined {
91+
export function getRawComment(
92+
node: ts.Node,
93+
logger: Logger
94+
): string | undefined {
9895
// This happens if we are converting a JS project that has @typedef "interfaces"
9996
// with an @property tag, a @typedef type alias, a callback with parameters, etc.
10097
if (
@@ -105,7 +102,7 @@ export function getRawComment(node: ts.Node): string | undefined {
105102
) {
106103
// Also strip off leading dashes:
107104
// @property {string} name - docs
108-
return node.comment?.replace(/^\s*-\s*/, "");
105+
return getJsDocCommentText(node.comment)?.replace(/^\s*-\s*/, "");
109106
}
110107

111108
if (
@@ -129,52 +126,46 @@ export function getRawComment(node: ts.Node): string | undefined {
129126
const comments = getJSDocCommentRanges(node, sourceFile.text);
130127
if (comments.length) {
131128
let comment: ts.CommentRange;
132-
let explicitPackageComment = comments.find((comment) =>
133-
sourceFile.text
134-
.substring(comment.pos, comment.end)
135-
.includes("@module")
136-
);
137129

138-
// TODO: Deprecate and remove. This is an abuse of the @packageDocumentation tag. See:
139-
// https://github.com/TypeStrong/typedoc/issues/1504#issuecomment-775842609
140-
// Deprecate in 0.21, remove in 0.22
141-
explicitPackageComment ??= comments.find((comment) =>
142-
sourceFile.text
143-
.substring(comment.pos, comment.end)
144-
.includes("@packageDocumentation")
145-
);
146130
if (node.kind === ts.SyntaxKind.SourceFile) {
131+
const explicitPackageComment =
132+
comments.find((comment) =>
133+
sourceFile.text
134+
.substring(comment.pos, comment.end)
135+
.includes("@module")
136+
) ??
137+
comments.find((comment) =>
138+
sourceFile.text
139+
.substring(comment.pos, comment.end)
140+
.includes("@packageDocumentation")
141+
);
142+
147143
if (explicitPackageComment) {
148144
comment = explicitPackageComment;
149145
} else if (comments.length > 1) {
150146
// Legacy behavior, require more than one comment and use the first comment.
151-
// FUTURE: GH#1083, follow deprecation process to phase this out.
152147
comment = comments[0];
148+
149+
logger.deprecated(
150+
`Specifying multiple comments at the start of a file to use the first comment as the comment for the module has been deprecated. Use @module or @packageDocumentation instead.`,
151+
false
152+
);
153153
} else {
154154
// Single comment that may be a license comment, or no comments, bail.
155155
return;
156156
}
157157
} else {
158158
comment = comments[comments.length - 1];
159-
// If a non-SourceFile node comment has this tag, it should not be attached to the node
160-
// as it documents the whole file by convention.
161-
// TODO: Deprecate and remove. This is an abuse of the @packageDocumentation tag. See:
162-
// https://github.com/TypeStrong/typedoc/issues/1504#issuecomment-775842609
163-
// Deprecate in 0.21, remove in 0.22
164-
if (
165-
sourceFile.text
166-
.substring(comment.pos, comment.end)
167-
.includes("@packageDocumentation")
168-
) {
169-
return;
170-
}
171159

172160
// If a non-SourceFile node comment has this tag, it should not be attached to the node
173161
// as it documents the module.
174162
if (
175163
sourceFile.text
176164
.substring(comment.pos, comment.end)
177-
.includes("@module")
165+
.includes("@module") ||
166+
sourceFile.text
167+
.substring(comment.pos, comment.end)
168+
.includes("@packageDocumentation")
178169
) {
179170
return;
180171
}

src/lib/converter/plugins/CommentPlugin.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ import {
99
DeclarationReflection,
1010
} from "../../models/reflections/index";
1111
import { Component, ConverterComponent } from "../components";
12-
import { parseComment, getRawComment } from "../factories/comment";
12+
import {
13+
parseComment,
14+
getRawComment,
15+
getJsDocCommentText,
16+
} from "../factories/comment";
1317
import { Converter } from "../converter";
1418
import { Context } from "../context";
1519
import { partition, uniq } from "lodash";
@@ -124,8 +128,9 @@ export class CommentPlugin extends ConverterComponent {
124128
node?: ts.Node
125129
) {
126130
if (node && ts.isJSDocTemplateTag(node.parent)) {
127-
if (node.parent.comment) {
128-
reflection.comment = new Comment(node.parent.comment);
131+
const comment = getJsDocCommentText(node.parent.comment);
132+
if (comment) {
133+
reflection.comment = new Comment(comment);
129134
}
130135
}
131136

@@ -167,10 +172,11 @@ export class CommentPlugin extends ConverterComponent {
167172
return;
168173
}
169174

170-
// Clean this up in 0.21. We should really accept a ts.Symbol so we don't need exportSymbol on Context
175+
// Clean this up in 0.22. We should really accept a ts.Symbol so we don't need exportSymbol on Context
171176
const exportNode = context.exportSymbol?.getDeclarations()?.[0];
172-
let rawComment = exportNode && getRawComment(exportNode);
173-
rawComment ??= node && getRawComment(node);
177+
let rawComment =
178+
exportNode && getRawComment(exportNode, this.application.logger);
179+
rawComment ??= node && getRawComment(node, this.application.logger);
174180
if (!rawComment) {
175181
return;
176182
}

src/lib/converter/symbols.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,7 @@ function convertClassOrInterface(
491491
if (instanceType.typeParameters) {
492492
reflection.typeParameters = instanceType.typeParameters.map((param) => {
493493
const declaration = param.symbol?.declarations?.[0];
494-
assert(ts.isTypeParameterDeclaration(declaration));
494+
assert(declaration && ts.isTypeParameterDeclaration(declaration));
495495
return createTypeParamReflection(declaration, reflectionContext);
496496
});
497497
}
@@ -596,7 +596,9 @@ function convertProperty(
596596
reflection.type = context.converter.convertType(
597597
context,
598598
(context.isConvertingTypeNode() ? parameterType : void 0) ??
599-
context.checker.getTypeOfSymbolAtLocation(symbol, {} as any)
599+
context.checker.getTypeOfSymbolAtLocation(symbol, {
600+
kind: ts.SyntaxKind.SourceFile,
601+
} as any)
600602
);
601603

602604
if (reflection.flags.isOptional) {
@@ -801,17 +803,18 @@ function convertVariableAsFunction(
801803
.getDeclarations()
802804
?.find(ts.isVariableDeclaration);
803805

804-
const type = context.checker.getTypeOfSymbolAtLocation(
805-
symbol,
806-
declaration ?? symbol.valueDeclaration
807-
);
806+
const accessDeclaration = declaration ?? symbol.valueDeclaration;
807+
808+
const type = accessDeclaration
809+
? context.checker.getTypeOfSymbolAtLocation(symbol, accessDeclaration)
810+
: context.checker.getDeclaredTypeOfSymbol(symbol);
808811

809812
const reflection = context.createDeclarationReflection(
810813
ReflectionKind.Function,
811814
symbol,
812815
exportSymbol
813816
);
814-
setModifiers(symbol, declaration ?? symbol.valueDeclaration, reflection);
817+
setModifiers(symbol, accessDeclaration, reflection);
815818
// Does anyone care about this? I doubt it...
816819
if (
817820
declaration &&
@@ -906,9 +909,13 @@ function isInherited(context: Context, symbol: ts.Symbol) {
906909

907910
function setModifiers(
908911
symbol: ts.Symbol,
909-
declaration: ts.Declaration,
912+
declaration: ts.Declaration | undefined,
910913
reflection: Reflection
911914
) {
915+
if (!declaration) {
916+
return;
917+
}
918+
912919
const modifiers = ts.getCombinedModifierFlags(declaration);
913920

914921
if (

src/lib/utils/loggers.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -167,10 +167,12 @@ export class Logger {
167167
}
168168

169169
/** @internal */
170-
deprecated(text: string) {
171-
const stack = new Error().stack?.split("\n");
172-
if (stack && stack.length >= 4) {
173-
text = text + "\n" + stack[3];
170+
deprecated(text: string, addStack = true) {
171+
if (addStack) {
172+
const stack = new Error().stack?.split("\n");
173+
if (stack && stack.length >= 4) {
174+
text = text + "\n" + stack[3];
175+
}
174176
}
175177
if (!this.deprecationWarnings.has(text)) {
176178
this.deprecationWarnings.add(text);

0 commit comments

Comments
 (0)