@oicl-lit/analyzer 0.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/LICENSE +28 -0
  2. package/README.md +76 -0
  3. package/index.d.ts +10 -0
  4. package/index.d.ts.map +1 -0
  5. package/index.js +10 -0
  6. package/index.js.map +1 -0
  7. package/lib/analyzer.d.ts +47 -0
  8. package/lib/analyzer.d.ts.map +1 -0
  9. package/lib/analyzer.js +90 -0
  10. package/lib/analyzer.js.map +1 -0
  11. package/lib/custom-elements/custom-elements.d.ts +33 -0
  12. package/lib/custom-elements/custom-elements.d.ts.map +1 -0
  13. package/lib/custom-elements/custom-elements.js +124 -0
  14. package/lib/custom-elements/custom-elements.js.map +1 -0
  15. package/lib/custom-elements/events.d.ts +19 -0
  16. package/lib/custom-elements/events.d.ts.map +1 -0
  17. package/lib/custom-elements/events.js +25 -0
  18. package/lib/custom-elements/events.js.map +1 -0
  19. package/lib/diagnostic-code.d.ts +21 -0
  20. package/lib/diagnostic-code.d.ts.map +1 -0
  21. package/lib/diagnostic-code.js +20 -0
  22. package/lib/diagnostic-code.js.map +1 -0
  23. package/lib/errors.d.ts +24 -0
  24. package/lib/errors.d.ts.map +1 -0
  25. package/lib/errors.js +17 -0
  26. package/lib/errors.js.map +1 -0
  27. package/lib/javascript/classes.d.ts +50 -0
  28. package/lib/javascript/classes.d.ts.map +1 -0
  29. package/lib/javascript/classes.js +307 -0
  30. package/lib/javascript/classes.js.map +1 -0
  31. package/lib/javascript/functions.d.ts +31 -0
  32. package/lib/javascript/functions.d.ts.map +1 -0
  33. package/lib/javascript/functions.js +144 -0
  34. package/lib/javascript/functions.js.map +1 -0
  35. package/lib/javascript/jsdoc.d.ts +67 -0
  36. package/lib/javascript/jsdoc.d.ts.map +1 -0
  37. package/lib/javascript/jsdoc.js +244 -0
  38. package/lib/javascript/jsdoc.js.map +1 -0
  39. package/lib/javascript/mixins.d.ts +45 -0
  40. package/lib/javascript/mixins.d.ts.map +1 -0
  41. package/lib/javascript/mixins.js +147 -0
  42. package/lib/javascript/mixins.js.map +1 -0
  43. package/lib/javascript/modules.d.ts +42 -0
  44. package/lib/javascript/modules.d.ts.map +1 -0
  45. package/lib/javascript/modules.js +277 -0
  46. package/lib/javascript/modules.js.map +1 -0
  47. package/lib/javascript/packages.d.ts +18 -0
  48. package/lib/javascript/packages.d.ts.map +1 -0
  49. package/lib/javascript/packages.js +53 -0
  50. package/lib/javascript/packages.js.map +1 -0
  51. package/lib/javascript/variables.d.ts +29 -0
  52. package/lib/javascript/variables.d.ts.map +1 -0
  53. package/lib/javascript/variables.js +143 -0
  54. package/lib/javascript/variables.js.map +1 -0
  55. package/lib/lit/decorators.d.ts +36 -0
  56. package/lib/lit/decorators.d.ts.map +1 -0
  57. package/lib/lit/decorators.js +32 -0
  58. package/lib/lit/decorators.js.map +1 -0
  59. package/lib/lit/lit-element.d.ts +39 -0
  60. package/lib/lit/lit-element.d.ts.map +1 -0
  61. package/lib/lit/lit-element.js +96 -0
  62. package/lib/lit/lit-element.js.map +1 -0
  63. package/lib/lit/modules.d.ts +28 -0
  64. package/lib/lit/modules.d.ts.map +1 -0
  65. package/lib/lit/modules.js +62 -0
  66. package/lib/lit/modules.js.map +1 -0
  67. package/lib/lit/properties.d.ts +43 -0
  68. package/lib/lit/properties.d.ts.map +1 -0
  69. package/lib/lit/properties.js +268 -0
  70. package/lib/lit/properties.js.map +1 -0
  71. package/lib/lit/template.d.ts +110 -0
  72. package/lib/lit/template.d.ts.map +1 -0
  73. package/lib/lit/template.js +412 -0
  74. package/lib/lit/template.js.map +1 -0
  75. package/lib/lit-element/decorators.d.ts +11 -0
  76. package/lib/lit-element/decorators.d.ts.map +1 -0
  77. package/lib/lit-element/decorators.js +11 -0
  78. package/lib/lit-element/decorators.js.map +1 -0
  79. package/lib/lit-element/lit-element.d.ts +11 -0
  80. package/lib/lit-element/lit-element.d.ts.map +1 -0
  81. package/lib/lit-element/lit-element.js +11 -0
  82. package/lib/lit-element/lit-element.js.map +1 -0
  83. package/lib/lit-element/properties.d.ts +11 -0
  84. package/lib/lit-element/properties.d.ts.map +1 -0
  85. package/lib/lit-element/properties.js +11 -0
  86. package/lib/lit-element/properties.js.map +1 -0
  87. package/lib/model.d.ts +506 -0
  88. package/lib/model.d.ts.map +1 -0
  89. package/lib/model.js +392 -0
  90. package/lib/model.js.map +1 -0
  91. package/lib/package-analyzer.d.ts +25 -0
  92. package/lib/package-analyzer.d.ts.map +1 -0
  93. package/lib/package-analyzer.js +81 -0
  94. package/lib/package-analyzer.js.map +1 -0
  95. package/lib/paths.d.ts +24 -0
  96. package/lib/paths.d.ts.map +1 -0
  97. package/lib/paths.js +35 -0
  98. package/lib/paths.js.map +1 -0
  99. package/lib/references.d.ts +107 -0
  100. package/lib/references.d.ts.map +1 -0
  101. package/lib/references.js +345 -0
  102. package/lib/references.js.map +1 -0
  103. package/lib/types.d.ts +25 -0
  104. package/lib/types.d.ts.map +1 -0
  105. package/lib/types.js +257 -0
  106. package/lib/types.js.map +1 -0
  107. package/lib/utils.d.ts +22 -0
  108. package/lib/utils.d.ts.map +1 -0
  109. package/lib/utils.js +51 -0
  110. package/lib/utils.js.map +1 -0
  111. package/package-analyzer.d.ts +8 -0
  112. package/package-analyzer.d.ts.map +1 -0
  113. package/package-analyzer.js +8 -0
  114. package/package-analyzer.js.map +1 -0
  115. package/package.json +109 -0
