@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.
- package/LICENSE +28 -0
- package/README.md +76 -0
- package/index.d.ts +10 -0
- package/index.d.ts.map +1 -0
- package/index.js +10 -0
- package/index.js.map +1 -0
- package/lib/analyzer.d.ts +47 -0
- package/lib/analyzer.d.ts.map +1 -0
- package/lib/analyzer.js +90 -0
- package/lib/analyzer.js.map +1 -0
- package/lib/custom-elements/custom-elements.d.ts +33 -0
- package/lib/custom-elements/custom-elements.d.ts.map +1 -0
- package/lib/custom-elements/custom-elements.js +124 -0
- package/lib/custom-elements/custom-elements.js.map +1 -0
- package/lib/custom-elements/events.d.ts +19 -0
- package/lib/custom-elements/events.d.ts.map +1 -0
- package/lib/custom-elements/events.js +25 -0
- package/lib/custom-elements/events.js.map +1 -0
- package/lib/diagnostic-code.d.ts +21 -0
- package/lib/diagnostic-code.d.ts.map +1 -0
- package/lib/diagnostic-code.js +20 -0
- package/lib/diagnostic-code.js.map +1 -0
- package/lib/errors.d.ts +24 -0
- package/lib/errors.d.ts.map +1 -0
- package/lib/errors.js +17 -0
- package/lib/errors.js.map +1 -0
- package/lib/javascript/classes.d.ts +50 -0
- package/lib/javascript/classes.d.ts.map +1 -0
- package/lib/javascript/classes.js +307 -0
- package/lib/javascript/classes.js.map +1 -0
- package/lib/javascript/functions.d.ts +31 -0
- package/lib/javascript/functions.d.ts.map +1 -0
- package/lib/javascript/functions.js +144 -0
- package/lib/javascript/functions.js.map +1 -0
- package/lib/javascript/jsdoc.d.ts +67 -0
- package/lib/javascript/jsdoc.d.ts.map +1 -0
- package/lib/javascript/jsdoc.js +244 -0
- package/lib/javascript/jsdoc.js.map +1 -0
- package/lib/javascript/mixins.d.ts +45 -0
- package/lib/javascript/mixins.d.ts.map +1 -0
- package/lib/javascript/mixins.js +147 -0
- package/lib/javascript/mixins.js.map +1 -0
- package/lib/javascript/modules.d.ts +42 -0
- package/lib/javascript/modules.d.ts.map +1 -0
- package/lib/javascript/modules.js +277 -0
- package/lib/javascript/modules.js.map +1 -0
- package/lib/javascript/packages.d.ts +18 -0
- package/lib/javascript/packages.d.ts.map +1 -0
- package/lib/javascript/packages.js +53 -0
- package/lib/javascript/packages.js.map +1 -0
- package/lib/javascript/variables.d.ts +29 -0
- package/lib/javascript/variables.d.ts.map +1 -0
- package/lib/javascript/variables.js +143 -0
- package/lib/javascript/variables.js.map +1 -0
- package/lib/lit/decorators.d.ts +36 -0
- package/lib/lit/decorators.d.ts.map +1 -0
- package/lib/lit/decorators.js +32 -0
- package/lib/lit/decorators.js.map +1 -0
- package/lib/lit/lit-element.d.ts +39 -0
- package/lib/lit/lit-element.d.ts.map +1 -0
- package/lib/lit/lit-element.js +96 -0
- package/lib/lit/lit-element.js.map +1 -0
- package/lib/lit/modules.d.ts +28 -0
- package/lib/lit/modules.d.ts.map +1 -0
- package/lib/lit/modules.js +62 -0
- package/lib/lit/modules.js.map +1 -0
- package/lib/lit/properties.d.ts +43 -0
- package/lib/lit/properties.d.ts.map +1 -0
- package/lib/lit/properties.js +268 -0
- package/lib/lit/properties.js.map +1 -0
- package/lib/lit/template.d.ts +110 -0
- package/lib/lit/template.d.ts.map +1 -0
- package/lib/lit/template.js +412 -0
- package/lib/lit/template.js.map +1 -0
- package/lib/lit-element/decorators.d.ts +11 -0
- package/lib/lit-element/decorators.d.ts.map +1 -0
- package/lib/lit-element/decorators.js +11 -0
- package/lib/lit-element/decorators.js.map +1 -0
- package/lib/lit-element/lit-element.d.ts +11 -0
- package/lib/lit-element/lit-element.d.ts.map +1 -0
- package/lib/lit-element/lit-element.js +11 -0
- package/lib/lit-element/lit-element.js.map +1 -0
- package/lib/lit-element/properties.d.ts +11 -0
- package/lib/lit-element/properties.d.ts.map +1 -0
- package/lib/lit-element/properties.js +11 -0
- package/lib/lit-element/properties.js.map +1 -0
- package/lib/model.d.ts +506 -0
- package/lib/model.d.ts.map +1 -0
- package/lib/model.js +392 -0
- package/lib/model.js.map +1 -0
- package/lib/package-analyzer.d.ts +25 -0
- package/lib/package-analyzer.d.ts.map +1 -0
- package/lib/package-analyzer.js +81 -0
- package/lib/package-analyzer.js.map +1 -0
- package/lib/paths.d.ts +24 -0
- package/lib/paths.d.ts.map +1 -0
- package/lib/paths.js +35 -0
- package/lib/paths.js.map +1 -0
- package/lib/references.d.ts +107 -0
- package/lib/references.d.ts.map +1 -0
- package/lib/references.js +345 -0
- package/lib/references.js.map +1 -0
- package/lib/types.d.ts +25 -0
- package/lib/types.d.ts.map +1 -0
- package/lib/types.js +257 -0
- package/lib/types.js.map +1 -0
- package/lib/utils.d.ts +22 -0
- package/lib/utils.d.ts.map +1 -0
- package/lib/utils.js +51 -0
- package/lib/utils.js.map +1 -0
- package/package-analyzer.d.ts +8 -0
- package/package-analyzer.d.ts.map +1 -0
- package/package-analyzer.js +8 -0
- package/package-analyzer.js.map +1 -0
- package/package.json +109 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../../src/lib/lit/decorators.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAEjC,MAAM,MAAM,UAAU,GAAG,OAAO,EAAE,CAAC;AAiBnC,eAAO,MAAM,wBAAwB,GACnC,IAAI,UAAU,EACd,WAAW,EAAE,CAAC,SAAS,KACtB,SAAS,IAAI,sBACyC,CAAC;AAE1D;;;GAGG;AACH,MAAM,WAAW,sBAAuB,SAAQ,EAAE,CAAC,SAAS;IAC1D,QAAQ,CAAC,UAAU,EAAE,EAAE,CAAC,cAAc,CAAC;CACxC;AAED,eAAO,MAAM,oBAAoB,GAC/B,IAAI,UAAU,EACd,aAAa,EAAE,CAAC,mBAAmB,kCAIgC,CAAC;AAQtE;;;GAGG;AACH,UAAU,iBAAkB,SAAQ,EAAE,CAAC,SAAS;IAC9C,QAAQ,CAAC,UAAU,EAAE,EAAE,CAAC,cAAc,CAAC;CACxC;AAED;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,GAC7B,IAAI,UAAU,EACd,WAAW,iBAAiB,2CAO7B,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Returns true if the decorator site is a simple called decorator factory of
|
|
8
|
+
* the form `@decoratorName()`.
|
|
9
|
+
*
|
|
10
|
+
* TODO (justinfagnani): change to looking up decorators by known declarations.
|
|
11
|
+
*/
|
|
12
|
+
const isNamedDecoratorFactory = (ts, decorator, name) => ts.isCallExpression(decorator.expression) &&
|
|
13
|
+
ts.isIdentifier(decorator.expression.expression) &&
|
|
14
|
+
decorator.expression.expression.text === name;
|
|
15
|
+
export const isCustomElementDecorator = (ts, decorator) => isNamedDecoratorFactory(ts, decorator, 'customElement');
|
|
16
|
+
export const getPropertyDecorator = (ts, declaration) => ts
|
|
17
|
+
.getDecorators(declaration)
|
|
18
|
+
?.find((d) => isPropertyDecorator(ts, d));
|
|
19
|
+
const isPropertyDecorator = (ts, decorator) => isNamedDecoratorFactory(ts, decorator, 'property');
|
|
20
|
+
/**
|
|
21
|
+
* Gets the property options object from a `@property()` decorator callsite.
|
|
22
|
+
*
|
|
23
|
+
* Only works with an object literal passed as the first argument.
|
|
24
|
+
*/
|
|
25
|
+
export const getPropertyOptions = (ts, decorator) => {
|
|
26
|
+
const options = decorator.expression.arguments[0];
|
|
27
|
+
if (options !== undefined && ts.isObjectLiteralExpression(options)) {
|
|
28
|
+
return options;
|
|
29
|
+
}
|
|
30
|
+
return undefined;
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=decorators.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decorators.js","sourceRoot":"","sources":["../../src/lib/lit/decorators.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAYH;;;;;GAKG;AACH,MAAM,uBAAuB,GAAG,CAC9B,EAAc,EACd,SAAuB,EACvB,IAAY,EACyB,EAAE,CACvC,EAAE,CAAC,gBAAgB,CAAC,SAAS,CAAC,UAAU,CAAC;IACzC,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,UAAU,CAAC,UAAU,CAAC;IAChD,SAAS,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,KAAK,IAAI,CAAC;AAEhD,MAAM,CAAC,MAAM,wBAAwB,GAAG,CACtC,EAAc,EACd,SAAuB,EACc,EAAE,CACvC,uBAAuB,CAAC,EAAE,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC;AAU1D,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,EAAc,EACd,WAAmC,EACnC,EAAE,CACF,EAAE;KACC,aAAa,CAAC,WAAW,CAAC;IAC3B,EAAE,IAAI,CAAC,CAAC,CAAC,EAA0B,EAAE,CAAC,mBAAmB,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;AAEtE,MAAM,mBAAmB,GAAG,CAC1B,EAAc,EACd,SAAuB,EACS,EAAE,CAClC,uBAAuB,CAAC,EAAE,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;AAUrD;;;;GAIG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,EAAc,EACd,SAA4B,EAC5B,EAAE;IACF,MAAM,OAAO,GAAG,SAAS,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAClD,IAAI,OAAO,KAAK,SAAS,IAAI,EAAE,CAAC,yBAAyB,CAAC,OAAO,CAAC,EAAE,CAAC;QACnE,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC","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 ReactiveElement decorators.\n */\n\nimport type ts from 'typescript';\n\nexport type TypeScript = typeof ts;\n\n/**\n * Returns true if the decorator site is a simple called decorator factory of\n * the form `@decoratorName()`.\n *\n * TODO (justinfagnani): change to looking up decorators by known declarations.\n */\nconst isNamedDecoratorFactory = (\n ts: TypeScript,\n decorator: ts.Decorator,\n name: string\n): decorator is CustomElementDecorator =>\n ts.isCallExpression(decorator.expression) &&\n ts.isIdentifier(decorator.expression.expression) &&\n decorator.expression.expression.text === name;\n\nexport const isCustomElementDecorator = (\n ts: TypeScript,\n decorator: ts.Decorator\n): decorator is CustomElementDecorator =>\n isNamedDecoratorFactory(ts, decorator, 'customElement');\n\n/**\n * A narrower type for ts.Decorator that represents the shape of an analyzable\n * `@customElement('x')` callsite.\n */\nexport interface CustomElementDecorator extends ts.Decorator {\n readonly expression: ts.CallExpression;\n}\n\nexport const getPropertyDecorator = (\n ts: TypeScript,\n declaration: ts.PropertyDeclaration\n) =>\n ts\n .getDecorators(declaration)\n ?.find((d): d is PropertyDecorator => isPropertyDecorator(ts, d));\n\nconst isPropertyDecorator = (\n ts: TypeScript,\n decorator: ts.Decorator\n): decorator is PropertyDecorator =>\n isNamedDecoratorFactory(ts, decorator, 'property');\n\n/**\n * A narrower type for ts.Decorator that represents the shape of an analyzable\n * `@customElement('x')` callsite.\n */\ninterface PropertyDecorator extends ts.Decorator {\n readonly expression: ts.CallExpression;\n}\n\n/**\n * Gets the property options object from a `@property()` decorator callsite.\n *\n * Only works with an object literal passed as the first argument.\n */\nexport const getPropertyOptions = (\n ts: TypeScript,\n decorator: PropertyDecorator\n) => {\n const options = decorator.expression.arguments[0];\n if (options !== undefined && ts.isObjectLiteralExpression(options)) {\n return options;\n }\n return undefined;\n};\n"]}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* @fileoverview
|
|
8
|
+
*
|
|
9
|
+
* Utilities for analyzing LitElement (and ReactiveElement) declarations.
|
|
10
|
+
*/
|
|
11
|
+
import type ts from 'typescript';
|
|
12
|
+
import { LitElementDeclaration, AnalyzerInterface } from '../model.js';
|
|
13
|
+
export type TypeScript = typeof ts;
|
|
14
|
+
/**
|
|
15
|
+
* Gets an analyzer LitElementDeclaration object from a ts.ClassDeclaration
|
|
16
|
+
* (branded as LitClassDeclaration).
|
|
17
|
+
*/
|
|
18
|
+
export declare const getLitElementDeclaration: (declaration: LitClassDeclaration, analyzer: AnalyzerInterface, isMixinClass?: boolean) => LitElementDeclaration;
|
|
19
|
+
/**
|
|
20
|
+
* This type identifies a ClassDeclaration as one that inherits from LitElement.
|
|
21
|
+
*
|
|
22
|
+
* It lets isLitElement function as a type predicate that returns whether or
|
|
23
|
+
* not its argument is a LitElement such that when it returns false TypeScript
|
|
24
|
+
* doesn't infer that the argument is not a ClassDeclaration.
|
|
25
|
+
*/
|
|
26
|
+
export type LitClassDeclaration = ts.ClassDeclaration & {
|
|
27
|
+
__litBrand: never;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Returns true if `node` is a ClassLikeDeclaration that extends LitElement.
|
|
31
|
+
*/
|
|
32
|
+
export declare const isLitElementSubclass: (node: ts.Node, analyzer: AnalyzerInterface) => node is LitClassDeclaration;
|
|
33
|
+
/**
|
|
34
|
+
* Returns the tagname associated with a LitClassDeclaration
|
|
35
|
+
* @param declaration
|
|
36
|
+
* @returns
|
|
37
|
+
*/
|
|
38
|
+
export declare const getTagName: (declaration: LitClassDeclaration, analyzer: AnalyzerInterface) => string | undefined;
|
|
39
|
+
//# sourceMappingURL=lit-element.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lit-element.d.ts","sourceRoot":"","sources":["../../src/lib/lit/lit-element.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAEjC,OAAO,EAAC,qBAAqB,EAAE,iBAAiB,EAAC,MAAM,aAAa,CAAC;AAYrE,MAAM,MAAM,UAAU,GAAG,OAAO,EAAE,CAAC;AAEnC;;;GAGG;AACH,eAAO,MAAM,wBAAwB,GACnC,aAAa,mBAAmB,EAChC,UAAU,iBAAiB,EAC3B,eAAe,OAAO,KACrB,qBAWF,CAAC;AAkDF;;;;;;GAMG;AACH,MAAM,MAAM,mBAAmB,GAAG,EAAE,CAAC,gBAAgB,GAAG;IACtD,UAAU,EAAE,KAAK,CAAC;CACnB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,oBAAoB,GAC/B,MAAM,EAAE,CAAC,IAAI,EACb,UAAU,iBAAiB,KAC1B,IAAI,IAAI,mBAeV,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,UAAU,GACrB,aAAa,mBAAmB,EAChC,UAAU,iBAAiB,uBAkB5B,CAAC"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
5
|
+
*/
|
|
6
|
+
import { getClassMembers, getHeritage } from '../javascript/classes.js';
|
|
7
|
+
import { LitElementDeclaration } from '../model.js';
|
|
8
|
+
import { isCustomElementDecorator, } from './decorators.js';
|
|
9
|
+
import { getProperties } from './properties.js';
|
|
10
|
+
import { getJSDocData, getTagName as getCustomElementTagName, } from '../custom-elements/custom-elements.js';
|
|
11
|
+
import { getBaseTypes } from '../utils.js';
|
|
12
|
+
/**
|
|
13
|
+
* Gets an analyzer LitElementDeclaration object from a ts.ClassDeclaration
|
|
14
|
+
* (branded as LitClassDeclaration).
|
|
15
|
+
*/
|
|
16
|
+
export const getLitElementDeclaration = (declaration, analyzer, isMixinClass) => {
|
|
17
|
+
return new LitElementDeclaration({
|
|
18
|
+
tagname: getTagName(declaration, analyzer),
|
|
19
|
+
// TODO(kschaaf): support anonymous class expressions when assigned to a const
|
|
20
|
+
name: declaration.name?.text ?? '',
|
|
21
|
+
node: declaration,
|
|
22
|
+
reactiveProperties: getProperties(declaration, analyzer),
|
|
23
|
+
...getJSDocData(declaration, analyzer),
|
|
24
|
+
getHeritage: () => getHeritage(declaration, analyzer, isMixinClass),
|
|
25
|
+
...getClassMembers(declaration, analyzer),
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Returns true if this type represents the actual LitElement class.
|
|
30
|
+
*/
|
|
31
|
+
const _isLitElementClassDeclaration = (t, analyzer) => {
|
|
32
|
+
// TODO: should we memoize this for performance?
|
|
33
|
+
const declarations = t.getSymbol()?.getDeclarations();
|
|
34
|
+
if (declarations?.length !== 1) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
const node = declarations[0];
|
|
38
|
+
return (_isLitElement(analyzer.typescript, node) ||
|
|
39
|
+
isLitElementSubclass(node, analyzer));
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Returns true if the given declaration is THE LitElement declaration.
|
|
43
|
+
*
|
|
44
|
+
* TODO(kschaaf): consider a less brittle method of detecting canonical
|
|
45
|
+
* LitElement
|
|
46
|
+
*/
|
|
47
|
+
const _isLitElement = (ts, node) => {
|
|
48
|
+
return (_isLitElementModule(node.getSourceFile()) &&
|
|
49
|
+
ts.isClassDeclaration(node) &&
|
|
50
|
+
node.name?.text === 'LitElement');
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Returns true if the given source file is THE lit-element source file.
|
|
54
|
+
*/
|
|
55
|
+
const _isLitElementModule = (file) => {
|
|
56
|
+
return (file.fileName.endsWith('/node_modules/lit-element/lit-element.d.ts') ||
|
|
57
|
+
file.fileName.endsWith('/node_modules/lit-element/development/lit-element.d.ts') ||
|
|
58
|
+
// Handle case of running analyzer in symlinked monorepo
|
|
59
|
+
file.fileName.endsWith('/packages/lit-element/lit-element.d.ts') ||
|
|
60
|
+
file.fileName.endsWith('/packages/lit-element/development/lit-element.d.ts'));
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Returns true if `node` is a ClassLikeDeclaration that extends LitElement.
|
|
64
|
+
*/
|
|
65
|
+
export const isLitElementSubclass = (node, analyzer) => {
|
|
66
|
+
if (!analyzer.typescript.isClassLike(node)) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
const checker = analyzer.program.getTypeChecker();
|
|
70
|
+
const type = checker.getTypeAtLocation(node);
|
|
71
|
+
const baseTypes = getBaseTypes(type);
|
|
72
|
+
return baseTypes.some((t) =>
|
|
73
|
+
// Mixins will cause the base types to be an intersection that
|
|
74
|
+
// includes `LitElement`
|
|
75
|
+
t.isIntersection()
|
|
76
|
+
? t.types.some((t) => _isLitElementClassDeclaration(t, analyzer))
|
|
77
|
+
: _isLitElementClassDeclaration(t, analyzer));
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* Returns the tagname associated with a LitClassDeclaration
|
|
81
|
+
* @param declaration
|
|
82
|
+
* @returns
|
|
83
|
+
*/
|
|
84
|
+
export const getTagName = (declaration, analyzer) => {
|
|
85
|
+
const customElementDecorator = analyzer.typescript
|
|
86
|
+
.getDecorators(declaration)
|
|
87
|
+
?.find((d) => isCustomElementDecorator(analyzer.typescript, d));
|
|
88
|
+
if (customElementDecorator !== undefined &&
|
|
89
|
+
customElementDecorator.expression.arguments.length === 1 &&
|
|
90
|
+
analyzer.typescript.isStringLiteral(customElementDecorator.expression.arguments[0])) {
|
|
91
|
+
// Get tag from decorator: `@customElement('x-foo')`
|
|
92
|
+
return customElementDecorator.expression.arguments[0].text;
|
|
93
|
+
}
|
|
94
|
+
return getCustomElementTagName(declaration, analyzer);
|
|
95
|
+
};
|
|
96
|
+
//# sourceMappingURL=lit-element.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lit-element.js","sourceRoot":"","sources":["../../src/lib/lit/lit-element.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH,OAAO,EAAC,eAAe,EAAE,WAAW,EAAC,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAC,qBAAqB,EAAoB,MAAM,aAAa,CAAC;AACrE,OAAO,EAEL,wBAAwB,GACzB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EACL,YAAY,EACZ,UAAU,IAAI,uBAAuB,GACtC,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAAC,YAAY,EAAC,MAAM,aAAa,CAAC;AAIzC;;;GAGG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CACtC,WAAgC,EAChC,QAA2B,EAC3B,YAAsB,EACC,EAAE;IACzB,OAAO,IAAI,qBAAqB,CAAC;QAC/B,OAAO,EAAE,UAAU,CAAC,WAAW,EAAE,QAAQ,CAAC;QAC1C,8EAA8E;QAC9E,IAAI,EAAE,WAAW,CAAC,IAAI,EAAE,IAAI,IAAI,EAAE;QAClC,IAAI,EAAE,WAAW;QACjB,kBAAkB,EAAE,aAAa,CAAC,WAAW,EAAE,QAAQ,CAAC;QACxD,GAAG,YAAY,CAAC,WAAW,EAAE,QAAQ,CAAC;QACtC,WAAW,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,WAAW,EAAE,QAAQ,EAAE,YAAY,CAAC;QACnE,GAAG,eAAe,CAAC,WAAW,EAAE,QAAQ,CAAC;KAC1C,CAAC,CAAC;AACL,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,6BAA6B,GAAG,CACpC,CAAc,EACd,QAA2B,EAC3B,EAAE;IACF,gDAAgD;IAChD,MAAM,YAAY,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,eAAe,EAAE,CAAC;IACtD,IAAI,YAAY,EAAE,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,IAAI,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAC7B,OAAO,CACL,aAAa,CAAC,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC;QACxC,oBAAoB,CAAC,IAAI,EAAE,QAAQ,CAAC,CACrC,CAAC;AACJ,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,aAAa,GAAG,CAAC,EAAc,EAAE,IAAoB,EAAE,EAAE;IAC7D,OAAO,CACL,mBAAmB,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;QACzC,EAAE,CAAC,kBAAkB,CAAC,IAAI,CAAC;QAC3B,IAAI,CAAC,IAAI,EAAE,IAAI,KAAK,YAAY,CACjC,CAAC;AACJ,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,mBAAmB,GAAG,CAAC,IAAmB,EAAE,EAAE;IAClD,OAAO,CACL,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,4CAA4C,CAAC;QACpE,IAAI,CAAC,QAAQ,CAAC,QAAQ,CACpB,wDAAwD,CACzD;QACD,wDAAwD;QACxD,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,wCAAwC,CAAC;QAChE,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,oDAAoD,CAAC,CAC7E,CAAC;AACJ,CAAC,CAAC;AAaF;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,IAAa,EACb,QAA2B,EACE,EAAE;IAC/B,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3C,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC;IAClD,MAAM,IAAI,GAAG,OAAO,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAC7C,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAErC,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE;IAC1B,8DAA8D;IAC9D,wBAAwB;IACxB,CAAC,CAAC,cAAc,EAAE;QAChB,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,6BAA6B,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;QACjE,CAAC,CAAC,6BAA6B,CAAC,CAAC,EAAE,QAAQ,CAAC,CAC/C,CAAC;AACJ,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CACxB,WAAgC,EAChC,QAA2B,EAC3B,EAAE;IACF,MAAM,sBAAsB,GAAG,QAAQ,CAAC,UAAU;SAC/C,aAAa,CAAC,WAAW,CAAC;QAC3B,EAAE,IAAI,CAAC,CAAC,CAAC,EAA+B,EAAE,CACxC,wBAAwB,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC,CACjD,CAAC;IACJ,IACE,sBAAsB,KAAK,SAAS;QACpC,sBAAsB,CAAC,UAAU,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC;QACxD,QAAQ,CAAC,UAAU,CAAC,eAAe,CACjC,sBAAsB,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAC/C,EACD,CAAC;QACD,oDAAoD;QACpD,OAAO,sBAAsB,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC7D,CAAC;IACD,OAAO,uBAAuB,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;AACxD,CAAC,CAAC","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 LitElement (and ReactiveElement) declarations.\n */\n\nimport type ts from 'typescript';\nimport {getClassMembers, getHeritage} from '../javascript/classes.js';\nimport {LitElementDeclaration, AnalyzerInterface} from '../model.js';\nimport {\n CustomElementDecorator,\n isCustomElementDecorator,\n} from './decorators.js';\nimport {getProperties} from './properties.js';\nimport {\n getJSDocData,\n getTagName as getCustomElementTagName,\n} from '../custom-elements/custom-elements.js';\nimport {getBaseTypes} from '../utils.js';\n\nexport type TypeScript = typeof ts;\n\n/**\n * Gets an analyzer LitElementDeclaration object from a ts.ClassDeclaration\n * (branded as LitClassDeclaration).\n */\nexport const getLitElementDeclaration = (\n declaration: LitClassDeclaration,\n analyzer: AnalyzerInterface,\n isMixinClass?: boolean\n): LitElementDeclaration => {\n return new LitElementDeclaration({\n tagname: getTagName(declaration, analyzer),\n // TODO(kschaaf): support anonymous class expressions when assigned to a const\n name: declaration.name?.text ?? '',\n node: declaration,\n reactiveProperties: getProperties(declaration, analyzer),\n ...getJSDocData(declaration, analyzer),\n getHeritage: () => getHeritage(declaration, analyzer, isMixinClass),\n ...getClassMembers(declaration, analyzer),\n });\n};\n\n/**\n * Returns true if this type represents the actual LitElement class.\n */\nconst _isLitElementClassDeclaration = (\n t: ts.BaseType,\n analyzer: AnalyzerInterface\n) => {\n // TODO: should we memoize this for performance?\n const declarations = t.getSymbol()?.getDeclarations();\n if (declarations?.length !== 1) {\n return false;\n }\n const node = declarations[0];\n return (\n _isLitElement(analyzer.typescript, node) ||\n isLitElementSubclass(node, analyzer)\n );\n};\n\n/**\n * Returns true if the given declaration is THE LitElement declaration.\n *\n * TODO(kschaaf): consider a less brittle method of detecting canonical\n * LitElement\n */\nconst _isLitElement = (ts: TypeScript, node: ts.Declaration) => {\n return (\n _isLitElementModule(node.getSourceFile()) &&\n ts.isClassDeclaration(node) &&\n node.name?.text === 'LitElement'\n );\n};\n\n/**\n * Returns true if the given source file is THE lit-element source file.\n */\nconst _isLitElementModule = (file: ts.SourceFile) => {\n return (\n file.fileName.endsWith('/node_modules/lit-element/lit-element.d.ts') ||\n file.fileName.endsWith(\n '/node_modules/lit-element/development/lit-element.d.ts'\n ) ||\n // Handle case of running analyzer in symlinked monorepo\n file.fileName.endsWith('/packages/lit-element/lit-element.d.ts') ||\n file.fileName.endsWith('/packages/lit-element/development/lit-element.d.ts')\n );\n};\n\n/**\n * This type identifies a ClassDeclaration as one that inherits from LitElement.\n *\n * It lets isLitElement function as a type predicate that returns whether or\n * not its argument is a LitElement such that when it returns false TypeScript\n * doesn't infer that the argument is not a ClassDeclaration.\n */\nexport type LitClassDeclaration = ts.ClassDeclaration & {\n __litBrand: never;\n};\n\n/**\n * Returns true if `node` is a ClassLikeDeclaration that extends LitElement.\n */\nexport const isLitElementSubclass = (\n node: ts.Node,\n analyzer: AnalyzerInterface\n): node is LitClassDeclaration => {\n if (!analyzer.typescript.isClassLike(node)) {\n return false;\n }\n const checker = analyzer.program.getTypeChecker();\n const type = checker.getTypeAtLocation(node);\n const baseTypes = getBaseTypes(type);\n\n return baseTypes.some((t) =>\n // Mixins will cause the base types to be an intersection that\n // includes `LitElement`\n t.isIntersection()\n ? t.types.some((t) => _isLitElementClassDeclaration(t, analyzer))\n : _isLitElementClassDeclaration(t, analyzer)\n );\n};\n\n/**\n * Returns the tagname associated with a LitClassDeclaration\n * @param declaration\n * @returns\n */\nexport const getTagName = (\n declaration: LitClassDeclaration,\n analyzer: AnalyzerInterface\n) => {\n const customElementDecorator = analyzer.typescript\n .getDecorators(declaration)\n ?.find((d): d is CustomElementDecorator =>\n isCustomElementDecorator(analyzer.typescript, d)\n );\n if (\n customElementDecorator !== undefined &&\n customElementDecorator.expression.arguments.length === 1 &&\n analyzer.typescript.isStringLiteral(\n customElementDecorator.expression.arguments[0]\n )\n ) {\n // Get tag from decorator: `@customElement('x-foo')`\n return customElementDecorator.expression.arguments[0].text;\n }\n return getCustomElementTagName(declaration, analyzer);\n};\n"]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type ts from 'typescript';
|
|
2
|
+
type TypeScript = typeof ts;
|
|
3
|
+
/**
|
|
4
|
+
* Returns true if this node is an import declaration for a module known to
|
|
5
|
+
* export the Lit html template tag.
|
|
6
|
+
*/
|
|
7
|
+
export declare const isLitHtmlImportDeclaration: (node: ts.Node, ts: TypeScript) => node is ts.ImportDeclaration;
|
|
8
|
+
/**
|
|
9
|
+
* Returns true if the specifier is known to export the Lit html template tag.
|
|
10
|
+
*
|
|
11
|
+
* This can be used in a heuristic to determine if a template is a lit-html
|
|
12
|
+
* template.
|
|
13
|
+
*/
|
|
14
|
+
export declare const isKnownLitHtmlModuleSpecifier: (specifier: string) => boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Resolve a common pattern of using the `html` identifier of a lit namespace
|
|
17
|
+
* import.
|
|
18
|
+
*
|
|
19
|
+
* E.g.:
|
|
20
|
+
*
|
|
21
|
+
* ```ts
|
|
22
|
+
* import * as identifier from 'lit';
|
|
23
|
+
* identifier.html`<p>I am compiled!</p>`;
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare const isResolvedPropertyAccessExpressionLitHtmlNamespace: (node: ts.PropertyAccessExpression, ts: TypeScript, checker: ts.TypeChecker) => boolean;
|
|
27
|
+
export {};
|
|
28
|
+
//# sourceMappingURL=modules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modules.d.ts","sourceRoot":"","sources":["../../src/lib/lit/modules.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAEjC,KAAK,UAAU,GAAG,OAAO,EAAE,CAAC;AAE5B;;;GAGG;AACH,eAAO,MAAM,0BAA0B,GACrC,MAAM,EAAE,CAAC,IAAI,EACb,IAAI,UAAU,KACb,IAAI,IAAI,EAAE,CAAC,iBASb,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,6BAA6B,GAAI,WAAW,MAAM,KAAG,OAMjE,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,kDAAkD,GAC7D,MAAM,EAAE,CAAC,wBAAwB,EACjC,IAAI,UAAU,EACd,SAAS,EAAE,CAAC,WAAW,KACtB,OAyBF,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns true if this node is an import declaration for a module known to
|
|
3
|
+
* export the Lit html template tag.
|
|
4
|
+
*/
|
|
5
|
+
export const isLitHtmlImportDeclaration = (node, ts) => {
|
|
6
|
+
if (!ts.isImportDeclaration(node)) {
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
const specifier = node.moduleSpecifier;
|
|
10
|
+
if (!ts.isStringLiteral(specifier)) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
return isKnownLitHtmlModuleSpecifier(specifier.text);
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Returns true if the specifier is known to export the Lit html template tag.
|
|
17
|
+
*
|
|
18
|
+
* This can be used in a heuristic to determine if a template is a lit-html
|
|
19
|
+
* template.
|
|
20
|
+
*/
|
|
21
|
+
export const isKnownLitHtmlModuleSpecifier = (specifier) => {
|
|
22
|
+
return (specifier === 'lit' ||
|
|
23
|
+
specifier === 'lit-html' ||
|
|
24
|
+
specifier === 'lit-element');
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Resolve a common pattern of using the `html` identifier of a lit namespace
|
|
28
|
+
* import.
|
|
29
|
+
*
|
|
30
|
+
* E.g.:
|
|
31
|
+
*
|
|
32
|
+
* ```ts
|
|
33
|
+
* import * as identifier from 'lit';
|
|
34
|
+
* identifier.html`<p>I am compiled!</p>`;
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export const isResolvedPropertyAccessExpressionLitHtmlNamespace = (node, ts, checker) => {
|
|
38
|
+
// Ensure propertyAccessExpression ends with `.html`.
|
|
39
|
+
if (ts.isIdentifier(node.name) && node.name.text !== 'html') {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
// Expect a namespace preceding `html`, `<namespace>.html`.
|
|
43
|
+
if (!ts.isIdentifier(node.expression)) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
// Resolve the namespace if it has been aliased.
|
|
47
|
+
const symbol = checker.getSymbolAtLocation(node.expression);
|
|
48
|
+
if (!symbol) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
const namespaceImport = symbol.declarations?.[0];
|
|
52
|
+
if (!namespaceImport || !ts.isNamespaceImport(namespaceImport)) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
const importDeclaration = namespaceImport.parent.parent;
|
|
56
|
+
const specifier = importDeclaration.moduleSpecifier;
|
|
57
|
+
if (!ts.isStringLiteral(specifier)) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
return isKnownLitHtmlModuleSpecifier(specifier.text);
|
|
61
|
+
};
|
|
62
|
+
//# sourceMappingURL=modules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modules.js","sourceRoot":"","sources":["../../src/lib/lit/modules.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CACxC,IAAa,EACb,EAAc,EACgB,EAAE;IAChC,IAAI,CAAC,EAAE,CAAC,mBAAmB,CAAC,IAAI,CAAC,EAAE,CAAC;QAClC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,SAAS,GAAG,IAAI,CAAC,eAAe,CAAC;IACvC,IAAI,CAAC,EAAE,CAAC,eAAe,CAAC,SAAS,CAAC,EAAE,CAAC;QACnC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,6BAA6B,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;AACvD,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,SAAiB,EAAW,EAAE;IAC1E,OAAO,CACL,SAAS,KAAK,KAAK;QACnB,SAAS,KAAK,UAAU;QACxB,SAAS,KAAK,aAAa,CAC5B,CAAC;AACJ,CAAC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,kDAAkD,GAAG,CAChE,IAAiC,EACjC,EAAc,EACd,OAAuB,EACd,EAAE;IACX,qDAAqD;IACrD,IAAI,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC5D,OAAO,KAAK,CAAC;IACf,CAAC;IACD,2DAA2D;IAC3D,IAAI,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QACtC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,gDAAgD;IAChD,MAAM,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC5D,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,eAAe,GAAG,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,CAAC;IACjD,IAAI,CAAC,eAAe,IAAI,CAAC,EAAE,CAAC,iBAAiB,CAAC,eAAe,CAAC,EAAE,CAAC;QAC/D,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,iBAAiB,GAAG,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC;IACxD,MAAM,SAAS,GAAG,iBAAiB,CAAC,eAAe,CAAC;IACpD,IAAI,CAAC,EAAE,CAAC,eAAe,CAAC,SAAS,CAAC,EAAE,CAAC;QACnC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,6BAA6B,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;AACvD,CAAC,CAAC","sourcesContent":["import type ts from 'typescript';\n\ntype TypeScript = typeof ts;\n\n/**\n * Returns true if this node is an import declaration for a module known to\n * export the Lit html template tag.\n */\nexport const isLitHtmlImportDeclaration = (\n node: ts.Node,\n ts: TypeScript\n): node is ts.ImportDeclaration => {\n if (!ts.isImportDeclaration(node)) {\n return false;\n }\n const specifier = node.moduleSpecifier;\n if (!ts.isStringLiteral(specifier)) {\n return false;\n }\n return isKnownLitHtmlModuleSpecifier(specifier.text);\n};\n\n/**\n * Returns true if the specifier is known to export the Lit html template tag.\n *\n * This can be used in a heuristic to determine if a template is a lit-html\n * template.\n */\nexport const isKnownLitHtmlModuleSpecifier = (specifier: string): boolean => {\n return (\n specifier === 'lit' ||\n specifier === 'lit-html' ||\n specifier === 'lit-element'\n );\n};\n\n/**\n * Resolve a common pattern of using the `html` identifier of a lit namespace\n * import.\n *\n * E.g.:\n *\n * ```ts\n * import * as identifier from 'lit';\n * identifier.html`<p>I am compiled!</p>`;\n * ```\n */\nexport const isResolvedPropertyAccessExpressionLitHtmlNamespace = (\n node: ts.PropertyAccessExpression,\n ts: TypeScript,\n checker: ts.TypeChecker\n): boolean => {\n // Ensure propertyAccessExpression ends with `.html`.\n if (ts.isIdentifier(node.name) && node.name.text !== 'html') {\n return false;\n }\n // Expect a namespace preceding `html`, `<namespace>.html`.\n if (!ts.isIdentifier(node.expression)) {\n return false;\n }\n\n // Resolve the namespace if it has been aliased.\n const symbol = checker.getSymbolAtLocation(node.expression);\n if (!symbol) {\n return false;\n }\n const namespaceImport = symbol.declarations?.[0];\n if (!namespaceImport || !ts.isNamespaceImport(namespaceImport)) {\n return false;\n }\n const importDeclaration = namespaceImport.parent.parent;\n const specifier = importDeclaration.moduleSpecifier;\n if (!ts.isStringLiteral(specifier)) {\n return false;\n }\n return isKnownLitHtmlModuleSpecifier(specifier.text);\n};\n"]}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* @fileoverview
|
|
8
|
+
*
|
|
9
|
+
* Utilities for analyzing reactive property declarations
|
|
10
|
+
*/
|
|
11
|
+
import type ts from 'typescript';
|
|
12
|
+
import { LitClassDeclaration } from './lit-element.js';
|
|
13
|
+
import { ReactiveProperty, AnalyzerInterface } from '../model.js';
|
|
14
|
+
export type TypeScript = typeof ts;
|
|
15
|
+
export declare const getProperties: (classDeclaration: LitClassDeclaration, analyzer: AnalyzerInterface) => Map<string, ReactiveProperty>;
|
|
16
|
+
/**
|
|
17
|
+
* Gets the `attribute` property of a property options object as a string.
|
|
18
|
+
*
|
|
19
|
+
* The attribute value returned is the value that is used at runtime by
|
|
20
|
+
* ReactiveElement, not the raw option. If the attribute property option is
|
|
21
|
+
* not given or is `true`, the lower-cased property name is used. If the
|
|
22
|
+
* attribute property option is `false`, `undefined` is returned.
|
|
23
|
+
*/
|
|
24
|
+
export declare const getPropertyAttribute: (ts: TypeScript, optionsNode: ts.ObjectLiteralExpression | undefined, propertyName: string) => string | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* Gets the `type` property of a property options object as a string.
|
|
27
|
+
*
|
|
28
|
+
* Note: A string is returned as a convenience so we don't have to compare
|
|
29
|
+
* the type value against a known set of TS references for String, Number, etc.
|
|
30
|
+
*
|
|
31
|
+
* If a non-default converter is used, the types might not mean the same thing,
|
|
32
|
+
* but we might not be able to realistically support custom converters.
|
|
33
|
+
*/
|
|
34
|
+
export declare const getPropertyType: (ts: TypeScript, obj: ts.ObjectLiteralExpression | undefined) => string | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* Gets the `reflect` property of a property options object as a boolean.
|
|
37
|
+
*/
|
|
38
|
+
export declare const getPropertyReflect: (ts: TypeScript, obj: ts.ObjectLiteralExpression | undefined) => boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Gets the `converter` property of a property options object.
|
|
41
|
+
*/
|
|
42
|
+
export declare const getPropertyConverter: (ts: TypeScript, obj: ts.ObjectLiteralExpression | undefined) => ts.PropertyAssignment | undefined;
|
|
43
|
+
//# sourceMappingURL=properties.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"properties.d.ts","sourceRoot":"","sources":["../../src/lib/lit/properties.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,EAAC,mBAAmB,EAAC,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAC,gBAAgB,EAAE,iBAAiB,EAAC,MAAM,aAAa,CAAC;AAOhE,MAAM,MAAM,UAAU,GAAG,OAAO,EAAE,CAAC;AAEnC,eAAO,MAAM,aAAa,GACxB,kBAAkB,mBAAmB,EACrC,UAAU,iBAAiB,kCA0E5B,CAAC;AAyJF;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,GAC/B,IAAI,UAAU,EACd,aAAa,EAAE,CAAC,uBAAuB,GAAG,SAAS,EACnD,cAAc,MAAM,uBAwBrB,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe,GAC1B,IAAI,UAAU,EACd,KAAK,EAAE,CAAC,uBAAuB,GAAG,SAAS,uBAU5C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAC7B,IAAI,UAAU,EACd,KAAK,EAAE,CAAC,uBAAuB,GAAG,SAAS,YAU5C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,oBAAoB,GAC/B,IAAI,UAAU,EACd,KAAK,EAAE,CAAC,uBAAuB,GAAG,SAAS,sCAM5C,CAAC"}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2022 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
5
|
+
*/
|
|
6
|
+
import { getTypeForNode } from '../types.js';
|
|
7
|
+
import { getPropertyDecorator, getPropertyOptions } from './decorators.js';
|
|
8
|
+
import { hasStaticModifier } from '../utils.js';
|
|
9
|
+
import { DiagnosticCode } from '../diagnostic-code.js';
|
|
10
|
+
import { createDiagnostic } from '../errors.js';
|
|
11
|
+
export const getProperties = (classDeclaration, analyzer) => {
|
|
12
|
+
const { typescript: ts } = analyzer;
|
|
13
|
+
const reactiveProperties = new Map();
|
|
14
|
+
const undecoratedProperties = new Map();
|
|
15
|
+
// Filter down to just the property and getter declarations
|
|
16
|
+
const propertyDeclarations = classDeclaration.members.filter((m) => ts.isPropertyDeclaration(m) || ts.isGetAccessorDeclaration(m));
|
|
17
|
+
let staticProperties;
|
|
18
|
+
for (const prop of propertyDeclarations) {
|
|
19
|
+
if (!ts.isIdentifier(prop.name) && !ts.isPrivateIdentifier(prop.name)) {
|
|
20
|
+
analyzer.addDiagnostic(createDiagnostic({
|
|
21
|
+
typescript: ts,
|
|
22
|
+
node: prop,
|
|
23
|
+
message: '@lit-labs/analyzer only supports analyzing class properties ' +
|
|
24
|
+
'named with plain identifiers, or private class fields. This ' +
|
|
25
|
+
'property was ignored: ' +
|
|
26
|
+
prop.name.getText(),
|
|
27
|
+
category: ts.DiagnosticCategory.Warning,
|
|
28
|
+
code: DiagnosticCode.UNSUPPORTED,
|
|
29
|
+
}));
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
const name = prop.name.text;
|
|
33
|
+
const propertyDecorator = getPropertyDecorator(ts, prop);
|
|
34
|
+
if (propertyDecorator !== undefined) {
|
|
35
|
+
// Decorated property; get property options from the decorator and add
|
|
36
|
+
// them to the reactiveProperties map
|
|
37
|
+
const options = getPropertyOptions(ts, propertyDecorator);
|
|
38
|
+
reactiveProperties.set(name, {
|
|
39
|
+
name,
|
|
40
|
+
node: prop,
|
|
41
|
+
optionsNode: options,
|
|
42
|
+
type: getTypeForNode(prop, analyzer),
|
|
43
|
+
attribute: getPropertyAttribute(ts, options, name),
|
|
44
|
+
typeOption: getPropertyType(ts, options),
|
|
45
|
+
reflect: getPropertyReflect(ts, options),
|
|
46
|
+
converter: getPropertyConverter(ts, options),
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
else if (name === 'properties' && hasStaticModifier(ts, prop)) {
|
|
50
|
+
// This field has the static properties block (initializer or getter).
|
|
51
|
+
// Note we will process this after the loop so that the
|
|
52
|
+
// `undecoratedProperties` map is complete before processing the static
|
|
53
|
+
// properties block.
|
|
54
|
+
staticProperties = prop;
|
|
55
|
+
}
|
|
56
|
+
else if (!hasStaticModifier(ts, prop)) {
|
|
57
|
+
// Store the declaration node for any undecorated properties. In a TS
|
|
58
|
+
// program that happens to use a static properties block along with
|
|
59
|
+
// the `declare` keyword to type the field, we can use this node to
|
|
60
|
+
// get/infer the TS type of the field from
|
|
61
|
+
undecoratedProperties.set(name, prop);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// Handle static properties block (initializer or getter).
|
|
65
|
+
if (staticProperties !== undefined) {
|
|
66
|
+
addPropertiesFromStaticBlock(classDeclaration, staticProperties, undecoratedProperties, reactiveProperties, analyzer);
|
|
67
|
+
}
|
|
68
|
+
return reactiveProperties;
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Given a static properties declaration (field or getter), add property
|
|
72
|
+
* options to the provided `reactiveProperties` map.
|
|
73
|
+
*/
|
|
74
|
+
const addPropertiesFromStaticBlock = (classDeclaration, properties, undecoratedProperties, reactiveProperties, analyzer) => {
|
|
75
|
+
const { typescript: ts } = analyzer;
|
|
76
|
+
// Add any constructor initializers to the undecorated properties node map
|
|
77
|
+
// from which we can infer types from. This is the primary path that JS source
|
|
78
|
+
// can get their inferred types (in TS, types will come from the undecorated
|
|
79
|
+
// fields passed in, since you need to declare the field to assign it in the
|
|
80
|
+
// constructor).
|
|
81
|
+
addConstructorInitializers(ts, classDeclaration, undecoratedProperties);
|
|
82
|
+
// Find the object literal from the initializer or getter return value
|
|
83
|
+
const object = getStaticPropertiesObjectLiteral(properties, analyzer);
|
|
84
|
+
if (object === undefined) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
// Loop over each key/value in the object and add them to the map
|
|
88
|
+
for (const prop of object.properties) {
|
|
89
|
+
if (ts.isPropertyAssignment(prop) &&
|
|
90
|
+
ts.isIdentifier(prop.name) &&
|
|
91
|
+
ts.isObjectLiteralExpression(prop.initializer)) {
|
|
92
|
+
const name = prop.name.text;
|
|
93
|
+
const options = prop.initializer;
|
|
94
|
+
const nodeForType = undecoratedProperties.get(name);
|
|
95
|
+
reactiveProperties.set(name, {
|
|
96
|
+
name,
|
|
97
|
+
node: prop,
|
|
98
|
+
optionsNode: options,
|
|
99
|
+
type: nodeForType !== undefined
|
|
100
|
+
? getTypeForNode(nodeForType, analyzer)
|
|
101
|
+
: undefined,
|
|
102
|
+
attribute: getPropertyAttribute(ts, options, name),
|
|
103
|
+
typeOption: getPropertyType(ts, options),
|
|
104
|
+
reflect: getPropertyReflect(ts, options),
|
|
105
|
+
converter: getPropertyConverter(ts, options),
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
analyzer.addDiagnostic(createDiagnostic({
|
|
110
|
+
typescript: ts,
|
|
111
|
+
node: prop,
|
|
112
|
+
message: 'Unsupported static properties entry. Expected a string identifier key and object literal value.',
|
|
113
|
+
code: DiagnosticCode.UNSUPPORTED,
|
|
114
|
+
category: ts.DiagnosticCategory.Warning,
|
|
115
|
+
}));
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
/**
|
|
120
|
+
* Find the object literal for a static properties block.
|
|
121
|
+
*
|
|
122
|
+
* If a ts.PropertyDeclaration, it will look like:
|
|
123
|
+
*
|
|
124
|
+
* static properties = { ... };
|
|
125
|
+
*
|
|
126
|
+
* If a ts.GetAccessorDeclaration, it will look like:
|
|
127
|
+
*
|
|
128
|
+
* static get properties() {
|
|
129
|
+
* return {... }
|
|
130
|
+
* }
|
|
131
|
+
*/
|
|
132
|
+
const getStaticPropertiesObjectLiteral = (properties, analyzer) => {
|
|
133
|
+
const { typescript: ts } = analyzer;
|
|
134
|
+
let object = undefined;
|
|
135
|
+
if (ts.isPropertyDeclaration(properties) &&
|
|
136
|
+
properties.initializer !== undefined &&
|
|
137
|
+
ts.isObjectLiteralExpression(properties.initializer)) {
|
|
138
|
+
// `properties` has a static initializer; get the object from there
|
|
139
|
+
object = properties.initializer;
|
|
140
|
+
}
|
|
141
|
+
else if (ts.isGetAccessorDeclaration(properties)) {
|
|
142
|
+
// Object was in a static getter: find the object in the return value
|
|
143
|
+
const statements = properties.body?.statements;
|
|
144
|
+
const statement = statements?.[statements.length - 1];
|
|
145
|
+
if (statement !== undefined &&
|
|
146
|
+
ts.isReturnStatement(statement) &&
|
|
147
|
+
statement.expression !== undefined &&
|
|
148
|
+
ts.isObjectLiteralExpression(statement.expression)) {
|
|
149
|
+
object = statement.expression;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
if (object === undefined) {
|
|
153
|
+
analyzer.addDiagnostic(createDiagnostic({
|
|
154
|
+
typescript: ts,
|
|
155
|
+
node: properties,
|
|
156
|
+
message: `Unsupported static properties format. Expected an object literal assigned in a static initializer or returned from a static getter.`,
|
|
157
|
+
code: DiagnosticCode.UNSUPPORTED,
|
|
158
|
+
category: ts.DiagnosticCategory.Warning,
|
|
159
|
+
}));
|
|
160
|
+
}
|
|
161
|
+
return object;
|
|
162
|
+
};
|
|
163
|
+
/**
|
|
164
|
+
* Adds any field initializers in the given class's constructor to the provided
|
|
165
|
+
* map. This will be used for inferring the type of fields in JS programs.
|
|
166
|
+
*/
|
|
167
|
+
const addConstructorInitializers = (ts, classDeclaration, undecoratedProperties) => {
|
|
168
|
+
const ctor = classDeclaration.forEachChild((node) => ts.isConstructorDeclaration(node) ? node : undefined);
|
|
169
|
+
if (ctor !== undefined) {
|
|
170
|
+
ctor.body?.statements.forEach((stmt) => {
|
|
171
|
+
// Look for initializers in the form of `this.foo = xxxx`
|
|
172
|
+
if (ts.isExpressionStatement(stmt) &&
|
|
173
|
+
ts.isBinaryExpression(stmt.expression) &&
|
|
174
|
+
ts.isPropertyAccessExpression(stmt.expression.left) &&
|
|
175
|
+
stmt.expression.left.expression.kind === ts.SyntaxKind.ThisKeyword &&
|
|
176
|
+
ts.isIdentifier(stmt.expression.left.name) &&
|
|
177
|
+
!undecoratedProperties.has(stmt.expression.left.name.text)) {
|
|
178
|
+
// Add the initializer expression to the map
|
|
179
|
+
undecoratedProperties.set(
|
|
180
|
+
// Property name
|
|
181
|
+
stmt.expression.left.name.text,
|
|
182
|
+
// Expression from which we can infer a type
|
|
183
|
+
stmt.expression.right);
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
/**
|
|
189
|
+
* Gets the `attribute` property of a property options object as a string.
|
|
190
|
+
*
|
|
191
|
+
* The attribute value returned is the value that is used at runtime by
|
|
192
|
+
* ReactiveElement, not the raw option. If the attribute property option is
|
|
193
|
+
* not given or is `true`, the lower-cased property name is used. If the
|
|
194
|
+
* attribute property option is `false`, `undefined` is returned.
|
|
195
|
+
*/
|
|
196
|
+
export const getPropertyAttribute = (ts, optionsNode, propertyName) => {
|
|
197
|
+
if (optionsNode === undefined) {
|
|
198
|
+
return propertyName.toLowerCase();
|
|
199
|
+
}
|
|
200
|
+
const attributeProperty = getObjectProperty(ts, optionsNode, 'attribute');
|
|
201
|
+
if (attributeProperty === undefined) {
|
|
202
|
+
return propertyName.toLowerCase();
|
|
203
|
+
}
|
|
204
|
+
const { initializer } = attributeProperty;
|
|
205
|
+
if (ts.isStringLiteral(initializer)) {
|
|
206
|
+
return initializer.text;
|
|
207
|
+
}
|
|
208
|
+
if (initializer.kind === ts.SyntaxKind.FalseKeyword) {
|
|
209
|
+
return undefined;
|
|
210
|
+
}
|
|
211
|
+
if (initializer.kind === ts.SyntaxKind.TrueKeyword ||
|
|
212
|
+
(ts.isIdentifier(initializer) && initializer.text === 'undefined') ||
|
|
213
|
+
initializer.kind === ts.SyntaxKind.UndefinedKeyword) {
|
|
214
|
+
return propertyName.toLowerCase();
|
|
215
|
+
}
|
|
216
|
+
return undefined;
|
|
217
|
+
};
|
|
218
|
+
/**
|
|
219
|
+
* Gets the `type` property of a property options object as a string.
|
|
220
|
+
*
|
|
221
|
+
* Note: A string is returned as a convenience so we don't have to compare
|
|
222
|
+
* the type value against a known set of TS references for String, Number, etc.
|
|
223
|
+
*
|
|
224
|
+
* If a non-default converter is used, the types might not mean the same thing,
|
|
225
|
+
* but we might not be able to realistically support custom converters.
|
|
226
|
+
*/
|
|
227
|
+
export const getPropertyType = (ts, obj) => {
|
|
228
|
+
if (obj === undefined) {
|
|
229
|
+
return undefined;
|
|
230
|
+
}
|
|
231
|
+
const typeProperty = getObjectProperty(ts, obj, 'type');
|
|
232
|
+
if (typeProperty !== undefined && ts.isIdentifier(typeProperty.initializer)) {
|
|
233
|
+
return typeProperty.initializer.text;
|
|
234
|
+
}
|
|
235
|
+
return undefined;
|
|
236
|
+
};
|
|
237
|
+
/**
|
|
238
|
+
* Gets the `reflect` property of a property options object as a boolean.
|
|
239
|
+
*/
|
|
240
|
+
export const getPropertyReflect = (ts, obj) => {
|
|
241
|
+
if (obj === undefined) {
|
|
242
|
+
return false;
|
|
243
|
+
}
|
|
244
|
+
const reflectProperty = getObjectProperty(ts, obj, 'reflect');
|
|
245
|
+
if (reflectProperty === undefined) {
|
|
246
|
+
return false;
|
|
247
|
+
}
|
|
248
|
+
return reflectProperty.initializer.kind === ts.SyntaxKind.TrueKeyword;
|
|
249
|
+
};
|
|
250
|
+
/**
|
|
251
|
+
* Gets the `converter` property of a property options object.
|
|
252
|
+
*/
|
|
253
|
+
export const getPropertyConverter = (ts, obj) => {
|
|
254
|
+
if (obj === undefined) {
|
|
255
|
+
return undefined;
|
|
256
|
+
}
|
|
257
|
+
return getObjectProperty(ts, obj, 'converter');
|
|
258
|
+
};
|
|
259
|
+
/**
|
|
260
|
+
* Gets a named property from an object literal expression.
|
|
261
|
+
*
|
|
262
|
+
* Only returns a value for `{k: v}` property assignments. Does not work for
|
|
263
|
+
* shorthand properties (`{k}`), methods, or accessors.
|
|
264
|
+
*/
|
|
265
|
+
const getObjectProperty = (ts, obj, name) => obj.properties.find((p) => ts.isPropertyAssignment(p) &&
|
|
266
|
+
ts.isIdentifier(p.name) &&
|
|
267
|
+
p.name.text === name);
|
|
268
|
+
//# sourceMappingURL=properties.js.map
|