• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2024-2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import { ArkParameterRef, ArkThisRef } from '../base/Ref';
17import { ArkAssignStmt, ArkReturnStmt, Stmt } from '../base/Stmt';
18import {
19    AliasType,
20    ClassType,
21    EnumValueType,
22    FunctionType,
23    GenericType,
24    LiteralType,
25    Type,
26    UnionType
27} from '../base/Type';
28import { Value } from '../base/Value';
29import { Cfg } from '../graph/Cfg';
30import { ViewTree } from '../graph/ViewTree';
31import { ArkBody } from './ArkBody';
32import { ArkClass, ClassCategory } from './ArkClass';
33import { MethodSignature, MethodSubSignature } from './ArkSignature';
34import { BodyBuilder } from './builder/BodyBuilder';
35import { ArkExport, ExportType } from './ArkExport';
36import { ANONYMOUS_METHOD_PREFIX, DEFAULT_ARK_METHOD_NAME, LEXICAL_ENV_NAME_PREFIX } from '../common/Const';
37import { getColNo, getLineNo, LineCol, setCol, setLine } from '../base/Position';
38import { ArkBaseModel, ModifierType } from './ArkBaseModel';
39import { ArkError, ArkErrorCode } from '../common/ArkError';
40import { CALL_BACK } from '../common/EtsConst';
41import { Constant } from '../base/Constant';
42import { Local } from '../base/Local';
43import { ArkFile, Language } from './ArkFile';
44import { CONSTRUCTOR_NAME } from '../common/TSConst';
45import { MethodParameter } from './builder/ArkMethodBuilder';
46import { TypeInference } from '../common/TypeInference';
47
48export const arkMethodNodeKind = [
49    'MethodDeclaration',
50    'Constructor',
51    'FunctionDeclaration',
52    'GetAccessor',
53    'SetAccessor',
54    'ArrowFunction',
55    'FunctionExpression',
56    'MethodSignature',
57    'ConstructSignature',
58    'CallSignature',
59];
60
61/**
62 * @category core/model
63 */
64export class ArkMethod extends ArkBaseModel implements ArkExport {
65    private code?: string;
66    private declaringArkClass!: ArkClass;
67    // used for the nested function to locate its outer function
68    private outerMethod?: ArkMethod;
69
70    private genericTypes?: GenericType[];
71
72    private methodDeclareSignatures?: MethodSignature[];
73    private methodDeclareLineCols?: LineCol[];
74
75    private methodSignature?: MethodSignature;
76    private lineCol?: LineCol;
77
78    private body?: ArkBody;
79    private viewTree?: ViewTree;
80
81    private bodyBuilder?: BodyBuilder;
82
83    private isGeneratedFlag: boolean = false;
84    private asteriskToken: boolean = false;
85    private questionToken: boolean = false;
86
87    constructor() {
88        super();
89    }
90
91    /**
92     * Returns the program language of the file where this method defined.
93     */
94    public getLanguage(): Language {
95        return this.getDeclaringArkClass().getLanguage();
96    }
97
98    public getExportType(): ExportType {
99        return ExportType.METHOD;
100    }
101
102    public getName(): string {
103        return this.getSignature().getMethodSubSignature().getMethodName();
104    }
105
106    /**
107     * Returns the codes of method as a **string.**
108     * @returns the codes of method.
109     */
110    public getCode(): string | undefined {
111        return this.code;
112    }
113
114    public setCode(code: string): void {
115        this.code = code;
116    }
117
118    /**
119     * Get all lines of the method's declarations or null if the method has no seperated declaration.
120     * @returns null or the lines of the method's declarations with number type.
121     */
122    public getDeclareLines(): number[] | null {
123        if (this.methodDeclareLineCols === undefined) {
124            return null;
125        }
126        let lines: number[] = [];
127        this.methodDeclareLineCols.forEach(lineCol => {
128            lines.push(getLineNo(lineCol));
129        });
130        return lines;
131    }
132
133    /**
134     * Get all columns of the method's declarations or null if the method has no seperated declaration.
135     * @returns null or the columns of the method's declarations with number type.
136     */
137    public getDeclareColumns(): number[] | null {
138        if (this.methodDeclareLineCols === undefined) {
139            return null;
140        }
141        let columns: number[] = [];
142        this.methodDeclareLineCols.forEach(lineCol => {
143            columns.push(getColNo(lineCol));
144        });
145        return columns;
146    }
147
148    /**
149     * Set lines and columns of the declarations with number type inputs and then encoded them to LineCol type.
150     * The length of lines and columns should be the same otherwise they cannot be encoded together.
151     * @param lines - the number of lines.
152     * @param columns - the number of columns.
153     * @returns
154     */
155    public setDeclareLinesAndCols(lines: number[], columns: number[]): void {
156        if (lines?.length !== columns?.length) {
157            return;
158        }
159        this.methodDeclareLineCols = [];
160        lines.forEach((line, index) => {
161            let lineCol: LineCol = 0;
162            lineCol = setLine(lineCol, line);
163            lineCol = setCol(lineCol, columns[index]);
164            (this.methodDeclareLineCols as LineCol[]).push(lineCol);
165        });
166    }
167
168    /**
169     * Set lineCols of the declarations directly with LineCol type input.
170     * @param lineCols - the encoded lines and columns with LineCol type.
171     * @returns
172     */
173    public setDeclareLineCols(lineCols: LineCol[]): void {
174        this.methodDeclareLineCols = lineCols;
175    }
176
177    /**
178     * Get encoded lines and columns of the method's declarations or null if the method has no seperated declaration.
179     * @returns null or the encoded lines and columns of the method's declarations with LineCol type.
180     */
181    public getDeclareLineCols(): LineCol[] | null {
182        return this.methodDeclareLineCols ?? null;
183    }
184
185    /**
186     * Get line of the method's implementation or null if the method has no implementation.
187     * @returns null or the number of the line.
188     */
189    public getLine(): number | null {
190        if (this.lineCol === undefined) {
191            return null;
192        }
193        return getLineNo(this.lineCol);
194    }
195
196    /**
197     * Set line of the implementation with line number input.
198     * The line number will be encoded together with the original column number.
199     * @param line - the line number of the method implementation.
200     * @returns
201     */
202    public setLine(line: number): void {
203        if (this.lineCol === undefined) {
204            this.lineCol = 0;
205        }
206        this.lineCol = setLine(this.lineCol, line);
207    }
208
209    /**
210     * Get column of the method's implementation or null if the method has no implementation.
211     * @returns null or the number of the column.
212     */
213    public getColumn(): number | null {
214        if (this.lineCol === undefined) {
215            return null;
216        }
217        return getColNo(this.lineCol);
218    }
219
220    /**
221     * Set column of the implementation with column number input.
222     * The column number will be encoded together with the original line number.
223     * @param column - the column number of the method implementation.
224     * @returns
225     */
226    public setColumn(column: number): void {
227        if (this.lineCol === undefined) {
228            this.lineCol = 0;
229        }
230        this.lineCol = setCol(this.lineCol, column);
231    }
232
233    /**
234     * Get encoded line and column of the method's implementation or null if the method has no implementation.
235     * @returns null or the encoded line and column of the method's implementation with LineCol type.
236     */
237    public getLineCol(): LineCol | null {
238        return this.lineCol ?? null;
239    }
240
241    /**
242     * Set lineCol of the implementation directly with LineCol type input.
243     * @param lineCol - the encoded line and column with LineCol type.
244     * @returns
245     */
246    public setLineCol(lineCol: LineCol): void {
247        this.lineCol = lineCol;
248    }
249
250    /**
251     * Returns the declaring class of the method.
252     * @returns The declaring class of the method.
253     */
254    public getDeclaringArkClass(): ArkClass {
255        return this.declaringArkClass;
256    }
257
258    public setDeclaringArkClass(declaringArkClass: ArkClass): void {
259        this.declaringArkClass = declaringArkClass;
260    }
261
262    public getDeclaringArkFile(): ArkFile {
263        return this.declaringArkClass.getDeclaringArkFile();
264    }
265
266    public isDefaultArkMethod(): boolean {
267        return this.getName() === DEFAULT_ARK_METHOD_NAME;
268    }
269
270    public isAnonymousMethod(): boolean {
271        return this.getName().startsWith(ANONYMOUS_METHOD_PREFIX);
272    }
273
274    public getParameters(): MethodParameter[] {
275        return this.getSignature().getMethodSubSignature().getParameters();
276    }
277
278    public getReturnType(): Type {
279        return this.getSignature().getType();
280    }
281
282    /**
283     * Get all declare signatures.
284     * The results could be null if there is no seperated declaration of the method.
285     * @returns null or the method declare signatures.
286     */
287    public getDeclareSignatures(): MethodSignature[] | null {
288        return this.methodDeclareSignatures ?? null;
289    }
290
291    /**
292     * Get the index of the matched method declare signature among all declare signatures.
293     * The index will be -1 if there is no matched signature found.
294     * @param targetSignature - the target declare signature want to search.
295     * @returns -1 or the index of the matched signature.
296     */
297    public getDeclareSignatureIndex(targetSignature: MethodSignature): number {
298        let declareSignatures = this.methodDeclareSignatures;
299        if (declareSignatures === undefined) {
300            return -1;
301        }
302        for (let i = 0; i < declareSignatures.length; i++) {
303            if (declareSignatures[i].isMatch(targetSignature)) {
304                return i;
305            }
306        }
307        return -1;
308    }
309
310    /**
311     * Get the method signature of the implementation.
312     * The signature could be null if the method is only a declaration which body is undefined.
313     * @returns null or the method implementation signature.
314     */
315    public getImplementationSignature(): MethodSignature | null {
316        return this.methodSignature ?? null;
317    }
318
319    /**
320     * Get the method signature of the implementation or the first declaration if there is no implementation.
321     * For a method, the implementation and declaration signatures must not be undefined at the same time.
322     * A {@link MethodSignature} includes:
323     * - Class Signature: indicates which class this method belong to.
324     * - Method SubSignature: indicates the detail info of this method such as method name, parameters, returnType, etc.
325     * @returns The method signature.
326     * @example
327     * 1. Get the signature of method mtd.
328
329     ```typescript
330     let signature = mtd.getSignature();
331     // ... ...
332     ```
333     */
334    public getSignature(): MethodSignature {
335        return this.methodSignature ?? (this.methodDeclareSignatures as MethodSignature[])[0];
336    }
337
338    /**
339     * Set signatures of all declarations.
340     * It will reset the declaration signatures if they are already defined before.
341     * @param signatures - one signature or a list of signatures.
342     * @returns
343     */
344    public setDeclareSignatures(signatures: MethodSignature | MethodSignature[]): void {
345        if (Array.isArray(signatures)) {
346            this.methodDeclareSignatures = signatures;
347        } else {
348            this.methodDeclareSignatures = [signatures];
349        }
350    }
351
352    /**
353     * Reset signature of one declaration with the specified index.
354     * Will do nothing if the index doesn't exist.
355     * @param signature - new signature want to set.
356     * @param index - index of signature want to set.
357     * @returns
358     */
359    public setDeclareSignatureWithIndex(signature: MethodSignature, index: number): void {
360        if (this.methodDeclareSignatures === undefined || this.methodDeclareSignatures.length <= index) {
361            return;
362        }
363        this.methodDeclareSignatures[index] = signature;
364    }
365
366    /**
367     * Set signature of implementation.
368     * It will reset the implementation signature if it is already defined before.
369     * @param signature - signature of implementation.
370     * @returns
371     */
372    public setImplementationSignature(signature: MethodSignature): void {
373        this.methodSignature = signature;
374    }
375
376    public getSubSignature(): MethodSubSignature {
377        return this.getSignature().getMethodSubSignature();
378    }
379
380    public getGenericTypes(): GenericType[] | undefined {
381        return this.genericTypes;
382    }
383
384    public isGenericsMethod(): boolean {
385        return this.genericTypes !== undefined;
386    }
387
388    public setGenericTypes(genericTypes: GenericType[]): void {
389        this.genericTypes = genericTypes;
390    }
391
392    public getBodyBuilder(): BodyBuilder | undefined {
393        return this.bodyBuilder;
394    }
395
396    /**
397     * Get {@link ArkBody} of a Method.
398     * A {@link ArkBody} contains the CFG and actual instructions or operations to be executed for a method.
399     * It is analogous to the body of a function or method in high-level programming languages,
400     * which contains the statements and expressions that define what the function does.
401     * @returns The {@link ArkBody} of a method.
402     * @example
403     * 1. Get cfg or stmt through ArkBody.
404
405     ```typescript
406     let cfg = this.scene.getMethod()?.getBody().getCfg();
407     const body = arkMethod.getBody()
408     ```
409
410     2. Get local variable through ArkBody.
411
412     ```typescript
413     arkClass.getDefaultArkMethod()?.getBody().getLocals.forEach(local=>{...})
414     let locals = arkFile().getDefaultClass().getDefaultArkMethod()?.getBody()?.getLocals();
415     ```
416     */
417    public getBody(): ArkBody | undefined {
418        return this.body;
419    }
420
421    public setBody(body: ArkBody): void {
422        this.body = body;
423    }
424
425    /**
426     * Get the CFG (i.e., control flow graph) of a method.
427     * The CFG is a graphical representation of all possible control flow paths within a method's body.
428     * A CFG consists of blocks, statements and goto control jumps.
429     * @returns The CFG (i.e., control flow graph) of a method.
430     * @example
431     * 1. get stmt through ArkBody cfg.
432
433     ```typescript
434     body = arkMethod.getBody();
435     const cfg = body.getCfg();
436     for (const threeAddressStmt of cfg.getStmts()) {
437     ... ...
438     }
439     ```
440
441     2. get blocks through ArkBody cfg.
442
443     ```typescript
444     const body = arkMethod.getBody();
445     const blocks = [...body.getCfg().getBlocks()];
446     for (let i=0; i<blocks.length; i++) {
447     const block = blocks[i];
448     ... ...
449     for (const stmt of block.getStmts()) {
450     ... ...
451     }
452     let text = "next;"
453     for (const next of block.getSuccessors()) {
454     text += blocks.indexOf(next) + ' ';
455     }
456     // ... ...
457     }
458     ```
459     */
460    public getCfg(): Cfg | undefined {
461        return this.body?.getCfg();
462    }
463
464    public getOriginalCfg(): Cfg | undefined {
465        return undefined;
466    }
467
468    public getParameterRefs(): ArkParameterRef[] | null {
469        let paramRefs: ArkParameterRef[] = [];
470        const blocks = this.getBody()?.getCfg().getBlocks();
471        if (blocks === undefined) {
472            return null;
473        }
474        const stmts = Array.from(blocks)[0].getStmts();
475        for (let stmt of stmts) {
476            if (stmt instanceof ArkAssignStmt && stmt.getRightOp() instanceof ArkParameterRef) {
477                paramRefs.push((stmt as ArkAssignStmt).getRightOp() as ArkParameterRef);
478            }
479        }
480        return paramRefs;
481    }
482
483    public getParameterInstances(): Value[] {
484        // 获取方法体中参数Local实例
485        let stmts: Stmt[] = [];
486        if (this.getCfg()) {
487            const cfg = this.getCfg() as Cfg;
488            cfg.getStmts().forEach(stmt => stmts.push(stmt));
489        }
490        let results: Value[] = [];
491        for (let stmt of stmts) {
492            if (stmt instanceof ArkAssignStmt) {
493                if (stmt.getRightOp() instanceof ArkParameterRef) {
494                    results.push((stmt as ArkAssignStmt).getLeftOp());
495                }
496            }
497            if (results.length === this.getParameters().length) {
498                return results;
499            }
500        }
501        return results;
502    }
503
504    public getThisInstance(): Value | null {
505        // 获取方法体中This实例
506        let stmts: Stmt[] = [];
507        if (this.getCfg()) {
508            const cfg = this.getCfg() as Cfg;
509            cfg.getStmts().forEach(stmt => stmts.push(stmt));
510        }
511        for (let stmt of stmts) {
512            if (stmt instanceof ArkAssignStmt) {
513                if (stmt.getRightOp() instanceof ArkThisRef) {
514                    return stmt.getLeftOp();
515                }
516            }
517        }
518        return null;
519    }
520
521    public getReturnValues(): Value[] {
522        // 获取方法体中return值实例
523        let resultValues: Value[] = [];
524        this.getCfg()
525            ?.getStmts()
526            .forEach(stmt => {
527                if (stmt instanceof ArkReturnStmt) {
528                    resultValues.push(stmt.getOp());
529                }
530            });
531        return resultValues;
532    }
533
534    public getReturnStmt(): Stmt[] {
535        return this.getCfg()!
536            .getStmts()
537            .filter(stmt => stmt instanceof ArkReturnStmt);
538    }
539
540    public setViewTree(viewTree: ViewTree): void {
541        this.viewTree = viewTree;
542    }
543
544    public getViewTree(): ViewTree | undefined {
545        return this.viewTree;
546    }
547
548    public hasViewTree(): boolean {
549        return this.viewTree !== undefined;
550    }
551
552    public setBodyBuilder(bodyBuilder: BodyBuilder): void {
553        this.bodyBuilder = bodyBuilder;
554        if (this.getDeclaringArkFile().getScene().buildClassDone()) {
555            this.buildBody();
556        }
557    }
558
559    public freeBodyBuilder(): void {
560        this.bodyBuilder = undefined;
561    }
562
563    public buildBody(): void {
564        if (this.bodyBuilder) {
565            const arkBody: ArkBody | null = this.bodyBuilder.build();
566            if (arkBody) {
567                this.setBody(arkBody);
568                arkBody.getCfg().setDeclaringMethod(this);
569                if (this.getOuterMethod() === undefined) {
570                    this.bodyBuilder.handleGlobalAndClosure();
571                }
572            }
573        }
574    }
575
576    public isGenerated(): boolean {
577        return this.isGeneratedFlag;
578    }
579
580    public setIsGeneratedFlag(isGeneratedFlag: boolean): void {
581        this.isGeneratedFlag = isGeneratedFlag;
582    }
583
584    public getAsteriskToken(): boolean {
585        return this.asteriskToken;
586    }
587
588    public setAsteriskToken(asteriskToken: boolean): void {
589        this.asteriskToken = asteriskToken;
590    }
591
592    public validate(): ArkError {
593        const declareSignatures = this.getDeclareSignatures();
594        const declareLineCols = this.getDeclareLineCols();
595        const signature = this.getImplementationSignature();
596        const lineCol = this.getLineCol();
597
598        if (declareSignatures === null && signature === null) {
599            return {
600                errCode: ArkErrorCode.METHOD_SIGNATURE_UNDEFINED,
601                errMsg: 'methodDeclareSignatures and methodSignature are both undefined.',
602            };
603        }
604        if ((declareSignatures === null) !== (declareLineCols === null)) {
605            return {
606                errCode: ArkErrorCode.METHOD_SIGNATURE_LINE_UNMATCHED,
607                errMsg: 'methodDeclareSignatures and methodDeclareLineCols are not matched.',
608            };
609        }
610        if (declareSignatures !== null && declareLineCols !== null && declareSignatures.length !== declareLineCols.length) {
611            return {
612                errCode: ArkErrorCode.METHOD_SIGNATURE_LINE_UNMATCHED,
613                errMsg: 'methodDeclareSignatures and methodDeclareLineCols are not matched.',
614            };
615        }
616        if ((signature === null) !== (lineCol === null)) {
617            return {
618                errCode: ArkErrorCode.METHOD_SIGNATURE_LINE_UNMATCHED,
619                errMsg: 'methodSignature and lineCol are not matched.',
620            };
621        }
622        return this.validateFields(['declaringArkClass']);
623    }
624
625    public matchMethodSignature(args: Value[]): MethodSignature {
626        const signatures = this.methodDeclareSignatures?.filter(f => {
627            const parameters = f.getMethodSubSignature().getParameters();
628            const max = parameters.length;
629            let min = 0;
630            while (min < max && !parameters[min].isOptional()) {
631                min++;
632            }
633            return args.length >= min && args.length <= max;
634        });
635        return (
636            signatures?.find(p => this.isMatched(p.getMethodSubSignature().getParameters(), args)) ??
637            signatures?.[0] ??
638            this.getSignature()
639        );
640    }
641
642    private isMatched(parameters: MethodParameter[], args: Value[], isArrowFunc: boolean = false): boolean {
643        for (let i = 0; i < parameters.length; i++) {
644            if (!args[i]) {
645                return isArrowFunc ? true : parameters[i].isOptional();
646            }
647            const paramType = parameters[i].getType();
648            const isMatched = this.matchParam(paramType, args[i]);
649            if (!isMatched) {
650                return false;
651            } else if (paramType instanceof EnumValueType || paramType instanceof LiteralType) {
652                return true;
653            }
654        }
655        return true;
656    }
657
658    private matchParam(paramType: Type, arg: Value): boolean {
659        if (paramType instanceof EnumValueType || paramType instanceof LiteralType) {
660            arg = ArkMethod.parseArg(arg);
661        }
662        const argType = arg.getType();
663        if (paramType instanceof AliasType && !(argType instanceof AliasType)) {
664            paramType = TypeInference.replaceAliasType(paramType);
665        }
666        if (paramType instanceof UnionType) {
667            return !!paramType.getTypes().find(p => this.matchParam(p, arg));
668        } else if (argType instanceof FunctionType && paramType instanceof FunctionType) {
669            if (argType.getMethodSignature().getParamLength() > paramType.getMethodSignature().getParamLength()) {
670                return false;
671            }
672            const parameters = paramType.getMethodSignature().getMethodSubSignature().getParameters();
673            const args = argType.getMethodSignature().getMethodSubSignature().getParameters().filter(p => !p.getName().startsWith(LEXICAL_ENV_NAME_PREFIX));
674            return this.isMatched(parameters, args, true);
675        } else if (paramType instanceof ClassType && paramType.getClassSignature().getClassName().includes(CALL_BACK)) {
676            return argType instanceof FunctionType;
677        } else if (paramType instanceof LiteralType && arg instanceof Constant) {
678            return (
679                arg.getValue().replace(/[\"|\']/g, '') ===
680                paramType
681                    .getLiteralName()
682                    .toString()
683                    .replace(/[\"|\']/g, '')
684            );
685        } else if (paramType instanceof ClassType && argType instanceof EnumValueType) {
686            return paramType.getClassSignature() === argType.getFieldSignature().getDeclaringSignature();
687        } else if (paramType instanceof EnumValueType) {
688            if (argType instanceof EnumValueType) {
689                return paramType.getFieldSignature() === argType.getFieldSignature();
690            } else if (argType.constructor === paramType.getConstant()?.getType().constructor && arg instanceof Constant) {
691                return paramType.getConstant()?.getValue() === arg.getValue();
692            }
693        }
694        return argType.constructor === paramType.constructor;
695    }
696
697    private static parseArg(arg: Value): Value {
698        if (arg instanceof Local) {
699            const stmt = arg.getDeclaringStmt();
700            const argType = arg.getType();
701            if (argType instanceof EnumValueType && argType.getConstant()) {
702                arg = argType.getConstant()!;
703            } else if (stmt instanceof ArkAssignStmt && stmt.getRightOp() instanceof Constant) {
704                arg = stmt.getRightOp();
705            }
706        }
707        return arg;
708    }
709
710    public getOuterMethod(): ArkMethod | undefined {
711        return this.outerMethod;
712    }
713
714    public setOuterMethod(method: ArkMethod): void {
715        this.outerMethod = method;
716    }
717
718    public getFunctionLocal(name: string): Local | null {
719        const local = this.getBody()?.getLocals().get(name);
720        return local?.getType() instanceof FunctionType ? local : null;
721    }
722
723    public setQuestionToken(questionToken: boolean): void {
724        this.questionToken = questionToken;
725    }
726
727    public getQuestionToken(): boolean {
728        return this.questionToken;
729    }
730
731    // For class method, if there is no public/private/protected access modifier, it is actually public
732    public isPublic(): boolean {
733        if (
734            !this.containsModifier(ModifierType.PUBLIC) &&
735            !this.containsModifier(ModifierType.PRIVATE) &&
736            !this.containsModifier(ModifierType.PROTECTED) &&
737            !this.getDeclaringArkClass().isDefaultArkClass() &&
738            !this.isGenerated() &&
739            !this.isAnonymousMethod() &&
740            this.getName() !== CONSTRUCTOR_NAME &&
741            this.getDeclaringArkClass().getCategory() === ClassCategory.CLASS
742        ) {
743            return true;
744        }
745        return this.containsModifier(ModifierType.PUBLIC);
746    }
747}
748