Skip to content

Commit 40516ea

Browse files
johnjenkinsJohn Jenkins
andauthored
fix(build): add extended class source in collection dependencies (#6412)
Co-authored-by: John Jenkins <john.jenkins@nanoporetech.com>
1 parent ef05b45 commit 40516ea

File tree

3 files changed

+41
-14
lines changed

3 files changed

+41
-14
lines changed

src/compiler/sys/typescript/typescript-resolve-module.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,16 @@ export const tsResolveModuleName = (
2424
return null;
2525
};
2626

27+
export const tsGetSourceFile = (config: d.ValidatedConfig, module: ts.ResolvedModuleWithFailedLookupLocations) => {
28+
if (!module || !module.resolvedModule) {
29+
return null;
30+
}
31+
const compilerOptions: ts.CompilerOptions = { ...config.tsCompilerOptions };
32+
const host = ts.createCompilerHost(compilerOptions);
33+
const program = ts.createProgram([module.resolvedModule.resolvedFileName], compilerOptions, host);
34+
return program.getSourceFile(module.resolvedModule.resolvedFileName);
35+
};
36+
2737
export const tsResolveModuleNamePackageJsonPath = (
2838
config: d.ValidatedConfig,
2939
compilerCtx: d.CompilerCtx,

src/compiler/transformers/detect-modern-prop-decls.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import { getStaticValue } from './transform-utils';
2929
* @param cmp metadata about the stencil component of interest
3030
* @returns true if the class has modern property declarations, false otherwise
3131
*/
32-
export const detectModernPropDeclarations = (classNode: ts.ClassDeclaration) => {
32+
export const detectModernPropDeclarations = (classNode: ts.ClassDeclaration, sourceFile?: ts.SourceFile) => {
3333
const parsedProps: { [key: string]: d.ComponentCompilerProperty } = getStaticValue(classNode.members, 'properties');
3434
const parsedStates: { [key: string]: d.ComponentCompilerProperty } = getStaticValue(classNode.members, 'states');
3535

@@ -48,8 +48,8 @@ export const detectModernPropDeclarations = (classNode: ts.ClassDeclaration) =>
4848
const prop = classNode.members.find((m) => {
4949
return (
5050
ts.isPropertyDeclaration(m) &&
51-
((ts.isComputedPropertyName(m.name) && m.name.expression.getText() === dynamicPropName) ||
52-
m.name.getText() === propName)
51+
((ts.isComputedPropertyName(m.name) && m.name.expression.getText(sourceFile) === dynamicPropName) ||
52+
m.name.getText(sourceFile) === propName)
5353
);
5454
}) as any as ts.PropertyDeclaration;
5555

src/compiler/transformers/static-to-meta/class-extension.ts

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import ts from 'typescript';
22
import { augmentDiagnosticWithNode, buildWarn } from '@utils';
3-
import { tsResolveModuleName } from '../../sys/typescript/typescript-resolve-module';
3+
import { tsResolveModuleName, tsGetSourceFile } from '../../sys/typescript/typescript-resolve-module';
44
import { isStaticGetter } from '../transform-utils';
55
import { parseStaticEvents } from './events';
66
import { parseStaticListeners } from './listeners';
@@ -109,7 +109,7 @@ function matchesNamedDeclaration(name: string) {
109109
function buildExtendsTree(
110110
compilerCtx: d.CompilerCtx,
111111
classDeclaration: ts.ClassDeclaration,
112-
dependentClasses: { classNode: ts.ClassDeclaration; fileName: string }[],
112+
dependentClasses: { classNode: ts.ClassDeclaration; sourceFile: ts.SourceFile; fileName: string }[],
113113
typeChecker: ts.TypeChecker,
114114
buildCtx: d.BuildCtx,
115115
ogModule: d.Module,
@@ -164,7 +164,7 @@ function buildExtendsTree(
164164
const sourceClass = findClassWalk(source, foundClassDeclaration.name?.getText());
165165

166166
if (sourceClass) {
167-
dependentClasses.push({ classNode: sourceClass, fileName: source.fileName });
167+
dependentClasses.push({ classNode: sourceClass, sourceFile: source, fileName: source.fileName });
168168
if (keepLooking) {
169169
buildExtendsTree(compilerCtx, foundClassDeclaration, dependentClasses, typeChecker, buildCtx, ogModule);
170170
}
@@ -199,7 +199,11 @@ function buildExtendsTree(
199199

200200
if (foundClassDeclaration && !dependentClasses.some((dc) => dc.classNode === foundClassDeclaration)) {
201201
// we found the class declaration in the current module
202-
dependentClasses.push({ classNode: foundClassDeclaration, fileName: currentSource.fileName });
202+
dependentClasses.push({
203+
classNode: foundClassDeclaration,
204+
sourceFile: currentSource,
205+
fileName: currentSource.fileName,
206+
});
203207
if (keepLooking) {
204208
buildExtendsTree(compilerCtx, foundClassDeclaration, dependentClasses, typeChecker, buildCtx, ogModule);
205209
}
@@ -226,12 +230,17 @@ function buildExtendsTree(
226230

227231
if (foundFile?.resolvedModule && className) {
228232
// 4) resolve the module name to a file
229-
const foundModule = compilerCtx.moduleMap.get(foundFile.resolvedModule.resolvedFileName);
233+
let foundSource: ts.SourceFile = compilerCtx.moduleMap.get(
234+
foundFile.resolvedModule.resolvedFileName,
235+
)?.staticSourceFile;
236+
if (!foundSource) {
237+
// Stencil only loads module entries from node_modules collections,
238+
// so if we didn't find the source file in the module map,
239+
// let's create a temporary program and get the source file from there
240+
foundSource = tsGetSourceFile(buildCtx.config, foundFile);
241+
}
230242

231-
// 5) look for the corresponding resolved statement
232-
const matchedStatement = (foundModule?.staticSourceFile as ts.SourceFile).statements.find(
233-
matchesNamedDeclaration(className),
234-
);
243+
const matchedStatement = foundSource.statements.find(matchesNamedDeclaration(className));
235244
foundClassDeclaration = matchedStatement
236245
? ts.isClassDeclaration(matchedStatement)
237246
? matchedStatement
@@ -247,7 +256,12 @@ function buildExtendsTree(
247256

248257
if (foundClassDeclaration && !dependentClasses.some((dc) => dc.classNode === foundClassDeclaration)) {
249258
// 6) if we found the class declaration, push it and check if it itself extends from another class
250-
dependentClasses.push({ classNode: foundClassDeclaration, fileName: currentSource.fileName });
259+
dependentClasses.push({
260+
classNode: foundClassDeclaration,
261+
sourceFile: foundSource,
262+
fileName: currentSource.fileName,
263+
});
264+
251265
if (keepLooking) {
252266
buildExtendsTree(
253267
compilerCtx,
@@ -320,7 +334,10 @@ export function mergeExtendedClassMeta(
320334
module.isExtended = true;
321335
doesExtend = true;
322336

323-
if ((mixinProps.length > 0 || mixinStates.length > 0) && !detectModernPropDeclarations(extendedClass.classNode)) {
337+
if (
338+
(mixinProps.length > 0 || mixinStates.length > 0) &&
339+
!detectModernPropDeclarations(extendedClass.classNode, extendedClass.sourceFile)
340+
) {
324341
const err = buildWarn(buildCtx.diagnostics);
325342
const target = buildCtx.config.tsCompilerOptions?.target;
326343
err.messageText = `Component classes can only extend from other Stencil decorated base classes when targetting more modern JavaScript (ES2022 and above).

0 commit comments

Comments
 (0)