@lit-labs/analyzer
Advanced tools
Comparing version
@@ -8,2 +8,3 @@ /** | ||
import { Package, Module } from './model.js'; | ||
import { AbsolutePath } from './paths.js'; | ||
/** | ||
@@ -13,3 +14,3 @@ * An analyzer for Lit npm packages | ||
export declare class Analyzer { | ||
readonly packageRoot: string; | ||
readonly packageRoot: AbsolutePath; | ||
readonly commandLine: ts.ParsedCommandLine; | ||
@@ -22,9 +23,6 @@ readonly program: ts.Program; | ||
*/ | ||
constructor(packageRoot: string); | ||
constructor(packageRoot: AbsolutePath); | ||
analyzePackage(): Package; | ||
analyzeFile(fileName: string): Module; | ||
private _isLitElementClassDeclaration; | ||
private _isLitElementModule; | ||
isLitElement: (node: ts.Node) => node is ts.ClassDeclaration; | ||
analyzeFile(fileName: AbsolutePath): Module; | ||
} | ||
//# sourceMappingURL=analyzer.d.ts.map |
@@ -7,3 +7,5 @@ /** | ||
import ts from 'typescript'; | ||
import { Package, Module } from './model.js'; | ||
import { Package, Module, ClassDeclaration, LitElementDeclaration, } from './model.js'; | ||
import { absoluteToPackage } from './paths.js'; | ||
import { isLitElement, getTagName } from './lit-element.js'; | ||
/** | ||
@@ -18,28 +20,2 @@ * An analyzer for Lit npm packages | ||
constructor(packageRoot) { | ||
this._isLitElementClassDeclaration = (t) => { | ||
const declarations = t.getSymbol()?.getDeclarations(); | ||
if (declarations?.length !== 1) { | ||
return false; | ||
} | ||
const node = declarations[0]; | ||
return (this._isLitElementModule(node.getSourceFile()) && | ||
ts.isClassDeclaration(node) && | ||
node.name?.getText() === 'LitElement'); | ||
}; | ||
this._isLitElementModule = (file) => { | ||
return file.fileName.endsWith('/node_modules/lit-element/lit-element.d.ts'); | ||
}; | ||
this.isLitElement = (node) => { | ||
if (!ts.isClassLike(node)) { | ||
return false; | ||
} | ||
const type = this.checker.getTypeAtLocation(node); | ||
const baseTypes = this.checker.getBaseTypes(type); | ||
for (const t of baseTypes) { | ||
if (this._isLitElementClassDeclaration(t)) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
}; | ||
this.packageRoot = packageRoot; | ||
@@ -61,3 +37,3 @@ const configFileName = ts.findConfigFile(packageRoot, ts.sys.fileExists, 'tsconfig.json'); | ||
console.error(diagnostics); | ||
throw new Error('Copmiler errors'); | ||
throw new Error('Compiler errors'); | ||
} | ||
@@ -69,3 +45,2 @@ const rootFileNames = this.program.getRootFileNames(); | ||
} | ||
// TODO: return a package object... | ||
return new Package(modules); | ||
@@ -75,5 +50,27 @@ } | ||
const sourceFile = this.program.getSourceFile(fileName); | ||
return new Module(sourceFile); | ||
const module = new Module({ | ||
path: absoluteToPackage(fileName, this.packageRoot), | ||
sourceFile, | ||
}); | ||
for (const statement of sourceFile.statements) { | ||
if (ts.isClassDeclaration(statement)) { | ||
const name = statement.name?.text; | ||
if (isLitElement(statement, this.checker)) { | ||
module.declarations.push(new LitElementDeclaration({ | ||
tagname: getTagName(statement), | ||
name, | ||
node: statement, | ||
})); | ||
} | ||
else { | ||
module.declarations.push(new ClassDeclaration({ | ||
name, | ||
node: statement, | ||
})); | ||
} | ||
} | ||
} | ||
return module; | ||
} | ||
} | ||
//# sourceMappingURL=analyzer.js.map |
@@ -7,2 +7,3 @@ /** | ||
import ts from 'typescript'; | ||
import { PackagePath } from './paths.js'; | ||
export declare class Package { | ||
@@ -12,6 +13,40 @@ readonly modules: ReadonlyArray<Module>; | ||
} | ||
export interface ModuleInit { | ||
sourceFile: ts.SourceFile; | ||
path: PackagePath; | ||
} | ||
export declare class Module { | ||
readonly sourceFile: ts.SourceFile; | ||
constructor(sourceFile: ts.SourceFile); | ||
readonly path: PackagePath; | ||
readonly declarations: Array<Declaration>; | ||
constructor(init: ModuleInit); | ||
} | ||
export declare type Declaration = ClassDeclaration; | ||
export interface ClassDeclarationInit { | ||
name: string | undefined; | ||
node: ts.ClassDeclaration; | ||
} | ||
export declare class ClassDeclaration { | ||
readonly name: string | undefined; | ||
readonly node: ts.ClassDeclaration; | ||
constructor(init: ClassDeclarationInit); | ||
} | ||
interface LitElementDeclarationInit extends ClassDeclarationInit { | ||
tagname: string | undefined; | ||
} | ||
export declare class LitElementDeclaration extends ClassDeclaration { | ||
readonly isLitElement = true; | ||
/** | ||
* The element's tag name, if one is associated with this class declaration, | ||
* such as with a `@customElement()` decorator or `customElements.define()` | ||
* call int he same module. | ||
* | ||
* This is undefined if the element has no associated custom element | ||
* registration in the same module. This class might be intended for use as a | ||
* base class or with scoped custom element registries. | ||
*/ | ||
readonly tagname: string | undefined; | ||
constructor(init: LitElementDeclarationInit); | ||
} | ||
export {}; | ||
//# sourceMappingURL=model.d.ts.map |
@@ -12,6 +12,21 @@ /** | ||
export class Module { | ||
constructor(sourceFile) { | ||
this.sourceFile = sourceFile; | ||
constructor(init) { | ||
this.declarations = []; | ||
this.sourceFile = init.sourceFile; | ||
this.path = init.path; | ||
} | ||
} | ||
export class ClassDeclaration { | ||
constructor(init) { | ||
this.name = init.name; | ||
this.node = init.node; | ||
} | ||
} | ||
export class LitElementDeclaration extends ClassDeclaration { | ||
constructor(init) { | ||
super(init); | ||
this.isLitElement = true; | ||
this.tagname = init.tagname; | ||
} | ||
} | ||
//# sourceMappingURL=model.js.map |
{ | ||
"name": "@lit-labs/analyzer", | ||
"version": "0.1.0", | ||
"version": "0.1.1", | ||
"publishConfig": { | ||
@@ -5,0 +5,0 @@ "access": "public" |
@@ -8,3 +8,10 @@ /** | ||
import ts from 'typescript'; | ||
import {Package, Module} from './model.js'; | ||
import { | ||
Package, | ||
Module, | ||
ClassDeclaration, | ||
LitElementDeclaration, | ||
} from './model.js'; | ||
import {AbsolutePath, absoluteToPackage} from './paths.js'; | ||
import {isLitElement, getTagName} from './lit-element.js'; | ||
@@ -15,3 +22,3 @@ /** | ||
export class Analyzer { | ||
readonly packageRoot: string; | ||
readonly packageRoot: AbsolutePath; | ||
readonly commandLine: ts.ParsedCommandLine; | ||
@@ -25,3 +32,3 @@ readonly program: ts.Program; | ||
*/ | ||
constructor(packageRoot: string) { | ||
constructor(packageRoot: AbsolutePath) { | ||
this.packageRoot = packageRoot; | ||
@@ -56,49 +63,44 @@ | ||
console.error(diagnostics); | ||
throw new Error('Copmiler errors'); | ||
throw new Error('Compiler errors'); | ||
} | ||
const rootFileNames = this.program.getRootFileNames(); | ||
const modules = []; | ||
for (const fileName of rootFileNames) { | ||
modules.push(this.analyzeFile(fileName)); | ||
modules.push(this.analyzeFile(fileName as AbsolutePath)); | ||
} | ||
// TODO: return a package object... | ||
return new Package(modules); | ||
} | ||
analyzeFile(fileName: string) { | ||
analyzeFile(fileName: AbsolutePath) { | ||
const sourceFile = this.program.getSourceFile(fileName)!; | ||
return new Module(sourceFile); | ||
} | ||
const module = new Module({ | ||
path: absoluteToPackage(fileName, this.packageRoot), | ||
sourceFile, | ||
}); | ||
private _isLitElementClassDeclaration = (t: ts.BaseType) => { | ||
const declarations = t.getSymbol()?.getDeclarations(); | ||
if (declarations?.length !== 1) { | ||
return false; | ||
} | ||
const node = declarations[0]; | ||
return ( | ||
this._isLitElementModule(node.getSourceFile()) && | ||
ts.isClassDeclaration(node) && | ||
node.name?.getText() === 'LitElement' | ||
); | ||
}; | ||
private _isLitElementModule = (file: ts.SourceFile) => { | ||
return file.fileName.endsWith('/node_modules/lit-element/lit-element.d.ts'); | ||
}; | ||
isLitElement = (node: ts.Node): node is ts.ClassDeclaration => { | ||
if (!ts.isClassLike(node)) { | ||
return false; | ||
} | ||
const type = this.checker.getTypeAtLocation(node) as ts.InterfaceType; | ||
const baseTypes = this.checker.getBaseTypes(type); | ||
for (const t of baseTypes) { | ||
if (this._isLitElementClassDeclaration(t)) { | ||
return true; | ||
for (const statement of sourceFile.statements) { | ||
if (ts.isClassDeclaration(statement)) { | ||
const name = statement.name?.text; | ||
if (isLitElement(statement, this.checker)) { | ||
module.declarations.push( | ||
new LitElementDeclaration({ | ||
tagname: getTagName(statement), | ||
name, | ||
node: statement, | ||
}) | ||
); | ||
} else { | ||
module.declarations.push( | ||
new ClassDeclaration({ | ||
name, | ||
node: statement, | ||
}) | ||
); | ||
} | ||
} | ||
} | ||
return false; | ||
}; | ||
return module; | ||
} | ||
} |
@@ -8,2 +8,3 @@ /** | ||
import ts from 'typescript'; | ||
import {PackagePath} from './paths.js'; | ||
@@ -18,8 +19,57 @@ export class Package { | ||
export interface ModuleInit { | ||
sourceFile: ts.SourceFile; | ||
path: PackagePath; | ||
} | ||
export class Module { | ||
readonly sourceFile: ts.SourceFile; | ||
readonly path: PackagePath; | ||
readonly declarations: Array<Declaration> = []; | ||
constructor(sourceFile: ts.SourceFile) { | ||
this.sourceFile = sourceFile; | ||
constructor(init: ModuleInit) { | ||
this.sourceFile = init.sourceFile; | ||
this.path = init.path; | ||
} | ||
} | ||
export type Declaration = ClassDeclaration; | ||
export interface ClassDeclarationInit { | ||
name: string | undefined; | ||
node: ts.ClassDeclaration; | ||
} | ||
export class ClassDeclaration { | ||
readonly name: string | undefined; | ||
readonly node: ts.ClassDeclaration; | ||
constructor(init: ClassDeclarationInit) { | ||
this.name = init.name; | ||
this.node = init.node; | ||
} | ||
} | ||
interface LitElementDeclarationInit extends ClassDeclarationInit { | ||
tagname: string | undefined; | ||
} | ||
export class LitElementDeclaration extends ClassDeclaration { | ||
readonly isLitElement = true; | ||
/** | ||
* The element's tag name, if one is associated with this class declaration, | ||
* such as with a `@customElement()` decorator or `customElements.define()` | ||
* call int he same module. | ||
* | ||
* This is undefined if the element has no associated custom element | ||
* registration in the same module. This class might be intended for use as a | ||
* base class or with scoped custom element registries. | ||
*/ | ||
readonly tagname: string | undefined; | ||
constructor(init: LitElementDeclarationInit) { | ||
super(init); | ||
this.tagname = init.tagname; | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
37485
111.89%25
66.67%586
136.29%1
Infinity%