diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/UElementVisitor.java b/plugins/lint/lint-api/src/com/android/tools/klint/client/api/UElementVisitor.java index 146f6b4a252..fb3ee689662 100644 --- a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/UElementVisitor.java +++ b/plugins/lint/lint-api/src/com/android/tools/klint/client/api/UElementVisitor.java @@ -16,13 +16,9 @@ package com.android.tools.klint.client.api; -import static com.android.SdkConstants.ANDROID_PKG; -import static com.android.SdkConstants.R_CLASS; - import com.android.annotations.NonNull; import com.android.annotations.Nullable; import com.android.annotations.VisibleForTesting; -import com.android.resources.ResourceType; import com.android.tools.klint.detector.api.Detector; import com.android.tools.klint.detector.api.Detector.JavaPsiScanner; import com.android.tools.klint.detector.api.Detector.UastScanner; @@ -35,30 +31,15 @@ import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.StandardFileSystems; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.JavaElementVisitor; -import com.intellij.psi.JavaRecursiveElementVisitor; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiJavaCodeReferenceElement; -import com.intellij.psi.PsiManager; -import com.intellij.psi.PsiMethod; -import com.intellij.psi.PsiMethodCallExpression; -import com.intellij.psi.PsiNewExpression; -import com.intellij.psi.PsiReferenceExpression; -import com.intellij.psi.PsiTypeParameter; - +import com.intellij.psi.*; import org.jetbrains.uast.*; -import org.jetbrains.uast.expressions.UTypeReferenceExpression; import org.jetbrains.uast.util.UastExpressionUtils; import org.jetbrains.uast.visitor.AbstractUastVisitor; import org.jetbrains.uast.visitor.UastVisitor; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; + +import static com.android.SdkConstants.ANDROID_PKG; /** * Specialized visitor for running detectors on a Java AST. diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/UastLintUtils.java b/plugins/lint/lint-api/src/com/android/tools/klint/client/api/UastLintUtils.java index 56a94c65eee..84922d24063 100644 --- a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/UastLintUtils.java +++ b/plugins/lint/lint-api/src/com/android/tools/klint/client/api/UastLintUtils.java @@ -26,7 +26,7 @@ import com.google.common.base.Joiner; import com.intellij.psi.*; import org.jetbrains.uast.*; -import org.jetbrains.uast.expressions.UReferenceExpression; +import org.jetbrains.uast.UReferenceExpression; import org.jetbrains.uast.java.JavaAbstractUExpression; import org.jetbrains.uast.java.JavaUDeclarationsExpression; diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/ConstantEvaluator.java b/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/ConstantEvaluator.java index 7be5a256c9c..99a602ca2bd 100644 --- a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/ConstantEvaluator.java +++ b/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/ConstantEvaluator.java @@ -64,7 +64,7 @@ import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.uast.*; -import org.jetbrains.uast.expressions.UReferenceExpression; +import org.jetbrains.uast.UReferenceExpression; import org.jetbrains.uast.util.UastExpressionUtils; import org.jetbrains.uast.visitor.AbstractUastVisitor; diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/Detector.java b/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/Detector.java index 5814cc9df41..fc60ac8b3fb 100644 --- a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/Detector.java +++ b/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/Detector.java @@ -39,7 +39,7 @@ import org.jetbrains.uast.UCallExpression; import org.jetbrains.uast.UClass; import org.jetbrains.uast.UElement; import org.jetbrains.uast.UMethod; -import org.jetbrains.uast.expressions.UReferenceExpression; +import org.jetbrains.uast.UReferenceExpression; import org.jetbrains.uast.visitor.UastVisitor; import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode; import org.jetbrains.org.objectweb.asm.tree.ClassNode; diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/ResourceEvaluator.java b/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/ResourceEvaluator.java index 9519a785f56..447731cf446 100644 --- a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/ResourceEvaluator.java +++ b/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/ResourceEvaluator.java @@ -60,7 +60,7 @@ import org.jetbrains.uast.UIfExpression; import org.jetbrains.uast.UParenthesizedExpression; import org.jetbrains.uast.UQualifiedReferenceExpression; import org.jetbrains.uast.UastUtils; -import org.jetbrains.uast.expressions.UReferenceExpression; +import org.jetbrains.uast.UReferenceExpression; import java.util.EnumSet; import java.util.List; diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/TypeEvaluator.java b/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/TypeEvaluator.java index 4a9f5a64e17..74afe269b45 100644 --- a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/TypeEvaluator.java +++ b/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/TypeEvaluator.java @@ -56,7 +56,7 @@ import org.jetbrains.uast.UExpression; import org.jetbrains.uast.UMethod; import org.jetbrains.uast.UVariable; import org.jetbrains.uast.UastUtils; -import org.jetbrains.uast.expressions.UReferenceExpression; +import org.jetbrains.uast.UReferenceExpression; import org.jetbrains.uast.util.UastExpressionUtils; import java.util.ListIterator; diff --git a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/AlwaysShowActionDetector.java b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/AlwaysShowActionDetector.java index 5bcd54adb1c..7a67588bc39 100644 --- a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/AlwaysShowActionDetector.java +++ b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/AlwaysShowActionDetector.java @@ -38,7 +38,7 @@ import com.android.tools.klint.detector.api.XmlContext; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiField; -import org.jetbrains.uast.expressions.UReferenceExpression; +import org.jetbrains.uast.UReferenceExpression; import org.jetbrains.uast.visitor.UastVisitor; import org.w3c.dom.Attr; diff --git a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/AnnotationDetector.java b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/AnnotationDetector.java index 451594e1825..8e14c9489f4 100644 --- a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/AnnotationDetector.java +++ b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/AnnotationDetector.java @@ -16,102 +16,33 @@ package com.android.tools.klint.checks; -import static com.android.SdkConstants.ATTR_VALUE; -import static com.android.SdkConstants.FQCN_SUPPRESS_LINT; -import static com.android.SdkConstants.INT_DEF_ANNOTATION; -import static com.android.SdkConstants.STRING_DEF_ANNOTATION; -import static com.android.SdkConstants.SUPPORT_ANNOTATIONS_PREFIX; -import static com.android.SdkConstants.TYPE_DEF_FLAG_ATTRIBUTE; -import static com.android.tools.klint.checks.PermissionRequirement.getAnnotationBooleanValue; -import static com.android.tools.klint.checks.SupportAnnotationDetector.ATTR_ALL_OF; -import static com.android.tools.klint.checks.SupportAnnotationDetector.ATTR_ANY_OF; -import static com.android.tools.klint.checks.SupportAnnotationDetector.ATTR_FROM; -import static com.android.tools.klint.checks.SupportAnnotationDetector.ATTR_MAX; -import static com.android.tools.klint.checks.SupportAnnotationDetector.ATTR_MIN; -import static com.android.tools.klint.checks.SupportAnnotationDetector.ATTR_MULTIPLE; -import static com.android.tools.klint.checks.SupportAnnotationDetector.ATTR_TO; -import static com.android.tools.klint.checks.SupportAnnotationDetector.CHECK_RESULT_ANNOTATION; -import static com.android.tools.klint.checks.SupportAnnotationDetector.FLOAT_RANGE_ANNOTATION; -import static com.android.tools.klint.checks.SupportAnnotationDetector.INT_RANGE_ANNOTATION; -import static com.android.tools.klint.checks.SupportAnnotationDetector.PERMISSION_ANNOTATION; -import static com.android.tools.klint.checks.SupportAnnotationDetector.PERMISSION_ANNOTATION_READ; -import static com.android.tools.klint.checks.SupportAnnotationDetector.PERMISSION_ANNOTATION_WRITE; -import static com.android.tools.klint.checks.SupportAnnotationDetector.SIZE_ANNOTATION; -import static com.android.tools.klint.checks.SupportAnnotationDetector.filterRelevantAnnotations; -import static com.android.tools.klint.checks.SupportAnnotationDetector.getDoubleAttribute; -import static com.android.tools.klint.checks.SupportAnnotationDetector.getLongAttribute; -import static com.android.tools.klint.client.api.JavaParser.TYPE_DOUBLE; -import static com.android.tools.klint.client.api.JavaParser.TYPE_FLOAT; -import static com.android.tools.klint.client.api.JavaParser.TYPE_INT; -import static com.android.tools.klint.client.api.JavaParser.TYPE_LONG; -import static com.android.tools.klint.client.api.JavaParser.TYPE_STRING; -import static com.android.tools.klint.detector.api.LintUtils.findSubstring; -import static com.android.tools.klint.detector.api.LintUtils.getAutoBoxedType; -import static com.android.tools.klint.detector.api.ResourceEvaluator.COLOR_INT_ANNOTATION; -import static com.android.tools.klint.detector.api.ResourceEvaluator.PX_ANNOTATION; -import static com.android.tools.klint.detector.api.ResourceEvaluator.RES_SUFFIX; - import com.android.annotations.NonNull; import com.android.annotations.Nullable; import com.android.tools.klint.client.api.ExternalReferenceExpression; import com.android.tools.klint.client.api.IssueRegistry; -import com.android.tools.klint.client.api.JavaEvaluator; import com.android.tools.klint.client.api.UastLintUtils; -import com.android.tools.klint.detector.api.Category; -import com.android.tools.klint.detector.api.ConstantEvaluator; -import com.android.tools.klint.detector.api.Detector; -import com.android.tools.klint.detector.api.Implementation; -import com.android.tools.klint.detector.api.Issue; -import com.android.tools.klint.detector.api.JavaContext; -import com.android.tools.klint.detector.api.Location; -import com.android.tools.klint.detector.api.Scope; -import com.android.tools.klint.detector.api.Severity; -import com.android.tools.klint.detector.api.TextFormat; +import com.android.tools.klint.detector.api.*; import com.google.common.base.Joiner; -import com.google.common.base.Splitter; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; -import com.intellij.psi.PsiAnnotation; -import com.intellij.psi.PsiAnnotationMemberValue; -import com.intellij.psi.PsiAnnotationOwner; -import com.intellij.psi.PsiArrayInitializerMemberValue; -import com.intellij.psi.PsiArrayType; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiClassType; -import com.intellij.psi.PsiDeclarationStatement; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiExpression; -import com.intellij.psi.PsiField; -import com.intellij.psi.PsiJavaCodeReferenceElement; -import com.intellij.psi.PsiLiteral; -import com.intellij.psi.PsiLocalVariable; -import com.intellij.psi.PsiMethod; -import com.intellij.psi.PsiModifierList; -import com.intellij.psi.PsiModifierListOwner; -import com.intellij.psi.PsiNameValuePair; -import com.intellij.psi.PsiParameter; -import com.intellij.psi.PsiReferenceExpression; -import com.intellij.psi.PsiType; -import com.intellij.psi.PsiVariable; +import com.intellij.psi.*; import com.intellij.psi.util.InheritanceUtil; -import com.intellij.psi.util.PsiTreeUtil; - import org.jetbrains.uast.*; -import org.jetbrains.uast.expressions.UReferenceExpression; import org.jetbrains.uast.java.JavaUAnnotation; import org.jetbrains.uast.java.JavaUTypeCastExpression; import org.jetbrains.uast.util.UastExpressionUtils; import org.jetbrains.uast.visitor.AbstractUastVisitor; import org.jetbrains.uast.visitor.UastVisitor; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.ListIterator; -import java.util.Map; -import java.util.Set; +import java.util.*; + +import static com.android.SdkConstants.*; +import static com.android.tools.klint.checks.PermissionRequirement.getAnnotationBooleanValue; +import static com.android.tools.klint.checks.SupportAnnotationDetector.*; +import static com.android.tools.klint.client.api.JavaParser.*; +import static com.android.tools.klint.detector.api.LintUtils.getAutoBoxedType; +import static com.android.tools.klint.detector.api.ResourceEvaluator.*; /** * Checks annotations to make sure they are valid diff --git a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/ApiDetector.java b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/ApiDetector.java index 95e0dd32c60..f453b619fb2 100644 --- a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/ApiDetector.java +++ b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/ApiDetector.java @@ -40,8 +40,6 @@ import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.android.inspections.klint.IntellijLintUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.uast.*; -import org.jetbrains.uast.expressions.UReferenceExpression; -import org.jetbrains.uast.expressions.UTypeReferenceExpression; import org.jetbrains.uast.util.UastExpressionUtils; import org.jetbrains.uast.visitor.AbstractUastVisitor; import org.jetbrains.uast.visitor.UastVisitor; @@ -1028,6 +1026,10 @@ public class ApiDetector extends ResourceXmlDetector } } } + } else { + for (UTypeReferenceExpression t : aClass.getUastSuperTypes()) { + checkType(t.getType(), t); + } } return super.visitClass(aClass); @@ -1320,8 +1322,8 @@ public class ApiDetector extends ResourceXmlDetector } @Override - public boolean visitTryExpression(UTryExpression statement) { - if (statement.isResources()) { + public boolean visitTryExpression(@NotNull UTryExpression statement) { + if (statement.getHasResources()) { int api = 19; // minSdk for try with resources int minSdk = getMinSdk(mContext); diff --git a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/BatteryDetector.java b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/BatteryDetector.java index ef8c5295560..7853317c718 100644 --- a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/BatteryDetector.java +++ b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/BatteryDetector.java @@ -16,26 +16,12 @@ package com.android.tools.klint.checks; -import static com.android.SdkConstants.ANDROID_URI; -import static com.android.SdkConstants.ATTR_NAME; -import static com.android.SdkConstants.TAG_RECEIVER; - import com.android.annotations.NonNull; import com.android.annotations.Nullable; -import com.android.tools.klint.detector.api.Category; -import com.android.tools.klint.detector.api.Detector; -import com.android.tools.klint.detector.api.Implementation; -import com.android.tools.klint.detector.api.Issue; -import com.android.tools.klint.detector.api.JavaContext; -import com.android.tools.klint.detector.api.ResourceXmlDetector; -import com.android.tools.klint.detector.api.Scope; -import com.android.tools.klint.detector.api.Severity; -import com.android.tools.klint.detector.api.XmlContext; -import com.intellij.psi.JavaElementVisitor; +import com.android.tools.klint.detector.api.*; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiField; - -import org.jetbrains.uast.expressions.UReferenceExpression; +import org.jetbrains.uast.UReferenceExpression; import org.jetbrains.uast.visitor.UastVisitor; import org.w3c.dom.Attr; import org.w3c.dom.Element; @@ -45,6 +31,8 @@ import java.util.Collections; import java.util.EnumSet; import java.util.List; +import static com.android.SdkConstants.*; + /** * Checks looking for issues that negatively affect battery life */ 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 dd8831860ff..99bf2582fe5 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 @@ -39,7 +39,7 @@ import com.intellij.psi.PsiMethod; import org.jetbrains.uast.UElement; import org.jetbrains.uast.UMethod; import org.jetbrains.uast.USuperExpression; -import org.jetbrains.uast.expressions.UReferenceExpression; +import org.jetbrains.uast.UReferenceExpression; import org.jetbrains.uast.visitor.AbstractUastVisitor; import org.jetbrains.uast.visitor.UastVisitor; 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 106f17f5970..033e7721829 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 @@ -63,7 +63,7 @@ import org.jetbrains.uast.UVariable; import org.jetbrains.uast.UWhileExpression; import org.jetbrains.uast.UastCallKind; import org.jetbrains.uast.UastUtils; -import org.jetbrains.uast.expressions.UReferenceExpression; +import org.jetbrains.uast.UReferenceExpression; import org.jetbrains.uast.util.UastExpressionUtils; import org.jetbrains.uast.visitor.AbstractUastVisitor; import org.jetbrains.uast.visitor.UastVisitor; 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 5ec943bf1df..02cf13c4bec 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 @@ -16,41 +16,12 @@ package com.android.tools.klint.checks; -import static com.android.SdkConstants.RESOURCE_CLZ_ID; -import static com.android.tools.klint.detector.api.LintUtils.skipParentheses; - import com.android.annotations.NonNull; import com.android.annotations.Nullable; -import com.android.tools.klint.detector.api.Category; -import com.android.tools.klint.detector.api.Detector; -import com.android.tools.klint.detector.api.Implementation; -import com.android.tools.klint.detector.api.Issue; -import com.android.tools.klint.detector.api.JavaContext; -import com.android.tools.klint.detector.api.Location; -import com.android.tools.klint.detector.api.Scope; -import com.android.tools.klint.detector.api.Severity; +import com.android.tools.klint.detector.api.*; import com.google.common.collect.Maps; -import com.intellij.psi.PsiBreakStatement; -import com.intellij.psi.PsiContinueStatement; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiIfStatement; -import com.intellij.psi.PsiJavaToken; -import com.intellij.psi.PsiLoopStatement; import com.intellij.psi.PsiMethod; -import com.intellij.psi.PsiReturnStatement; -import com.intellij.psi.PsiStatement; -import com.intellij.psi.PsiWhiteSpace; - -import org.jetbrains.uast.UArrayAccessExpression; import org.jetbrains.uast.*; -import org.jetbrains.uast.UCallExpression; -import org.jetbrains.uast.UElement; -import org.jetbrains.uast.UExpression; -import org.jetbrains.uast.ULocalVariable; -import org.jetbrains.uast.UMethod; -import org.jetbrains.uast.UQualifiedReferenceExpression; -import org.jetbrains.uast.UastUtils; -import org.jetbrains.uast.expressions.UReferenceExpression; import org.jetbrains.uast.util.UastExpressionUtils; import org.jetbrains.uast.visitor.AbstractUastVisitor; import org.jetbrains.uast.visitor.UastVisitor; @@ -59,6 +30,8 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import static com.android.SdkConstants.RESOURCE_CLZ_ID; + /** * Detector looking for cut & paste issues */ 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 a547753c172..1bad2d5527f 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 @@ -16,32 +16,6 @@ package com.android.tools.klint.checks; -import static com.android.SdkConstants.ANDROID_MANIFEST_XML; -import static com.android.SdkConstants.ANDROID_URI; -import static com.android.SdkConstants.ATTR_ICON; -import static com.android.SdkConstants.DOT_9PNG; -import static com.android.SdkConstants.DOT_GIF; -import static com.android.SdkConstants.DOT_JPEG; -import static com.android.SdkConstants.DOT_JPG; -import static com.android.SdkConstants.DOT_PNG; -import static com.android.SdkConstants.DOT_WEBP; -import static com.android.SdkConstants.DOT_XML; -import static com.android.SdkConstants.DRAWABLE_FOLDER; -import static com.android.SdkConstants.DRAWABLE_HDPI; -import static com.android.SdkConstants.DRAWABLE_LDPI; -import static com.android.SdkConstants.DRAWABLE_MDPI; -import static com.android.SdkConstants.DRAWABLE_PREFIX; -import static com.android.SdkConstants.DRAWABLE_XHDPI; -import static com.android.SdkConstants.DRAWABLE_XXHDPI; -import static com.android.SdkConstants.DRAWABLE_XXXHDPI; -import static com.android.SdkConstants.TAG_ACTIVITY; -import static com.android.SdkConstants.TAG_APPLICATION; -import static com.android.SdkConstants.TAG_ITEM; -import static com.android.SdkConstants.TAG_PROVIDER; -import static com.android.SdkConstants.TAG_RECEIVER; -import static com.android.SdkConstants.TAG_SERVICE; -import static com.android.tools.klint.detector.api.LintUtils.endsWith; - import com.android.annotations.NonNull; import com.android.annotations.Nullable; import com.android.builder.model.ProductFlavor; @@ -50,74 +24,31 @@ import com.android.ide.common.resources.ResourceUrl; import com.android.resources.Density; import com.android.resources.ResourceFolderType; import com.android.resources.ResourceType; -import com.android.tools.klint.detector.api.Category; -import com.android.tools.klint.detector.api.Context; -import com.android.tools.klint.detector.api.Detector; -import com.android.tools.klint.detector.api.Implementation; -import com.android.tools.klint.detector.api.Issue; -import com.android.tools.klint.detector.api.JavaContext; -import com.android.tools.klint.detector.api.LintUtils; -import com.android.tools.klint.detector.api.Location; -import com.android.tools.klint.detector.api.Project; -import com.android.tools.klint.detector.api.ResourceEvaluator; -import com.android.tools.klint.detector.api.ResourceXmlDetector; -import com.android.tools.klint.detector.api.Scope; -import com.android.tools.klint.detector.api.Severity; -import com.android.tools.klint.detector.api.XmlContext; -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Multimap; -import com.google.common.collect.Sets; -import com.intellij.psi.JavaRecursiveElementVisitor; -import com.intellij.psi.PsiAnonymousClass; +import com.android.tools.klint.detector.api.*; +import com.google.common.collect.*; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiExpression; -import com.intellij.psi.PsiMethod; -import com.intellij.psi.PsiMethodCallExpression; -import com.intellij.psi.PsiReferenceExpression; -import com.intellij.psi.util.PsiTreeUtil; - -import org.jetbrains.uast.UAnonymousClass; -import org.jetbrains.uast.UCallExpression; -import org.jetbrains.uast.UClass; -import org.jetbrains.uast.UElement; -import org.jetbrains.uast.UExpression; -import org.jetbrains.uast.UMethod; -import org.jetbrains.uast.USimpleNameReferenceExpression; -import org.jetbrains.uast.UastUtils; -import org.jetbrains.uast.expressions.UReferenceExpression; +import org.jetbrains.uast.*; import org.jetbrains.uast.util.UastExpressionUtils; import org.jetbrains.uast.visitor.AbstractUastVisitor; import org.jetbrains.uast.visitor.UastVisitor; import org.w3c.dom.Element; -import java.awt.Dimension; -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; -import java.util.Locale; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - import javax.imageio.ImageIO; import javax.imageio.ImageReader; import javax.imageio.stream.ImageInputStream; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.util.*; +import java.util.List; +import java.util.Map.Entry; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static com.android.SdkConstants.*; +import static com.android.tools.klint.detector.api.LintUtils.endsWith; /** * Checks for common icon problems, such as wrong icon sizes, placing icons in the 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 ac1b65d44f8..62a422e2141 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 @@ -60,7 +60,7 @@ import org.jetbrains.uast.USuperExpression; import org.jetbrains.uast.UThisExpression; import org.jetbrains.uast.UThrowExpression; import org.jetbrains.uast.UastUtils; -import org.jetbrains.uast.expressions.UReferenceExpression; +import org.jetbrains.uast.UReferenceExpression; import org.jetbrains.uast.util.UastExpressionUtils; import org.jetbrains.uast.visitor.AbstractUastVisitor; import org.jetbrains.uast.visitor.UastVisitor; diff --git a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/MergeRootFrameLayoutDetector.java b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/MergeRootFrameLayoutDetector.java index 26f6e1cab45..7bc51b36335 100644 --- a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/MergeRootFrameLayoutDetector.java +++ b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/MergeRootFrameLayoutDetector.java @@ -16,58 +16,24 @@ package com.android.tools.klint.checks; -import static com.android.SdkConstants.ANDROID_URI; -import static com.android.SdkConstants.ATTR_BACKGROUND; -import static com.android.SdkConstants.ATTR_FOREGROUND; -import static com.android.SdkConstants.ATTR_LAYOUT; -import static com.android.SdkConstants.ATTR_LAYOUT_GRAVITY; -import static com.android.SdkConstants.FRAME_LAYOUT; -import static com.android.SdkConstants.LAYOUT_RESOURCE_PREFIX; -import static com.android.SdkConstants.VIEW_INCLUDE; - import com.android.annotations.NonNull; import com.android.annotations.Nullable; import com.android.resources.ResourceType; import com.android.tools.klint.client.api.AndroidReference; import com.android.tools.klint.client.api.UastLintUtils; -import com.android.tools.klint.detector.api.Category; -import com.android.tools.klint.detector.api.Context; -import com.android.tools.klint.detector.api.Detector; -import com.android.tools.klint.detector.api.Detector.JavaPsiScanner; -import com.android.tools.klint.detector.api.Implementation; -import com.android.tools.klint.detector.api.Issue; -import com.android.tools.klint.detector.api.JavaContext; -import com.android.tools.klint.detector.api.LayoutDetector; -import com.android.tools.klint.detector.api.LintUtils; -import com.android.tools.klint.detector.api.Location; +import com.android.tools.klint.detector.api.*; import com.android.tools.klint.detector.api.Location.Handle; -import com.android.tools.klint.detector.api.Scope; -import com.android.tools.klint.detector.api.Severity; -import com.android.tools.klint.detector.api.XmlContext; import com.android.utils.Pair; -import com.intellij.psi.JavaElementVisitor; -import com.intellij.psi.PsiExpression; -import com.intellij.psi.PsiMethod; -import com.intellij.psi.PsiMethodCallExpression; -import com.intellij.psi.PsiReferenceExpression; - import org.jetbrains.uast.UCallExpression; import org.jetbrains.uast.UExpression; import org.jetbrains.uast.UMethod; -import org.jetbrains.uast.UQualifiedReferenceExpression; -import org.jetbrains.uast.expressions.UReferenceExpression; import org.jetbrains.uast.visitor.UastVisitor; import org.w3c.dom.Element; import org.w3c.dom.Node; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.EnumSet; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; + +import static com.android.SdkConstants.*; /** * Checks whether a root FrameLayout can be replaced with a {@code } tag. diff --git a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/PermissionFinder.java b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/PermissionFinder.java index 1f1357ac9c3..c95c3bff9eb 100644 --- a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/PermissionFinder.java +++ b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/PermissionFinder.java @@ -30,7 +30,6 @@ import com.intellij.psi.PsiField; import com.intellij.psi.PsiVariable; import org.jetbrains.uast.*; -import org.jetbrains.uast.expressions.UReferenceExpression; import org.jetbrains.uast.util.UastExpressionUtils; import java.util.List; diff --git a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/RecyclerViewDetector.java b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/RecyclerViewDetector.java index ccc73374453..99bfb72dc8d 100644 --- a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/RecyclerViewDetector.java +++ b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/RecyclerViewDetector.java @@ -40,7 +40,6 @@ import com.intellij.psi.PsiParameter; import com.intellij.psi.PsiVariable; import org.jetbrains.uast.*; -import org.jetbrains.uast.expressions.UReferenceExpression; import org.jetbrains.uast.util.UastExpressionUtils; import org.jetbrains.uast.visitor.AbstractUastVisitor; diff --git a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/ServiceCastDetector.java b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/ServiceCastDetector.java index 3313cddfb09..0fa80de7507 100644 --- a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/ServiceCastDetector.java +++ b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/ServiceCastDetector.java @@ -36,7 +36,7 @@ import org.jetbrains.uast.UElement; import org.jetbrains.uast.UExpression; import org.jetbrains.uast.UMethod; import org.jetbrains.uast.UastUtils; -import org.jetbrains.uast.expressions.UReferenceExpression; +import org.jetbrains.uast.UReferenceExpression; import org.jetbrains.uast.util.UastExpressionUtils; import org.jetbrains.uast.visitor.UastVisitor; 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 8cfe511c687..4dbd36118f1 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 @@ -78,7 +78,7 @@ import org.jetbrains.uast.UCallExpression; import org.jetbrains.uast.UExpression; import org.jetbrains.uast.ULiteralExpression; import org.jetbrains.uast.UMethod; -import org.jetbrains.uast.expressions.UReferenceExpression; +import org.jetbrains.uast.UReferenceExpression; import org.jetbrains.uast.util.UastExpressionUtils; import org.jetbrains.uast.visitor.UastVisitor; import org.w3c.dom.Element; 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 28bb1c10e71..14cf7c24c39 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 @@ -88,7 +88,6 @@ import com.intellij.psi.PsiType; import com.intellij.psi.PsiVariable; import org.jetbrains.uast.*; -import org.jetbrains.uast.expressions.UReferenceExpression; import org.jetbrains.uast.java.JavaUAnnotation; import org.jetbrains.uast.util.UastExpressionUtils; import org.jetbrains.uast.visitor.AbstractUastVisitor; diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt index 4c54c66a433..3912b9ec744 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt @@ -18,17 +18,13 @@ package org.jetbrains.uast.kotlin import com.intellij.lang.Language import com.intellij.openapi.project.Project -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiFile -import com.intellij.psi.PsiVariable +import com.intellij.psi.* import com.intellij.psi.impl.source.tree.LeafPsiElement import com.intellij.psi.util.PsiTreeUtil import org.jetbrains.kotlin.asJava.LightClassUtil import org.jetbrains.kotlin.asJava.classes.KtLightClass -import org.jetbrains.kotlin.asJava.elements.FakeFileForLightClass -import org.jetbrains.kotlin.asJava.elements.KtLightField -import org.jetbrains.kotlin.asJava.elements.KtLightMethod -import org.jetbrains.kotlin.asJava.elements.KtLightParameter +import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade +import org.jetbrains.kotlin.asJava.elements.* import org.jetbrains.kotlin.asJava.toLightClass import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper import org.jetbrains.kotlin.descriptors.ConstructorDescriptor @@ -41,8 +37,7 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.uast.* import org.jetbrains.uast.java.JavaUastLanguagePlugin import org.jetbrains.uast.kotlin.declarations.KotlinUMethod -import org.jetbrains.uast.kotlin.expressions.KotlinUBreakExpression -import org.jetbrains.uast.kotlin.expressions.KotlinUContinueExpression +import org.jetbrains.uast.kotlin.expressions.* import org.jetbrains.uast.kotlin.kinds.KotlinSpecialExpressionKinds import org.jetbrains.uast.kotlin.psi.UastKotlinPsiParameter import org.jetbrains.uast.kotlin.psi.UastKotlinPsiVariable @@ -73,6 +68,7 @@ class KotlinUastLanguagePlugin(override val project: Project) : UastLanguagePlug override fun convertElementWithParent(element: PsiElement, requiredType: Class?): UElement? { if (element !is PsiElement) return null if (element is PsiFile) return convertDeclaration(element, null, requiredType) + if (element is KtLightClassForFacade) return convertDeclaration(element, null, requiredType) val parent = element.parent ?: return null val parentUElement = convertElementWithParent(parent, null) ?: return null @@ -191,6 +187,13 @@ internal object KotlinConverter { is KtContainerNode -> element.getExpression()?.let { KotlinConverter.convertExpression(it, parent, requiredType) } ?: UastEmptyExpression + is KtLightAnnotation.LightExpressionValue<*> -> { + val expression = element.originalExpression + when (expression) { + is KtExpression -> KotlinConverter.convertExpression(expression, parent, requiredType) + else -> UastEmptyExpression + } + } else -> { if (element is LeafPsiElement && element.elementType == KtTokens.IDENTIFIER) { el { UIdentifier(element, parent) } @@ -209,20 +212,6 @@ internal object KotlinConverter { val variable = KotlinUVariable.create(UastKotlinPsiVariable.create(psi, parentPsiElement, parent!!), parent) return KotlinUDeclarationsExpression(parent).apply { declarations = listOf(variable) } } - - private fun convertStringTemplateExpression( - expression: KtStringTemplateExpression, - parent: UElement?, - i: Int - ): UExpression { - return if (i == 1) KotlinStringTemplateUBinaryExpression(expression, parent).apply { - leftOperand = convert(expression.entries[0], this) - rightOperand = convert(expression.entries[1], this) - } else KotlinStringTemplateUBinaryExpression(expression, parent).apply { - leftOperand = convertStringTemplateExpression(expression, parent, i - 1) - rightOperand = convert(expression.entries[i], this) - } - } internal fun convert(entry: KtStringTemplateEntry, parent: UElement?): UExpression = when (entry) { is KtStringTemplateEntryWithExpression -> convertOrEmpty(entry.expression, parent) @@ -242,7 +231,7 @@ internal object KotlinConverter { else if (expression.entries.size == 1) convert(expression.entries[0], parent) else - convertStringTemplateExpression(expression, parent, expression.entries.size - 1) + KotlinStringTemplateUPolyadicExpression(expression, parent) } is KtDestructuringDeclaration -> expr { KotlinUDeclarationsExpression(parent).apply { @@ -267,7 +256,12 @@ internal object KotlinConverter { KotlinUSimpleReferenceExpression(expression, expression.getReferencedName(), parent) } is KtCallExpression -> expr { KotlinUFunctionCallExpression(expression, parent) } - is KtBinaryExpression -> expr { KotlinUBinaryExpression(expression, parent) } + is KtBinaryExpression -> { + if (expression.operationToken == KtTokens.ELVIS) { + expr { createElvisExpression(expression, parent) ?: UastEmptyExpression } + } + else expr { KotlinUBinaryExpression(expression, parent) } + } is KtParenthesizedExpression -> expr { KotlinUParenthesizedExpression(expression, parent) } is KtPrefixExpression -> expr { KotlinUPrefixExpression(expression, parent) } is KtPostfixExpression -> expr { KotlinUPostfixExpression(expression, parent) } @@ -290,6 +284,20 @@ internal object KotlinConverter { is KtArrayAccessExpression -> expr { KotlinUArrayAccessExpression(expression, parent) } is KtLambdaExpression -> expr { KotlinULambdaExpression(expression, parent) } is KtBinaryExpressionWithTypeRHS -> expr { KotlinUBinaryExpressionWithType(expression, parent) } + is KtClassOrObject -> expr { + expression.toLightClass()?.let { lightClass -> + KotlinUDeclarationsExpression(parent).apply { + declarations = listOf(KotlinUClass.create(lightClass, this)) + } + } ?: UastEmptyExpression + } + is KtFunction -> if (expression.name.isNullOrEmpty()) { + expr { createLocalFunctionLambdaExpression(expression, parent) } + } + else { + expr { createLocalFunctionDeclaration(expression, parent) } + } + else -> UnknownKotlinExpression(expression, parent) }} diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUClass.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUClass.kt index 560ec1c993d..e68716b6265 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUClass.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUClass.kt @@ -19,9 +19,12 @@ package org.jetbrains.uast.kotlin import com.intellij.psi.PsiAnonymousClass import com.intellij.psi.PsiClass import com.intellij.psi.PsiElement +import com.intellij.psi.PsiMethod import org.jetbrains.kotlin.asJava.classes.KtLightClass import org.jetbrains.kotlin.asJava.elements.KtLightMethod import org.jetbrains.kotlin.asJava.toLightMethods +import org.jetbrains.kotlin.load.java.JvmAbi +import org.jetbrains.kotlin.psi.KtEnumEntry import org.jetbrains.kotlin.psi.KtObjectDeclaration import org.jetbrains.uast.* import org.jetbrains.uast.java.AbstractJavaUClass @@ -31,7 +34,9 @@ class KotlinUClass private constructor( psi: KtLightClass, override val containingElement: UElement? ) : AbstractJavaUClass(), PsiClass by psi { + val ktClass = psi.kotlinOrigin + override val psi = unwrap(psi) override fun getOriginalElement(): PsiElement? { @@ -40,15 +45,25 @@ class KotlinUClass private constructor( override val uastAnchor: UElement get() = UIdentifier(psi.nameIdentifier, this) - + + override val uastNestedClasses: List by lz { + // filter DefaultImpls to avoid processing same methods from original interface multiple times + // filter Enum entry classes to avoid duplication with PsiEnumConstant initializer class + psi.innerClasses.filter { + it.name != JvmAbi.DEFAULT_IMPLS_CLASS_NAME && !it.isEnumEntryLightClass() + }.map { + getLanguagePlugin().convert(it, this) + } + } + override val uastMethods: List by lz { val primaryConstructor = ktClass?.getPrimaryConstructor()?.toLightMethods()?.firstOrNull() val initBlocks = ktClass?.getAnonymousInitializers() ?: emptyList() - psi.methods.map { - if (it is KtLightMethod && it.isConstructor && initBlocks.isNotEmpty() - && (primaryConstructor == null || it == primaryConstructor)) { - object : KotlinUMethod(it, this@KotlinUClass) { + fun createUMethod(psiMethod: PsiMethod): UMethod { + return if (psiMethod is KtLightMethod && psiMethod.isConstructor && initBlocks.isNotEmpty() + && (primaryConstructor == null || psiMethod == primaryConstructor)) { + object : KotlinUMethod(psiMethod, this@KotlinUClass) { override val uastBody by lz { val initializers = ktClass?.getAnonymousInitializers() ?: return@lz UastEmptyExpression val containingMethod = this @@ -68,13 +83,21 @@ class KotlinUClass private constructor( } } } + } else { + getLanguagePlugin().convert(psiMethod, this) } - else { - getLanguagePlugin().convert(it, this) - } - } + } + + fun isDelegatedMethod(psiMethod: PsiMethod) = psiMethod is KtLightMethod && psiMethod.isDelegated + + psi.methods.asSequence() + .filterNot(::isDelegatedMethod) + .map(::createUMethod) + .toList() } + private fun PsiClass.isEnumEntryLightClass() = (this as? KtLightClass)?.kotlinOrigin is KtEnumEntry + companion object { fun create(psi: KtLightClass, containingElement: UElement?): UClass { return if (psi is PsiAnonymousClass) @@ -89,6 +112,7 @@ class KotlinUAnonymousClass( psi: PsiAnonymousClass, override val containingElement: UElement? ) : AbstractJavaUClass(), UAnonymousClass, PsiAnonymousClass by psi { + override val psi: PsiAnonymousClass = unwrap(psi) override fun getOriginalElement(): PsiElement? { diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUFile.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUFile.kt index 5c1fc2e6011..527fbb7f382 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUFile.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUFile.kt @@ -16,8 +16,12 @@ package org.jetbrains.uast.kotlin +import com.intellij.psi.PsiClass import com.intellij.psi.PsiComment import com.intellij.psi.PsiRecursiveElementWalkingVisitor +import org.jetbrains.kotlin.asJava.findFacadeClass +import org.jetbrains.kotlin.asJava.toLightClass +import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.uast.* import java.util.* @@ -40,5 +44,16 @@ class KotlinUFile(override val psi: KtFile, override val languagePlugin: UastLan } override val imports by lz { psi.importDirectives.map { KotlinUImportStatement(it, this) } } - override val classes by lz { psi.classes.map { languagePlugin.convert(it, this) } } + + override val classes by lz { + fun PsiClass.toUClass() = languagePlugin.convert(this, this@KotlinUFile) + + val classes = psi.findFacadeClass()?.let { mutableListOf(it.toUClass()) } ?: mutableListOf() + + for (declaration in psi.declarations) { + (declaration as? KtClassOrObject)?.toLightClass()?.let { classes += it.toUClass() } + } + + return@lz classes + } } \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUMethod.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUMethod.kt index eb4c2782456..a57b8153b12 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUMethod.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUMethod.kt @@ -20,13 +20,12 @@ import com.intellij.psi.PsiCodeBlock import com.intellij.psi.PsiElement import com.intellij.psi.PsiMethod import com.intellij.psi.PsiNameIdentifierOwner -import org.jetbrains.kotlin.asJava.elements.KtLightElement -import org.jetbrains.kotlin.asJava.elements.KtLightMethod -import org.jetbrains.kotlin.asJava.elements.KtLightMethodImpl +import org.jetbrains.kotlin.asJava.elements.* import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.KtCallableDeclaration import org.jetbrains.kotlin.psi.KtFunction import org.jetbrains.kotlin.psi.KtParameter +import org.jetbrains.kotlin.psi.KtProperty import org.jetbrains.uast.* import org.jetbrains.uast.java.JavaUAnnotation import org.jetbrains.uast.java.annotations @@ -54,7 +53,16 @@ open class KotlinUMethod( override val uastBody by lz { - val bodyExpression = (kotlinOrigin as? KtFunction)?.bodyExpression ?: return@lz null + val bodyExpression = when (kotlinOrigin) { + is KtFunction -> kotlinOrigin.bodyExpression + is KtProperty -> when { + psi.isGetter -> kotlinOrigin.getter?.bodyExpression + psi.isSetter -> kotlinOrigin.setter?.bodyExpression + else -> null + } + else -> null + } ?: return@lz null + getLanguagePlugin().convertElement(bodyExpression, this) as? UExpression } @@ -65,6 +73,10 @@ open class KotlinUMethod( override fun getOriginalElement(): PsiElement? = super.getOriginalElement() + override fun equals(other: Any?) = other is KotlinUMethod && psi == other.psi + + override fun hashCode() = psi.hashCode() + companion object { fun create(psi: KtLightMethod, containingElement: UElement?) = when (psi) { is KtLightMethodImpl.KtLightAnnotationMethod -> KotlinUAnnotationMethod(psi, containingElement) diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUVariable.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUVariable.kt index b598acc0b72..05252ecac49 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUVariable.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUVariable.kt @@ -21,8 +21,6 @@ import org.jetbrains.kotlin.asJava.elements.KtLightElement import org.jetbrains.kotlin.psi.KtParameter import org.jetbrains.kotlin.psi.KtVariableDeclaration import org.jetbrains.uast.* -import org.jetbrains.uast.expressions.UReferenceExpression -import org.jetbrains.uast.expressions.UTypeReferenceExpression import org.jetbrains.uast.java.AbstractJavaUVariable import org.jetbrains.uast.java.JavaAbstractUExpression import org.jetbrains.uast.java.JavaUAnnotation @@ -58,6 +56,9 @@ class KotlinUVariable( ) : AbstractKotlinUVariable(), UVariable, PsiVariable by psi { override val psi = unwrap(psi) + override val annotations by lz { psi.annotations.map { JavaUAnnotation(it, this) } } + override val typeReference by lz { getLanguagePlugin().convertOpt(psi.typeElement, this) } + override fun getInitializer(): PsiExpression? { return super.getInitializer() } @@ -66,9 +67,6 @@ class KotlinUVariable( return super.getOriginalElement() } - override val annotations by lz { psi.annotations.map { JavaUAnnotation(it, this) } } - override val typeReference by lz { getLanguagePlugin().convertOpt(psi.typeElement, this) } - companion object { fun create(psi: PsiVariable, containingElement: UElement?): UVariable { return when (psi) { @@ -86,6 +84,7 @@ open class KotlinUParameter( psi: PsiParameter, override val containingElement: UElement? ) : AbstractKotlinUVariable(), UParameter, PsiParameter by psi { + override val psi = unwrap(psi) override fun getInitializer(): PsiExpression? { @@ -95,13 +94,13 @@ open class KotlinUParameter( override fun getOriginalElement(): PsiElement? { return super.getOriginalElement() } - } open class KotlinUField( psi: PsiField, override val containingElement: UElement? ) : AbstractKotlinUVariable(), UField, PsiField by psi { + override val psi = unwrap(psi) override fun getInitializer(): PsiExpression? { @@ -111,13 +110,13 @@ open class KotlinUField( override fun getOriginalElement(): PsiElement? { return super.getOriginalElement() } - } open class KotlinULocalVariable( psi: PsiLocalVariable, override val containingElement: UElement? ) : AbstractKotlinUVariable(), ULocalVariable, PsiLocalVariable by psi { + override val psi = unwrap(psi) override fun getInitializer(): PsiExpression? { @@ -134,6 +133,8 @@ open class KotlinUEnumConstant( psi: PsiEnumConstant, override val containingElement: UElement? ) : AbstractKotlinUVariable(), UEnumConstant, PsiEnumConstant by psi { + override val initializingClass: UClass? by lz { getLanguagePlugin().convertOpt(psi.initializingClass, this) } + override val psi = unwrap(psi) override fun getInitializer(): PsiExpression? { diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/evaluation/KotlinEvaluatorExtension.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/evaluation/KotlinEvaluatorExtension.kt new file mode 100644 index 00000000000..38003243e55 --- /dev/null +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/evaluation/KotlinEvaluatorExtension.kt @@ -0,0 +1,58 @@ +package org.jetbrains.uast.kotlin.evaluation + +import org.jetbrains.kotlin.idea.KotlinLanguage +import org.jetbrains.uast.UastBinaryOperator +import org.jetbrains.uast.UastPostfixOperator +import org.jetbrains.uast.evaluation.UEvaluationInfo +import org.jetbrains.uast.evaluation.UEvaluationState +import org.jetbrains.uast.evaluation.UEvaluatorExtension +import org.jetbrains.uast.kotlin.KotlinBinaryOperators +import org.jetbrains.uast.kotlin.KotlinPostfixOperators +import org.jetbrains.uast.values.* + +class KotlinEvaluatorExtension : UEvaluatorExtension { + + private data class Range(val from: UValue, val to: UValue) { + override fun toString() = "$from..$to" + } + + private class UClosedRangeConstant(override val value: Range) : UAbstractConstant() { + constructor(from: UValue, to: UValue): this(Range(from, to)) + } + + override val language: KotlinLanguage = KotlinLanguage.INSTANCE + + override fun evaluatePostfix( + operator: UastPostfixOperator, + operandValue: UValue, + state: UEvaluationState + ): UEvaluationInfo { + return when (operator) { + KotlinPostfixOperators.EXCLEXCL -> when (operandValue.toConstant()) { + UNullConstant -> UValue.UNREACHABLE + is UConstant -> operandValue + else -> UUndeterminedValue + } to state + else -> return super.evaluatePostfix(operator, operandValue, state) + } + } + + private fun UValue.contains(value: UValue): UValue { + val range = (this as? UClosedRangeConstant)?.value ?: return UUndeterminedValue + return (value greaterOrEquals range.from) and (value lessOrEquals range.to) + } + + override fun evaluateBinary( + operator: UastBinaryOperator, + leftValue: UValue, + rightValue: UValue, + state: UEvaluationState + ): UEvaluationInfo { + return when (operator) { + KotlinBinaryOperators.IN -> rightValue.contains(leftValue) + KotlinBinaryOperators.NOT_IN -> !rightValue.contains(leftValue) + KotlinBinaryOperators.RANGE_TO -> UClosedRangeConstant(leftValue, rightValue) + else -> UUndeterminedValue + } to state + } +} \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/ElvisExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/ElvisExpression.kt new file mode 100644 index 00000000000..b76b01320c6 --- /dev/null +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/ElvisExpression.kt @@ -0,0 +1,82 @@ +package org.jetbrains.uast.kotlin.expressions + +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiMethod +import org.jetbrains.kotlin.psi.KtBinaryExpression +import org.jetbrains.kotlin.psi.KtExpression +import org.jetbrains.uast.* +import org.jetbrains.uast.kotlin.* +import org.jetbrains.uast.kotlin.kinds.KotlinSpecialExpressionKinds +import org.jetbrains.uast.kotlin.psi.UastKotlinPsiVariable + + +private fun createVariableReferenceExpression(variable: UVariable, containingElement: UElement?) = + object : USimpleNameReferenceExpression { + override fun resolve(): PsiElement? = variable + override val containingElement: UElement? = containingElement + override val resolvedName: String? = variable.name + override val annotations: List = emptyList() + override val identifier: String = variable.name.orAnonymous() + } + +private fun createNullLiteralExpression(containingElement: UElement?) = + object : ULiteralExpression { + override val containingElement: UElement? = containingElement + override val value: Any? = null + override val annotations: List = emptyList() + } + +private fun createNotEqWithNullExpression(variable: UVariable, containingElement: UElement?) = + object : UBinaryExpression { + override val containingElement: UElement? = containingElement + override val leftOperand: UExpression by lz { createVariableReferenceExpression(variable, this) } + override val rightOperand: UExpression by lz { createNullLiteralExpression(this) } + override val operator: UastBinaryOperator = UastBinaryOperator.NOT_EQUALS + override val operatorIdentifier: UIdentifier? = UIdentifier(null, this) + override fun resolveOperator(): PsiMethod? = null + override val annotations: List = emptyList() + } + +private fun createElvisExpressions( + left: KtExpression, + right: KtExpression, + containingElement: UElement?, + psiParent: PsiElement): List { + + val declaration = KotlinUDeclarationsExpression(containingElement) + val tempVariable = KotlinUVariable.create(UastKotlinPsiVariable.create(left, declaration, psiParent), + declaration) + declaration.declarations = listOf(tempVariable) + + val ifExpression = object : UIfExpression { + override val containingElement: UElement? = containingElement + override val condition: UExpression by lz { createNotEqWithNullExpression(tempVariable, this) } + override val thenExpression: UExpression? by lz { createVariableReferenceExpression(tempVariable, this) } + override val elseExpression: UExpression? by lz { KotlinConverter.convertExpression(right, this) } + override val isTernary: Boolean = false + override val annotations: List = emptyList() + override val ifIdentifier: UIdentifier = UIdentifier(null, this) + override val elseIdentifier: UIdentifier? = UIdentifier(null, this) + } + + return listOf(declaration, ifExpression) +} + +fun createElvisExpression(elvisExpression: KtBinaryExpression, containingElement: UElement?): UExpressionList? { + val left = elvisExpression.left ?: return null + val right = elvisExpression.right ?: return null + + return object : UExpressionList, KotlinEvaluatableUElement, KotlinUElementWithType { + override val psi: PsiElement? = elvisExpression + override val kind = KotlinSpecialExpressionKinds.ELVIS + override val containingElement: UElement? = containingElement + override val annotations: List = emptyList() + override val expressions: List by lz { + createElvisExpressions(left, right, this, elvisExpression.parent) + } + override fun asRenderString(): String = kind.name + " " + + expressions.joinToString(separator = "\n", prefix = "{\n", postfix = "\n}") { + it.asRenderString().withMargin + } + } +} \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinStringTemplateUPolyadicExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinStringTemplateUPolyadicExpression.kt new file mode 100644 index 00000000000..67f77e80579 --- /dev/null +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinStringTemplateUPolyadicExpression.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.uast.kotlin + +import org.jetbrains.kotlin.psi.KtStringTemplateExpression +import org.jetbrains.uast.* +import org.jetbrains.uast.psi.PsiElementBacked + +class KotlinStringTemplateUPolyadicExpression( + override val psi: KtStringTemplateExpression, + override val containingElement: UElement? +) : KotlinAbstractUExpression(), + UPolyadicExpression, + PsiElementBacked, + KotlinUElementWithType, + KotlinEvaluatableUElement { + override val operands: List by lz { psi.entries.map { KotlinConverter.convert(it, this) } } + override val operator = UastBinaryOperator.PLUS +} \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUBinaryExpressionWithType.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUBinaryExpressionWithType.kt index d6a886b33ad..71ad801cf41 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUBinaryExpressionWithType.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUBinaryExpressionWithType.kt @@ -20,11 +20,7 @@ import com.intellij.psi.PsiElement import com.intellij.psi.PsiType import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.KtBinaryExpressionWithTypeRHS -import org.jetbrains.uast.UBinaryExpressionWithType -import org.jetbrains.uast.UElement -import org.jetbrains.uast.UExpression -import org.jetbrains.uast.UastBinaryExpressionWithTypeKind -import org.jetbrains.uast.expressions.UTypeReferenceExpression +import org.jetbrains.uast.* import org.jetbrains.uast.psi.PsiElementBacked class KotlinUBinaryExpressionWithType( @@ -37,7 +33,7 @@ class KotlinUBinaryExpressionWithType( override val type by lz { psi.right.toPsiType(this) } override val typeReference by lz { - psi.right?.let { KotlinUTypeReferenceExpression(it.toPsiType(this), it, this) } + psi.right?.let { LazyKotlinUTypeReferenceExpression(it, this) { it.toPsiType(this) } } } override val operationKind = when (psi.operationReference.getReferencedNameElementType()) { @@ -57,9 +53,8 @@ class KotlinCustomUBinaryExpressionWithType( lateinit override var operationKind: UastBinaryExpressionWithTypeKind internal set - lateinit override var type: PsiType - internal set - + override val type: PsiType by lz { typeReference?.type ?: UastErrorType } + override var typeReference: UTypeReferenceExpression? = null internal set } \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUCallableReferenceExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUCallableReferenceExpression.kt index d2f875432b5..8328e3705af 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUCallableReferenceExpression.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUCallableReferenceExpression.kt @@ -16,6 +16,7 @@ package org.jetbrains.uast.kotlin +import com.intellij.psi.PsiNamedElement import org.jetbrains.kotlin.psi.KtCallableReferenceExpression import org.jetbrains.kotlin.resolve.BindingContext.DOUBLE_COLON_LHS import org.jetbrains.uast.UCallableReferenceExpression @@ -41,4 +42,9 @@ class KotlinUCallableReferenceExpression( override val callableName: String get() = psi.callableReference.getReferencedName() + + override val resolvedName: String? + get() = (resolve() as? PsiNamedElement)?.name + + override fun resolve() = psi.callableReference.resolveCallToDeclaration(this) } \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUCatchClause.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUCatchClause.kt index 3bef2026126..e74aebeffbc 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUCatchClause.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUCatchClause.kt @@ -20,7 +20,7 @@ import org.jetbrains.kotlin.psi.KtCatchClause import org.jetbrains.uast.UCatchClause import org.jetbrains.uast.UElement import org.jetbrains.uast.UParameter -import org.jetbrains.uast.expressions.UTypeReferenceExpression +import org.jetbrains.uast.UTypeReferenceExpression import org.jetbrains.uast.kotlin.psi.UastKotlinPsiParameter import org.jetbrains.uast.psi.PsiElementBacked @@ -37,8 +37,7 @@ class KotlinUCatchClause( override val typeReferences by lz { val parameter = psi.catchParameter ?: return@lz emptyList() - val typeReference = parameter.typeReference - val type = typeReference.toPsiType(this, boxed = true) - listOf(KotlinUTypeReferenceExpression(type, typeReference, this)) + val typeReference = parameter.typeReference ?: return@lz emptyList() + listOf(LazyKotlinUTypeReferenceExpression(typeReference, this) { typeReference.toPsiType(this, boxed = true) } ) } } \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUObjectLiteralExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUObjectLiteralExpression.kt index 2b1b5f769d8..106f1a76140 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUObjectLiteralExpression.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUObjectLiteralExpression.kt @@ -22,7 +22,6 @@ import org.jetbrains.kotlin.asJava.toLightClass import org.jetbrains.kotlin.psi.KtObjectLiteralExpression import org.jetbrains.kotlin.psi.KtSuperTypeCallEntry import org.jetbrains.uast.* -import org.jetbrains.uast.expressions.UReferenceExpression import org.jetbrains.uast.psi.PsiElementBacked class KotlinUObjectLiteralExpression( diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUSimpleReferenceExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUSimpleReferenceExpression.kt index 3b26a65dcc5..bcb8cf96736 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUSimpleReferenceExpression.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUSimpleReferenceExpression.kt @@ -31,7 +31,6 @@ import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor import org.jetbrains.kotlin.utils.addToStdlib.constant import org.jetbrains.uast.* -import org.jetbrains.uast.expressions.UReferenceExpression import org.jetbrains.uast.psi.PsiElementBacked import org.jetbrains.uast.visitor.UastVisitor diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUSwitchExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUSwitchExpression.kt index 7efb15138eb..9a4a5f08a89 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUSwitchExpression.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUSwitchExpression.kt @@ -67,9 +67,9 @@ class KotlinUSwitchEntry( else -> UastBinaryExpressionWithTypeKind.INSTANCE_CHECK } val typeRef = it.typeReference - val type = typeRef.toPsiType(this, boxed = true) - this.type = type - typeReference = typeRef?.let { KotlinUTypeReferenceExpression(type, it, this) } + typeReference = typeRef?.let { + LazyKotlinUTypeReferenceExpression(it, this) { typeRef.toPsiType(this, boxed = true) } + } } is KtWhenConditionWithExpression -> KotlinConverter.convertOrEmpty(it.expression, this) else -> UastEmptyExpression diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUTryExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUTryExpression.kt index 624bc6ad860..e03f2686975 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUTryExpression.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUTryExpression.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.psi.KtTryExpression import org.jetbrains.uast.UElement import org.jetbrains.uast.UIdentifier import org.jetbrains.uast.UTryExpression +import org.jetbrains.uast.UVariable import org.jetbrains.uast.psi.PsiElementBacked class KotlinUTryExpression( @@ -31,10 +32,10 @@ class KotlinUTryExpression( override val catchClauses by lz { psi.catchClauses.map { KotlinUCatchClause(it, this) } } override val finallyClause by lz { psi.finallyBlock?.finalExpression?.let { KotlinConverter.convertExpression(it, this) } } - override val resources: List? - get() = null + override val resourceVariables: List + get() = emptyList() - override val isResources: Boolean + override val hasResources: Boolean get() = false override val tryIdentifier: UIdentifier diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUTypeCheckExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUTypeCheckExpression.kt index a99e5e66f51..b6d7394b9cd 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUTypeCheckExpression.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUTypeCheckExpression.kt @@ -19,6 +19,7 @@ package org.jetbrains.uast.kotlin import org.jetbrains.kotlin.psi.KtIsExpression import org.jetbrains.uast.UBinaryExpressionWithType import org.jetbrains.uast.UElement +import org.jetbrains.uast.UastBinaryExpressionWithTypeKind import org.jetbrains.uast.psi.PsiElementBacked class KotlinUTypeCheckExpression( @@ -29,9 +30,13 @@ class KotlinUTypeCheckExpression( override val type by lz { psi.typeReference.toPsiType(this) } - override val typeReference by lz { - psi.typeReference?.let { KotlinUTypeReferenceExpression(it.toPsiType(this), it, this) } + override val typeReference = psi.typeReference?.let { + LazyKotlinUTypeReferenceExpression(it, this) { it.toPsiType(this) } } - override val operationKind = KotlinBinaryExpressionWithTypeKinds.NEGATED_INSTANCE_CHECK + override val operationKind = + if(psi.isNegated) + KotlinBinaryExpressionWithTypeKinds.NEGATED_INSTANCE_CHECK + else + UastBinaryExpressionWithTypeKind.INSTANCE_CHECK } \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUTypeReferenceExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUTypeReferenceExpression.kt index 55aa03a4ce6..bf748d9ac95 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUTypeReferenceExpression.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUTypeReferenceExpression.kt @@ -3,11 +3,20 @@ package org.jetbrains.uast.kotlin import com.intellij.psi.PsiElement import com.intellij.psi.PsiType import org.jetbrains.uast.UElement -import org.jetbrains.uast.expressions.UTypeReferenceExpression +import org.jetbrains.uast.UTypeReferenceExpression import org.jetbrains.uast.psi.PsiElementBacked open class KotlinUTypeReferenceExpression( override val type: PsiType, override val psi: PsiElement?, override val containingElement: UElement? -) : KotlinAbstractUExpression(), UTypeReferenceExpression, PsiElementBacked, KotlinUElementWithType \ No newline at end of file +) : KotlinAbstractUExpression(), UTypeReferenceExpression, PsiElementBacked, KotlinUElementWithType + + +class LazyKotlinUTypeReferenceExpression( + override val psi: PsiElement, + override val containingElement: UElement?, + private val typeSupplier: () -> PsiType +) : KotlinAbstractUExpression(), UTypeReferenceExpression, PsiElementBacked { + override val type: PsiType by lz { typeSupplier() } +} \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/LocalFunction.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/LocalFunction.kt new file mode 100644 index 00000000000..6a9ae3eed62 --- /dev/null +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/LocalFunction.kt @@ -0,0 +1,61 @@ +package org.jetbrains.uast.kotlin.expressions + +import com.intellij.psi.PsiVariable +import org.jetbrains.kotlin.psi.KtFunction +import org.jetbrains.uast.* +import org.jetbrains.uast.kotlin.* +import org.jetbrains.uast.kotlin.psi.UastKotlinPsiParameter +import org.jetbrains.uast.kotlin.psi.UastKotlinPsiVariable +import org.jetbrains.uast.psi.PsiElementBacked + + +private class KotlinLocalFunctionUVariable( + val function: KtFunction, + override val psi: PsiVariable, + override val containingElement: UElement? +) : UVariable, PsiVariable by psi { + override val uastInitializer: UExpression? by lz { + createLocalFunctionLambdaExpression(function, this) + } + override val typeReference: UTypeReferenceExpression? = null + override val uastAnchor: UElement? = null + override val annotations: List = emptyList() + + override fun equals(other: Any?) = other is KotlinLocalFunctionUVariable && psi == other.psi + override fun hashCode() = psi.hashCode() +} + + +private class KotlinLocalFunctionULambdaExpression( + override val psi: KtFunction, + override val containingElement: UElement? +): KotlinAbstractUExpression(), ULambdaExpression, PsiElementBacked { + + override val body by lz { KotlinConverter.convertOrEmpty(psi.bodyExpression, this) } + + override val valueParameters by lz { + psi.valueParameters.mapIndexed { i, p -> + KotlinUParameter(UastKotlinPsiParameter.create(p, psi, this, i), this) + } + } + + override fun asRenderString(): String { + val renderedValueParameters = valueParameters.joinToString(prefix = "(", postfix = ")", + transform = KotlinUParameter::asRenderString) + val expressions = (body as? UBlockExpression)?.expressions?.joinToString("\n") { + it.asRenderString().withMargin + } ?: body.asRenderString() + return "fun $renderedValueParameters {\n${expressions.withMargin}\n}" + } +} + + +fun createLocalFunctionDeclaration(function: KtFunction, parent: UElement?): UDeclarationsExpression { + return KotlinUDeclarationsExpression(parent).apply { + val functionVariable = UastKotlinPsiVariable.create(function.name.orAnonymous(), function, this) + declarations = listOf(KotlinLocalFunctionUVariable(function, functionVariable, this)) + } +} + +fun createLocalFunctionLambdaExpression(function: KtFunction, parent: UElement?): ULambdaExpression = + KotlinLocalFunctionULambdaExpression(function, parent) diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/kinds/KotlinBinaryExpressionWithTypeKinds.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/kinds/KotlinBinaryExpressionWithTypeKinds.kt index 7c489f07901..1eb4cb90788 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/kinds/KotlinBinaryExpressionWithTypeKinds.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/kinds/KotlinBinaryExpressionWithTypeKinds.kt @@ -20,8 +20,8 @@ import org.jetbrains.uast.UastBinaryExpressionWithTypeKind object KotlinBinaryExpressionWithTypeKinds { @JvmField - val NEGATED_INSTANCE_CHECK = UastBinaryExpressionWithTypeKind("!is") + val NEGATED_INSTANCE_CHECK = UastBinaryExpressionWithTypeKind.InstanceCheck("!is") @JvmField - val SAFE_TYPE_CAST = UastBinaryExpressionWithTypeKind("!is") + val SAFE_TYPE_CAST = UastBinaryExpressionWithTypeKind.TypeCast("as?") } \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/kinds/KotlinSpecialExpressionKinds.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/kinds/KotlinSpecialExpressionKinds.kt index bb130a6badc..00d1b05cb42 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/kinds/KotlinSpecialExpressionKinds.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/kinds/KotlinSpecialExpressionKinds.kt @@ -27,4 +27,7 @@ object KotlinSpecialExpressionKinds { @JvmField val CLASS_BODY = UastSpecialExpressionKind("class_body") + + @JvmField + val ELVIS = UastSpecialExpressionKind("elvis") } \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/psi/UastKotlinPsiVariable.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/psi/UastKotlinPsiVariable.kt index 6cdbc7d286a..2ed4a1ff0a8 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/psi/UastKotlinPsiVariable.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/psi/UastKotlinPsiVariable.kt @@ -4,10 +4,8 @@ import com.intellij.lang.Language import com.intellij.psi.* import org.jetbrains.kotlin.asJava.elements.LightVariableBuilder import org.jetbrains.kotlin.idea.KotlinLanguage -import org.jetbrains.kotlin.psi.KtDestructuringDeclaration -import org.jetbrains.kotlin.psi.KtElement -import org.jetbrains.kotlin.psi.KtExpression -import org.jetbrains.kotlin.psi.KtVariableDeclaration +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.uast.UDeclaration import org.jetbrains.uast.UElement @@ -68,7 +66,7 @@ class UastKotlinPsiVariable( val psiParent = containingElement.getParentOfType()?.psi ?: declaration.parent return UastKotlinPsiVariable( declaration.manager, - "var" + Integer.toHexString(declaration.hashCode()), + "var" + Integer.toHexString(declaration.getHashCode()), UastErrorType, //TODO, KotlinLanguage.INSTANCE, declaration.initializer, @@ -76,6 +74,32 @@ class UastKotlinPsiVariable( containingElement, declaration) } + + fun create(initializer: KtExpression, containingElement: UElement, parent: PsiElement): PsiVariable { + val psiParent = containingElement.getParentOfType()?.psi ?: parent + return UastKotlinPsiVariable( + initializer.manager, + "var" + Integer.toHexString(initializer.getHashCode()), + UastErrorType, //TODO, + KotlinLanguage.INSTANCE, + initializer, + psiParent, + containingElement, + initializer) + } + + fun create(name: String, localFunction: KtFunction, containingElement: UElement): PsiVariable { + val psiParent = containingElement.getParentOfType()?.psi ?: localFunction.parent + return UastKotlinPsiVariable( + localFunction.manager, + name, + UastErrorType, // TODO, + KotlinLanguage.INSTANCE, + localFunction, + psiParent, + containingElement, + localFunction) + } } } @@ -84,4 +108,12 @@ private class KotlinUastPsiExpression(val ktExpression: KtExpression, val parent val ktType = ktExpression.analyze()[BindingContext.EXPRESSION_TYPE_INFO, ktExpression]?.type ?: return null return ktType.toPsiType(parent, ktExpression, boxed = false) } +} + +private fun PsiElement.getHashCode(): Int { + var result = 42 + result = 41 * result + containingFile.name.hashCode() + result = 41 * result + startOffset + result = 41 * result + text.hashCode() + return result } \ No newline at end of file diff --git a/update_dependencies.xml b/update_dependencies.xml index 8a54c81332c..1109adc33a3 100644 --- a/update_dependencies.xml +++ b/update_dependencies.xml @@ -31,7 +31,7 @@ - +