@@ -0,0 +1,50 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022 Google LLC
4
+ * SPDX-License-Identifier: BSD-3-Clause
5
+ */
6
+ /**
7
+ * @fileoverview
8
+ *
9
+ * Utilities for analyzing class declarations
10
+ */
11
+ import type ts from 'typescript';
12
+ import { ClassDeclaration, AnalyzerInterface, DeclarationInfo, ClassHeritage, Reference, ClassField, ClassMethod } from '../model.js';
13
+ export type TypeScript = typeof ts;
14
+ /**
15
+ * Returns an analyzer `ClassDeclaration` model for the given
16
+ * ts.ClassLikeDeclaration.
17
+ *
18
+ * Note, the `docNode` may differ from the `declaration` in the case of a const
19
+ * assignment to a class expression, as the JSDoc will be attached to the
20
+ * VariableStatement rather than the class-like expression.
21
+ */
22
+ export declare const getClassDeclaration: (declaration: ts.ClassLikeDeclaration, name: string, analyzer: AnalyzerInterface, docNode?: ts.Node, isMixinClass?: boolean) => ClassDeclaration;
23
+ /**
24
+ * Returns the `fields` and `methods` of a class.
25
+ */
26
+ export declare const getClassMembers: (declaration: ts.ClassLikeDeclaration, analyzer: AnalyzerInterface) => {
27
+ fieldMap: Map<string, ClassField>;
28
+ staticFieldMap: Map<string, ClassField>;
29
+ methodMap: Map<string, ClassMethod>;
30
+ staticMethodMap: Map<string, ClassMethod>;
31
+ };
32
+ /**
33
+ * Returns name and model factory for a class declaration.
34
+ */
35
+ export declare const getClassDeclarationInfo: (declaration: ts.ClassDeclaration, analyzer: AnalyzerInterface) => DeclarationInfo | undefined;
36
+ /**
37
+ * Returns the superClass and any applied mixins for a given class declaration.
38
+ */
39
+ export declare const getHeritage: (declaration: ts.ClassLikeDeclarationBase, analyzer: AnalyzerInterface, isMixinClass?: boolean) => ClassHeritage;
40
+ export declare const getHeritageFromExpression: (expression: ts.Expression, analyzer: AnalyzerInterface, isMixinClass?: boolean) => ClassHeritage;
41
+ export declare const getSuperClassAndMixins: (expression: ts.Expression, foundMixins: Reference[], analyzer: AnalyzerInterface) => Reference | undefined;
42
+ export declare const isConstructorFieldInitializer: (expression: ts.Expression, typescript: typeof ts) => expression is ConstructorFieldInitializer;
43
+ type ConstructorFieldInitializer = ts.AssignmentExpression<ts.EqualsToken> & {
44
+ left: ts.PropertyAccessExpression & {
45
+ expression: ts.ThisExpression;
46
+ };
47
+ };
48
+ export declare const maybeGetAppliedMixin: (expression: ts.Expression, identifier: ts.Identifier, analyzer: AnalyzerInterface) => ClassDeclaration | undefined;
49
+ export {};
50
+ //# sourceMappingURL=classes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classes.d.ts","sourceRoot":"","sources":["../../src/lib/javascript/classes.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAGjC,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,SAAS,EACT,UAAU,EACV,WAAW,EAEZ,MAAM,aAAa,CAAC;AAoBrB,MAAM,MAAM,UAAU,GAAG,OAAO,EAAE,CAAC;AAEnC;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,GAC9B,aAAa,EAAE,CAAC,oBAAoB,EACpC,MAAM,MAAM,EACZ,UAAU,iBAAiB,EAC3B,UAAU,EAAE,CAAC,IAAI,EACjB,eAAe,OAAO,qBAevB,CAAC;AAwBF;;GAEG;AACH,eAAO,MAAM,eAAe,GAC1B,aAAa,EAAE,CAAC,oBAAoB,EACpC,UAAU,iBAAiB;;;;;CAsH5B,CAAC;AAuCF;;GAEG;AACH,eAAO,MAAM,uBAAuB,GAClC,aAAa,EAAE,CAAC,gBAAgB,EAChC,UAAU,iBAAiB,KAC1B,eAAe,GAAG,SAWpB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,WAAW,GACtB,aAAa,EAAE,CAAC,wBAAwB,EACxC,UAAU,iBAAiB,EAC3B,eAAe,OAAO,KACrB,aA0BF,CAAC;AAEF,eAAO,MAAM,yBAAyB,GACpC,YAAY,EAAE,CAAC,UAAU,EACzB,UAAU,iBAAiB,EAC3B,eAAe,OAAO,KACrB,aAOF,CAAC;AAEF,eAAO,MAAM,sBAAsB,GACjC,YAAY,EAAE,CAAC,UAAU,EACzB,aAAa,SAAS,EAAE,EACxB,UAAU,iBAAiB,KAC1B,SAAS,GAAG,SA4Dd,CAAC;AAEF,eAAO,MAAM,6BAA6B,GACxC,YAAY,EAAE,CAAC,UAAU,EACzB,YAAY,OAAO,EAAE,KACpB,UAAU,IAAI,2BAOhB,CAAC;AAEF,KAAK,2BAA2B,GAAG,EAAE,CAAC,oBAAoB,CAAC,EAAE,CAAC,WAAW,CAAC,GAAG;IAC3E,IAAI,EAAE,EAAE,CAAC,wBAAwB,GAAG;QAAC,UAAU,EAAE,EAAE,CAAC,cAAc,CAAA;KAAC,CAAC;CACrE,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAC/B,YAAY,EAAE,CAAC,UAAU,EACzB,YAAY,EAAE,CAAC,UAAU,EACzB,UAAU,iBAAiB,KAC1B,gBAAgB,GAAG,SAwBrB,CAAC"}
@@ -0,0 +1,307 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022 Google LLC
4
+ * SPDX-License-Identifier: BSD-3-Clause
5
+ */
6
+ import { DiagnosticCode } from '../diagnostic-code.js';
7
+ import { createDiagnostic } from '../errors.js';
8
+ import { ClassDeclaration, ClassField, ClassMethod, MixinDeclaration, } from '../model.js';
9
+ import { isLitElementSubclass, getLitElementDeclaration, } from '../lit-element/lit-element.js';
10
+ import { getReferenceForIdentifier } from '../references.js';
11
+ import { parseNodeJSDocInfo } from './jsdoc.js';
12
+ import { hasDefaultModifier, hasStaticModifier, hasExportModifier, getPrivacy, } from '../utils.js';
13
+ import { getFunctionLikeInfo } from './functions.js';
14
+ import { getTypeForNode } from '../types.js';
15
+ import { isCustomElementSubclass, getCustomElementDeclaration, } from '../custom-elements/custom-elements.js';
16
+ /**
17
+ * Returns an analyzer `ClassDeclaration` model for the given
18
+ * ts.ClassLikeDeclaration.
19
+ *
20
+ * Note, the `docNode` may differ from the `declaration` in the case of a const
21
+ * assignment to a class expression, as the JSDoc will be attached to the
22
+ * VariableStatement rather than the class-like expression.
23
+ */
24
+ export const getClassDeclaration = (declaration, name, analyzer, docNode, isMixinClass) => {
25
+ if (isLitElementSubclass(declaration, analyzer)) {
26
+ return getLitElementDeclaration(declaration, analyzer, isMixinClass);
27
+ }
28
+ if (isCustomElementSubclass(declaration, analyzer)) {
29
+ return getCustomElementDeclaration(declaration, analyzer, isMixinClass);
30
+ }
31
+ return new ClassDeclaration({
32
+ name,
33
+ node: declaration,
34
+ getHeritage: () => getHeritage(declaration, analyzer, isMixinClass),
35
+ ...parseNodeJSDocInfo(docNode ?? declaration, analyzer),
36
+ ...getClassMembers(declaration, analyzer),
37
+ });
38
+ };
39
+ const getIsReadonlyForNode = (node, analyzer) => {
40
+ const { typescript } = analyzer;
41
+ if (typescript.isPropertyDeclaration(node)) {
42
+ return (node.modifiers?.some((mod) => typescript.isReadonlyKeywordOrPlusOrMinusToken(mod)) ||
43
+ typescript
44
+ .getJSDocTags(node)
45
+ .some((tag) => tag.tagName.text === 'readonly'));
46
+ }
47
+ else if (typescript.isStatement(node)) {
48
+ return typescript
49
+ .getJSDocTags(node)
50
+ .some((tag) => tag.tagName.text === 'readonly');
51
+ }
52
+ return false;
53
+ };
54
+ /**
55
+ * Returns the `fields` and `methods` of a class.
56
+ */
57
+ export const getClassMembers = (declaration, analyzer) => {
58
+ const { typescript } = analyzer;
59
+ const fieldMap = new Map();
60
+ const staticFieldMap = new Map();
61
+ const methodMap = new Map();
62
+ const staticMethodMap = new Map();
63
+ const accessors = new Map();
64
+ declaration.members.forEach((member) => {
65
+ // Ignore non-implementation signatures of overloaded methods by checking
66
+ // for `node.body`.
67
+ if (typescript.isConstructorDeclaration(member) && member.body) {
68
+ // TODO(bennypowers): We probably want to see if this matches what TypeScript considers a field initialization.
69
+ // Maybe instead of iterating through the constructor statements, we walk the body looking for any
70
+ // assignment expression so that we get ones inside of if statements, in parenthesized expressions, etc.
71
+ //
72
+ // Also, this doesn't cover destructuring assignment.
73
+ //
74
+ // This is ok for now because these are rare ways to "declare" a field,
75
+ // especially in web components where you shouldn't have constructor parameters.
76
+ member.body.statements.forEach((statement) => {
77
+ if (typescript.isExpressionStatement(statement) &&
78
+ isConstructorFieldInitializer(statement.expression, typescript)) {
79
+ const name = statement.expression.left.name.getText();
80
+ fieldMap.set(name, new ClassField({
81
+ name,
82
+ type: getTypeForNode(statement.expression.right, analyzer),
83
+ privacy: getPrivacy(typescript, statement),
84
+ readonly: getIsReadonlyForNode(statement, analyzer),
85
+ node: statement.expression,
86
+ }));
87
+ }
88
+ });
89
+ }
90
+ else if (typescript.isMethodDeclaration(member) && member.body) {
91
+ const info = getMemberInfo(typescript, member);
92
+ const name = member.name.getText();
93
+ (info.static ? staticMethodMap : methodMap).set(name, new ClassMethod({
94
+ ...info,
95
+ ...getFunctionLikeInfo(member, name, analyzer),
96
+ ...parseNodeJSDocInfo(member, analyzer),
97
+ node: member,
98
+ }));
99
+ }
100
+ else if (typescript.isPropertyDeclaration(member)) {
101
+ if (!typescript.isIdentifier(member.name) &&
102
+ !typescript.isPrivateIdentifier(member.name)) {
103
+ analyzer.addDiagnostic(createDiagnostic({
104
+ typescript,
105
+ node: member,
106
+ message: '@lit-labs/analyzer only supports analyzing class properties ' +
107
+ 'named with plain identifiers, or private class fields. This ' +
108
+ 'property was ignored: ' +
109
+ member.name.getText(),
110
+ category: typescript.DiagnosticCategory.Warning,
111
+ code: DiagnosticCode.UNSUPPORTED,
112
+ }));
113
+ return;
114
+ }
115
+ const info = getMemberInfo(typescript, member);
116
+ (info.static ? staticFieldMap : fieldMap).set(member.name.getText(), new ClassField({
117
+ ...info,
118
+ default: member.initializer?.getText(),
119
+ type: getTypeForNode(member, analyzer),
120
+ ...parseNodeJSDocInfo(member, analyzer),
121
+ readonly: getIsReadonlyForNode(member, analyzer),
122
+ node: member,
123
+ }));
124
+ }
125
+ else if (typescript.isAccessor(member)) {
126
+ const name = member.name.getText();
127
+ const _accessors = accessors.get(name) ?? {};
128
+ if (typescript.isGetAccessor(member))
129
+ _accessors.get = member;
130
+ else if (typescript.isSetAccessor(member))
131
+ _accessors.set = member;
132
+ accessors.set(name, _accessors);
133
+ }
134
+ });
135
+ for (const [name, { get, set }] of accessors) {
136
+ if (get ?? set) {
137
+ fieldMap.set(name, new ClassField({
138
+ name,
139
+ type: getTypeForNode((get ?? set), analyzer),
140
+ privacy: getPrivacy(typescript, (get ?? set)),
141
+ readonly: !!get && !set,
142
+ // TODO(bennypowers): derive from getter?
143
+ // default: ???
144
+ // TODO(bennypowers): reflect, etc?
145
+ node: (set ?? get),
146
+ }));
147
+ }
148
+ }
149
+ return {
150
+ fieldMap,
151
+ staticFieldMap,
152
+ methodMap,
153
+ staticMethodMap,
154
+ };
155
+ };
156
+ const getMemberInfo = (typescript, node) => {
157
+ return {
158
+ name: node.name.getText(),
159
+ static: hasStaticModifier(typescript, node),
160
+ privacy: getPrivacy(typescript, node),
161
+ };
162
+ };
163
+ /**
164
+ * Returns the name of a class declaration.
165
+ */
166
+ const getClassDeclarationName = (declaration, analyzer) => {
167
+ const name = declaration.name?.text ??
168
+ // The only time a class declaration will not have a name is when it is
169
+ // a default export, aka `export default class { }`
170
+ (hasDefaultModifier(analyzer.typescript, declaration)
171
+ ? 'default'
172
+ : undefined);
173
+ if (name === undefined) {
174
+ analyzer.addDiagnostic(createDiagnostic({
175
+ typescript: analyzer.typescript,
176
+ node: declaration,
177
+ message: `Illegal syntax: a class declaration must either have a name or be a default export`,
178
+ }));
179
+ }
180
+ return name;
181
+ };
182
+ /**
183
+ * Returns name and model factory for a class declaration.
184
+ */
185
+ export const getClassDeclarationInfo = (declaration, analyzer) => {
186
+ const name = getClassDeclarationName(declaration, analyzer);
187
+ if (name === undefined) {
188
+ return undefined;
189
+ }
190
+ return {
191
+ name,
192
+ node: declaration,
193
+ factory: () => getClassDeclaration(declaration, name, analyzer),
194
+ isExport: hasExportModifier(analyzer.typescript, declaration),
195
+ };
196
+ };
197
+ /**
198
+ * Returns the superClass and any applied mixins for a given class declaration.
199
+ */
200
+ export const getHeritage = (declaration, analyzer, isMixinClass) => {
201
+ const extendsClause = declaration.heritageClauses?.find((c) => c.token === analyzer.typescript.SyntaxKind.ExtendsKeyword);
202
+ if (extendsClause !== undefined) {
203
+ if (extendsClause.types.length === 1) {
204
+ return getHeritageFromExpression(extendsClause.types[0].expression, analyzer, isMixinClass);
205
+ }
206
+ analyzer.addDiagnostic(createDiagnostic({
207
+ typescript: analyzer.typescript,
208
+ node: extendsClause,
209
+ message: 'Illegal syntax: did not expect extends clause to have multiple types',
210
+ }));
211
+ }
212
+ // No extends clause; return empty heritage
213
+ return {
214
+ mixins: [],
215
+ superClass: undefined,
216
+ };
217
+ };
218
+ export const getHeritageFromExpression = (expression, analyzer, isMixinClass) => {
219
+ const mixins = [];
220
+ const superClass = getSuperClassAndMixins(expression, mixins, analyzer);
221
+ return {
222
+ superClass: isMixinClass ? undefined : superClass,
223
+ mixins,
224
+ };
225
+ };
226
+ export const getSuperClassAndMixins = (expression, foundMixins, analyzer) => {
227
+ // TODO(kschaaf) Could add support for inline class expressions here as well
228
+ if (analyzer.typescript.isIdentifier(expression)) {
229
+ return getReferenceForIdentifier(expression, analyzer);
230
+ }
231
+ else if (analyzer.typescript.isCallExpression(expression) &&
232
+ analyzer.typescript.isIdentifier(expression.expression)) {
233
+ // FYI we purposely restrict to identifiers since we represent mixins
234
+ // as references. If we want to support complex expressions in future,
235
+ // we will need to rework that in the model.
236
+ const mixinRef = getReferenceForIdentifier(expression.expression, analyzer);
237
+ // We need to eagerly dereference a mixin ref to know what argument the
238
+ // super class is passed into
239
+ let mixin;
240
+ try {
241
+ mixin = mixinRef?.dereference(MixinDeclaration);
242
+ }
243
+ catch (_err) {
244
+ // It wasn't a MixinDeclaration for whatever reason
245
+ mixin = undefined;
246
+ }
247
+ // TODO (43081j): consider supporting external mixins properly at some point
248
+ // An external mixin is one which we discovered via analysis (e.g. CEM)
249
+ // but don't have a reference to in sources. In future, we should support
250
+ // those as it is likely we will pull most dependencies from manifest
251
+ // analysis rather than source.
252
+ // See issue #4492
253
+ if (mixinRef === undefined || mixin === undefined) {
254
+ analyzer.addDiagnostic(createDiagnostic({
255
+ typescript: analyzer.typescript,
256
+ node: expression,
257
+ message: `This is presumed to be a mixin but it could not be found ` +
258
+ `in the current project. Mixins imported from outside the ` +
259
+ `project are not yet supported ` +
260
+ `(see https://github.com/lit/lit/issues/4492).`,
261
+ code: DiagnosticCode.UNSUPPORTED,
262
+ category: analyzer.typescript.DiagnosticCategory.Warning,
263
+ }));
264
+ return undefined;
265
+ }
266
+ foundMixins.push(mixinRef);
267
+ const superArg = expression.arguments[mixin.superClassArgIndex];
268
+ const superClass = getSuperClassAndMixins(superArg, foundMixins, analyzer);
269
+ return superClass;
270
+ }
271
+ analyzer.addDiagnostic(createDiagnostic({
272
+ typescript: analyzer.typescript,
273
+ node: expression,
274
+ message: `Expected expression to be a concrete superclass or mixin.`,
275
+ code: DiagnosticCode.UNSUPPORTED,
276
+ category: analyzer.typescript.DiagnosticCategory.Warning,
277
+ }));
278
+ return undefined;
279
+ };
280
+ export const isConstructorFieldInitializer = (expression, typescript) => {
281
+ return (typescript.isBinaryExpression(expression) &&
282
+ expression.operatorToken.kind === typescript.SyntaxKind.EqualsToken &&
283
+ typescript.isPropertyAccessExpression(expression.left) &&
284
+ expression.left.expression.kind === typescript.SyntaxKind.ThisKeyword);
285
+ };
286
+ export const maybeGetAppliedMixin = (expression, identifier, analyzer) => {
287
+ if (analyzer.typescript.isCallExpression(expression) &&
288
+ analyzer.typescript.isIdentifier(expression.expression)) {
289
+ const mixinRef = getReferenceForIdentifier(expression.expression, analyzer);
290
+ try {
291
+ mixinRef?.dereference(MixinDeclaration);
292
+ }
293
+ catch (_err) {
294
+ return undefined;
295
+ }
296
+ const heritage = getHeritageFromExpression(expression, analyzer);
297
+ if (heritage.superClass) {
298
+ return new ClassDeclaration({
299
+ name: identifier.text,
300
+ node: expression,
301
+ getHeritage: () => heritage,
302
+ });
303
+ }
304
+ }
305
+ return undefined;
306
+ };
307
+ //# sourceMappingURL=classes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classes.js","sourceRoot":"","sources":["../../src/lib/javascript/classes.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license\n * Copyright 2022 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\n/**\n * @fileoverview\n *\n * Utilities for analyzing class declarations\n */\n\nimport type ts from 'typescript';\nimport {DiagnosticCode} from '../diagnostic-code.js';\nimport {createDiagnostic} from '../errors.js';\nimport {\n ClassDeclaration,\n AnalyzerInterface,\n DeclarationInfo,\n ClassHeritage,\n Reference,\n ClassField,\n ClassMethod,\n MixinDeclaration,\n} from '../model.js';\nimport {\n isLitElementSubclass,\n getLitElementDeclaration,\n} from '../lit-element/lit-element.js';\nimport {getReferenceForIdentifier} from '../references.js';\nimport {parseNodeJSDocInfo} from './jsdoc.js';\nimport {\n hasDefaultModifier,\n hasStaticModifier,\n hasExportModifier,\n getPrivacy,\n} from '../utils.js';\nimport {getFunctionLikeInfo} from './functions.js';\nimport {getTypeForNode} from '../types.js';\nimport {\n isCustomElementSubclass,\n getCustomElementDeclaration,\n} from '../custom-elements/custom-elements.js';\n\nexport type TypeScript = typeof ts;\n\n/**\n * Returns an analyzer `ClassDeclaration` model for the given\n * ts.ClassLikeDeclaration.\n *\n * Note, the `docNode` may differ from the `declaration` in the case of a const\n * assignment to a class expression, as the JSDoc will be attached to the\n * VariableStatement rather than the class-like expression.\n */\nexport const getClassDeclaration = (\n declaration: ts.ClassLikeDeclaration,\n name: string,\n analyzer: AnalyzerInterface,\n docNode?: ts.Node,\n isMixinClass?: boolean\n) => {\n if (isLitElementSubclass(declaration, analyzer)) {\n return getLitElementDeclaration(declaration, analyzer, isMixinClass);\n }\n if (isCustomElementSubclass(declaration, analyzer)) {\n return getCustomElementDeclaration(declaration, analyzer, isMixinClass);\n }\n return new ClassDeclaration({\n name,\n node: declaration,\n getHeritage: () => getHeritage(declaration, analyzer, isMixinClass),\n ...parseNodeJSDocInfo(docNode ?? declaration, analyzer),\n ...getClassMembers(declaration, analyzer),\n });\n};\n\nconst getIsReadonlyForNode = (\n node: ts.Node,\n analyzer: AnalyzerInterface\n): boolean => {\n const {typescript} = analyzer;\n if (typescript.isPropertyDeclaration(node)) {\n return (\n node.modifiers?.some((mod) =>\n typescript.isReadonlyKeywordOrPlusOrMinusToken(mod)\n ) ||\n typescript\n .getJSDocTags(node)\n .some((tag) => tag.tagName.text === 'readonly')\n );\n } else if (typescript.isStatement(node)) {\n return typescript\n .getJSDocTags(node)\n .some((tag) => tag.tagName.text === 'readonly');\n }\n return false;\n};\n\n/**\n * Returns the `fields` and `methods` of a class.\n */\nexport const getClassMembers = (\n declaration: ts.ClassLikeDeclaration,\n analyzer: AnalyzerInterface\n) => {\n const {typescript} = analyzer;\n const fieldMap = new Map<string, ClassField>();\n const staticFieldMap = new Map<string, ClassField>();\n const methodMap = new Map<string, ClassMethod>();\n const staticMethodMap = new Map<string, ClassMethod>();\n const accessors = new Map<\n string,\n {get?: ts.AccessorDeclaration; set?: ts.AccessorDeclaration}\n >();\n declaration.members.forEach((member) => {\n // Ignore non-implementation signatures of overloaded methods by checking\n // for `node.body`.\n if (typescript.isConstructorDeclaration(member) && member.body) {\n // TODO(bennypowers): We probably want to see if this matches what TypeScript considers a field initialization.\n // Maybe instead of iterating through the constructor statements, we walk the body looking for any\n // assignment expression so that we get ones inside of if statements, in parenthesized expressions, etc.\n //\n // Also, this doesn't cover destructuring assignment.\n //\n // This is ok for now because these are rare ways to \"declare\" a field,\n // especially in web components where you shouldn't have constructor parameters.\n member.body.statements.forEach((statement) => {\n if (\n typescript.isExpressionStatement(statement) &&\n isConstructorFieldInitializer(statement.expression, typescript)\n ) {\n const name = statement.expression.left.name.getText();\n fieldMap.set(\n name,\n new ClassField({\n name,\n type: getTypeForNode(statement.expression.right, analyzer),\n privacy: getPrivacy(typescript, statement),\n readonly: getIsReadonlyForNode(statement, analyzer),\n node: statement.expression,\n })\n );\n }\n });\n } else if (typescript.isMethodDeclaration(member) && member.body) {\n const info = getMemberInfo(typescript, member);\n const name = member.name.getText();\n (info.static ? staticMethodMap : methodMap).set(\n name,\n new ClassMethod({\n ...info,\n ...getFunctionLikeInfo(member, name, analyzer),\n ...parseNodeJSDocInfo(member, analyzer),\n node: member,\n })\n );\n } else if (typescript.isPropertyDeclaration(member)) {\n if (\n !typescript.isIdentifier(member.name) &&\n !typescript.isPrivateIdentifier(member.name)\n ) {\n analyzer.addDiagnostic(\n createDiagnostic({\n typescript,\n node: member,\n message:\n '@lit-labs/analyzer only supports analyzing class properties ' +\n 'named with plain identifiers, or private class fields. This ' +\n 'property was ignored: ' +\n member.name.getText(),\n category: typescript.DiagnosticCategory.Warning,\n code: DiagnosticCode.UNSUPPORTED,\n })\n );\n return;\n }\n\n const info = getMemberInfo(typescript, member);\n\n (info.static ? staticFieldMap : fieldMap).set(\n member.name.getText(),\n new ClassField({\n ...info,\n default: member.initializer?.getText(),\n type: getTypeForNode(member, analyzer),\n ...parseNodeJSDocInfo(member, analyzer),\n readonly: getIsReadonlyForNode(member, analyzer),\n node: member,\n })\n );\n } else if (typescript.isAccessor(member)) {\n const name = member.name.getText();\n const _accessors = accessors.get(name) ?? {};\n if (typescript.isGetAccessor(member)) _accessors.get = member;\n else if (typescript.isSetAccessor(member)) _accessors.set = member;\n accessors.set(name, _accessors);\n }\n });\n for (const [name, {get, set}] of accessors) {\n if (get ?? set) {\n fieldMap.set(\n name,\n new ClassField({\n name,\n type: getTypeForNode((get ?? set)!, analyzer),\n privacy: getPrivacy(typescript, (get ?? set)!),\n readonly: !!get && !set,\n // TODO(bennypowers): derive from getter?\n // default: ???\n // TODO(bennypowers): reflect, etc?\n node: (set ?? get)!,\n })\n );\n }\n }\n return {\n fieldMap,\n staticFieldMap,\n methodMap,\n staticMethodMap,\n };\n};\n\nconst getMemberInfo = (\n typescript: TypeScript,\n node: ts.MethodDeclaration | ts.PropertyDeclaration\n) => {\n return {\n name: node.name.getText(),\n static: hasStaticModifier(typescript, node),\n privacy: getPrivacy(typescript, node),\n };\n};\n\n/**\n * Returns the name of a class declaration.\n */\nconst getClassDeclarationName = (\n declaration: ts.ClassDeclaration,\n analyzer: AnalyzerInterface\n) => {\n const name =\n declaration.name?.text ??\n // The only time a class declaration will not have a name is when it is\n // a default export, aka `export default class { }`\n (hasDefaultModifier(analyzer.typescript, declaration)\n ? 'default'\n : undefined);\n if (name === undefined) {\n analyzer.addDiagnostic(\n createDiagnostic({\n typescript: analyzer.typescript,\n node: declaration,\n message: `Illegal syntax: a class declaration must either have a name or be a default export`,\n })\n );\n }\n return name;\n};\n\n/**\n * Returns name and model factory for a class declaration.\n */\nexport const getClassDeclarationInfo = (\n declaration: ts.ClassDeclaration,\n analyzer: AnalyzerInterface\n): DeclarationInfo | undefined => {\n const name = getClassDeclarationName(declaration, analyzer);\n if (name === undefined) {\n return undefined;\n }\n return {\n name,\n node: declaration,\n factory: () => getClassDeclaration(declaration, name, analyzer),\n isExport: hasExportModifier(analyzer.typescript, declaration),\n };\n};\n\n/**\n * Returns the superClass and any applied mixins for a given class declaration.\n */\nexport const getHeritage = (\n declaration: ts.ClassLikeDeclarationBase,\n analyzer: AnalyzerInterface,\n isMixinClass?: boolean\n): ClassHeritage => {\n const extendsClause = declaration.heritageClauses?.find(\n (c) => c.token === analyzer.typescript.SyntaxKind.ExtendsKeyword\n );\n if (extendsClause !== undefined) {\n if (extendsClause.types.length === 1) {\n return getHeritageFromExpression(\n extendsClause.types[0].expression,\n analyzer,\n isMixinClass\n );\n }\n analyzer.addDiagnostic(\n createDiagnostic({\n typescript: analyzer.typescript,\n node: extendsClause,\n message:\n 'Illegal syntax: did not expect extends clause to have multiple types',\n })\n );\n }\n // No extends clause; return empty heritage\n return {\n mixins: [],\n superClass: undefined,\n };\n};\n\nexport const getHeritageFromExpression = (\n expression: ts.Expression,\n analyzer: AnalyzerInterface,\n isMixinClass?: boolean\n): ClassHeritage => {\n const mixins: Reference[] = [];\n const superClass = getSuperClassAndMixins(expression, mixins, analyzer);\n return {\n superClass: isMixinClass ? undefined : superClass,\n mixins,\n };\n};\n\nexport const getSuperClassAndMixins = (\n expression: ts.Expression,\n foundMixins: Reference[],\n analyzer: AnalyzerInterface\n): Reference | undefined => {\n // TODO(kschaaf) Could add support for inline class expressions here as well\n if (analyzer.typescript.isIdentifier(expression)) {\n return getReferenceForIdentifier(expression, analyzer);\n } else if (\n analyzer.typescript.isCallExpression(expression) &&\n analyzer.typescript.isIdentifier(expression.expression)\n ) {\n // FYI we purposely restrict to identifiers since we represent mixins\n // as references. If we want to support complex expressions in future,\n // we will need to rework that in the model.\n const mixinRef = getReferenceForIdentifier(expression.expression, analyzer);\n // We need to eagerly dereference a mixin ref to know what argument the\n // super class is passed into\n let mixin;\n\n try {\n mixin = mixinRef?.dereference(MixinDeclaration);\n } catch (_err) {\n // It wasn't a MixinDeclaration for whatever reason\n mixin = undefined;\n }\n\n // TODO (43081j): consider supporting external mixins properly at some point\n // An external mixin is one which we discovered via analysis (e.g. CEM)\n // but don't have a reference to in sources. In future, we should support\n // those as it is likely we will pull most dependencies from manifest\n // analysis rather than source.\n // See issue #4492\n if (mixinRef === undefined || mixin === undefined) {\n analyzer.addDiagnostic(\n createDiagnostic({\n typescript: analyzer.typescript,\n node: expression,\n message:\n `This is presumed to be a mixin but it could not be found ` +\n `in the current project. Mixins imported from outside the ` +\n `project are not yet supported ` +\n `(see https://github.com/lit/lit/issues/4492).`,\n code: DiagnosticCode.UNSUPPORTED,\n category: analyzer.typescript.DiagnosticCategory.Warning,\n })\n );\n return undefined;\n }\n foundMixins.push(mixinRef);\n const superArg = expression.arguments[mixin.superClassArgIndex];\n const superClass = getSuperClassAndMixins(superArg, foundMixins, analyzer);\n return superClass;\n }\n analyzer.addDiagnostic(\n createDiagnostic({\n typescript: analyzer.typescript,\n node: expression,\n message: `Expected expression to be a concrete superclass or mixin.`,\n code: DiagnosticCode.UNSUPPORTED,\n category: analyzer.typescript.DiagnosticCategory.Warning,\n })\n );\n return undefined;\n};\n\nexport const isConstructorFieldInitializer = (\n expression: ts.Expression,\n typescript: typeof ts\n): expression is ConstructorFieldInitializer => {\n return (\n typescript.isBinaryExpression(expression) &&\n expression.operatorToken.kind === typescript.SyntaxKind.EqualsToken &&\n typescript.isPropertyAccessExpression(expression.left) &&\n expression.left.expression.kind === typescript.SyntaxKind.ThisKeyword\n );\n};\n\ntype ConstructorFieldInitializer = ts.AssignmentExpression<ts.EqualsToken> & {\n left: ts.PropertyAccessExpression & {expression: ts.ThisExpression};\n};\n\nexport const maybeGetAppliedMixin = (\n expression: ts.Expression,\n identifier: ts.Identifier,\n analyzer: AnalyzerInterface\n): ClassDeclaration | undefined => {\n if (\n analyzer.typescript.isCallExpression(expression) &&\n analyzer.typescript.isIdentifier(expression.expression)\n ) {\n const mixinRef = getReferenceForIdentifier(expression.expression, analyzer);\n\n try {\n mixinRef?.dereference(MixinDeclaration);\n } catch (_err) {\n return undefined;\n }\n\n const heritage = getHeritageFromExpression(expression, analyzer);\n\n if (heritage.superClass) {\n return new ClassDeclaration({\n name: identifier.text,\n node: expression,\n getHeritage: () => heritage,\n });\n }\n }\n return undefined;\n};\n"]}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022 Google LLC
4
+ * SPDX-License-Identifier: BSD-3-Clause
5
+ */
6
+ /**
7
+ * @fileoverview
8
+ *
9
+ * Utilities for analyzing function declarations
10
+ */
11
+ import type ts from 'typescript';
12
+ import { AnalyzerInterface, DeclarationInfo, FunctionDeclaration, FunctionLikeInit } from '../model.js';
13
+ export type TypeScript = typeof ts;
14
+ export declare const getFunctionDeclarationInfo: (declaration: ts.FunctionDeclaration, analyzer: AnalyzerInterface) => DeclarationInfo | undefined;
15
+ /**
16
+ * Returns an analyzer `FunctionDeclaration` model for the given
17
+ * ts.FunctionLikeDeclaration.
18
+ *
19
+ * If this is a mixin function, the return value will be a `MixinDeclaration`
20
+ * model instead.
21
+ *
22
+ * Note, the `docNode` may differ from the `declaration` in the case of a const
23
+ * assignment to a class expression, as the JSDoc will be attached to the
24
+ * VariableStatement rather than the class-like expression.
25
+ */
26
+ export declare const getFunctionDeclaration: (declaration: ts.FunctionLikeDeclaration, name: string, analyzer: AnalyzerInterface, docNode?: ts.Node) => FunctionDeclaration;
27
+ /**
28
+ * Returns information on FunctionLike nodes
29
+ */
30
+ export declare const getFunctionLikeInfo: (node: ts.FunctionLikeDeclaration, name: string, analyzer: AnalyzerInterface) => FunctionLikeInit;
31
+ //# sourceMappingURL=functions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"functions.d.ts","sourceRoot":"","sources":["../../src/lib/javascript/functions.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAEjC,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,mBAAmB,EACnB,gBAAgB,EAKjB,MAAM,aAAa,CAAC;AAMrB,MAAM,MAAM,UAAU,GAAG,OAAO,EAAE,CAAC;AA6BnC,eAAO,MAAM,0BAA0B,GACrC,aAAa,EAAE,CAAC,mBAAmB,EACnC,UAAU,iBAAiB,KAC1B,eAAe,GAAG,SAWpB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,sBAAsB,GACjC,aAAa,EAAE,CAAC,uBAAuB,EACvC,MAAM,MAAM,EACZ,UAAU,iBAAiB,EAC3B,UAAU,EAAE,CAAC,IAAI,KAChB,mBAmBF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,mBAAmB,GAC9B,MAAM,EAAE,CAAC,uBAAuB,EAChC,MAAM,MAAM,EACZ,UAAU,iBAAiB,KAC1B,gBAkCF,CAAC"}
@@ -0,0 +1,144 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022 Google LLC
4
+ * SPDX-License-Identifier: BSD-3-Clause
5
+ */
6
+ import { createDiagnostic } from '../errors.js';
7
+ import { FunctionDeclaration, FunctionOverloadDeclaration, MixinDeclaration, } from '../model.js';
8
+ import { getTypeForNode, getTypeForType } from '../types.js';
9
+ import { maybeGetMixinFromFunctionLike } from './mixins.js';
10
+ import { parseJSDocDescription, parseNodeJSDocInfo } from './jsdoc.js';
11
+ import { hasDefaultModifier, hasExportModifier } from '../utils.js';
12
+ /**
13
+ * Returns the name of a function declaration.
14
+ */
15
+ const getFunctionDeclarationName = (declaration, analyzer) => {
16
+ const name = declaration.name?.text ??
17
+ // The only time a function declaration will not have a name is when it is
18
+ // a default export, aka `export default function() {...}`
19
+ (hasDefaultModifier(analyzer.typescript, declaration)
20
+ ? 'default'
21
+ : undefined);
22
+ if (name === undefined) {
23
+ analyzer.addDiagnostic(createDiagnostic({
24
+ typescript: analyzer.typescript,
25
+ node: declaration,
26
+ message: 'Illegal syntax: expected every function declaration to either have a name or be a default export',
27
+ }));
28
+ }
29
+ return name;
30
+ };
31
+ export const getFunctionDeclarationInfo = (declaration, analyzer) => {
32
+ const name = getFunctionDeclarationName(declaration, analyzer);
33
+ if (name === undefined) {
34
+ return undefined;
35
+ }
36
+ return {
37
+ name,
38
+ node: declaration,
39
+ factory: () => getFunctionDeclaration(declaration, name, analyzer),
40
+ isExport: hasExportModifier(analyzer.typescript, declaration),
41
+ };
42
+ };
43
+ /**
44
+ * Returns an analyzer `FunctionDeclaration` model for the given
45
+ * ts.FunctionLikeDeclaration.
46
+ *
47
+ * If this is a mixin function, the return value will be a `MixinDeclaration`
48
+ * model instead.
49
+ *
50
+ * Note, the `docNode` may differ from the `declaration` in the case of a const
51
+ * assignment to a class expression, as the JSDoc will be attached to the
52
+ * VariableStatement rather than the class-like expression.
53
+ */
54
+ export const getFunctionDeclaration = (declaration, name, analyzer, docNode) => {
55
+ const mixinDeclarationInfo = maybeGetMixinFromFunctionLike(declaration, name, analyzer);
56
+ if (mixinDeclarationInfo !== undefined) {
57
+ return new MixinDeclaration({
58
+ ...mixinDeclarationInfo,
59
+ ...parseNodeJSDocInfo(docNode ?? declaration, analyzer),
60
+ ...getFunctionLikeInfo(declaration, name, analyzer),
61
+ });
62
+ }
63
+ return new FunctionDeclaration({
64
+ ...parseNodeJSDocInfo(docNode ?? declaration, analyzer),
65
+ ...getFunctionLikeInfo(declaration, name, analyzer),
66
+ });
67
+ };
68
+ /**
69
+ * Returns information on FunctionLike nodes
70
+ */
71
+ export const getFunctionLikeInfo = (node, name, analyzer) => {
72
+ let overloads = undefined;
73
+ if (node.body) {
74
+ // Overloaded functions have multiple declaration nodes.
75
+ const type = analyzer.program.getTypeChecker().getTypeAtLocation(node);
76
+ const overloadDeclarations = type
77
+ .getSymbol()
78
+ ?.getDeclarations()
79
+ ?.filter((x) => x !== node);
80
+ overloads = overloadDeclarations?.map((overload) => {
81
+ const info = getFunctionLikeInfo(overload, name, analyzer);
82
+ return new FunctionOverloadDeclaration({
83
+ // `docNode ?? overload` isn't needed here because TS doesn't allow
84
+ // const function assignments to be overloaded as of now.
85
+ ...parseNodeJSDocInfo(overload, analyzer),
86
+ // `info` can't be spread because `FunctionLikeInit` has an `overloads`
87
+ // property, even though it's always `undefined` in this case.
88
+ name: info.name,
89
+ parameters: info.parameters,
90
+ return: info.return,
91
+ node: overload,
92
+ });
93
+ });
94
+ }
95
+ return {
96
+ name,
97
+ parameters: node.parameters.map((p) => getParameter(p, analyzer)),
98
+ return: getReturn(node, analyzer),
99
+ overloads,
100
+ node,
101
+ };
102
+ };
103
+ const getParameter = (param, analyzer) => {
104
+ const paramTag = analyzer.typescript.getAllJSDocTagsOfKind(param, analyzer.typescript.SyntaxKind.JSDocParameterTag)[0];
105
+ const p = {
106
+ name: param.name.getText(),
107
+ node: param,
108
+ type: getTypeForNode(param, analyzer),
109
+ ...(paramTag ? parseJSDocDescription(paramTag, analyzer) : {}),
110
+ optional: false,
111
+ rest: false,
112
+ };
113
+ if (param.initializer !== undefined) {
114
+ p.optional = true;
115
+ p.default = param.initializer.getText();
116
+ }
117
+ if (param.questionToken !== undefined) {
118
+ p.optional = true;
119
+ }
120
+ if (param.dotDotDotToken !== undefined) {
121
+ p.rest = true;
122
+ }
123
+ return p;
124
+ };
125
+ const getReturn = (node, analyzer) => {
126
+ const returnTag = analyzer.typescript.getAllJSDocTagsOfKind(node, analyzer.typescript.SyntaxKind.JSDocReturnTag)[0];
127
+ const signature = analyzer.program
128
+ .getTypeChecker()
129
+ .getSignatureFromDeclaration(node);
130
+ if (signature === undefined) {
131
+ // TODO: when does this happen? is it actionable for the user? if so, how?
132
+ analyzer.addDiagnostic(createDiagnostic({
133
+ typescript: analyzer.typescript,
134
+ node,
135
+ message: `Could not get signature to determine return type`,
136
+ }));
137
+ return undefined;
138
+ }
139
+ return {
140
+ type: getTypeForType(signature.getReturnType(), node, analyzer),
141
+ ...(returnTag ? parseJSDocDescription(returnTag, analyzer) : {}),
142
+ };
143
+ };
144
+ //# sourceMappingURL=functions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"functions.js","sourceRoot":"","sources":["../../src/lib/javascript/functions.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license\n * Copyright 2022 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\n/**\n * @fileoverview\n *\n * Utilities for analyzing function declarations\n */\n\nimport type ts from 'typescript';\nimport {createDiagnostic} from '../errors.js';\nimport {\n AnalyzerInterface,\n DeclarationInfo,\n FunctionDeclaration,\n FunctionLikeInit,\n FunctionOverloadDeclaration,\n Parameter,\n Return,\n MixinDeclaration,\n} from '../model.js';\nimport {getTypeForNode, getTypeForType} from '../types.js';\nimport {maybeGetMixinFromFunctionLike} from './mixins.js';\nimport {parseJSDocDescription, parseNodeJSDocInfo} from './jsdoc.js';\nimport {hasDefaultModifier, hasExportModifier} from '../utils.js';\n\nexport type TypeScript = typeof ts;\n\n/**\n * Returns the name of a function declaration.\n */\nconst getFunctionDeclarationName = (\n declaration: ts.FunctionDeclaration,\n analyzer: AnalyzerInterface\n) => {\n const name =\n declaration.name?.text ??\n // The only time a function declaration will not have a name is when it is\n // a default export, aka `export default function() {...}`\n (hasDefaultModifier(analyzer.typescript, declaration)\n ? 'default'\n : undefined);\n if (name === undefined) {\n analyzer.addDiagnostic(\n createDiagnostic({\n typescript: analyzer.typescript,\n node: declaration,\n message:\n 'Illegal syntax: expected every function declaration to either have a name or be a default export',\n })\n );\n }\n return name;\n};\n\nexport const getFunctionDeclarationInfo = (\n declaration: ts.FunctionDeclaration,\n analyzer: AnalyzerInterface\n): DeclarationInfo | undefined => {\n const name = getFunctionDeclarationName(declaration, analyzer);\n if (name === undefined) {\n return undefined;\n }\n return {\n name,\n node: declaration,\n factory: () => getFunctionDeclaration(declaration, name, analyzer),\n isExport: hasExportModifier(analyzer.typescript, declaration),\n };\n};\n\n/**\n * Returns an analyzer `FunctionDeclaration` model for the given\n * ts.FunctionLikeDeclaration.\n *\n * If this is a mixin function, the return value will be a `MixinDeclaration`\n * model instead.\n *\n * Note, the `docNode` may differ from the `declaration` in the case of a const\n * assignment to a class expression, as the JSDoc will be attached to the\n * VariableStatement rather than the class-like expression.\n */\nexport const getFunctionDeclaration = (\n declaration: ts.FunctionLikeDeclaration,\n name: string,\n analyzer: AnalyzerInterface,\n docNode?: ts.Node\n): FunctionDeclaration => {\n const mixinDeclarationInfo = maybeGetMixinFromFunctionLike(\n declaration,\n name,\n analyzer\n );\n\n if (mixinDeclarationInfo !== undefined) {\n return new MixinDeclaration({\n ...mixinDeclarationInfo,\n ...parseNodeJSDocInfo(docNode ?? declaration, analyzer),\n ...getFunctionLikeInfo(declaration, name, analyzer),\n });\n }\n\n return new FunctionDeclaration({\n ...parseNodeJSDocInfo(docNode ?? declaration, analyzer),\n ...getFunctionLikeInfo(declaration, name, analyzer),\n });\n};\n\n/**\n * Returns information on FunctionLike nodes\n */\nexport const getFunctionLikeInfo = (\n node: ts.FunctionLikeDeclaration,\n name: string,\n analyzer: AnalyzerInterface\n): FunctionLikeInit => {\n let overloads = undefined;\n if (node.body) {\n // Overloaded functions have multiple declaration nodes.\n const type = analyzer.program.getTypeChecker().getTypeAtLocation(node);\n const overloadDeclarations = type\n .getSymbol()\n ?.getDeclarations()\n ?.filter((x) => x !== node) as Array<ts.FunctionLikeDeclaration>;\n\n overloads = overloadDeclarations?.map((overload) => {\n const info = getFunctionLikeInfo(overload, name, analyzer);\n return new FunctionOverloadDeclaration({\n // `docNode ?? overload` isn't needed here because TS doesn't allow\n // const function assignments to be overloaded as of now.\n ...parseNodeJSDocInfo(overload, analyzer),\n\n // `info` can't be spread because `FunctionLikeInit` has an `overloads`\n // property, even though it's always `undefined` in this case.\n name: info.name,\n parameters: info.parameters,\n return: info.return,\n node: overload,\n });\n });\n }\n\n return {\n name,\n parameters: node.parameters.map((p) => getParameter(p, analyzer)),\n return: getReturn(node, analyzer),\n overloads,\n node,\n };\n};\n\nconst getParameter = (\n param: ts.ParameterDeclaration,\n analyzer: AnalyzerInterface\n): Parameter => {\n const paramTag = analyzer.typescript.getAllJSDocTagsOfKind(\n param,\n analyzer.typescript.SyntaxKind.JSDocParameterTag\n )[0];\n const p: Parameter = {\n name: param.name.getText(),\n node: param,\n type: getTypeForNode(param, analyzer),\n ...(paramTag ? parseJSDocDescription(paramTag, analyzer) : {}),\n optional: false,\n rest: false,\n };\n if (param.initializer !== undefined) {\n p.optional = true;\n p.default = param.initializer.getText();\n }\n if (param.questionToken !== undefined) {\n p.optional = true;\n }\n if (param.dotDotDotToken !== undefined) {\n p.rest = true;\n }\n return p;\n};\n\nconst getReturn = (\n node: ts.FunctionLikeDeclaration,\n analyzer: AnalyzerInterface\n): Return | undefined => {\n const returnTag = analyzer.typescript.getAllJSDocTagsOfKind(\n node,\n analyzer.typescript.SyntaxKind.JSDocReturnTag\n )[0];\n const signature = analyzer.program\n .getTypeChecker()\n .getSignatureFromDeclaration(node);\n if (signature === undefined) {\n // TODO: when does this happen? is it actionable for the user? if so, how?\n analyzer.addDiagnostic(\n createDiagnostic({\n typescript: analyzer.typescript,\n node,\n message: `Could not get signature to determine return type`,\n })\n );\n return undefined;\n }\n return {\n type: getTypeForType(signature.getReturnType(), node, analyzer),\n ...(returnTag ? parseJSDocDescription(returnTag, analyzer) : {}),\n };\n};\n"]}