diff --git a/idea/testData/android/lint/wrongAnnotation.kt b/idea/testData/android/lint/wrongAnnotation.kt
index 62cb9f47bec..163256a6b51 100644
--- a/idea/testData/android/lint/wrongAnnotation.kt
+++ b/idea/testData/android/lint/wrongAnnotation.kt
@@ -15,24 +15,27 @@ class WrongAnnotation2 {
@SuppressLint("NewApi") // Valid: class-file check on method
fun foobar(view: View, @SuppressLint("NewApi") foo: Int) {
// Invalid: class-file check
- @SuppressLint("NewApi") // Invalid
+ @SuppressLint("NewApi") // Invalid
val a: Boolean
- @SuppressLint("SdCardPath", "NewApi") // Invalid: class-file based check on local variable
+
+ @SuppressLint("SdCardPath", "NewApi") // TODO: Invalid, class-file based check on local variable
val b: Boolean
- @android.annotation.SuppressLint("SdCardPath", "NewApi") // Invalid (FQN)
+
+ @android.annotation.SuppressLint("SdCardPath", "NewApi") // TDOD: Invalid (FQN)
val c: Boolean
+
@SuppressLint("SdCardPath") // Valid: AST-based check
val d: Boolean
}
init {
// Local variable outside method: invalid
- @SuppressLint("NewApi")
+ @SuppressLint("NewApi")
val localvar = 5
}
private fun test() {
- @SuppressLint("NewApi") // Invalid
+ @SuppressLint("NewApi") // Invalid
val a = View.MEASURED_STATE_MASK
}
}
diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt
index 755308677a3..f88af3a9d7d 100644
--- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt
+++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt
@@ -224,7 +224,7 @@ internal object KotlinConverter {
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
KotlinUDeclarationsExpression(parent).apply {
declarations = element.parameters.mapIndexed { i, p ->
- KotlinUVariable.create(UastKotlinPsiParameter.create(p, element, parent!!, i), this)
+ KotlinUParameter(UastKotlinPsiParameter.create(p, element, parent!!, i), this)
}
}
}
@@ -307,13 +307,12 @@ internal object KotlinConverter {
is KtDestructuringDeclaration -> expr {
val parent = if (parentCallback == null) null else (parentCallback() ?: return null)
KotlinUDeclarationsExpression(parent).apply {
- val tempAssignment = KotlinUVariable.create(UastKotlinPsiVariable.create(expression, parent!!), parent)
+ val tempAssignment = KotlinULocalVariable(UastKotlinPsiVariable.create(expression, parent!!), parent)
val destructuringAssignments = expression.entries.mapIndexed { i, entry ->
val psiFactory = KtPsiFactory(expression.project)
val initializer = psiFactory.createAnalyzableExpression("${tempAssignment.name}.component${i + 1}()",
expression.containingFile)
- KotlinUVariable.create(UastKotlinPsiVariable.create(
- entry, tempAssignment.psi, parent, initializer), parent)
+ KotlinULocalVariable(UastKotlinPsiVariable.create(entry, tempAssignment.psi, parent, initializer), parent)
}
declarations = listOf(tempAssignment) + destructuringAssignments
}
@@ -368,7 +367,6 @@ internal object KotlinConverter {
expr(build(::createLocalFunctionDeclaration))
}
-
else -> expr(build(::UnknownKotlinExpression))
}}
}
@@ -403,6 +401,9 @@ private fun convertVariablesDeclaration(
parent: UElement?
): UDeclarationsExpression {
val parentPsiElement = parent?.psi
- val variable = KotlinUVariable.create(UastKotlinPsiVariable.create(psi, parentPsiElement, parent!!), parent)
+ val variable = KotlinUAnnotatedLocalVariable(
+ UastKotlinPsiVariable.create(psi, parentPsiElement, parent!!), parent) { annotationParent ->
+ psi.annotationEntries.map { KotlinUAnnotation(it, annotationParent) }
+ }
return KotlinUDeclarationsExpression(parent).apply { declarations = listOf(variable) }
}
diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUClass.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUClass.kt
index 1e8daa05615..6b1194f34c3 100644
--- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUClass.kt
+++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUClass.kt
@@ -96,7 +96,7 @@ class KotlinUClass private constructor(
}
}
} else {
- getLanguagePlugin().convert(psiMethod, this)
+ getLanguagePlugin().convert(psiMethod, this)
}
}
diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUVariable.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUVariable.kt
index 055f5598f36..e3e6fa8b419 100644
--- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUVariable.kt
+++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUVariable.kt
@@ -24,16 +24,16 @@ import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.KtVariableDeclaration
import org.jetbrains.uast.*
import org.jetbrains.uast.internal.acceptList
-import org.jetbrains.uast.java.AbstractJavaUVariable
import org.jetbrains.uast.java.JavaAbstractUExpression
import org.jetbrains.uast.java.JavaUAnnotation
import org.jetbrains.uast.java.annotations
import org.jetbrains.uast.kotlin.declarations.UastLightIdentifier
+import org.jetbrains.uast.kotlin.internal.KotlinUElementWithComments
import org.jetbrains.uast.kotlin.psi.UastKotlinPsiParameter
import org.jetbrains.uast.kotlin.psi.UastKotlinPsiVariable
import org.jetbrains.uast.visitor.UastVisitor
-abstract class AbstractKotlinUVariable : AbstractJavaUVariable() {
+abstract class AbstractKotlinUVariable : PsiVariable, UVariable, KotlinUElementWithComments {
override val uastInitializer: UExpression?
get() {
val psi = psi
@@ -68,6 +68,17 @@ abstract class AbstractKotlinUVariable : AbstractJavaUVariable() {
val kotlinOrigin = (psi as? KtLightElement<*, *>)?.kotlinOrigin
return UastLightIdentifier(psi, kotlinOrigin as KtNamedDeclaration?)
}
+
+ override val annotations: List by lz { psi.annotations.map { JavaUAnnotation(it, this) } }
+
+ override val typeReference by lz { getLanguagePlugin().convertOpt(psi.typeElement, this) }
+
+ override val uastAnchor: UElement?
+ get() = UIdentifier(psi.nameIdentifier, this)
+
+ override fun equals(other: Any?) = other is AbstractKotlinUVariable && psi == other.psi
+
+ override fun hashCode() = psi.hashCode()
}
class KotlinUVariable(
@@ -77,6 +88,7 @@ class KotlinUVariable(
override val psi = unwrap(psi)
override val annotations by lz { psi.annotations.map { JavaUAnnotation(it, this) } }
+
override val typeReference by lz { getLanguagePlugin().convertOpt(psi.typeElement, this) }
override fun getContainingFile(): PsiFile? = (psi as? KtLightElement<*, *>)?.kotlinOrigin?.containingFile ?: psi.containingFile
@@ -92,18 +104,6 @@ class KotlinUVariable(
override fun getNameIdentifier(): PsiIdentifier {
return super.getNameIdentifier()
}
-
- companion object {
- fun create(psi: PsiVariable, containingElement: UElement?): UVariable {
- return when (psi) {
- is PsiEnumConstant -> KotlinUEnumConstant(psi, containingElement)
- is PsiLocalVariable -> KotlinULocalVariable(psi, containingElement)
- is PsiParameter -> KotlinUParameter(psi, containingElement)
- is PsiField -> KotlinUField(psi, containingElement)
- else -> KotlinUVariable(psi, containingElement)
- }
- }
- }
}
open class KotlinUParameter(
@@ -188,6 +188,15 @@ open class KotlinULocalVariable(
}
}
+open class KotlinUAnnotatedLocalVariable(
+ psi: PsiLocalVariable,
+ uastParent: UElement?,
+ computeAnnotations: (parent: UElement) -> List
+) : KotlinULocalVariable(psi, uastParent) {
+
+ override val annotations: List by lz { computeAnnotations(this) }
+}
+
open class KotlinUEnumConstant(
psi: PsiEnumConstant,
override val uastParent: UElement?
diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/ElvisExpression.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/ElvisExpression.kt
index f827b8f399a..b6a39c01b19 100644
--- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/ElvisExpression.kt
+++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/ElvisExpression.kt
@@ -47,8 +47,7 @@ private fun createElvisExpressions(
psiParent: PsiElement): List {
val declaration = KotlinUDeclarationsExpression(containingElement)
- val tempVariable = KotlinUVariable.create(UastKotlinPsiVariable.create(left, declaration, psiParent),
- declaration)
+ val tempVariable = KotlinULocalVariable(UastKotlinPsiVariable.create(left, declaration, psiParent), declaration)
declaration.declarations = listOf(tempVariable)
val ifExpression = object : UIfExpression {
diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/KotlinUElementWithComments.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/KotlinUElementWithComments.kt
new file mode 100644
index 00000000000..1c5de8fa704
--- /dev/null
+++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/KotlinUElementWithComments.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2010-2017 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jetbrains.uast.kotlin.internal
+
+import com.intellij.psi.PsiComment
+import org.jetbrains.uast.UComment
+import org.jetbrains.uast.UElement
+
+interface KotlinUElementWithComments : UElement {
+ override val comments: List
+ get() {
+ val psi = psi ?: return emptyList()
+ return psi.children.filter { it is PsiComment }.map { UComment(it, this) }
+ }
+}
\ No newline at end of file
diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/psi/UastKotlinPsiVariable.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/psi/UastKotlinPsiVariable.kt
index 77cf13e027d..7889f073829 100644
--- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/psi/UastKotlinPsiVariable.kt
+++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/psi/UastKotlinPsiVariable.kt
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
+import org.jetbrains.kotlin.utils.ifEmpty
import org.jetbrains.uast.UDeclaration
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UastErrorType
@@ -62,7 +63,7 @@ class UastKotlinPsiVariable(
parent: PsiElement?,
containingElement: UElement,
initializer: KtExpression? = null
- ): PsiVariable {
+ ): PsiLocalVariable {
val psiParent = containingElement.getParentOfType()?.psi ?: parent
return UastKotlinPsiVariable(
declaration.manager,
@@ -74,7 +75,7 @@ class UastKotlinPsiVariable(
declaration)
}
- fun create(declaration: KtDestructuringDeclaration, containingElement: UElement): PsiVariable {
+ fun create(declaration: KtDestructuringDeclaration, containingElement: UElement): PsiLocalVariable {
val psiParent = containingElement.getParentOfType()?.psi ?: declaration.parent
return UastKotlinPsiVariable(
declaration.manager,
@@ -86,7 +87,7 @@ class UastKotlinPsiVariable(
declaration)
}
- fun create(initializer: KtExpression, containingElement: UElement, parent: PsiElement): PsiVariable {
+ fun create(initializer: KtExpression, containingElement: UElement, parent: PsiElement): PsiLocalVariable {
val psiParent = containingElement.getParentOfType()?.psi ?: parent
return UastKotlinPsiVariable(
initializer.manager,
@@ -98,7 +99,7 @@ class UastKotlinPsiVariable(
initializer)
}
- fun create(name: String, localFunction: KtFunction, containingElement: UElement): PsiVariable {
+ fun create(name: String, localFunction: KtFunction, containingElement: UElement): PsiLocalVariable {
val psiParent = containingElement.getParentOfType()?.psi ?: localFunction.parent
return UastKotlinPsiVariable(
localFunction.manager,