(set.size());
- for (Quantity quantity : set) {
- list.add('`' + quantity.name() + '`');
- }
- return LintUtils.formatList(list, Integer.MAX_VALUE);
- }
- }
-
- // GENERATED DATA.
- // This data is generated by the #testDatabaseAccurate method in PluralsDatabaseTest
- // which will generate the following if it can find an ICU plurals database file
- // in the unit test data folder.
-
- /** Set of language codes relevant to plurals data */
- private static final String[] LANGUAGE_CODES = new String[] {
- "af", "ak", "am", "ar", "az", "be", "bg", "bh", "bm", "bn",
- "bo", "br", "bs", "ca", "cs", "cy", "da", "de", "dv", "dz",
- "ee", "el", "en", "eo", "es", "et", "eu", "fa", "ff", "fi",
- "fo", "fr", "fy", "ga", "gd", "gl", "gu", "gv", "ha", "he",
- "hi", "hr", "hu", "hy", "id", "ig", "ii", "in", "is", "it",
- "iu", "iw", "ja", "ji", "jv", "ka", "kk", "kl", "km", "kn",
- "ko", "ks", "ku", "kw", "ky", "lb", "lg", "ln", "lo", "lt",
- "lv", "mg", "mk", "ml", "mn", "mr", "ms", "mt", "my", "nb",
- "nd", "ne", "nl", "nn", "no", "nr", "ny", "om", "or", "os",
- "pa", "pl", "ps", "pt", "rm", "ro", "ru", "se", "sg", "si",
- "sk", "sl", "sn", "so", "sq", "sr", "ss", "st", "sv", "sw",
- "ta", "te", "th", "ti", "tk", "tl", "tn", "to", "tr", "ts",
- "ug", "uk", "ur", "uz", "ve", "vi", "vo", "wa", "wo", "xh",
- "yi", "yo", "zh", "zu"
- };
-
- /**
- * Relevant flags for each language (corresponding to each language listed
- * in the same position in {@link #LANGUAGE_CODES}).
- */
- private static final int[] FLAGS = new int[] {
- 0x0002, 0x0042, 0x0042, 0x001f, 0x0002, 0x005a, 0x0002, 0x0042,
- 0x0000, 0x0042, 0x0000, 0x00de, 0x004a, 0x0002, 0x000a, 0x001f,
- 0x0002, 0x0002, 0x0002, 0x0000, 0x0002, 0x0002, 0x0002, 0x0002,
- 0x0002, 0x0002, 0x0002, 0x0042, 0x0042, 0x0002, 0x0002, 0x0042,
- 0x0002, 0x001e, 0x00ce, 0x0002, 0x0042, 0x00ce, 0x0002, 0x0016,
- 0x0042, 0x004a, 0x0002, 0x0042, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0042, 0x0002, 0x0006, 0x0016, 0x0000, 0x0002, 0x0000, 0x0002,
- 0x0002, 0x0002, 0x0000, 0x0042, 0x0000, 0x0002, 0x0002, 0x0006,
- 0x0002, 0x0002, 0x0002, 0x0042, 0x0000, 0x004a, 0x0063, 0x0042,
- 0x0042, 0x0002, 0x0002, 0x0042, 0x0000, 0x001a, 0x0000, 0x0002,
- 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
- 0x0002, 0x0002, 0x0042, 0x001a, 0x0002, 0x0002, 0x0002, 0x000a,
- 0x005a, 0x0006, 0x0000, 0x0042, 0x000a, 0x00ce, 0x0002, 0x0002,
- 0x0002, 0x004a, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
- 0x0000, 0x0042, 0x0002, 0x0042, 0x0002, 0x0000, 0x0002, 0x0002,
- 0x0002, 0x005a, 0x0002, 0x0002, 0x0002, 0x0000, 0x0002, 0x0042,
- 0x0000, 0x0002, 0x0002, 0x0000, 0x0000, 0x0042
- };
-
- @Nullable
- private static String getExampleForQuantityZero(@NonNull String language) {
- int index = getLanguageIndex(language);
- switch (index) {
- // set14
- case 70: // lv
- return "0, 10~20, 30, 40, 50, 60, 100, 1000, 10000, 100000, 1000000, \u2026";
- case -1:
- default:
- return null;
- }
- }
-
- @Nullable
- private static String getExampleForQuantityOne(@NonNull String language) {
- int index = getLanguageIndex(language);
- switch (index) {
- // set1
- case 2: // am
- case 9: // bn
- case 27: // fa
- case 36: // gu
- case 40: // hi
- case 59: // kn
- case 75: // mr
- case 133: // zu
- return "0, 1";
- // set11
- case 48: // is
- return "1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, \u2026";
- // set12
- case 72: // mk
- return "1, 11, 21, 31, 41, 51, 61, 71, 101, 1001, \u2026";
- // set13
- case 115: // tl
- return "0~3, 5, 7, 8, 10~13, 15, 17, 18, 20, 21, 100, 1000, 10000, 100000, 1000000, \u2026";
- // set14
- case 70: // lv
- return "1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, \u2026";
- // set2
- case 28: // ff
- case 31: // fr
- case 43: // hy
- return "0, 1";
- // set20
- case 12: // bs
- case 41: // hr
- case 105: // sr
- return "1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, \u2026";
- // set21
- case 34: // gd
- return "1, 11";
- // set22
- case 101: // sl
- return "1, 101, 201, 301, 401, 501, 601, 701, 1001, \u2026";
- // set26
- case 5: // be
- return "1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, \u2026";
- // set27
- case 69: // lt
- return "1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, \u2026";
- // set29
- case 96: // ru
- case 121: // uk
- return "1, 21, 31, 41, 51, 61, 71, 81, 101, 1001, \u2026";
- // set30
- case 11: // br
- return "1, 21, 31, 41, 51, 61, 81, 101, 1001, \u2026";
- // set32
- case 37: // gv
- return "1, 11, 21, 31, 41, 51, 61, 71, 101, 1001, \u2026";
- // set5
- case 99: // si
- return "0, 1";
- // set6
- case 1: // ak
- case 7: // bh
- case 67: // ln
- case 71: // mg
- case 90: // pa
- case 113: // ti
- case 127: // wa
- return "0, 1";
- case -1:
- default:
- return null;
- }
- }
-
- @Nullable
- private static String getExampleForQuantityTwo(@NonNull String language) {
- int index = getLanguageIndex(language);
- switch (index) {
- // set21
- case 34: // gd
- return "2, 12";
- // set22
- case 101: // sl
- return "2, 102, 202, 302, 402, 502, 602, 702, 1002, \u2026";
- // set30
- case 11: // br
- return "2, 22, 32, 42, 52, 62, 82, 102, 1002, \u2026";
- // set32
- case 37: // gv
- return "2, 12, 22, 32, 42, 52, 62, 72, 102, 1002, \u2026";
- case -1:
- default:
- return null;
- }
- }
-}
diff --git a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/PrivateResourceDetector.java b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/PrivateResourceDetector.java
index a8ca82cd828..77344401c20 100644
--- a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/PrivateResourceDetector.java
+++ b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/PrivateResourceDetector.java
@@ -81,7 +81,7 @@ public class PrivateResourceDetector extends ResourceXmlDetector implements Uast
private static final Implementation IMPLEMENTATION = new Implementation(
PrivateResourceDetector.class,
Scope.SOURCE_AND_RESOURCE_FILES,
- Scope.JAVA_FILE_SCOPE,
+ Scope.SOURCE_FILE_SCOPE,
Scope.RESOURCE_FILE_SCOPE);
/** The main issue discovered by this detector */
@@ -259,7 +259,7 @@ public class PrivateResourceDetector extends ResourceXmlDetector implements Uast
}
@Override
- public void beforeCheckProject(@NonNull Context context) {
+ public void beforeCheckFile(@NonNull Context context) {
File file = context.file;
boolean isXmlFile = LintUtils.isXmlFile(file);
if (!isXmlFile && !LintUtils.isBitmapFile(file)) {
diff --git a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/RegistrationDetector.java b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/RegistrationDetector.java
deleted file mode 100644
index e1670621b1e..00000000000
--- a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/RegistrationDetector.java
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * 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 com.android.tools.klint.checks;
-
-import static com.android.SdkConstants.ANDROID_APP_ACTIVITY;
-import static com.android.SdkConstants.ANDROID_APP_SERVICE;
-import static com.android.SdkConstants.ANDROID_CONTENT_BROADCAST_RECEIVER;
-import static com.android.SdkConstants.ANDROID_CONTENT_CONTENT_PROVIDER;
-import static com.android.SdkConstants.ANDROID_URI;
-import static com.android.SdkConstants.ATTR_NAME;
-import static com.android.SdkConstants.TAG_ACTIVITY;
-import static com.android.SdkConstants.TAG_PROVIDER;
-import static com.android.SdkConstants.TAG_RECEIVER;
-import static com.android.SdkConstants.TAG_SERVICE;
-
-import com.android.annotations.NonNull;
-import com.android.tools.klint.detector.api.Category;
-import com.android.tools.klint.detector.api.ClassContext;
-import com.android.tools.klint.detector.api.Detector.ClassScanner;
-import com.android.tools.klint.detector.api.Implementation;
-import com.android.tools.klint.detector.api.Issue;
-import com.android.tools.klint.detector.api.LayoutDetector;
-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.Speed;
-import com.android.tools.klint.detector.api.XmlContext;
-import com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.Multimap;
-
-import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.tree.ClassNode;
-import org.w3c.dom.Element;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.EnumSet;
-import java.util.Map.Entry;
-
-/**
- * Checks for missing manifest registrations for activities, services etc
- * and also makes sure that they are registered with the correct tag
- *
- * TODO: Rewrite as Java visitor!
- */
-public class RegistrationDetector extends LayoutDetector implements ClassScanner {
- /** Unregistered activities and services */
- public static final Issue ISSUE = Issue.create(
- "Registered", //$NON-NLS-1$
- "Class is not registered in the manifest",
-
- "Activities, services and content providers should be registered in the " +
- "`AndroidManifest.xml` file using ``, `` and `` tags.\n" +
- "\n" +
- "If your activity is simply a parent class intended to be subclassed by other " +
- "\"real\" activities, make it an abstract class.",
-
- Category.CORRECTNESS,
- 6,
- Severity.WARNING,
- new Implementation(
- RegistrationDetector.class,
- EnumSet.of(Scope.MANIFEST, Scope.CLASS_FILE)))
- .addMoreInfo(
- "http://developer.android.com/guide/topics/manifest/manifest-intro.html"); //$NON-NLS-1$
-
- protected Multimap mManifestRegistrations;
-
- /** Constructs a new {@link RegistrationDetector} */
- public RegistrationDetector() {
- }
-
- @NonNull
- @Override
- public Speed getSpeed() {
- return Speed.FAST;
- }
-
- // ---- Implements XmlScanner ----
-
- @Override
- public Collection getApplicableElements() {
- return Arrays.asList(sTags);
- }
-
- @Override
- public void visitElement(@NonNull XmlContext context, @NonNull Element element) {
- String fqcn = getFqcn(context, element);
- String tag = element.getTagName();
- String frameworkClass = tagToClass(tag);
- if (frameworkClass != null) {
- String signature = ClassContext.getInternalName(fqcn);
- if (mManifestRegistrations == null) {
- mManifestRegistrations = ArrayListMultimap.create(4, 8);
- }
- mManifestRegistrations.put(frameworkClass, signature);
- if (signature.indexOf('$') != -1) {
- // The internal name contains a $ which means it's an inner class.
- // The conversion from fqcn to internal name is a bit ambiguous:
- // "a.b.C.D" usually means "inner class D in class C in package a.b".
- // However, it can (see issue 31592) also mean class D in package "a.b.C".
- // Place *both* of these possibilities in the registered map, since this
- // is only used to check that an activity is registered, not the other way
- // (so it's okay to have entries there that do not correspond to real classes).
- signature = signature.replace('$', '/');
- mManifestRegistrations.put(frameworkClass, signature);
- }
- }
- }
-
- /**
- * Returns the fully qualified class name for a manifest entry element that
- * specifies a name attribute
- *
- * @param context the query context providing the project
- * @param element the element
- * @return the fully qualified class name
- */
- @NonNull
- private static String getFqcn(@NonNull XmlContext context, @NonNull Element element) {
- String className = element.getAttributeNS(ANDROID_URI, ATTR_NAME);
- if (className.startsWith(".")) { //$NON-NLS-1$
- return context.getMainProject().getPackage() + className;
- } else if (className.indexOf('.') == -1) {
- // According to the manifest element documentation, this is not
- // valid ( http://developer.android.com/guide/topics/manifest/activity-element.html )
- // but it appears in manifest files and appears to be supported by the runtime
- // so handle this in code as well:
- return context.getMainProject().getPackage() + '.' + className;
- } // else: the class name is already a fully qualified class name
-
- return className;
- }
-
- // ---- Implements ClassScanner ----
-
- @Override
- public void checkClass(@NonNull ClassContext context, @NonNull ClassNode classNode) {
- // Abstract classes do not need to be registered
- if ((classNode.access & Opcodes.ACC_ABSTRACT) != 0) {
- return;
- }
- String curr = classNode.name;
-
- int lastIndex = curr.lastIndexOf('$');
- if (lastIndex != -1 && lastIndex < curr.length() - 1) {
- if (Character.isDigit(curr.charAt(lastIndex+1))) {
- // Anonymous inner class, doesn't need to be registered
- return;
- }
- }
-
- while (curr != null) {
- for (String s : sClasses) {
- if (curr.equals(s)) {
- Collection registered = mManifestRegistrations != null ?
- mManifestRegistrations.get(curr) : null;
- if (registered == null || !registered.contains(classNode.name)) {
- report(context, classNode, curr);
- }
-
- }
- }
-
- curr = context.getDriver().getSuperClass(curr);
- }
- }
-
- private void report(ClassContext context, ClassNode classNode, String curr) {
- String tag = classToTag(curr);
- String className = ClassContext.createSignature(classNode.name, null, null);
-
- String wrongClass = null; // The framework class this class actually extends
- if (mManifestRegistrations != null) {
- Collection> entries =
- mManifestRegistrations.entries();
- for (Entry entry : entries) {
- if (entry.getValue().equals(classNode.name)) {
- wrongClass = entry.getKey();
- break;
- }
- }
- }
- if (wrongClass != null) {
- Location location = context.getLocation(classNode);
- context.report(
- ISSUE,
- location,
- String.format(
- "`%1$s` is a `<%2$s>` but is registered in the manifest as a `<%3$s>`",
- className, tag, classToTag(wrongClass)));
- } else if (!TAG_RECEIVER.equals(tag)) { // don't need to be registered
- if (context.getMainProject().isGradleProject()) {
- // Disabled for now; we need to formalize the difference between
- // the *manifest* package and the variant package, since in some contexts
- // (such as manifest registrations) we should be using the manifest package,
- // not the gradle package
- return;
- }
- Location location = context.getLocation(classNode);
- context.report(
- ISSUE,
- location,
- String.format(
- "The `<%1$s> %2$s` is not registered in the manifest",
- tag, className));
- }
- }
-
- /** The manifest tags we care about */
- private static final String[] sTags = new String[] {
- TAG_ACTIVITY,
- TAG_SERVICE,
- TAG_RECEIVER,
- TAG_PROVIDER,
- // Keep synchronized with {@link #sClasses}
- };
-
- /** The corresponding framework classes that the tags in {@link #sTags} should extend */
- private static final String[] sClasses = new String[] {
- ANDROID_APP_ACTIVITY,
- ANDROID_APP_SERVICE,
- ANDROID_CONTENT_BROADCAST_RECEIVER,
- ANDROID_CONTENT_CONTENT_PROVIDER,
- // Keep synchronized with {@link #sTags}
- };
-
- /** Looks up the corresponding framework class a given manifest tag's class should extend */
- private static String tagToClass(String tag) {
- for (int i = 0, n = sTags.length; i < n; i++) {
- if (sTags[i].equals(tag)) {
- return sClasses[i];
- }
- }
-
- return null;
- }
-
- /** Looks up the tag a given framework class should be registered with */
- protected static String classToTag(String className) {
- for (int i = 0, n = sClasses.length; i < n; i++) {
- if (sClasses[i].equals(className)) {
- return sTags[i];
- }
- }
-
- return null;
- }
-}
diff --git a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/RequiredAttributeDetector.java b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/RequiredAttributeDetector.java
index 08f10995213..df31c354861 100644
--- a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/RequiredAttributeDetector.java
+++ b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/RequiredAttributeDetector.java
@@ -538,7 +538,7 @@ public class RequiredAttributeDetector extends LayoutDetector implements UastSca
}
@Override
- public void visitFunctionCall(UastAndroidContext context, UCallExpression node) {
+ public void visitCall(UastAndroidContext context, UCallExpression node) {
// Handle
// View#inflate(Context context, int resource, ViewGroup root)
// LayoutInflater#inflate(int resource, ViewGroup root)
diff --git a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/RtlDetector.java b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/RtlDetector.java
index 0a169c82bb8..a43819f3681 100644
--- a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/RtlDetector.java
+++ b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/RtlDetector.java
@@ -73,7 +73,6 @@ import com.android.tools.klint.detector.api.XmlContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.uast.*;
-import org.jetbrains.uast.check.UastAndroidUtils;
import org.jetbrains.uast.check.UastAndroidContext;
import org.jetbrains.uast.check.UastScanner;
import org.jetbrains.uast.visitor.EmptyUastVisitor;
@@ -99,7 +98,7 @@ public class RtlDetector extends LayoutDetector implements UastScanner {
RtlDetector.class,
EnumSet.of(Scope.RESOURCE_FILE, Scope.SOURCE_FILE, Scope.MANIFEST),
Scope.RESOURCE_FILE_SCOPE,
- Scope.JAVA_FILE_SCOPE,
+ Scope.SOURCE_FILE_SCOPE,
Scope.MANIFEST_SCOPE
);
@@ -607,7 +606,7 @@ public class RtlDetector extends LayoutDetector implements UastScanner {
// Can't resolve types (for example while editing code with errors):
// rely on heuristics like import statements and class qualifiers
if (parent instanceof UQualifiedExpression &&
- !(GRAVITY_CLASS.equals(((UQualifiedExpression) parent).getReceiver().renderString()))) {
+ !(UastUtils.matchesQualified(((UQualifiedExpression) parent).getReceiver(), GRAVITY_CLASS))) {
return false;
}
if (parent instanceof USimpleReferenceExpression) {
@@ -624,7 +623,7 @@ public class RtlDetector extends LayoutDetector implements UastScanner {
+ "behavior in right-to-left locales",
(isLeft ? GRAVITY_VALUE_START : GRAVITY_VALUE_END).toUpperCase(Locale.US),
(isLeft ? GRAVITY_VALUE_LEFT : GRAVITY_VALUE_RIGHT).toUpperCase(Locale.US));
- Location location = UastAndroidUtils.getLocation(node);
+ Location location = mContext.getLocation(node);
mContext.report(USE_START, node, location, message);
return true;
diff --git a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/SQLiteDetector.java b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/SQLiteDetector.java
index 70dca758002..f30a9b0b415 100644
--- a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/SQLiteDetector.java
+++ b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/SQLiteDetector.java
@@ -29,7 +29,6 @@ import java.util.Collections;
import java.util.List;
import org.jetbrains.uast.*;
-import org.jetbrains.uast.check.UastAndroidUtils;
import org.jetbrains.uast.check.UastAndroidContext;
import org.jetbrains.uast.check.UastScanner;
@@ -38,7 +37,7 @@ import org.jetbrains.uast.check.UastScanner;
*/
public class SQLiteDetector extends Detector implements UastScanner {
private static final Implementation IMPLEMENTATION = new Implementation(
- SQLiteDetector.class, Scope.JAVA_FILE_SCOPE);
+ SQLiteDetector.class, Scope.SOURCE_FILE_SCOPE);
/** Using STRING instead of TEXT for columns */
public static final Issue ISSUE = Issue.create(
@@ -77,7 +76,7 @@ public class SQLiteDetector extends Detector implements UastScanner {
}
@Override
- public void visitFunctionCall(UastAndroidContext context, UCallExpression node) {
+ public void visitCall(UastAndroidContext context, UCallExpression node) {
UFunction resolvedFunction = node.resolve(context);
UClass containingClass = UastUtils.getContainingClass(resolvedFunction);
if (resolvedFunction == null || containingClass == null) {
@@ -100,7 +99,7 @@ public class SQLiteDetector extends Detector implements UastScanner {
+ "(STRING is a numeric type and its value can be adjusted; for example,"
+ "strings that look like integers can drop leading zeroes. See issue "
+ "explanation for details.)";
- context.report(ISSUE, node, UastAndroidUtils.getLocation(node), message);
+ context.report(ISSUE, node, context.getLocation(node), message);
}
}
}
diff --git a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/SdCardDetector.java b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/SdCardDetector.java
index 9dbe622b9da..07c2ccb77b2 100644
--- a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/SdCardDetector.java
+++ b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/SdCardDetector.java
@@ -31,7 +31,6 @@ import java.io.File;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.uast.ULiteralExpression;
-import org.jetbrains.uast.check.UastAndroidUtils;
import org.jetbrains.uast.check.UastAndroidContext;
import org.jetbrains.uast.check.UastScanner;
import org.jetbrains.uast.visitor.UastVisitor;
@@ -57,7 +56,7 @@ public class SdCardDetector extends Detector implements UastScanner {
Severity.WARNING,
new Implementation(
SdCardDetector.class,
- Scope.JAVA_FILE_SCOPE))
+ Scope.SOURCE_FILE_SCOPE))
.addMoreInfo(
"http://developer.android.com/guide/topics/data/data-storage.html#filesExternal"); //$NON-NLS-1$
@@ -110,13 +109,13 @@ public class SdCardDetector extends Detector implements UastScanner {
|| s.startsWith("file:///sdcard/")) { //$NON-NLS-1$
String message = "Do not hardcode \"/sdcard/\"; " +
"use `Environment.getExternalStorageDirectory().getPath()` instead";
- Location location = UastAndroidUtils.getLocation(node);
+ Location location = mContext.getLocation(node);
mContext.report(ISSUE, node, location, message);
} else if (s.startsWith("/data/data/") //$NON-NLS-1$
|| s.startsWith("/data/user/")) { //$NON-NLS-1$
String message = "Do not hardcode \"`/data/`\"; " +
"use `Context.getFilesDir().getPath()` instead";
- Location location = UastAndroidUtils.getLocation(node);
+ Location location = mContext.getLocation(node);
mContext.report(ISSUE, node, location, message);
}
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 ddd71b9bf31..9092ed96e73 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
@@ -52,7 +52,6 @@ import com.android.tools.klint.detector.api.XmlContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.uast.UCallExpression;
import org.jetbrains.uast.USimpleReferenceExpression;
-import org.jetbrains.uast.check.UastAndroidUtils;
import org.jetbrains.uast.check.UastAndroidContext;
import org.jetbrains.uast.check.UastScanner;
import org.jetbrains.uast.visitor.UastVisitor;
@@ -75,7 +74,7 @@ public class SecurityDetector extends Detector implements Detector.XmlScanner, U
private static final Implementation IMPLEMENTATION_JAVA = new Implementation(
SecurityDetector.class,
- Scope.JAVA_FILE_SCOPE);
+ Scope.SOURCE_FILE_SCOPE);
/** Exported services */
public static final Issue EXPORTED_SERVICE = Issue.create(
@@ -366,12 +365,12 @@ public class SecurityDetector extends Detector implements Detector.XmlScanner, U
@Override
public boolean visitSimpleReferenceExpression(@NotNull USimpleReferenceExpression node) {
if ("MODE_WORLD_WRITEABLE".equals(node.getIdentifier())) { //$NON-NLS-1$
- Location location = UastAndroidUtils.getLocation(node);
+ Location location = mContext.getLocation(node);
mContext.report(WORLD_WRITEABLE, node, location,
"Using `MODE_WORLD_WRITEABLE` when creating files can be " +
"risky, review carefully");
} else if ("MODE_WORLD_READABLE".equals(node.getIdentifier())) { //$NON-NLS-1$
- Location location = UastAndroidUtils.getLocation(node);
+ Location location = mContext.getLocation(node);
mContext.report(WORLD_READABLE, node, location,
"Using `MODE_WORLD_READABLE` when creating files can be " +
"risky, review carefully");
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 9b92117ad33..719c28c5471 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
@@ -33,7 +33,6 @@ import java.util.List;
import java.util.Map;
import org.jetbrains.uast.*;
-import org.jetbrains.uast.check.UastAndroidUtils;
import org.jetbrains.uast.check.UastAndroidContext;
import org.jetbrains.uast.check.UastScanner;
@@ -55,7 +54,7 @@ public class ServiceCastDetector extends Detector implements UastScanner {
Severity.FATAL,
new Implementation(
ServiceCastDetector.class,
- Scope.JAVA_FILE_SCOPE));
+ Scope.SOURCE_FILE_SCOPE));
/** Constructs a new {@link ServiceCastDetector} check */
public ServiceCastDetector() {
@@ -75,7 +74,7 @@ public class ServiceCastDetector extends Detector implements UastScanner {
}
@Override
- public void visitFunctionCall(UastAndroidContext context, UCallExpression node) {
+ public void visitCall(UastAndroidContext context, UCallExpression node) {
UExpression receiver = UastUtils.getQualifiedCallElement(node);
UElement parent = receiver.getParent();
if (!(parent instanceof UBinaryExpressionWithType)
@@ -103,7 +102,7 @@ public class ServiceCastDetector extends Detector implements UastScanner {
String message = String.format(
"Suspicious cast to `%1$s` for a `%2$s`: expected `%3$s`",
stripPackage(castType), name, stripPackage(expectedClass));
- context.report(ISSUE, node, UastAndroidUtils.getLocation(cast), message);
+ context.report(ISSUE, node, context.getLocation(cast), message);
}
}
}
diff --git a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/SetJavaScriptEnabledDetector.java b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/SetJavaScriptEnabledDetector.java
index a8f62ddcf7f..0b1b5e96bc5 100644
--- a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/SetJavaScriptEnabledDetector.java
+++ b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/SetJavaScriptEnabledDetector.java
@@ -27,7 +27,6 @@ import java.util.Collections;
import java.util.List;
import org.jetbrains.uast.UCallExpression;
-import org.jetbrains.uast.check.UastAndroidUtils;
import org.jetbrains.uast.check.UastAndroidContext;
import org.jetbrains.uast.check.UastScanner;
@@ -47,7 +46,7 @@ public class SetJavaScriptEnabledDetector extends Detector implements UastScanne
Severity.WARNING,
new Implementation(
SetJavaScriptEnabledDetector.class,
- Scope.JAVA_FILE_SCOPE))
+ Scope.SOURCE_FILE_SCOPE))
.addMoreInfo(
"http://developer.android.com/guide/practices/security.html"); //$NON-NLS-1$
@@ -58,14 +57,14 @@ public class SetJavaScriptEnabledDetector extends Detector implements UastScanne
// ---- Implements UastScanner ----
@Override
- public void visitFunctionCall(UastAndroidContext context, UCallExpression node) {
+ public void visitCall(UastAndroidContext context, UCallExpression node) {
if (node.getValueArgumentCount() != 1) {
return;
}
Object value = node.getValueArguments().get(0).evaluate();
if (value instanceof Boolean && (Boolean) value) {
- context.report(ISSUE, node, UastAndroidUtils.getLocation(node),
+ context.report(ISSUE, node, context.getLocation(node),
"Using `setJavaScriptEnabled` can introduce XSS vulnerabilities " +
"into you application, review carefully.");
}
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 1ae46cca7a8..8c764ee9b47 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
@@ -34,9 +34,8 @@ import java.util.List;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.uast.*;
import org.jetbrains.uast.check.UastAndroidContext;
-import org.jetbrains.uast.check.UastAndroidUtils;
import org.jetbrains.uast.check.UastScanner;
-import org.jetbrains.uast.java.JavaSpecialExpressionKinds;
+import org.jetbrains.uast.java.JavaUAssertExpression;
import org.jetbrains.uast.visitor.UastVisitor;
/**
@@ -57,7 +56,7 @@ public class SharedPrefsDetector extends Detector implements UastScanner {
Severity.WARNING,
new Implementation(
SharedPrefsDetector.class,
- Scope.JAVA_FILE_SCOPE));
+ Scope.SOURCE_FILE_SCOPE));
public static final String ANDROID_CONTENT_SHARED_PREFERENCES =
"android.content.SharedPreferences"; //$NON-NLS-1$
@@ -82,7 +81,7 @@ public class SharedPrefsDetector extends Detector implements UastScanner {
}
@Override
- public void visitFunctionCall(UastAndroidContext context, UCallExpression node) {
+ public void visitCall(UastAndroidContext context, UCallExpression node) {
assert "edit".equals(node.getFunctionName());
boolean verifiedType = false;
@@ -149,7 +148,7 @@ public class SharedPrefsDetector extends Detector implements UastScanner {
CommitFinder finder = new CommitFinder(context, node, allowCommitBeforeTarget);
method.accept(finder);
if (!finder.isCommitCalled()) {
- context.report(ISSUE, method, UastAndroidUtils.getLocation(node),
+ context.report(ISSUE, method, context.getLocation(node),
"`SharedPreferences.edit()` without a corresponding `commit()` or `apply()` call");
}
}
@@ -220,8 +219,7 @@ public class SharedPrefsDetector extends Detector implements UastScanner {
returnValueIgnored = true;
} else if (qualifiedElement instanceof UIfExpression) {
returnValueIgnored = ((UIfExpression) qualifiedElement).getCondition() != node;
- } else if (qualifiedElement instanceof USpecialExpressionList &&
- ((USpecialExpressionList)qualifiedElement).getKind() == UastSpecialExpressionKind.RETURN) {
+ } else if (qualifiedElement instanceof UReturnExpression) {
returnValueIgnored = false;
} else if (qualifiedElement instanceof UVariable) {
returnValueIgnored = false;
@@ -231,11 +229,16 @@ public class SharedPrefsDetector extends Detector implements UastScanner {
returnValueIgnored = ((UWhileExpression) qualifiedElement).getCondition() != node;
} else if (qualifiedElement instanceof UDoWhileExpression) {
returnValueIgnored = ((UDoWhileExpression) qualifiedElement).getCondition() != node;
- } else if (qualifiedElement instanceof UExpressionSwitchClauseExpression) {
- returnValueIgnored = ((UExpressionSwitchClauseExpression) qualifiedElement).getCaseValue() != node;
- } else if (qualifiedElement instanceof USpecialExpressionList &&
- ((USpecialExpressionList)qualifiedElement).getKind() == JavaSpecialExpressionKinds.ASSERT) {
- returnValueIgnored = !((USpecialExpressionList) qualifiedElement).getExpressions().contains(node);
+ } else if (qualifiedElement instanceof USwitchClauseExpression) {
+ List caseValues = ((USwitchClauseExpression) qualifiedElement).getCaseValues();
+ for (UExpression caseValue : caseValues) {
+ if (caseValue == node) {
+ returnValueIgnored = false;
+ break;
+ }
+ }
+ } else if (qualifiedElement instanceof JavaUAssertExpression) {
+ returnValueIgnored = !((JavaUAssertExpression) qualifiedElement).getCondition().equals(node);
} else {
returnValueIgnored = true;
}
@@ -243,7 +246,7 @@ public class SharedPrefsDetector extends Detector implements UastScanner {
String message = "Consider using `apply()` instead; `commit` writes "
+ "its data to persistent storage immediately, whereas "
+ "`apply` will handle it in the background";
- mContext.report(ISSUE, node, UastAndroidUtils.getLocation(node), message);
+ mContext.report(ISSUE, node, mContext.getLocation(node), message);
}
}
}
@@ -254,11 +257,9 @@ public class SharedPrefsDetector extends Detector implements UastScanner {
}
@Override
- public boolean visitSpecialExpressionList(@NotNull USpecialExpressionList node) {
- if (node.getKind() == UastSpecialExpressionKind.RETURN) {
- if (node.getExpressions().contains(mTarget)) {
- mFound = true;
- }
+ public boolean visitReturnExpression(@NotNull UReturnExpression node) {
+ if (mTarget.equals(node.getExpressionType())) {
+ mFound = true;
}
return false;
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 7415d5130c7..5c979565007 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
@@ -102,7 +102,7 @@ public class StringFormatDetector extends ResourceXmlDetector implements UastSca
private static final Implementation IMPLEMENTATION_XML_AND_JAVA = new Implementation(
StringFormatDetector.class,
EnumSet.of(Scope.ALL_RESOURCE_FILES, Scope.SOURCE_FILE),
- Scope.JAVA_FILE_SCOPE);
+ Scope.SOURCE_FILE_SCOPE);
/** Whether formatting strings are invalid */
@@ -987,7 +987,7 @@ public class StringFormatDetector extends ResourceXmlDetector implements UastSca
}
@Override
- public void visitFunctionCall(UastAndroidContext context, UCallExpression node) {
+ public void visitCall(UastAndroidContext context, UCallExpression node) {
if (mFormatStrings == null && !context.getLintContext().getClient().supportsProjectResources()) {
return;
}
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 a052377f592..747c0c1e311 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
@@ -53,7 +53,6 @@ import org.jetbrains.uast.check.UastAndroidContext;
import org.jetbrains.uast.check.UastScanner;
import org.jetbrains.uast.java.JavaUFunction;
import org.jetbrains.uast.java.JavaUastCallKinds;
-import org.jetbrains.uast.kinds.UastOperator;
import org.jetbrains.uast.visitor.UastVisitor;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
@@ -79,7 +78,7 @@ import java.util.Set;
public class SupportAnnotationDetector extends Detector implements UastScanner {
public static final Implementation IMPLEMENTATION
- = new Implementation(SupportAnnotationDetector.class, Scope.JAVA_FILE_SCOPE);
+ = new Implementation(SupportAnnotationDetector.class, Scope.SOURCE_FILE_SCOPE);
/** Method result should be used */
public static final Issue RANGE = Issue.create(
@@ -753,7 +752,7 @@ public class SupportAnnotationDetector extends Detector implements UastScanner {
UQualifiedExpression select = (UQualifiedExpression) node.getReceiver();
if (select.getReceiver() instanceof UQualifiedExpression) { // android.R....
UQualifiedExpression innerSelect = (UQualifiedExpression) select.getReceiver();
- if (innerSelect.getSelector().renderString().equals(R_CLASS)) {
+ if (UastUtils.matchesQualified(innerSelect.getSelector(), R_CLASS)) {
String typeName = select.getSelector().renderString();
ResourceType type = ResourceType.getEnum(typeName);
return type != null ? Collections.singletonList(type) : null;
@@ -770,7 +769,7 @@ public class SupportAnnotationDetector extends Detector implements UastScanner {
}
// Arbitrary packages -- android.R.type.name, foo.bar.R.type.name
- if (node.getSelector().renderString().equals(R_CLASS)) {
+ if (UastUtils.matchesQualified(node.getSelector(), R_CLASS)) {
UElement parent = node.getParent();
if (parent instanceof UQualifiedExpression) {
UElement grandParent = parent.getParent();
@@ -788,8 +787,7 @@ public class SupportAnnotationDetector extends Detector implements UastScanner {
}
} else if (argument instanceof UCallExpression) {
UDeclaration resolved = ((UCallExpression)argument).resolve(context);
- //noinspection ConstantConditions
- if (resolved instanceof UAnnotated) {
+ if (resolved != null) {
List annotations = ((UAnnotated) resolved).getAnnotations();
for (UAnnotation annotation : annotations) {
String signature = annotation.getFqName();
@@ -972,7 +970,7 @@ public class SupportAnnotationDetector extends Detector implements UastScanner {
assert s != null;
actual = s.length();
} else if (argument instanceof UCallExpression
- && ((UCallExpression)argument).getKind() == JavaUastCallKinds.ARRAY_INITIALIZER) {
+ && ((UCallExpression)argument).getKind() == UastCallKind.ARRAY_INITIALIZER) {
UCallExpression initializer = (UCallExpression) argument;
actual = initializer.getValueArgumentCount();
} else {
@@ -1059,7 +1057,7 @@ public class SupportAnnotationDetector extends Detector implements UastScanner {
if (!flag) {
reportTypeDef(context, annotation, argument, errorNode);
}
- } else if (argument instanceof UIfExpression && ((UIfExpression) argument).isTernary()) {
+ } else if (argument instanceof UIfExpression) {
UIfExpression expression = (UIfExpression) argument;
if (expression.getThenBranch() != null) {
checkTypeDefConstant(context, annotation, expression.getThenBranch(), errorNode, flag);
@@ -1077,7 +1075,6 @@ public class SupportAnnotationDetector extends Detector implements UastScanner {
"Flag not allowed here");
}
} else if (argument instanceof UBinaryExpression) {
- // If it's ?: then check both the if and else clauses
UBinaryExpression expression = (UBinaryExpression) argument;
if (flag) {
checkTypeDefConstant(context, annotation, expression.getLeftOperand(), errorNode, true);
@@ -1102,13 +1099,18 @@ public class SupportAnnotationDetector extends Detector implements UastScanner {
private static void checkTypeDefConstant(@NonNull UastAndroidContext context,
@NonNull UAnnotation annotation, @NonNull UElement argument,
@Nullable UElement errorNode, boolean flag, Object value) {
- List> valueArguments = annotation.getValues();
- for (Pair o : valueArguments) {
- if (o.getSecond().equals(value)) {
- return;
+ for (UNamedExpression namedExpression : annotation.getValueArguments()) {
+ UExpression expression = namedExpression.getExpression();
+ if (expression instanceof UCallExpression &&
+ ((UCallExpression) expression).getKind() == UastCallKind.ARRAY_INITIALIZER) {
+ for (UExpression arg : ((UCallExpression) expression).getValueArguments()) {
+ if (value.equals(arg.evaluate())) {
+ return;
+ }
+ }
}
}
- reportTypeDef(context, argument, errorNode, flag, valueArguments);
+ reportTypeDef(context, argument, errorNode, flag, annotation.getValues());
}
private static void reportTypeDef(@NonNull UastAndroidContext context,
@@ -1242,47 +1244,6 @@ public class SupportAnnotationDetector extends Detector implements UastScanner {
return null;
}
- @Nullable
- static UAnnotation getRelevantAnnotation(
- @NonNull UastAndroidContext context,
- @NonNull UAnnotation annotation
- ) {
- String signature = annotation.getFqName();
- if (signature != null && signature.startsWith(SUPPORT_ANNOTATIONS_PREFIX)) {
- // Bail on the nullness annotations early since they're the most commonly
- // defined ones. They're not analyzed in lint yet.
- if (signature.endsWith(".Nullable") || signature.endsWith(".NonNull")) {
- return null;
- }
-
-
- return annotation;
- }
-
- if (signature != null && signature.startsWith("java.")) {
- // @Override, @SuppressWarnings etc. Ignore
- return null;
- }
-
- // Special case @IntDef and @StringDef: These are used on annotations
- // themselves. For example, you create a new annotation named @foo.bar.Baz,
- // annotate it with @IntDef, and then use @foo.bar.Baz in your signatures.
- // Here we want to map from @foo.bar.Baz to the corresponding int def.
- // Don't need to compute this if performing @IntDef or @StringDef lookup
- UClass type = annotation.resolve(context);
- if (type != null) {
- for (UAnnotation inner : type.getAnnotations()) {
- if (INT_DEF_ANNOTATION.equals(inner.getFqName())
- || STRING_DEF_ANNOTATION.equals(inner.getFqName())
- || PERMISSION_ANNOTATION.equals(inner.getFqName())) {
- return inner;
- }
- }
- }
-
- return null;
- }
-
// ---- Implements UastScanner ----
@Override
diff --git a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/TitleDetector.java b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/TitleDetector.java
deleted file mode 100644
index a409c084206..00000000000
--- a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/TitleDetector.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * 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 com.android.tools.klint.checks;
-
-import static com.android.SdkConstants.ANDROID_URI;
-import static com.android.SdkConstants.ATTR_TITLE;
-import static com.android.SdkConstants.ATTR_VISIBLE;
-import static com.android.SdkConstants.TAG_ITEM;
-import static com.android.SdkConstants.VALUE_FALSE;
-
-import com.android.annotations.NonNull;
-import com.android.annotations.Nullable;
-import com.android.resources.ResourceFolderType;
-import com.android.tools.klint.detector.api.Category;
-import com.android.tools.klint.detector.api.Implementation;
-import com.android.tools.klint.detector.api.Issue;
-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.Speed;
-import com.android.tools.klint.detector.api.XmlContext;
-
-import org.jetbrains.uast.check.UastScanner;
-import org.w3c.dom.Element;
-
-import java.util.Collection;
-import java.util.Collections;
-
-/**
- * Check which makes sure menu items specify a title
- */
-public class TitleDetector extends ResourceXmlDetector implements UastScanner {
- /** The main issue discovered by this detector */
- public static final Issue ISSUE = Issue.create(
- "MenuTitle", //$NON-NLS-1$
- "Missing menu title",
-
- "From the action bar documentation:\n" +
- // u2014: em dash
- "\"It's important that you always define android:title for each menu item \u2014 " +
- "even if you don't declare that the title appear with the action item \u2014 for " +
- "three reasons:\n" +
- "\n" +
- "* If there's not enough room in the action bar for the action item, the menu " +
- "item appears in the overflow menu and only the title appears.\n" +
- "* Screen readers for sight-impaired users read the menu item's title.\n" +
- "* If the action item appears with only the icon, a user can long-press the item " +
- "to reveal a tool-tip that displays the action item's title.\n" +
- "The android:icon is always optional, but recommended.",
-
- Category.USABILITY,
- 5,
- Severity.ERROR,
- new Implementation(
- TitleDetector.class,
- Scope.RESOURCE_FILE_SCOPE))
- .addMoreInfo(
- "http://developer.android.com/guide/topics/ui/actionbar.html"); //$NON-NLS-1$
-
- /** Constructs a new {@link TitleDetector} */
- public TitleDetector() {
- }
-
- @Override
- public boolean appliesTo(@NonNull ResourceFolderType folderType) {
- return folderType == ResourceFolderType.MENU;
- }
-
- @NonNull
- @Override
- public Speed getSpeed() {
- return Speed.FAST;
- }
-
- @Override
- @Nullable
- public Collection getApplicableElements() {
- return Collections.singletonList(TAG_ITEM);
- }
-
- @Override
- public void visitElement(@NonNull XmlContext context, @NonNull Element element) {
- if (element.hasAttributeNS(ANDROID_URI, ATTR_TITLE)) {
- return;
- }
-
- // TODO: Find out if this is necessary on older versions too.
- // I swear I saw it mentioned.
- if (context.getMainProject().getTargetSdk() < 11) {
- return;
- }
-
- if (VALUE_FALSE.equals(element.getAttributeNS(ANDROID_URI, ATTR_VISIBLE))) {
- return;
- }
-
- String message = "Menu items should specify a `title`";
- context.report(ISSUE, element, context.getLocation(element), message);
- }
-}
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 45e2aa81c45..7b9602a3d52 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
@@ -31,7 +31,6 @@ import java.util.List;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.uast.*;
-import org.jetbrains.uast.check.UastAndroidUtils;
import org.jetbrains.uast.check.UastAndroidContext;
import org.jetbrains.uast.check.UastScanner;
import org.jetbrains.uast.visitor.UastVisitor;
@@ -51,7 +50,7 @@ public class ToastDetector extends Detector implements UastScanner {
Severity.WARNING,
new Implementation(
ToastDetector.class,
- Scope.JAVA_FILE_SCOPE));
+ Scope.SOURCE_FILE_SCOPE));
/** Constructs a new {@link ToastDetector} check */
@@ -72,7 +71,7 @@ public class ToastDetector extends Detector implements UastScanner {
}
@Override
- public void visitFunctionCall(UastAndroidContext context, UCallExpression node) {
+ public void visitCall(UastAndroidContext context, UCallExpression node) {
assert "makeText".equals(node.getFunctionName());
UElement qualifiedExpression = node.getParent();
@@ -80,8 +79,7 @@ public class ToastDetector extends Detector implements UastScanner {
return;
}
- String operand = ((UQualifiedExpression)qualifiedExpression).getReceiver().renderString();
- if (!(operand.equals("Toast") || operand.endsWith(".Toast"))) {
+ if (!UastUtils.endsWithQualified(((UQualifiedExpression) qualifiedExpression).getReceiver(), "Toast")) {
return;
}
@@ -107,7 +105,7 @@ public class ToastDetector extends Detector implements UastScanner {
ShowFinder finder = new ShowFinder(nodeWithPossibleQualifier);
method.accept(finder);
if (!finder.isShowCalled()) {
- context.report(ISSUE, node, UastAndroidUtils.getLocation(node),
+ context.report(ISSUE, node, context.getLocation(node),
"Toast created but not shown: did you forget to call `show()` ?");
}
}
@@ -128,7 +126,7 @@ public class ToastDetector extends Detector implements UastScanner {
public boolean visitCallExpression(@NotNull UCallExpression node) {
if (node == mTarget) {
mSeenTarget = true;
- } else if (mSeenTarget && node.functionNameMatches("show")) { //$NON-NLS-1$
+ } else if (mSeenTarget && node.matchesFunctionName("show")) { //$NON-NLS-1$
// TODO: Do more flow analysis to see whether we're really calling show
// on the right type of object?
mFound = true;
@@ -147,9 +145,8 @@ public class ToastDetector extends Detector implements UastScanner {
}
@Override
- public boolean visitSpecialExpressionList(@NotNull USpecialExpressionList node) {
- if (node.getKind() == UastSpecialExpressionKind.RETURN && node.firstOrNull() == mTarget) {
- // If you just do "return Toast.makeText(...) don't warn
+ public boolean visitReturnExpression(@NotNull UReturnExpression node) {
+ if (mTarget.equals(node.getReturnExpression())) {
mFound = true;
}
diff --git a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/ViewConstructorDetector.java b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/ViewConstructorDetector.java
index bf954c10168..74ea0e86961 100644
--- a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/ViewConstructorDetector.java
+++ b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/ViewConstructorDetector.java
@@ -35,10 +35,8 @@ import java.util.Collections;
import java.util.List;
import org.jetbrains.uast.*;
-import org.jetbrains.uast.check.UastAndroidUtils;
import org.jetbrains.uast.check.UastAndroidContext;
import org.jetbrains.uast.check.UastScanner;
-import org.jetbrains.uast.kinds.UastClassKind;
/**
* Looks for custom views that do not define the view constructors needed by UI builders
@@ -65,7 +63,7 @@ public class ViewConstructorDetector extends Detector implements UastScanner {
Severity.WARNING,
new Implementation(
ViewConstructorDetector.class,
- Scope.JAVA_FILE_SCOPE));
+ Scope.SOURCE_FILE_SCOPE));
/** Constructs a new {@link ViewConstructorDetector} check */
public ViewConstructorDetector() {
@@ -140,7 +138,7 @@ public class ViewConstructorDetector extends Detector implements UastScanner {
+ "`(Context)` or `(Context,AttributeSet)` "
+ "or `(Context,AttributeSet,int)`",
node.getFqName());
- Location location = UastAndroidUtils.getLocation(node.getNameElement());
+ Location location = context.getLocation(node.getNameElement());
context.report(ISSUE, node, location, message /*data*/);
}
}
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 39cbca1a7eb..6439689c12e 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
@@ -34,7 +34,6 @@ import java.util.List;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.uast.*;
import org.jetbrains.uast.check.UastAndroidContext;
-import org.jetbrains.uast.check.UastAndroidUtils;
import org.jetbrains.uast.check.UastScanner;
import org.jetbrains.uast.visitor.UastVisitor;
@@ -45,7 +44,7 @@ public class ViewHolderDetector extends Detector implements UastScanner {
private static final Implementation IMPLEMENTATION = new Implementation(
ViewHolderDetector.class,
- Scope.JAVA_FILE_SCOPE);
+ Scope.SOURCE_FILE_SCOPE);
/** Using a view inflater unconditionally in an AdapterView */
public static final Issue ISSUE = Issue.create(
@@ -109,32 +108,8 @@ public class ViewHolderDetector extends Detector implements UastScanner {
if (GET_VIEW.equals(node.getName())) {
List parameters = node.getValueParameters();
if (parameters.size() == 3) {
- Iterator iterator = parameters.iterator();
- if (!iterator.hasNext()) {
- return false;
- }
-
- UVariable first = iterator.next();
- if (!first.getType().isInt()) {
- return false;
- }
-
- if (!iterator.hasNext()) {
- return false;
- }
-
- UVariable second = iterator.next();
- if (!second.getType().matchesFqName(CLASS_VIEW)) {
- return false;
- }
-
- if (!iterator.hasNext()) {
- return false;
- }
-
- UVariable third = iterator.next();
//noinspection RedundantIfStatement
- if (!third.getType().matchesFqName(CLASS_VIEWGROUP)) {
+ if (!parameters.get(2).getType().matchesFqName(CLASS_VIEWGROUP)) {
return false;
}
@@ -202,7 +177,7 @@ public class ViewHolderDetector extends Detector implements UastScanner {
+ "Should use View Holder pattern (use recycled view passed "
+ "into this method as the second parameter) for smoother "
+ "scrolling";
- mContext.report(ISSUE, node, UastAndroidUtils.getLocation(node), message);
+ mContext.report(ISSUE, node, mContext.getLocation(node), message);
}
}
}
diff --git a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/ViewTypeDetector.java b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/ViewTypeDetector.java
index 40c7a22835b..7f13c246df6 100644
--- a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/ViewTypeDetector.java
+++ b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/ViewTypeDetector.java
@@ -54,7 +54,6 @@ import com.google.common.collect.Sets;
import org.jetbrains.uast.*;
import org.jetbrains.uast.check.UastAndroidContext;
-import org.jetbrains.uast.check.UastAndroidUtils;
import org.jetbrains.uast.check.UastScanner;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
@@ -98,7 +97,7 @@ public class ViewTypeDetector extends ResourceXmlDetector implements UastScanner
new Implementation(
ViewTypeDetector.class,
EnumSet.of(Scope.ALL_RESOURCE_FILES, Scope.ALL_SOURCE_FILES),
- Scope.JAVA_FILE_SCOPE));
+ Scope.SOURCE_FILE_SCOPE));
/** Flag used to do no work if we're running in incremental mode in a .java file without
* a client supporting project resources */
@@ -168,7 +167,7 @@ public class ViewTypeDetector extends ResourceXmlDetector implements UastScanner
}
@Override
- public void visitFunctionCall(UastAndroidContext context, UCallExpression node) {
+ public void visitCall(UastAndroidContext context, UCallExpression node) {
JavaContext lintContext = context.getLintContext();
LintClient client = lintContext.getClient();
if (mIgnore == Boolean.TRUE) {
@@ -193,42 +192,42 @@ public class ViewTypeDetector extends ResourceXmlDetector implements UastScanner
// TODO: Do flow analysis as in the StringFormatDetector in order
// to handle variable references too
if (first instanceof UQualifiedExpression) {
- String resource = first.renderString();
- if (resource.startsWith("R.id.")) { //$NON-NLS-1$
- String id = ((UQualifiedExpression) first).getSelector().renderString();
+ if (UastUtils.startsWithQualified(first, "R.id")) { //$NON-NLS-1$
+ String id = ((UQualifiedExpression) first).getSelectorAsIdentifier();
- if (client.supportsProjectResources()) {
- AbstractResourceRepository resources = client
- .getProjectResources(lintContext.getMainProject(), true);
- if (resources == null) {
- return;
- }
+ if (id != null) {
+ if (client.supportsProjectResources()) {
+ AbstractResourceRepository resources = client
+ .getProjectResources(lintContext.getMainProject(), true);
+ if (resources == null) {
+ return;
+ }
- List items = resources.getResourceItem(ResourceType.ID,
- id);
- if (items != null && !items.isEmpty()) {
- Set compatible = Sets.newHashSet();
- for (ResourceItem item : items) {
- Collection tags = getViewTags(lintContext, item);
- if (tags != null) {
- compatible.addAll(tags);
+ List items = resources.getResourceItem(ResourceType.ID, id);
+ if (items != null && !items.isEmpty()) {
+ Set compatible = Sets.newHashSet();
+ for (ResourceItem item : items) {
+ Collection tags = getViewTags(lintContext, item);
+ if (tags != null) {
+ compatible.addAll(tags);
+ }
+ }
+ if (!compatible.isEmpty()) {
+ ArrayList layoutTypes = Lists.newArrayList(compatible);
+ checkCompatible(lintContext, castType, null, layoutTypes, cast);
}
}
- if (!compatible.isEmpty()) {
- ArrayList layoutTypes = Lists.newArrayList(compatible);
+ } else {
+ Object types = mIdToViewTag.get(id);
+ if (types instanceof String) {
+ String layoutType = (String) types;
+ checkCompatible(lintContext, castType, layoutType, null, cast);
+ } else if (types instanceof List>) {
+ @SuppressWarnings("unchecked")
+ List layoutTypes = (List) types;
checkCompatible(lintContext, castType, null, layoutTypes, cast);
}
}
- } else {
- Object types = mIdToViewTag.get(id);
- if (types instanceof String) {
- String layoutType = (String) types;
- checkCompatible(lintContext, castType, layoutType, null, cast);
- } else if (types instanceof List>) {
- @SuppressWarnings("unchecked")
- List layoutTypes = (List) types;
- checkCompatible(lintContext, castType, null, layoutTypes, cast);
- }
}
}
}
@@ -240,6 +239,8 @@ public class ViewTypeDetector extends ResourceXmlDetector implements UastScanner
return (UBinaryExpressionWithType) expression;
} else if (expression instanceof UQualifiedExpression) {
return findContainingTypeCast(expression.getParent());
+ } else if (expression instanceof UParenthesizedExpression) {
+ return findContainingTypeCast(((UParenthesizedExpression) expression).getExpression());
} else {
return null;
}
@@ -337,7 +338,7 @@ public class ViewTypeDetector extends ResourceXmlDetector implements UastScanner
String message = String.format(
"Unexpected cast to `%1$s`: layout tag was `%2$s`",
castType, layoutType);
- context.report(ISSUE, node, UastAndroidUtils.getLocation(node), message);
+ context.report(ISSUE, node, context.getLocation(node), message);
}
}
}
diff --git a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/WrongCallDetector.java b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/WrongCallDetector.java
index 29f38397482..09675c315f8 100644
--- a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/WrongCallDetector.java
+++ b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/WrongCallDetector.java
@@ -37,7 +37,6 @@ import java.util.Arrays;
import java.util.List;
import org.jetbrains.uast.*;
-import org.jetbrains.uast.check.UastAndroidUtils;
import org.jetbrains.uast.check.UastAndroidContext;
import org.jetbrains.uast.check.UastScanner;
@@ -58,7 +57,7 @@ public class WrongCallDetector extends Detector implements UastScanner {
Severity.FATAL,
new Implementation(
WrongCallDetector.class,
- Scope.JAVA_FILE_SCOPE));
+ Scope.SOURCE_FILE_SCOPE));
/** Constructs a new {@link WrongCallDetector} */
public WrongCallDetector() {
@@ -83,7 +82,7 @@ public class WrongCallDetector extends Detector implements UastScanner {
}
@Override
- public void visitFunctionCall(UastAndroidContext context, UCallExpression node) {
+ public void visitCall(UastAndroidContext context, UCallExpression node) {
// Call is only allowed if it is both only called on the super class (invoke special)
// as well as within the same overriding method (e.g. you can't call super.onLayout
// from the onMeasure method)
@@ -130,7 +129,7 @@ public class WrongCallDetector extends Detector implements UastScanner {
// Keep in sync with {@link #getOldValue} and {@link #getNewValue} below!
"Suspicious method call; should probably call \"`%1$s`\" rather than \"`%2$s`\"",
suggestion, name);
- context.report(ISSUE, node, UastAndroidUtils.getLocation(node.getFunctionReference()), message);
+ context.report(ISSUE, node, context.getLocation(node.getFunctionReference()), message);
}
/**
diff --git a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/WrongImportDetector.java b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/WrongImportDetector.java
index 115dbed5469..e9a4226052c 100644
--- a/plugins/lint/lint-checks/src/com/android/tools/klint/checks/WrongImportDetector.java
+++ b/plugins/lint/lint-checks/src/com/android/tools/klint/checks/WrongImportDetector.java
@@ -28,7 +28,6 @@ import com.android.tools.klint.detector.api.Speed;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.uast.UImportStatement;
-import org.jetbrains.uast.check.UastAndroidUtils;
import org.jetbrains.uast.check.UastAndroidContext;
import org.jetbrains.uast.check.UastScanner;
import org.jetbrains.uast.visitor.UastVisitor;
@@ -62,7 +61,7 @@ public class WrongImportDetector extends Detector implements UastScanner {
Severity.WARNING,
new Implementation(
WrongImportDetector.class,
- Scope.JAVA_FILE_SCOPE));
+ Scope.SOURCE_FILE_SCOPE));
/** Constructs a new {@link WrongImportDetector} check */
public WrongImportDetector() {
@@ -92,7 +91,7 @@ public class WrongImportDetector extends Detector implements UastScanner {
public boolean visitImportStatement(@NotNull UImportStatement node) {
String fqn = node.getFqNameToImport();
if (fqn != null && fqn.equals("android.R")) { //$NON-NLS-1$
- Location location = UastAndroidUtils.getLocation(node);
+ Location location = mContext.getLocation(node);
mContext.report(ISSUE, node, location,
"Don't include `android.R` here; use a fully qualified name for "
+ "each usage instead");
diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidInspectionExtensionsFactory.java b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidInspectionExtensionsFactory.java
index b5ac6f03bd2..f7da14066d3 100644
--- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidInspectionExtensionsFactory.java
+++ b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidInspectionExtensionsFactory.java
@@ -1,19 +1,3 @@
-/*
- * 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.android.inspections.klint;
import com.intellij.codeInspection.HTMLComposer;
diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintExternalAnnotator.java b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintExternalAnnotator.java
index 6f2ff8ed248..fc4d8d698bd 100644
--- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintExternalAnnotator.java
+++ b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintExternalAnnotator.java
@@ -1,19 +1,3 @@
-/*
- * 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.android.inspections.klint;
import com.android.SdkConstants;
@@ -139,14 +123,14 @@ public class AndroidLintExternalAnnotator extends ExternalAnnotator pair =
+ final Pair pair =
AndroidLintUtil.getHighlighLevelAndInspection(project, issue, file);
if (pair == null) {
continue;
}
- final org.jetbrains.android.inspections.klint.AndroidLintInspectionBase inspection = pair.getFirst();
+ final AndroidLintInspectionBase inspection = pair.getFirst();
HighlightDisplayLevel displayLevel = pair.getSecond();
if (inspection != null) {
@@ -259,7 +242,7 @@ public class AndroidLintExternalAnnotator extends ExternalAnnotator" + DaemonBundle.message("inspection.extended.description")
- + " " + getShowMoreShortCut();
+ + "href=\"#lint/" + issue.getId() + "\""
+ + (UIUtil.isUnderDarcula() ? " color=\"7AB4C9\" " : "")
+ + ">" + DaemonBundle.message("inspection.extended.description")
+ + " " + getShowMoreShortCut();
String tooltip = XmlStringUtil.wrapInHtml(RAW.convertTo(message, HTML) + link);
try {
@@ -333,7 +316,7 @@ public class AndroidLintExternalAnnotator extends ExternalAnnotator() {
@Override
public String compute() {
diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintGlobalInspectionContext.java b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintGlobalInspectionContext.java
index ff4c4001953..2984e790220 100644
--- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintGlobalInspectionContext.java
+++ b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintGlobalInspectionContext.java
@@ -1,19 +1,3 @@
-/*
- * 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.android.inspections.klint;
import com.android.tools.klint.client.api.LintDriver;
diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintInspectionBase.java b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintInspectionBase.java
index d85ba973410..24a070651dd 100644
--- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintInspectionBase.java
+++ b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintInspectionBase.java
@@ -1,19 +1,3 @@
-/*
- * 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.android.inspections.klint;
import com.android.annotations.concurrency.GuardedBy;
@@ -215,8 +199,7 @@ public abstract class AndroidLintInspectionBase extends GlobalInspectionTool {
if (AndroidLintExternalAnnotator.INCLUDE_IDEA_SUPPRESS_ACTIONS) {
final List result = new ArrayList();
result.add(suppressLintQuickFix);
- result.addAll(Arrays.asList(
- BatchSuppressManager.SERVICE.getInstance().createBatchSuppressActions(HighlightDisplayKey.find(getShortName()))));
+ result.addAll(Arrays.asList(BatchSuppressManager.SERVICE.getInstance().createBatchSuppressActions(HighlightDisplayKey.find(getShortName()))));
result.addAll(Arrays.asList(new XmlSuppressableInspectionTool.SuppressTagStatic(getShortName()),
new XmlSuppressableInspectionTool.SuppressForFile(getShortName())));
return result.toArray(new SuppressQuickFix[result.size()]);
@@ -250,13 +233,7 @@ public abstract class AndroidLintInspectionBase extends GlobalInspectionTool {
}
@Override
- public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
- PsiElement myElement = descriptor.getPsiElement();
- PsiFile file = PsiTreeUtil.getParentOfType(myElement, PsiFile.class, false);
- if (file != null) {
- new SuppressLintIntentionAction(myIssue.getId(), myElement).invoke(project, null, file);
- }
- }
+ public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {}
}
@TestOnly
@@ -454,9 +431,9 @@ public abstract class AndroidLintInspectionBase extends GlobalInspectionTool {
}
/**
- * A {@link ProblemDescriptor} for image and directory files. This is
+ * A {@link com.intellij.codeInspection.ProblemDescriptor} for image and directory files. This is
* necessary because the {@link InspectionManager}'s createProblemDescriptor methods
- * all use {@link ProblemDescriptorBase} where in the constructor
+ * all use {@link com.intellij.codeInspection.ProblemDescriptorBase} where in the constructor
* it insists that the start and end {@link PsiElement} instances must have a valid
* text range, which does not apply for images.
*
diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintInspectionToolProvider.java b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintInspectionToolProvider.java
index 6ec61151641..12ae6e4de2e 100644
--- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintInspectionToolProvider.java
+++ b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintInspectionToolProvider.java
@@ -1,19 +1,3 @@
-/*
- * 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.android.inspections.klint;
import com.android.tools.klint.checks.*;
@@ -67,12 +51,6 @@ public class AndroidLintInspectionToolProvider {
}
}
- public static class AndroidKLintFullBackupContentInspection extends AndroidLintInspectionBase {
- public AndroidKLintFullBackupContentInspection() {
- super(AndroidBundle.message("android.lint.inspections.full.backup.content"), FullBackupContentDetector.ISSUE);
- }
- }
-
public static class AndroidKLintGetInstanceInspection extends AndroidLintInspectionBase {
public AndroidKLintGetInstanceInspection() {
super(AndroidBundle.message("android.lint.inspections.get.instance"), CipherGetInstanceDetector.ISSUE);
@@ -139,12 +117,6 @@ public class AndroidLintInspectionToolProvider {
}
}
- public static class AndroidKLintAppCompatResourceInspection extends AndroidLintInspectionBase {
- public AndroidKLintAppCompatResourceInspection() {
- super(AndroidBundle.message("android.lint.inspections.app.compat.resource"), AppCompatResourceDetector.ISSUE);
- }
- }
-
public static class AndroidKLintAssertInspection extends AndroidLintInspectionBase {
public AndroidKLintAssertInspection() {
super(AndroidBundle.message("android.lint.inspections.assert"), AssertDetector.ISSUE);
@@ -271,12 +243,6 @@ public class AndroidLintInspectionToolProvider {
}
}
- public static class AndroidKLintNfcTechWhitespaceInspection extends AndroidLintInspectionBase {
- public AndroidKLintNfcTechWhitespaceInspection() {
- super(AndroidBundle.message("android.lint.inspections.nfc.tech.whitespace"), NfcTechListDetector.ISSUE);
- }
- }
-
public static class AndroidKLintExportedServiceInspection extends AndroidLintInspectionBase {
public AndroidKLintExportedServiceInspection() {
super(AndroidBundle.message("android.lint.inspections.exported.service"), SecurityDetector.EXPORTED_SERVICE);
@@ -441,12 +407,6 @@ public class AndroidLintInspectionToolProvider {
}
}
- public static class AndroidKLintMenuTitleInspection extends AndroidLintInspectionBase {
- public AndroidKLintMenuTitleInspection() {
- super(AndroidBundle.message("android.lint.inspections.menu.title"), TitleDetector.ISSUE);
- }
- }
-
public static class AndroidKLintOverrideAbstractInspection extends AndroidLintInspectionBase {
public AndroidKLintOverrideAbstractInspection() {
super(AndroidBundle.message("android.lint.inspections.override.abstract"), OverrideConcreteDetector.ISSUE);
@@ -459,12 +419,6 @@ public class AndroidLintInspectionToolProvider {
}
}
- public static class AndroidKLintRegisteredInspection extends AndroidLintInspectionBase {
- public AndroidKLintRegisteredInspection() {
- super(AndroidBundle.message("android.lint.inspections.registered"), RegistrationDetector.ISSUE);
- }
- }
-
public static class AndroidKLintRequiredSizeInspection extends AndroidLintInspectionBase {
public AndroidKLintRequiredSizeInspection() {
super(AndroidBundle.message("android.lint.inspections.required.size"), RequiredAttributeDetector.ISSUE);
diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintQuickFix.java b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintQuickFix.java
index 29c44f17e74..d5690b77072 100644
--- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintQuickFix.java
+++ b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintQuickFix.java
@@ -1,32 +1,16 @@
-/*
- * 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.android.inspections.klint;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
public interface AndroidLintQuickFix {
- AndroidLintQuickFix[] EMPTY_ARRAY = new AndroidLintQuickFix[0];
+ AndroidLintQuickFix[] EMPTY_ARRAY = new AndroidLintQuickFix[0];
- void apply(@NotNull PsiElement startElement, @NotNull PsiElement endElement, @NotNull AndroidQuickfixContexts.Context context);
+ void apply(@NotNull PsiElement startElement, @NotNull PsiElement endElement, @NotNull AndroidQuickfixContexts.Context context);
- boolean isApplicable(@NotNull PsiElement startElement, @NotNull PsiElement endElement, @NotNull AndroidQuickfixContexts.ContextType contextType);
+ boolean isApplicable(@NotNull PsiElement startElement, @NotNull PsiElement endElement, @NotNull AndroidQuickfixContexts.ContextType contextType);
- @NotNull
- String getName();
+ @NotNull
+ String getName();
}
diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintUtil.java b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintUtil.java
index b95935ff428..4682520d9e7 100644
--- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintUtil.java
+++ b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintUtil.java
@@ -1,19 +1,3 @@
-/*
- * 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.android.inspections.klint;
import com.android.tools.klint.detector.api.Issue;
diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidModelFacade.kt b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidModelFacade.kt
index 7bf38c07e49..b397078d556 100644
--- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidModelFacade.kt
+++ b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidModelFacade.kt
@@ -1,35 +1,3 @@
-/*
- * 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.
- */
-
-/*
- * 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.android.inspections.klint
import com.android.builder.model.AndroidProject
diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidQuickfixContexts.java b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidQuickfixContexts.java
index c1e5827318a..a83fd52060a 100644
--- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidQuickfixContexts.java
+++ b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidQuickfixContexts.java
@@ -1,19 +1,3 @@
-/*
- * 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.android.inspections.klint;
import com.intellij.openapi.editor.Editor;
diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/DomPsiParser.java b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/DomPsiParser.java
index edbbe97d166..1c0ca05feec 100644
--- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/DomPsiParser.java
+++ b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/DomPsiParser.java
@@ -57,13 +57,13 @@ class DomPsiParser extends XmlParser {
@Override
public int getNodeStartOffset(@NonNull XmlContext context, @NonNull Node node) {
- TextRange textRange = org.jetbrains.android.inspections.klint.DomPsiConverter.getTextRange(node);
+ TextRange textRange = DomPsiConverter.getTextRange(node);
return textRange.getStartOffset();
}
@Override
public int getNodeEndOffset(@NonNull XmlContext context, @NonNull Node node) {
- TextRange textRange = org.jetbrains.android.inspections.klint.DomPsiConverter.getTextRange(node);
+ TextRange textRange = DomPsiConverter.getTextRange(node);
return textRange.getEndOffset();
}
@@ -92,7 +92,7 @@ class DomPsiParser extends XmlParser {
XmlFile xmlFile = (XmlFile)psiFile;
try {
- return org.jetbrains.android.inspections.klint.DomPsiConverter.convert(xmlFile);
+ return DomPsiConverter.convert(xmlFile);
} catch (Throwable t) {
myClient.log(t, "Failed converting PSI parse tree to DOM for file %1$s",
context.file.getPath());
@@ -103,7 +103,7 @@ class DomPsiParser extends XmlParser {
@NonNull
@Override
public Location getLocation(@NonNull XmlContext context, @NonNull Node node) {
- TextRange textRange = org.jetbrains.android.inspections.klint.DomPsiConverter.getTextRange(node);
+ TextRange textRange = DomPsiConverter.getTextRange(node);
Position start = new DefaultPosition(-1, -1, textRange.getStartOffset());
Position end = new DefaultPosition(-1, -1, textRange.getEndOffset());
return Location.create(context.file, start, end);
@@ -112,7 +112,7 @@ class DomPsiParser extends XmlParser {
@NonNull
@Override
public Location getLocation(@NonNull XmlContext context, @NonNull Node node, int startDelta, int endDelta) {
- TextRange textRange = org.jetbrains.android.inspections.klint.DomPsiConverter.getTextRange(node);
+ TextRange textRange = DomPsiConverter.getTextRange(node);
Position start = new DefaultPosition(-1, -1, textRange.getStartOffset() + startDelta);
Position end = new DefaultPosition(-1, -1, textRange.getStartOffset() + endDelta);
return Location.create(context.file, start, end);
@@ -121,7 +121,7 @@ class DomPsiParser extends XmlParser {
@NonNull
@Override
public Location getNameLocation(@NonNull XmlContext context, @NonNull Node node) {
- TextRange textRange = org.jetbrains.android.inspections.klint.DomPsiConverter.getTextNameRange(node);
+ TextRange textRange = DomPsiConverter.getTextNameRange(node);
Position start = new DefaultPosition(-1, -1, textRange.getStartOffset());
Position end = new DefaultPosition(-1, -1, textRange.getEndOffset());
return Location.create(context.file, start, end);
@@ -130,7 +130,7 @@ class DomPsiParser extends XmlParser {
@NonNull
@Override
public Location getValueLocation(@NonNull XmlContext context, @NonNull Attr node) {
- TextRange textRange = org.jetbrains.android.inspections.klint.DomPsiConverter.getTextValueRange(node);
+ TextRange textRange = DomPsiConverter.getTextValueRange(node);
Position start = new DefaultPosition(-1, -1, textRange.getStartOffset());
Position end = new DefaultPosition(-1, -1, textRange.getEndOffset());
return Location.create(context.file, start, end);
@@ -163,7 +163,7 @@ class DomPsiParser extends XmlParser {
}
});
}
- TextRange textRange = org.jetbrains.android.inspections.klint.DomPsiConverter.getTextRange(myNode);
+ TextRange textRange = DomPsiConverter.getTextRange(myNode);
Position start = new DefaultPosition(-1, -1, textRange.getStartOffset());
Position end = new DefaultPosition(-1, -1, textRange.getEndOffset());
return Location.create(myFile, start, end);
diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintClient.java b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintClient.java
index c211eb38b80..e27d8260e5a 100644
--- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintClient.java
+++ b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintClient.java
@@ -1,19 +1,3 @@
-/*
- * 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.android.inspections.klint;
import com.android.annotations.NonNull;
@@ -30,6 +14,13 @@ import com.android.tools.idea.rendering.LocalResourceRepository;
import com.android.tools.idea.sdk.IdeSdks;
import com.android.tools.klint.client.api.*;
import com.android.tools.klint.checks.ApiLookup;
+import com.android.tools.klint.detector.api.Context;
+import com.android.tools.klint.detector.api.DefaultPosition;
+import com.android.tools.klint.detector.api.Issue;
+import com.android.tools.klint.detector.api.Location;
+import com.android.tools.klint.detector.api.Position;
+import com.android.tools.klint.detector.api.Severity;
+import com.android.tools.klint.detector.api.TextFormat;
import com.intellij.analysis.AnalysisScope;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
@@ -77,10 +68,10 @@ import java.util.Map;
import static com.android.tools.klint.detector.api.TextFormat.RAW;
/**
- * Implementation of the {@linkplain com.android.tools.klint.client.api.LintClient} API for executing lint within the IDE:
+ * Implementation of the {@linkplain LintClient} API for executing lint within the IDE:
* reading files, reporting issues, logging errors, etc.
*/
-public class IntellijLintClient extends com.android.tools.klint.client.api.LintClient implements Disposable {
+public class IntellijLintClient extends LintClient implements Disposable {
protected static final Logger LOG = Logger.getInstance("#org.jetbrains.android.inspections.IntellijLintClient");
@NonNull protected Project myProject;
@@ -96,9 +87,9 @@ public class IntellijLintClient extends com.android.tools.klint.client.api.LintC
/** Creates a lint client for batch inspections */
public static IntellijLintClient forBatch(@NotNull Project project,
- @NotNull Map>> problemMap,
+ @NotNull Map>> problemMap,
@NotNull AnalysisScope scope,
- @NotNull List issues) {
+ @NotNull List issues) {
return new BatchLintClient(project, problemMap, scope, issues);
}
@@ -139,7 +130,7 @@ public class IntellijLintClient extends com.android.tools.klint.client.api.LintC
}
@Override
- public com.android.tools.klint.client.api.Configuration getConfiguration(@NonNull com.android.tools.klint.detector.api.Project project) {
+ public Configuration getConfiguration(@NonNull com.android.tools.klint.detector.api.Project project) {
if (project.isGradleProject() && project.isAndroidProject() && !project.isLibrary()) {
AndroidProject model = project.getGradleProjectModel();
if (model != null) {
@@ -147,30 +138,30 @@ public class IntellijLintClient extends com.android.tools.klint.client.api.LintC
LintOptions lintOptions = model.getLintOptions();
final Map overrides = lintOptions.getSeverityOverrides();
if (overrides != null && !overrides.isEmpty()) {
- return new com.android.tools.klint.client.api.DefaultConfiguration(this, project, null) {
+ return new DefaultConfiguration(this, project, null) {
@NonNull
@Override
- public com.android.tools.klint.detector.api.Severity getSeverity(@NonNull com.android.tools.klint.detector.api.Issue issue) {
+ public Severity getSeverity(@NonNull Issue issue) {
Integer severity = overrides.get(issue.getId());
if (severity != null) {
switch (severity.intValue()) {
case LintOptions.SEVERITY_FATAL:
- return com.android.tools.klint.detector.api.Severity.FATAL;
+ return Severity.FATAL;
case LintOptions.SEVERITY_ERROR:
- return com.android.tools.klint.detector.api.Severity.ERROR;
+ return Severity.ERROR;
case LintOptions.SEVERITY_WARNING:
- return com.android.tools.klint.detector.api.Severity.WARNING;
+ return Severity.WARNING;
case LintOptions.SEVERITY_INFORMATIONAL:
- return com.android.tools.klint.detector.api.Severity.INFORMATIONAL;
+ return Severity.INFORMATIONAL;
case LintOptions.SEVERITY_IGNORE:
default:
- return com.android.tools.klint.detector.api.Severity.IGNORE;
+ return Severity.IGNORE;
}
}
// This is a LIST lookup. I should make this faster!
if (!getIssues().contains(issue)) {
- return com.android.tools.klint.detector.api.Severity.IGNORE;
+ return Severity.IGNORE;
}
return super.getSeverity(issue);
@@ -182,25 +173,25 @@ public class IntellijLintClient extends com.android.tools.klint.client.api.LintC
}
}
}
- return new com.android.tools.klint.client.api.DefaultConfiguration(this, project, null) {
+ return new DefaultConfiguration(this, project, null) {
@Override
- public boolean isEnabled(@NonNull com.android.tools.klint.detector.api.Issue issue) {
+ public boolean isEnabled(@NonNull Issue issue) {
return getIssues().contains(issue) && super.isEnabled(issue);
}
};
}
@Override
- public void report(@NonNull com.android.tools.klint.detector.api.Context context,
- @NonNull com.android.tools.klint.detector.api.Issue issue,
- @NonNull com.android.tools.klint.detector.api.Severity severity,
- @Nullable com.android.tools.klint.detector.api.Location location,
+ public void report(@NonNull Context context,
+ @NonNull Issue issue,
+ @NonNull Severity severity,
+ @Nullable Location location,
@NonNull String message,
- @NonNull com.android.tools.klint.detector.api.TextFormat format) {
+ @NonNull TextFormat format) {
assert false : message;
}
- @NonNull protected List getIssues() {
+ @NonNull protected List getIssues() {
return Collections.emptyList();
}
@@ -214,9 +205,9 @@ public class IntellijLintClient extends com.android.tools.klint.client.api.LintC
* linked location, and so on.This is necessary since IntelliJ problems don't have secondary locations; instead, we create one
* problem for each location associated with the lint error.
*/
- protected void reportSecondary(@NonNull com.android.tools.klint.detector.api.Context context, @NonNull com.android.tools.klint.detector.api.Issue issue, @NonNull com.android.tools.klint.detector.api.Severity severity, @NonNull com.android.tools.klint.detector.api.Location location,
- @NonNull String message, @NonNull com.android.tools.klint.detector.api.TextFormat format) {
- com.android.tools.klint.detector.api.Location secondary = location.getSecondary();
+ protected void reportSecondary(@NonNull Context context, @NonNull Issue issue, @NonNull Severity severity, @NonNull Location location,
+ @NonNull String message, @NonNull TextFormat format) {
+ Location secondary = location.getSecondary();
if (secondary != null) {
if (secondary.getMessage() != null) {
message = message + " (" + secondary.getMessage() + ")";
@@ -226,14 +217,14 @@ public class IntellijLintClient extends com.android.tools.klint.client.api.LintC
}
@Override
- public void log(@NonNull com.android.tools.klint.detector.api.Severity severity, @Nullable Throwable exception, @Nullable String format, @Nullable Object... args) {
- if (severity == com.android.tools.klint.detector.api.Severity.ERROR || severity == com.android.tools.klint.detector.api.Severity.FATAL) {
+ public void log(@NonNull Severity severity, @Nullable Throwable exception, @Nullable String format, @Nullable Object... args) {
+ if (severity == Severity.ERROR || severity == Severity.FATAL) {
if (format != null) {
LOG.error(String.format(format, args), exception);
} else if (exception != null) {
LOG.error(exception);
}
- } else if (severity == com.android.tools.klint.detector.api.Severity.WARNING) {
+ } else if (severity == Severity.WARNING) {
if (format != null) {
LOG.warn(String.format(format, args), exception);
} else if (exception != null) {
@@ -249,7 +240,7 @@ public class IntellijLintClient extends com.android.tools.klint.client.api.LintC
}
@Override
- public com.android.tools.klint.client.api.XmlParser getXmlParser() {
+ public XmlParser getXmlParser() {
return new DomPsiParser(this);
}
@@ -453,35 +444,35 @@ public class IntellijLintClient extends com.android.tools.klint.client.api.LintC
@NonNull
@Override
- protected List getIssues() {
+ protected List getIssues() {
return myState.getIssues();
}
@Override
- public void report(@NonNull com.android.tools.klint.detector.api.Context context,
- @NonNull com.android.tools.klint.detector.api.Issue issue,
- @NonNull com.android.tools.klint.detector.api.Severity severity,
- @Nullable com.android.tools.klint.detector.api.Location location,
+ public void report(@NonNull Context context,
+ @NonNull Issue issue,
+ @NonNull Severity severity,
+ @Nullable Location location,
@NonNull String message,
- @NonNull com.android.tools.klint.detector.api.TextFormat format) {
+ @NonNull TextFormat format) {
if (location != null) {
final File file = location.getFile();
final VirtualFile vFile = LocalFileSystem.getInstance().findFileByIoFile(file);
if (myState.getMainFile().equals(vFile)) {
- final com.android.tools.klint.detector.api.Position start = location.getStart();
- final com.android.tools.klint.detector.api.Position end = location.getEnd();
+ final Position start = location.getStart();
+ final Position end = location.getEnd();
final TextRange textRange = start != null && end != null && start.getOffset() <= end.getOffset()
? new TextRange(start.getOffset(), end.getOffset())
: TextRange.EMPTY_RANGE;
- com.android.tools.klint.detector.api.Severity configuredSeverity = severity != issue.getDefaultSeverity() ? severity : null;
+ Severity configuredSeverity = severity != issue.getDefaultSeverity() ? severity : null;
message = format.convertTo(message, RAW);
- myState.getProblems().add(new org.jetbrains.android.inspections.klint.ProblemData(issue, message, textRange, configuredSeverity));
+ myState.getProblems().add(new ProblemData(issue, message, textRange, configuredSeverity));
}
- com.android.tools.klint.detector.api.Location secondary = location.getSecondary();
+ Location secondary = location.getSecondary();
if (secondary != null && myState.getMainFile().equals(LocalFileSystem.getInstance().findFileByIoFile(secondary.getFile()))) {
reportSecondary(context, issue, severity, location, message, format);
}
@@ -560,7 +551,7 @@ public class IntellijLintClient extends com.android.tools.klint.client.api.LintC
public List getResourceFolders(@NonNull com.android.tools.klint.detector.api.Project project) {
AndroidFacet facet = AndroidFacet.getInstance(myState.getModule());
if (facet != null) {
- return org.jetbrains.android.inspections.klint.IntellijLintUtils.getResourceDirectories(facet);
+ return IntellijLintUtils.getResourceDirectories(facet);
}
return super.getResourceFolders(project);
}
@@ -568,14 +559,14 @@ public class IntellijLintClient extends com.android.tools.klint.client.api.LintC
/** Lint client used for batch operations */
private static class BatchLintClient extends IntellijLintClient {
- private final Map>> myProblemMap;
+ private final Map>> myProblemMap;
private final AnalysisScope myScope;
- private final List myIssues;
+ private final List myIssues;
public BatchLintClient(@NotNull Project project,
- @NotNull Map>> problemMap,
+ @NotNull Map>> problemMap,
@NotNull AnalysisScope scope,
- @NotNull List issues) {
+ @NotNull List issues) {
super(project);
myProblemMap = problemMap;
myScope = scope;
@@ -591,17 +582,17 @@ public class IntellijLintClient extends com.android.tools.klint.client.api.LintC
@NonNull
@Override
- protected List getIssues() {
+ protected List getIssues() {
return myIssues;
}
@Override
- public void report(@NonNull com.android.tools.klint.detector.api.Context context,
- @NonNull com.android.tools.klint.detector.api.Issue issue,
- @NonNull com.android.tools.klint.detector.api.Severity severity,
- @Nullable com.android.tools.klint.detector.api.Location location,
+ public void report(@NonNull Context context,
+ @NonNull Issue issue,
+ @NonNull Severity severity,
+ @Nullable Location location,
@NonNull String message,
- @NonNull com.android.tools.klint.detector.api.TextFormat format) {
+ @NonNull TextFormat format) {
VirtualFile vFile = null;
File file = null;
@@ -642,31 +633,31 @@ public class IntellijLintClient extends com.android.tools.klint.client.api.LintC
if (inScope) {
file = new File(PathUtil.getCanonicalPath(file.getPath()));
- Map> file2ProblemList = myProblemMap.get(issue);
+ Map> file2ProblemList = myProblemMap.get(issue);
if (file2ProblemList == null) {
- file2ProblemList = new HashMap>();
+ file2ProblemList = new HashMap>();
myProblemMap.put(issue, file2ProblemList);
}
- List problemList = file2ProblemList.get(file);
+ List problemList = file2ProblemList.get(file);
if (problemList == null) {
- problemList = new ArrayList();
+ problemList = new ArrayList();
file2ProblemList.put(file, problemList);
}
TextRange textRange = TextRange.EMPTY_RANGE;
if (location != null) {
- final com.android.tools.klint.detector.api.Position start = location.getStart();
- final com.android.tools.klint.detector.api.Position end = location.getEnd();
+ final Position start = location.getStart();
+ final Position end = location.getEnd();
if (start != null && end != null && start.getOffset() <= end.getOffset()) {
textRange = new TextRange(start.getOffset(), end.getOffset());
}
}
- com.android.tools.klint.detector.api.Severity configuredSeverity = severity != issue.getDefaultSeverity() ? severity : null;
+ Severity configuredSeverity = severity != issue.getDefaultSeverity() ? severity : null;
message = format.convertTo(message, RAW);
- problemList.add(new org.jetbrains.android.inspections.klint.ProblemData(issue, message, textRange, configuredSeverity));
+ problemList.add(new ProblemData(issue, message, textRange, configuredSeverity));
if (location != null && location.getSecondary() != null) {
reportSecondary(context, issue, severity, location, message, format);
@@ -697,7 +688,7 @@ public class IntellijLintClient extends com.android.tools.klint.client.api.LintC
if (module != null) {
AndroidFacet facet = AndroidFacet.getInstance(module);
if (facet != null) {
- return org.jetbrains.android.inspections.klint.IntellijLintUtils.getResourceDirectories(facet);
+ return IntellijLintUtils.getResourceDirectories(facet);
}
}
return super.getResourceFolders(project);
@@ -736,7 +727,7 @@ public class IntellijLintClient extends com.android.tools.klint.client.api.LintC
@NonNull
@Override
- public com.android.tools.klint.detector.api.Location.Handle createResourceItemHandle(@NonNull ResourceItem item) {
+ public Location.Handle createResourceItemHandle(@NonNull ResourceItem item) {
XmlTag tag = LocalResourceRepository.getItemTag(myProject, item);
if (tag != null) {
ResourceFile source = item.getSource();
@@ -762,7 +753,7 @@ public class IntellijLintClient extends com.android.tools.klint.client.api.LintC
return super.getResourceVisibilityProvider();
}
- private static class LocationHandle implements com.android.tools.klint.detector.api.Location.Handle, Computable {
+ private static class LocationHandle implements Location.Handle, Computable {
private final File myFile;
private final XmlElement myNode;
private Object myClientData;
@@ -774,7 +765,7 @@ public class IntellijLintClient extends com.android.tools.klint.client.api.LintC
@NonNull
@Override
- public com.android.tools.klint.detector.api.Location resolve() {
+ public Location resolve() {
if (!ApplicationManager.getApplication().isReadAccessAllowed()) {
return ApplicationManager.getApplication().runReadAction(this);
}
@@ -791,13 +782,13 @@ public class IntellijLintClient extends com.android.tools.klint.client.api.LintC
}
}
- com.android.tools.klint.detector.api.Position start = new com.android.tools.klint.detector.api.DefaultPosition(-1, -1, textRange.getStartOffset());
- com.android.tools.klint.detector.api.Position end = new com.android.tools.klint.detector.api.DefaultPosition(-1, -1, textRange.getEndOffset());
- return com.android.tools.klint.detector.api.Location.create(myFile, start, end);
+ Position start = new DefaultPosition(-1, -1, textRange.getStartOffset());
+ Position end = new DefaultPosition(-1, -1, textRange.getEndOffset());
+ return Location.create(myFile, start, end);
}
@Override
- public com.android.tools.klint.detector.api.Location compute() {
+ public Location compute() {
return resolve();
}
diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintIssueRegistry.java b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintIssueRegistry.java
index 943ce94b445..0f415867b71 100644
--- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintIssueRegistry.java
+++ b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintIssueRegistry.java
@@ -49,16 +49,12 @@ public class IntellijLintIssueRegistry extends BuiltinIssueRegistry {
Implementation implementation = issue.getImplementation();
EnumSet scope = implementation.getScope();
Class extends Detector> detectorClass = implementation.getDetectorClass();
- if (detectorClass == RegistrationDetector.class) {
- issue.setImplementation(IntellijRegistrationDetector.IMPLEMENTATION);
- } else if (detectorClass == ViewTypeDetector.class) {
- issue.setImplementation(IntellijViewTypeDetector.IMPLEMENTATION);
- } else if (detectorClass == SupportAnnotationDetector.class) {
+ if (detectorClass == SupportAnnotationDetector.class) {
// Handled by the ResourceTypeInspection
continue;
} else if (scope.contains(Scope.CLASS_FILE) ||
- scope.contains(Scope.ALL_CLASS_FILES) ||
- scope.contains(Scope.JAVA_LIBRARIES)) {
+ scope.contains(Scope.ALL_CLASS_FILES) ||
+ scope.contains(Scope.JAVA_LIBRARIES)) {
//noinspection ConstantConditions
assert !IntellijLintProject.SUPPORT_CLASS_FILES; // When enabled, adjust this to include class detector based issues
diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintRequest.java b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintRequest.java
index 859e7f97f99..497db06767d 100644
--- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintRequest.java
+++ b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintRequest.java
@@ -73,8 +73,8 @@ public class IntellijLintRequest extends LintRequest {
mScope = Scope.infer(projects);
//noinspection ConstantConditions
- if (!org.jetbrains.android.inspections.klint.IntellijLintProject.SUPPORT_CLASS_FILES && (mScope.contains(Scope.CLASS_FILE) || mScope.contains(Scope.ALL_CLASS_FILES)
- || mScope.contains(Scope.JAVA_LIBRARIES))) {
+ if (!IntellijLintProject.SUPPORT_CLASS_FILES && (mScope.contains(Scope.CLASS_FILE) || mScope.contains(Scope.ALL_CLASS_FILES)
+ || mScope.contains(Scope.JAVA_LIBRARIES))) {
mScope = EnumSet.copyOf(mScope); // make mutable
// Can't run class file based checks
mScope.remove(Scope.CLASS_FILE);
@@ -93,7 +93,7 @@ public class IntellijLintRequest extends LintRequest {
if (mProjects == null) {
if (myIncremental && myFileList != null && myFileList.size() == 1 && myModules.size() == 1) {
Pair pair =
- org.jetbrains.android.inspections.klint.IntellijLintProject.createForSingleFile(mLintClient, myFileList.get(0), myModules.get(0));
+ IntellijLintProject.createForSingleFile(mLintClient, myFileList.get(0), myModules.get(0));
mProjects = pair.first != null ? Collections.singletonList(pair.first)
: Collections.emptyList();
myMainProject = pair.second;
@@ -102,7 +102,7 @@ public class IntellijLintRequest extends LintRequest {
// and add projects for the gradle libraries and set error reporting to
// false on those
//mProjects = computeProjects()
- mProjects = org.jetbrains.android.inspections.klint.IntellijLintProject.create(mLintClient, myFileList, myModules.toArray(new Module[myModules.size()]));
+ mProjects = IntellijLintProject.create(mLintClient, myFileList, myModules.toArray(new Module[myModules.size()]));
} else {
mProjects = super.getProjects();
}
diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintUtils.java b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintUtils.java
index 896764b2a31..bdcf145c93d 100644
--- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintUtils.java
+++ b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintUtils.java
@@ -20,6 +20,12 @@ import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.builder.model.SourceProvider;
import com.android.tools.klint.client.api.LintRequest;
+import com.android.tools.klint.detector.api.ClassContext;
+import com.android.tools.klint.detector.api.Context;
+import com.android.tools.klint.detector.api.DefaultPosition;
+import com.android.tools.klint.detector.api.Issue;
+import com.android.tools.klint.detector.api.Location;
+import com.android.tools.klint.detector.api.Position;
import com.google.common.base.Splitter;
import com.intellij.debugger.engine.JVMNameUtil;
import com.intellij.facet.Facet;
@@ -36,9 +42,7 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.util.ClassUtil;
import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.psi.util.TypeConversionUtil;
import org.jetbrains.android.facet.AndroidFacet;
-import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.uast.UClass;
import org.jetbrains.uast.UElement;
@@ -49,9 +53,6 @@ import java.io.File;
import java.util.ArrayList;
import java.util.List;
-import static com.android.SdkConstants.CONSTRUCTOR_NAME;
-import static com.android.SdkConstants.SUPPRESS_ALL;
-
/**
* Common utilities for handling lint within IntelliJ
* TODO: Merge with {@link AndroidLintUtil}
@@ -60,11 +61,6 @@ public class IntellijLintUtils {
private IntellijLintUtils() {
}
- @NonNls
- public static final String SUPPRESS_LINT_FQCN = "android.annotation.SuppressLint";
- @NonNls
- public static final String SUPPRESS_WARNINGS_FQCN = "java.lang.SuppressWarnings";
-
private static final ProjectSystemId GRADLE_ID = new ProjectSystemId("GRADLE");
/**
@@ -75,7 +71,7 @@ public class IntellijLintUtils {
* @return the location of the given element
*/
@NonNull
- public static com.android.tools.klint.detector.api.Location getLocation(@NonNull File file, @NonNull PsiElement element) {
+ public static Location getLocation(@NonNull File file, @NonNull PsiElement element) {
//noinspection ConstantConditions
assert element.getContainingFile().getVirtualFile() == null
|| FileUtil.filesEqual(VfsUtilCore.virtualToIoFile(element.getContainingFile().getVirtualFile()), file);
@@ -90,19 +86,19 @@ public class IntellijLintUtils {
}
TextRange textRange = element.getTextRange();
- com.android.tools.klint.detector.api.Position start = new com.android.tools.klint.detector.api.DefaultPosition(-1, -1, textRange.getStartOffset());
- com.android.tools.klint.detector.api.Position end = new com.android.tools.klint.detector.api.DefaultPosition(-1, -1, textRange.getEndOffset());
- return com.android.tools.klint.detector.api.Location.create(file, start, end);
+ Position start = new DefaultPosition(-1, -1, textRange.getStartOffset());
+ Position end = new DefaultPosition(-1, -1, textRange.getEndOffset());
+ return Location.create(file, start, end);
}
/**
- * Returns the {@link PsiFile} associated with a given lint {@link com.android.tools.klint.detector.api.Context}
+ * Returns the {@link PsiFile} associated with a given lint {@link Context}
*
* @param context the context to look up the file for
* @return the corresponding {@link PsiFile}, or null
*/
@Nullable
- public static PsiFile getPsiFile(@NonNull com.android.tools.klint.detector.api.Context context) {
+ public static PsiFile getPsiFile(@NonNull Context context) {
VirtualFile file = VfsUtil.findFileByIoFile(context.file, false);
if (file == null) {
return null;
@@ -115,106 +111,17 @@ public class IntellijLintUtils {
return PsiManager.getInstance(project).findFile(file);
}
- public static boolean isSuppressed(@NonNull UElement element, @NonNull UFile file, @NonNull com.android.tools.klint.detector.api.Issue issue) {
- //TODO
- return true;
- }
-
- /**
- * Returns true if the given issue is suppressed at the given element within the given file
- *
- * @param element the element to check
- * @param file the file containing the element
- * @param issue the issue to check
- * @return true if the given issue is suppressed
- */
- public static boolean isSuppressed(@NonNull PsiElement element, @NonNull PsiFile file, @NonNull com.android.tools.klint.detector.api.Issue issue) {
- // Search upwards for suppress lint and suppress warnings annotations
- // Search upwards for target api annotations
- while (element != null && element != file) { // otherwise it will keep going into directories!
- if (element instanceof PsiModifierListOwner) {
- PsiModifierListOwner owner = (PsiModifierListOwner)element;
- PsiModifierList modifierList = owner.getModifierList();
- if (modifierList != null) {
- for (PsiAnnotation annotation : modifierList.getAnnotations()) {
- String fqcn = annotation.getQualifiedName();
- if (fqcn.equals(SUPPRESS_LINT_FQCN) || fqcn.equals(SUPPRESS_WARNINGS_FQCN)) {
- PsiAnnotationParameterList parameterList = annotation.getParameterList();
- for (PsiNameValuePair pair : parameterList.getAttributes()) {
- PsiAnnotationMemberValue v = pair.getValue();
- String text = v.getText().trim(); // UGH! Find better way to access value!
- if (text.isEmpty()) {
- continue;
- }
- if (v instanceof PsiLiteral) {
- PsiLiteral literal = (PsiLiteral)v;
- Object value = literal.getValue();
- if (value instanceof String) {
- text = (String) value;
- }
- } else if (v instanceof PsiArrayInitializerMemberValue) {
- PsiArrayInitializerMemberValue mv = (PsiArrayInitializerMemberValue)v;
- for (PsiAnnotationMemberValue mmv : mv.getInitializers()) {
- if (mmv instanceof PsiLiteral) {
- PsiLiteral literal = (PsiLiteral) mmv;
- Object value = literal.getValue();
- if (value instanceof String) {
- text = (String) value;
- break;
- }
- }
- }
- }
-
- if (text != null) {
- for (String id : Splitter.on(',').trimResults().split(text)) {
- if (id.equals(issue.getId()) || id.equals(SUPPRESS_ALL)) {
- return true;
- }
- }
- }
- }
- }
- }
- }
- }
- element = element.getParent();
- }
-
+ public static boolean isSuppressed(@NonNull UElement element, @NonNull UFile file, @NonNull Issue issue) {
return false;
}
- /** Returns the internal method name */
- @NonNull
- public static String getInternalMethodName(@NonNull PsiMethod method) {
- if (method.isConstructor()) {
- return SdkConstants.CONSTRUCTOR_NAME;
- }
- else {
- return method.getName();
- }
- }
-
- @Nullable
- public static PsiElement getCallName(@NonNull PsiCallExpression expression) {
- PsiElement firstChild = expression.getFirstChild();
- if (firstChild != null) {
- PsiElement lastChild = firstChild.getLastChild();
- if (lastChild instanceof PsiIdentifier) {
- return lastChild;
- }
- }
- return null;
- }
-
-
/**
* Computes the internal class name of the given class.
* For example, for PsiClass foo.bar.Foo.Bar it returns foo/bar/Foo$Bar.
*
* @param psiClass the class to look up the internal name for
* @return the internal class name
- * @see com.android.tools.klint.detector.api.ClassContext#getInternalName(String)
+ * @see ClassContext#getInternalName(String)
*/
@Nullable
public static String getInternalName(@NonNull PsiClass psiClass) {
@@ -232,13 +139,13 @@ public class IntellijLintUtils {
if (sig == null) {
String qualifiedName = psiClass.getQualifiedName();
if (qualifiedName != null) {
- return com.android.tools.klint.detector.api.ClassContext.getInternalName(qualifiedName);
+ return ClassContext.getInternalName(qualifiedName);
}
return null;
} else if (sig.indexOf('.') != -1) {
// Workaround -- ClassUtil doesn't treat this correctly!
// .replace('.', '/');
- sig = com.android.tools.klint.detector.api.ClassContext.getInternalName(sig);
+ sig = ClassContext.getInternalName(sig);
}
return sig;
}
@@ -251,134 +158,6 @@ public class IntellijLintUtils {
}
}
- /**
- * Computes the internal class name of the given class type.
- * For example, for PsiClassType foo.bar.Foo.Bar it returns foo/bar/Foo$Bar.
- *
- * @param psiClassType the class type to look up the internal name for
- * @return the internal class name
- * @see com.android.tools.klint.detector.api.ClassContext#getInternalName(String)
- */
- @Nullable
- public static String getInternalName(@NonNull PsiClassType psiClassType) {
- PsiClass resolved = psiClassType.resolve();
- if (resolved != null) {
- return getInternalName(resolved);
- }
-
- String className = psiClassType.getClassName();
- if (className != null) {
- return com.android.tools.klint.detector.api.ClassContext.getInternalName(className);
- }
-
- return null;
- }
-
- /**
- * Computes the internal JVM description of the given method. This is in the same
- * format as the ASM desc fields for methods; meaning that a method named foo which for example takes an
- * int and a String and returns a void will have description {@code foo(ILjava/lang/String;):V}.
- *
- * @param method the method to look up the description for
- * @param includeName whether the name should be included
- * @param includeReturn whether the return type should be included
- * @return the internal JVM description for this method
- */
- @Nullable
- public static String getInternalDescription(@NonNull PsiMethod method, boolean includeName, boolean includeReturn) {
- assert !includeName; // not yet tested
- assert !includeReturn; // not yet tested
-
- StringBuilder signature = new StringBuilder();
-
- if (includeName) {
- if (method.isConstructor()) {
- final PsiClass declaringClass = method.getContainingClass();
- if (declaringClass != null) {
- final PsiClass outerClass = declaringClass.getContainingClass();
- if (outerClass != null) {
- // declaring class is an inner class
- if (!declaringClass.hasModifierProperty(PsiModifier.STATIC)) {
- if (!appendJvmTypeName(signature, outerClass)) {
- return null;
- }
- }
- }
- }
- signature.append(CONSTRUCTOR_NAME);
- } else {
- signature.append(method.getName());
- }
- }
-
- signature.append('(');
-
- for (PsiParameter psiParameter : method.getParameterList().getParameters()) {
- if (!appendJvmSignature(signature, psiParameter.getType())) {
- return null;
- }
- }
- signature.append(')');
- if (includeReturn) {
- if (!method.isConstructor()) {
- if (!appendJvmSignature(signature, method.getReturnType())) {
- return null;
- }
- }
- else {
- signature.append('V');
- }
- }
- return signature.toString();
- }
-
- private static boolean appendJvmTypeName(@NonNull StringBuilder signature, @NonNull PsiClass outerClass) {
- String className = getInternalName(outerClass);
- if (className == null) {
- return false;
- }
- signature.append('L').append(className.replace('.', '/')).append(';');
- return true;
- }
-
- private static boolean appendJvmSignature(@NonNull StringBuilder buffer, @Nullable PsiType type) {
- if (type == null) {
- return false;
- }
- final PsiType psiType = TypeConversionUtil.erasure(type);
- if (psiType instanceof PsiArrayType) {
- buffer.append('[');
- appendJvmSignature(buffer, ((PsiArrayType)psiType).getComponentType());
- }
- else if (psiType instanceof PsiClassType) {
- PsiClass resolved = ((PsiClassType)psiType).resolve();
- if (resolved == null) {
- return false;
- }
- if (!appendJvmTypeName(buffer, resolved)) {
- return false;
- }
- }
- else if (psiType instanceof PsiPrimitiveType) {
- buffer.append(JVMNameUtil.getPrimitiveSignature(psiType.getCanonicalText()));
- }
- else {
- return false;
- }
- return true;
- }
-
- public static boolean isProjectReady(AndroidFacet facet) {
- try {
- return AndroidFacet.class.getMethod("getIdeaAndroidProject", AndroidFacet.class).invoke(facet) != null;
- } catch (Exception e) {
- try {
- return AndroidFacet.class.getMethod("getAndroidModel", AndroidFacet.class).invoke(facet) != null;
- } catch (Exception ignored) {}
- }
- return false;
- }
-
public static AndroidModelFacade getModelFacade(AndroidFacet facet) {
return new AndroidModelFacade(facet);
}
diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijRegistrationDetector.java b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijRegistrationDetector.java
deleted file mode 100644
index b82edc0173e..00000000000
--- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijRegistrationDetector.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * 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.android.inspections.klint;
-
-import com.android.tools.klint.checks.RegistrationDetector;
-import com.android.tools.klint.detector.api.ClassContext;
-import com.android.tools.klint.detector.api.Implementation;
-import com.android.tools.klint.detector.api.Location;
-import com.android.tools.klint.detector.api.Scope;
-import com.intellij.openapi.application.ApplicationManager;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.uast.UClass;
-import org.jetbrains.uast.UFile;
-import org.jetbrains.uast.UastModifier;
-import org.jetbrains.uast.UastUtils;
-import org.jetbrains.uast.check.UastAndroidContext;
-import org.jetbrains.uast.check.UastAndroidUtils;
-import org.jetbrains.uast.check.UastScanner;
-import org.jetbrains.uast.kinds.UastClassKind;
-import org.jetbrains.uast.visitor.UastVisitor;
-
-import java.util.Collection;
-import java.util.EnumSet;
-
-import static com.android.SdkConstants.*;
-
-/**
- * Intellij-specific version of the {@link RegistrationDetector} which uses the PSI structure
- * to check classes.
- *
- *
- * - Unit tests, and compare to the bytecode based results
- *
- */
-public class IntellijRegistrationDetector extends RegistrationDetector implements UastScanner {
- static final Implementation IMPLEMENTATION = new Implementation(
- IntellijRegistrationDetector.class,
- EnumSet.of(Scope.MANIFEST, Scope.SOURCE_FILE));
-
- @Override
- public UastVisitor createUastVisitor(final UastAndroidContext context) {
- return new UastVisitor() {
- @Override
- public boolean visitFile(@NotNull UFile file) {
- check(context, file);
- return true;
- }
- };
- }
-
- private void check(final UastAndroidContext context, final UFile file) {
- ApplicationManager.getApplication().runReadAction(new Runnable() {
- @Override
- public void run() {
- for (UClass clz : file.getClasses()) {
- check(context, clz);
- }
- }
- });
- }
-
- private void check(UastAndroidContext context, UClass clz) {
- for (UClass current = clz.getSuperClass(context); current != null; current = current.getSuperClass(context)) {
- // Ignore abstract classes
- if (clz.hasModifier(UastModifier.ABSTRACT) || clz.getKind() != UastClassKind.CLASS) {
- continue;
- }
- String fqcn = current.getFqName();
- if (fqcn == null) {
- continue;
- }
- if (CLASS_ACTIVITY.equals(fqcn)
- || CLASS_SERVICE.equals(fqcn)
- || CLASS_CONTENTPROVIDER.equals(fqcn)) {
-
- String internalName = clz.getInternalName();
- if (internalName == null) {
- internalName = IntellijLintUtils.getInternalName(clz);
- }
- if (internalName == null) {
- continue;
- }
- String frameworkClass = ClassContext.getInternalName(fqcn);
- Collection registered = mManifestRegistrations != null ? mManifestRegistrations.get(frameworkClass) : null;
- if (registered == null || !registered.contains(internalName)) {
- report(context, clz, frameworkClass);
- }
- break;
- }
- }
-
- for (UClass innerClass : clz.getNestedClasses()) {
- check(context, innerClass);
- }
- }
-
- private static void report(UastAndroidContext context, UClass clz, String internalName) {
- // Unlike the superclass, we don't have to check that the tags are compatible;
- // IDEA already checks that as part of its XML validation
-
- if (IntellijLintUtils.isSuppressed(clz, UastUtils.getContainingFile(clz), ISSUE)) {
- return;
- }
- String tag = classToTag(internalName);
- Location location = UastAndroidUtils.getLocation(clz);
- String fqcn = clz.getFqName();
- if (fqcn == null) {
- fqcn = clz.getName();
- }
- context.report(ISSUE, clz, location, String.format("The <%1$s> %2$s is not registered in the manifest", tag, fqcn));
- }
-}
diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijViewTypeDetector.java b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijViewTypeDetector.java
index 4c54a1910bb..6bb95d42253 100644
--- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijViewTypeDetector.java
+++ b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijViewTypeDetector.java
@@ -30,8 +30,8 @@ import java.util.Collections;
public class IntellijViewTypeDetector extends ViewTypeDetector {
static final Implementation IMPLEMENTATION = new Implementation(
- IntellijViewTypeDetector.class,
- Scope.JAVA_FILE_SCOPE);
+ IntellijViewTypeDetector.class,
+ Scope.SOURCE_FILE_SCOPE);
@Nullable
@Override
diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/ProblemData.java b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/ProblemData.java
index ff2aedda337..33abc54e177 100644
--- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/ProblemData.java
+++ b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/ProblemData.java
@@ -1,19 +1,3 @@
-/*
- * 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.android.inspections.klint;
import com.android.tools.klint.detector.api.Issue;
diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/State.java b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/State.java
index 29cc5c66b0b..b122b494b16 100644
--- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/State.java
+++ b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/State.java
@@ -1,19 +1,3 @@
-/*
- * 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.android.inspections.klint;
import com.android.tools.klint.detector.api.Issue;
diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/SuppressLintIntentionAction.java b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/SuppressLintIntentionAction.java
deleted file mode 100644
index ed85df873aa..00000000000
--- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/SuppressLintIntentionAction.java
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * 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.android.inspections.klint;
-
-import com.google.common.base.Joiner;
-import com.google.common.base.Splitter;
-import com.intellij.codeInsight.AnnotationUtil;
-import com.intellij.codeInsight.FileModificationService;
-import com.intellij.codeInsight.intention.AddAnnotationFix;
-import com.intellij.codeInsight.intention.IntentionAction;
-import com.intellij.icons.AllIcons;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Iconable;
-import com.intellij.openapi.util.TextRange;
-import com.intellij.psi.*;
-import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.psi.xml.XmlAttribute;
-import com.intellij.psi.xml.XmlFile;
-import com.intellij.psi.xml.XmlTag;
-import com.intellij.util.IncorrectOperationException;
-import org.jetbrains.android.util.AndroidBundle;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import javax.swing.*;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import static com.android.SdkConstants.*;
-
-/** Intention for adding a {@code @SuppressLint} annotation on the given element for the given id */
-public class SuppressLintIntentionAction implements IntentionAction, Iconable {
- private static final String NO_INSPECTION_PREFIX = "//noinspection ";
- private final String myId;
- private final PsiElement myElement;
-
- SuppressLintIntentionAction(String id, PsiElement element) {
- myId = id;
- myElement = element;
- }
-
- @Override
- public Icon getIcon(@IconFlags int flags) {
- return AllIcons.Actions.Cancel;
- }
-
- @NotNull
- @Override
- public String getText() {
- String id = getLintId(myId);
- final PsiFile file = PsiTreeUtil.getParentOfType(myElement, PsiFile.class);
- if (file == null) {
- return "";
- } else if (file instanceof XmlFile) {
- return AndroidBundle.message("android.lint.fix.suppress.lint.api.attr", id);
- } else if (file instanceof PsiJavaFile) {
- return AndroidBundle.message("android.lint.fix.suppress.lint.api.annotation", id);
- } else {
- return "";
- }
- }
-
- @NotNull
- @Override
- public String getFamilyName() {
- return getText();
- }
-
- @Override
- public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
- return true;
- }
-
- @Override
- public void invoke(@NotNull Project project, @Nullable Editor editor, @NotNull PsiFile file) throws IncorrectOperationException {
- if (file instanceof XmlFile) {
- final XmlTag element = PsiTreeUtil.getParentOfType(myElement, XmlTag.class);
- if (element == null) {
- return;
- }
-
- if (!FileModificationService.getInstance().preparePsiElementForWrite(element)) {
- return;
- }
- String lintId = getLintId(myId);
- addSuppressAttribute(project, (XmlFile) file, element, lintId);
- } else if (file instanceof PsiJavaFile) {
- final PsiModifierListOwner container =
- PsiTreeUtil.getParentOfType(myElement, PsiModifierListOwner.class);
- if (container == null) {
- return;
- }
-
- if (!FileModificationService.getInstance().preparePsiElementForWrite(container)) {
- return;
- }
- final PsiModifierList modifierList = container.getModifierList();
- if (modifierList != null) {
-
- String lintId = getLintId(myId);
- addSuppressAnnotation(project, container, container, lintId);
- }
- }
- }
-
- /**
- * TODO: There is probably an existing utility method somewhere in IntelliJ for this;
- * find it and inline. Possible candidate: {@link com.intellij.xml.XmlNamespaceHelper#insertNamespaceDeclaration}.
- * See also code in {@link com.intellij.codeInsight.completion.XmlAttributeInsertHandler} for additional useful
- * code such as code to pick a unique prefix, look up the prefix from the schema provider etc (which presumably would
- * consult {@link org.jetbrains.android.AndroidXmlSchemaProvider}).
- *
- */
- @NotNull
- public static String ensureNamespaceImported(@NotNull Project project, @NotNull XmlFile file, @NotNull String namespaceUri) {
- ApplicationManager.getApplication().assertWriteAccessAllowed();
-
- final XmlTag rootTag = file.getRootTag();
-
- assert rootTag != null;
- final XmlElementFactory elementFactory = XmlElementFactory.getInstance(project);
-
- String prefix = rootTag.getPrefixByNamespace(namespaceUri);
- if (prefix != null) {
- return prefix;
- }
-
- if (TOOLS_URI.equals(namespaceUri)) {
- prefix = TOOLS_PREFIX;
- } else if (ANDROID_URI.equals(namespaceUri)) {
- prefix = ANDROID_NS_NAME;
- } else {
- prefix = APP_PREFIX;
- }
- if (rootTag.getAttribute(XMLNS_PREFIX + prefix) != null) {
- String base = prefix;
- for (int i = 2; ; i++) {
- prefix = base + Integer.toString(i);
- if (rootTag.getAttribute(XMLNS_PREFIX + prefix) == null) {
- break;
- }
- }
- }
- String name = XMLNS_PREFIX + prefix;
- final XmlAttribute xmlnsAttr = elementFactory.createXmlAttribute(name, namespaceUri);
- final XmlAttribute[] attributes = rootTag.getAttributes();
- XmlAttribute next = attributes.length > 0 ? attributes[0] : null;
- for (XmlAttribute attribute : attributes) {
- String attributeName = attribute.getName();
- if (!attributeName.startsWith(XMLNS_PREFIX) || attributeName.compareTo(name) > 0) {
- next = attribute;
- break;
- }
- }
- if (next != null) {
- rootTag.addBefore(xmlnsAttr, next);
- }
- else {
- rootTag.add(xmlnsAttr);
- }
-
- return prefix;
- }
-
- static String getLintId(String intentionId) {
- String lintId = intentionId;
- if (lintId.startsWith("AndroidLint")) {
- lintId = lintId.substring("AndroidLint".length());
- }
-
- return lintId;
- }
-
- @Override
- public boolean startInWriteAction() {
- return true;
- }
-
- private static void addSuppressAttribute(final Project project,
- final XmlFile file,
- final XmlTag element,
- final String id) throws IncorrectOperationException {
- XmlAttribute attribute = element.getAttribute(ATTR_IGNORE, TOOLS_URI);
- String value;
- if (attribute == null) {
- value = id;
- } else {
- List ids = new ArrayList();
- for (String existing : Splitter.on(',').trimResults().split(attribute.getValue())) {
- if (!existing.equals(id)) {
- ids.add(existing);
- }
- }
- ids.add(id);
- Collections.sort(ids);
- value = Joiner.on(',').join(ids);
- }
- ensureNamespaceImported(project, file, TOOLS_URI);
- element.setAttribute(ATTR_IGNORE, TOOLS_URI, value);
- }
-
- // Based on the equivalent code in com.intellij.codeInsight.daemon.impl.actions.SuppressFix
- // to add @SuppressWarnings annotations
-
- private static void addSuppressAnnotation(final Project project,
- final PsiElement container,
- final PsiModifierListOwner modifierOwner,
- final String id) throws IncorrectOperationException {
- PsiAnnotation annotation = AnnotationUtil.findAnnotation(modifierOwner, FQCN_SUPPRESS_LINT);
- final PsiAnnotation newAnnotation = createNewAnnotation(project, container, annotation, id);
- if (newAnnotation != null) {
- if (annotation != null && annotation.isPhysical()) {
- annotation.replace(newAnnotation);
- }
- else {
- final PsiNameValuePair[] attributes = newAnnotation.getParameterList().getAttributes();
- //noinspection ConstantConditions
- new AddAnnotationFix(FQCN_SUPPRESS_LINT, modifierOwner, attributes).invoke(project, null /*editor*/,
- container.getContainingFile());
- }
- }
- }
-
- @Nullable
- private static PsiAnnotation createNewAnnotation(@NotNull final Project project,
- @NotNull final PsiElement container,
- @Nullable final PsiAnnotation annotation,
- @NotNull final String id) {
- if (annotation != null) {
- final String currentSuppressedId = "\"" + id + "\"";
- String annotationText = annotation.getText();
- if (!annotationText.contains("{")) {
- final PsiNameValuePair[] attributes = annotation.getParameterList().getAttributes();
- if (attributes.length == 1) {
- final String suppressedWarnings = attributes[0].getText();
- if (suppressedWarnings.contains(currentSuppressedId)) return null;
- return JavaPsiFacade.getInstance(project).getElementFactory().createAnnotationFromText(
- "@" + FQCN_SUPPRESS_LINT + "({" + suppressedWarnings + ", " + currentSuppressedId + "})", container);
-
- }
- }
- else {
- final int curlyBraceIndex = annotationText.lastIndexOf("}");
- if (curlyBraceIndex > 0) {
- final String oldSuppressWarning = annotationText.substring(0, curlyBraceIndex);
- if (oldSuppressWarning.contains(currentSuppressedId)) return null;
- return JavaPsiFacade.getInstance(project).getElementFactory().createAnnotationFromText(
- oldSuppressWarning + ", " + currentSuppressedId + "})", container);
- }
- }
- }
- else {
- return JavaPsiFacade.getInstance(project).getElementFactory()
- .createAnnotationFromText("@" + FQCN_SUPPRESS_LINT + "(\"" + id + "\")", container);
- }
- return null;
- }
-}
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 546c3656c94..52b6c140dab 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
@@ -75,7 +75,7 @@ object UastChecker {
override fun visitCallExpression(node: UCallExpression): Boolean {
if (applicableFunctionNames.isNotEmpty()) {
if (node.kind == FUNCTION_CALL && node.functionName in applicableFunctionNames) {
- scanner.visitFunctionCall(context, node)
+ scanner.visitCall(context, node)
}
}
diff --git a/plugins/lint/uast-android/src/org/jetbrains/uast/check/UastScanner.java b/plugins/lint/uast-android/src/org/jetbrains/uast/check/UastScanner.java
index 061b9bb73de..1940452596d 100644
--- a/plugins/lint/uast-android/src/org/jetbrains/uast/check/UastScanner.java
+++ b/plugins/lint/uast-android/src/org/jetbrains/uast/check/UastScanner.java
@@ -30,7 +30,7 @@ public interface UastScanner {
List getApplicableSuperClasses();
List getApplicableConstructorTypes();
- void visitFunctionCall(UastAndroidContext context, UCallExpression node);
+ void visitCall(UastAndroidContext context, UCallExpression node);
void visitClass(UastAndroidContext context, UClass node);
void visitConstructor(UastAndroidContext context, UCallExpression functionCall, UFunction constructor);
diff --git a/plugins/uast-common/src/org/jetbrains/uast/UastUtils.kt b/plugins/uast-common/src/org/jetbrains/uast/UastUtils.kt
index 8082c69c6e6..74eaa1d3f9e 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/UastUtils.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/UastUtils.kt
@@ -16,15 +16,28 @@
@file:JvmName("UastUtils")
package org.jetbrains.uast
-import org.jetbrains.uast.kinds.UastClassKind
import org.jetbrains.uast.visitor.UastVisitor
+internal val ERROR_NAME = ""
+
+/**
+ * Returns the containing class of an element.
+ *
+ * @return the containing [UClass] element,
+ * or null if the receiver is null, or it is a top-level declaration.
+ */
tailrec fun UElement?.getContainingClass(): UClass? {
val parent = this?.parent ?: return null
if (parent is UClass) return parent
return parent.getContainingClass()
}
+/**
+ * Returns the containing file of an element.
+ *
+ * @return the containing [UFile] element,
+ * or null if the receiver is null, or the element is not inside a [UFile] (it is abmormal).
+ */
tailrec fun UElement?.getContainingFile(): UFile? {
val parent = this?.parent ?: return null
if (parent is UFile) return parent
@@ -33,20 +46,45 @@ tailrec fun UElement?.getContainingFile(): UFile? {
fun UElement?.getContainingClassOrEmpty() = getContainingClass() ?: UClassNotResolved
+/**
+ * Returns the containing function of an element.
+ *
+ * @return the containing [UFunction] element,
+ * or null if the receiver is null, or the element is not inside a [UFunction].
+ */
tailrec fun UElement?.getContainingFunction(): UFunction? {
val parent = this?.parent ?: return null
if (parent is UFunction) return parent
return parent.getContainingFunction()
}
+/**
+ * Returns the containing declaration of an element.
+ *
+ * @return the containing [UDeclaration] element,
+ * or null if the receiver is null, or the element is a top-level declaration.
+ */
tailrec fun UElement?.getContainingDeclaration(): UDeclaration? {
val parent = this?.parent ?: return null
if (parent is UDeclaration) return parent
return parent.getContainingDeclaration()
}
+/**
+ * Checks if the element is a top-level declaration.
+ *
+ * @return true if the element is a top-level declaration, false otherwise.
+ */
fun UDeclaration.isTopLevel() = parent is UFile
+/**
+ * Builds the log message for the [UElement.logString] function.
+ *
+ * @param firstLine the message line (the interface name, some optional information).
+ * @param nested nested UElements. Could be `List`, [UElement] or `null`.
+ * @throws IllegalStateException if the [nested] argument is invalid.
+ * @return the rendered log string.
+ */
fun UElement.log(firstLine: String, vararg nested: Any?): String {
return (if (firstLine.isBlank()) "" else firstLine + "\n") + nested.joinToString("\n") {
when (it) {
@@ -74,12 +112,27 @@ fun UClass.findFunctions(name: String) = declarations.filter { it is UFunction &
fun UCallExpression.getReceiver(): UExpression? = (this.parent as? UQualifiedExpression)?.receiver
+/**
+ * Resolves the receiver element if it implements [UResolvable].
+ *
+ * @return the resolved element, or null if the element was not resolved, or if the receiver element is not an [UResolvable].
+ */
fun UElement.resolveIfCan(context: UastContext): UDeclaration? = (this as? UResolvable)?.resolve(context)
-fun UElement.isThrow() = this is USpecialExpressionList && this.kind == UastSpecialExpressionKind.THROW
-
+/**
+ * Find an annotation with the required qualified name.
+ *
+ * @param fqName the qualified name to search
+ * @return [UAnnotation] element if the annotation with the specified [fqName] was found, null otherwise.
+ */
fun UAnnotated.findAnnotation(fqName: String) = annotations.firstOrNull { it.fqName == fqName }
+/**
+ * Get all class declarations (including supertypes).
+ *
+ * @param context the Uast context
+ * @return the list of declarations for the receiver class
+ */
fun UClass.getAllDeclarations(context: UastContext): List = mutableListOf().apply {
this += declarations
for (superType in superTypes) {
@@ -107,14 +160,6 @@ fun UCallExpression.getQualifiedCallElement(): UExpression {
return findParent(parent as? UExpression) ?: this
}
-val UDeclaration.fqName: String
- get() {
- val containingFqName = this.getContainingDeclaration()?.fqName
- ?: this.getContainingFile()?.packageFqName
- val containingFqNameWithDot = containingFqName?.let { it + "." } ?: ""
- return containingFqNameWithDot + this.name
- }
-
inline fun UElement.getParentOfType(): T? = getParentOfType(T::class.java)
fun UElement.getParentOfType(clazz: Class): T? {
@@ -133,10 +178,9 @@ fun UElement.getParentOfType(clazz: Class): T? {
fun UClass.findStaticMemberOfType(name: String, type: Class): T? {
for (companion in companions) {
- val classKind = companion.kind as? UastClassKind.UastCompanionObject ?: continue
- if (!classKind.default) continue
-
- val member = companion.declarations.firstOrNull { it.name == name && type.isInstance(it) }
+ val member = companion.declarations.firstOrNull {
+ it.name == name && type.isInstance(it) && it is UModifierOwner && it.hasModifier(UastModifier.STATIC)
+ }
@Suppress("UNCHECKED_CAST")
if (member != null) return member as T
}
@@ -146,4 +190,52 @@ fun UClass.findStaticMemberOfType(name: String, type: Class): T? {
it.name == name && it is UModifierOwner
&& it.hasModifier(UastModifier.STATIC) && type.isInstance(it)
} as T
+}
+
+fun UExpression.asQualifiedIdentifiers(): List? {
+ var error = false
+ val list = mutableListOf()
+ fun addIdentifiers(expr: UQualifiedExpression) {
+ val receiver = expr.receiver
+ val selector = expr.selector as? USimpleReferenceExpression ?: run { error = true; return }
+ when (receiver) {
+ is UQualifiedExpression -> addIdentifiers(receiver)
+ is USimpleReferenceExpression -> list += receiver.identifier
+ else -> {
+ error = true
+ return
+ }
+ }
+ list += selector.identifier
+ }
+ when (this) {
+ is UQualifiedExpression -> addIdentifiers(this)
+ is USimpleReferenceExpression -> listOf(identifier)
+ else -> return null
+ }
+ return if (error) null else list
+}
+
+fun UExpression.matchesQualified(fqName: String): Boolean {
+ val identifiers = this.asQualifiedIdentifiers() ?: return false
+ val passedIdentifiers = fqName.split('.')
+ return identifiers == passedIdentifiers
+}
+
+fun UExpression.startsWithQualified(fqName: String): Boolean {
+ val identifiers = this.asQualifiedIdentifiers() ?: return false
+ val passedIdentifiers = fqName.split('.')
+ identifiers.forEachIndexed { i, identifier ->
+ if (identifier != passedIdentifiers[i]) return false
+ }
+ return true
+}
+
+fun UExpression.endsWithQualified(fqName: String): Boolean {
+ val identifiers = this.asQualifiedIdentifiers() ?: return false
+ val passedIdentifiers = fqName.split('.')
+ identifiers.forEachIndexed { i, identifier ->
+ if (identifier != passedIdentifiers[i]) return false
+ }
+ return true
}
\ No newline at end of file
diff --git a/plugins/uast-common/src/org/jetbrains/uast/UastVisitor.kt b/plugins/uast-common/src/org/jetbrains/uast/UastVisitor.kt
index 15d777422dc..5578578d882 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/UastVisitor.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/UastVisitor.kt
@@ -46,7 +46,6 @@ abstract class UastVisitor {
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)
@@ -58,11 +57,66 @@ abstract class UastVisitor {
open fun visitLiteralExpression(node: ULiteralExpression) = visitElement(node)
open fun visitThisExpression(node: UThisExpression) = visitElement(node)
open fun visitSuperExpression(node: USuperExpression) = visitElement(node)
+ open fun visitReturnExpression(node: UReturnExpression) = visitElement(node)
+ open fun visitBreakExpression(node: UBreakExpression) = visitElement(node)
+ open fun visitContinueExpression(node: UContinueExpression) = visitElement(node)
+ open fun visitThrowExpression(node: UThrowExpression) = 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)
+
+ // After
+
+ open fun afterVisitElement(node: UElement) {}
+
+ open fun afterVisitFile(node: UFile) {}
+ open fun afterVisitImportStatement(node: UImportStatement) {}
+ open fun afterVisitAnnotation(node: UAnnotation) {}
+ open fun afterVisitCatchClause(node: UCatchClause) {}
+ open fun afterVisitType(node: UType) {}
+
+ // Declarations
+ open fun afterVisitClass(node: UClass) {}
+ open fun afterVisitFunction(node: UFunction) {}
+ open fun afterVisitVariable(node: UVariable) {}
+
+
+ // Expressions
+ open fun afterVisitLabeledExpression(node: ULabeledExpression) {}
+ open fun afterVisitDeclarationsExpression(node: UDeclarationsExpression) {}
+ open fun afterVisitBlockExpression(node: UBlockExpression) {}
+ open fun afterVisitQualifiedExpression(node: UQualifiedExpression) {}
+ open fun afterVisitSimpleReferenceExpression(node: USimpleReferenceExpression) {}
+ open fun afterVisitCallExpression(node: UCallExpression) {}
+ open fun afterVisitBinaryExpression(node: UBinaryExpression) {}
+ open fun afterVisitBinaryExpressionWithType(node: UBinaryExpressionWithType) {}
+ open fun afterVisitParenthesizedExpression(node: UParenthesizedExpression) {}
+ open fun afterVisitUnaryExpression(node: UUnaryExpression) {}
+ open fun afterVisitPrefixExpression(node: UPrefixExpression) {}
+ open fun afterVisitPostfixExpression(node: UPostfixExpression) {}
+ open fun afterVisitSpecialExpressionList(node: USpecialExpressionList) {}
+ open fun afterVisitIfExpression(node: UIfExpression) {}
+ open fun afterVisitSwitchExpression(node: USwitchExpression) {}
+ open fun afterVisitSwitchClauseExpression(node: USwitchClauseExpression) {}
+ open fun afterVisitWhileExpression(node: UWhileExpression) {}
+ open fun afterVisitDoWhileExpression(node: UDoWhileExpression) {}
+ open fun afterVisitForExpression(node: UForExpression) {}
+ open fun afterVisitForEachExpression(node: UForEachExpression) {}
+ open fun afterVisitTryExpression(node: UTryExpression) {}
+ open fun afterVisitLiteralExpression(node: ULiteralExpression) {}
+ open fun afterVisitThisExpression(node: UThisExpression) {}
+ open fun afterVisitSuperExpression(node: USuperExpression) {}
+ open fun afterVisitReturnExpression(node: UReturnExpression) {}
+ open fun afterVisitBreakExpression(node: UBreakExpression) {}
+ open fun afterVisitContinueExpression(node: UContinueExpression) {}
+ open fun afterVisitThrowExpression(node: UThrowExpression) {}
+ open fun afterVisitArrayAccessExpression(node: UArrayAccessExpression) {}
+ open fun afterVisitCallableReferenceExpression(node: UCallableReferenceExpression) {}
+ open fun afterVisitClassLiteralExpression(node: UClassLiteralExpression) {}
+ open fun afterVisitLambdaExpression(node: ULambdaExpression) {}
+ open fun afterVisitObjectLiteralExpression(node: UObjectLiteralExpression) {}
}
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 e4de5de6dca..1a5f7cee61d 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/baseElements/UAnnotation.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/baseElements/UAnnotation.kt
@@ -17,24 +17,59 @@ package org.jetbrains.uast
import org.jetbrains.uast.visitor.UastVisitor
+/**
+ Represents an applied JVM annotation.
+ */
interface UAnnotation : UElement, UNamed, UFqNamed {
+ /**
+ * Returns the list of named value arguments.
+ */
val valueArguments: List
+ /**
+ * Returns the class of this annotation.
+ *
+ * @return annotation class or null if the class was not resolved
+ */
fun resolve(context: UastContext): UClass?
+
+ /**
+ * Returns the evaluated value of the argument with the specified name.
+ *
+ * @param name name of the annotation value parameter
+ * @return the argument value
+ */
fun getValue(name: String) = valueArguments.firstOrNull { it.name == name }?.expression?.evaluate()
+ /**
+ * Returns the list of Pair(name, evaluatedValue) for all applied annotation arguments.
+ *
+ * @return the list of name-value pairs.
+ */
fun getValues() = valueArguments.map { Pair(it.name, it.expression.evaluate()) }
override fun logString() = log("UAnnotation ($name)")
- override fun renderString() = if (valueArguments.isEmpty()) "@$name" else "@$name(" +
- valueArguments.joinToString { it.renderString() } + ")"
+
+ override fun renderString(): String {
+ return if (valueArguments.isEmpty())
+ "@$name"
+ else
+ "@$name(" + valueArguments.joinToString { it.renderString() } + ")"
+ }
override fun accept(visitor: UastVisitor) {
if (visitor.visitAnnotation(this)) return
valueArguments.acceptList(visitor)
+ visitor.afterVisitAnnotation(this)
}
}
+/**
+ * Represents an annotated element.
+ */
interface UAnnotated : UElement {
+ /**
+ * Returns the list of annotations applied to the current element.
+ */
val annotations: List
}
\ No newline at end of file
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 ef79af1bd4a..044777452a4 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/baseElements/UElement.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/baseElements/UElement.kt
@@ -17,39 +17,153 @@ package org.jetbrains.uast
import org.jetbrains.uast.visitor.UastVisitor
+/**
+ * The common interface for all Uast elements.
+ */
interface UElement {
+ /**
+ * Returns the element parent.
+ */
val parent: UElement?
+ /**
+ * Returns true if this element is valid, false otherwise.
+ */
open val isValid: Boolean
get() = true
-
+
+ /**
+ * Returns the log string.
+ *
+ * Output example (should be something like this):
+ * UWhileExpression
+ * UBinaryExpression (>)
+ * USimpleReferenceExpression (i)
+ * ULiteralExpression (5)
+ * UBlockExpression
+ * UCallExpression (println)
+ * ULiteralExpression (ABC)
+ * UPostfixExpression (--)
+ * USimpleReferenceExpression(i)
+ *
+ * @return the expression tree for this element.
+ * @see [UIfExpression] for example.
+ */
fun logString(): String
+
+ /**
+ * Returns the string in pseudo-code.
+ *
+ * Output example (should be something like this):
+ * while (i > 5) {
+ * println("Hello, world")
+ * i--
+ * }
+ *
+ * @return the rendered text.
+ * @see [UIfExpression] for example.
+ */
fun renderString(): String = logString()
+ /**
+ * Passes the element to the specified visitor.
+ *
+ * @param visitor the visitor to pass the element to.
+ */
fun accept(visitor: UastVisitor) {
visitor.visitElement(this)
}
}
+/**
+ * An interface for the [UElement] which has a name.
+ */
interface UNamed {
+ /**
+ * Returns the name of this element.
+ */
val name: String
+ /**
+ * Checks if the element name is equal to the passed name.
+ *
+ * @param name the name to check against
+ * @return true if the element name is equal to [name], false otherwise.
+ */
fun matchesName(name: String) = this.name == name
}
+/**
+ * An interface for the [UElement] which has a qualified name.
+ */
interface UFqNamed : UNamed {
+ /**
+ * Returns the qualified name of this element, or null if the qualified name was not resolved.
+ */
val fqName: String?
+ /**
+ * Checks if the element qualified name is equal to the passed name.
+ *
+ * @param fqName qualified name to check against
+ * @return true if the element name is not null and is equal to [name], false otherwise.
+ */
fun matchesFqName(fqName: String) = this.fqName == fqName
}
+/**
+ * An interface for the [UElement] which has Uast modifiers.
+ */
interface UModifierOwner {
+ /**
+ * Checks if the element has the passed modifier.
+ *
+ * @param modifier modifier to check
+ * @return true if the element has [modifier], false otherwise.
+ */
fun hasModifier(modifier: UastModifier): Boolean
}
+/**
+ * An interface for the [UElement] which has a visibility (class, function, variable).
+ */
+interface UVisibilityOwner {
+ /**
+ * Returns the element visibility.
+ */
+ val visibility: UastVisibility
+}
+
+/**
+ * An inteface for the [UElement] which can be resolved to the its declaration.
+ */
interface UResolvable {
+ /**
+ * Returns the declaration element.
+ *
+ * @param context the Uast context
+ * @return the resolved declaration, or null if the declaration was not resolved.
+ */
fun resolve(context: UastContext): UDeclaration?
+
+ /**
+ * Returns the declaration element or an empty Uast declaration element if the declaration was not resolved.
+ * An empty declaration element should be a singleton.
+ * [resolveOrEmpty] should not create new elements each time the declaration was not resolved.
+ *
+ * @param context the Uast context
+ * @return the resolved declaration, of an empty error Uast declaration element if the declaration was not resolved.
+ *
+ * @see [UDeclarationNotResolved]
+ */
fun resolveOrEmpty(context: UastContext): UDeclaration = resolve(context) ?: UDeclarationNotResolved
+ /**
+ * Returns the declaration [UClass] element of null if the declaration was not resolved.
+ *
+ * @param context the Uast context
+ * @return the resolved [UClass] element, or null if the class was not resolved,
+ * or if the resolved [UElement] is not an instance of [UClass].
+ */
fun resolveClass(context: UastContext): UClass? = resolve(context) as? UClass
}
\ No newline at end of file
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 e869c61d95d..c2cf5bbb251 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/baseElements/UExpression.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/baseElements/UExpression.kt
@@ -24,6 +24,7 @@ interface UExpression : UElement {
override fun accept(visitor: UastVisitor) {
visitor.visitElement(this)
+ visitor.afterVisitElement(this)
}
}
@@ -36,6 +37,6 @@ interface NoModifiers : UModifierOwner {
override fun hasModifier(modifier: UastModifier) = false
}
-class EmptyExpression(override val parent: UElement) : UExpression {
+class EmptyUExpression(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 9c6085eaaf7..30bd6467c60 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/baseElements/UFile.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/baseElements/UFile.kt
@@ -17,11 +17,31 @@ package org.jetbrains.uast
import org.jetbrains.uast.visitor.UastVisitor
+/**
+ * Represents a source file.
+ * File is the topmost element of the UElement hierarchy.
+ * Files should not be nested, thus the [parent] property should always return null.
+ */
interface UFile: UElement {
+ /**
+ * Returns the qualified package name of this file.
+ * Could be an empty string if the package is "default", or null if the package directive is not present in this file.
+ */
val packageFqName: String?
+
+ /**
+ * Returns the list of import statements.
+ */
val importStatements: List
+
+ /**
+ * Returns the list of declarations in this file (classes, properties, functions, etc).
+ */
val declarations: List
+ /**
+ * Returns list of classes containing in this file.
+ */
val classes: List
get() = declarations.filterIsInstance()
@@ -32,12 +52,13 @@ interface UFile: UElement {
if (visitor.visitFile(this)) return
declarations.acceptList(visitor)
importStatements.acceptList(visitor)
+ visitor.afterVisitFile(this)
}
override fun logString() = "UFile (package = $packageFqName)\n" + declarations.joinToString("\n") { it.logString().withMargin }
override fun renderString() = buildString {
- if (packageFqName != null) {
+ if (!packageFqName.isNullOrBlank()) {
appendln("package $packageFqName")
appendln()
}
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 31124fd2b71..bb4509bf8bb 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/controlStructures/UDoWhileExpression.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/controlStructures/UDoWhileExpression.kt
@@ -17,13 +17,26 @@ package org.jetbrains.uast
import org.jetbrains.uast.visitor.UastVisitor
+/**
+ * Represent a
+ *
+ * `do {
+ * // body
+ * } while (expr)`
+ *
+ * loop expression.
+ */
interface UDoWhileExpression : ULoopExpression {
+ /**
+ * Returns the loop post-condition.
+ */
val condition: UExpression
override fun accept(visitor: UastVisitor) {
if (visitor.visitDoWhileExpression(this)) return
condition.accept(visitor)
body.accept(visitor)
+ visitor.afterVisitDoWhileExpression(this)
}
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 23979f1066d..051b98aa6a3 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/controlStructures/UForEachExpression.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/controlStructures/UForEachExpression.kt
@@ -17,8 +17,24 @@ package org.jetbrains.uast
import org.jetbrains.uast.visitor.UastVisitor
+/**
+ * Represents a
+ *
+ * `for (element : collectionOfElements) {
+ * // body
+ * }`
+ *
+ * loop expression.
+ */
interface UForEachExpression : ULoopExpression {
+ /**
+ * Returns the loop variable.
+ */
val variable: UVariable
+
+ /**
+ * Returns the iterated value (collection, sequence, iterable etc.)
+ */
val iteratedValue: UExpression
override fun accept(visitor: UastVisitor) {
@@ -26,6 +42,7 @@ interface UForEachExpression : ULoopExpression {
variable.accept(visitor)
iteratedValue.accept(visitor)
body.accept(visitor)
+ visitor.afterVisitForEachExpression(this)
}
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 497d96e8850..044dcba18c7 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/controlStructures/UForExpression.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/controlStructures/UForExpression.kt
@@ -17,9 +17,29 @@ package org.jetbrains.uast
import org.jetbrains.uast.visitor.UastVisitor
+/**
+ * Represents a
+ *
+ * `for (initDeclarations; loopCondition; update) {
+ * // body
+ * }`
+ *
+ * loop expression.
+ */
interface UForExpression : ULoopExpression {
+ /**
+ * Returns the [UExpression] containing variable declarations, or null if the are no variables declared.
+ */
val declaration: UExpression?
+
+ /**
+ * Returns the loop condition, or null if the condition is empty.
+ */
val condition: UExpression?
+
+ /**
+ * Returns the loop update expression(s).
+ */
val update: UExpression?
override fun accept(visitor: UastVisitor) {
@@ -28,6 +48,7 @@ interface UForExpression : ULoopExpression {
condition?.accept(visitor)
update?.accept(visitor)
body.accept(visitor)
+ visitor.afterVisitForExpression(this)
}
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 2be73c1b1bb..fdffd3b42d5 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/controlStructures/UIfExpression.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/controlStructures/UIfExpression.kt
@@ -17,10 +17,40 @@ package org.jetbrains.uast
import org.jetbrains.uast.visitor.UastVisitor
+/**
+ * Represents
+ *
+ * `if (condition) {
+ * // do if true
+ * } else {
+ * // do if false
+ * }`
+ *
+ * and
+ *
+ * `condition : trueExpression ? falseExpression`
+ *
+ * condition expressions.
+ */
interface UIfExpression : UExpression {
+ /**
+ * Returns the condition expression.
+ */
val condition: UExpression
+
+ /**
+ * Returns the expression which is executed if the condition is true, or null if the expression is empty.
+ */
val thenBranch: UExpression?
+
+ /**
+ * Returns the expression which is executed if the condition is false, or null if the expression is empty.
+ */
val elseBranch: UExpression?
+
+ /**
+ * Returns true if the expression is ternary (condition ? trueExpression : falseExpression).
+ */
val isTernary: Boolean
override fun accept(visitor: UastVisitor) {
@@ -28,9 +58,11 @@ interface UIfExpression : UExpression {
condition.accept(visitor)
thenBranch?.accept(visitor)
elseBranch?.accept(visitor)
+ visitor.afterVisitIfExpression(this)
}
override fun logString() = log("UIfExpression", condition, thenBranch, elseBranch)
+
override fun renderString() = buildString {
if (isTernary) {
append("(" + condition.renderString() + ")")
@@ -42,7 +74,7 @@ interface UIfExpression : UExpression {
append("if (${condition.renderString()}) ")
thenBranch?.let { append(it.renderString()) }
val elseBranch = elseBranch
- if (elseBranch != null && elseBranch !is EmptyExpression) {
+ if (elseBranch != null && elseBranch !is EmptyUExpression) {
if (thenBranch !is UBlockExpression) append(" ")
append("else ")
append(elseBranch.renderString())
diff --git a/plugins/uast-common/src/org/jetbrains/uast/controlStructures/ULoopExpression.kt b/plugins/uast-common/src/org/jetbrains/uast/controlStructures/ULoopExpression.kt
index 9c5028250a5..2eb6b03b47b 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/controlStructures/ULoopExpression.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/controlStructures/ULoopExpression.kt
@@ -15,6 +15,12 @@
*/
package org.jetbrains.uast
+/**
+ * Represents the loop expression.
+ */
interface ULoopExpression : UExpression {
+ /**
+ * Returns the loop body [UExpression].
+ */
val body: UExpression
}
\ No newline at end of file
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 99b0001a52b..80c0871baea 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/controlStructures/USwitchExpression.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/controlStructures/USwitchExpression.kt
@@ -17,14 +17,35 @@ package org.jetbrains.uast
import org.jetbrains.uast.visitor.UastVisitor
+/**
+ * Represents a
+ *
+ * ` switch (expression) {
+ * case value1 -> expr1
+ * case value2 -> expr2
+ * ...
+ * else -> exprElse
+ * }
+ *
+ * conditional expression.
+ */
interface USwitchExpression : UExpression {
+ /*
+ Returns the expression on which the `switch` expression is performed.
+ */
val expression: UExpression?
+
+ /*
+ Returns the switch body.
+ Body should contain [USwitchClauseExpression] expressions.
+ */
val body: UExpression
override fun accept(visitor: UastVisitor) {
if (visitor.visitSwitchExpression(this)) return
expression?.accept(visitor)
body.accept(visitor)
+ visitor.afterVisitSwitchExpression(this)
}
override fun logString() = log("USwitchExpression", expression, body)
@@ -35,23 +56,47 @@ interface USwitchExpression : UExpression {
}
}
-interface USwitchClauseExpression : UExpression
-
-interface UExpressionSwitchClauseExpression : USwitchClauseExpression {
- val caseValue: UExpression
+/**
+ * Represents a [USwitchExpression] clause.
+ * [USwitchClauseExpression] does not contain the clause body,
+ * and the actual body expression should be the next element in the parent expression list.
+ */
+interface USwitchClauseExpression : UExpression {
+ /**
+ * Returns the list of values for this clause, or null if the are no values for this close
+ * (for example, for the `else` clause).
+ */
+ val caseValues: List?
override fun accept(visitor: UastVisitor) {
if (visitor.visitSwitchClauseExpression(this)) return
- caseValue.accept(visitor)
+ caseValues?.acceptList(visitor)
+ visitor.afterVisitSwitchClauseExpression(this)
}
- override fun renderString() = caseValue.renderString() + " -> "
- override fun logString() = log("UExpressionSwitchClauseExpression", caseValue)
+ override fun renderString() = (caseValues?.joinToString { it.renderString() } ?: "else") + " -> "
+ override fun logString() = log("USwitchClauseExpression", caseValues)
}
-interface UDefaultSwitchClauseExpression : USwitchClauseExpression {
- override fun logString() = "UDefaultSwitchClause"
- override fun renderString() = "else -> "
-}
+/**
+ * Represents a [USwitchExpression] clause with the body.
+ * [USwitchClauseExpressionWithBody], comparing with [USwitchClauseExpression], contains the body expression.
+ *
+ * Implementing this interface *is the right way* to support `switch` clauses in your language.
+ */
+interface USwitchClauseExpressionWithBody : USwitchClauseExpression {
+ /**
+ * Returns the body expression for this clause.
+ */
+ val body: UExpression
-class SimpleUDefaultSwitchClauseExpression(override val parent: UElement) : UDefaultSwitchClauseExpression
\ No newline at end of file
+ override fun accept(visitor: UastVisitor) {
+ if (visitor.visitSwitchClauseExpression(this)) return
+ caseValues?.acceptList(visitor)
+ body.accept(visitor)
+ visitor.afterVisitSwitchClauseExpression(this)
+ }
+
+ override fun renderString() = (caseValues?.joinToString { it.renderString() } ?: "else") + " -> " + body.renderString()
+ override fun logString() = log("USwitchClauseExpressionWithBody", caseValues, body)
+}
\ No newline at end of file
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 919560f6152..c6c9a491bd1 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/controlStructures/UTryExpression.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/controlStructures/UTryExpression.kt
@@ -17,10 +17,45 @@ package org.jetbrains.uast
import org.jetbrains.uast.visitor.UastVisitor
+/**
+ * Represents
+ *
+ * `try {
+ * // tryClause body
+ * } catch (e: Type1, Type2 ... TypeN) {
+ * // catchClause1 body
+ * } ... {
+ * finally {
+ * //finallyBody
+ * }`
+ *
+ * and
+ *
+ * `try (resource1, ..., resourceN) {
+ * // tryClause body
+ * }`
+ *
+ * expressions.
+ */
interface UTryExpression : UExpression {
+ /**
+ * Returns the list of try resources, or null if this expression is not a `try-with-resources` expression.
+ */
val resources: List?
+
+ /**
+ * Returns the `try` clause expression.
+ */
val tryClause: UExpression
+
+ /**
+ * Returns the `catch` clauses [UCatchClause] expression list.
+ */
val catchClauses: List
+
+ /**
+ * Returns the `finally` clause expression, or null if the `finally` clause is absent.
+ */
val finallyClause: UExpression?
override fun accept(visitor: UastVisitor) {
@@ -29,13 +64,14 @@ interface UTryExpression : UExpression {
tryClause.accept(visitor)
catchClauses.acceptList(visitor)
finallyClause?.accept(visitor)
+ visitor.afterVisitTryExpression(this)
}
override fun renderString() = buildString {
append("try ")
- appendln(tryClause.renderString())
- catchClauses.forEach { appendln(it.renderString()) }
- finallyClause?.let { append("finally ").append(it.renderString()) }
+ appendln(tryClause.renderString().trim('\n'))
+ catchClauses.forEach { appendln(it.renderString().trim('\n')) }
+ finallyClause?.let { append("finally ").append(it.renderString().trim('\n')) }
}
override fun logString() = "UTryExpression\n" +
@@ -44,9 +80,23 @@ interface UTryExpression : UExpression {
(finallyClause?.let { it.logString().withMargin } ?: "" )
}
+/**
+ * Represents the `catch` clause in [UTryExpression].
+ */
interface UCatchClause : UElement {
+ /**
+ * Returns the `catch` clause body expression.
+ */
val body: UExpression
+
+ /**
+ * Returns the exception parameter variables for this `catch` clause.
+ */
val parameters: List
+
+ /**
+ * Returns the exception types for this `catch` clause.
+ */
val types: List
override fun accept(visitor: UastVisitor) {
@@ -54,6 +104,7 @@ interface UCatchClause : UElement {
body.accept(visitor)
parameters.acceptList(visitor)
types.acceptList(visitor)
+ visitor.afterVisitCatchClause(this)
}
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 8ed670e799b..4a354dc9308 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/controlStructures/UWhileExpression.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/controlStructures/UWhileExpression.kt
@@ -17,13 +17,26 @@ package org.jetbrains.uast
import org.jetbrains.uast.visitor.UastVisitor
+/**
+ * Represents a
+ *
+ * `while (condition) {
+ * // body
+ * }`
+ *
+ * expression.
+ */
interface UWhileExpression : ULoopExpression {
+ /**
+ * Returns the loop condition.
+ */
val condition: UExpression
override fun accept(visitor: UastVisitor) {
if (visitor.visitWhileExpression(this)) return
condition.accept(visitor)
body.accept(visitor)
+ visitor.afterVisitWhileExpression(this)
}
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 b0bd5f12022..3506e40bbf4 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/declarations/UClass.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/declarations/UClass.kt
@@ -15,41 +15,94 @@
*/
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 */
+/**
+ * Represents a JVM class (ordinary class, interface, annotation, singleton, etc.).
+ */
+interface UClass : UDeclaration, UFqNamed, UModifierOwner, UVisibilityOwner, UAnnotated {
+ /**
+ * Returns the class simple (non-qualified) name.
+ * The simple class name is only for the debug purposes. Do not check against it in the production code.
+ */
override val name: String
+ /**
+ * Returns true if the class is anonymous ([name] in this case should return a placeholder like "").
+ */
val isAnonymous: Boolean
- val visibility: UastVisibility
+
+ /**
+ * Returns the class kind (ordinary class, interface, annotation, etc.).
+ */
val kind: UastClassKind
+
+ /**
+ * Returns the default type for this class.
+ */
val defaultType: UType
+ /**
+ * Returns the class companions.
+ */
val companions: List
+ /**
+ * Returns the class JVM name, or null if the JVM name is unknown.
+ */
open val internalName: String?
get() = null
+ /**
+ * Returns the all supertypes of this class.
+ */
val superTypes: List
+
+ /**
+ * Returns class declarations (nested classes, constructors, functions, variables, etc.).
+ * An empty (default) constructor also should be present.
+ */
val declarations: List
+ /**
+ * Returns nested classes declared in this class.
+ */
val nestedClasses: List
get() = declarations.filterIsInstance()
+ /**
+ * Returns functions declared in this class.
+ */
val functions: List
get() = declarations.filterIsInstance()
+ /**
+ * Returns properties declared in this class.
+ */
val properties: List
get() = declarations.filterIsInstance()
+ /**
+ * Returns constructors declared in this class.
+ */
@Suppress("UNCHECKED_CAST")
val constructors: List
get() = declarations.filter { it is UFunction && it.kind == UastFunctionKind.CONSTRUCTOR } as List
+ /**
+ * Checks if the class is subclass of another.
+ *
+ * @param fqName qualified name of the class to check against
+ * @return true if the class is the *subclass* of the class with the specified [fqName],
+ * false if the class qualified name is [fqName] or if the class is not a subclass of the class with the specified [fqName]
+ */
fun isSubclassOf(fqName: String) : Boolean
+ /**
+ * Get the direct superclass of this class.
+ *
+ * @return null if the class has not a superclass (java.lang.Object).
+ */
fun getSuperClass(context: UastContext): UClass?
override fun accept(visitor: UastVisitor) {
@@ -57,24 +110,24 @@ interface UClass : UDeclaration, UFqNamed, UModifierOwner, UAnnotated {
nameElement?.accept(visitor)
declarations.acceptList(visitor)
annotations.acceptList(visitor)
+ visitor.afterVisitClass(this)
}
- override fun renderString(): String {
- val modifiers = listOf(UastModifier.ABSTRACT, UastModifier.FINAL, UastModifier.STATIC)
- .filter { hasModifier(it) }.joinToString(" ") { it.name }.let { if (it.isBlank()) it else "$it " }
-
- val name = if (isAnonymous) "" else " $name"
+ override fun renderString() = buildString {
+ appendWithSpace(visibility.name)
+ appendWithSpace(renderModifiers())
+ appendWithSpace(kind.text)
+ appendWithSpace(name)
val declarations = if (declarations.isEmpty()) "" else buildString {
appendln("{")
- append(declarations.joinToString("\n") { it.renderString() }.withMargin)
+ append(declarations.joinToString("\n\n") { it.renderString().trim('\n') }.withMargin)
append("\n}")
}
-
- return "${visibility.name} " + modifiers + kind.text + name + " " + declarations
+ append(declarations)
}
- override fun logString() = "UClass ($name, kind = ${kind.text})\n" + declarations.logString()
+ override fun logString() = log("UClass ($name, kind = ${kind.text})", declarations)
}
object UClassNotResolved : UClass {
@@ -88,7 +141,7 @@ object UClassNotResolved : UClass {
override val defaultType = UastErrorType
override val nameElement = null
override val parent = null
- override val name = ""
+ override val name = ERROR_NAME
override val fqName = null
override val internalName = null
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 45f5e593454..31f8a295bde 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/declarations/UDeclaration.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/declarations/UDeclaration.kt
@@ -17,16 +17,38 @@ package org.jetbrains.uast
import org.jetbrains.uast.visitor.UastVisitor
+/**
+ * Represents a declaration.
+ */
interface UDeclaration : UElement, UNamed {
+ /**
+ * Returns an element for the name node, or null if the node does not exist in the underlying AST (Psi).
+ */
val nameElement: UElement?
+ /**
+ * Checks if the function name is [name], and the function containing class qualified name is [containingClassFqName].
+ *
+ * @param containingClassFqName the required containing class qualified name.
+ * @param name the function name to check against.
+ * @return true if the call is a function call, the function name is [name],
+ * and the qualified name of the function direct containing class is [containingClassFqName],
+ * false otherwise.
+ */
+ open fun matchesNameWithContaining(containingClassFqName: String, name: String): Boolean {
+ if (!matchesName(name)) return false
+ val containingClass = parent as? UClass ?: return false
+ return containingClass.matchesFqName(containingClassFqName)
+ }
+
override fun accept(visitor: UastVisitor) {
visitor.visitElement(this)
+ visitor.afterVisitElement(this)
}
}
object UDeclarationNotResolved : UDeclaration {
- override val name = ""
+ override val name = ERROR_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 aae00f8aea2..9cf8d7f720a 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/declarations/UFunction.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/declarations/UFunction.kt
@@ -17,58 +17,109 @@ package org.jetbrains.uast
import org.jetbrains.uast.visitor.UastVisitor
-interface UFunction : UDeclaration, UModifierOwner, UAnnotated {
+/**
+ * Represents a function.
+ * Function could be a JVM method, a property accessor, a constructor, etc.
+ */
+interface UFunction : UDeclaration, UModifierOwner, UVisibilityOwner, UAnnotated {
+ /**
+ * Returns the function kind.
+ */
val kind: UastFunctionKind
- val valueParameters: List
- val valueParameterCount: Int
- val typeParameters: List
- val typeParameterCount: Int
- val returnType: UType?
- val body: UExpression
- val visibility: UastVisibility
+ /**
+ * Returns the function value parameters.
+ */
+ val valueParameters: List
+
+ /**
+ * Returns the function value parameters count.
+ * Retrieving the parameter count could be faster than getting the [valueParameters.size],
+ * because there is no need to create actual [UVariable] instances.
+ */
+ val valueParameterCount: Int
+
+ /**
+ * Returns the function type parameters.
+ */
+ val typeParameters: List
+
+ /**
+ * Returns the function type parameter count.
+ */
+ val typeParameterCount: Int
+
+ /**
+ * Returns the function return type, or null if the function does not have a return type
+ * (e.g. it is a constructor).
+ */
+ val returnType: UType?
+
+ /**
+ * Returns the function body expression.
+ */
+ val body: UExpression?
+
+ /**
+ * Returns the function JVM descriptor (for example, "(ILjava/lang/String;)[I"), or null if the descriptor is unknown.
+ */
open val bytecodeDescriptor: String?
get() = null
+
+ /**
+ * Get the list of all super functions for this function.
+ */
fun getSuperFunctions(context: UastContext): List
override fun accept(visitor: UastVisitor) {
if (visitor.visitFunction(this)) return
nameElement?.accept(visitor)
valueParameters.acceptList(visitor)
- body.accept(visitor)
+ body?.accept(visitor)
annotations.acceptList(visitor)
typeParameters.acceptList(visitor)
returnType?.accept(visitor)
+ visitor.afterVisitFunction(this)
}
- override fun renderString(): String {
- val typeParameters = if (typeParameterCount == 0) "" else "<" + typeParameters.joinToString { it.renderString() } + "> "
- val valueParameters = valueParameters.joinToString { it.renderString() }
- val returnType = returnType?.let { ": " + it.renderString() } ?: ""
- val body = when (body) {
+ override fun renderString(): String = buildString {
+ appendWithSpace(visibility.name)
+ appendWithSpace(renderModifiers())
+ append("fun ")
+ if (typeParameterCount > 0) {
+ append('<').append(typeParameters.joinToString { it.renderString() }).append("> ")
+ }
+ append(name)
+ append('(')
+ append(valueParameters.joinToString() { it.renderString() })
+ append(')')
+ returnType?.let { append(": " + it.renderString()) }
+
+ val body = body
+ val bodyRendered = when (body) {
+ null -> ""
is UBlockExpression -> " " + body.renderString()
else -> " = " + body.renderString()
}
- return "${visibility.name} fun " + typeParameters + name + "(" + valueParameters + ")" + returnType + body
+ append(bodyRendered)
}
- override fun logString() = "UFunction ($name, kind = ${kind.text}, " +
- "paramCount = $valueParameterCount)\n" + body.logString().withMargin
+ override fun logString() = log("UFunction ($name, kind = ${kind.text}, paramCount = $valueParameterCount)", body)
}
object UFunctionNotResolved : UFunction {
- override val kind = UastFunctionKind("")
+ override val kind = UastFunctionKind(ERROR_NAME)
override val valueParameters = emptyList()
override val valueParameterCount = 0
override val typeParameters = emptyList()
override val typeParameterCount = 0
override val returnType = null
- override val body = EmptyExpression(this)
+ override val body = null
override val visibility = UastVisibility.PRIVATE
override val nameElement = null
override val parent = null
- override val name = ""
+ override val name = ERROR_NAME
override fun hasModifier(modifier: UastModifier) = false
override fun getSuperFunctions(context: UastContext) = emptyList()
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 beb39d81a81..74420f5003a 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/declarations/UImportStatement.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/declarations/UImportStatement.kt
@@ -15,19 +15,33 @@
*/
package org.jetbrains.uast
-import org.jetbrains.uast.kinds.UastImportKind
import org.jetbrains.uast.visitor.UastVisitor
+/**
+ * Represents an import statement.
+ */
interface UImportStatement : UElement {
+ /**
+ * Returns the qualified name to import.
+ */
val fqNameToImport: String?
- val isStarImport: Boolean
- val kind: UastImportKind
- /* Returns null if isStarImport = true */
+ /**
+ * Returns true is the import is a "star" import (on-demand, all-under).
+ */
+ val isStarImport: Boolean
+
+ /**
+ * Resolve the import statement to the declaration.
+ *
+ * @param context the Uast context
+ * @return the declaration element, or null if the declaration was not resolved.
+ */
fun resolve(context: UastContext): UDeclaration?
override fun accept(visitor: UastVisitor) {
visitor.visitImportStatement(this)
+ visitor.afterVisitImportStatement(this)
}
override fun logString() = "UImport ($fqNameToImport)"
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 2198f551c21..3f12e8259ac 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/declarations/UType.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/declarations/UType.kt
@@ -17,50 +17,105 @@ package org.jetbrains.uast
import org.jetbrains.uast.visitor.UastVisitor
+/**
+ * Represents the type.
+ * The abstraction is quite simple. Intersection types, union types, platform types are yet to be supported.
+ */
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 */
+ /**
+ * Returns the simple (non-qualified) type name.
+ * The simple type name is only for the debug purposes. Do not check against it in the production code.
+ */
override val name: String
- /* Semantics: returns true if the type is either a boxed or an unboxed, false otherwise */
+ /**
+ * Returns true if the type is either a boxed or an unboxed [Integer], false otherwise.
+ */
val isInt: Boolean
+
+ /**
+ * Returns true if the type is either a boxed or an unboxed [Short], false otherwise.
+ */
+ val isShort: Boolean
+
+ /**
+ * Returns true if the type is either a boxed or an unboxed [Long], false otherwise.
+ */
val isLong: Boolean
+
+ /**
+ * Returns true if the type is either a boxed or an unboxed [Float], false otherwise.
+ */
val isFloat: Boolean
+
+ /**
+ * Returns true if the type is either a boxed or an unboxed [Double], false otherwise.
+ */
val isDouble: Boolean
+
+ /**
+ * Returns true if the type is either a boxed or an unboxed [Character], false otherwise.
+ */
val isChar: Boolean
+
+ /**
+ * Returns true if the type is either a boxed or an unboxed [Boolean], false otherwise.
+ */
val isBoolean: Boolean
+
+ /**
+ * Returns true if the type is either a boxed or an unboxed [Byte], false otherwise.
+ */
val isByte: Boolean
override fun logString() = "UType ($name)"
override fun renderString() = name
+ /**
+ * Returns the [UClass] declaration element for this type.
+ *
+ * @param context the Uast context
+ * @return the [UClass] declaration element, or null if the class was not resolved.
+ */
override fun resolve(context: UastContext): UClass?
+
override fun resolveOrEmpty(context: UastContext) = resolve(context) ?: UClassNotResolved
override fun accept(visitor: UastVisitor) {
if (visitor.visitType(this)) return
annotations.acceptList(visitor)
+ visitor.afterVisitType(this)
}
}
+/**
+ * Represents a type reference.
+ */
interface UTypeReference : UDeclaration, UResolvable {
override fun renderString() = ""
override fun logString() = log("UTypeReference")
+ /**
+ * Returns the [UClass] declaration for this type reference.
+ *
+ * @param context the Uast context
+ * @return the [UClass] declaration element, or null if the class was not resolved.
+ */
override fun resolve(context: UastContext): UClass?
+
override fun resolveOrEmpty(context: UastContext) = resolve(context) ?: UClassNotResolved
}
object UastErrorType : UType, NoAnnotations {
override val isInt = false
override val isLong = false
+ override val isShort = false
override val isFloat = false
override val isDouble = false
override val isChar = false
override val isByte = false
override val parent = null
- override val name = ""
+ override val name = ERROR_NAME
override val fqName = null
override val isBoolean = false
override fun resolve(context: UastContext) = null
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 2b5346b3da7..c361535ae8b 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/declarations/UVariable.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/declarations/UVariable.kt
@@ -17,16 +17,26 @@ package org.jetbrains.uast
import org.jetbrains.uast.visitor.UastVisitor
-interface UVariable : UDeclaration, UModifierOwner, UAnnotated {
+interface UVariable : UDeclaration, UModifierOwner, UVisibilityOwner, UAnnotated {
+ /**
+ * Return the variable initializer (or the default value for value parameter), or null if the variable is not initialized.
+ */
val initializer: UExpression?
+
+ /**
+ * Return the variable kind.
+ */
val kind: UastVariableKind
+
+ /**
+ * Return the variable type.
+ */
val type: UType
- val visibility: UastVisibility
- open val getters: List?
- get() = null
-
- open val setters: List?
+ /**
+ * Return the list of accessors if the variable is a property, or null otherwise.
+ */
+ open val accessors: List?
get() = null
override fun accept(visitor: UastVisitor) {
@@ -35,13 +45,28 @@ interface UVariable : UDeclaration, UModifierOwner, UAnnotated {
initializer?.accept(visitor)
annotations.acceptList(visitor)
type.accept(visitor)
+ visitor.afterVisitVariable(this)
}
- override fun renderString(): String {
- val initializer = if (initializer != null && initializer !is EmptyExpression) " = ${initializer!!.renderString()}" else ""
- val prefix = if (kind == UastVariableKind.VALUE_PARAMETER) "" else "var "
- val emptyLine = if (kind == UastVariableKind.MEMBER) "\n" else ""
- return "$prefix$name: " + type.name + initializer + emptyLine
+ override fun renderString(): String = buildString {
+ if (kind != UastVariableKind.VALUE_PARAMETER) appendWithSpace(visibility.name)
+ appendWithSpace(renderModifiers())
+ if (kind != UastVariableKind.VALUE_PARAMETER) append("var ")
+ append(name)
+ append(": ")
+ append(type.name)
+ if (initializer != null && initializer !is EmptyUExpression) {
+ append(" = ")
+ append(initializer!!.renderString())
+ }
+
+ accessors?.let {
+ appendln()
+ it.forEachIndexed { i, accessor ->
+ this@buildString.append(accessor.renderString().withMargin)
+ if ((i + 1) < it.size) appendln()
+ }
+ }
}
override fun logString() = "UVariable ($name, kind = ${kind.name})\n" +
@@ -50,11 +75,11 @@ interface UVariable : UDeclaration, UModifierOwner, UAnnotated {
object UVariableNotResolved : UVariable {
override val initializer = null
- override val kind = UastVariableKind.MEMBER
+ override val kind = UastVariableKind(ERROR_NAME)
override val type = UastErrorType
override val nameElement = null
override val parent = null
- override val name = ""
+ override val name = ERROR_NAME
override val visibility = UastVisibility.LOCAL
override fun hasModifier(modifier: UastModifier) = false
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 d5529328e71..d422327d3df 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/expressions/UArrayAccessExpression.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/UArrayAccessExpression.kt
@@ -17,14 +17,25 @@ package org.jetbrains.uast
import org.jetbrains.uast.visitor.UastVisitor
+/**
+ * Represents `receiver[index0, ..., indexN]` expression.
+ */
interface UArrayAccessExpression : UExpression {
+ /**
+ * Returns the receiver expression.
+ */
val receiver: UExpression
+
+ /**
+ * Returns the list of index expressions.
+ */
val indices: List
override fun accept(visitor: UastVisitor) {
if (visitor.visitArrayAccessExpression(this)) return
receiver.accept(visitor)
indices.acceptList(visitor)
+ visitor.afterVisitArrayAccessExpression(this)
}
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 94a9601941b..88bbc193dae 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/expressions/UBinaryExpression.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/UBinaryExpression.kt
@@ -17,15 +17,30 @@ package org.jetbrains.uast
import org.jetbrains.uast.visitor.UastVisitor
+/**
+ * Represents a binary expression (value1 op value2), eg. `2 + "A"`.
+ */
interface UBinaryExpression : UExpression {
+ /**
+ * Returns the left operand.
+ */
val leftOperand: UExpression
+
+ /**
+ * Returns the binary operator.
+ */
val operator: UastBinaryOperator
+
+ /**
+ * Returns the right operand.
+ */
val rightOperand: UExpression
override fun accept(visitor: UastVisitor) {
if (visitor.visitBinaryExpression(this)) return
leftOperand.accept(visitor)
rightOperand.accept(visitor)
+ visitor.afterVisitBinaryExpression(this)
}
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 3561cac92ac..8d9fd5be3a7 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/expressions/UBinaryExpressionWithType.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/UBinaryExpressionWithType.kt
@@ -17,17 +17,32 @@ package org.jetbrains.uast
import org.jetbrains.uast.visitor.UastVisitor
+/**
+ * Represents a binary expression with type (value op type), e.g. ("A" instanceof String).
+ */
interface UBinaryExpressionWithType : UExpression {
+ /**
+ * Returns the operand expression.
+ */
val operand: UExpression
+
+ /**
+ * Returns the operation kind.
+ */
val operationKind: UastBinaryExpressionWithTypeKind
+
+ /**
+ * Returns the type.
+ */
val type: UType
override fun logString() = log("UBinaryExpressionWithType (${getExpressionType()?.name}, ${operationKind.name})", operand)
- override fun renderString() = "(${operand.renderString()}) ${operationKind.name} ${getExpressionType()?.name}"
+ override fun renderString() = "${operand.renderString()} ${operationKind.name} ${type.name}"
override fun accept(visitor: UastVisitor) {
if (visitor.visitBinaryExpressionWithType(this)) return
operand.accept(visitor)
type.accept(visitor)
+ visitor.afterVisitBinaryExpressionWithType(this)
}
}
\ 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 478ce438373..0e24b3ba099 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/expressions/UBlockExpression.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/UBlockExpression.kt
@@ -17,12 +17,19 @@ package org.jetbrains.uast
import org.jetbrains.uast.visitor.UastVisitor
+/**
+ * Represents the code block expression: `{ /* code */ }`.
+ */
interface UBlockExpression : UExpression {
+ /**
+ * Returns the list of block expressions.
+ */
val expressions: List
override fun accept(visitor: UastVisitor) {
if (visitor.visitBlockExpression(this)) return
expressions.acceptList(visitor)
+ visitor.afterVisitBlockExpression(this)
}
override fun logString() = log("UBlockExpression", expressions)
diff --git a/plugins/uast-common/src/org/jetbrains/uast/expressions/UBreakExpression.kt b/plugins/uast-common/src/org/jetbrains/uast/expressions/UBreakExpression.kt
new file mode 100644
index 00000000000..c68ae13d789
--- /dev/null
+++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/UBreakExpression.kt
@@ -0,0 +1,37 @@
+/*
+ * 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
+
+import org.jetbrains.uast.visitor.UastVisitor
+
+/**
+ * Represents a `break` expression.
+ */
+interface UBreakExpression : UExpression {
+ /**
+ * Returns the expression label, or null if the label is not specified.
+ */
+ val label: String?
+
+ override fun accept(visitor: UastVisitor) {
+ visitor.visitBreakExpression(this)
+ visitor.afterVisitBreakExpression(this)
+ }
+
+ override fun logString() = "UBreakExpression (" + (label ?: "") + ")"
+ override fun renderString() = label?.let { "break@$it" } ?: "break"
+}
\ No newline at end of file
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 c18fa7be054..b550bab0014 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/expressions/UCallExpression.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/UCallExpression.kt
@@ -17,25 +17,99 @@ package org.jetbrains.uast
import org.jetbrains.uast.visitor.UastVisitor
+/**
+ * Represents a call expression (function call, constructor call, array initializer).
+ */
interface UCallExpression : UExpression, UResolvable {
- val functionReference: USimpleReferenceExpression?
-
- val classReference: USimpleReferenceExpression?
-
- val functionName: String?
- val functionNameElement: UElement?
-
- fun functionNameMatches(name: String) = functionName == name
-
- val valueArgumentCount: Int
- val valueArguments: List
-
- val typeArgumentCount: Int
- val typeArguments: List
-
+ /**
+ * Returns the call kind.
+ */
val kind: UastCallKind
+ /**
+ * Returns the function reference expression if the call is a function call, null otherwise.
+ */
+ val functionReference: USimpleReferenceExpression?
+
+ /**
+ * Returns the class reference if the call is a constructor call, null otherwise.
+ */
+ val classReference: USimpleReferenceExpression?
+
+ /**
+ * Returns the function name if the call is a function call, null otherwise.
+ *
+ * [functionName] should only be used in debug messages.
+ * Use [matchesFunctionName] to check against the name.
+ */
+ val functionName: String?
+
+ /**
+ * Returns an element for the function name node, or null if the node does not exist in the underlying AST (Psi).
+ */
+ val functionNameElement: UElement?
+
+ /**
+ * Checks if the function name is [name].
+ *
+ * @param name the name to check against.
+ * @return true if the call is a function call, and the function name is [name], false otherwise.
+ */
+ open fun matchesFunctionName(name: String) = functionName == name
+
+ /**
+ * Checks if the function name is [name], and the function containing class qualified name is [containingClassFqName].
+ *
+ * @param containingClassFqName the required containing class qualified name.
+ * @param name the function name to check against.
+ * @return true if the call is a function call, the function name is [name],
+ * and the qualified name of the function direct containing class is [containingClassFqName],
+ * false otherwise.
+ */
+ open fun matchesFunctionNameWithContaining(containingClassFqName: String, name: String): Boolean {
+ if (!matchesFunctionName(name)) return false
+ val containingClass = parent as? UClass ?: return false
+ return containingClass.matchesFqName(containingClassFqName)
+ }
+
+ /**
+ * Returns the value argument count.
+ *
+ * Retrieving the argument count could be faster than getting the [valueArguments.size],
+ * because there is no need to create actual [UExpression] instances.
+ */
+ val valueArgumentCount: Int
+
+ /**
+ * Returns the list of value arguments.
+ */
+ val valueArguments: List
+
+ /**
+ * Returns the type argument count.
+ */
+ val typeArgumentCount: Int
+
+ /**
+ * Returns the function type arguments.
+ */
+ val typeArguments: List
+
+ /**
+ * Resolve the call to the [UFunction] element.
+ *
+ * @param context the Uast context
+ * @return the [UFunction] element, or null if the reference was not resolved.
+ */
override fun resolve(context: UastContext): UFunction?
+
+ /**
+ * Try to resolve the call to the [UFunction] element.
+ *
+ * @param context the Uast context
+ * @return the [UFunction] element, of [UFunctionNotResolved] if the reference was not resolved,
+ * or the call is not a function call.
+ */
override fun resolveOrEmpty(context: UastContext): UFunction = resolve(context) ?: UFunctionNotResolved
override fun accept(visitor: UastVisitor) {
@@ -45,11 +119,12 @@ interface UCallExpression : UExpression, UResolvable {
functionNameElement?.accept(visitor)
valueArguments.acceptList(visitor)
typeArguments.acceptList(visitor)
+ visitor.afterVisitCallExpression(this)
}
override fun logString() = log("UFunctionCallExpression ($kind, argCount = $valueArgumentCount)", functionReference, valueArguments)
override fun renderString(): String {
- val ref = functionName ?: functionReference?.renderString() ?: classReference?.renderString() ?: ""
+ val ref = functionName ?: classReference?.renderString() ?: functionReference?.renderString() ?: ""
return ref + "(" + valueArguments.joinToString { it.renderString() } + ")"
}
}
\ No newline at end of file
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 010c47a9876..27c23ce73aa 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/expressions/UCallableReferenceExpression.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/UCallableReferenceExpression.kt
@@ -17,14 +17,42 @@ package org.jetbrains.uast
import org.jetbrains.uast.visitor.UastVisitor
-interface UCallableReferenceExpression : UExpression {
- val qualifierType: UType
+/**
+ * Represents a callable reference expression, e.g. `Clazz::functionName`.
+ */
+interface UCallableReferenceExpression : UExpression, UResolvable {
+ /**
+ * Returns the qualifier expression.
+ * Can be null if the [qualifierType] is known.
+ */
+ val qualifierExpression: UExpression?
+
+ /**
+ * Returns the qualifier type.
+ * Can be null if the qualifier is an expression.
+ */
+ val qualifierType: UType?
+
+ /**
+ * Returns the callable name.
+ */
+ val callableName: String
override fun accept(visitor: UastVisitor) {
if (visitor.visitCallableReferenceExpression(this)) return
- qualifierType.accept(visitor)
+ qualifierExpression?.accept(visitor)
+ qualifierType?.accept(visitor)
+ visitor.afterVisitCallableReferenceExpression(this)
}
override fun logString() = "UCallableReferenceExpression"
- override fun renderString() = "::" + qualifierType.name
+ override fun renderString() = buildString {
+ qualifierExpression?.let {
+ append(it.renderString())
+ } ?: qualifierType?.let {
+ append(it.name)
+ }
+ append("::")
+ append(callableName)
+ }
}
\ No newline at end of file
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 46c39fdda32..807b0d4a06d 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/expressions/UClassLiteralExpression.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/UClassLiteralExpression.kt
@@ -17,13 +17,20 @@ package org.jetbrains.uast
import org.jetbrains.uast.visitor.UastVisitor
+/**
+ * Represents the class literal expression, e.g. `Clazz.class`.
+ */
interface UClassLiteralExpression : UExpression {
override fun logString() = "UClassLiteralExpression"
- override fun renderString() = getExpressionType()?.name ?: "::class"
+ override fun renderString() = type.name + "::class"
+ /**
+ * Returns the type for this class literal expression.
+ */
val type: UType
override fun accept(visitor: UastVisitor) {
visitor.visitClassLiteralExpression(this)
+ visitor.afterVisitClassLiteralExpression(this)
}
}
\ No newline at end of file
diff --git a/plugins/uast-common/src/org/jetbrains/uast/expressions/UContinueExpression.kt b/plugins/uast-common/src/org/jetbrains/uast/expressions/UContinueExpression.kt
new file mode 100644
index 00000000000..a560e632d61
--- /dev/null
+++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/UContinueExpression.kt
@@ -0,0 +1,37 @@
+/*
+ * 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
+
+import org.jetbrains.uast.visitor.UastVisitor
+
+/**
+ * Represents a `continue` expression.
+ */
+interface UContinueExpression : UExpression {
+ /**
+ * Returns the expression label, or null if the label is not specified.
+ */
+ val label: String?
+
+ override fun accept(visitor: UastVisitor) {
+ visitor.visitContinueExpression(this)
+ visitor.afterVisitContinueExpression(this)
+ }
+
+ override fun logString() = "UContinueExpression (" + (label ?: "") + ")"
+ override fun renderString() = label?.let { "continue@$it" } ?: "continue"
+}
\ 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 e43066a7882..b9d09823eb9 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/expressions/UDeclarationsExpression.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/UDeclarationsExpression.kt
@@ -17,15 +17,26 @@ package org.jetbrains.uast
import org.jetbrains.uast.visitor.UastVisitor
+/**
+ * Represents a list of declarations.
+ * Example in Java: `int a = 4, b = 3`.
+ */
interface UDeclarationsExpression : UExpression {
+ /**
+ * Returns the list of declarations inside this [UDeclarationsExpression].
+ */
val declarations: List
+ /**
+ * Returns the list of variables inside this [UDeclarationsExpression].
+ */
val variables: List
get() = declarations.filterIsInstance()
override fun accept(visitor: UastVisitor) {
if (visitor.visitDeclarationsExpression(this)) return
declarations.acceptList(visitor)
+ visitor.afterVisitDeclarationsExpression(this)
}
override fun renderString() = declarations.joinToString("\n") { it.renderString() }
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 e220b8fa6e2..220dec6f324 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/expressions/UExpressionList.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/UExpressionList.kt
@@ -17,21 +17,26 @@ package org.jetbrains.uast
import org.jetbrains.uast.visitor.UastVisitor
-interface UExpressionList : UExpression {
+/**
+ * Represents a generic list of expressions.
+ */
+interface USpecialExpressionList : UExpression {
+ /**
+ * Returns the list of expressions.
+ */
val expressions: List
- override fun accept(visitor: UastVisitor) {
- if (visitor.visitExpressionList(this)) return
- expressions.acceptList(visitor)
- }
-
- override fun logString() = log("UExpressionList", expressions)
- override fun renderString() = log("", expressions)
-}
-
-interface USpecialExpressionList : UExpressionList {
+ /**
+ * Returns the list kind.
+ */
val kind: UastSpecialExpressionKind
+ override fun accept(visitor: UastVisitor) {
+ if (visitor.visitSpecialExpressionList(this)) return
+ expressions.acceptList(visitor)
+ visitor.afterVisitSpecialExpressionList(this)
+ }
+
fun firstOrNull(): UExpression? = expressions.firstOrNull()
override fun logString() = log("USpecialExpressionList (${kind.name})", 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 fcf35b620e1..156fce62ef2 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/expressions/ULabeledExpression.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/ULabeledExpression.kt
@@ -17,13 +17,24 @@ package org.jetbrains.uast
import org.jetbrains.uast.visitor.UastVisitor
+/**
+ * Represents an expression with the label specified.
+ */
interface ULabeledExpression : UExpression {
+ /**
+ * Returns the expression label.
+ */
val label: String
+
+ /**
+ * Returns the expression itself.
+ */
val expression: UExpression
override fun accept(visitor: UastVisitor) {
if (visitor.visitLabeledExpression(this)) return
expression.accept(visitor)
+ visitor.afterVisitLabeledExpression(this)
}
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 9766c51dfc4..e35a4222b15 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/expressions/ULambdaExpression.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/ULambdaExpression.kt
@@ -17,14 +17,25 @@ package org.jetbrains.uast
import org.jetbrains.uast.visitor.UastVisitor
+/**
+ * Represents the lambda expression.
+ */
interface ULambdaExpression : UExpression {
+ /**
+ * Returns the list of lambda value parameters.
+ */
val valueParameters: List
+
+ /**
+ * Returns the lambda body expression.
+ */
val body: UExpression
override fun accept(visitor: UastVisitor) {
if (visitor.visitLambdaExpression(this)) return
valueParameters.acceptList(visitor)
body.accept(visitor)
+ visitor.afterVisitLambdaExpression(this)
}
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 2ac3cfa58e8..8e4f5048005 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/expressions/ULiteralExpression.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/ULiteralExpression.kt
@@ -17,23 +17,51 @@ package org.jetbrains.uast
import org.jetbrains.uast.visitor.UastVisitor
+/**
+ * Represents a literal expression.
+ */
interface ULiteralExpression : UExpression {
+ /**
+ * Returns the literal expression value.
+ * This is basically a String, Number or null if the literal is a `null` literal.
+ */
val value: Any?
+ /**
+ * Returns true if the literal is a `null`-literal, false otherwise.
+ */
val isNull: Boolean
+ /**
+ * Returns true if the literal is a [String] literal, false otherwise.
+ */
val isString: Boolean
get() = evaluate() is String
+ /**
+ * Returns true if the literal is a [Boolean] literal, false otherwise.
+ */
val isBoolean: Boolean
get() = evaluate() is Boolean
- fun asString() = value?.toString() ?: ""
+ /**
+ * Returns the string representation of the literal expression.
+ *
+ * @return the string representation, or "null" if the literal is a "null"-literal.
+ */
+ fun asString(): String {
+ val value = value
+ return if (value == null)
+ "null"
+ else
+ value.toString()
+ }
override fun accept(visitor: UastVisitor) {
visitor.visitLiteralExpression(this)
+ visitor.afterVisitLiteralExpression(this)
}
override fun logString() = "ULiteralExpression (${asString()})"
- override fun renderString() = asString()
+ override fun renderString() = if (value is String) "\"$value\"" else 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 0b9c2a6e871..03743129934 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/expressions/UNamedExpression.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/UNamedExpression.kt
@@ -26,6 +26,7 @@ class UNamedExpression(
override fun accept(visitor: UastVisitor) {
if (visitor.visitElement(this)) return
expression.accept(visitor)
+ visitor.afterVisitElement(this)
}
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 5e153d3ea7b..b7806d4a974 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/expressions/UObjectLiteralExpression.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/UObjectLiteralExpression.kt
@@ -17,12 +17,19 @@ package org.jetbrains.uast
import org.jetbrains.uast.visitor.UastVisitor
+/**
+ * Represents an object literal expression, e.g. `new Runnable() {}` in Java.
+ */
interface UObjectLiteralExpression : UExpression {
+ /**
+ * Returns the class declaration.
+ */
val declaration: UClass
override fun accept(visitor: UastVisitor) {
if (visitor.visitObjectLiteralExpression(this)) return
declaration.accept(visitor)
+ visitor.afterVisitObjectLiteralExpression(this)
}
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 a03ac041278..47a96f996bb 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/expressions/UParenthesizedExpression.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/UParenthesizedExpression.kt
@@ -17,12 +17,19 @@ package org.jetbrains.uast
import org.jetbrains.uast.visitor.UastVisitor
+/**
+ * Represents a parenthesized expression, e.g. `(23 + 3)`.
+ */
interface UParenthesizedExpression : UExpression {
+ /**
+ * Returns an expression inside the parenthesis.
+ */
val expression: UExpression
override fun accept(visitor: UastVisitor) {
if (visitor.visitParenthesizedExpression(this)) return
expression.accept(visitor)
+ visitor.afterVisitParenthesizedExpression(this)
}
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 93972c70759..ee842be7b41 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/expressions/UQualifiedExpression.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/UQualifiedExpression.kt
@@ -17,19 +17,48 @@ package org.jetbrains.uast
import org.jetbrains.uast.visitor.UastVisitor
+/**
+ * Represents the qualified expression (receiver.selector).
+ */
interface UQualifiedExpression : UExpression, UResolvable {
+ /**
+ * Returns the expression receiver.
+ */
val receiver: UExpression
+
+ /**
+ * Returns the expression selector.
+ */
val selector: UExpression
+
+ /**
+ * Returns the access type (simple, safe access, etc.).
+ */
val accessType: UastQualifiedExpressionAccessType
+ /**
+ * Checks if the selector is a simple reference expression, and if its identifier is [identifier].
+ *
+ * @param identifier the identifier to check agains
+ * @return true if the selector is a simple reference expression, and if its identifier is [identifier],
+ * false otherwise
+ */
fun selectorMatches(identifier: String) = (selector as? USimpleReferenceExpression)?.identifier == identifier
+ /**
+ * Returns the selector identifier if the selector is a simple reference expression.
+ *
+ * @return the selector identifier if the selector is a simple reference expression, null otherwise.
+ */
+ fun getSelectorAsIdentifier(): String? = (selector as? USimpleReferenceExpression)?.identifier
+
override fun renderString() = receiver.renderString() + accessType.name + selector.renderString()
override fun accept(visitor: UastVisitor) {
if (visitor.visitQualifiedExpression(this)) return
receiver.accept(visitor)
selector.accept(visitor)
+ visitor.afterVisitQualifiedExpression(this)
}
override fun logString() = log("UQualifiedExpression", receiver, selector)
diff --git a/plugins/uast-common/src/org/jetbrains/uast/expressions/UReturnExpression.kt b/plugins/uast-common/src/org/jetbrains/uast/expressions/UReturnExpression.kt
new file mode 100644
index 00000000000..87dd8148d94
--- /dev/null
+++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/UReturnExpression.kt
@@ -0,0 +1,38 @@
+/*
+ * 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
+
+import org.jetbrains.uast.visitor.UastVisitor
+
+/**
+ * Represents a `return` expression.
+ */
+interface UReturnExpression : UExpression {
+ /**
+ * Returns the `return` value.
+ */
+ val returnExpression: UExpression?
+
+ override fun accept(visitor: UastVisitor) {
+ if (visitor.visitReturnExpression(this)) return
+ returnExpression?.accept(visitor)
+ visitor.afterVisitReturnExpression(this)
+ }
+
+ override fun renderString() = returnExpression.let { if (it == null) "return" else "return " + it.renderString() }
+ override fun logString() = log("UReturnExpression", returnExpression)
+}
\ No newline at end of file
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 4cf4ab38dd5..32ec7a9748d 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/expressions/USimpleReferenceExpression.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/USimpleReferenceExpression.kt
@@ -17,11 +17,18 @@ package org.jetbrains.uast
import org.jetbrains.uast.visitor.UastVisitor
+/**
+ * Represents a simple reference expression (a non-qualified identifier).
+ */
interface USimpleReferenceExpression : UExpression, UResolvable {
+ /**
+ * Returns the identifier name.
+ */
val identifier: String
override fun accept(visitor: UastVisitor) {
visitor.visitSimpleReferenceExpression(this)
+ visitor.afterVisitSimpleReferenceExpression(this)
}
override fun logString() = "USimpleReferenceExpression ($identifier)"
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 2edf91a02a4..867d510a35e 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/expressions/USuperExpression.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/USuperExpression.kt
@@ -17,11 +17,16 @@ package org.jetbrains.uast
import org.jetbrains.uast.visitor.UastVisitor
+/**
+ * Represents a `super` expression.
+ * Qualified `super` is not supported at the moment.
+ */
interface USuperExpression : UExpression {
override fun logString() = "USuperExpression"
override fun renderString() = "super"
override fun accept(visitor: UastVisitor) {
visitor.visitSuperExpression(this)
+ visitor.afterVisitSuperExpression(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 bb82dc8ee58..cd16221e92d 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/expressions/UThisExpression.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/UThisExpression.kt
@@ -17,11 +17,16 @@ package org.jetbrains.uast
import org.jetbrains.uast.visitor.UastVisitor
+/**
+ * Represents a `this` expression.
+ * Qualified `this` is not supported at the moment.
+ */
interface UThisExpression : UExpression {
override fun logString() = "UThisExpression"
override fun renderString() = "this"
override fun accept(visitor: UastVisitor) {
visitor.visitThisExpression(this)
+ visitor.afterVisitThisExpression(this)
}
}
\ No newline at end of file
diff --git a/plugins/uast-common/src/org/jetbrains/uast/expressions/UThrowExpression.kt b/plugins/uast-common/src/org/jetbrains/uast/expressions/UThrowExpression.kt
new file mode 100644
index 00000000000..bd78321e2d3
--- /dev/null
+++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/UThrowExpression.kt
@@ -0,0 +1,39 @@
+/*
+ * 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
+
+import org.jetbrains.uast.visitor.UastVisitor
+
+/**
+ * Represents a `throw` expression.
+ */
+interface UThrowExpression : UExpression {
+ /**
+ * Returns ths thrown expression.
+ */
+ val thrownExpression: UExpression
+
+ override fun accept(visitor: UastVisitor) {
+ if (visitor.visitThrowExpression(this)) return
+ thrownExpression.accept(visitor)
+ visitor.afterVisitThrowExpression(this)
+ }
+
+ override fun renderString() = "throw " + thrownExpression.renderString()
+
+ override fun logString() = log("UThrowExpression", thrownExpression)
+}
\ 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 3e3411a95bf..512f9383ff4 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/expressions/UUnaryExpression.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/UUnaryExpression.kt
@@ -15,7 +15,6 @@
*/
package org.jetbrains.uast
-import org.jetbrains.uast.kinds.UastOperator
import org.jetbrains.uast.visitor.UastVisitor
interface UUnaryExpression : UExpression {
@@ -25,6 +24,7 @@ interface UUnaryExpression : UExpression {
override fun accept(visitor: UastVisitor) {
if (visitor.visitUnaryExpression(this)) return
operand.accept(visitor)
+ visitor.afterVisitUnaryExpression(this)
}
}
@@ -34,6 +34,7 @@ interface UPrefixExpression : UUnaryExpression {
override fun accept(visitor: UastVisitor) {
if (visitor.visitPrefixExpression(this)) return
operand.accept(visitor)
+ visitor.afterVisitPrefixExpression(this)
}
override fun logString() = log("UPrefixExpression (${operator.text})", operand)
@@ -46,6 +47,7 @@ interface UPostfixExpression : UUnaryExpression {
override fun accept(visitor: UastVisitor) {
if (visitor.visitPostfixExpression(this)) return
operand.accept(visitor)
+ visitor.afterVisitPostfixExpression(this)
}
override fun logString() = log("UPostfixExpression (${operator.text})", operand)
diff --git a/plugins/uast-common/src/org/jetbrains/uast/expressions/uastLiteralUtils.kt b/plugins/uast-common/src/org/jetbrains/uast/expressions/uastLiteralUtils.kt
index 087be8bcc76..557809aca6c 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/expressions/uastLiteralUtils.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/expressions/uastLiteralUtils.kt
@@ -16,15 +16,40 @@
@file:JvmName("UastLiteralUtils")
package org.jetbrains.uast
+/**
+ * Checks if the [UElement] is a null literal.
+ *
+ * @return true if the receiver is a null literal, false otherwise.
+ */
fun UElement.isNullLiteral(): Boolean = this is ULiteralExpression && this.isNull
+/**
+ * Checks if the [UElement] is a [String] literal.
+ *
+ * @return true if the receiver is a [String] literal, false otherwise.
+ */
fun UElement.isStringLiteral(): Boolean = this is ULiteralExpression && this.isString
+/**
+ * Returns the [String] literal value.
+ *
+ * @return literal text if the receiver is a valid [String] literal, null otherwise.
+ */
fun UElement.getValueIfStringLiteral(): String? =
if (isStringLiteral()) (this as ULiteralExpression).value as String else null
+/**
+ * Checks if the [UElement] is a [Number] literal (Integer, Long, Float, Double, etc.).
+ *
+ * @return true if the receiver is a [Number] literal, false otherwise.
+ */
fun UElement.isNumberLiteral(): Boolean = this is ULiteralExpression && this.value is Number
+/**
+ * Checks if the [UElement] is an integral literal (is an [Integer], [Long], [Short], [Char] or [Byte]).
+ *
+ * @return true if the receiver is an integral literal, false otherwise.
+ */
fun UElement.isIntegralLiteral(): Boolean = this is ULiteralExpression && when (value) {
is Int -> true
is Long -> true
@@ -34,8 +59,12 @@ fun UElement.isIntegralLiteral(): Boolean = this is ULiteralExpression && when (
else -> false
}
-fun UElement.isBooleanLiteral(): Boolean = this is ULiteralExpression && this.isBoolean
-
+/**
+ * Returns the integral value of the literal.
+ *
+ * @return long representation of the literal expression value,
+ * 0 if the receiver literal expression is not a integral one.
+ */
fun ULiteralExpression.getLongValue(): Long = value.let {
when (it) {
is Long -> it
diff --git a/plugins/uast-common/src/org/jetbrains/uast/internal/internalUastUtils.kt b/plugins/uast-common/src/org/jetbrains/uast/internal/internalUastUtils.kt
index 6a585432c06..60d8a0823e9 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/internal/internalUastUtils.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/internal/internalUastUtils.kt
@@ -15,4 +15,15 @@
*/
package org.jetbrains.uast
-internal fun List.logString() = joinToString("\n") { it.logString().withMargin }
\ No newline at end of file
+internal fun List.logString() = joinToString("\n") { it.logString().withMargin }
+
+internal fun UModifierOwner.renderModifiers() = UastModifier.VALUES
+ .filter { hasModifier(it) }
+ .joinToString(" ") { it.name }
+
+internal fun StringBuilder.appendWithSpace(s: String) {
+ if (s.isNotEmpty()) {
+ append(s)
+ append(' ')
+ }
+}
\ No newline at end of file
diff --git a/plugins/uast-common/src/org/jetbrains/uast/kinds/UastBinaryExpressionWithTypeKind.kt b/plugins/uast-common/src/org/jetbrains/uast/kinds/UastBinaryExpressionWithTypeKind.kt
index 93643a3c1fb..dc73b665dde 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/kinds/UastBinaryExpressionWithTypeKind.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/kinds/UastBinaryExpressionWithTypeKind.kt
@@ -16,6 +16,10 @@
@file:JvmName("UastBinaryExpressionWithTypeUtils")
package org.jetbrains.uast
+/**
+ * Kinds of [UBinaryExpressionWithType].
+ * Examples: type casts, instance checks.
+ */
open class UastBinaryExpressionWithTypeKind(val name: String) {
open class TypeCast(name: String) : UastBinaryExpressionWithTypeKind(name)
open class InstanceCheck(name: String) : UastBinaryExpressionWithTypeKind(name)
diff --git a/plugins/uast-common/src/org/jetbrains/uast/kinds/UastBinaryOperator.kt b/plugins/uast-common/src/org/jetbrains/uast/kinds/UastBinaryOperator.kt
index 8f0bef29f0d..7e24a472970 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/kinds/UastBinaryOperator.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/kinds/UastBinaryOperator.kt
@@ -15,8 +15,9 @@
*/
package org.jetbrains.uast
-import org.jetbrains.uast.kinds.UastOperator
-
+/**
+ * Kinds of operators in [UBinaryExpression].
+ */
open class UastBinaryOperator(override val text: String): UastOperator {
class LogicalOperator(text: String): UastBinaryOperator(text)
class ComparationOperator(text: String): UastBinaryOperator(text)
@@ -105,7 +106,7 @@ open class UastBinaryOperator(override val text: String): UastOperator {
@JvmField
val DIVIDE_ASSIGN = AssignOperator("/=")
-
+
@JvmField
val REMAINDER_ASSIGN = AssignOperator("%=")
diff --git a/plugins/uast-common/src/org/jetbrains/uast/kinds/UastCallKind.kt b/plugins/uast-common/src/org/jetbrains/uast/kinds/UastCallKind.kt
index 43f4e295f9d..c99e9b9004b 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/kinds/UastCallKind.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/kinds/UastCallKind.kt
@@ -15,13 +15,19 @@
*/
package org.jetbrains.uast
-class UastCallKind(val name: String) {
+/**
+ * Kinds of [UCallExpression].
+ */
+open class UastCallKind(val name: String) {
companion object {
@JvmField
val FUNCTION_CALL = UastCallKind("function_call")
@JvmField
val CONSTRUCTOR_CALL = UastCallKind("constructor_call")
+
+ @JvmField
+ val ARRAY_INITIALIZER = UastCallKind("array_initializer")
}
override fun toString(): String{
diff --git a/plugins/uast-common/src/org/jetbrains/uast/kinds/UastClassKind.kt b/plugins/uast-common/src/org/jetbrains/uast/kinds/UastClassKind.kt
index 6f6319c6533..d8d9bb44db4 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/kinds/UastClassKind.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/kinds/UastClassKind.kt
@@ -14,11 +14,12 @@
* limitations under the License.
*/
-package org.jetbrains.uast.kinds
+package org.jetbrains.uast
+/**
+ * Kinds of [UClass].
+ */
open class UastClassKind(val text: String) {
- class UastCompanionObject(val default: Boolean) : UastClassKind("companion object")
-
companion object {
@JvmField
val CLASS = UastClassKind("class")
diff --git a/plugins/uast-common/src/org/jetbrains/uast/kinds/UastFunctionKind.kt b/plugins/uast-common/src/org/jetbrains/uast/kinds/UastFunctionKind.kt
index a5584de91bb..6e229ca2f05 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/kinds/UastFunctionKind.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/kinds/UastFunctionKind.kt
@@ -15,6 +15,9 @@
*/
package org.jetbrains.uast
+/**
+ * Kinds of [UFunction].
+ */
open class UastFunctionKind(val text: String) {
class UastInitializerKind(val name: String) : UastFunctionKind("INITIALIZER ($name)")
class UastVariableAccessor(val name: String) : UastFunctionKind(name)
diff --git a/plugins/uast-common/src/org/jetbrains/uast/kinds/UastModifier.kt b/plugins/uast-common/src/org/jetbrains/uast/kinds/UastModifier.kt
index ad63533cea1..973a1fa63d9 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/kinds/UastModifier.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/kinds/UastModifier.kt
@@ -15,7 +15,12 @@
*/
package org.jetbrains.uast
-class UastModifier(val name: String) {
+/**
+ * Uast declaration modifiers.
+ *
+ * @see UModifierOwner
+ */
+open class UastModifier(val name: String) {
companion object {
@JvmField
val ABSTRACT = UastModifier("abstract")
@@ -24,9 +29,13 @@ class UastModifier(val name: String) {
@JvmField
val FINAL = UastModifier("final")
@JvmField
+ val IMMUTABLE = UastModifier("immutable")
+ @JvmField
val VARARG = UastModifier("vararg")
@JvmField
val OVERRIDE = UastModifier("override")
+
+ val VALUES = listOf(ABSTRACT, STATIC, FINAL, IMMUTABLE, VARARG, OVERRIDE)
}
override fun toString(): String{
diff --git a/plugins/uast-common/src/org/jetbrains/uast/kinds/UastOperator.kt b/plugins/uast-common/src/org/jetbrains/uast/kinds/UastOperator.kt
index 72022aa9087..968bd4656e8 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/kinds/UastOperator.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/kinds/UastOperator.kt
@@ -13,8 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.jetbrains.uast.kinds
+package org.jetbrains.uast
+/**
+ * Uast operator base inteface.
+ *
+ * @see [UastPrefixOperator], [UastPostfixOperator], [UastBinaryOperator]
+ */
interface UastOperator {
+ /**
+ * Returns the operator text to render in [UElement.renderString].
+ */
val text: String
}
\ No newline at end of file
diff --git a/plugins/uast-common/src/org/jetbrains/uast/kinds/UastPostfixOperator.kt b/plugins/uast-common/src/org/jetbrains/uast/kinds/UastPostfixOperator.kt
index c2ef7e1913b..1fbd2af5773 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/kinds/UastPostfixOperator.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/kinds/UastPostfixOperator.kt
@@ -15,9 +15,10 @@
*/
package org.jetbrains.uast
-import org.jetbrains.uast.kinds.UastOperator
-
-class UastPostfixOperator(override val text: String): UastOperator {
+/**
+ * [UPostfixExpression] operators.
+ */
+open class UastPostfixOperator(override val text: String): UastOperator {
companion object {
@JvmField
val INC = UastPostfixOperator("++")
diff --git a/plugins/uast-common/src/org/jetbrains/uast/kinds/UastPrefixOperator.kt b/plugins/uast-common/src/org/jetbrains/uast/kinds/UastPrefixOperator.kt
index 3bdc50cc2c3..e4f021998ce 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/kinds/UastPrefixOperator.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/kinds/UastPrefixOperator.kt
@@ -15,8 +15,9 @@
*/
package org.jetbrains.uast
-import org.jetbrains.uast.kinds.UastOperator
-
+/**
+ * [UPrefixExpression] operators.
+ */
class UastPrefixOperator(override val text: String): UastOperator {
companion object {
@JvmField
diff --git a/plugins/uast-common/src/org/jetbrains/uast/kinds/UastQualifiedExpressionAccessType.kt b/plugins/uast-common/src/org/jetbrains/uast/kinds/UastQualifiedExpressionAccessType.kt
index 4e4d01d94b7..b2b3968a029 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/kinds/UastQualifiedExpressionAccessType.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/kinds/UastQualifiedExpressionAccessType.kt
@@ -15,7 +15,11 @@
*/
package org.jetbrains.uast
-class UastQualifiedExpressionAccessType(val name: String) {
+/**
+ * Access types of [UQualifiedExpression].
+ * Additional type examples: Kotlin safe call (?.).
+ */
+open class UastQualifiedExpressionAccessType(val name: String) {
companion object {
@JvmField
val SIMPLE = UastQualifiedExpressionAccessType(".")
diff --git a/plugins/uast-common/src/org/jetbrains/uast/kinds/UastSpecialExpressionKind.kt b/plugins/uast-common/src/org/jetbrains/uast/kinds/UastSpecialExpressionKind.kt
index 369d3f8e443..162eebac8a9 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/kinds/UastSpecialExpressionKind.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/kinds/UastSpecialExpressionKind.kt
@@ -15,21 +15,10 @@
*/
package org.jetbrains.uast
-class UastSpecialExpressionKind(val name: String) {
- companion object {
- @JvmField
- val RETURN = UastSpecialExpressionKind("return")
-
- @JvmField
- val THROW = UastSpecialExpressionKind("throw")
-
- @JvmField
- val BREAK = UastSpecialExpressionKind("break")
-
- @JvmField
- val CONTINUE = UastSpecialExpressionKind("continue")
- }
-
+/**
+ * Kinds of [USpecialExpressionList].
+ */
+open class UastSpecialExpressionKind(val name: String) {
override fun toString(): String{
return "UastSpecialExpressionKind(name='$name')"
}
diff --git a/plugins/uast-common/src/org/jetbrains/uast/kinds/UastVariableKind.kt b/plugins/uast-common/src/org/jetbrains/uast/kinds/UastVariableKind.kt
index 823bc4e86fb..fb997b903c5 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/kinds/UastVariableKind.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/kinds/UastVariableKind.kt
@@ -15,7 +15,10 @@
*/
package org.jetbrains.uast
-class UastVariableKind(val name: String) {
+/**
+ * Kinds of [UVariable].
+ */
+open class UastVariableKind(val name: String) {
companion object {
@JvmField
val LOCAL_VARIABLE = UastVariableKind("local")
diff --git a/plugins/uast-common/src/org/jetbrains/uast/kinds/UastVisibility.kt b/plugins/uast-common/src/org/jetbrains/uast/kinds/UastVisibility.kt
index 188f5ee83ac..4bbe5d69f1e 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/kinds/UastVisibility.kt
+++ b/plugins/uast-common/src/org/jetbrains/uast/kinds/UastVisibility.kt
@@ -15,7 +15,10 @@
*/
package org.jetbrains.uast
-class UastVisibility(val name: String) {
+/**
+ * Uast visibility list.
+ */
+open class UastVisibility(val name: String) {
companion object {
@JvmField
val PUBLIC = UastVisibility("public")
diff --git a/plugins/uast-java/src/org/jetbrains/uast/java/JavaUastLanguagePlugin.kt b/plugins/uast-java/src/org/jetbrains/uast/java/JavaUastLanguagePlugin.kt
index c6c8af85642..2c732164324 100644
--- a/plugins/uast-java/src/org/jetbrains/uast/java/JavaUastLanguagePlugin.kt
+++ b/plugins/uast-java/src/org/jetbrains/uast/java/JavaUastLanguagePlugin.kt
@@ -18,6 +18,7 @@ package org.jetbrains.uast.java
import com.intellij.psi.*
import org.jetbrains.uast.*
+import org.jetbrains.uast.java.expressions.JavaUSynchronizedExpression
object JavaUastLanguagePlugin : UastLanguagePlugin {
override val converter: UastConverter = JavaConverter
@@ -45,8 +46,6 @@ internal object JavaConverter : UastConverter {
return convertPsiElement(element, parentUElement)
}
- fun convertAnnotation(annotation: PsiAnnotation) = convertWithParent(annotation) as UAnnotation
-
private fun convertPsiElement(element: PsiElement?, parent: UElement) = when (element) {
is PsiJavaFile -> JavaUFile(element)
is PsiClass -> JavaUClass(element, parent)
@@ -115,7 +114,7 @@ internal object JavaConverter : UastConverter {
val referenceNameElement = expression.element ?: expression
return JavaUCompositeQualifiedExpression(parent).apply {
- receiver = expression.qualifier?.let { convert(it, this) } as? UExpression ?: EmptyExpression(parent)
+ receiver = expression.qualifier?.let { convert(it, this) } as? UExpression ?: EmptyUExpression(parent)
selector = JavaUSimpleReferenceExpression(referenceNameElement, referenceName, this)
}
}
@@ -185,42 +184,30 @@ internal object JavaConverter : UastConverter {
is PsiSwitchStatement -> JavaUSwitchExpression(statement, parent)
is PsiSwitchLabelStatement -> {
if (statement.isDefaultCase)
- SimpleUDefaultSwitchClauseExpression(parent)
- else JavaUExpressionSwitchClauseExpression(statement, parent)
+ DefaultUSwitchClauseExpression(parent)
+ else JavaUCaseSwitchClauseExpression(statement, parent)
}
is PsiWhileStatement -> JavaUWhileExpression(statement, parent)
is PsiDoWhileStatement -> JavaUDoWhileExpression(statement, parent)
is PsiForStatement -> JavaUForExpression(statement, parent)
is PsiForeachStatement -> JavaUForEachExpression(statement, parent)
- is PsiBreakStatement -> JavaUSpecialExpressionList.Empty(statement, UastSpecialExpressionKind.BREAK, parent)
- is PsiContinueStatement -> JavaUSpecialExpressionList.Empty(statement, UastSpecialExpressionKind.CONTINUE, parent)
- is PsiReturnStatement -> JavaUSpecialExpressionList(statement, UastSpecialExpressionKind.RETURN, parent).apply {
- expressions = singletonListOrEmpty(convertOrNull(statement.returnValue, this))
- }
- is PsiAssertStatement -> JavaUSpecialExpressionList(statement, JavaSpecialExpressionKinds.ASSERT, parent).apply {
- expressions = listOf(
- convertOrEmpty(statement.assertCondition, this),
- convertOrEmpty(statement.assertDescription, this))
- }
- is PsiThrowStatement -> JavaUSpecialExpressionList(statement, UastSpecialExpressionKind.THROW, parent).apply {
- expressions = singletonListOrEmpty(convertOrNull(statement.exception, this))
- }
- is PsiSynchronizedStatement -> JavaUSpecialExpressionList(statement, JavaSpecialExpressionKinds.SYNCHRONIZED, parent).apply {
- expressions = listOf(
- convertOrEmpty(statement.lockExpression, this),
- convertOrEmpty(statement.body, this))
- }
+ is PsiBreakStatement -> JavaUBreakExpression(statement, parent)
+ is PsiContinueStatement -> JavaUContinueExpression(statement, parent)
+ is PsiReturnStatement -> JavaUReturnExpression(statement, parent)
+ is PsiAssertStatement -> JavaUAssertExpression(statement, parent)
+ is PsiThrowStatement -> JavaUThrowExpression(statement, parent)
+ is PsiSynchronizedStatement -> JavaUSynchronizedExpression(statement, parent)
is PsiTryStatement -> JavaUTryExpression(statement, parent)
else -> UnknownJavaExpression(statement, parent)
}
internal fun convertOrEmpty(statement: PsiStatement?, parent: UElement): UExpression {
- return if (statement != null) convert(statement, parent) else EmptyExpression(parent)
+ return if (statement != null) convert(statement, parent) else EmptyUExpression(parent)
}
internal fun convertOrEmpty(expression: PsiExpression?, parent: UElement): UExpression {
- return if (expression != null) convert(expression, parent) else EmptyExpression(parent)
+ return if (expression != null) convert(expression, parent) else EmptyUExpression(parent)
}
internal fun convertOrNull(expression: PsiExpression?, parent: UElement): UExpression? {
@@ -228,7 +215,7 @@ internal object JavaConverter : UastConverter {
}
internal fun convertOrEmpty(block: PsiCodeBlock?, parent: UElement): UExpression {
- return if (block != null) convert(block, parent) else EmptyExpression(parent)
+ return if (block != null) convert(block, parent) else EmptyUExpression(parent)
}
private fun convertDeclarations(elements: Array, parent: UElement): SimpleUDeclarationsExpression {
diff --git a/plugins/uast-java/src/org/jetbrains/uast/java/controlStructures/JavaUSwitchExpression.kt b/plugins/uast-java/src/org/jetbrains/uast/java/controlStructures/JavaUSwitchExpression.kt
index 7c3a6792905..01412b30e44 100644
--- a/plugins/uast-java/src/org/jetbrains/uast/java/controlStructures/JavaUSwitchExpression.kt
+++ b/plugins/uast-java/src/org/jetbrains/uast/java/controlStructures/JavaUSwitchExpression.kt
@@ -17,9 +17,7 @@ package org.jetbrains.uast.java
import com.intellij.psi.PsiSwitchLabelStatement
import com.intellij.psi.PsiSwitchStatement
-import org.jetbrains.uast.UElement
-import org.jetbrains.uast.UExpressionSwitchClauseExpression
-import org.jetbrains.uast.USwitchExpression
+import org.jetbrains.uast.*
import org.jetbrains.uast.psi.PsiElementBacked
class JavaUSwitchExpression(
@@ -30,9 +28,20 @@ class JavaUSwitchExpression(
override val body by lz { JavaConverter.convertOrEmpty(psi.body, this) }
}
-class JavaUExpressionSwitchClauseExpression(
+class JavaUCaseSwitchClauseExpression(
override val psi: PsiSwitchLabelStatement,
override val parent: UElement
-) : JavaAbstractUElement(), UExpressionSwitchClauseExpression, PsiElementBacked {
- override val caseValue by lz { JavaConverter.convertOrEmpty(psi.caseValue, this) }
+) : JavaAbstractUElement(), USwitchClauseExpression, PsiElementBacked {
+ override val caseValues by lz {
+ val value = psi.caseValue ?: return@lz null
+ listOf(JavaConverter.convert(value, this))
+ }
+}
+
+class DefaultUSwitchClauseExpression(override val parent: UElement) : USwitchClauseExpression {
+ override val caseValues: List?
+ get() = null
+
+ override fun logString() = "DefaultUSwitchClauseExpression"
+ override fun renderString() = "else -> "
}
\ No newline at end of file
diff --git a/plugins/uast-java/src/org/jetbrains/uast/java/declarations/JavaClassInitializerUFunction.kt b/plugins/uast-java/src/org/jetbrains/uast/java/declarations/JavaClassInitializerUFunction.kt
index 3303fc47b6c..cf0db6ed937 100644
--- a/plugins/uast-java/src/org/jetbrains/uast/java/declarations/JavaClassInitializerUFunction.kt
+++ b/plugins/uast-java/src/org/jetbrains/uast/java/declarations/JavaClassInitializerUFunction.kt
@@ -16,15 +16,21 @@
package org.jetbrains.uast.java
import com.intellij.psi.PsiClassInitializer
+import com.intellij.psi.PsiModifier
import org.jetbrains.uast.*
import org.jetbrains.uast.psi.PsiElementBacked
class JavaClassInitializerUFunction(
override val psi: PsiClassInitializer,
override val parent: UElement
-) : JavaAbstractUElement(), UFunction, PsiElementBacked, NoAnnotations, NoModifiers {
+) : JavaAbstractUElement(), UFunction, PsiElementBacked, NoAnnotations {
override val kind: UastFunctionKind.UastInitializerKind
- get() = JavaFunctionKinds.STATIC_INITIALIZER
+ get() {
+ return if (psi.hasModifierProperty(PsiModifier.STATIC))
+ JavaFunctionKinds.STATIC_INITIALIZER
+ else
+ JavaFunctionKinds.INSTANCE_INITIALIZER
+ }
override val valueParameters: List
get() = emptyList()
@@ -53,4 +59,5 @@ class JavaClassInitializerUFunction(
get() = ""
override fun getSuperFunctions(context: UastContext) = emptyList()
+ override fun hasModifier(modifier: UastModifier) = psi.hasModifier(modifier)
}
\ No newline at end of file
diff --git a/plugins/uast-java/src/org/jetbrains/uast/java/declarations/JavaUAnnotation.kt b/plugins/uast-java/src/org/jetbrains/uast/java/declarations/JavaUAnnotation.kt
index 1a10b4054cb..375c1a98d1a 100644
--- a/plugins/uast-java/src/org/jetbrains/uast/java/declarations/JavaUAnnotation.kt
+++ b/plugins/uast-java/src/org/jetbrains/uast/java/declarations/JavaUAnnotation.kt
@@ -24,7 +24,7 @@ import org.jetbrains.uast.psi.PsiElementBacked
class JavaUAnnotation(
override val psi: PsiAnnotation,
- override val parent: UElement?
+ override val parent: UElement
) : JavaAbstractUElement(), UAnnotation, PsiElementBacked {
override val name: String
get() = psi.nameReferenceElement?.referenceName.orAnonymous()
diff --git a/plugins/uast-java/src/org/jetbrains/uast/java/declarations/JavaUClass.kt b/plugins/uast-java/src/org/jetbrains/uast/java/declarations/JavaUClass.kt
index 4fb404684b2..d88e0cb24e1 100644
--- a/plugins/uast-java/src/org/jetbrains/uast/java/declarations/JavaUClass.kt
+++ b/plugins/uast-java/src/org/jetbrains/uast/java/declarations/JavaUClass.kt
@@ -21,13 +21,11 @@ import com.intellij.psi.util.ClassUtil
import com.intellij.psi.util.PsiTreeUtil
import com.intellij.psi.util.PsiTypesUtil
import org.jetbrains.uast.*
-import org.jetbrains.uast.kinds.UastClassKind
import org.jetbrains.uast.psi.PsiElementBacked
-import java.util.*
class JavaUClass(
override val psi: PsiClass,
- override val parent: UElement?,
+ override val parent: UElement,
val newExpression: PsiNewExpression? = null
) : JavaAbstractUElement(), UClass, PsiElementBacked {
override val name: String
@@ -79,27 +77,19 @@ class JavaUClass(
override val declarations by lz {
val declarations = arrayListOf()
psi.fields.mapTo(declarations) { JavaConverter.convert(it, this) }
- psi.constructors.mapTo(declarations) { JavaConverter.convert(it, this) }
if (psi is PsiAnonymousClass && newExpression != null) {
declarations += JavaUAnonymousClassConstructor(psi, newExpression, this)
}
- psi.methods.filter { !it.isConstructor }.mapTo(declarations) { JavaConverter.convert(it, this) }
- psi.interfaces.mapTo(declarations) { JavaConverter.convert(it, this) }
+ psi.methods.mapTo(declarations) { JavaConverter.convert(it, this) }
psi.innerClasses.mapTo(declarations) { JavaConverter.convert(it, this) }
psi.initializers.mapTo(declarations) { JavaConverter.convert(it, this) }
declarations
}
override fun isSubclassOf(fqName: String): Boolean {
- tailrec fun isSubClassOf(clazz: PsiClass?, name: String): Boolean = when {
- clazz == null -> false
- clazz.qualifiedName == name -> true
- else -> isSubClassOf(clazz.superClass, name)
- }
-
- return isSubClassOf(psi, fqName)
+ return psi.supers.any { base -> psi.isInheritor(base, false) }
}
private companion object {
@@ -179,7 +169,8 @@ private class JavaUAnonymousClassConstructor(
override val returnType: UType?
get() = null
- override val body = EmptyExpression(this)
+ override val body: UExpression?
+ get() = null
override val visibility: UastVisibility
get() = UastVisibility.LOCAL
diff --git a/plugins/uast-java/src/org/jetbrains/uast/java/declarations/JavaUFunction.kt b/plugins/uast-java/src/org/jetbrains/uast/java/declarations/JavaUFunction.kt
index a6580b10589..6b09774e7e8 100644
--- a/plugins/uast-java/src/org/jetbrains/uast/java/declarations/JavaUFunction.kt
+++ b/plugins/uast-java/src/org/jetbrains/uast/java/declarations/JavaUFunction.kt
@@ -57,7 +57,7 @@ class JavaUFunction(
override val visibility: UastVisibility
get() = psi.getVisibility()
- override val body by lz { JavaConverter.convertOrEmpty(psi.body, this) }
+ override val body by lz { psi.body?.let { JavaConverter.convert(it, this) } }
override val bytecodeDescriptor by lz { getDescriptor(psi) }
diff --git a/plugins/uast-java/src/org/jetbrains/uast/java/declarations/JavaUImportStatement.kt b/plugins/uast-java/src/org/jetbrains/uast/java/declarations/JavaUImportStatement.kt
index 2780f7f418e..0676d06ce79 100644
--- a/plugins/uast-java/src/org/jetbrains/uast/java/declarations/JavaUImportStatement.kt
+++ b/plugins/uast-java/src/org/jetbrains/uast/java/declarations/JavaUImportStatement.kt
@@ -20,7 +20,6 @@ import org.jetbrains.uast.UDeclaration
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UImportStatement
import org.jetbrains.uast.UastContext
-import org.jetbrains.uast.kinds.UastImportKind
import org.jetbrains.uast.psi.PsiElementBacked
class JavaUImportStatement(
@@ -30,9 +29,6 @@ class JavaUImportStatement(
override val fqNameToImport: String?
get() = psi.qualifiedName
- override val kind: UastImportKind
- get() = UastImportKind.CLASS
-
override val isStarImport: Boolean
get() = psi.isOnDemand
diff --git a/plugins/uast-java/src/org/jetbrains/uast/java/declarations/JavaUStaticImportStatement.kt b/plugins/uast-java/src/org/jetbrains/uast/java/declarations/JavaUStaticImportStatement.kt
index e697f6c7f91..8dda062ba19 100644
--- a/plugins/uast-java/src/org/jetbrains/uast/java/declarations/JavaUStaticImportStatement.kt
+++ b/plugins/uast-java/src/org/jetbrains/uast/java/declarations/JavaUStaticImportStatement.kt
@@ -20,7 +20,6 @@ import org.jetbrains.uast.UDeclaration
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UImportStatement
import org.jetbrains.uast.UastContext
-import org.jetbrains.uast.kinds.UastImportKind
import org.jetbrains.uast.psi.PsiElementBacked
class JavaUStaticImportStatement(
@@ -30,9 +29,6 @@ class JavaUStaticImportStatement(
override val fqNameToImport: String?
get() = psi.referenceName
- override val kind: UastImportKind
- get() = UastImportKind.MEMBER
-
override val isStarImport: Boolean
get() = psi.isOnDemand
diff --git a/plugins/uast-java/src/org/jetbrains/uast/java/declarations/JavaUType.kt b/plugins/uast-java/src/org/jetbrains/uast/java/declarations/JavaUType.kt
index 830dc346dfd..163fc740869 100644
--- a/plugins/uast-java/src/org/jetbrains/uast/java/declarations/JavaUType.kt
+++ b/plugins/uast-java/src/org/jetbrains/uast/java/declarations/JavaUType.kt
@@ -44,6 +44,9 @@ class JavaUType(
override val isLong: Boolean
get() = check("long", "java.lang.Long")
+ override val isShort: Boolean
+ get() = check("short", "java.lang.Short")
+
override val isFloat: Boolean
get() = check("float", "java.lang.Float")
@@ -59,6 +62,7 @@ class JavaUType(
override val isByte: Boolean
get() = check("byte", "java.lang.Byte")
+ @Suppress("NOTHING_TO_INLINE")
private inline fun check(unboxedType: String, boxedType: String): Boolean =
name == unboxedType || (psi as? PsiClassType)?.resolve()?.qualifiedName == boxedType
diff --git a/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUAssertExpression.kt b/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUAssertExpression.kt
new file mode 100644
index 00000000000..fe8764f3f82
--- /dev/null
+++ b/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUAssertExpression.kt
@@ -0,0 +1,59 @@
+/*
+ * 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.java
+
+import com.intellij.psi.PsiAssertStatement
+import org.jetbrains.uast.*
+import org.jetbrains.uast.psi.PsiElementBacked
+
+class JavaUAssertExpression(
+ override val psi: PsiAssertStatement,
+ override val parent: UElement
+) : JavaAbstractUElement(), UCallExpression, PsiElementBacked {
+ val condition: UExpression by lz { JavaConverter.convertOrEmpty(psi.assertCondition, this) }
+ val message: UExpression? by lz { JavaConverter.convertOrNull(psi.assertDescription, this) }
+
+ override val functionReference: USimpleReferenceExpression?
+ get() = null
+
+ override val classReference: USimpleReferenceExpression?
+ get() = null
+
+ override val functionName: String?
+ get() = ""
+
+ override val functionNameElement: UElement?
+ get() = null
+
+ override val valueArgumentCount: Int
+ get() = if (message != null) 2 else 1
+
+ override val valueArguments by lz {
+ val message = this.message
+ if (message != null) listOf(condition, message) else listOf(condition)
+ }
+
+ override val typeArgumentCount: Int
+ get() = 0
+ override val typeArguments: List
+ get() = emptyList()
+
+ override val kind: UastCallKind
+ get() = JavaUastCallKinds.ASSERT
+
+ override fun resolve(context: UastContext) = null
+}
\ No newline at end of file
diff --git a/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUAssignmentExpression.kt b/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUAssignmentExpression.kt
index 48fe06ed8a9..cc17bf2de65 100644
--- a/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUAssignmentExpression.kt
+++ b/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUAssignmentExpression.kt
@@ -18,7 +18,6 @@ package org.jetbrains.uast.java
import com.intellij.psi.PsiAssignmentExpression
import org.jetbrains.uast.UBinaryExpression
import org.jetbrains.uast.UElement
-import org.jetbrains.uast.UastBinaryOperator
import org.jetbrains.uast.psi.PsiElementBacked
class JavaUAssignmentExpression(
@@ -26,9 +25,6 @@ class JavaUAssignmentExpression(
override val parent: UElement
) : JavaAbstractUElement(), UBinaryExpression, PsiElementBacked, JavaUElementWithType, JavaEvaluatableUElement {
override val leftOperand by lz { JavaConverter.convert(psi.lExpression, this) }
-
- override val operator: UastBinaryOperator
- get() = UastBinaryOperator.ASSIGN
-
override val rightOperand by lz { JavaConverter.convertOrEmpty(psi.rExpression, this) }
+ override val operator by lz { psi.operationTokenType.getOperatorType() }
}
\ No newline at end of file
diff --git a/plugins/uast-common/src/org/jetbrains/uast/kinds/UastImportKind.kt b/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUBreakExpression.kt
similarity index 57%
rename from plugins/uast-common/src/org/jetbrains/uast/kinds/UastImportKind.kt
rename to plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUBreakExpression.kt
index 7385b34df14..936b560d767 100644
--- a/plugins/uast-common/src/org/jetbrains/uast/kinds/UastImportKind.kt
+++ b/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUBreakExpression.kt
@@ -14,22 +14,17 @@
* limitations under the License.
*/
-package org.jetbrains.uast.kinds
+package org.jetbrains.uast.java
-class UastImportKind(val text: String) {
+import com.intellij.psi.PsiBreakStatement
+import org.jetbrains.uast.UBreakExpression
+import org.jetbrains.uast.UElement
+import org.jetbrains.uast.psi.PsiElementBacked
- companion object {
- @JvmField
- val CLASS = UastImportKind("class")
-
- @JvmField
- val MEMBER = UastImportKind("member")
-
- @JvmField
- val UNKNOWN = UastImportKind("unknown")
- }
-
- override fun toString(): String{
- return "UastImportKind(text='$text')"
- }
+class JavaUBreakExpression(
+ override val psi: PsiBreakStatement,
+ override val parent: UElement
+) : JavaAbstractUElement(), UBreakExpression, PsiElementBacked {
+ override val label: String?
+ get() = psi.labelIdentifier?.text
}
\ No newline at end of file
diff --git a/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUCallableReferenceExpression.kt b/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUCallableReferenceExpression.kt
index e8fd2acee7a..08d844d05e7 100644
--- a/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUCallableReferenceExpression.kt
+++ b/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUCallableReferenceExpression.kt
@@ -17,12 +17,19 @@ package org.jetbrains.uast.java
import com.intellij.psi.PsiMethodReferenceExpression
import org.jetbrains.uast.UCallableReferenceExpression
+import org.jetbrains.uast.UDeclaration
import org.jetbrains.uast.UElement
+import org.jetbrains.uast.UastContext
import org.jetbrains.uast.psi.PsiElementBacked
class JavaUCallableReferenceExpression(
override val psi: PsiMethodReferenceExpression,
override val parent: UElement
) : JavaAbstractUElement(), UCallableReferenceExpression, PsiElementBacked, JavaUElementWithType {
+ override val qualifierExpression by lz { JavaConverter.convertOrNull(psi.qualifierExpression, this) }
override val qualifierType by lz { JavaConverter.convert(psi.qualifierType?.type, this) }
+ override val callableName: String
+ get() = psi.referenceName.orAnonymous()
+
+ override fun resolve(context: UastContext) = context.convert(psi.resolve()) as? UDeclaration
}
\ No newline at end of file
diff --git a/plugins/lint/uast-android/src/org/jetbrains/uast/check/AndroidUastAdditionalChecker.kt b/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUContinueExpression.kt
similarity index 56%
rename from plugins/lint/uast-android/src/org/jetbrains/uast/check/AndroidUastAdditionalChecker.kt
rename to plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUContinueExpression.kt
index ca372b1a8f4..28278517478 100644
--- a/plugins/lint/uast-android/src/org/jetbrains/uast/check/AndroidUastAdditionalChecker.kt
+++ b/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUContinueExpression.kt
@@ -14,8 +14,17 @@
* limitations under the License.
*/
-package org.jetbrains.uast.check
+package org.jetbrains.uast.java
-import org.jetbrains.uast.UastAdditionalChecker
+import com.intellij.psi.PsiContinueStatement
+import org.jetbrains.uast.UContinueExpression
+import org.jetbrains.uast.UElement
+import org.jetbrains.uast.psi.PsiElementBacked
-interface AndroidUastAdditionalChecker : UastAdditionalChecker
\ No newline at end of file
+class JavaUContinueExpression(
+ override val psi: PsiContinueStatement,
+ override val parent: UElement
+) : JavaAbstractUElement(), UContinueExpression, PsiElementBacked {
+ override val label: String?
+ get() = psi.labelIdentifier?.text
+}
\ No newline at end of file
diff --git a/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaULambdaExpression.kt b/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaULambdaExpression.kt
index 03dd5fe50eb..27a7c6f88ca 100644
--- a/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaULambdaExpression.kt
+++ b/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaULambdaExpression.kt
@@ -18,7 +18,7 @@ package org.jetbrains.uast.java
import com.intellij.psi.PsiCodeBlock
import com.intellij.psi.PsiExpression
import com.intellij.psi.PsiLambdaExpression
-import org.jetbrains.uast.EmptyExpression
+import org.jetbrains.uast.EmptyUExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.ULambdaExpression
import org.jetbrains.uast.psi.PsiElementBacked
@@ -34,7 +34,7 @@ class JavaULambdaExpression(
when (b) {
is PsiCodeBlock -> JavaConverter.convert(b, this)
is PsiExpression -> JavaConverter.convert(b, this)
- else -> EmptyExpression(this)
+ else -> EmptyUExpression(this)
}
}
}
\ 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 0dfce0edbaa..f96679fdca2 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
@@ -15,6 +15,7 @@
*/
package org.jetbrains.uast.java
+import com.intellij.psi.PsiKeyword
import com.intellij.psi.PsiLiteralExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.ULiteralExpression
@@ -29,5 +30,5 @@ class JavaULiteralExpression(
override val value by lz { evaluate() }
override val isNull: Boolean
- get() = asString() == "null"
+ get() = asString() == PsiKeyword.NULL
}
\ No newline at end of file
diff --git a/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUPostfixExpression.kt b/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUPostfixExpression.kt
index 5f8a75ff541..dca782c2e76 100644
--- a/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUPostfixExpression.kt
+++ b/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUPostfixExpression.kt
@@ -15,6 +15,7 @@
*/
package org.jetbrains.uast.java
+import com.intellij.psi.JavaTokenType
import com.intellij.psi.PsiPostfixExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UPostfixExpression
@@ -27,9 +28,9 @@ class JavaUPostfixExpression(
) : JavaAbstractUElement(), UPostfixExpression, PsiElementBacked, JavaUElementWithType, JavaEvaluatableUElement {
override val operand by lz { JavaConverter.convertOrEmpty(psi.operand, this) }
- override val operator = when (psi.operationSign.text) {
- "++" -> UastPostfixOperator.INC
- "--" -> UastPostfixOperator.DEC
+ override val operator = when (psi.operationSign) {
+ JavaTokenType.PLUSPLUS -> UastPostfixOperator.INC
+ JavaTokenType.MINUSMINUS -> UastPostfixOperator.DEC
else -> UastPostfixOperator.UNKNOWN
}
}
\ No newline at end of file
diff --git a/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUPrefixExpression.kt b/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUPrefixExpression.kt
index 103688b478e..d9831ab5f58 100644
--- a/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUPrefixExpression.kt
+++ b/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUPrefixExpression.kt
@@ -15,6 +15,7 @@
*/
package org.jetbrains.uast.java
+import com.intellij.psi.JavaTokenType
import com.intellij.psi.PsiPrefixExpression
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UPrefixExpression
@@ -27,13 +28,13 @@ class JavaUPrefixExpression(
) : JavaAbstractUElement(), UPrefixExpression, PsiElementBacked, JavaUElementWithType, JavaEvaluatableUElement {
override val operand by lz { JavaConverter.convertOrEmpty(psi.operand, this) }
- override val operator = when (psi.operationSign.text) {
- "+" -> UastPrefixOperator.UNARY_PLUS
- "-" -> UastPrefixOperator.UNARY_MINUS
- "++" -> UastPrefixOperator.INC
- "--" -> UastPrefixOperator.DEC
- "!" -> UastPrefixOperator.LOGICAL_NOT
- "~" -> UastPrefixOperator.BITWISE_NOT
+ override val operator = when (psi.operationSign) {
+ JavaTokenType.PLUS -> UastPrefixOperator.UNARY_PLUS
+ JavaTokenType.MINUS -> UastPrefixOperator.UNARY_MINUS
+ JavaTokenType.PLUSPLUS -> UastPrefixOperator.INC
+ JavaTokenType.MINUSMINUS-> UastPrefixOperator.DEC
+ JavaTokenType.EXCL -> UastPrefixOperator.LOGICAL_NOT
+ JavaTokenType.TILDE -> UastPrefixOperator.BITWISE_NOT
else -> UastPrefixOperator.UNKNOWN
}
}
\ No newline at end of file
diff --git a/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUQualifiedExpression.kt b/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUQualifiedExpression.kt
index 9f3fdb4c6bc..bd3fccd26a9 100644
--- a/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUQualifiedExpression.kt
+++ b/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUQualifiedExpression.kt
@@ -24,7 +24,7 @@ class JavaUQualifiedExpression(
override val parent: UElement
) : JavaAbstractUElement(), UQualifiedExpression, PsiElementBacked, JavaUElementWithType {
override val receiver by lz { JavaConverter.convertOrEmpty(psi.qualifierExpression, this) }
- override val selector by lz { JavaConverter.convert(psi.referenceNameElement, this) as? UExpression ?: EmptyExpression(this) }
+ override val selector by lz { JavaConverter.convert(psi.referenceNameElement, this) as? UExpression ?: EmptyUExpression(this) }
override val accessType: UastQualifiedExpressionAccessType
get() = UastQualifiedExpressionAccessType.SIMPLE
diff --git a/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUReturnExpression.kt b/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUReturnExpression.kt
new file mode 100644
index 00000000000..485ed9677ab
--- /dev/null
+++ b/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUReturnExpression.kt
@@ -0,0 +1,29 @@
+/*
+ * 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.java
+
+import com.intellij.psi.PsiReturnStatement
+import org.jetbrains.uast.UElement
+import org.jetbrains.uast.UReturnExpression
+import org.jetbrains.uast.psi.PsiElementBacked
+
+class JavaUReturnExpression(
+ override val psi: PsiReturnStatement,
+ override val parent: UElement
+) : JavaAbstractUElement(), UReturnExpression, PsiElementBacked {
+ override val returnExpression by lz { JavaConverter.convertOrNull(psi.returnValue, this) }
+}
\ No newline at end of file
diff --git a/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUSynchronizedExpression.kt b/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUSynchronizedExpression.kt
new file mode 100644
index 00000000000..2120aa0bef8
--- /dev/null
+++ b/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUSynchronizedExpression.kt
@@ -0,0 +1,44 @@
+/*
+ * 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.java.expressions
+
+import com.intellij.psi.PsiSynchronizedStatement
+import org.jetbrains.uast.UBlockExpression
+import org.jetbrains.uast.UElement
+import org.jetbrains.uast.acceptList
+import org.jetbrains.uast.java.JavaAbstractUElement
+import org.jetbrains.uast.java.JavaConverter
+import org.jetbrains.uast.java.JavaUElementWithType
+import org.jetbrains.uast.java.lz
+import org.jetbrains.uast.psi.PsiElementBacked
+import org.jetbrains.uast.visitor.UastVisitor
+
+class JavaUSynchronizedExpression(
+ override val psi: PsiSynchronizedStatement,
+ override val parent: UElement
+) : JavaAbstractUElement(), UBlockExpression, PsiElementBacked, JavaUElementWithType {
+ override val expressions by lz { psi.body?.statements?.map { JavaConverter.convert(it, this) } ?: listOf() }
+ val lockExpression by lz { JavaConverter.convertOrEmpty(psi.lockExpression, this) }
+
+ override fun accept(visitor: UastVisitor) {
+ if (visitor.visitBlockExpression(this)) return
+ psi.lockExpression
+ expressions.acceptList(visitor)
+ lockExpression.accept(visitor)
+ visitor.afterVisitBlockExpression(this)
+ }
+}
\ No newline at end of file
diff --git a/plugins/uast-java/src/org/jetbrains/uast/java/kinds/JavaSpecialExpressionKinds.kt b/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUThrowExpression.kt
similarity index 55%
rename from plugins/uast-java/src/org/jetbrains/uast/java/kinds/JavaSpecialExpressionKinds.kt
rename to plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUThrowExpression.kt
index 78eede2ba8b..85d70a4a9c1 100644
--- a/plugins/uast-java/src/org/jetbrains/uast/java/kinds/JavaSpecialExpressionKinds.kt
+++ b/plugins/uast-java/src/org/jetbrains/uast/java/expressions/JavaUThrowExpression.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2016 JetBrains s.r.o.
+ * 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.
@@ -13,14 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package org.jetbrains.uast.java
-import org.jetbrains.uast.UastSpecialExpressionKind
+import com.intellij.psi.PsiThrowStatement
+import org.jetbrains.uast.UElement
+import org.jetbrains.uast.UThrowExpression
+import org.jetbrains.uast.psi.PsiElementBacked
-object JavaSpecialExpressionKinds {
- @JvmField
- val ASSERT = UastSpecialExpressionKind("assert")
-
- @JvmField
- val SYNCHRONIZED = UastSpecialExpressionKind("synchronized")
+class JavaUThrowExpression(
+ override val psi: PsiThrowStatement,
+ override val parent: UElement
+) : JavaAbstractUElement(), UThrowExpression, PsiElementBacked {
+ override val thrownExpression by lz { JavaConverter.convertOrEmpty(psi.exception, this) }
}
\ 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 31d03b14ac7..d2482ba57d8 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
@@ -57,8 +57,8 @@ class JavaConstructorUCallExpression(
) : JavaAbstractUElement(), UCallExpression, PsiElementBacked, JavaUElementWithType {
override val kind by lz {
when {
- psi.arrayInitializer != null -> JavaUastCallKinds.ARRAY_INITIALIZER
- psi.arrayDimensions.isNotEmpty() -> JavaUastCallKinds.ARRAY_DIMENSIONS
+ psi.arrayInitializer != null -> JavaUastCallKinds.NEW_ARRAY_WITH_INITIALIZER
+ psi.arrayDimensions.isNotEmpty() -> JavaUastCallKinds.NEW_ARRAY_DIMENTIONS
else -> UastCallKind.CONSTRUCTOR_CALL
}
}
@@ -104,7 +104,7 @@ class JavaConstructorUCallExpression(
get() {
val initializer = psi.arrayInitializer
return if (initializer != null)
- ""
+ ""
else if (psi.arrayDimensions.isNotEmpty())
""
else null
@@ -141,7 +141,7 @@ class JavaArrayInitializerUCallExpression(
get() = emptyList()
override val kind: UastCallKind
- get() = JavaUastCallKinds.ARRAY_INITIALIZER
+ get() = UastCallKind.ARRAY_INITIALIZER
override fun resolve(context: UastContext) = null
}
@@ -150,7 +150,8 @@ class JavaAnnotationArrayInitializerUCallExpression(
override val psi: PsiArrayInitializerMemberValue,
override val parent: UElement
) : JavaAbstractUElement(), UCallExpression, PsiElementBacked, JavaUElementWithType, JavaEvaluatableUElement {
- override val kind = JavaUastCallKinds.ARRAY_INITIALIZER
+ override val kind: UastCallKind
+ get() = UastCallKind.ARRAY_INITIALIZER
override val functionReference: USimpleReferenceExpression?
get() = null
diff --git a/plugins/uast-java/src/org/jetbrains/uast/java/internal/javaInternalUastUtils.kt b/plugins/uast-java/src/org/jetbrains/uast/java/internal/javaInternalUastUtils.kt
index c0c91e6573d..8a35f8f9624 100644
--- a/plugins/uast-java/src/org/jetbrains/uast/java/internal/javaInternalUastUtils.kt
+++ b/plugins/uast-java/src/org/jetbrains/uast/java/internal/javaInternalUastUtils.kt
@@ -33,6 +33,12 @@ internal fun PsiModifierListOwner.hasModifier(modifier: UastModifier): Boolean {
if (modifier == UastModifier.VARARG && this is PsiParameter) {
return this.isVarArgs
}
+ if (modifier == UastModifier.IMMUTABLE && this is PsiVariable) {
+ return this.hasModifierProperty(PsiModifier.FINAL)
+ }
+ if (modifier == UastModifier.FINAL && this is PsiVariable) {
+ return false;
+ }
val javaModifier = MODIFIER_MAP[modifier] ?: return false
return hasModifierProperty(javaModifier)
}
@@ -58,7 +64,6 @@ internal fun IElementType.getOperatorType() = when (this) {
JavaTokenType.PERC -> UastBinaryOperator.MOD
JavaTokenType.OR -> UastBinaryOperator.BITWISE_OR
JavaTokenType.AND -> UastBinaryOperator.BITWISE_AND
- JavaTokenType.TILDE -> UastBinaryOperator.BITWISE_XOR
JavaTokenType.EQEQ -> UastBinaryOperator.IDENTITY_EQUALS
JavaTokenType.NE -> UastBinaryOperator.IDENTITY_NOT_EQUALS
JavaTokenType.GT -> UastBinaryOperator.GREATER
@@ -72,6 +77,7 @@ internal fun IElementType.getOperatorType() = when (this) {
JavaTokenType.MINUSEQ -> UastBinaryOperator.MINUS_ASSIGN
JavaTokenType.ASTERISKEQ -> UastBinaryOperator.MULTIPLY_ASSIGN
JavaTokenType.DIVEQ -> UastBinaryOperator.DIVIDE_ASSIGN
+ JavaTokenType.PERCEQ -> UastBinaryOperator.REMAINDER_ASSIGN
JavaTokenType.ANDEQ -> UastBinaryOperator.AND_ASSIGN
JavaTokenType.XOREQ -> UastBinaryOperator.XOR_ASSIGN
JavaTokenType.OREQ -> UastBinaryOperator.OR_ASSIGN
diff --git a/plugins/uast-java/src/org/jetbrains/uast/java/kinds/JavaFunctionKinds.kt b/plugins/uast-java/src/org/jetbrains/uast/java/kinds/JavaFunctionKinds.kt
index 0ac3da8526a..e668b8f6c55 100644
--- a/plugins/uast-java/src/org/jetbrains/uast/java/kinds/JavaFunctionKinds.kt
+++ b/plugins/uast-java/src/org/jetbrains/uast/java/kinds/JavaFunctionKinds.kt
@@ -19,5 +19,6 @@ package org.jetbrains.uast.java
import org.jetbrains.uast.UastFunctionKind
object JavaFunctionKinds {
+ val INSTANCE_INITIALIZER = UastFunctionKind.UastInitializerKind("")
val STATIC_INITIALIZER = UastFunctionKind.UastInitializerKind("")
}
\ No newline at end of file
diff --git a/plugins/uast-java/src/org/jetbrains/uast/java/kinds/JavaUastCallKinds.kt b/plugins/uast-java/src/org/jetbrains/uast/java/kinds/JavaUastCallKinds.kt
index 0df6bd91778..24a0dc850b4 100644
--- a/plugins/uast-java/src/org/jetbrains/uast/java/kinds/JavaUastCallKinds.kt
+++ b/plugins/uast-java/src/org/jetbrains/uast/java/kinds/JavaUastCallKinds.kt
@@ -19,8 +19,11 @@ import org.jetbrains.uast.UastCallKind
object JavaUastCallKinds {
@JvmField
- val ARRAY_INITIALIZER = UastCallKind("array_initializer")
+ val NEW_ARRAY_WITH_INITIALIZER = UastCallKind("new_array_with_initializer")
@JvmField
- val ARRAY_DIMENSIONS = UastCallKind("array_dimensions")
+ val NEW_ARRAY_DIMENTIONS = UastCallKind("new_array_dimensions")
+
+ @JvmField
+ val ASSERT = UastCallKind("assert")
}
\ No newline at end of file
diff --git a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/KotlinUastLanguagePlugin.kt b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/KotlinUastLanguagePlugin.kt
index 79eb1e479c8..47bef979715 100644
--- a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/KotlinUastLanguagePlugin.kt
+++ b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/KotlinUastLanguagePlugin.kt
@@ -25,6 +25,8 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.types.KotlinType
+import org.jetbrains.kotlin.uast.expressions.KotlinUBreakExpression
+import org.jetbrains.kotlin.uast.expressions.KotlinUContinueExpression
import org.jetbrains.kotlin.uast.kinds.KotlinSpecialExpressionKinds
import org.jetbrains.kotlin.uast.lint.PropertyAsCallAndroidUastAdditionalChecker
import org.jetbrains.uast.*
@@ -102,7 +104,10 @@ internal object KotlinConverter : UastConverter {
internal fun convert(entry: KtStringTemplateEntry, parent: UElement): UExpression = when (entry) {
is KtStringTemplateEntryWithExpression -> convertOrEmpty(entry.expression, parent)
- else -> KotlinStringULiteralExpression(entry, parent)
+ is KtEscapeStringTemplateEntry -> KotlinStringULiteralExpression(entry, parent, entry.unescapedValue)
+ else -> {
+ KotlinStringULiteralExpression(entry, parent)
+ }
}
internal fun convert(expression: KtExpression, parent: UElement): UExpression = when (expression) {
@@ -111,7 +116,9 @@ internal object KotlinConverter : UastConverter {
is KtClass -> convertDeclaration(expression, parent)
is KtStringTemplateExpression -> {
- if (expression.entries.size == 1)
+ if (expression.entries.isEmpty())
+ KotlinStringULiteralExpression(expression, parent)
+ else if (expression.entries.size == 1)
convert(expression.entries[0], parent)
else
convertStringTemplateExpression(expression, parent, expression.entries.size - 1)
@@ -128,6 +135,7 @@ internal object KotlinConverter : UastConverter {
}
declarations = listOf(tempAssignment) + destructuringAssignments
}
+ is KtLabeledExpression -> KotlinULabeledExpression(expression, parent)
is KtClassLiteralExpression -> KotlinUClassLiteralExpression(expression, parent)
is KtObjectLiteralExpression -> KotlinUObjectLiteralExpression(expression, parent)
is KtStringTemplateEntry -> convertOrEmpty(expression.expression, parent)
@@ -141,20 +149,17 @@ internal object KotlinConverter : UastConverter {
is KtPostfixExpression -> KotlinUPostfixExpression(expression, parent)
is KtThisExpression -> KotlinUThisExpression(expression, parent)
is KtSuperExpression -> KotlinUSuperExpression(expression, parent)
+ is KtCallableReferenceExpression -> KotlinUCallableReferenceExpression(expression, parent)
is KtIsExpression -> KotlinUTypeCheckExpression(expression, parent)
is KtIfExpression -> KotlinUIfExpression(expression, parent)
is KtWhileExpression -> KotlinUWhileExpression(expression, parent)
is KtDoWhileExpression -> KotlinUDoWhileExpression(expression, parent)
is KtForExpression -> KotlinUForEachExpression(expression, parent)
is KtWhenExpression -> KotlinUSwitchExpression(expression, parent)
- is KtBreakExpression -> KotlinUSpecialExpressionList.Empty(expression, UastSpecialExpressionKind.BREAK, parent)
- is KtContinueExpression -> KotlinUSpecialExpressionList.Empty(expression, UastSpecialExpressionKind.CONTINUE, parent)
- is KtReturnExpression -> KotlinUSpecialExpressionList(expression, UastSpecialExpressionKind.RETURN, parent).apply {
- expressions = listOf(convertOrEmpty(expression.returnedExpression, this))
- }
- is KtThrowExpression -> KotlinUSpecialExpressionList(expression, UastSpecialExpressionKind.THROW, parent).apply {
- expressions = singletonListOrEmpty(convertOrNull(expression.thrownExpression, this))
- }
+ is KtBreakExpression -> KotlinUBreakExpression(expression, parent)
+ is KtContinueExpression -> KotlinUContinueExpression(expression, parent)
+ is KtReturnExpression -> KotlinUReturnExpression(expression, parent)
+ is KtThrowExpression -> KotlinUThrowExpression(expression, parent)
is KtBlockExpression -> KotlinUBlockExpression(expression, parent)
is KtConstantExpression -> KotlinULiteralExpression(expression, parent)
is KtTryExpression -> KotlinUTryExpression(expression, parent)
@@ -190,7 +195,7 @@ internal object KotlinConverter : UastConverter {
}
internal fun convertOrEmpty(expression: KtExpression?, parent: UElement): UExpression {
- return if (expression != null) convert(expression, parent) else EmptyExpression(parent)
+ return if (expression != null) convert(expression, parent) else EmptyUExpression(parent)
}
internal fun convertOrNull(expression: KtExpression?, parent: UElement): UExpression? {
diff --git a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/declarations/KotlinParameterUTypeReference.kt b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/declarations/KotlinParameterUTypeReference.kt
index 5307977ccc7..b9eeea5637c 100644
--- a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/declarations/KotlinParameterUTypeReference.kt
+++ b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/declarations/KotlinParameterUTypeReference.kt
@@ -31,7 +31,7 @@ class KotlinParameterUTypeReference(
override fun resolve(context: UastContext): UClass? {
val descriptor = psi.analyze(BodyResolveMode.PARTIAL)[BindingContext.TYPE_PARAMETER, psi]
?.typeConstructor?.declarationDescriptor as? ClassDescriptor ?: return null
- return context.convert(descriptor.toSource(psi)) as? UClass
+ return context.convert(descriptor.toSource()) as? UClass
}
override val nameElement: UElement?
diff --git a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/declarations/KotlinUAnnotation.kt b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/declarations/KotlinUAnnotation.kt
index aa80571a4e3..d4875f2d7c5 100644
--- a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/declarations/KotlinUAnnotation.kt
+++ b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/declarations/KotlinUAnnotation.kt
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.uast
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze
-import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
import org.jetbrains.kotlin.psi.KtAnnotationEntry
import org.jetbrains.kotlin.psi.KtUserType
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
@@ -55,7 +54,7 @@ class KotlinUAnnotation(
override fun resolve(context: UastContext): UClass? {
val classDescriptor = resolveToDescriptor() ?: return null
- val source = DescriptorToSourceUtilsIde.getAnyDeclaration(psi.project, classDescriptor) ?: return null
+ val source = classDescriptor.toSource() ?: return null
return context.convert(source) as? UClass
}
}
\ 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 60eac7ef61c..89cc63d28c4 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
@@ -35,5 +35,6 @@ class KotlinUAnnotationList(
override fun accept(visitor: UastVisitor) {
if (visitor.visitElement(this)) return
annotations.acceptList(visitor)
+ visitor.afterVisitElement(this)
}
}
\ No newline at end of file
diff --git a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/declarations/KotlinUClass.kt b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/declarations/KotlinUClass.kt
index 96c4def32b2..884f4b1c5b8 100644
--- a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/declarations/KotlinUClass.kt
+++ b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/declarations/KotlinUClass.kt
@@ -25,7 +25,6 @@ import org.jetbrains.kotlin.fileClasses.NoResolveFileClassesProvider
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
import org.jetbrains.kotlin.load.java.JvmAbi
-import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtObjectDeclaration
@@ -35,7 +34,6 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.types.typeUtil.supertypes
import org.jetbrains.uast.*
-import org.jetbrains.uast.kinds.UastClassKind
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUClass(
@@ -47,13 +45,8 @@ class KotlinUClass(
get() = psi.name.orAnonymous()
override val nameElement by lz {
- fun objectKeyword() = try { // !! in getObjectKeyword()
- if (psi is KtObjectDeclaration && psi.isObjectLiteral()) psi.getObjectKeyword() else null
- } catch (e: NullPointerException) {
- null
- }
-
- val namePsiElement = psi.nameIdentifier ?: objectKeyword()
+ val namePsiElement = psi.nameIdentifier
+ ?: if (psi is KtObjectDeclaration && psi.isObjectLiteral()) psi.getObjectKeyword() else null
KotlinConverter.asSimpleReference(namePsiElement, this)
}
@@ -63,12 +56,7 @@ class KotlinUClass(
override val kind by lz {
when {
psi.isAnnotation() -> UastClassKind.ANNOTATION
- (psi as? KtObjectDeclaration)?.isCompanion() ?: false -> {
- if (psi.name == SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT.toString())
- KotlinClassKinds.DEFAULT_COMPANION_OBJECT
- else
- KotlinClassKinds.NAMED_COMPANION_OBJECT
- }
+ (psi as? KtObjectDeclaration)?.isCompanion() ?: false -> KotlinClassKinds.COMPANION_OBJECT
psi is KtObjectDeclaration -> UastClassKind.OBJECT
(psi as? KtClass)?.isInterface() ?: false -> UastClassKind.INTERFACE
(psi as? KtClass)?.isEnum() ?: false -> UastClassKind.ENUM
@@ -95,7 +83,7 @@ class KotlinUClass(
override fun getSuperClass(context: UastContext): UClass? {
val descriptor = resolveToDescriptor() ?: return null
if (KotlinBuiltIns.isAny(descriptor)) return null
- val source = descriptor.getSuperClassOrAny().toSource(psi.project) ?: return null
+ val source = descriptor.getSuperClassOrAny().toSource() ?: return null
return context.convert(source) as? UClass
}
@@ -103,10 +91,7 @@ class KotlinUClass(
override val declarations by lz {
val primaryConstructor = if (psi is KtObjectDeclaration && psi.isObjectLiteral()) {
- val obj = psi
- object : KotlinObjectLiteralConstructorUFunction(obj, this) {
-
- }
+ KotlinObjectLiteralConstructorUFunction(psi, this)
} else {
psi.getPrimaryConstructor()?.let { KotlinConverter.convert(it, this) } ?: run {
if (psi.getSecondaryConstructors().isEmpty())
diff --git a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/declarations/KotlinUImportStatement.kt b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/declarations/KotlinUImportStatement.kt
index 0ba93bd5dac..8f2c2173f75 100644
--- a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/declarations/KotlinUImportStatement.kt
+++ b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/declarations/KotlinUImportStatement.kt
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.psi.KtImportDirective
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UImportStatement
import org.jetbrains.uast.UastContext
-import org.jetbrains.uast.kinds.UastImportKind
import org.jetbrains.uast.psi.PsiElementBacked
class KotlinUImportStatement(
@@ -29,10 +28,6 @@ class KotlinUImportStatement(
) : KotlinAbstractUElement(), UImportStatement, PsiElementBacked {
override val fqNameToImport = psi.importedFqName?.asString()
- //TODO support member imports
- override val kind: UastImportKind
- get() = UastImportKind.UNKNOWN
-
override val isStarImport: Boolean
get() = psi.isAllUnder
diff --git a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/declarations/KotlinUType.kt b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/declarations/KotlinUType.kt
index 0bf301590d4..f8e2b943c23 100644
--- a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/declarations/KotlinUType.kt
+++ b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/declarations/KotlinUType.kt
@@ -39,17 +39,21 @@ class KotlinUType(
override val fqName: String?
get() = type.constructor.declarationDescriptor?.fqNameSafe?.asString()
- override val isInt = name == "Int"
-
override fun resolve(context: UastContext): UClass? {
val descriptor = type.constructor.declarationDescriptor ?: return null
- val sourceElement = descriptor.toSource(project) ?: return null
+ val sourceElement = descriptor.toSource() ?: return null
return context.convert(sourceElement) as? UClass
}
override val isBoolean: Boolean
get() = checkType(KotlinBuiltIns.FQ_NAMES._boolean)
+ override val isInt: Boolean
+ get() = checkType(KotlinBuiltIns.FQ_NAMES._int)
+
+ override val isShort: Boolean
+ get() = checkType(KotlinBuiltIns.FQ_NAMES._short)
+
override val isLong: Boolean
get() = checkType(KotlinBuiltIns.FQ_NAMES._long)
diff --git a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/declarations/KotlinUVariable.kt b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/declarations/KotlinUVariable.kt
index 0f85189bf2d..8f4c171e027 100644
--- a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/declarations/KotlinUVariable.kt
+++ b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/declarations/KotlinUVariable.kt
@@ -42,12 +42,8 @@ open class KotlinUVariable(
KotlinConverter.convert(type, psi.project, this)
}
- override val getters: List? by lz {
- (psi as? KtProperty)?.accessors?.filter { it.isGetter }?.map { VariableAccessorFunction(it, this) }
- }
-
- override val setters: List? by lz {
- (psi as? KtProperty)?.accessors?.filter { it.isSetter }?.map { VariableAccessorFunction(it, this) }
+ override val accessors: List? by lz {
+ (psi as? KtProperty)?.accessors?.map { VariableAccessorFunction(it, this) }
}
override val kind: UastVariableKind
@@ -82,32 +78,33 @@ open class KotlinUVariable(
override val typeParameters: List
get() = emptyList()
+
override val typeParameterCount: Int
get() = 0
override val returnType: UType?
get() = if (psi.isSetter) null else parent.type
- override val body by lz { KotlinConverter.convertOrEmpty(psi.bodyExpression, this) }
+ override val body by lz { KotlinConverter.convertOrNull(psi.bodyExpression, this) }
override val visibility: UastVisibility
get() = psi.getVisibility()
- override fun getSuperFunctions(context: UastContext): List {
- throw UnsupportedOperationException()
- }
+ override fun getSuperFunctions(context: UastContext) = emptyList()
+
+ override val nameElement by lz { KotlinDumbUElement(psi.namePlaceholder, this) }
- override val nameElement: UElement?
- get() = throw UnsupportedOperationException()
override val name: String
- get() = throw UnsupportedOperationException()
+ get() = when {
+ psi.isSetter -> ""
+ psi.isGetter -> ""
+ else -> ""
+ }
- override fun hasModifier(modifier: UastModifier): Boolean {
- throw UnsupportedOperationException()
- }
+ override fun hasModifier(modifier: UastModifier) = false
override val annotations: List
- get() = throw UnsupportedOperationException()
+ get() = emptyList()
}
}
diff --git a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/declarations/kotlinUFunctions.kt b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/declarations/kotlinUFunctions.kt
index d8483cb876b..d530917c1f7 100644
--- a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/declarations/kotlinUFunctions.kt
+++ b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/declarations/kotlinUFunctions.kt
@@ -43,10 +43,11 @@ abstract class KotlinAbstractUFunction : KotlinAbstractUElement(), UFunction, Ps
override val valueParameters by lz { psi.valueParameters.map { KotlinConverter.convert(it, this) } }
override fun getSuperFunctions(context: UastContext): List {
+ if (this.isTopLevel()) return emptyList()
val bindingContext = psi.analyze(BodyResolveMode.PARTIAL)
val clazz = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, psi] as? FunctionDescriptor ?: return emptyList()
return clazz.overriddenDescriptors.map {
- context.convert(it.toSource(psi)) as? UFunction
+ context.convert(it.toSource()) as? UFunction
}.filterNotNull()
}
@@ -61,7 +62,7 @@ abstract class KotlinAbstractUFunction : KotlinAbstractUElement(), UFunction, Ps
override fun hasModifier(modifier: UastModifier) = psi.hasModifier(modifier)
override val annotations by lz { psi.getUastAnnotations(this) }
- override val body by lz { KotlinConverter.convertOrEmpty(psi.bodyExpression, this) }
+ override val body by lz { KotlinConverter.convertOrNull(psi.bodyExpression, this) }
override val visibility by lz { psi.getVisibility() }
}
@@ -126,7 +127,7 @@ class KotlinAnonymousInitializerUFunction(
override val returnType: UType?
get() = null
- override val body by lz { KotlinConverter.convertOrEmpty(psi.body, this) }
+ override val body by lz { KotlinConverter.convertOrNull(psi.body, this) }
override val visibility: UastVisibility
get() = UastVisibility.PRIVATE
@@ -168,7 +169,8 @@ open class KotlinDefaultPrimaryConstructorUFunction(
override val returnType: UType?
get() = null
- override val body: UExpression = EmptyExpression(this)
+ override val body: UExpression?
+ get() = null
override val visibility: UastVisibility
get() = parent.visibility
@@ -207,7 +209,7 @@ open class KotlinObjectLiteralConstructorUFunction(
get() = KotlinConverter.convert(param.type, psi.project, this)
override val nameElement: UElement?
get() = null
- override val parent: UElement?
+ override val parent: UElement
get() = this@KotlinObjectLiteralConstructorUFunction
override val name: String
get() = param.name.asString()
@@ -237,7 +239,8 @@ open class KotlinObjectLiteralConstructorUFunction(
override val returnType: UType?
get() = null
- override val body: UExpression = EmptyExpression(this)
+ override val body: UExpression?
+ get() = null
override val visibility: UastVisibility
get() = parent.visibility
diff --git a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUBinaryExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUBinaryExpression.kt
index 67ff90efd0d..e5ac4305f49 100644
--- a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUBinaryExpression.kt
+++ b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUBinaryExpression.kt
@@ -38,9 +38,6 @@ class KotlinUBinaryExpression(
KtTokens.PERC -> UastBinaryOperator.MOD
KtTokens.OROR -> UastBinaryOperator.LOGICAL_OR
KtTokens.ANDAND -> UastBinaryOperator.LOGICAL_AND
- //KtTokens.OR -> UastBinaryOperator.BITWISE_OR
- //KtTokens.AND -> UastBinaryOperator.BITWISE_AND
- //KtTokens.XOR -> UastBinaryOperator.BITWISE_XOR
KtTokens.EQEQ -> UastBinaryOperator.EQUALS
KtTokens.EXCLEQ -> UastBinaryOperator.NOT_EQUALS
KtTokens.EQEQEQ -> UastBinaryOperator.IDENTITY_EQUALS
@@ -56,6 +53,7 @@ class KotlinUBinaryExpression(
KtTokens.PERCEQ -> UastBinaryOperator.REMAINDER_ASSIGN
KtTokens.IN_KEYWORD -> KotlinBinaryOperators.IN
KtTokens.NOT_IN -> KotlinBinaryOperators.NOT_IN
+ KtTokens.RANGE -> KotlinBinaryOperators.RANGE_TO
else -> UastBinaryOperator.UNKNOWN
}
}
diff --git a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUBreakExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUBreakExpression.kt
new file mode 100644
index 00000000000..f768700758f
--- /dev/null
+++ b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUBreakExpression.kt
@@ -0,0 +1,31 @@
+/*
+ * 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.kotlin.uast.expressions
+
+import org.jetbrains.kotlin.psi.KtBreakExpression
+import org.jetbrains.kotlin.uast.KotlinAbstractUElement
+import org.jetbrains.uast.UBreakExpression
+import org.jetbrains.uast.UElement
+import org.jetbrains.uast.psi.PsiElementBacked
+
+class KotlinUBreakExpression(
+ override val psi: KtBreakExpression,
+ override val parent: UElement
+) : KotlinAbstractUElement(), UBreakExpression, PsiElementBacked {
+ override val label: String?
+ get() = psi.getLabelName()
+}
\ No newline at end of file
diff --git a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUCallableReferenceExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUCallableReferenceExpression.kt
new file mode 100644
index 00000000000..49ee5b7fbe9
--- /dev/null
+++ b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUCallableReferenceExpression.kt
@@ -0,0 +1,35 @@
+/*
+ * 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.kotlin.uast
+
+import org.jetbrains.kotlin.psi.KtCallableReferenceExpression
+import org.jetbrains.uast.*
+import org.jetbrains.uast.psi.PsiElementBacked
+
+class KotlinUCallableReferenceExpression(
+ override val psi: KtCallableReferenceExpression,
+ override val parent: UElement
+) : KotlinAbstractUElement(), UCallableReferenceExpression, PsiElementBacked, KotlinUElementWithType {
+ override val qualifierExpression = null
+ override val qualifierType by lz { KotlinConverter.convert(psi.typeReference, this) }
+ override val callableName: String
+ get() = psi.callableReference.getReferencedName()
+
+ override fun resolve(context: UastContext): UDeclaration? {
+ throw UnsupportedOperationException()
+ }
+}
\ No newline at end of file
diff --git a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUContinueExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUContinueExpression.kt
new file mode 100644
index 00000000000..010c36b64cb
--- /dev/null
+++ b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUContinueExpression.kt
@@ -0,0 +1,31 @@
+/*
+ * 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.kotlin.uast.expressions
+
+import org.jetbrains.kotlin.psi.KtContinueExpression
+import org.jetbrains.kotlin.uast.KotlinAbstractUElement
+import org.jetbrains.uast.UContinueExpression
+import org.jetbrains.uast.UElement
+import org.jetbrains.uast.psi.PsiElementBacked
+
+class KotlinUContinueExpression(
+ override val psi: KtContinueExpression,
+ override val parent: UElement
+) : KotlinAbstractUElement(), UContinueExpression, PsiElementBacked {
+ override val label: String?
+ get() = psi.getLabelName()
+}
\ No newline at end of file
diff --git a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUFunctionCallExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUFunctionCallExpression.kt
index 55b5e8c6213..9cdb46ebdc8 100644
--- a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUFunctionCallExpression.kt
+++ b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUFunctionCallExpression.kt
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.uast
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze
-import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
@@ -31,8 +30,8 @@ class KotlinUFunctionCallExpression(
override val psi: KtCallExpression,
override val parent: UElement
) : KotlinAbstractUElement(), UCallExpression, PsiElementBacked, KotlinUElementWithType {
- override val functionName: String?
- get() = (psi.calleeExpression as? KtSimpleNameExpression)?.getReferencedName()
+ override val functionName: String? by lz { resolveCall()?.resultingDescriptor?.name?.asString().orAnonymous() }
+ override fun matchesFunctionName(name: String) = functionName == name
override val functionNameElement by lz { psi.calleeExpression?.let { KotlinConverter.convert(it, this) } }
@@ -66,7 +65,7 @@ class KotlinUFunctionCallExpression(
override fun resolve(context: UastContext): UFunction? {
val resolvedCall = resolveCall()
val descriptor = resolvedCall?.resultingDescriptor ?: return null
- val source = descriptor.toSource(psi) ?: return null
+ val source = descriptor.toSource() ?: return null
if (descriptor is ConstructorDescriptor && descriptor.isPrimary
&& source is KtClassOrObject && source.getPrimaryConstructor() == null
@@ -95,65 +94,4 @@ class KotlinUComponentFunctionCallExpression(
override val functionNameElement = null
override val kind = UastCallKind.FUNCTION_CALL
override fun resolve(context: UastContext) = null
-}
-
-class KotlinUSuperConstructorCallExpression(
- override val psi: KtObjectDeclaration,
- override val parent: UElement,
- val resolvedCall: () -> ResolvedCall<*>?
-) : UCallExpression, PsiElementBacked {
- override val functionReference: USimpleReferenceExpression?
- get() = null
-
- override val classReference: USimpleReferenceExpression by lz {
- val referenceParent = this
- object : USimpleReferenceExpression, PsiElementBacked {
- override val parent: UElement?
- get() = referenceParent
-
- override val identifier: String
- get() = resolvedCall()?.resultingDescriptor?.name?.asString().orAnonymous()
-
- override fun resolve(context: UastContext): UDeclaration? {
- val descriptor = resolvedCall()?.resultingDescriptor ?: return null
- val source = DescriptorToSourceUtilsIde.getAnyDeclaration(psi.project, descriptor) ?: return null
- return context.convert(source) as? UDeclaration
- }
-
- override val psi: PsiElement
- get() = this@KotlinUSuperConstructorCallExpression.psi
- }
- }
-
- override val functionName: String?
- get() = ""
-
- override val functionNameElement by lz {
- try {
- KotlinDumbUElement(psi.getObjectKeyword(), this)
- } catch (e: NullPointerException) {
- null
- }
- }
-
- override val valueArgumentCount: Int
- get() = resolvedCall()?.valueArguments?.size ?: 0
-
- override val valueArguments by lz {
- resolvedCall()?.call?.valueArguments?.map { KotlinConverter.convertOrEmpty(it.getArgumentExpression(), this) } ?: emptyList()
- }
-
- override val typeArgumentCount: Int
- get() = 0
- override val typeArguments: List
- get() = emptyList()
-
- override val kind: UastCallKind
- get() = UastCallKind.CONSTRUCTOR_CALL
-
- override fun resolve(context: UastContext): UFunction? {
- val descriptor = resolvedCall()?.resultingDescriptor ?: return null
- val source = DescriptorToSourceUtilsIde.getAnyDeclaration(psi.project, descriptor) ?: return null
- return context.convert(source) as? UFunction
- }
}
\ No newline at end of file
diff --git a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinULabeledExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinULabeledExpression.kt
new file mode 100644
index 00000000000..f8924b11969
--- /dev/null
+++ b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinULabeledExpression.kt
@@ -0,0 +1,32 @@
+/*
+ * 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.kotlin.uast
+
+import org.jetbrains.kotlin.psi.KtLabeledExpression
+import org.jetbrains.uast.UElement
+import org.jetbrains.uast.ULabeledExpression
+import org.jetbrains.uast.psi.PsiElementBacked
+
+class KotlinULabeledExpression(
+ override val psi: KtLabeledExpression,
+ override val parent: UElement
+) : KotlinAbstractUElement(), ULabeledExpression, PsiElementBacked {
+ override val label: String
+ get() = psi.getLabelName().orAnonymous("label")
+
+ override val expression by lz { KotlinConverter.convertOrEmpty(psi.baseExpression, this) }
+}
\ 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 b13592ee099..2661dc1a65f 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
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.uast
+import com.intellij.openapi.util.text.StringUtil
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.idea.intentions.branchedTransformations.isNullExpression
import org.jetbrains.kotlin.psi.KtConstantExpression
@@ -30,20 +31,18 @@ class KotlinULiteralExpression(
override val isNull: Boolean
get() = psi.isNullExpression()
- override fun asString(): String = psi.text
-
override val value by lz { evaluate() }
}
class KotlinStringULiteralExpression(
override val psi: PsiElement,
- override val parent: UElement
-) : KotlinAbstractUElement(), ULiteralExpression, PsiElementBacked, KotlinUElementWithType, KotlinEvaluatableUElement {
+ override val parent: UElement,
+ val text: String? = null
+) : KotlinAbstractUElement(), ULiteralExpression, PsiElementBacked, KotlinUElementWithType{
override val isNull = false
- override fun asString(): String = '"' + psi.text + '"'
override val value: String
- get() = psi.text
+ get() = text ?: StringUtil.unescapeStringCharacters(psi.text)
- override fun evaluate() = psi.text
+ override fun evaluate() = value
}
\ No newline at end of file
diff --git a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUPrefixExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUPrefixExpression.kt
index 229c534ec6a..ec07a395d19 100644
--- a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUPrefixExpression.kt
+++ b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUPrefixExpression.kt
@@ -30,6 +30,7 @@ class KotlinUPrefixExpression(
override val operand by lz { KotlinConverter.convertOrEmpty(psi.baseExpression, this) }
override val operator = when (psi.operationToken) {
+ KtTokens.EXCL -> UastPrefixOperator.LOGICAL_NOT
KtTokens.PLUS -> UastPrefixOperator.UNARY_PLUS
KtTokens.MINUS -> UastPrefixOperator.UNARY_MINUS
KtTokens.PLUSPLUS -> UastPrefixOperator.INC
diff --git a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUQualifiedExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUQualifiedExpression.kt
index aa971b34da9..086ab84496e 100644
--- a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUQualifiedExpression.kt
+++ b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUQualifiedExpression.kt
@@ -16,8 +16,11 @@
package org.jetbrains.kotlin.uast
+import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.psi.KtDestructuringDeclarationEntry
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
+import org.jetbrains.kotlin.resolve.BindingContext
+import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.uast.*
import org.jetbrains.uast.psi.PsiElementBacked
@@ -43,5 +46,10 @@ class KotlinUComponentQualifiedExpression(
internal set
override val accessType = UastQualifiedExpressionAccessType.SIMPLE
- override fun resolve(context: UastContext) = null
+ override fun resolve(context: UastContext): UDeclaration? {
+ val bindingContext = psi.analyze(BodyResolveMode.PARTIAL)
+ val descriptor = bindingContext[BindingContext.COMPONENT_RESOLVED_CALL, psi]?.resultingDescriptor ?: return null
+ val source = descriptor.toSource() ?: return null
+ return context.convert(source) as? UDeclaration
+ }
}
\ No newline at end of file
diff --git a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUReturnExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUReturnExpression.kt
new file mode 100644
index 00000000000..14e23e7e90e
--- /dev/null
+++ b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUReturnExpression.kt
@@ -0,0 +1,29 @@
+/*
+ * 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.kotlin.uast
+
+import org.jetbrains.kotlin.psi.KtReturnExpression
+import org.jetbrains.uast.UElement
+import org.jetbrains.uast.UReturnExpression
+import org.jetbrains.uast.psi.PsiElementBacked
+
+class KotlinUReturnExpression(
+ override val psi: KtReturnExpression,
+ override val parent: UElement
+) : KotlinAbstractUElement(), UReturnExpression, PsiElementBacked, KotlinUElementWithType {
+ override val returnExpression by lz { KotlinConverter.convertOrNull(psi.returnedExpression, this) }
+}
\ No newline at end of file
diff --git a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUSimpleReferenceExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUSimpleReferenceExpression.kt
index 3b6adbdb6a8..0b95883fcb9 100644
--- a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUSimpleReferenceExpression.kt
+++ b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUSimpleReferenceExpression.kt
@@ -20,7 +20,6 @@ import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze
-import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
import org.jetbrains.kotlin.psi.KtCallExpression
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
@@ -42,7 +41,7 @@ open class KotlinUSimpleReferenceExpression(
resolvedCall.resultingDescriptor
}
- val source = DescriptorToSourceUtilsIde.getAnyDeclaration(psi.project, resultingDescriptor) ?: return null
+ val source = resultingDescriptor.toSource() ?: return null
return context.convert(source) as? UDeclaration
}
}
@@ -63,7 +62,7 @@ class KotlinClassViaConstructorUSimpleReferenceExpression(
val resolvedCall = psi.getResolvedCall(psi.analyze(BodyResolveMode.PARTIAL))
val resultingDescriptor = resolvedCall?.resultingDescriptor as? ConstructorDescriptor ?: return null
val clazz = resultingDescriptor.containingDeclaration
- val source = clazz.toSource(psi) ?: return null
+ val source = clazz.toSource() ?: return null
return context.convert(source) as? UClass
}
}
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 112792c82f5..1004c563971 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
@@ -28,7 +28,6 @@ class KotlinUSwitchExpression(
) : KotlinAbstractUElement(), USwitchExpression, PsiElementBacked, KotlinUElementWithType {
override val expression by lz { KotlinConverter.convertOrNull(psi.subjectExpression, this) }
- //TODO to entries
override val body: UExpression by lz {
object : KotlinUSpecialExpressionList(psi, KotlinSpecialExpressionKinds.WHEN, this) {
override fun renderString() = expressions.joinToString("\n") { it.renderString().withMargin }
@@ -48,8 +47,8 @@ class KotlinUSwitchExpression(
class KotlinUSwitchEntry(
override val psi: KtWhenEntry,
override val parent: UExpression
-) : KotlinAbstractUElement(), UExpression, PsiElementBacked {
- val conditions by lz {
+) : KotlinAbstractUElement(), USwitchClauseExpressionWithBody, PsiElementBacked {
+ override val caseValues by lz {
psi.conditions.map { when (it) {
is KtWhenConditionInRange -> KotlinCustomUBinaryExpression(it, this).apply {
leftOperand = KotlinStringUSimpleReferenceExpression("it", this)
@@ -68,11 +67,11 @@ class KotlinUSwitchEntry(
type = KotlinConverter.convert(it.typeReference, this)
}
is KtWhenConditionWithExpression -> KotlinConverter.convertOrEmpty(it.expression, this)
- else -> EmptyExpression(this)
+ else -> EmptyUExpression(this)
}}
}
- val expression: UExpression by lz {
+ override val body: UExpression by lz {
object : KotlinUSpecialExpressionList(psi, KotlinSpecialExpressionKinds.WHEN_ENTRY, this) {
override fun renderString() = buildString {
appendln("{")
@@ -85,25 +84,13 @@ class KotlinUSwitchEntry(
is KtBlockExpression -> exprPsi.statements.map { KotlinConverter.convert(it, this) }
else -> listOf(KotlinConverter.convertOrEmpty(exprPsi, this))
}
- expressions = userExpressions + KotlinUSpecialExpressionList.Empty(
- exprPsi ?: this@KotlinUSwitchEntry.psi, UastSpecialExpressionKind.BREAK, parent)
+ parent
+ expressions = userExpressions + object : UBreakExpression {
+ override val label: String?
+ get() = null
+ override val parent: UElement?
+ get() = this@KotlinUSwitchEntry
+ }
}
}
-
- override fun renderString() = buildString {
- if (conditions.isEmpty()) {
- append("else")
- } else {
- append(conditions.joinToString { it.renderString() })
- }
- append(" -> ")
- append(expression.renderString())
- }
-
- override fun logString() = log("KotlinUSwitchEntry", expression)
-
- 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/KotlinUThrowExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUThrowExpression.kt
new file mode 100644
index 00000000000..097f79bafe9
--- /dev/null
+++ b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/expressions/KotlinUThrowExpression.kt
@@ -0,0 +1,29 @@
+/*
+ * 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.kotlin.uast
+
+import org.jetbrains.kotlin.psi.KtThrowExpression
+import org.jetbrains.uast.UElement
+import org.jetbrains.uast.UThrowExpression
+import org.jetbrains.uast.psi.PsiElementBacked
+
+class KotlinUThrowExpression(
+ override val psi: KtThrowExpression,
+ override val parent: UElement
+) : KotlinAbstractUElement(), UThrowExpression, PsiElementBacked, KotlinUElementWithType {
+ override val thrownExpression by lz { KotlinConverter.convertOrEmpty(psi.thrownExpression, this) }
+}
\ No newline at end of file
diff --git a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/internal/kotlinInternalUastUtils.kt b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/internal/kotlinInternalUastUtils.kt
index c0ac0dc73ed..470f9a679bc 100644
--- a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/internal/kotlinInternalUastUtils.kt
+++ b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/internal/kotlinInternalUastUtils.kt
@@ -17,15 +17,12 @@
package org.jetbrains.kotlin.uast
import com.intellij.openapi.application.ApplicationManager
-import com.intellij.openapi.project.Project
-import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze
-import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierType
-import org.jetbrains.kotlin.resolve.BindingContext
+import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.uast.kinds.KotlinUastVisibilities
@@ -49,15 +46,18 @@ internal fun KtModifierListOwner.hasModifier(modifier: UastModifier): Boolean {
if (this is KtObjectDeclaration && this.isObjectLiteral()) {
return false
}
- return !hasModifier(KtTokens.INNER_KEYWORD)
- }
-
- if (modifier == UastModifier.FINAL) {
- if (hasModifier(KtTokens.FINAL_KEYWORD)) return true
- if (this is KtProperty && !this.isVar) return true
+ if (this is KtClassOrObject && !hasModifier(KtTokens.INNER_KEYWORD)) {
+ return true
+ }
+ if (this is KtDeclaration && parent is KtObjectDeclaration) {
+ return true
+ }
return false
}
+ if (modifier == UastModifier.IMMUTABLE && this is KtVariableDeclaration && !this.isVar) return true
+ if (modifier == UastModifier.FINAL && hasModifier(KtTokens.FINAL_KEYWORD)) return true
+
val javaModifier = MODIFIER_MAP[modifier] ?: return false
return hasModifier(javaModifier)
}
@@ -69,15 +69,7 @@ internal fun runReadAction(action: () -> T): T {
internal fun KtElement?.resolveCallToUDeclaration(context: UastContext): UDeclaration? {
if (this == null) return null
val resolvedCall = this.getResolvedCall(analyze(BodyResolveMode.PARTIAL)) ?: return null
- val source = (resolvedCall.resultingDescriptor).toSource(project) ?: return null
- return context.convert(source) as? UDeclaration
-}
-
-internal fun KtElement?.resolveElementToUDeclaration(context: UastContext): UDeclaration? {
- if (this == null) return null
- val bindingContext = analyze(BodyResolveMode.PARTIAL)
- val descriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, this] ?: return null
- val source = descriptor.toSource(project) ?: return null
+ val source = (resolvedCall.resultingDescriptor).toSource() ?: return null
return context.convert(source) as? UDeclaration
}
@@ -90,11 +82,8 @@ internal fun KtAnnotated.getUastAnnotations(parent: UElement) = annotationEntrie
internal fun singletonListOrEmpty(element: T?) = if (element != null) listOf(element) else emptyList()
-@Suppress("NOTHING_TO_INLINE")
-internal inline fun DeclarationDescriptor.toSource(element: PsiElement) = toSource(element.project)
-
-internal fun DeclarationDescriptor.toSource(project: Project) = try {
- DescriptorToSourceUtilsIde.getAnyDeclaration(project, this)
+internal fun DeclarationDescriptor.toSource() = try {
+ DescriptorToSourceUtils.descriptorToDeclaration(this)
} catch (e: Exception) {
null
}
diff --git a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/kinds/KotlinBinaryOperators.kt b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/kinds/KotlinBinaryOperators.kt
index 2e3447f424c..8098c315dcd 100644
--- a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/kinds/KotlinBinaryOperators.kt
+++ b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/kinds/KotlinBinaryOperators.kt
@@ -23,4 +23,7 @@ object KotlinBinaryOperators {
val IN = UastBinaryOperator("in")
@JvmField
val NOT_IN = UastBinaryOperator("!in")
+
+ @JvmField
+ val RANGE_TO = UastBinaryOperator("..")
}
\ No newline at end of file
diff --git a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/kinds/KotlinClassKinds.kt b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/kinds/KotlinClassKinds.kt
index a5c62519e99..b474b5dd726 100644
--- a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/kinds/KotlinClassKinds.kt
+++ b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/kinds/KotlinClassKinds.kt
@@ -16,12 +16,10 @@
package org.jetbrains.kotlin.uast
-import org.jetbrains.uast.kinds.UastClassKind
+import org.jetbrains.uast.UastClassKind
+
object KotlinClassKinds {
@JvmField
- val DEFAULT_COMPANION_OBJECT = UastClassKind.UastCompanionObject(true)
-
- @JvmField
- val NAMED_COMPANION_OBJECT = UastClassKind.UastCompanionObject(false)
+ val COMPANION_OBJECT = UastClassKind("companion object")
}
\ No newline at end of file
diff --git a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/lint/PropertyAsCallAndroidUastAdditionalChecker.kt b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/lint/PropertyAsCallAndroidUastAdditionalChecker.kt
index 4a75107e47c..cf4f3c9494a 100644
--- a/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/lint/PropertyAsCallAndroidUastAdditionalChecker.kt
+++ b/plugins/uast-kotlin/src/org/jetbrains/kotlin/uast/lint/PropertyAsCallAndroidUastAdditionalChecker.kt
@@ -25,10 +25,9 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.uast.*
import org.jetbrains.uast.*
-import org.jetbrains.uast.check.AndroidUastAdditionalChecker
import org.jetbrains.uast.psi.PsiElementBacked
-class PropertyAsCallAndroidUastAdditionalChecker : AndroidUastAdditionalChecker {
+class PropertyAsCallAndroidUastAdditionalChecker : UastAdditionalChecker {
override fun invoke(element: UElement, callback: UastCallback, context: UastContext) {
val expr = element as? KotlinUSimpleReferenceExpression ?: return
if (expr is KotlinNameUSimpleReferenceExpression) return
@@ -78,7 +77,7 @@ class PropertyAsCallAndroidUastAdditionalChecker : AndroidUastAdditionalChecker
override val kind = UastCallKind.FUNCTION_CALL
override fun resolve(context: UastContext): UFunction? {
- val source = accessorDescriptor.toSource(psi.project)
+ val source = accessorDescriptor.toSource()
if (source != null) {
(context.convert(source) as? UFunction)?.let { return it }
}
diff --git a/plugins/uast-kotlin/testData/ControlStructures.kt b/plugins/uast-kotlin/testData/ControlStructures.kt
index eaff37c7ecf..c460d37cdcb 100644
--- a/plugins/uast-kotlin/testData/ControlStructures.kt
+++ b/plugins/uast-kotlin/testData/ControlStructures.kt
@@ -1,59 +1,107 @@
class ControlStructures {
+ val prop = 3
+
+ fun nullFun(): String? = null
+
fun test(): Boolean {
- if (5 > 3) {
- println("5 > 3")
- }
+ ""
+// " "
+// "Z Z"
+//
+// val qwe = 2
+// " $qwe "
+// "5\n 2"
+// "\t\t\t"
- for (c in "ABC") {
- println(c)
- }
-
- for (c: Char in "DEF") {
- println(c.toByte())
- }
-
- var i = 5
- while (i > 0) {
- i--
- if (i == 3) break
- if (i == 2) {
- continue
- }
- }
-
- i = 5
- do {
- i -= 1
- } while (i > 0)
-
- "ABC".forEach { println(it.toString()[0]) }
-
- "ABC".zip("DEF").forEach { println(it.first + " " + it.second) }
-
- val (a, b) = "ABC".zip("DEF")
-
- val value = if (5 > 3) "a" else "b"
- val list = listOf("A")
- val list2 = listOf("A")
-
- val type = when (value) {
- in list -> "inlist"
- !in list2 -> "notinlist2"
- is String -> "string"
- is CharSequence -> "cs"
- else -> "unknown"
- }
-
- val x = when {
- value == "b" -> "B"
- 5 % 2 == 0 -> {
- println("A")
- "Q"
- }
- false -> "!"
- else -> "A"
- }
-
- return false
+// if (5 > 3) {
+// println("5 > 3")
+// }
+//
+// for (c in "ABC") {
+// println(c)
+// }
+//
+// for (c: Char in "DEF") {
+// println(c.toByte())
+// }
+//
+// var i = 5
+// while (i > 0) {
+// i--
+// if (i == 3) break
+// if (i == 2) {
+// continue
+// }
+// }
+//
+// "" is String
+// ("" as Any) as String?
+//
+// super.equals(this)
+// this.equals(this)
+//
+// this@ControlStructures.equals(this)
+//
+// ControlStructures::test
+// ControlStructures::prop
+// ControlStructures::class.java
+//
+// outer@ for (outerVal in 1..2) {
+// inner@ for (innerVal in 3..4) {
+// continue@outer
+// }
+// break@outer
+// }
+//
+// nullFun()?.let { println(it) }
+//
+// i = 5
+// do {
+// i -= 1
+// } while (i > 0)
+//
+// "ABC".forEach { println(it.toString()[0]) }
+//
+// "ABC".zip("DEF").forEach { println(it.first + " " + it.second) }
+//
+// val arr = arrayOf("A", "B", "C")
+// println(arr[2])
+//
+// val (a, b) = "ABC".zip("DEF")
+//
+// val value = if (5 > 3) "a" else "b"
+// val list = listOf("A")
+// val list2 = listOf("A")
+//
+// val type = when (value) {
+// in list -> "inlist"
+// !in list2 -> "notinlist2"
+// is String -> "string"
+// is CharSequence -> "cs"
+// else -> "unknown"
+// }
+//
+// val x = when {
+// value == "b" -> "B"
+// 5 % 2 == 0 -> {
+// println("A")
+// "Q"
+// }
+// false -> "!"
+// else -> "A"
+// }
+//
+// try {
+// 5 + 1
+// throw Exception()
+// } catch (e: Exception) {
+// e.printStackTrace()
+// } catch (thr: Throwable) {
+// System.out.println("error!")
+// } finally {
+// System.out.println("finally")
+// }
+//
+// return false
}
}
\ No newline at end of file
diff --git a/plugins/uast-kotlin/testData/Declarations.kt b/plugins/uast-kotlin/testData/Declarations.kt
index bb423f89146..05c2edf6dfa 100644
--- a/plugins/uast-kotlin/testData/Declarations.kt
+++ b/plugins/uast-kotlin/testData/Declarations.kt
@@ -1,5 +1,10 @@
class Declarations {
val a: String = "a"
+ var b: String
+ get() = "A"
+ set(v) { println(v) }
+ val c: String
+
class NestedClass {
val b: String = "b"
}
@@ -7,6 +12,14 @@ class Declarations {
val c: CharSequence = a
}
+ companion object {
+ val CONST_VAL = 1
+ }
+
+ companion object A {
+ fun b(): Boolean = true
+ }
+
fun func(a: Int, b: String): Int {
return (a + 1) * b.length
}
diff --git a/plugins/uast-kotlin/testData/log/Declarations.txt b/plugins/uast-kotlin/testData/log/Declarations.txt
index b2240295f9a..5bb903f36b7 100644
--- a/plugins/uast-kotlin/testData/log/Declarations.txt
+++ b/plugins/uast-kotlin/testData/log/Declarations.txt
@@ -1,22 +1,36 @@
-UFile (package = null)
+UFile (package = )
UClass (Declarations, kind = class)
- UFunction (, kind = CONSTRUCTOR, paramCount = 0)
+ UFunction (, kind = constructor, paramCount = 0)
EmptyExpression
UVariable (a, kind = member)
ULiteralExpression ("a")
+ UVariable (b, kind = member)
+ EmptyExpression
+ UVariable (c, kind = member)
+ EmptyExpression
UClass (NestedClass, kind = class)
- UFunction (, kind = CONSTRUCTOR, paramCount = 0)
+ UFunction (, kind = constructor, paramCount = 0)
EmptyExpression
UVariable (b, kind = member)
ULiteralExpression ("b")
UClass (InnerClass, kind = class)
- UFunction (, kind = CONSTRUCTOR, paramCount = 0)
+ UFunction (, kind = constructor, paramCount = 0)
EmptyExpression
UVariable (c, kind = member)
USimpleReferenceExpression (a)
+ UClass (Companion, kind = companion object)
+ UFunction (, kind = constructor, paramCount = 0)
+ EmptyExpression
+ UVariable (CONST_VAL, kind = member)
+ ULiteralExpression (1)
+ UClass (A, kind = companion object)
+ UFunction (, kind = constructor, paramCount = 0)
+ EmptyExpression
+ UFunction (b, kind = function, paramCount = 0)
+ ULiteralExpression (true)
UFunction (func, kind = function, paramCount = 2)
UBlockExpression
- USpecialExpressionList (return)
+ UReturnExpression
UBinaryExpression (*)
UParenthesizedExpression
UBinaryExpression (+)
diff --git a/plugins/uast-kotlin/testData/log/Simple.txt b/plugins/uast-kotlin/testData/log/Simple.txt
index c2c6f6a0ddf..262fc426347 100644
--- a/plugins/uast-kotlin/testData/log/Simple.txt
+++ b/plugins/uast-kotlin/testData/log/Simple.txt
@@ -1,6 +1,6 @@
-UFile (package = null)
+UFile (package = )
UClass (Simple, kind = class)
- UFunction (, kind = CONSTRUCTOR, paramCount = 0)
+ UFunction (, kind = constructor, paramCount = 0)
EmptyExpression
UVariable (a, kind = member)
UBinaryExpression (+)
diff --git a/plugins/uast-kotlin/testData/render/Declarations.txt b/plugins/uast-kotlin/testData/render/Declarations.txt
index 88c905cfb49..95af5700823 100644
--- a/plugins/uast-kotlin/testData/render/Declarations.txt
+++ b/plugins/uast-kotlin/testData/render/Declarations.txt
@@ -1,19 +1,42 @@
public static class Declarations {
public fun () = EmptyExpression
- var a: String = "a"
+
+ public immutable var a: String = "a"
+
+ public var b: String
+ public fun (): String = "A"
+ public fun (v: String) {
+ println(v)
+ }
+
+
+ public immutable var c: String
public static class NestedClass {
public fun () = EmptyExpression
- var b: String = "b"
+ public immutable var b: String = "b"
}
+
public class InnerClass {
public fun () = EmptyExpression
- var c: CharSequence = a
+ public immutable var c: CharSequence = a
}
+
+ public static companion object Companion {
+ public fun () = EmptyExpression
+
+ public immutable var CONST_VAL: Int = 1
+ }
+
+ public static companion object A {
+ public fun () = EmptyExpression
+
+ public fun b(): Boolean = true
+ }
+
public fun func(a: Int, b: String): Int {
return (a + 1) * b.length
}
-
}
diff --git a/plugins/uast-kotlin/testData/render/Simple.txt b/plugins/uast-kotlin/testData/render/Simple.txt
index b8256ae00b3..4bf7171b32f 100644
--- a/plugins/uast-kotlin/testData/render/Simple.txt
+++ b/plugins/uast-kotlin/testData/render/Simple.txt
@@ -1,8 +1,8 @@
public static class Simple {
public fun () = EmptyExpression
- var a: String = "text" + "other" + "text"
+ public immutable var a: String = "text" + "other" + "text"
- var b: List = listOf("A")
+ public immutable var b: List = listOf("A")
public fun test(): Unit {
System.out.println(5.0f / 2)