diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/LintDriver.java b/plugins/lint/lint-api/src/com/android/tools/klint/client/api/LintDriver.java index a1fc93aaa7b..b58244ea01e 100644 --- a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/LintDriver.java +++ b/plugins/lint/lint-api/src/com/android/tools/klint/client/api/LintDriver.java @@ -1454,7 +1454,7 @@ public class LintDriver { UastScanner scanner = (UastScanner) check; UastVisitor customVisitor = scanner.createUastVisitor(context); if (customVisitor != null) { - UastChecker.INSTANCE.checkWithCustomHandler( + UastChecker.INSTANCE.check( ideaProject, context.file, context, customVisitor); } else { UastChecker.INSTANCE.check( @@ -1515,7 +1515,7 @@ public class LintDriver { for (UastScanner detector : detectors) { UastVisitor customHandler = detector.createUastVisitor(context); if (customHandler != null) { - checker.checkWithCustomHandler(intellijProject, file, context, customHandler); + checker.check(intellijProject, file, context, customHandler); } else { checker.check(intellijProject, file, detector, context); } diff --git a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/CallSuperDetector.java b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/CallSuperDetector.java index 602f07fb427..a62ba8bb821 100644 --- a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/CallSuperDetector.java +++ b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/CallSuperDetector.java @@ -177,7 +177,7 @@ public class CallSuperDetector extends Detector implements UastScanner { @NonNull UFunction methodDeclaration, @NonNull UFunction superMethod) { SuperCallVisitor visitor = new SuperCallVisitor(context, superMethod); - visitor.process(methodDeclaration); + methodDeclaration.accept(visitor); return visitor.mCallsSuper; } @@ -203,10 +203,8 @@ public class CallSuperDetector extends Detector implements UastScanner { } @Override - public void process(@NotNull UElement element) { - if (!mCallsSuper) { - super.process(element); - } + public boolean visitElement(@NotNull UElement node) { + return mCallsSuper || super.visitElement(node); } } } diff --git a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/CleanupDetector.java b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/CleanupDetector.java index ccec93db878..8cfd23ac323 100644 --- a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/CleanupDetector.java +++ b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/CleanupDetector.java @@ -269,7 +269,7 @@ public class CleanupDetector extends Detector implements UastScanner { } }; - visitor.process(method); + method.accept(visitor); if (visitor.isCleanedUp() || visitor.variableEscapes()) { return; } @@ -346,7 +346,7 @@ public class CleanupDetector extends Detector implements UastScanner { } }; - commitVisitor.handle(method); + method.accept(commitVisitor); if (commitVisitor.isCleanedUp() || commitVisitor.variableEscapes()) { return true; } @@ -476,10 +476,8 @@ public class CleanupDetector extends Detector implements UastScanner { } @Override - public void process(@NotNull UElement element) { - if (!mContainsCleanup) { - super.process(element); - } + public boolean visitElement(@NotNull UElement node) { + return mContainsCleanup || super.visitElement(node); } protected abstract boolean isCleanupCall(@NonNull UCallExpression call); diff --git a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/CutPasteDetector.java b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/CutPasteDetector.java index f4ff7aef4e9..5b4465101cd 100644 --- a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/CutPasteDetector.java +++ b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/CutPasteDetector.java @@ -179,7 +179,7 @@ public class CutPasteDetector extends Detector implements UastScanner { @NonNull UCallExpression from, @NonNull UCallExpression to) { ReachableVisitor visitor = new ReachableVisitor(from, to); - visitor.process(method); + method.accept(visitor); return visitor.isReachable(); } @@ -214,16 +214,16 @@ public class CutPasteDetector extends Detector implements UastScanner { UExpression condition = node.getCondition(); UExpression body = node.getThenBranch(); UElement elseBody = node.getElseBranch(); - process(condition); + condition.accept(this); if (body != null) { boolean wasReachable = mReachable; - process(body); + body.accept(this); mReachable = wasReachable; } if (elseBody != null) { boolean wasReachable = mReachable; - process(elseBody); + elseBody.accept(this); mReachable = wasReachable; } @@ -231,10 +231,8 @@ public class CutPasteDetector extends Detector implements UastScanner { } @Override - public void process(@NotNull UElement element) { - if (!mSeenEnd) { - super.process(element); - } + public boolean visitElement(@NotNull UElement node) { + return mSeenEnd; } } } diff --git a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/IconDetector.java b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/IconDetector.java index 116891d7b6a..536ad5aa843 100644 --- a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/IconDetector.java +++ b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/IconDetector.java @@ -1985,7 +1985,7 @@ public class IconDetector extends ResourceXmlDetector implements UastScanner { public boolean visitFunction(@NotNull UFunction node) { if (node.matchesName(ON_CREATE_OPTIONS_MENU)) { // Gather any R.menu references found in this method - new MenuFinder().process(node); + node.accept(new MenuFinder()); } return super.visitFunction(node); @@ -2036,7 +2036,7 @@ public class IconDetector extends ResourceXmlDetector implements UastScanner { UFunction method = UastUtils.getContainingFunction(node); if (method != null) { SetIconFinder finder = new SetIconFinder(); - finder.process(method); + method.accept(finder); } } } diff --git a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/JavaPerformanceDetector.java b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/JavaPerformanceDetector.java index 2d132169bb8..f38e00d2173 100644 --- a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/JavaPerformanceDetector.java +++ b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/JavaPerformanceDetector.java @@ -324,7 +324,7 @@ public class JavaPerformanceDetector extends Detector implements UastScanner { UExpression thenBranch = ifNode.getThenBranch(); if (thenBranch != null) { AssignmentTracker visitor = new AssignmentTracker(assignments); - visitor.process(thenBranch); + thenBranch.accept(visitor); } if (!assignments.isEmpty()) { List references = new ArrayList(); diff --git a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/JavaScriptInterfaceDetector.java b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/JavaScriptInterfaceDetector.java index b55cefe508b..c21a7e75bab 100644 --- a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/JavaScriptInterfaceDetector.java +++ b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/JavaScriptInterfaceDetector.java @@ -109,7 +109,7 @@ public class JavaScriptInterfaceDetector extends Detector implements UastScanner UFunction method = UastUtils.getContainingFunction(node); if (method != null) { ConcreteTypeVisitor v = new ConcreteTypeVisitor(context, node); - v.process(method); + method.accept(v); resolved = v.getType(); if (resolved == null) { return; @@ -211,10 +211,8 @@ public class JavaScriptInterfaceDetector extends Detector implements UastScanner } @Override - public void process(@NotNull UElement element) { - if (!mFoundCall) { - super.process(element); - } + public boolean visitElement(@NotNull UElement node) { + return mFoundCall || super.visitElement(node); } @Override diff --git a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/PermissionRequirement.java b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/PermissionRequirement.java index 0088e8776ea..65cdc01f8da 100644 --- a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/PermissionRequirement.java +++ b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/PermissionRequirement.java @@ -590,13 +590,13 @@ public abstract class PermissionRequirement { if (node != null) { final AtomicReference reference = new AtomicReference(); - new UastVisitor() { + node.accept(new UastVisitor() { @Override public boolean visitVariable(@NotNull UVariable node) { reference.set(node.getInitializer()); return true; } - }.process(node); + }); UExpression expression = reference.get(); if (expression != null) { return parse(annotation, expression); diff --git a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/SecurityDetector.java b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/SecurityDetector.java index 4172cad1087..ddd71b9bf31 100644 --- a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/SecurityDetector.java +++ b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/SecurityDetector.java @@ -389,10 +389,10 @@ public class SecurityDetector extends Detector implements Detector.XmlScanner, U public boolean visitCallExpression(@NotNull UCallExpression node) { String name = node.getFunctionName(); if ("openFileOutput".equals(name) || "getSharedPreferences".equals(name)) { - identifierHandler.processChildren(node); + return false; } - return false; + return true; } } } diff --git a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/SharedPrefsDetector.java b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/SharedPrefsDetector.java index 0514abe455f..1ae46cca7a8 100644 --- a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/SharedPrefsDetector.java +++ b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/SharedPrefsDetector.java @@ -147,7 +147,7 @@ public class SharedPrefsDetector extends Detector implements UastScanner { } CommitFinder finder = new CommitFinder(context, node, allowCommitBeforeTarget); - finder.process(method); + method.accept(finder); if (!finder.isCommitCalled()) { context.report(ISSUE, method, UastAndroidUtils.getLocation(node), "`SharedPreferences.edit()` without a corresponding `commit()` or `apply()` call"); diff --git a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/StringFormatDetector.java b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/StringFormatDetector.java index 98e6dcc79df..7415d5130c7 100644 --- a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/StringFormatDetector.java +++ b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/StringFormatDetector.java @@ -1043,7 +1043,7 @@ public class StringFormatDetector extends ResourceXmlDetector implements UastSca JavaContext lintContext = context.getLintContext(); UastStringTracker tracker = new UastStringTracker(lintContext, method, call, 0); - tracker.process(method); + method.accept(tracker); String name = tracker.getFormatStringName(); if (name == null) { return; @@ -1314,7 +1314,7 @@ public class StringFormatDetector extends ResourceXmlDetector implements UastSca @NonNull UElement call) { assert call instanceof UCallExpression; UastStringTracker tracker = new UastStringTracker(null, method, call, 0); - tracker.process(method); + method.accept(tracker); return tracker.getFormatStringName(); } @@ -1327,7 +1327,7 @@ public class StringFormatDetector extends ResourceXmlDetector implements UastSca int argIndex) { assert call instanceof UCallExpression; UastStringTracker tracker = new UastStringTracker(null, method, call, argIndex); - tracker.process(method); + method.accept(tracker); return tracker.getFormatStringName(); } @@ -1481,10 +1481,8 @@ public class StringFormatDetector extends ResourceXmlDetector implements UastSca } @Override - public void process(@NotNull UElement element) { - if (!mDone) { - super.process(element); - } + public boolean visitElement(@NotNull UElement node) { + return mDone || super.visitElement(node); } @Override diff --git a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/SupportAnnotationDetector.java b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/SupportAnnotationDetector.java index 1d83b8f73bb..a052377f592 100644 --- a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/SupportAnnotationDetector.java +++ b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/SupportAnnotationDetector.java @@ -388,7 +388,7 @@ public class SupportAnnotationDetector extends Detector implements UastScanner { UFunction methodNode = UastUtils.getContainingFunction(node); if (methodNode != null) { CheckPermissionVisitor visitor = new CheckPermissionVisitor(node); - visitor.process(methodNode); + methodNode.accept(visitor); handlesMissingPermission = visitor.checksPermission(); } } @@ -466,10 +466,8 @@ public class SupportAnnotationDetector extends Detector implements UastScanner { } @Override - public void process(@NotNull UElement element) { - if (!mDone) { - super.process(element); - } + public boolean visitElement(@NotNull UElement node) { + return mDone; } @Override diff --git a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/ToastDetector.java b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/ToastDetector.java index 8f49d911800..45e2aa81c45 100644 --- a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/ToastDetector.java +++ b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/ToastDetector.java @@ -105,7 +105,7 @@ public class ToastDetector extends Detector implements UastScanner { UExpression nodeWithPossibleQualifier = UastUtils.getQualifiedCallElement(node); ShowFinder finder = new ShowFinder(nodeWithPossibleQualifier); - finder.process(method); + method.accept(finder); if (!finder.isShowCalled()) { context.report(ISSUE, node, UastAndroidUtils.getLocation(node), "Toast created but not shown: did you forget to call `show()` ?"); diff --git a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/ViewHolderDetector.java b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/ViewHolderDetector.java index 63d8d257e29..39cbca1a7eb 100644 --- a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/ViewHolderDetector.java +++ b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/ViewHolderDetector.java @@ -95,7 +95,7 @@ public class ViewHolderDetector extends Detector implements UastScanner { public boolean visitFunction(@NotNull UFunction node) { if (isViewAdapterMethod(node)) { InflationVisitor visitor = new InflationVisitor(mContext); - visitor.process(node); + node.accept(visitor); visitor.finish(); } return false; diff --git a/plugins/lint/uast-android/src/org/jetbrains/uast/check/UastChecker.kt b/plugins/lint/uast-android/src/org/jetbrains/uast/check/UastChecker.kt index aa97cee1833..546c3656c94 100644 --- a/plugins/lint/uast-android/src/org/jetbrains/uast/check/UastChecker.kt +++ b/plugins/lint/uast-android/src/org/jetbrains/uast/check/UastChecker.kt @@ -38,26 +38,10 @@ interface UastAndroidContext : UastContext { } object UastChecker { - fun checkWithCustomHandler( - project: Project, - file: File, - context: UastAndroidContext, - visitor: UastVisitor) { - check(project, file, context, UastCallback { visitor.handle(it) }) - } - - fun check(project: Project, file: File, context: UastAndroidContext, callback: UastCallback) { + fun check(project: Project, file: File, context: UastAndroidContext, visitor: UastVisitor) { val vfile = VirtualFileManager.getInstance().findFileByUrl("file://" + file.absolutePath) ?: return val plugins = context.languagePlugins - val additionalCheckers = plugins.fold(mutableListOf()) { list, plugin -> - for (checker in plugin.additionalCheckers) { - if (checker is AndroidUastAdditionalChecker) list += checker - } - list - } - - val handlerWrapper = CallbackWrapper(callback, additionalCheckers, context) ApplicationManager.getApplication().runReadAction { val psiFile = PsiManager.getInstance(project).findFile(vfile) @@ -66,12 +50,12 @@ object UastChecker { when (psiFile) { is PsiJavaFile -> { val ufile = JavaUastLanguagePlugin.converter.convertWithParent(psiFile) - ufile?.handleTraverse(handlerWrapper) + ufile?.accept(visitor) } else -> for (plugin in plugins) { val ufile = plugin.converter.convertWithParent(psiFile) if (ufile != null) { - ufile.handleTraverse(handlerWrapper) + ufile.accept(visitor) break } } @@ -80,19 +64,6 @@ object UastChecker { } } - private class CallbackWrapper( - val original: UastCallback, - val additionalCheckers: List, - val context: UastAndroidContext - ) : UastCallback { - override fun invoke(element: UElement) { - original(element) - for (checker in additionalCheckers) { - checker(element, this, context) - } - } - } - fun check(project: Project, file: File, scanner: UastScanner, context: UastAndroidContext) { val applicableFunctionNames = scanner.applicableFunctionNames ?: emptyList() val applicableSuperClasses = scanner.applicableSuperClasses ?: emptyList() @@ -100,57 +71,64 @@ object UastChecker { val appliesToResourcesRefs = scanner.appliesToResourceRefs() - var callback: UastCallback? - callback = UastCallback { element -> - when (element) { - is UCallExpression -> { - if (applicableFunctionNames.isNotEmpty()) { - if (element.kind == FUNCTION_CALL && element.functionName in applicableFunctionNames) { - scanner.visitFunctionCall(context, element) - } + val visitor = object : UastVisitor() { + override fun visitCallExpression(node: UCallExpression): Boolean { + if (applicableFunctionNames.isNotEmpty()) { + if (node.kind == FUNCTION_CALL && node.functionName in applicableFunctionNames) { + scanner.visitFunctionCall(context, node) } + } - if (applicableConstructorTypes.isNotEmpty()) { - if (element.kind == CONSTRUCTOR_CALL) { - element.resolve(context)?.let { constructor -> - if (constructor.getContainingClass()?.fqName in applicableConstructorTypes) { - scanner.visitConstructor(context, element, constructor) - } + if (applicableConstructorTypes.isNotEmpty()) { + if (node.kind == CONSTRUCTOR_CALL) { + node.resolve(context)?.let { constructor -> + if (constructor.getContainingClass()?.fqName in applicableConstructorTypes) { + scanner.visitConstructor(context, node, constructor) } } } } - is UClass -> if (applicableSuperClasses.isNotEmpty()) { - if (applicableSuperClasses.any { element.isSubclassOf(it) }) { - scanner.visitClass(context, element) + + return false + } + + override fun visitClass(node: UClass): Boolean { + if (applicableSuperClasses.isNotEmpty()) { + if (applicableSuperClasses.any { node.isSubclassOf(it) }) { + scanner.visitClass(context, node) } } - is UQualifiedExpression -> { - if (appliesToResourcesRefs && element.receiver is UQualifiedExpression) { - val parentQualifiedExpr = element.receiver as UQualifiedExpression - val resourceName = element.selector - val resourceType = parentQualifiedExpr.selector - val receiver = parentQualifiedExpr.receiver - val receiverIsResourceClass = when (receiver) { - is USimpleReferenceExpression -> receiver.identifier == "R" - is UQualifiedExpression -> receiver.selectorMatches("R") - else -> false - } + return false + } - if (resourceName is USimpleReferenceExpression && resourceType is USimpleReferenceExpression - && receiverIsResourceClass && receiver is UResolvable) { - val resolvedReceiver = receiver.resolve(context) - val isFramework = (resolvedReceiver as? UClass)?.matchesFqName("android.R") ?: false + override fun visitQualifiedExpression(node: UQualifiedExpression): Boolean { + if (appliesToResourcesRefs && node.receiver is UQualifiedExpression) { + val parentQualifiedExpr = node.receiver as UQualifiedExpression + val resourceName = node.selector + val resourceType = parentQualifiedExpr.selector + val receiver = parentQualifiedExpr.receiver - scanner.visitResourceReference(context, element, resourceType.identifier, resourceName.identifier, isFramework) - } + val receiverIsResourceClass = when (receiver) { + is USimpleReferenceExpression -> receiver.identifier == "R" + is UQualifiedExpression -> receiver.selectorMatches("R") + else -> false + } + + if (resourceName is USimpleReferenceExpression && resourceType is USimpleReferenceExpression + && receiverIsResourceClass && receiver is UResolvable) { + val resolvedReceiver = receiver.resolve(context) + val isFramework = (resolvedReceiver as? UClass)?.matchesFqName("android.R") ?: false + + scanner.visitResourceReference(context, node, resourceType.identifier, resourceName.identifier, isFramework) } } + + return false } } - check(project, file, context, callback) + check(project, file, context, visitor) } } \ No newline at end of file diff --git a/plugins/uast-common/src/org/jetbrains/uast/UastUtils.kt b/plugins/uast-common/src/org/jetbrains/uast/UastUtils.kt index 2e7db003108..8082c69c6e6 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/UastUtils.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/UastUtils.kt @@ -17,6 +17,7 @@ package org.jetbrains.uast import org.jetbrains.uast.kinds.UastClassKind +import org.jetbrains.uast.visitor.UastVisitor tailrec fun UElement?.getContainingClass(): UClass? { val parent = this?.parent ?: return null @@ -44,11 +45,6 @@ tailrec fun UElement?.getContainingDeclaration(): UDeclaration? { return parent.getContainingDeclaration() } -fun UElement.handleTraverse(callback: UastCallback) { - callback(this) - this.traverse(callback) -} - fun UDeclaration.isTopLevel() = parent is UFile fun UElement.log(firstLine: String, vararg nested: Any?): String { @@ -67,10 +63,9 @@ fun UElement.log(firstLine: String, vararg nested: Any?): String { val String.withMargin: String get() = lines().joinToString("\n") { " " + it } -fun List.handleTraverseList(callback: UastCallback) { +fun List.acceptList(visitor: UastVisitor) { for (element in this) { - callback(element) - element.traverse(callback) + element.accept(visitor) } } diff --git a/plugins/uast-common/src/org/jetbrains/uast/UastVisitor.kt b/plugins/uast-common/src/org/jetbrains/uast/UastVisitor.kt index 366c99e14c9..15d777422dc 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/UastVisitor.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/UastVisitor.kt @@ -18,108 +18,51 @@ package org.jetbrains.uast.visitor import org.jetbrains.uast.* abstract class UastVisitor { - open fun visitFile(node: UFile): Boolean = false + open fun visitElement(node: UElement): Boolean = false + + open fun visitFile(node: UFile) = visitElement(node) + open fun visitImportStatement(node: UImportStatement) = visitElement(node) + open fun visitAnnotation(node: UAnnotation) = visitElement(node) + open fun visitCatchClause(node: UCatchClause) = visitElement(node) + open fun visitType(node: UType) = visitElement(node) // Declarations - open fun visitClass(node: UClass): Boolean = false - open fun visitFunction(node: UFunction): Boolean = false - open fun visitVariable(node: UVariable): Boolean = false - open fun visitImportStatement(node: UImportStatement): Boolean = false - open fun visitAnnotation(node: UAnnotation): Boolean = false + open fun visitClass(node: UClass) = visitElement(node) + open fun visitFunction(node: UFunction) = visitElement(node) + open fun visitVariable(node: UVariable) = visitElement(node) + // Expressions - open fun visitLabeledExpression(node: ULabeledExpression): Boolean = false - open fun visitDeclarationsExpression(node: UDeclarationsExpression): Boolean = false - open fun visitBlockExpression(node: UBlockExpression): Boolean = false - open fun visitQualifiedExpression(node: UQualifiedExpression): Boolean = false - open fun visitSimpleReferenceExpression(node: USimpleReferenceExpression): Boolean = false - open fun visitCallExpression(node: UCallExpression): Boolean = false - open fun visitBinaryExpression(node: UBinaryExpression): Boolean = false - open fun visitBinaryExpressionWithType(node: UBinaryExpressionWithType): Boolean = false - open fun visitParenthesizedExpression(node: UParenthesizedExpression): Boolean = false - open fun visitPrefixExpression(node: UPrefixExpression): Boolean = false - open fun visitPostfixExpression(node: UPostfixExpression): Boolean = false - open fun visitSpecialExpressionList(node: USpecialExpressionList): Boolean = false - open fun visitExpressionList(node: UExpressionList): Boolean = false - open fun visitIfExpression(node: UIfExpression): Boolean = false - open fun visitSwitchExpression(node: USwitchExpression): Boolean = false - open fun visitSwitchClauseExpression(node: USwitchClauseExpression): Boolean = false - open fun visitWhileExpression(node: UWhileExpression): Boolean = false - open fun visitDoWhileExpression(node: UDoWhileExpression): Boolean = false - open fun visitForExpression(node: UForExpression): Boolean = false - open fun visitForEachExpression(node: UForEachExpression): Boolean = false - open fun visitTryExpression(node: UTryExpression): Boolean = false - open fun visitLiteralExpression(node: ULiteralExpression): Boolean = false - open fun visitThisExpression(node: UThisExpression): Boolean = false - open fun visitSuperExpression(node: USuperExpression): Boolean = false - open fun visitArrayAccessExpression(node: UArrayAccessExpression): Boolean = false - open fun visitCallableReferenceExpression(node: UCallableReferenceExpression): Boolean = false - open fun visitClassLiteralExpression(node: UClassLiteralExpression): Boolean = false - open fun visitLambdaExpression(node: ULambdaExpression): Boolean = false - open fun visitObjectLiteralExpression(node: UObjectLiteralExpression): Boolean = false - - open fun beforeVisit(node: UElement) {} - open fun visitOther(node: UElement): Boolean = true - open fun afterVisit(node: UElement) {} - - fun handle(node: UElement): Boolean { - beforeVisit(node) - val result = when (node) { - is UFile -> visitFile(node) - - is UClass -> visitClass(node) - is UFunction -> visitFunction(node) - is UVariable -> visitVariable(node) - is UImportStatement -> visitImportStatement(node) - is UAnnotation -> visitAnnotation(node) - - is ULabeledExpression -> visitLabeledExpression(node) - is UDeclarationsExpression -> visitDeclarationsExpression(node) - is UBlockExpression -> visitBlockExpression(node) - is UQualifiedExpression -> visitQualifiedExpression(node) - is USimpleReferenceExpression -> visitSimpleReferenceExpression(node) - is UCallExpression -> visitCallExpression(node) - is UBinaryExpression -> visitBinaryExpression(node) - is UBinaryExpressionWithType -> visitBinaryExpressionWithType(node) - is UParenthesizedExpression -> visitParenthesizedExpression(node) - is UPrefixExpression -> visitPrefixExpression(node) - is UPostfixExpression -> visitPostfixExpression(node) - is USpecialExpressionList -> visitSpecialExpressionList(node) - is UExpressionList -> visitExpressionList(node) - is UIfExpression -> visitIfExpression(node) - is USwitchExpression -> visitSwitchExpression(node) - is USwitchClauseExpression -> visitSwitchClauseExpression(node) - is UWhileExpression -> visitWhileExpression(node) - is UDoWhileExpression -> visitDoWhileExpression(node) - is UForExpression -> visitForExpression(node) - is UForEachExpression -> visitForEachExpression(node) - is UTryExpression -> visitTryExpression(node) - is ULiteralExpression -> visitLiteralExpression(node) - is UThisExpression -> visitThisExpression(node) - is USuperExpression -> visitSuperExpression(node) - is UArrayAccessExpression -> visitArrayAccessExpression(node) - is UCallableReferenceExpression -> visitCallableReferenceExpression(node) - is UClassLiteralExpression -> visitClassLiteralExpression(node) - is ULambdaExpression -> visitLambdaExpression(node) - is UObjectLiteralExpression -> visitObjectLiteralExpression(node) - - else -> visitOther(node) - } - afterVisit(node) - return result - } - - open fun process(element: UElement) { - if (!handle(element)) { - processChildren(element) - } - } - - fun processChildren(element: UElement) { - element.traverse(UastCallback { handle(it) }) - } + open fun visitLabeledExpression(node: ULabeledExpression) = visitElement(node) + open fun visitDeclarationsExpression(node: UDeclarationsExpression) = visitElement(node) + open fun visitBlockExpression(node: UBlockExpression) = visitElement(node) + open fun visitQualifiedExpression(node: UQualifiedExpression) = visitElement(node) + open fun visitSimpleReferenceExpression(node: USimpleReferenceExpression) = visitElement(node) + open fun visitCallExpression(node: UCallExpression) = visitElement(node) + open fun visitBinaryExpression(node: UBinaryExpression) = visitElement(node) + open fun visitBinaryExpressionWithType(node: UBinaryExpressionWithType) = visitElement(node) + open fun visitParenthesizedExpression(node: UParenthesizedExpression) = visitElement(node) + open fun visitUnaryExpression(node: UUnaryExpression) = visitElement(node) + open fun visitPrefixExpression(node: UPrefixExpression) = visitElement(node) + open fun visitPostfixExpression(node: UPostfixExpression) = visitElement(node) + open fun visitSpecialExpressionList(node: USpecialExpressionList) = visitElement(node) + open fun visitExpressionList(node: UExpressionList) = visitElement(node) + open fun visitIfExpression(node: UIfExpression) = visitElement(node) + open fun visitSwitchExpression(node: USwitchExpression) = visitElement(node) + open fun visitSwitchClauseExpression(node: USwitchClauseExpression) = visitElement(node) + open fun visitWhileExpression(node: UWhileExpression) = visitElement(node) + open fun visitDoWhileExpression(node: UDoWhileExpression) = visitElement(node) + open fun visitForExpression(node: UForExpression) = visitElement(node) + open fun visitForEachExpression(node: UForEachExpression) = visitElement(node) + open fun visitTryExpression(node: UTryExpression) = visitElement(node) + open fun visitLiteralExpression(node: ULiteralExpression) = visitElement(node) + open fun visitThisExpression(node: UThisExpression) = visitElement(node) + open fun visitSuperExpression(node: USuperExpression) = visitElement(node) + open fun visitArrayAccessExpression(node: UArrayAccessExpression) = visitElement(node) + open fun visitCallableReferenceExpression(node: UCallableReferenceExpression) = visitElement(node) + open fun visitClassLiteralExpression(node: UClassLiteralExpression) = visitElement(node) + open fun visitLambdaExpression(node: ULambdaExpression) = visitElement(node) + open fun visitObjectLiteralExpression(node: UObjectLiteralExpression) = visitElement(node) } -object EmptyUastVisitor : UastVisitor() { - override fun process(element: UElement) {} -} \ No newline at end of file +object EmptyUastVisitor : UastVisitor() \ No newline at end of file diff --git a/plugins/uast-common/src/org/jetbrains/uast/baseElements/UAnnotation.kt b/plugins/uast-common/src/org/jetbrains/uast/baseElements/UAnnotation.kt index 0763b24df25..e4de5de6dca 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/baseElements/UAnnotation.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/baseElements/UAnnotation.kt @@ -15,10 +15,12 @@ */ package org.jetbrains.uast -interface UAnnotation : UElement, UNamed, UFqNamed, LeafUElement { - fun resolve(context: UastContext): UClass? +import org.jetbrains.uast.visitor.UastVisitor +interface UAnnotation : UElement, UNamed, UFqNamed { val valueArguments: List + + fun resolve(context: UastContext): UClass? fun getValue(name: String) = valueArguments.firstOrNull { it.name == name }?.expression?.evaluate() fun getValues() = valueArguments.map { Pair(it.name, it.expression.evaluate()) } @@ -26,6 +28,11 @@ interface UAnnotation : UElement, UNamed, UFqNamed, LeafUElement { override fun logString() = log("UAnnotation ($name)") override fun renderString() = if (valueArguments.isEmpty()) "@$name" else "@$name(" + valueArguments.joinToString { it.renderString() } + ")" + + override fun accept(visitor: UastVisitor) { + if (visitor.visitAnnotation(this)) return + valueArguments.acceptList(visitor) + } } interface UAnnotated : UElement { diff --git a/plugins/uast-common/src/org/jetbrains/uast/baseElements/UElement.kt b/plugins/uast-common/src/org/jetbrains/uast/baseElements/UElement.kt index 02809eacee2..ef79af1bd4a 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/baseElements/UElement.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/baseElements/UElement.kt @@ -15,6 +15,8 @@ */ package org.jetbrains.uast +import org.jetbrains.uast.visitor.UastVisitor + interface UElement { val parent: UElement? @@ -23,7 +25,10 @@ interface UElement { fun logString(): String fun renderString(): String = logString() - fun traverse(callback: UastCallback) + + fun accept(visitor: UastVisitor) { + visitor.visitElement(this) + } } interface UNamed { @@ -42,10 +47,6 @@ interface UModifierOwner { fun hasModifier(modifier: UastModifier): Boolean } -interface LeafUElement : UElement { - override fun traverse(callback: UastCallback) {} -} - interface UResolvable { fun resolve(context: UastContext): UDeclaration? fun resolveOrEmpty(context: UastContext): UDeclaration = resolve(context) ?: UDeclarationNotResolved diff --git a/plugins/uast-common/src/org/jetbrains/uast/baseElements/UExpression.kt b/plugins/uast-common/src/org/jetbrains/uast/baseElements/UExpression.kt index d95c6d125e8..e869c61d95d 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/baseElements/UExpression.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/baseElements/UExpression.kt @@ -15,10 +15,16 @@ */ package org.jetbrains.uast +import org.jetbrains.uast.visitor.UastVisitor + interface UExpression : UElement { open fun evaluate(): Any? = null fun evaluateString(): String? = evaluate() as? String fun getExpressionType(): UType? = null + + override fun accept(visitor: UastVisitor) { + visitor.visitElement(this) + } } interface NoAnnotations : UAnnotated { @@ -30,6 +36,6 @@ interface NoModifiers : UModifierOwner { override fun hasModifier(modifier: UastModifier) = false } -class EmptyExpression(override val parent: UElement) : UExpression, LeafUElement { +class EmptyExpression(override val parent: UElement) : UExpression { override fun logString() = "EmptyExpression" } \ No newline at end of file diff --git a/plugins/uast-common/src/org/jetbrains/uast/baseElements/UFile.kt b/plugins/uast-common/src/org/jetbrains/uast/baseElements/UFile.kt index d65f60e98ee..9c6085eaaf7 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/baseElements/UFile.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/baseElements/UFile.kt @@ -15,6 +15,8 @@ */ package org.jetbrains.uast +import org.jetbrains.uast.visitor.UastVisitor + interface UFile: UElement { val packageFqName: String? val importStatements: List @@ -26,9 +28,10 @@ interface UFile: UElement { override val parent: UElement? get() = null - override fun traverse(callback: UastCallback) { - declarations.handleTraverseList(callback) - importStatements.handleTraverseList(callback) + override fun accept(visitor: UastVisitor) { + if (visitor.visitFile(this)) return + declarations.acceptList(visitor) + importStatements.acceptList(visitor) } override fun logString() = "UFile (package = $packageFqName)\n" + declarations.joinToString("\n") { it.logString().withMargin } diff --git a/plugins/uast-common/src/org/jetbrains/uast/controlStructures/UDoWhileExpression.kt b/plugins/uast-common/src/org/jetbrains/uast/controlStructures/UDoWhileExpression.kt index fb4b8e42eb3..31124fd2b71 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/controlStructures/UDoWhileExpression.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/controlStructures/UDoWhileExpression.kt @@ -15,12 +15,15 @@ */ package org.jetbrains.uast +import org.jetbrains.uast.visitor.UastVisitor + interface UDoWhileExpression : ULoopExpression { val condition: UExpression - override fun traverse(callback: UastCallback) { - condition.handleTraverse(callback) - body.handleTraverse(callback) + override fun accept(visitor: UastVisitor) { + if (visitor.visitDoWhileExpression(this)) return + condition.accept(visitor) + body.accept(visitor) } override fun renderString() = buildString { diff --git a/plugins/uast-common/src/org/jetbrains/uast/controlStructures/UForEachExpression.kt b/plugins/uast-common/src/org/jetbrains/uast/controlStructures/UForEachExpression.kt index a1494130920..23979f1066d 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/controlStructures/UForEachExpression.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/controlStructures/UForEachExpression.kt @@ -15,14 +15,17 @@ */ package org.jetbrains.uast +import org.jetbrains.uast.visitor.UastVisitor + interface UForEachExpression : ULoopExpression { val variable: UVariable val iteratedValue: UExpression - override fun traverse(callback: UastCallback) { - variable.handleTraverse(callback) - iteratedValue.handleTraverse(callback) - body.handleTraverse(callback) + override fun accept(visitor: UastVisitor) { + if (visitor.visitForEachExpression(this)) return + variable.accept(visitor) + iteratedValue.accept(visitor) + body.accept(visitor) } override fun renderString() = buildString { diff --git a/plugins/uast-common/src/org/jetbrains/uast/controlStructures/UForExpression.kt b/plugins/uast-common/src/org/jetbrains/uast/controlStructures/UForExpression.kt index e265c3ea820..497d96e8850 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/controlStructures/UForExpression.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/controlStructures/UForExpression.kt @@ -15,16 +15,19 @@ */ package org.jetbrains.uast +import org.jetbrains.uast.visitor.UastVisitor + interface UForExpression : ULoopExpression { val declaration: UExpression? val condition: UExpression? val update: UExpression? - override fun traverse(callback: UastCallback) { - declaration?.handleTraverse(callback) - condition?.handleTraverse(callback) - update?.handleTraverse(callback) - body.handleTraverse(callback) + override fun accept(visitor: UastVisitor) { + if (visitor.visitForExpression(this)) return + declaration?.accept(visitor) + condition?.accept(visitor) + update?.accept(visitor) + body.accept(visitor) } override fun renderString() = buildString { diff --git a/plugins/uast-common/src/org/jetbrains/uast/controlStructures/UIfExpression.kt b/plugins/uast-common/src/org/jetbrains/uast/controlStructures/UIfExpression.kt index 3730b0750d9..2be73c1b1bb 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/controlStructures/UIfExpression.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/controlStructures/UIfExpression.kt @@ -15,16 +15,19 @@ */ package org.jetbrains.uast +import org.jetbrains.uast.visitor.UastVisitor + interface UIfExpression : UExpression { val condition: UExpression val thenBranch: UExpression? val elseBranch: UExpression? val isTernary: Boolean - override fun traverse(callback: UastCallback) { - condition.handleTraverse(callback) - thenBranch?.handleTraverse(callback) - elseBranch?.handleTraverse(callback) + override fun accept(visitor: UastVisitor) { + if (visitor.visitIfExpression(this)) return + condition.accept(visitor) + thenBranch?.accept(visitor) + elseBranch?.accept(visitor) } override fun logString() = log("UIfExpression", condition, thenBranch, elseBranch) diff --git a/plugins/uast-common/src/org/jetbrains/uast/controlStructures/USwitchExpression.kt b/plugins/uast-common/src/org/jetbrains/uast/controlStructures/USwitchExpression.kt index 57ce6b56b47..99b0001a52b 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/controlStructures/USwitchExpression.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/controlStructures/USwitchExpression.kt @@ -15,13 +15,16 @@ */ package org.jetbrains.uast +import org.jetbrains.uast.visitor.UastVisitor + interface USwitchExpression : UExpression { val expression: UExpression? val body: UExpression - override fun traverse(callback: UastCallback) { - expression?.handleTraverse(callback) - body.handleTraverse(callback) + override fun accept(visitor: UastVisitor) { + if (visitor.visitSwitchExpression(this)) return + expression?.accept(visitor) + body.accept(visitor) } override fun logString() = log("USwitchExpression", expression, body) @@ -37,8 +40,9 @@ interface USwitchClauseExpression : UExpression interface UExpressionSwitchClauseExpression : USwitchClauseExpression { val caseValue: UExpression - override fun traverse(callback: UastCallback) { - caseValue.handleTraverse(callback) + override fun accept(visitor: UastVisitor) { + if (visitor.visitSwitchClauseExpression(this)) return + caseValue.accept(visitor) } override fun renderString() = caseValue.renderString() + " -> " @@ -46,7 +50,6 @@ interface UExpressionSwitchClauseExpression : USwitchClauseExpression { } interface UDefaultSwitchClauseExpression : USwitchClauseExpression { - override fun traverse(callback: UastCallback) {} override fun logString() = "UDefaultSwitchClause" override fun renderString() = "else -> " } diff --git a/plugins/uast-common/src/org/jetbrains/uast/controlStructures/UTryExpression.kt b/plugins/uast-common/src/org/jetbrains/uast/controlStructures/UTryExpression.kt index 11ba98bb1da..919560f6152 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/controlStructures/UTryExpression.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/controlStructures/UTryExpression.kt @@ -15,17 +15,20 @@ */ package org.jetbrains.uast +import org.jetbrains.uast.visitor.UastVisitor + interface UTryExpression : UExpression { val resources: List? val tryClause: UExpression val catchClauses: List val finallyClause: UExpression? - override fun traverse(callback: UastCallback) { - resources?.handleTraverseList(callback) - tryClause.handleTraverse(callback) - catchClauses.handleTraverseList(callback) - finallyClause?.handleTraverse(callback) + override fun accept(visitor: UastVisitor) { + if (visitor.visitTryExpression(this)) return + resources?.acceptList(visitor) + tryClause.accept(visitor) + catchClauses.acceptList(visitor) + finallyClause?.accept(visitor) } override fun renderString() = buildString { @@ -46,10 +49,11 @@ interface UCatchClause : UElement { val parameters: List val types: List - override fun traverse(callback: UastCallback) { - body.handleTraverse(callback) - parameters.handleTraverseList(callback) - types.handleTraverseList(callback) + override fun accept(visitor: UastVisitor) { + if (visitor.visitCatchClause(this)) return + body.accept(visitor) + parameters.acceptList(visitor) + types.acceptList(visitor) } override fun logString() = log("UCatchClause", body) diff --git a/plugins/uast-common/src/org/jetbrains/uast/controlStructures/UWhileExpression.kt b/plugins/uast-common/src/org/jetbrains/uast/controlStructures/UWhileExpression.kt index 04111611640..8ed670e799b 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/controlStructures/UWhileExpression.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/controlStructures/UWhileExpression.kt @@ -15,12 +15,15 @@ */ package org.jetbrains.uast +import org.jetbrains.uast.visitor.UastVisitor + interface UWhileExpression : ULoopExpression { val condition: UExpression - override fun traverse(callback: UastCallback) { - condition.handleTraverse(callback) - body.handleTraverse(callback) + override fun accept(visitor: UastVisitor) { + if (visitor.visitWhileExpression(this)) return + condition.accept(visitor) + body.accept(visitor) } override fun renderString() = buildString { diff --git a/plugins/uast-common/src/org/jetbrains/uast/declarations/UClass.kt b/plugins/uast-common/src/org/jetbrains/uast/declarations/UClass.kt index e49cc896e43..b0bd5f12022 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/declarations/UClass.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/declarations/UClass.kt @@ -16,6 +16,7 @@ package org.jetbrains.uast import org.jetbrains.uast.kinds.UastClassKind +import org.jetbrains.uast.visitor.UastVisitor interface UClass : UDeclaration, UFqNamed, UModifierOwner, UAnnotated { /* The simple class name is only for the debug purposes. Do not check against it in the production code */ @@ -51,10 +52,11 @@ interface UClass : UDeclaration, UFqNamed, UModifierOwner, UAnnotated { fun getSuperClass(context: UastContext): UClass? - override fun traverse(callback: UastCallback) { - nameElement?.handleTraverse(callback) - declarations.handleTraverseList(callback) - annotations.handleTraverseList(callback) + override fun accept(visitor: UastVisitor) { + if (visitor.visitClass(this)) return + nameElement?.accept(visitor) + declarations.acceptList(visitor) + annotations.acceptList(visitor) } override fun renderString(): String { diff --git a/plugins/uast-common/src/org/jetbrains/uast/declarations/UDeclaration.kt b/plugins/uast-common/src/org/jetbrains/uast/declarations/UDeclaration.kt index df2c3ebbdab..45f5e593454 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/declarations/UDeclaration.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/declarations/UDeclaration.kt @@ -15,11 +15,17 @@ */ package org.jetbrains.uast +import org.jetbrains.uast.visitor.UastVisitor + interface UDeclaration : UElement, UNamed { val nameElement: UElement? + + override fun accept(visitor: UastVisitor) { + visitor.visitElement(this) + } } -object UDeclarationNotResolved : UDeclaration, LeafUElement { +object UDeclarationNotResolved : UDeclaration { override val name = "" override val nameElement = null override val parent = null diff --git a/plugins/uast-common/src/org/jetbrains/uast/declarations/UFunction.kt b/plugins/uast-common/src/org/jetbrains/uast/declarations/UFunction.kt index e715be5a38b..aae00f8aea2 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/declarations/UFunction.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/declarations/UFunction.kt @@ -15,6 +15,8 @@ */ package org.jetbrains.uast +import org.jetbrains.uast.visitor.UastVisitor + interface UFunction : UDeclaration, UModifierOwner, UAnnotated { val kind: UastFunctionKind val valueParameters: List @@ -30,13 +32,14 @@ interface UFunction : UDeclaration, UModifierOwner, UAnnotated { fun getSuperFunctions(context: UastContext): List - override fun traverse(callback: UastCallback) { - nameElement?.handleTraverse(callback) - valueParameters.handleTraverseList(callback) - body.handleTraverse(callback) - annotations.handleTraverseList(callback) - typeParameters.handleTraverseList(callback) - returnType?.handleTraverse(callback) + override fun accept(visitor: UastVisitor) { + if (visitor.visitFunction(this)) return + nameElement?.accept(visitor) + valueParameters.acceptList(visitor) + body.accept(visitor) + annotations.acceptList(visitor) + typeParameters.acceptList(visitor) + returnType?.accept(visitor) } override fun renderString(): String { diff --git a/plugins/uast-common/src/org/jetbrains/uast/declarations/UImportStatement.kt b/plugins/uast-common/src/org/jetbrains/uast/declarations/UImportStatement.kt index ba4cdcc13d4..beb39d81a81 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/declarations/UImportStatement.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/declarations/UImportStatement.kt @@ -16,6 +16,7 @@ package org.jetbrains.uast import org.jetbrains.uast.kinds.UastImportKind +import org.jetbrains.uast.visitor.UastVisitor interface UImportStatement : UElement { val fqNameToImport: String? @@ -25,7 +26,10 @@ interface UImportStatement : UElement { /* Returns null if isStarImport = true */ fun resolve(context: UastContext): UDeclaration? - override fun traverse(callback: UastCallback) {} + override fun accept(visitor: UastVisitor) { + visitor.visitImportStatement(this) + } + override fun logString() = "UImport ($fqNameToImport)" override fun renderString() = "import ${fqNameToImport ?: ""}" } \ No newline at end of file diff --git a/plugins/uast-common/src/org/jetbrains/uast/declarations/UType.kt b/plugins/uast-common/src/org/jetbrains/uast/declarations/UType.kt index dc0334b8c0c..2198f551c21 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/declarations/UType.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/declarations/UType.kt @@ -15,7 +15,9 @@ */ package org.jetbrains.uast -interface UType : UElement, UNamed, UFqNamed, UAnnotated, UResolvable, LeafUElement { +import org.jetbrains.uast.visitor.UastVisitor + +interface UType : UElement, UNamed, UFqNamed, UAnnotated, UResolvable { override fun matchesName(name: String) = this.name == name || this.name.endsWith(".$name") /* The simple type name is only for the debug purposes. Do not check against it in the production code */ @@ -36,12 +38,13 @@ interface UType : UElement, UNamed, UFqNamed, UAnnotated, UResolvable, LeafUElem override fun resolve(context: UastContext): UClass? override fun resolveOrEmpty(context: UastContext) = resolve(context) ?: UClassNotResolved - override fun traverse(callback: UastCallback) { - annotations.handleTraverseList(callback) + override fun accept(visitor: UastVisitor) { + if (visitor.visitType(this)) return + annotations.acceptList(visitor) } } -interface UTypeReference : UDeclaration, UResolvable, LeafUElement { +interface UTypeReference : UDeclaration, UResolvable { override fun renderString() = "" override fun logString() = log("UTypeReference") diff --git a/plugins/uast-common/src/org/jetbrains/uast/declarations/UVariable.kt b/plugins/uast-common/src/org/jetbrains/uast/declarations/UVariable.kt index fc46cfc2bff..2b5346b3da7 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/declarations/UVariable.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/declarations/UVariable.kt @@ -15,6 +15,8 @@ */ package org.jetbrains.uast +import org.jetbrains.uast.visitor.UastVisitor + interface UVariable : UDeclaration, UModifierOwner, UAnnotated { val initializer: UExpression? val kind: UastVariableKind @@ -27,11 +29,12 @@ interface UVariable : UDeclaration, UModifierOwner, UAnnotated { open val setters: List? get() = null - override fun traverse(callback: UastCallback) { - nameElement?.handleTraverse(callback) - initializer?.handleTraverse(callback) - annotations.handleTraverseList(callback) - type.handleTraverse(callback) + override fun accept(visitor: UastVisitor) { + if (visitor.visitVariable(this)) return + nameElement?.accept(visitor) + initializer?.accept(visitor) + annotations.acceptList(visitor) + type.accept(visitor) } override fun renderString(): String { diff --git a/plugins/uast-common/src/org/jetbrains/uast/expressions/UArrayAccessExpression.kt b/plugins/uast-common/src/org/jetbrains/uast/expressions/UArrayAccessExpression.kt index 244b373df20..d5529328e71 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/expressions/UArrayAccessExpression.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/UArrayAccessExpression.kt @@ -15,13 +15,16 @@ */ package org.jetbrains.uast +import org.jetbrains.uast.visitor.UastVisitor + interface UArrayAccessExpression : UExpression { val receiver: UExpression val indices: List - override fun traverse(callback: UastCallback) { - receiver.handleTraverse(callback) - indices.handleTraverseList(callback) + override fun accept(visitor: UastVisitor) { + if (visitor.visitArrayAccessExpression(this)) return + receiver.accept(visitor) + indices.acceptList(visitor) } override fun logString() = log("UArrayAccessExpression", receiver, indices) diff --git a/plugins/uast-common/src/org/jetbrains/uast/expressions/UBinaryExpression.kt b/plugins/uast-common/src/org/jetbrains/uast/expressions/UBinaryExpression.kt index 023ad12c8e9..94a9601941b 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/expressions/UBinaryExpression.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/UBinaryExpression.kt @@ -15,14 +15,17 @@ */ package org.jetbrains.uast +import org.jetbrains.uast.visitor.UastVisitor + interface UBinaryExpression : UExpression { val leftOperand: UExpression val operator: UastBinaryOperator val rightOperand: UExpression - override fun traverse(callback: UastCallback) { - leftOperand.handleTraverse(callback) - rightOperand.handleTraverse(callback) + override fun accept(visitor: UastVisitor) { + if (visitor.visitBinaryExpression(this)) return + leftOperand.accept(visitor) + rightOperand.accept(visitor) } override fun logString() = diff --git a/plugins/uast-common/src/org/jetbrains/uast/expressions/UBinaryExpressionWithType.kt b/plugins/uast-common/src/org/jetbrains/uast/expressions/UBinaryExpressionWithType.kt index e8527f75a33..3561cac92ac 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/expressions/UBinaryExpressionWithType.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/UBinaryExpressionWithType.kt @@ -15,6 +15,8 @@ */ package org.jetbrains.uast +import org.jetbrains.uast.visitor.UastVisitor + interface UBinaryExpressionWithType : UExpression { val operand: UExpression val operationKind: UastBinaryExpressionWithTypeKind @@ -23,8 +25,9 @@ interface UBinaryExpressionWithType : UExpression { override fun logString() = log("UBinaryExpressionWithType (${getExpressionType()?.name}, ${operationKind.name})", operand) override fun renderString() = "(${operand.renderString()}) ${operationKind.name} ${getExpressionType()?.name}" - override fun traverse(callback: UastCallback) { - operand.handleTraverse(callback) - type.handleTraverse(callback) + override fun accept(visitor: UastVisitor) { + if (visitor.visitBinaryExpressionWithType(this)) return + operand.accept(visitor) + type.accept(visitor) } } \ No newline at end of file diff --git a/plugins/uast-common/src/org/jetbrains/uast/expressions/UBlockExpression.kt b/plugins/uast-common/src/org/jetbrains/uast/expressions/UBlockExpression.kt index 172d9b3251d..478ce438373 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/expressions/UBlockExpression.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/UBlockExpression.kt @@ -15,10 +15,16 @@ */ package org.jetbrains.uast +import org.jetbrains.uast.visitor.UastVisitor + interface UBlockExpression : UExpression { val expressions: List - override fun traverse(callback: UastCallback) = expressions.handleTraverseList(callback) + override fun accept(visitor: UastVisitor) { + if (visitor.visitBlockExpression(this)) return + expressions.acceptList(visitor) + } + override fun logString() = log("UBlockExpression", expressions) override fun renderString() = buildString { diff --git a/plugins/uast-common/src/org/jetbrains/uast/expressions/UCallExpression.kt b/plugins/uast-common/src/org/jetbrains/uast/expressions/UCallExpression.kt index 93d4a8eac2d..c18fa7be054 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/expressions/UCallExpression.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/UCallExpression.kt @@ -15,6 +15,8 @@ */ package org.jetbrains.uast +import org.jetbrains.uast.visitor.UastVisitor + interface UCallExpression : UExpression, UResolvable { val functionReference: USimpleReferenceExpression? @@ -36,12 +38,13 @@ interface UCallExpression : UExpression, UResolvable { override fun resolve(context: UastContext): UFunction? override fun resolveOrEmpty(context: UastContext): UFunction = resolve(context) ?: UFunctionNotResolved - override fun traverse(callback: UastCallback) { - functionReference?.handleTraverse(callback) - classReference?.handleTraverse(callback) - functionNameElement?.handleTraverse(callback) - valueArguments.handleTraverseList(callback) - typeArguments.handleTraverseList(callback) + override fun accept(visitor: UastVisitor) { + if (visitor.visitCallExpression(this)) return + functionReference?.accept(visitor) + classReference?.accept(visitor) + functionNameElement?.accept(visitor) + valueArguments.acceptList(visitor) + typeArguments.acceptList(visitor) } override fun logString() = log("UFunctionCallExpression ($kind, argCount = $valueArgumentCount)", functionReference, valueArguments) diff --git a/plugins/uast-common/src/org/jetbrains/uast/expressions/UCallableReferenceExpression.kt b/plugins/uast-common/src/org/jetbrains/uast/expressions/UCallableReferenceExpression.kt index ca1b7e6c0a9..010c47a9876 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/expressions/UCallableReferenceExpression.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/UCallableReferenceExpression.kt @@ -15,11 +15,14 @@ */ package org.jetbrains.uast +import org.jetbrains.uast.visitor.UastVisitor + interface UCallableReferenceExpression : UExpression { val qualifierType: UType - override fun traverse(callback: UastCallback) { - qualifierType.handleTraverse(callback) + override fun accept(visitor: UastVisitor) { + if (visitor.visitCallableReferenceExpression(this)) return + qualifierType.accept(visitor) } override fun logString() = "UCallableReferenceExpression" diff --git a/plugins/uast-common/src/org/jetbrains/uast/expressions/UClassLiteralExpression.kt b/plugins/uast-common/src/org/jetbrains/uast/expressions/UClassLiteralExpression.kt index f29281599cd..46c39fdda32 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/expressions/UClassLiteralExpression.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/UClassLiteralExpression.kt @@ -15,9 +15,15 @@ */ package org.jetbrains.uast -interface UClassLiteralExpression : UExpression, LeafUElement { +import org.jetbrains.uast.visitor.UastVisitor + +interface UClassLiteralExpression : UExpression { override fun logString() = "UClassLiteralExpression" override fun renderString() = getExpressionType()?.name ?: "::class" val type: UType + + override fun accept(visitor: UastVisitor) { + visitor.visitClassLiteralExpression(this) + } } \ No newline at end of file diff --git a/plugins/uast-common/src/org/jetbrains/uast/expressions/UDeclarationsExpression.kt b/plugins/uast-common/src/org/jetbrains/uast/expressions/UDeclarationsExpression.kt index a1e856a0f00..e43066a7882 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/expressions/UDeclarationsExpression.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/UDeclarationsExpression.kt @@ -15,14 +15,18 @@ */ package org.jetbrains.uast +import org.jetbrains.uast.visitor.UastVisitor + interface UDeclarationsExpression : UExpression { val declarations: List val variables: List get() = declarations.filterIsInstance() - override fun evaluate() = null - override fun traverse(callback: UastCallback) = declarations.handleTraverseList(callback) + override fun accept(visitor: UastVisitor) { + if (visitor.visitDeclarationsExpression(this)) return + declarations.acceptList(visitor) + } override fun renderString() = declarations.joinToString("\n") { it.renderString() } override fun logString() = log("UDeclarationsExpression", declarations) @@ -31,6 +35,4 @@ interface UDeclarationsExpression : UExpression { class SimpleUDeclarationsExpression( override val parent: UElement, override val declarations: List -) : UDeclarationsExpression { - override fun evaluate() = null -} \ No newline at end of file +) : UDeclarationsExpression \ No newline at end of file diff --git a/plugins/uast-common/src/org/jetbrains/uast/expressions/UExpressionList.kt b/plugins/uast-common/src/org/jetbrains/uast/expressions/UExpressionList.kt index 6d23b04514a..e220b8fa6e2 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/expressions/UExpressionList.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/UExpressionList.kt @@ -15,11 +15,15 @@ */ package org.jetbrains.uast +import org.jetbrains.uast.visitor.UastVisitor + interface UExpressionList : UExpression { val expressions: List - override fun evaluate(): Any? = null - override fun traverse(callback: UastCallback) = expressions.forEach { it.handleTraverse(callback) } + override fun accept(visitor: UastVisitor) { + if (visitor.visitExpressionList(this)) return + expressions.acceptList(visitor) + } override fun logString() = log("UExpressionList", expressions) override fun renderString() = log("", expressions) diff --git a/plugins/uast-common/src/org/jetbrains/uast/expressions/ULabeledExpression.kt b/plugins/uast-common/src/org/jetbrains/uast/expressions/ULabeledExpression.kt index d729537c0f5..fcf35b620e1 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/expressions/ULabeledExpression.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/ULabeledExpression.kt @@ -15,12 +15,15 @@ */ package org.jetbrains.uast +import org.jetbrains.uast.visitor.UastVisitor + interface ULabeledExpression : UExpression { val label: String val expression: UExpression - override fun traverse(callback: UastCallback) { - expression.handleTraverse(callback) + override fun accept(visitor: UastVisitor) { + if (visitor.visitLabeledExpression(this)) return + expression.accept(visitor) } override fun evaluate() = expression.evaluate() diff --git a/plugins/uast-common/src/org/jetbrains/uast/expressions/ULambdaExpression.kt b/plugins/uast-common/src/org/jetbrains/uast/expressions/ULambdaExpression.kt index 9898c03e480..9766c51dfc4 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/expressions/ULambdaExpression.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/ULambdaExpression.kt @@ -15,13 +15,16 @@ */ package org.jetbrains.uast +import org.jetbrains.uast.visitor.UastVisitor + interface ULambdaExpression : UExpression { val valueParameters: List val body: UExpression - override fun traverse(callback: UastCallback) { - valueParameters.handleTraverseList(callback) - body.handleTraverse(callback) + override fun accept(visitor: UastVisitor) { + if (visitor.visitLambdaExpression(this)) return + valueParameters.acceptList(visitor) + body.accept(visitor) } override fun logString() = log("ULambdaExpression", valueParameters, body) diff --git a/plugins/uast-common/src/org/jetbrains/uast/expressions/ULiteralExpression.kt b/plugins/uast-common/src/org/jetbrains/uast/expressions/ULiteralExpression.kt index 6692c31867c..2ac3cfa58e8 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/expressions/ULiteralExpression.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/ULiteralExpression.kt @@ -15,6 +15,8 @@ */ package org.jetbrains.uast +import org.jetbrains.uast.visitor.UastVisitor + interface ULiteralExpression : UExpression { val value: Any? @@ -28,7 +30,10 @@ interface ULiteralExpression : UExpression { fun asString() = value?.toString() ?: "" - override fun traverse(callback: UastCallback) {} + override fun accept(visitor: UastVisitor) { + visitor.visitLiteralExpression(this) + } + override fun logString() = "ULiteralExpression (${asString()})" override fun renderString() = asString() } diff --git a/plugins/uast-common/src/org/jetbrains/uast/expressions/UNamedExpression.kt b/plugins/uast-common/src/org/jetbrains/uast/expressions/UNamedExpression.kt index fd259508122..0b9c2a6e871 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/expressions/UNamedExpression.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/UNamedExpression.kt @@ -15,14 +15,17 @@ */ package org.jetbrains.uast +import org.jetbrains.uast.visitor.UastVisitor + class UNamedExpression( override val name: String, override val parent: UElement ): UExpression, UNamed { lateinit var expression: UExpression - override fun traverse(callback: UastCallback) { - expression.handleTraverse(callback) + override fun accept(visitor: UastVisitor) { + if (visitor.visitElement(this)) return + expression.accept(visitor) } override fun logString() = log("UNamedExpression ($name)", expression) diff --git a/plugins/uast-common/src/org/jetbrains/uast/expressions/UObjectLiteralExpression.kt b/plugins/uast-common/src/org/jetbrains/uast/expressions/UObjectLiteralExpression.kt index 4c47b40dc62..5e153d3ea7b 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/expressions/UObjectLiteralExpression.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/UObjectLiteralExpression.kt @@ -15,11 +15,14 @@ */ package org.jetbrains.uast +import org.jetbrains.uast.visitor.UastVisitor + interface UObjectLiteralExpression : UExpression { val declaration: UClass - override fun traverse(callback: UastCallback) { - declaration.handleTraverse(callback) + override fun accept(visitor: UastVisitor) { + if (visitor.visitObjectLiteralExpression(this)) return + declaration.accept(visitor) } override fun logString() = log("UObjectLiteralExpression", declaration) diff --git a/plugins/uast-common/src/org/jetbrains/uast/expressions/UParenthesizedExpression.kt b/plugins/uast-common/src/org/jetbrains/uast/expressions/UParenthesizedExpression.kt index 1615c6472db..a03ac041278 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/expressions/UParenthesizedExpression.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/UParenthesizedExpression.kt @@ -15,11 +15,14 @@ */ package org.jetbrains.uast +import org.jetbrains.uast.visitor.UastVisitor + interface UParenthesizedExpression : UExpression { val expression: UExpression - override fun traverse(callback: UastCallback) { - expression.handleTraverse(callback) + override fun accept(visitor: UastVisitor) { + if (visitor.visitParenthesizedExpression(this)) return + expression.accept(visitor) } override fun evaluate() = expression.evaluate() diff --git a/plugins/uast-common/src/org/jetbrains/uast/expressions/UQualifiedExpression.kt b/plugins/uast-common/src/org/jetbrains/uast/expressions/UQualifiedExpression.kt index 115cf3364b6..93972c70759 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/expressions/UQualifiedExpression.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/UQualifiedExpression.kt @@ -15,6 +15,8 @@ */ package org.jetbrains.uast +import org.jetbrains.uast.visitor.UastVisitor + interface UQualifiedExpression : UExpression, UResolvable { val receiver: UExpression val selector: UExpression @@ -24,9 +26,10 @@ interface UQualifiedExpression : UExpression, UResolvable { override fun renderString() = receiver.renderString() + accessType.name + selector.renderString() - override fun traverse(callback: UastCallback) { - receiver.handleTraverse(callback) - selector.handleTraverse(callback) + override fun accept(visitor: UastVisitor) { + if (visitor.visitQualifiedExpression(this)) return + receiver.accept(visitor) + selector.accept(visitor) } override fun logString() = log("UQualifiedExpression", receiver, selector) diff --git a/plugins/uast-common/src/org/jetbrains/uast/expressions/USimpleReferenceExpression.kt b/plugins/uast-common/src/org/jetbrains/uast/expressions/USimpleReferenceExpression.kt index e6925872f65..4cf4ab38dd5 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/expressions/USimpleReferenceExpression.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/USimpleReferenceExpression.kt @@ -15,9 +15,15 @@ */ package org.jetbrains.uast -interface USimpleReferenceExpression : UExpression, UResolvable, LeafUElement { +import org.jetbrains.uast.visitor.UastVisitor + +interface USimpleReferenceExpression : UExpression, UResolvable { val identifier: String + override fun accept(visitor: UastVisitor) { + visitor.visitSimpleReferenceExpression(this) + } + override fun logString() = "USimpleReferenceExpression ($identifier)" override fun renderString() = identifier } \ No newline at end of file diff --git a/plugins/uast-common/src/org/jetbrains/uast/expressions/USuperExpression.kt b/plugins/uast-common/src/org/jetbrains/uast/expressions/USuperExpression.kt index e0e5949aca7..2edf91a02a4 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/expressions/USuperExpression.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/USuperExpression.kt @@ -15,7 +15,13 @@ */ package org.jetbrains.uast -interface USuperExpression : UExpression, LeafUElement { +import org.jetbrains.uast.visitor.UastVisitor + +interface USuperExpression : UExpression { override fun logString() = "USuperExpression" override fun renderString() = "super" + + override fun accept(visitor: UastVisitor) { + visitor.visitSuperExpression(this) + } } \ No newline at end of file diff --git a/plugins/uast-common/src/org/jetbrains/uast/expressions/UThisExpression.kt b/plugins/uast-common/src/org/jetbrains/uast/expressions/UThisExpression.kt index 8c9dfe2d132..bb82dc8ee58 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/expressions/UThisExpression.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/UThisExpression.kt @@ -15,7 +15,13 @@ */ package org.jetbrains.uast -interface UThisExpression : UExpression, LeafUElement { +import org.jetbrains.uast.visitor.UastVisitor + +interface UThisExpression : UExpression { override fun logString() = "UThisExpression" override fun renderString() = "this" + + override fun accept(visitor: UastVisitor) { + visitor.visitThisExpression(this) + } } \ No newline at end of file diff --git a/plugins/uast-common/src/org/jetbrains/uast/expressions/UUnaryExpression.kt b/plugins/uast-common/src/org/jetbrains/uast/expressions/UUnaryExpression.kt index 7fc8d6c2b55..3e3411a95bf 100644 --- a/plugins/uast-common/src/org/jetbrains/uast/expressions/UUnaryExpression.kt +++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/UUnaryExpression.kt @@ -16,24 +16,38 @@ package org.jetbrains.uast import org.jetbrains.uast.kinds.UastOperator +import org.jetbrains.uast.visitor.UastVisitor interface UUnaryExpression : UExpression { val operand: UExpression val operator: UastOperator - override fun traverse(callback: UastCallback) { - operand.handleTraverse(callback) + override fun accept(visitor: UastVisitor) { + if (visitor.visitUnaryExpression(this)) return + operand.accept(visitor) } } interface UPrefixExpression : UUnaryExpression { override val operator: UastPrefixOperator + + override fun accept(visitor: UastVisitor) { + if (visitor.visitPrefixExpression(this)) return + operand.accept(visitor) + } + override fun logString() = log("UPrefixExpression (${operator.text})", operand) override fun renderString() = operator.text + operand.renderString() } interface UPostfixExpression : UUnaryExpression { override val operator: UastPostfixOperator + + override fun accept(visitor: UastVisitor) { + if (visitor.visitPostfixExpression(this)) return + operand.accept(visitor) + } + override fun logString() = log("UPostfixExpression (${operator.text})", operand) override fun renderString() = operand.renderString() + operator.text } \ No newline at end of file diff --git a/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaDumbUElement.kt b/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaDumbUElement.kt index be17243358b..6bed5be5a53 100644 --- a/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaDumbUElement.kt +++ b/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaDumbUElement.kt @@ -16,14 +16,13 @@ package org.jetbrains.uast.java import com.intellij.psi.PsiElement -import org.jetbrains.uast.LeafUElement import org.jetbrains.uast.UElement import org.jetbrains.uast.psi.PsiElementBacked class JavaDumbUElement( override val psi: PsiElement?, override val parent: UElement -) : JavaAbstractUElement(), UElement, PsiElementBacked, LeafUElement { +) : JavaAbstractUElement(), UElement, PsiElementBacked { override fun logString() = "JavaDumbUElement" override fun renderString() = "" } \ No newline at end of file diff --git a/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUInstanceCheckExpression.kt b/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUInstanceCheckExpression.kt index 9a4b6ba7fbd..981aaf5433d 100644 --- a/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUInstanceCheckExpression.kt +++ b/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUInstanceCheckExpression.kt @@ -30,6 +30,4 @@ class JavaUInstanceCheckExpression( override val operationKind: UastBinaryExpressionWithTypeKind.InstanceCheck get() = UastBinaryExpressionWithTypeKind.INSTANCE_CHECK - - override fun evaluate() = null } \ No newline at end of file diff --git a/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaULiteralExpression.kt b/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaULiteralExpression.kt index 22a118c9580..0dfce0edbaa 100644 --- a/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaULiteralExpression.kt +++ b/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaULiteralExpression.kt @@ -24,7 +24,7 @@ class JavaULiteralExpression( override val psi: PsiLiteralExpression, override val parent: UElement ) : JavaAbstractUElement(), ULiteralExpression, PsiElementBacked, JavaUElementWithType { - override val asString by lz { psi.text } + override fun asString() = psi.text override fun evaluate() = psi.value override val value by lz { evaluate() } diff --git a/plugins/uast-java/src/org/jetbrains/uast/java/expressions/UnknownJavaExpression.kt b/plugins/uast-java/src/org/jetbrains/uast/java/expressions/UnknownJavaExpression.kt index 6a5438a51c0..44973510b85 100644 --- a/plugins/uast-java/src/org/jetbrains/uast/java/expressions/UnknownJavaExpression.kt +++ b/plugins/uast-java/src/org/jetbrains/uast/java/expressions/UnknownJavaExpression.kt @@ -22,6 +22,6 @@ import org.jetbrains.uast.psi.PsiElementBacked class UnknownJavaExpression( override val psi: PsiElement, override val parent: UElement -) : UExpression, PsiElementBacked, LeafUElement { +) : UExpression, PsiElementBacked { override fun logString() = "[!] UnknownJavaExpression ($psi)" } \ No newline at end of file diff --git a/plugins/uast-java/src/org/jetbrains/uast/java/expressions/javaUCallExpressions.kt b/plugins/uast-java/src/org/jetbrains/uast/java/expressions/javaUCallExpressions.kt index e6aaa6df35f..31d03b14ac7 100644 --- a/plugins/uast-java/src/org/jetbrains/uast/java/expressions/javaUCallExpressions.kt +++ b/plugins/uast-java/src/org/jetbrains/uast/java/expressions/javaUCallExpressions.kt @@ -144,7 +144,6 @@ class JavaArrayInitializerUCallExpression( get() = JavaUastCallKinds.ARRAY_INITIALIZER override fun resolve(context: UastContext) = null - override fun evaluate() = null } class JavaAnnotationArrayInitializerUCallExpression( diff --git a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/declarations/KotlinDumbUElement.kt b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/declarations/KotlinDumbUElement.kt index c33f3c77a2a..1d01aedea00 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/declarations/KotlinDumbUElement.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/declarations/KotlinDumbUElement.kt @@ -17,14 +17,13 @@ package org.jetbrains.kotlin.uast import com.intellij.psi.PsiElement -import org.jetbrains.uast.LeafUElement import org.jetbrains.uast.UElement import org.jetbrains.uast.psi.PsiElementBacked class KotlinDumbUElement( override val psi: PsiElement?, override val parent: UElement -) : KotlinAbstractUElement(), UElement, PsiElementBacked, LeafUElement { +) : KotlinAbstractUElement(), UElement, PsiElementBacked { override fun logString() = "KotlinDumbUElement" override fun renderString() = "" } \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/declarations/KotlinUAnnotationList.kt b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/declarations/KotlinUAnnotationList.kt index 985487b7a49..60eac7ef61c 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/declarations/KotlinUAnnotationList.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/declarations/KotlinUAnnotationList.kt @@ -19,9 +19,9 @@ package org.jetbrains.kotlin.uast import org.jetbrains.kotlin.psi.KtAnnotation import org.jetbrains.uast.UAnnotation import org.jetbrains.uast.UElement -import org.jetbrains.uast.UastCallback -import org.jetbrains.uast.handleTraverseList +import org.jetbrains.uast.acceptList import org.jetbrains.uast.psi.PsiElementBacked +import org.jetbrains.uast.visitor.UastVisitor class KotlinUAnnotationList( override val psi: KtAnnotation, @@ -31,7 +31,9 @@ class KotlinUAnnotationList( override fun logString() = "KotlinUAnnotationList" override fun renderString() = annotations.joinToString(" ") { it.renderString() } - override fun traverse(callback: UastCallback) { - annotations.handleTraverseList(callback) + + override fun accept(visitor: UastVisitor) { + if (visitor.visitElement(this)) return + annotations.acceptList(visitor) } } \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUDeclarationsExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUDeclarationsExpression.kt index e46bed5bbba..a1d8eacfde3 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUDeclarationsExpression.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUDeclarationsExpression.kt @@ -20,6 +20,4 @@ import org.jetbrains.kotlin.uast.KotlinAbstractUElement class KotlinUDeclarationsExpression(override val parent: UElement) : KotlinAbstractUElement(), UDeclarationsExpression { override lateinit var declarations: List internal set - - override fun evaluate() = null } \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinULiteralExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinULiteralExpression.kt index 2871d411fa5..b13592ee099 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinULiteralExpression.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinULiteralExpression.kt @@ -40,8 +40,7 @@ class KotlinStringULiteralExpression( override val parent: UElement ) : KotlinAbstractUElement(), ULiteralExpression, PsiElementBacked, KotlinUElementWithType, KotlinEvaluatableUElement { override val isNull = false - override val asString: String - get() = '"' + psi.text + '"' + override fun asString(): String = '"' + psi.text + '"' override val value: String get() = psi.text diff --git a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUSwitchExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUSwitchExpression.kt index 0eff37d5ef7..112792c82f5 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUSwitchExpression.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUSwitchExpression.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.uast.kinds.KotlinSpecialExpressionKinds import org.jetbrains.uast.* import org.jetbrains.uast.psi.PsiElementBacked +import org.jetbrains.uast.visitor.UastVisitor class KotlinUSwitchExpression( override val psi: KtWhenExpression, @@ -101,7 +102,8 @@ class KotlinUSwitchEntry( override fun logString() = log("KotlinUSwitchEntry", expression) - override fun traverse(callback: UastCallback) { - expression.handleTraverse(callback) + override fun accept(visitor: UastVisitor) { + if (visitor.visitElement(this)) return + expression.accept(visitor) } } \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/UnknownKotlinExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/UnknownKotlinExpression.kt index 2a8850c8188..b6ee1760844 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/UnknownKotlinExpression.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/UnknownKotlinExpression.kt @@ -19,13 +19,11 @@ package org.jetbrains.kotlin.uast import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.uast.UElement import org.jetbrains.uast.UExpression -import org.jetbrains.uast.UastCallback import org.jetbrains.uast.psi.PsiElementBacked class UnknownKotlinExpression( override val psi: KtExpression, override val parent: UElement ) : KotlinAbstractUElement(), UExpression, PsiElementBacked { - override fun traverse(callback: UastCallback) {} override fun logString() = "[!] UnknownKotlinExpression ($psi)" } \ No newline at end of file diff --git a/plugins/uast-kotlin/test/org.jetbrains.kotlin.uast/AbstractKotlinUastStructureTest.kt b/plugins/uast-kotlin/test/org.jetbrains.kotlin.uast/AbstractKotlinUastStructureTest.kt index 6e64a9d3b35..ab0ec3c7b8c 100644 --- a/plugins/uast-kotlin/test/org.jetbrains.kotlin.uast/AbstractKotlinUastStructureTest.kt +++ b/plugins/uast-kotlin/test/org.jetbrains.kotlin.uast/AbstractKotlinUastStructureTest.kt @@ -19,6 +19,8 @@ package org.jetbrains.kotlin.uast import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor import org.jetbrains.kotlin.test.KotlinTestUtils +import org.jetbrains.uast.UElement +import org.jetbrains.uast.visitor.UastVisitor import java.io.File abstract class AbstractKotlinUastStructureTest : KotlinLightCodeInsightFixtureTestCase() { @@ -28,6 +30,7 @@ abstract class AbstractKotlinUastStructureTest : KotlinLightCodeInsightFixtureTe val logFile = File(File(testDataPath, "log"), "$testName.txt") val renderFile = File(File(testDataPath, "render"), "$testName.txt") + val treeFile = File(File(testDataPath, "tree"), "$testName.txt") val psiFile = myFixture.file val uElement = KotlinUastLanguagePlugin.converter.convertWithParent(psiFile) ?: error("UFile was not created") @@ -42,6 +45,24 @@ abstract class AbstractKotlinUastStructureTest : KotlinLightCodeInsightFixtureTe throw e } KotlinTestUtils.assertEqualsToFile(renderFile, renderActual) + KotlinTestUtils.assertEqualsToFile(treeFile, genTree(uElement)) + } + + private fun genTree(node: UElement): String { + val builder = StringBuilder() + val visitor = object : UastVisitor() { + private tailrec fun getParentCount(node: UElement): Int { + val parent = node.parent ?: return 0 + return getParentCount(parent) + } + + override fun visitElement(node: UElement): Boolean { + builder.appendln(" ".repeat(getParentCount(node)) + node.javaClass.name) + return super.visitElement(node) + } + } + visitor.visitElement(node) + return builder.toString() } override fun getTestDataPath() = "plugins/uast-kotlin/testData"