@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
package/lib/types.js ADDED
@@ -0,0 +1,257 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022 Google LLC
4
+ * SPDX-License-Identifier: BSD-3-Clause
5
+ */
6
+ import { getPackageInfo } from './javascript/packages.js';
7
+ import { Type } from './model.js';
8
+ import { absoluteToPackage, resolveExtension, } from './paths.js';
9
+ import { getImportReference, getReferenceForSymbol, getSymbolForName, } from './references.js';
10
+ import { createDiagnostic } from './errors.js';
11
+ /**
12
+ * Returns an analyzer `Type` object for the given type string,
13
+ * evaluated at the given location.
14
+ *
15
+ * Used for parsing types from JSDoc.
16
+ */
17
+ export const getTypeForTypeString = (typeString, location, analyzer) => {
18
+ const { typescript, program } = analyzer;
19
+ if (typeString !== undefined) {
20
+ const typeNode = parseType(typescript, typeString);
21
+ if (typeNode == undefined) {
22
+ analyzer.addDiagnostic(createDiagnostic({
23
+ typescript,
24
+ node: location,
25
+ message: `Failed to parse type from JSDoc comment.`,
26
+ category: typescript.DiagnosticCategory.Warning,
27
+ }));
28
+ return undefined;
29
+ }
30
+ const type = program.getTypeChecker().getTypeFromTypeNode(typeNode);
31
+ return new Type({
32
+ type,
33
+ text: typeString,
34
+ getReferences: () => getReferencesForTypeNode(typeNode, location, analyzer),
35
+ });
36
+ }
37
+ else {
38
+ return undefined;
39
+ }
40
+ };
41
+ /**
42
+ * Returns an analyzer `Type` object for the given AST node.
43
+ */
44
+ export const getTypeForNode = (node, analyzer) => {
45
+ return getTypeForType(analyzer.program.getTypeChecker().getTypeAtLocation(node), node, analyzer);
46
+ };
47
+ /**
48
+ * Converts a ts.Type into an analyzer Type object (which wraps
49
+ * the ts.Type, but also provides analyzer Reference objects).
50
+ */
51
+ export const getTypeForType = (type, location, analyzer) => {
52
+ const { typescript } = analyzer;
53
+ const checker = analyzer.program.getTypeChecker();
54
+ // Ensure we treat inferred `foo = 'hi'` as 'string' not '"hi"',
55
+ // but retain explicitly defined unions
56
+ if (!type.isUnion()) {
57
+ type = checker.getBaseTypeOfLiteralType(type);
58
+ }
59
+ const text = checker.typeToString(type);
60
+ const typeNode = checker.typeToTypeNode(type, location, typescript.NodeBuilderFlags.IgnoreErrors);
61
+ let getReferences;
62
+ if (typeNode === undefined) {
63
+ analyzer.addDiagnostic(createDiagnostic({
64
+ typescript,
65
+ node: location,
66
+ message: `Could not convert type to type node`,
67
+ category: typescript.DiagnosticCategory.Warning,
68
+ }));
69
+ getReferences = () => [];
70
+ }
71
+ else {
72
+ getReferences = () => getReferencesForTypeNode(typeNode, location, analyzer);
73
+ }
74
+ return new Type({
75
+ type,
76
+ text,
77
+ getReferences,
78
+ });
79
+ };
80
+ /**
81
+ * For a given TypeNode syntax tree, walk the AST and extract Reference
82
+ * model objects for any TypeReferenceNode or ImportTypeNode's.
83
+ */
84
+ const getReferencesForTypeNode = (typeNode, location, analyzer) => {
85
+ const { typescript } = analyzer;
86
+ const references = [];
87
+ const visit = (node) => {
88
+ if (typescript.isTypeReferenceNode(node)) {
89
+ const name = getRootName(typescript, node.typeName);
90
+ // TODO(kschaaf): we'd like to just do
91
+ // `checker.getSymbolAtLocation(node)` to get the symbol, but it appears
92
+ // that nodes created with `checker.typeToTypeNode()` do not have
93
+ // associated symbols, so we need to look up by name via
94
+ // `checker.getSymbolsInScope()`
95
+ const symbol = getSymbolForName(name, location, analyzer);
96
+ if (symbol === undefined) {
97
+ analyzer.addDiagnostic(createDiagnostic({
98
+ typescript,
99
+ node: location,
100
+ message: `Could not get symbol for '${name}'.`,
101
+ }));
102
+ return;
103
+ }
104
+ const ref = getReferenceForSymbol(symbol, location, analyzer);
105
+ if (ref !== undefined) {
106
+ references.push(ref);
107
+ }
108
+ }
109
+ else if (typescript.isImportTypeNode(node)) {
110
+ if (!typescript.isLiteralTypeNode(node.argument)) {
111
+ analyzer.addDiagnostic(createDiagnostic({
112
+ typescript,
113
+ node: node.argument,
114
+ message: 'Expected a string literal.',
115
+ }));
116
+ return;
117
+ }
118
+ const name = getRootName(typescript, node.qualifier);
119
+ if (!typescript.isStringLiteral(node.argument.literal)) {
120
+ analyzer.addDiagnostic(createDiagnostic({
121
+ typescript,
122
+ node: node.argument.literal,
123
+ message: `Expected import specifier to be a string literal`,
124
+ }));
125
+ return;
126
+ }
127
+ const specifier = getSpecifierFromTypeImport(node.argument.literal.text, analyzer);
128
+ // TODO(kschaaf): This may have been an inferred type from a transitive
129
+ // dependency; in this case we should include version information in the
130
+ // reference model
131
+ references.push(getImportReference(specifier, node.argument.literal, name, analyzer));
132
+ }
133
+ typescript.forEachChild(node, visit);
134
+ };
135
+ visit(typeNode);
136
+ return references;
137
+ };
138
+ /**
139
+ * If the given specifier is an absolute path, turns it into an npm import
140
+ * specifier by looking for its package.json and using package information found
141
+ * there.
142
+ *
143
+ * If the path was not absolute, it returns the specifier as-is.
144
+ */
145
+ const getSpecifierFromTypeImport = (specifier, analyzer) => {
146
+ specifier = analyzer.path.normalize(
147
+ // Types can resolve to source or declaration files, so include those
148
+ // extensions as well. We still include JS extensions to support JSDoc
149
+ // types.
150
+ // We don't include the CommonJS-only extensions .cts and .d.cts here
151
+ resolveExtension(specifier, analyzer, [
152
+ 'js',
153
+ 'mjs',
154
+ 'ts',
155
+ 'mts',
156
+ 'tsx',
157
+ 'jsx',
158
+ 'd.ts',
159
+ 'd.mts',
160
+ ]));
161
+ if (analyzer.path.isAbsolute(specifier)) {
162
+ const { rootDir, name, packageJson: { main, module }, } = getPackageInfo(specifier, analyzer);
163
+ let modulePath = absoluteToPackage(specifier, rootDir, analyzer.path.sep);
164
+ const packageMain = module ?? main;
165
+ if (packageMain !== undefined && modulePath === packageMain) {
166
+ modulePath = '';
167
+ }
168
+ specifier = name + (modulePath ? `/${modulePath}` : '');
169
+ }
170
+ return specifier;
171
+ };
172
+ /**
173
+ * Gets the left-most name of a (possibly qualified) identifier, i.e.
174
+ * 'Foo' returns 'Foo', but 'ts.SyntaxKind' returns 'ts'. This is the
175
+ * symbol that would need to be imported into a given scope.
176
+ */
177
+ const getRootName = (typescript, name) => {
178
+ if (name === undefined) {
179
+ return '';
180
+ }
181
+ if (typescript.isQualifiedName(name)) {
182
+ return getRootName(typescript, name.left);
183
+ }
184
+ else {
185
+ return name.text;
186
+ }
187
+ };
188
+ /**
189
+ * Below is a minimal LanguageService that allows quickly parsing snippets of TS
190
+ * syntax into an AST. There's one file `contents.ts` in the program that we
191
+ * update with snippets to parse.
192
+ *
193
+ * This allows extracting a type string from a custom JSDoc comment (like
194
+ * `@event`), parsing it into syntax, and than walking it to extract references.
195
+ *
196
+ * Note, the program may have semantic errors (e.g. it may reference imports
197
+ * that aren't included in the snippet), but that's ok because we only care
198
+ * about parsing the syntax. When extracting references, we can use
199
+ * `getSymbolByName` to re-associate symbols by name from a disassociated syntax
200
+ * tree and the actual program.
201
+ *
202
+ * TODO(kschaaf): Providing diagnostic errors for semantically incorrect custom
203
+ * JSDoc types would be nice, but that's pretty difficult in analyzers
204
+ * where we don't control the TS program creation such that we can re-write
205
+ * source files, etc. (as is the case when using in plugins).
206
+ */
207
+ let contents = '';
208
+ let contentsId = 0;
209
+ const services = new WeakMap();
210
+ const getService = (typescript) => {
211
+ let service = services.get(typescript);
212
+ if (service === undefined) {
213
+ service = typescript.createLanguageService({
214
+ getScriptFileNames: () => ['contents.ts'],
215
+ getScriptVersion: () => contentsId.toString(),
216
+ getScriptSnapshot: () => typescript.ScriptSnapshot.fromString(contents),
217
+ getCurrentDirectory: () => '',
218
+ getCompilationSettings: () => ({ include: ['contents.ts'] }),
219
+ getDefaultLibFileName: (options) => typescript.getDefaultLibFilePath(options),
220
+ fileExists: () => true,
221
+ readFile: () => undefined,
222
+ readDirectory: () => [],
223
+ directoryExists: () => true,
224
+ getDirectories: () => [],
225
+ }, typescript.createDocumentRegistry());
226
+ services.set(typescript, service);
227
+ }
228
+ return service;
229
+ };
230
+ /**
231
+ * Uses the stub LSH above to parse a type string and return a syntax-only
232
+ * TypeNode (there will be no valid symbol information retrievable directly from
233
+ * these nodes).
234
+ */
235
+ // TODO (justinfagnani): This would probably be a bit cleaner as an instance
236
+ // method on Analyzer now.
237
+ const parseType = (typescript, typeString) => {
238
+ // Update the file
239
+ contents = `export type typeToParse = ${typeString}`;
240
+ contentsId++;
241
+ // Get a new program & parsed source file
242
+ const sourceFile = getService(typescript)
243
+ .getProgram()
244
+ ?.getSourceFileByPath('contents.ts');
245
+ if (sourceFile === undefined) {
246
+ return undefined;
247
+ }
248
+ // Find the type alias node and return it
249
+ let typeNode = undefined;
250
+ typescript.forEachChild(sourceFile, (node) => {
251
+ if (typescript.isTypeAliasDeclaration(node)) {
252
+ typeNode = node.type;
253
+ }
254
+ });
255
+ return typeNode;
256
+ };
257
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/lib/types.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license\n * Copyright 2022 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\nimport type ts from 'typescript';\nimport {getPackageInfo} from './javascript/packages.js';\nimport {Type, Reference, AnalyzerInterface} from './model.js';\nimport {\n AbsolutePath,\n absoluteToPackage,\n PackagePath,\n resolveExtension,\n} from './paths.js';\nimport {\n getImportReference,\n getReferenceForSymbol,\n getSymbolForName,\n} from './references.js';\nimport {createDiagnostic} from './errors.js';\n\nexport type TypeScript = typeof ts;\n\n/**\n * Returns an analyzer `Type` object for the given type string,\n * evaluated at the given location.\n *\n * Used for parsing types from JSDoc.\n */\nexport const getTypeForTypeString = (\n typeString: string,\n location: ts.Node,\n analyzer: AnalyzerInterface\n): Type | undefined => {\n const {typescript, program} = analyzer;\n if (typeString !== undefined) {\n const typeNode = parseType(typescript, typeString);\n if (typeNode == undefined) {\n analyzer.addDiagnostic(\n createDiagnostic({\n typescript,\n node: location,\n message: `Failed to parse type from JSDoc comment.`,\n category: typescript.DiagnosticCategory.Warning,\n })\n );\n return undefined;\n }\n const type = program.getTypeChecker().getTypeFromTypeNode(typeNode);\n return new Type({\n type,\n text: typeString,\n getReferences: () =>\n getReferencesForTypeNode(typeNode, location, analyzer),\n });\n } else {\n return undefined;\n }\n};\n\n/**\n * Returns an analyzer `Type` object for the given AST node.\n */\nexport const getTypeForNode = (\n node: ts.Node,\n analyzer: AnalyzerInterface\n): Type => {\n return getTypeForType(\n analyzer.program.getTypeChecker().getTypeAtLocation(node),\n node,\n analyzer\n );\n};\n\n/**\n * Converts a ts.Type into an analyzer Type object (which wraps\n * the ts.Type, but also provides analyzer Reference objects).\n */\nexport const getTypeForType = (\n type: ts.Type,\n location: ts.Node,\n analyzer: AnalyzerInterface\n): Type => {\n const {typescript} = analyzer;\n const checker = analyzer.program.getTypeChecker();\n // Ensure we treat inferred `foo = 'hi'` as 'string' not '\"hi\"',\n // but retain explicitly defined unions\n if (!type.isUnion()) {\n type = checker.getBaseTypeOfLiteralType(type);\n }\n const text = checker.typeToString(type);\n const typeNode = checker.typeToTypeNode(\n type,\n location,\n typescript.NodeBuilderFlags.IgnoreErrors\n );\n let getReferences;\n if (typeNode === undefined) {\n analyzer.addDiagnostic(\n createDiagnostic({\n typescript,\n node: location,\n message: `Could not convert type to type node`,\n category: typescript.DiagnosticCategory.Warning,\n })\n );\n getReferences = () => [];\n } else {\n getReferences = () =>\n getReferencesForTypeNode(typeNode, location, analyzer);\n }\n return new Type({\n type,\n text,\n getReferences,\n });\n};\n\n/**\n * For a given TypeNode syntax tree, walk the AST and extract Reference\n * model objects for any TypeReferenceNode or ImportTypeNode's.\n */\nconst getReferencesForTypeNode = (\n typeNode: ts.TypeNode,\n location: ts.Node,\n analyzer: AnalyzerInterface\n): Reference[] => {\n const {typescript} = analyzer;\n const references: Reference[] = [];\n const visit = (node: ts.Node) => {\n if (typescript.isTypeReferenceNode(node)) {\n const name = getRootName(typescript, node.typeName);\n // TODO(kschaaf): we'd like to just do\n // `checker.getSymbolAtLocation(node)` to get the symbol, but it appears\n // that nodes created with `checker.typeToTypeNode()` do not have\n // associated symbols, so we need to look up by name via\n // `checker.getSymbolsInScope()`\n const symbol = getSymbolForName(name, location, analyzer);\n if (symbol === undefined) {\n analyzer.addDiagnostic(\n createDiagnostic({\n typescript,\n node: location,\n message: `Could not get symbol for '${name}'.`,\n })\n );\n return;\n }\n const ref = getReferenceForSymbol(symbol, location, analyzer);\n if (ref !== undefined) {\n references.push(ref);\n }\n } else if (typescript.isImportTypeNode(node)) {\n if (!typescript.isLiteralTypeNode(node.argument)) {\n analyzer.addDiagnostic(\n createDiagnostic({\n typescript,\n node: node.argument,\n message: 'Expected a string literal.',\n })\n );\n return;\n }\n const name = getRootName(typescript, node.qualifier);\n if (!typescript.isStringLiteral(node.argument.literal)) {\n analyzer.addDiagnostic(\n createDiagnostic({\n typescript,\n node: node.argument.literal,\n message: `Expected import specifier to be a string literal`,\n })\n );\n return;\n }\n const specifier = getSpecifierFromTypeImport(\n node.argument.literal.text,\n analyzer\n );\n // TODO(kschaaf): This may have been an inferred type from a transitive\n // dependency; in this case we should include version information in the\n // reference model\n references.push(\n getImportReference(specifier, node.argument.literal, name, analyzer)\n );\n }\n typescript.forEachChild(node, visit);\n };\n visit(typeNode);\n return references;\n};\n\n/**\n * If the given specifier is an absolute path, turns it into an npm import\n * specifier by looking for its package.json and using package information found\n * there.\n *\n * If the path was not absolute, it returns the specifier as-is.\n */\nconst getSpecifierFromTypeImport = (\n specifier: string,\n analyzer: AnalyzerInterface\n) => {\n specifier = analyzer.path.normalize(\n // Types can resolve to source or declaration files, so include those\n // extensions as well. We still include JS extensions to support JSDoc\n // types.\n // We don't include the CommonJS-only extensions .cts and .d.cts here\n resolveExtension(specifier as AbsolutePath, analyzer, [\n 'js',\n 'mjs',\n 'ts',\n 'mts',\n 'tsx',\n 'jsx',\n 'd.ts',\n 'd.mts',\n ])\n );\n if (analyzer.path.isAbsolute(specifier)) {\n const {\n rootDir,\n name,\n packageJson: {main, module},\n } = getPackageInfo(specifier as AbsolutePath, analyzer);\n let modulePath = absoluteToPackage(\n specifier as AbsolutePath,\n rootDir,\n analyzer.path.sep\n );\n const packageMain = module ?? main;\n if (packageMain !== undefined && modulePath === packageMain) {\n modulePath = '' as PackagePath;\n }\n specifier = name + (modulePath ? `/${modulePath}` : '');\n }\n return specifier;\n};\n\n/**\n * Gets the left-most name of a (possibly qualified) identifier, i.e.\n * 'Foo' returns 'Foo', but 'ts.SyntaxKind' returns 'ts'. This is the\n * symbol that would need to be imported into a given scope.\n */\nconst getRootName = (\n typescript: TypeScript,\n name: ts.Identifier | ts.QualifiedName | undefined\n): string => {\n if (name === undefined) {\n return '';\n }\n if (typescript.isQualifiedName(name)) {\n return getRootName(typescript, name.left);\n } else {\n return name.text;\n }\n};\n\n/**\n * Below is a minimal LanguageService that allows quickly parsing snippets of TS\n * syntax into an AST. There's one file `contents.ts` in the program that we\n * update with snippets to parse.\n *\n * This allows extracting a type string from a custom JSDoc comment (like\n * `@event`), parsing it into syntax, and than walking it to extract references.\n *\n * Note, the program may have semantic errors (e.g. it may reference imports\n * that aren't included in the snippet), but that's ok because we only care\n * about parsing the syntax. When extracting references, we can use\n * `getSymbolByName` to re-associate symbols by name from a disassociated syntax\n * tree and the actual program.\n *\n * TODO(kschaaf): Providing diagnostic errors for semantically incorrect custom\n * JSDoc types would be nice, but that's pretty difficult in analyzers\n * where we don't control the TS program creation such that we can re-write\n * source files, etc. (as is the case when using in plugins).\n */\n\nlet contents = '';\nlet contentsId = 0;\n\nconst services = new WeakMap<TypeScript, ts.LanguageService>();\nconst getService = (typescript: TypeScript) => {\n let service = services.get(typescript);\n if (service === undefined) {\n service = typescript.createLanguageService(\n {\n getScriptFileNames: () => ['contents.ts'],\n getScriptVersion: () => contentsId.toString(),\n getScriptSnapshot: () => typescript.ScriptSnapshot.fromString(contents),\n getCurrentDirectory: () => '',\n getCompilationSettings: () => ({include: ['contents.ts']}),\n getDefaultLibFileName: (options) =>\n typescript.getDefaultLibFilePath(options),\n fileExists: () => true,\n readFile: () => undefined,\n readDirectory: () => [],\n directoryExists: () => true,\n getDirectories: () => [],\n },\n typescript.createDocumentRegistry()\n );\n services.set(typescript, service);\n }\n return service;\n};\n\n/**\n * Uses the stub LSH above to parse a type string and return a syntax-only\n * TypeNode (there will be no valid symbol information retrievable directly from\n * these nodes).\n */\n// TODO (justinfagnani): This would probably be a bit cleaner as an instance\n// method on Analyzer now.\nconst parseType = (\n typescript: TypeScript,\n typeString: string\n): ts.TypeNode | undefined => {\n // Update the file\n contents = `export type typeToParse = ${typeString}`;\n contentsId++;\n // Get a new program & parsed source file\n const sourceFile = getService(typescript)\n .getProgram()\n ?.getSourceFileByPath('contents.ts' as ts.Path);\n if (sourceFile === undefined) {\n return undefined;\n }\n // Find the type alias node and return it\n let typeNode: ts.TypeNode | undefined = undefined;\n typescript.forEachChild(sourceFile, (node) => {\n if (typescript.isTypeAliasDeclaration(node)) {\n typeNode = node.type;\n }\n });\n return typeNode;\n};\n"]}
package/lib/utils.d.ts ADDED
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022 Google LLC
4
+ * SPDX-License-Identifier: BSD-3-Clause
5
+ */
6
+ /**
7
+ * @fileoverview
8
+ *
9
+ * Helper utilities for analyzing declarations
10
+ */
11
+ import type ts from 'typescript';
12
+ import { Privacy } from './model.js';
13
+ export type TypeScript = typeof ts;
14
+ export declare const hasModifier: (ts: TypeScript, node: ts.HasModifiers, modifier: ts.SyntaxKind) => boolean;
15
+ export declare const hasExportModifier: (ts: TypeScript, node: ts.HasModifiers) => boolean;
16
+ export declare const hasDefaultModifier: (ts: TypeScript, node: ts.HasModifiers) => boolean;
17
+ export declare const hasStaticModifier: (ts: TypeScript, node: ts.HasModifiers) => boolean;
18
+ export declare const hasPrivateModifier: (ts: TypeScript, node: ts.HasModifiers) => boolean;
19
+ export declare const hasProtectedModifier: (ts: TypeScript, node: ts.HasModifiers) => boolean;
20
+ export declare const getPrivacy: (ts: TypeScript, node: ts.Node) => Privacy;
21
+ export declare const getBaseTypes: (type: ts.Type) => ts.BaseType[];
22
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/lib/utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAEjC,OAAO,EAAC,OAAO,EAAC,MAAM,YAAY,CAAC;AAEnC,MAAM,MAAM,UAAU,GAAG,OAAO,EAAE,CAAC;AAEnC,eAAO,MAAM,WAAW,GACtB,IAAI,UAAU,EACd,MAAM,EAAE,CAAC,YAAY,EACrB,UAAU,EAAE,CAAC,UAAU,YAGxB,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,IAAI,UAAU,EAAE,MAAM,EAAE,CAAC,YAAY,YAEtE,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,IAAI,UAAU,EAAE,MAAM,EAAE,CAAC,YAAY,YAEvE,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,IAAI,UAAU,EAAE,MAAM,EAAE,CAAC,YAAY,YAEtE,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,IAAI,UAAU,EAAE,MAAM,EAAE,CAAC,YAAY,YAEvE,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,IAAI,UAAU,EAAE,MAAM,EAAE,CAAC,YAAY,YAEzE,CAAC;AAkBF,eAAO,MAAM,UAAU,GAAI,IAAI,UAAU,EAAE,MAAM,EAAE,CAAC,IAAI,KAAG,OAM1D,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,MAAM,EAAE,CAAC,IAAI,KAAG,EAAE,CAAC,QAAQ,EAUvD,CAAC"}
package/lib/utils.js ADDED
@@ -0,0 +1,51 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022 Google LLC
4
+ * SPDX-License-Identifier: BSD-3-Clause
5
+ */
6
+ import { hasJSDocTag } from './javascript/jsdoc.js';
7
+ export const hasModifier = (ts, node, modifier) => {
8
+ return ts.getModifiers(node)?.some((s) => s.kind === modifier) ?? false;
9
+ };
10
+ export const hasExportModifier = (ts, node) => {
11
+ return hasModifier(ts, node, ts.SyntaxKind.ExportKeyword);
12
+ };
13
+ export const hasDefaultModifier = (ts, node) => {
14
+ return hasModifier(ts, node, ts.SyntaxKind.DefaultKeyword);
15
+ };
16
+ export const hasStaticModifier = (ts, node) => {
17
+ return hasModifier(ts, node, ts.SyntaxKind.StaticKeyword);
18
+ };
19
+ export const hasPrivateModifier = (ts, node) => {
20
+ return hasModifier(ts, node, ts.SyntaxKind.PrivateKeyword);
21
+ };
22
+ export const hasProtectedModifier = (ts, node) => {
23
+ return hasModifier(ts, node, ts.SyntaxKind.ProtectedKeyword);
24
+ };
25
+ const isPrivate = (ts, node) => {
26
+ return ((ts.canHaveModifiers(node) && hasPrivateModifier(ts, node)) ||
27
+ ((ts.isPropertyDeclaration(node) || ts.isMethodDeclaration(node)) &&
28
+ ts.isPrivateIdentifier(node.name)) ||
29
+ hasJSDocTag(ts, node, 'private'));
30
+ };
31
+ const isProtected = (ts, node) => {
32
+ return ((ts.canHaveModifiers(node) && hasProtectedModifier(ts, node)) ||
33
+ hasJSDocTag(ts, node, 'protected'));
34
+ };
35
+ export const getPrivacy = (ts, node) => {
36
+ return isPrivate(ts, node)
37
+ ? 'private'
38
+ : isProtected(ts, node)
39
+ ? 'protected'
40
+ : 'public';
41
+ };
42
+ export const getBaseTypes = (type) => {
43
+ if (type.isClassOrInterface()) {
44
+ return type.getBaseTypes() ?? [];
45
+ }
46
+ if (type.isIntersection()) {
47
+ return type.types.map(getBaseTypes).flat();
48
+ }
49
+ return [];
50
+ };
51
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/lib/utils.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 * Helper utilities for analyzing declarations\n */\n\nimport type ts from 'typescript';\nimport {hasJSDocTag} from './javascript/jsdoc.js';\nimport {Privacy} from './model.js';\n\nexport type TypeScript = typeof ts;\n\nexport const hasModifier = (\n ts: TypeScript,\n node: ts.HasModifiers,\n modifier: ts.SyntaxKind\n) => {\n return ts.getModifiers(node)?.some((s) => s.kind === modifier) ?? false;\n};\n\nexport const hasExportModifier = (ts: TypeScript, node: ts.HasModifiers) => {\n return hasModifier(ts, node, ts.SyntaxKind.ExportKeyword);\n};\n\nexport const hasDefaultModifier = (ts: TypeScript, node: ts.HasModifiers) => {\n return hasModifier(ts, node, ts.SyntaxKind.DefaultKeyword);\n};\n\nexport const hasStaticModifier = (ts: TypeScript, node: ts.HasModifiers) => {\n return hasModifier(ts, node, ts.SyntaxKind.StaticKeyword);\n};\n\nexport const hasPrivateModifier = (ts: TypeScript, node: ts.HasModifiers) => {\n return hasModifier(ts, node, ts.SyntaxKind.PrivateKeyword);\n};\n\nexport const hasProtectedModifier = (ts: TypeScript, node: ts.HasModifiers) => {\n return hasModifier(ts, node, ts.SyntaxKind.ProtectedKeyword);\n};\n\nconst isPrivate = (ts: TypeScript, node: ts.Node) => {\n return (\n (ts.canHaveModifiers(node) && hasPrivateModifier(ts, node)) ||\n ((ts.isPropertyDeclaration(node) || ts.isMethodDeclaration(node)) &&\n ts.isPrivateIdentifier(node.name)) ||\n hasJSDocTag(ts, node, 'private')\n );\n};\n\nconst isProtected = (ts: TypeScript, node: ts.Node) => {\n return (\n (ts.canHaveModifiers(node) && hasProtectedModifier(ts, node)) ||\n hasJSDocTag(ts, node, 'protected')\n );\n};\n\nexport const getPrivacy = (ts: TypeScript, node: ts.Node): Privacy => {\n return isPrivate(ts, node)\n ? 'private'\n : isProtected(ts, node)\n ? 'protected'\n : 'public';\n};\n\nexport const getBaseTypes = (type: ts.Type): ts.BaseType[] => {\n if (type.isClassOrInterface()) {\n return type.getBaseTypes() ?? [];\n }\n\n if (type.isIntersection()) {\n return type.types.map(getBaseTypes).flat();\n }\n\n return [];\n};\n"]}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2023 Google LLC
4
+ * SPDX-License-Identifier: BSD-3-Clause
5
+ */
6
+ export * from './index.js';
7
+ export * from './lib/package-analyzer.js';
8
+ //# sourceMappingURL=package-analyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-analyzer.d.ts","sourceRoot":"","sources":["src/package-analyzer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,2BAA2B,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2023 Google LLC
4
+ * SPDX-License-Identifier: BSD-3-Clause
5
+ */
6
+ export * from './index.js';
7
+ export * from './lib/package-analyzer.js';
8
+ //# sourceMappingURL=package-analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-analyzer.js","sourceRoot":"","sources":["src/package-analyzer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,2BAA2B,CAAC","sourcesContent":["/**\n * @license\n * Copyright 2023 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\nexport * from './index.js';\nexport * from './lib/package-analyzer.js';\n"]}
package/package.json ADDED
@@ -0,0 +1,109 @@
1
+ {
2
+ "name": "@oicl-lit/analyzer",
3
+ "version": "0.14.1",
4
+ "publishConfig": {
5
+ "access": "public"
6
+ },
7
+ "description": "A static analyzer for Lit",
8
+ "license": "BSD-3-Clause",
9
+ "author": "Google LLC",
10
+ "homepage": "https://github.com/lit/lit/tree/main/packages/labs/analyzer",
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/lit/lit.git",
14
+ "directory": "packages/labs/analyzer"
15
+ },
16
+ "main": "index.js",
17
+ "type": "module",
18
+ "scripts": {
19
+ "build": "wireit",
20
+ "test": "wireit",
21
+ "test:server": "wireit",
22
+ "test:browser": "wireit"
23
+ },
24
+ "wireit": {
25
+ "build": {
26
+ "command": "tsc --build --pretty",
27
+ "dependencies": [
28
+ "../../lit:build"
29
+ ],
30
+ "files": [
31
+ "src/**/*.ts",
32
+ "tsconfig.json"
33
+ ],
34
+ "output": [
35
+ "lib",
36
+ "test",
37
+ "index.{js,js.map,d.ts,d.ts.map}",
38
+ "package-analyzer.{js,js.map,d.ts,d.ts.map}",
39
+ "tsconfig.tsbuildinfo",
40
+ "!test/browser/typescript.js"
41
+ ],
42
+ "clean": "if-file-deleted"
43
+ },
44
+ "build:ts-bundle": {
45
+ "#comment": "This builds a JS module of typescript for use in browser tests",
46
+ "command": "rollup -c rollup.config.typescript.js",
47
+ "files": [
48
+ "rollup.config.typescript.js"
49
+ ],
50
+ "output": [
51
+ "test/browser/typescript.js"
52
+ ]
53
+ },
54
+ "test": {
55
+ "dependencies": [
56
+ "test:server",
57
+ "test:browser"
58
+ ]
59
+ },
60
+ "test:server": {
61
+ "command": "node --enable-source-maps --test-reporter=spec --test test/server/*_test.js test/server/**/*_test.js",
62
+ "dependencies": [
63
+ "build"
64
+ ],
65
+ "files": [
66
+ "test-files/"
67
+ ],
68
+ "output": []
69
+ },
70
+ "test:browser": {
71
+ "command": "node ../../tests/run-web-tests.js \"test/browser/**/*_test.js\" --config ../../tests/web-test-runner.config.js",
72
+ "dependencies": [
73
+ "build",
74
+ "build:ts-bundle",
75
+ "../../tests:build"
76
+ ],
77
+ "env": {
78
+ "BROWSERS": {
79
+ "external": true
80
+ },
81
+ "MODE": "dev"
82
+ },
83
+ "files": [],
84
+ "output": []
85
+ }
86
+ },
87
+ "files": [
88
+ "index.*",
89
+ "package-analyzer.*",
90
+ "/lib/",
91
+ "!/lib/.tsbuildinfo"
92
+ ],
93
+ "exports": {
94
+ ".": "./index.js",
95
+ "./package-analyzer.js": "./package-analyzer.js",
96
+ "./lib/*.js": "./lib/*.js"
97
+ },
98
+ "dependencies": {
99
+ "@parse5/tools": "^0.7.0",
100
+ "lit-html": "^3.1.2",
101
+ "package-json-type": "^1.0.3",
102
+ "parse5": "^7.3.0",
103
+ "typescript": "~5.9.0"
104
+ },
105
+ "devDependencies": {
106
+ "@rollup/plugin-commonjs": "^25.0.7",
107
+ "path-module": "^0.1.2"
108
+ }
109
+ }