@@ -148,6 +148,8 @@ export const parseStaticComponentMeta = (
148
148
} ;
149
149
150
150
const visitComponentChildNode = ( node : ts . Node ) => {
151
+ validateComponentMembers ( node ) ;
152
+
151
153
if ( ts . isCallExpression ( node ) ) {
152
154
parseCallExpression ( cmp , node ) ;
153
155
} else if ( ts . isStringLiteral ( node ) ) {
@@ -176,6 +178,42 @@ export const parseStaticComponentMeta = (
176
178
return cmpNode ;
177
179
} ;
178
180
181
+ const validateComponentMembers = ( node : ts . Node ) => {
182
+ /**
183
+ * validate if:
184
+ */
185
+ if (
186
+ /**
187
+ * the component has a getter called "shadowRoot"
188
+ */
189
+ ts . isGetAccessorDeclaration ( node ) &&
190
+ ts . isIdentifier ( node . name ) &&
191
+ node . name . escapedText === 'shadowRoot' &&
192
+ /**
193
+ * the parent node is a class declaration
194
+ */
195
+ ts . isClassDeclaration ( node . parent )
196
+ ) {
197
+ const decorator = ts . getDecorators ( node . parent ) [ 0 ] ;
198
+ /**
199
+ * the class is actually a Stencil component, has a decorator with a property named "tag"
200
+ */
201
+ if (
202
+ ts . isCallExpression ( decorator . expression ) &&
203
+ decorator . expression . arguments . length === 1 &&
204
+ ts . isObjectLiteralExpression ( decorator . expression . arguments [ 0 ] ) &&
205
+ decorator . expression . arguments [ 0 ] . properties . some (
206
+ ( prop ) => ts . isPropertyAssignment ( prop ) && prop . name . getText ( ) === 'tag' ,
207
+ )
208
+ ) {
209
+ const componentName = node . parent . name . getText ( ) ;
210
+ throw new Error (
211
+ `The component "${ componentName } " has a getter called "shadowRoot". This getter is reserved for use by Stencil components and should not be defined by the user.` ,
212
+ ) ;
213
+ }
214
+ }
215
+ } ;
216
+
179
217
const parseVirtualProps = ( docs : d . CompilerJsDoc ) => {
180
218
return docs . tags
181
219
. filter ( ( { name } ) => name === 'virtualProp' )
0 commit comments