diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/modules/javaVersionUtils.kt.173 b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/modules/javaVersionUtils.kt.173 deleted file mode 100644 index c749d40a32b..00000000000 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/modules/javaVersionUtils.kt.173 +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license - * that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.cli.jvm.modules - -import com.intellij.openapi.util.SystemInfo - -fun isAtLeastJava9(): Boolean { - return SystemInfo.isJavaVersionAtLeast("9") -} diff --git a/compiler/daemon/daemon-client/build.gradle.kts.173 b/compiler/daemon/daemon-client/build.gradle.kts.173 deleted file mode 100644 index 10bfad5bf90..00000000000 --- a/compiler/daemon/daemon-client/build.gradle.kts.173 +++ /dev/null @@ -1,60 +0,0 @@ -import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar - -description = "Kotlin Daemon Client" - -plugins { - kotlin("jvm") - id("jps-compatible") -} - -jvmTarget = "1.6" - -val nativePlatformVariants = listOf( - "windows-amd64", - "windows-i386", - "osx-amd64", - "osx-i386", - "linux-amd64", - "linux-i386", - "freebsd-amd64-libcpp", - "freebsd-amd64-libstdcpp", - "freebsd-i386-libcpp", - "freebsd-i386-libstdcpp" -) - -dependencies { - compileOnly(project(":compiler:util")) - compileOnly(project(":compiler:cli-common")) - compileOnly(project(":compiler:daemon-common")) - compileOnly(project(":kotlin-reflect-api")) - compileOnly(project(":js:js.frontend")) - compileOnly(commonDep("net.rubygrapefruit", "native-platform")) - - embeddedComponents(project(":compiler:daemon-common")) { isTransitive = false } - embeddedComponents(commonDep("net.rubygrapefruit", "native-platform")) - nativePlatformVariants.forEach { - embeddedComponents(commonDep("net.rubygrapefruit", "native-platform", "-$it")) - } -} - -sourceSets { - "main" { projectDefault() } - "test" {} -} - -noDefaultJar() - -runtimeJar(task("shadowJar")) { - from(mainSourceSet.output) - fromEmbeddedComponents() -} - -sourcesJar() - -javadocJar() - -dist() - -ideaPlugin() - -publish() diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/builder/LightClassBuilder.kt.173 b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/builder/LightClassBuilder.kt.173 deleted file mode 100644 index ff9b11a1d16..00000000000 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/builder/LightClassBuilder.kt.173 +++ /dev/null @@ -1,142 +0,0 @@ -/* - * 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.kotlin.asJava.builder - -import com.intellij.openapi.components.ServiceManager -import com.intellij.openapi.diagnostic.Logger -import com.intellij.openapi.progress.ProcessCanceledException -import com.intellij.openapi.project.Project -import com.intellij.openapi.util.SystemInfo -import com.intellij.openapi.vfs.VirtualFile -import com.intellij.psi.ClassFileViewProvider -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiManager -import com.intellij.psi.impl.compiled.ClsFileImpl -import com.intellij.psi.impl.java.stubs.PsiJavaFileStub -import com.intellij.psi.impl.java.stubs.impl.PsiJavaFileStubImpl -import com.intellij.psi.impl.source.tree.TreeElement -import org.jetbrains.kotlin.codegen.state.GenerationState -import org.jetbrains.kotlin.config.* -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics -import java.lang.StringBuilder - -data class LightClassBuilderResult(val stub: PsiJavaFileStub, val bindingContext: BindingContext, val diagnostics: Diagnostics) - -fun buildLightClass( - packageFqName: FqName, - files: Collection, - generateClassFilter: GenerationState.GenerateClassFilter, - context: LightClassConstructionContext, - generate: (state: GenerationState, files: Collection) -> Unit -): LightClassBuilderResult { - val project = files.first().project - - try { - val classBuilderFactory = KotlinLightClassBuilderFactory(createJavaFileStub(project, packageFqName, files)) - val state = GenerationState.Builder( - project, - classBuilderFactory, - context.module, - context.bindingContext, - files.toList(), - context.languageVersionSettings?.let { - CompilerConfiguration().apply { - languageVersionSettings = it - isReadOnly = true - } - } ?: CompilerConfiguration.EMPTY - ).generateDeclaredClassFilter(generateClassFilter).wantsDiagnostics(false).build() - state.beforeCompile() - - generate(state, files) - - val javaFileStub = classBuilderFactory.result() - - ServiceManager.getService(project, StubComputationTracker::class.java)?.onStubComputed(javaFileStub, context) - return LightClassBuilderResult(javaFileStub, context.bindingContext, state.collectedExtraJvmDiagnostics) - } - catch (e: ProcessCanceledException) { - throw e - } - catch (e: RuntimeException) { - logErrorWithOSInfo(e, packageFqName, null) - throw e - } -} - -private fun createJavaFileStub(project: Project, packageFqName: FqName, files: Collection): PsiJavaFileStub { - val javaFileStub = PsiJavaFileStubImpl(packageFqName.asString(), /*compiled = */true) - javaFileStub.psiFactory = ClsWrapperStubPsiFactory.INSTANCE - - val manager = PsiManager.getInstance(project) - - val virtualFile = getRepresentativeVirtualFile(files) - val fakeFile = object : ClsFileImpl(ClassFileViewProvider(manager, virtualFile)) { - override fun getStub() = javaFileStub - - override fun getPackageName() = packageFqName.asString() - - override fun isPhysical() = false - - override fun appendMirrorText(indentLevel: Int, buffer: StringBuilder) { - if (files.size == 1) { - LOG.error("Mirror text should never be calculated for light classes generated from a single file") - } - super.appendMirrorText(indentLevel, buffer) - } - - - override fun setMirror(element: TreeElement) { - if (files.size == 1) { - LOG.error("Mirror element should never be set for light classes generated from a single file") - } - super.setMirror(element) - } - - override fun getMirror(): PsiElement { - if (files.size == 1) { - LOG.error("Mirror element should never be calculated for light classes generated from a single file") - } - return super.getMirror() - } - - override fun getText(): String { - return files.singleOrNull()?.text ?: super.getText() - } - } - - javaFileStub.psi = fakeFile - return javaFileStub -} - -private fun getRepresentativeVirtualFile(files: Collection): VirtualFile { - return files.first().viewProvider.virtualFile -} - -private fun logErrorWithOSInfo(cause: Throwable?, fqName: FqName, virtualFile: VirtualFile?) { - val path = if (virtualFile == null) "" else virtualFile.path - LOG.error( - "Could not generate LightClass for $fqName declared in $path\n" + - "System: ${SystemInfo.OS_NAME} ${SystemInfo.OS_VERSION} Java Runtime: ${SystemInfo.JAVA_RUNTIME_VERSION}", - cause - ) -} - -private val LOG = Logger.getInstance(LightClassBuilderResult::class.java) \ No newline at end of file diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/FakeFileForLightClass.kt.173 b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/FakeFileForLightClass.kt.173 deleted file mode 100644 index 8645df9afd3..00000000000 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/FakeFileForLightClass.kt.173 +++ /dev/null @@ -1,86 +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.kotlin.asJava.elements - -import com.intellij.pom.java.LanguageLevel -import com.intellij.psi.ClassFileViewProvider -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiElementVisitor -import com.intellij.psi.impl.compiled.ClsFileImpl -import com.intellij.psi.stubs.PsiClassHolderFileStub -import org.jetbrains.kotlin.asJava.classes.KtLightClass -import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade -import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.psi.KtFile - -open class FakeFileForLightClass( - val ktFile: KtFile, - private val lightClass: () -> KtLightClass, - private val stub: () -> PsiClassHolderFileStub<*>, - private val packageFqName: FqName = ktFile.packageFqName -) : ClsFileImpl(ClassFileViewProvider(ktFile.manager, ktFile.virtualFile ?: - ktFile.originalFile.virtualFile ?: - ktFile.viewProvider.virtualFile)) { - override fun getPackageName() = packageFqName.asString() - - override fun getStub() = stub() - - override fun getClasses() = arrayOf(lightClass()) - - override fun getNavigationElement() = ktFile - - override fun accept(visitor: PsiElementVisitor) { - // Prevent access to compiled PSI - // TODO: More complex traversal logic may be implemented when necessary - } - - // this should be equal to current compiler target language level - override fun getLanguageLevel() = LanguageLevel.JDK_1_6 - - override fun hashCode(): Int { - val thisClass = lightClass() - if (thisClass is KtLightClassForSourceDeclaration) return ktFile.hashCode() - return thisClass.hashCode() - } - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is FakeFileForLightClass) return false - val thisClass = lightClass() - val anotherClass = other.lightClass() - - if (thisClass is KtLightClassForSourceDeclaration) { - return anotherClass is KtLightClassForSourceDeclaration && ktFile == other.ktFile - } - - return thisClass == anotherClass - } - - override fun isEquivalentTo(another: PsiElement?) = this == another - - override fun setPackageName(packageName: String) { - if (lightClass() is KtLightClassForFacade) { - ktFile.packageDirective?.fqName = FqName(packageName) - } - else { - super.setPackageName(packageName) - } - } - - override fun isPhysical() = false -} \ No newline at end of file diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightAnnotationsValues.kt.173 b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightAnnotationsValues.kt.173 deleted file mode 100644 index e92006027a3..00000000000 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightAnnotationsValues.kt.173 +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license - * that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.asJava.elements - -import com.intellij.openapi.util.text.StringUtil -import com.intellij.psi.* -import com.intellij.psi.impl.LanguageConstantExpressionEvaluator -import com.intellij.psi.impl.light.LightIdentifier -import com.intellij.psi.impl.light.LightTypeElement -import org.jetbrains.kotlin.asJava.LightClassGenerationSupport -import org.jetbrains.kotlin.asJava.classes.lazyPub -import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap -import org.jetbrains.kotlin.name.FqNameUnsafe -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.constants.KClassValue -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe -import org.jetbrains.kotlin.types.TypeUtils -import org.jetbrains.kotlin.utils.addToStdlib.safeAs - -class KtLightPsiArrayInitializerMemberValue( - override val kotlinOrigin: KtElement, - val lightParent: PsiElement, - private val arguments: (KtLightPsiArrayInitializerMemberValue) -> List -) : KtLightElementBase(lightParent), PsiArrayInitializerMemberValue { - override fun getInitializers(): Array = arguments(this).toTypedArray() - - override fun getParent(): PsiElement = lightParent - - override fun isPhysical(): Boolean = true -} - -open class KtLightPsiLiteral( - override val kotlinOrigin: KtExpression, - val lightParent: PsiElement -) : KtLightElementBase(lightParent), PsiLiteralExpression { - - override fun getValue(): Any? = - LanguageConstantExpressionEvaluator.INSTANCE.forLanguage(kotlinOrigin.language)?.computeConstantExpression(this, false) - - override fun getType(): PsiType? { - val bindingContext = LightClassGenerationSupport.getInstance(this.project).analyze(kotlinOrigin) - val kotlinType = bindingContext[BindingContext.EXPECTED_EXPRESSION_TYPE, kotlinOrigin] ?: return null - val typeFqName = kotlinType.constructor.declarationDescriptor?.fqNameSafe?.asString() ?: return null - return psiType(typeFqName, kotlinOrigin) - } - - override fun getParent(): PsiElement = lightParent - - override fun isPhysical(): Boolean = true - - override fun replace(newElement: PsiElement): PsiElement { - val value = (newElement as? PsiLiteral)?.value as? String ?: return this - kotlinOrigin.replace(KtPsiFactory(this).createExpression("\"${StringUtil.escapeStringCharacters(value)}\"")) - return this - } - - override fun getReference(): PsiReference? = references.singleOrNull() - override fun getReferences(): Array = kotlinOrigin.references -} - -class KtLightPsiClassObjectAccessExpression(override val kotlinOrigin: KtClassLiteralExpression, lightParent: PsiElement) : - KtLightPsiLiteral(kotlinOrigin, lightParent), PsiClassObjectAccessExpression { - override fun getType(): PsiType { - val bindingContext = LightClassGenerationSupport.getInstance(this.project).analyze(kotlinOrigin) - val (classId, arrayDimensions) = bindingContext[BindingContext.COMPILE_TIME_VALUE, kotlinOrigin] - ?.toConstantValue(TypeUtils.NO_EXPECTED_TYPE)?.safeAs()?.value ?: return PsiType.VOID - var type = psiType(classId.asSingleFqName().asString(), kotlinOrigin, boxPrimitiveType = arrayDimensions > 0) ?: return PsiType.VOID - repeat(arrayDimensions) { - type = type.createArrayType() - } - return type - } - - override fun getOperand(): PsiTypeElement = LightTypeElement(kotlinOrigin.manager, type) -} - -internal fun psiType(kotlinFqName: String, context: PsiElement, boxPrimitiveType: Boolean = false): PsiType { - if (!boxPrimitiveType) { - when (kotlinFqName) { - "kotlin.Int" -> return PsiType.INT - "kotlin.Long" -> return PsiType.LONG - "kotlin.Short" -> return PsiType.SHORT - "kotlin.Boolean" -> return PsiType.BOOLEAN - "kotlin.Byte" -> return PsiType.BYTE - "kotlin.Char" -> return PsiType.CHAR - "kotlin.Double" -> return PsiType.DOUBLE - "kotlin.Float" -> return PsiType.FLOAT - } - } - when (kotlinFqName) { - "kotlin.IntArray" -> return PsiType.INT.createArrayType() - "kotlin.LongArray" -> return PsiType.LONG.createArrayType() - "kotlin.ShortArray" -> return PsiType.SHORT.createArrayType() - "kotlin.BooleanArray" -> return PsiType.BOOLEAN.createArrayType() - "kotlin.ByteArray" -> return PsiType.BYTE.createArrayType() - "kotlin.CharArray" -> return PsiType.CHAR.createArrayType() - "kotlin.DoubleArray" -> return PsiType.DOUBLE.createArrayType() - "kotlin.FloatArray" -> return PsiType.FLOAT.createArrayType() - } - val javaFqName = JavaToKotlinClassMap.mapKotlinToJava(FqNameUnsafe(kotlinFqName))?.asSingleFqName()?.asString() ?: kotlinFqName - return PsiType.getTypeByName(javaFqName, context.project, context.resolveScope) -} - -class KtLightPsiNameValuePair private constructor( - override val kotlinOrigin: KtElement, - val valueArgument: KtValueArgument, - lightParent: PsiElement, - private val argument: (KtLightPsiNameValuePair) -> PsiAnnotationMemberValue? -) : KtLightElementBase(lightParent), - PsiNameValuePair { - - constructor( - valueArgument: KtValueArgument, - lightParent: PsiElement, - argument: (KtLightPsiNameValuePair) -> PsiAnnotationMemberValue? - ) : this(valueArgument.asElement(), valueArgument, lightParent, argument) - - override fun setValue(newValue: PsiAnnotationMemberValue): PsiAnnotationMemberValue = - throw UnsupportedOperationException("can't modify KtLightPsiNameValuePair") - - override fun getNameIdentifier(): PsiIdentifier? = LightIdentifier(kotlinOrigin.manager, valueArgument.name) - - override fun getName(): String? = valueArgument.getArgumentName()?.asName?.asString() - - private val _value: PsiAnnotationMemberValue? by lazyPub { argument(this) } - - override fun getValue(): PsiAnnotationMemberValue? = _value - - override fun getLiteralValue(): String? = (getValue() as? PsiLiteralExpression)?.value?.toString() - -} diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/lightAnnotations.kt.173 b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/lightAnnotations.kt.173 deleted file mode 100644 index 06c8ad8f398..00000000000 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/lightAnnotations.kt.173 +++ /dev/null @@ -1,425 +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.kotlin.asJava.elements - -import com.intellij.openapi.application.ApplicationManager -import com.intellij.openapi.diagnostic.Logger -import com.intellij.psi.* -import com.intellij.psi.util.PsiTreeUtil -import org.jetbrains.annotations.NotNull -import org.jetbrains.annotations.Nullable -import org.jetbrains.annotations.TestOnly -import org.jetbrains.kotlin.asJava.LightClassGenerationSupport -import org.jetbrains.kotlin.asJava.classes.cannotModify -import org.jetbrains.kotlin.asJava.classes.lazyPub -import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.descriptors.CallableDescriptor -import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor -import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor -import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor -import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.load.java.descriptors.JavaClassConstructorDescriptor -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject -import org.jetbrains.kotlin.psi.psiUtil.getParentOfType -import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.CompileTimeConstantUtils -import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall -import org.jetbrains.kotlin.resolve.calls.callUtil.getType -import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall -import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument -import org.jetbrains.kotlin.resolve.descriptorUtil.declaresOrInheritsDefaultValue -import org.jetbrains.kotlin.resolve.source.getPsi -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.TypeUtils -import org.jetbrains.kotlin.types.typeUtil.TypeNullability -import org.jetbrains.kotlin.types.typeUtil.isTypeParameter -import org.jetbrains.kotlin.types.typeUtil.isUnit -import org.jetbrains.kotlin.types.typeUtil.nullability - -private val LOG = Logger.getInstance("#org.jetbrains.kotlin.asJava.elements.lightAnnotations") - -abstract class KtLightAbstractAnnotation(parent: PsiElement, computeDelegate: () -> PsiAnnotation) : - KtLightElementBase(parent), PsiAnnotation, KtLightElement { - - private val _clsDelegate: PsiAnnotation by lazyPub(computeDelegate) - - override val clsDelegate: PsiAnnotation - get() { - if (!accessAnnotationsClsDelegateIsAllowed && ApplicationManager.getApplication().isUnitTestMode && this !is KtLightNonSourceAnnotation) - LOG.error("KtLightAbstractAnnotation clsDelegate requested for ${this.javaClass}") - return _clsDelegate - } - - override fun getNameReferenceElement() = clsDelegate.nameReferenceElement - - override fun getOwner() = parent as? PsiAnnotationOwner - - override fun getMetaData() = clsDelegate.metaData - - override fun getParameterList() = clsDelegate.parameterList - - override fun canNavigate(): Boolean = super.canNavigate() - - override fun canNavigateToSource(): Boolean = super.canNavigateToSource() - - override fun navigate(requestFocus: Boolean) = super.navigate(requestFocus) - - open fun fqNameMatches(fqName: String): Boolean = qualifiedName == fqName -} - -class KtLightAnnotationForSourceEntry( - private val qualifiedName: String, - override val kotlinOrigin: KtCallElement, - parent: PsiElement, - computeDelegate: () -> PsiAnnotation -) : KtLightAbstractAnnotation(parent, computeDelegate) { - - override fun getQualifiedName() = qualifiedName - - override fun isPhysical() = true - - override fun getName(): String? = null - - override fun findAttributeValue(name: String?) = getAttributeValue(name, true) - - override fun findDeclaredAttributeValue(name: String?): PsiAnnotationMemberValue? = getAttributeValue(name, false) - - private fun getCallEntry(name: String): MutableMap.MutableEntry? { - val resolvedCall = kotlinOrigin.getResolvedCall() ?: return null - return resolvedCall.valueArguments.entries.find { (param, _) -> param.name.asString() == name } ?: return null - } - - private fun getAttributeValue(name: String?, useDefault: Boolean): PsiAnnotationMemberValue? { - val name = name ?: "value" - val callEntry = getCallEntry(name) ?: return null - - val valueArgument = callEntry.value.arguments.firstOrNull() - if (valueArgument != null) { - ktLightAnnotationParameterList.attributes.find { (it as KtLightPsiNameValuePair).valueArgument === valueArgument }?.let { - return it.value - } - } - - if (useDefault && callEntry.key.declaresOrInheritsDefaultValue()) { - val psiElement = callEntry.key.source.getPsi() - when (psiElement) { - is KtParameter -> - return psiElement.defaultValue?.let { convertToLightAnnotationMemberValue(this, it) } - is PsiAnnotationMethod -> - return psiElement.defaultValue - } - } - return null - } - - - override fun getNameReferenceElement(): PsiJavaCodeReferenceElement? = KtLightPsiJavaCodeReferenceElement( - kotlinOrigin.navigationElement, - { - (kotlinOrigin as? KtAnnotationEntry)?.typeReference?.reference - ?: (kotlinOrigin.calleeExpression?.nameReference)?.references?.firstOrNull() - }, - { super.getNameReferenceElement() } - ) - - - private val ktLightAnnotationParameterList by lazyPub { KtLightAnnotationParameterList() } - - override fun getParameterList(): PsiAnnotationParameterList = ktLightAnnotationParameterList - - inner class KtLightAnnotationParameterList() : KtLightElementBase(this), - PsiAnnotationParameterList { - override val kotlinOrigin: KtElement? get() = null - - private val _attributes: Array by lazyPub { - this@KtLightAnnotationForSourceEntry.kotlinOrigin.valueArguments.map { makeLightPsiNameValuePair(it as KtValueArgument) } - .toTypedArray() - } - - private fun makeArrayInitializerIfExpected(pair: KtLightPsiNameValuePair): PsiAnnotationMemberValue? { - val valueArgument = pair.valueArgument - val name = valueArgument.name ?: "value" - val callEntry = getCallEntry(name) ?: return null - - val valueArguments = callEntry.value.arguments - val argument = valueArguments.firstOrNull()?.getArgumentExpression() ?: return null - - if (!callEntry.key.type.let { KotlinBuiltIns.isArrayOrPrimitiveArray(it) }) return null - - if (argument !is KtStringTemplateExpression && - argument !is KtConstantExpression && - argument !is KtClassLiteralExpression && - getAnnotationName(argument) == null - ) { - return null - } - - val parent = PsiTreeUtil.findCommonParent(valueArguments.map { it.getArgumentExpression() }) as KtElement - return KtLightPsiArrayInitializerMemberValue(parent, pair) { self -> - valueArguments.mapNotNull { - it.getArgumentExpression()?.let { convertToLightAnnotationMemberValue(self, it) } - } - } - } - - private fun makeLightPsiNameValuePair(valueArgument: KtValueArgument) = KtLightPsiNameValuePair(valueArgument, this) { self -> - makeArrayInitializerIfExpected(self) - ?: self.valueArgument.getArgumentExpression()?.let { convertToLightAnnotationMemberValue(self, it) } - } - - override fun getAttributes(): Array = _attributes - - } - - - override fun delete() = kotlinOrigin.delete() - - override fun toString() = "@$qualifiedName" - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other == null || other::class.java != this::class.java) return false - return kotlinOrigin == (other as KtLightAnnotationForSourceEntry).kotlinOrigin - } - - override fun hashCode() = kotlinOrigin.hashCode() - - override fun setDeclaredAttributeValue(attributeName: String?, value: T?) = cannotModify() -} - -class KtLightNonSourceAnnotation( - parent: PsiElement, clsDelegate: PsiAnnotation -) : KtLightAbstractAnnotation(parent, { clsDelegate }) { - override val kotlinOrigin: KtAnnotationEntry? get() = null - override fun getQualifiedName() = kotlinOrigin?.name ?: clsDelegate.qualifiedName - override fun setDeclaredAttributeValue(attributeName: String?, value: T?) = cannotModify() - override fun findAttributeValue(attributeName: String?) = clsDelegate.findAttributeValue(attributeName) - override fun findDeclaredAttributeValue(attributeName: String?) = clsDelegate.findDeclaredAttributeValue(attributeName) -} - -class KtLightNonExistentAnnotation(parent: KtLightElement<*, *>) : KtLightElementBase(parent), PsiAnnotation { - override val kotlinOrigin get() = null - override fun toString() = this.javaClass.name - - override fun setDeclaredAttributeValue(attributeName: String?, value: T?) = cannotModify() - - override fun getNameReferenceElement() = null - override fun findAttributeValue(attributeName: String?) = null - override fun getQualifiedName() = null - override fun getOwner() = parent as? PsiAnnotationOwner - override fun findDeclaredAttributeValue(attributeName: String?) = null - override fun getMetaData() = null - override fun getParameterList() = KtLightEmptyAnnotationParameterList(this) - - override fun canNavigate(): Boolean = super.canNavigate() - - override fun canNavigateToSource(): Boolean = super.canNavigateToSource() - - override fun navigate(requestFocus: Boolean) = super.navigate(requestFocus) -} - -class KtLightEmptyAnnotationParameterList(parent: PsiElement) : KtLightElementBase(parent), PsiAnnotationParameterList { - override val kotlinOrigin get() = null - override fun getAttributes(): Array = emptyArray() -} - -open class KtLightNullabilityAnnotation>(val member: D, parent: PsiElement) : - KtLightAbstractAnnotation(parent, { - // searching for last because nullability annotations are generated after backend generates source annotations - getClsNullabilityAnnotation(member) ?: KtLightNonExistentAnnotation(member) -}) { - override fun fqNameMatches(fqName: String): Boolean { - if (!isNullabilityAnnotation(fqName)) return false - - return super.fqNameMatches(fqName) - } - - override val kotlinOrigin get() = null - override fun setDeclaredAttributeValue(attributeName: String?, value: T?) = cannotModify() - - override fun findAttributeValue(attributeName: String?) = null - - override fun getQualifiedName(): String? { - val annotatedElement = member.takeIf(::isFromSources)?.kotlinOrigin - ?: // it is out of our hands - return getClsNullabilityAnnotation(member)?.qualifiedName - - // all data-class generated members are not-null - if (annotatedElement is KtClass && annotatedElement.isData()) return NotNull::class.java.name - - if (annotatedElement is KtParameter) { - if (annotatedElement.containingClassOrObject?.isAnnotation() == true) return null - } - - // don't annotate property setters - if (annotatedElement is KtValVarKeywordOwner && member is KtLightMethod && member.returnType == PsiType.VOID) return null - - val kotlinType = getTargetType(annotatedElement) ?: return null - if (KotlinBuiltIns.isPrimitiveType(kotlinType) && (annotatedElement as? KtParameter)?.isVarArg != true) { - // no need to annotate them explicitly except the case when overriding reference-type makes it non-primitive for Jvm - if (!(annotatedElement is KtCallableDeclaration && annotatedElement.hasModifier(KtTokens.OVERRIDE_KEYWORD))) return null - - val overriddenDescriptors = - (annotatedElement.analyze()[BindingContext.DECLARATION_TO_DESCRIPTOR, annotatedElement] as? CallableMemberDescriptor)?.overriddenDescriptors - if (overriddenDescriptors?.all { it.returnType == kotlinType } == true) return null - } - if (kotlinType.isUnit() && (annotatedElement !is KtValVarKeywordOwner)) return null // not annotate unit-functions - if (kotlinType.isTypeParameter()) { - if (!TypeUtils.hasNullableSuperType(kotlinType)) return NotNull::class.java.name - if (!kotlinType.isMarkedNullable) return null - } - - val nullability = kotlinType.nullability() - return when (nullability) { - TypeNullability.NOT_NULL -> NotNull::class.java.name - TypeNullability.NULLABLE -> Nullable::class.java.name - TypeNullability.FLEXIBLE -> null - } - } - - internal fun KtTypeReference.getType(): KotlinType? = analyze()[BindingContext.TYPE, this] - - private fun getTargetType(annotatedElement: PsiElement): KotlinType? { - if (annotatedElement is KtTypeReference) { - annotatedElement.getType()?.let { return it } - } - if (annotatedElement is KtCallableDeclaration) { - annotatedElement.typeReference?.getType()?.let { return it } - } - if (annotatedElement is KtNamedFunction) { - annotatedElement.bodyExpression?.let { it.getType(it.analyze()) }?.let { return it } - } - if (annotatedElement is KtProperty) { - annotatedElement.initializer?.let { it.getType(it.analyze()) }?.let { return it } - annotatedElement.delegateExpression?.let { it.getType(it.analyze())?.arguments?.firstOrNull()?.type }?.let { return it } - } - annotatedElement.getParentOfType(false)?.let { - it.typeReference?.getType() ?: it.initializer?.let { it.getType(it.analyze()) } - }?.let { return it } - return null - } - - - override fun getNameReferenceElement(): PsiJavaCodeReferenceElement? = null - - override fun getParameterList(): PsiAnnotationParameterList = KtLightEmptyAnnotationParameterList(this) - - override fun findDeclaredAttributeValue(attributeName: String?) = null -} - -private fun getClsNullabilityAnnotation(member: KtLightElement<*, PsiModifierListOwner>): PsiAnnotation? { - if (!accessAnnotationsClsDelegateIsAllowed && ApplicationManager.getApplication().isUnitTestMode && isFromSources(member) && member.kotlinOrigin != null) - LOG.error("nullability should be retrieved from `kotlinOrigin`") - return member.clsDelegate.modifierList?.annotations?.findLast { - isNullabilityAnnotation(it.qualifiedName) - } -} - -internal fun isNullabilityAnnotation(qualifiedName: String?) = qualifiedName in backendNullabilityAnnotations - -private val backendNullabilityAnnotations = arrayOf(Nullable::class.java.name, NotNull::class.java.name) - -private fun KtElement.analyze(): BindingContext = LightClassGenerationSupport.getInstance(this.project).analyze(this) - -private fun KtElement.getResolvedCall(): ResolvedCall? { - if (!isValid) return null - val context = analyze() - return this.getResolvedCall(context) -} - -fun convertToLightAnnotationMemberValue(lightParent: PsiElement, argument: KtExpression): PsiAnnotationMemberValue { - val argument = unwrapCall(argument) - when (argument) { - is KtClassLiteralExpression -> { - return KtLightPsiClassObjectAccessExpression(argument, lightParent) - } - is KtStringTemplateExpression, is KtConstantExpression -> { - return KtLightPsiLiteral(argument, lightParent) - } - is KtCallExpression -> { - val arguments = argument.valueArguments - val annotationName = argument.calleeExpression?.let { getAnnotationName(it) } - if (annotationName != null) { - return KtLightAnnotationForSourceEntry( - annotationName, - argument, - lightParent, - { throw UnsupportedOperationException("cls delegate is not supported for nested annotations") }) - } - val resolvedCall = argument.getResolvedCall() - if (resolvedCall != null && CompileTimeConstantUtils.isArrayFunctionCall(resolvedCall)) - return KtLightPsiArrayInitializerMemberValue( - argument, - lightParent, - { self -> - arguments.mapNotNull { - it.getArgumentExpression()?.let { convertToLightAnnotationMemberValue(self, it) } - } - }) - } - is KtCollectionLiteralExpression -> { - val arguments = argument.getInnerExpressions() - if (arguments.isNotEmpty()) - return KtLightPsiArrayInitializerMemberValue( - argument, - lightParent, - { self -> arguments.mapNotNull { convertToLightAnnotationMemberValue(self, it) } }) - } - } - // everything else (like complex constant references) considered as PsiLiteral-s - return KtLightPsiLiteral(argument, lightParent) -} - -private val KtExpression.nameReference: KtNameReferenceExpression? - get() = when { - this is KtConstructorCalleeExpression -> constructorReferenceExpression as? KtNameReferenceExpression - else -> this as? KtNameReferenceExpression - } - -private fun unwrapCall(callee: KtExpression): KtExpression = when (callee) { - is KtDotQualifiedExpression -> callee.lastChild as? KtCallExpression ?: callee - else -> callee -} - -private fun getAnnotationName(callee: KtExpression): String? { - val callee = unwrapCall(callee) - val resultingDescriptor = callee.getResolvedCall()?.resultingDescriptor - if (resultingDescriptor is ClassConstructorDescriptor) { - val ktClass = resultingDescriptor.constructedClass.source.getPsi() as? KtClass - if (ktClass?.isAnnotation() == true) return ktClass.fqName?.toString() - } - if (resultingDescriptor is JavaClassConstructorDescriptor) { - val psiClass = resultingDescriptor.constructedClass.source.getPsi() as? PsiClass - if (psiClass?.isAnnotationType == true) return psiClass.qualifiedName - } - return null -} - -@TestOnly -var accessAnnotationsClsDelegateIsAllowed = false - -@TestOnly -fun withAllowedAnnotationsClsDelegate(body: () -> T): T { - val prev = accessAnnotationsClsDelegateIsAllowed - try { - accessAnnotationsClsDelegateIsAllowed = true - return body() - } finally { - accessAnnotationsClsDelegateIsAllowed = prev - } -} diff --git a/compiler/tests-common/build.gradle.kts.173 b/compiler/tests-common/build.gradle.kts.173 deleted file mode 100644 index 5f1a12de170..00000000000 --- a/compiler/tests-common/build.gradle.kts.173 +++ /dev/null @@ -1,49 +0,0 @@ - -plugins { - kotlin("jvm") - id("jps-compatible") -} - -dependencies { - testCompile(project(":core:descriptors")) - testCompile(project(":core:descriptors.jvm")) - testCompile(project(":core:deserialization")) - testCompile(project(":compiler:util")) - testCompile(project(":compiler:backend")) - testCompile(project(":compiler:fir:tree")) - testCompile(project(":compiler:fir:psi2fir")) - testCompile(project(":compiler:fir:cones")) - testCompile(project(":compiler:fir:resolve")) - testCompile(project(":compiler:fir:java")) - testCompile(project(":compiler:ir.ir2cfg")) - testCompile(project(":compiler:frontend")) - testCompile(project(":compiler:frontend.java")) - testCompile(project(":compiler:util")) - testCompile(project(":compiler:cli-common")) - testCompile(project(":compiler:cli")) - testCompile(project(":compiler:light-classes")) - testCompile(project(":compiler:serialization")) - testCompile(project(":kotlin-preloader")) - testCompile(project(":compiler:daemon-common")) - testCompile(project(":js:js.serializer")) - testCompile(project(":js:js.frontend")) - testCompile(project(":js:js.translator")) - testCompileOnly(project(":plugins:android-extensions-compiler")) - testCompile(project(":kotlin-test:kotlin-test-jvm")) - testCompile(projectTests(":compiler:tests-common-jvm6")) - testCompileOnly(project(":kotlin-reflect-api")) - testCompile(commonDep("junit:junit")) - testCompile(androidDxJar()) { isTransitive = false } - testCompileOnly(intellijCoreDep()) { includeJars("intellij-core") } - testCompile(intellijDep()) { - includeJars("openapi", "idea", "idea_rt", "guava", "trove4j", "picocontainer", "asm-all", "log4j", "jdom", "annotations", rootProject = rootProject) - isTransitive = false - } -} - -sourceSets { - "main" { } - "test" { projectDefault() } -} - -testsJar {} diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/test/KotlinTestUtils.java.173 b/compiler/tests-common/tests/org/jetbrains/kotlin/test/KotlinTestUtils.java.173 deleted file mode 100644 index 04cf71916d2..00000000000 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/test/KotlinTestUtils.java.173 +++ /dev/null @@ -1,1299 +0,0 @@ -/* - * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license - * that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.test; - -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Lists; -import com.intellij.openapi.Disposable; -import com.intellij.openapi.editor.Caret; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Comparing; -import com.intellij.openapi.util.ShutDownTracker; -import com.intellij.openapi.util.SystemInfo; -import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.util.text.StringUtilRt; -import com.intellij.openapi.vfs.CharsetToolkit; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFileFactory; -import com.intellij.psi.impl.PsiFileFactoryImpl; -import com.intellij.rt.execution.junit.FileComparisonFailure; -import com.intellij.testFramework.LightVirtualFile; -import com.intellij.testFramework.TestDataFile; -import com.intellij.util.PathUtil; -import com.intellij.util.containers.ContainerUtil; -import junit.framework.TestCase; -import kotlin.collections.CollectionsKt; -import kotlin.collections.SetsKt; -import kotlin.jvm.functions.Function1; -import kotlin.text.StringsKt; -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.annotations.TestOnly; -import org.jetbrains.kotlin.CoroutineTestUtilKt; -import org.jetbrains.kotlin.analyzer.AnalysisResult; -import org.jetbrains.kotlin.builtins.DefaultBuiltIns; -import org.jetbrains.kotlin.builtins.KotlinBuiltIns; -import org.jetbrains.kotlin.checkers.CompilerTestLanguageVersionSettings; -import org.jetbrains.kotlin.checkers.CompilerTestLanguageVersionSettingsKt; -import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys; -import org.jetbrains.kotlin.cli.common.config.ContentRootsKt; -import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot; -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation; -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity; -import org.jetbrains.kotlin.cli.common.messages.MessageCollector; -import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles; -import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment; -import org.jetbrains.kotlin.cli.jvm.config.JvmContentRootsKt; -import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime; -import org.jetbrains.kotlin.config.*; -import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl; -import org.jetbrains.kotlin.diagnostics.Diagnostic; -import org.jetbrains.kotlin.diagnostics.Errors; -import org.jetbrains.kotlin.diagnostics.Severity; -import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages; -import org.jetbrains.kotlin.idea.KotlinLanguage; -import org.jetbrains.kotlin.jvm.compiler.LoadDescriptorUtil; -import org.jetbrains.kotlin.lexer.KtTokens; -import org.jetbrains.kotlin.name.Name; -import org.jetbrains.kotlin.psi.KtExpression; -import org.jetbrains.kotlin.psi.KtFile; -import org.jetbrains.kotlin.psi.KtPsiFactoryKt; -import org.jetbrains.kotlin.resolve.BindingContext; -import org.jetbrains.kotlin.resolve.BindingTrace; -import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics; -import org.jetbrains.kotlin.resolve.lazy.JvmResolveUtil; -import org.jetbrains.kotlin.storage.LockBasedStorageManager; -import org.jetbrains.kotlin.test.util.JetTestUtilsKt; -import org.jetbrains.kotlin.types.KotlinType; -import org.jetbrains.kotlin.types.expressions.KotlinTypeInfo; -import org.jetbrains.kotlin.util.slicedMap.ReadOnlySlice; -import org.jetbrains.kotlin.util.slicedMap.SlicedMap; -import org.jetbrains.kotlin.util.slicedMap.WritableSlice; -import org.jetbrains.kotlin.utils.ExceptionUtilsKt; -import org.junit.Assert; - -import javax.tools.*; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.StringWriter; -import java.lang.reflect.Method; -import java.nio.charset.Charset; -import java.util.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import static org.jetbrains.kotlin.test.InTextDirectivesUtils.*; - -public class KotlinTestUtils { - public static String TEST_MODULE_NAME = "test-module"; - - public static final String TEST_GENERATOR_NAME = "org.jetbrains.kotlin.generators.tests.TestsPackage"; - private static final String PLEASE_REGENERATE_TESTS = "Please regenerate tests (GenerateTests.kt)"; - - private static final boolean RUN_IGNORED_TESTS_AS_REGULAR = - Boolean.getBoolean("org.jetbrains.kotlin.run.ignored.tests.as.regular"); - - private static final boolean PRINT_STACKTRACE_FOR_IGNORED_TESTS = - Boolean.getBoolean("org.jetbrains.kotlin.print.stacktrace.for.ignored.tests"); - - private static final boolean AUTOMATICALLY_UNMUTE_PASSED_TESTS = false; - private static final boolean AUTOMATICALLY_MUTE_FAILED_TESTS = false; - - private static final List filesToDelete = new ArrayList<>(); - - /** - * Syntax: - * - * // MODULE: name(dependency1, dependency2, ...) - * - * // FILE: name - * - * Several files may follow one module - */ - private static final String MODULE_DELIMITER = ",\\s*"; - - private static final Pattern FILE_OR_MODULE_PATTERN = Pattern.compile( - "(?://\\s*MODULE:\\s*([^()\\n]+)(?:\\(([^()]+(?:" + MODULE_DELIMITER + "[^()]+)*)\\))?\\s*(?:\\(([^()]+(?:" + MODULE_DELIMITER + "[^()]+)*)\\))?\\s*)?" + - "//\\s*FILE:\\s*(.*)$", Pattern.MULTILINE); - private static final Pattern DIRECTIVE_PATTERN = Pattern.compile("^//\\s*!([\\w_]+)(:\\s*(.*)$)?", Pattern.MULTILINE); - private static final Pattern LINE_SEPARATOR_PATTERN = Pattern.compile("\\r\\n|\\r|\\n"); - - public static final BindingTrace DUMMY_TRACE = new BindingTrace() { - @NotNull - @Override - public BindingContext getBindingContext() { - return new BindingContext() { - - @NotNull - @Override - public Diagnostics getDiagnostics() { - return Diagnostics.Companion.getEMPTY(); - } - - @Override - public V get(ReadOnlySlice slice, K key) { - return DUMMY_TRACE.get(slice, key); - } - - @NotNull - @Override - public Collection getKeys(WritableSlice slice) { - return DUMMY_TRACE.getKeys(slice); - } - - @NotNull - @TestOnly - @Override - public ImmutableMap getSliceContents(@NotNull ReadOnlySlice slice) { - return ImmutableMap.of(); - } - - @Nullable - @Override - public KotlinType getType(@NotNull KtExpression expression) { - return DUMMY_TRACE.getType(expression); - } - - @Override - public void addOwnDataTo(@NotNull BindingTrace trace, boolean commitDiagnostics) { - // do nothing - } - }; - } - - @Override - public void record(WritableSlice slice, K key, V value) { - } - - @Override - public void record(WritableSlice slice, K key) { - } - - @Override - @SuppressWarnings("unchecked") - public V get(ReadOnlySlice slice, K key) { - if (slice == BindingContext.PROCESSED) return (V) Boolean.FALSE; - return SlicedMap.DO_NOTHING.get(slice, key); - } - - @NotNull - @Override - public Collection getKeys(WritableSlice slice) { - assert slice.isCollective(); - return Collections.emptySet(); - } - - @Nullable - @Override - public KotlinType getType(@NotNull KtExpression expression) { - KotlinTypeInfo typeInfo = get(BindingContext.EXPRESSION_TYPE_INFO, expression); - return typeInfo != null ? typeInfo.getType() : null; - } - - @Override - public void recordType(@NotNull KtExpression expression, @Nullable KotlinType type) { - } - - @Override - public void report(@NotNull Diagnostic diagnostic) { - if (Errors.UNRESOLVED_REFERENCE_DIAGNOSTICS.contains(diagnostic.getFactory())) { - throw new IllegalStateException("Unresolved: " + diagnostic.getPsiElement().getText()); - } - } - - @Override - public boolean wantsDiagnostics() { - return false; - } - }; - - public static BindingTrace DUMMY_EXCEPTION_ON_ERROR_TRACE = new BindingTrace() { - @NotNull - @Override - public BindingContext getBindingContext() { - return new BindingContext() { - @NotNull - @Override - public Diagnostics getDiagnostics() { - throw new UnsupportedOperationException(); - } - - @Override - public V get(ReadOnlySlice slice, K key) { - return DUMMY_EXCEPTION_ON_ERROR_TRACE.get(slice, key); - } - - @NotNull - @Override - public Collection getKeys(WritableSlice slice) { - return DUMMY_EXCEPTION_ON_ERROR_TRACE.getKeys(slice); - } - - @NotNull - @TestOnly - @Override - public ImmutableMap getSliceContents(@NotNull ReadOnlySlice slice) { - return ImmutableMap.of(); - } - - @Nullable - @Override - public KotlinType getType(@NotNull KtExpression expression) { - return DUMMY_EXCEPTION_ON_ERROR_TRACE.getType(expression); - } - - @Override - public void addOwnDataTo(@NotNull BindingTrace trace, boolean commitDiagnostics) { - // do nothing - } - }; - } - - @Override - public void record(WritableSlice slice, K key, V value) { - } - - @Override - public void record(WritableSlice slice, K key) { - } - - @Override - public V get(ReadOnlySlice slice, K key) { - return null; - } - - @NotNull - @Override - public Collection getKeys(WritableSlice slice) { - assert slice.isCollective(); - return Collections.emptySet(); - } - - @Nullable - @Override - public KotlinType getType(@NotNull KtExpression expression) { - return null; - } - - @Override - public void recordType(@NotNull KtExpression expression, @Nullable KotlinType type) { - } - - @Override - public void report(@NotNull Diagnostic diagnostic) { - if (diagnostic.getSeverity() == Severity.ERROR) { - throw new IllegalStateException(DefaultErrorMessages.render(diagnostic)); - } - } - - @Override - public boolean wantsDiagnostics() { - return true; - } - }; - - // We suspect sequences of eight consecutive hexadecimal digits to be a package part hash code - private static final Pattern STRIP_PACKAGE_PART_HASH_PATTERN = Pattern.compile("\\$([0-9a-f]{8})"); - - private KotlinTestUtils() { - } - - @NotNull - public static AnalysisResult analyzeFile(@NotNull KtFile file, @NotNull KotlinCoreEnvironment environment) { - return JvmResolveUtil.analyze(file, environment); - } - - @NotNull - public static KotlinCoreEnvironment createEnvironmentWithMockJdkAndIdeaAnnotations(Disposable disposable) { - return createEnvironmentWithMockJdkAndIdeaAnnotations(disposable, ConfigurationKind.ALL); - } - - @NotNull - public static KotlinCoreEnvironment createEnvironmentWithMockJdkAndIdeaAnnotations(Disposable disposable, @NotNull ConfigurationKind configurationKind) { - return createEnvironmentWithJdkAndNullabilityAnnotationsFromIdea(disposable, configurationKind, TestJdkKind.MOCK_JDK); - } - - @NotNull - public static KotlinCoreEnvironment createEnvironmentWithJdkAndNullabilityAnnotationsFromIdea( - @NotNull Disposable disposable, - @NotNull ConfigurationKind configurationKind, - @NotNull TestJdkKind jdkKind - ) { - return KotlinCoreEnvironment.createForTests( - disposable, newConfiguration(configurationKind, jdkKind, getAnnotationsJar()), EnvironmentConfigFiles.JVM_CONFIG_FILES - ); - } - - @NotNull - public static KotlinCoreEnvironment createEnvironmentWithFullJdkAndIdeaAnnotations(Disposable disposable) { - return createEnvironmentWithJdkAndNullabilityAnnotationsFromIdea(disposable, ConfigurationKind.ALL, TestJdkKind.FULL_JDK); - } - - @NotNull - public static String getTestDataPathBase() { - return getHomeDirectory() + "/compiler/testData"; - } - - private static String homeDir = computeHomeDirectory(); - - @NotNull - public static String getHomeDirectory() { - return homeDir; - } - - @NotNull - private static String computeHomeDirectory() { - String userDir = System.getProperty("user.dir"); - File dir = new File(userDir == null ? "." : userDir); - return FileUtil.toCanonicalPath(dir.getAbsolutePath()); - } - - public static File findMockJdkRtJar() { - return new File(getHomeDirectory(), "compiler/testData/mockJDK/jre/lib/rt.jar"); - } - - // Differs from common mock JDK only by one additional 'nonExistingMethod' in Collection and constructor from Double in Throwable - // It's needed to test the way we load additional built-ins members that neither in black nor white lists - public static File findMockJdkRtModified() { - return new File(getHomeDirectory(), "compiler/testData/mockJDKModified/rt.jar"); - } - - public static File findAndroidApiJar() { - String androidJarProp = System.getProperty("android.jar"); - File androidJarFile = androidJarProp == null ? null : new File(androidJarProp); - if (androidJarFile == null || !androidJarFile.isFile()) { - throw new RuntimeException( - "Unable to get a valid path from 'android.jar' property (" + - androidJarProp + - "), please point it to the 'android.jar' file location"); - } - return androidJarFile; - } - - @NotNull - public static File findAndroidSdk() { - String androidSdkProp = System.getProperty("android.sdk"); - File androidSdkDir = androidSdkProp == null ? null : new File(androidSdkProp); - if (androidSdkDir == null || !androidSdkDir.isDirectory()) { - throw new RuntimeException( - "Unable to get a valid path from 'android.sdk' property (" + - androidSdkProp + - "), please point it to the android SDK location"); - } - return androidSdkDir; - } - - public static String getAndroidSdkSystemIndependentPath() { - return PathUtil.toSystemIndependentName(findAndroidSdk().getAbsolutePath()); - } - - public static File getAnnotationsJar() { - return new File(getHomeDirectory(), "compiler/testData/mockJDK/jre/lib/annotations.jar"); - } - - public static void mkdirs(@NotNull File file) { - if (file.isDirectory()) { - return; - } - if (!file.mkdirs()) { - if (file.exists()) { - throw new IllegalStateException("Failed to create " + file + ": file exists and not a directory"); - } - throw new IllegalStateException("Failed to create " + file); - } - } - - @NotNull - public static File tmpDirForTest(@NotNull String testClassName, @NotNull String testName) throws IOException { - File answer = normalizeFile(FileUtil.createTempDirectory(testClassName, testName)); - deleteOnShutdown(answer); - return answer; - } - - @NotNull - public static File tmpDirForTest(TestCase test) throws IOException { - return tmpDirForTest(test.getClass().getSimpleName(), test.getName()); - } - - @NotNull - public static File tmpDir(String name) throws IOException { - // We should use this form. otherwise directory will be deleted on each test. - File answer = normalizeFile(FileUtil.createTempDirectory(new File(System.getProperty("java.io.tmpdir")), name, "")); - deleteOnShutdown(answer); - return answer; - } - - private static File normalizeFile(File file) throws IOException { - // Get canonical file to be sure that it's the same as inside the compiler, - // for example, on Windows, if a canonical path contains any space from FileUtil.createTempDirectory we will get - // a File with short names (8.3) in its path and it will break some normalization passes in tests. - return file.getCanonicalFile(); - } - - private static void deleteOnShutdown(File file) { - if (filesToDelete.isEmpty()) { - ShutDownTracker.getInstance().registerShutdownTask(() -> ShutDownTracker.invokeAndWait(true, true, () -> { - for (File victim : filesToDelete) { - FileUtil.delete(victim); - } - })); - } - - filesToDelete.add(file); - } - - @NotNull - public static KtFile createFile(@NotNull @NonNls String name, @NotNull String text, @NotNull Project project) { - String shortName = name.substring(name.lastIndexOf('/') + 1); - shortName = shortName.substring(shortName.lastIndexOf('\\') + 1); - LightVirtualFile virtualFile = new LightVirtualFile(shortName, KotlinLanguage.INSTANCE, StringUtilRt.convertLineSeparators(text)) { - @NotNull - @Override - public String getPath() { - //TODO: patch LightVirtualFile - return "/" + name; - } - }; - - virtualFile.setCharset(CharsetToolkit.UTF8_CHARSET); - PsiFileFactoryImpl factory = (PsiFileFactoryImpl) PsiFileFactory.getInstance(project); - //noinspection ConstantConditions - return (KtFile) factory.trySetupPsiForFile(virtualFile, KotlinLanguage.INSTANCE, true, false); - } - - public static String doLoadFile(String myFullDataPath, String name) throws IOException { - String fullName = myFullDataPath + File.separatorChar + name; - return doLoadFile(new File(fullName)); - } - - public static String doLoadFile(@NotNull File file) throws IOException { - try { - return FileUtil.loadFile(file, CharsetToolkit.UTF8, true); - } - catch (FileNotFoundException fileNotFoundException) { - /* - * Unfortunately, the FileNotFoundException will only show the relative path in it's exception message. - * This clarifies the exception by showing the full path. - */ - String messageWithFullPath = file.getAbsolutePath() + " (No such file or directory)"; - throw new IOException( - "Ensure you have your 'Working Directory' configured correctly as the root " + - "Kotlin project directory in your test configuration\n\t" + - messageWithFullPath, - fileNotFoundException); - } - } - - public static String getFilePath(File file) { - return FileUtil.toSystemIndependentName(file.getPath()); - } - - @NotNull - public static CompilerConfiguration newConfiguration() { - CompilerConfiguration configuration = new CompilerConfiguration(); - configuration.put(CommonConfigurationKeys.MODULE_NAME, TEST_MODULE_NAME); - - if ("true".equals(System.getProperty("kotlin.ni"))) { - // Enable new inference for tests which do not declare their own language version settings - CommonConfigurationKeysKt.setLanguageVersionSettings(configuration, new CompilerTestLanguageVersionSettings( - Collections.emptyMap(), - LanguageVersionSettingsImpl.DEFAULT.getApiVersion(), - LanguageVersionSettingsImpl.DEFAULT.getLanguageVersion(), - Collections.emptyMap() - )); - } - - configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, new MessageCollector() { - @Override - public void clear() { - } - - @Override - public void report( - @NotNull CompilerMessageSeverity severity, @NotNull String message, @Nullable CompilerMessageLocation location - ) { - if (severity == CompilerMessageSeverity.ERROR) { - String prefix = location == null - ? "" - : "(" + location.getPath() + ":" + location.getLine() + ":" + location.getColumn() + ") "; - throw new AssertionError(prefix + message); - } - } - - @Override - public boolean hasErrors() { - return false; - } - }); - - return configuration; - } - - @NotNull - public static CompilerConfiguration newConfiguration( - @NotNull ConfigurationKind configurationKind, - @NotNull TestJdkKind jdkKind, - @NotNull File... extraClasspath - ) { - return newConfiguration(configurationKind, jdkKind, Arrays.asList(extraClasspath), Collections.emptyList()); - } - - @NotNull - public static CompilerConfiguration newConfiguration( - @NotNull ConfigurationKind configurationKind, - @NotNull TestJdkKind jdkKind, - @NotNull List classpath, - @NotNull List javaSource - ) { - CompilerConfiguration configuration = newConfiguration(); - JvmContentRootsKt.addJavaSourceRoots(configuration, javaSource); - if (jdkKind == TestJdkKind.MOCK_JDK) { - JvmContentRootsKt.addJvmClasspathRoot(configuration, findMockJdkRtJar()); - configuration.put(JVMConfigurationKeys.NO_JDK, true); - } - else if (jdkKind == TestJdkKind.MODIFIED_MOCK_JDK) { - JvmContentRootsKt.addJvmClasspathRoot(configuration, findMockJdkRtModified()); - configuration.put(JVMConfigurationKeys.NO_JDK, true); - } - else if (jdkKind == TestJdkKind.ANDROID_API) { - JvmContentRootsKt.addJvmClasspathRoot(configuration, findAndroidApiJar()); - configuration.put(JVMConfigurationKeys.NO_JDK, true); - } - else if (jdkKind == TestJdkKind.FULL_JDK_6) { - String jdk6 = System.getenv("JDK_16"); - assert jdk6 != null : "Environment variable JDK_16 is not set"; - configuration.put(JVMConfigurationKeys.JDK_HOME, new File(jdk6)); - } - else if (jdkKind == TestJdkKind.FULL_JDK_9) { - configuration.put(JVMConfigurationKeys.JDK_HOME, getJdk9Home()); - } - else if (SystemInfo.IS_AT_LEAST_JAVA9) { - configuration.put(JVMConfigurationKeys.JDK_HOME, new File(System.getProperty("java.home"))); - } - - if (configurationKind.getWithRuntime()) { - JvmContentRootsKt.addJvmClasspathRoot(configuration, ForTestCompileRuntime.runtimeJarForTests()); - JvmContentRootsKt.addJvmClasspathRoot(configuration, ForTestCompileRuntime.scriptRuntimeJarForTests()); - JvmContentRootsKt.addJvmClasspathRoot(configuration, ForTestCompileRuntime.kotlinTestJarForTests()); - } - else if (configurationKind.getWithMockRuntime()) { - JvmContentRootsKt.addJvmClasspathRoot(configuration, ForTestCompileRuntime.minimalRuntimeJarForTests()); - JvmContentRootsKt.addJvmClasspathRoot(configuration, ForTestCompileRuntime.scriptRuntimeJarForTests()); - } - if (configurationKind.getWithReflection()) { - JvmContentRootsKt.addJvmClasspathRoot(configuration, ForTestCompileRuntime.reflectJarForTests()); - } - - JvmContentRootsKt.addJvmClasspathRoots(configuration, classpath); - - return configuration; - } - - @NotNull - public static File getJdk9Home() { - String jdk9 = System.getenv("JDK_9"); - if (jdk9 == null) { - jdk9 = System.getenv("JDK_19"); - if (jdk9 == null) { - throw new AssertionError("Environment variable JDK_9 is not set!"); - } - } - return new File(jdk9); - } - - public static void resolveAllKotlinFiles(KotlinCoreEnvironment environment) throws IOException { - List roots = ContentRootsKt.getKotlinSourceRoots(environment.getConfiguration()); - if (roots.isEmpty()) return; - List ktFiles = new ArrayList<>(); - for (KotlinSourceRoot root : roots) { - File file = new File(root.getPath()); - if (file.isFile()) { - ktFiles.add(loadJetFile(environment.getProject(), file)); - } - else { - //noinspection ConstantConditions - for (File childFile : file.listFiles()) { - if (childFile.getName().endsWith(".kt") || childFile.getName().endsWith(".kts")) { - ktFiles.add(loadJetFile(environment.getProject(), childFile)); - } - } - } - } - JvmResolveUtil.analyze(ktFiles, environment); - } - - public static void assertEqualsToFile(@NotNull File expectedFile, @NotNull Editor editor) { - assertEqualsToFile(expectedFile, editor, true); - } - - public static void assertEqualsToFile(@NotNull File expectedFile, @NotNull Editor editor, Boolean enableSelectionTags) { - Caret caret = editor.getCaretModel().getCurrentCaret(); - List tags = Lists.newArrayList( - new TagsTestDataUtil.TagInfo<>(caret.getOffset(), true, "caret") - ); - - if (enableSelectionTags) { - int selectionStart = caret.getSelectionStart(); - int selectionEnd = caret.getSelectionEnd(); - - tags.add(new TagsTestDataUtil.TagInfo<>(selectionStart, true, "selection")); - tags.add(new TagsTestDataUtil.TagInfo<>(selectionEnd, false, "selection")); - } - - String afterText = TagsTestDataUtil.insertTagsInText(tags, editor.getDocument().getText()); - - assertEqualsToFile(expectedFile, afterText); - } - - public static void assertEqualsToFile(@NotNull File expectedFile, @NotNull String actual) { - assertEqualsToFile(expectedFile, actual, s -> s); - } - - public static void assertEqualsToFile(@NotNull String message, @NotNull File expectedFile, @NotNull String actual) { - assertEqualsToFile(message, expectedFile, actual, s -> s); - } - - public static void assertEqualsToFile(@NotNull File expectedFile, @NotNull String actual, @NotNull Function1 sanitizer) { - assertEqualsToFile("Actual data differs from file content", expectedFile, actual, sanitizer); - } - - public static void assertEqualsToFile(@NotNull String message, @NotNull File expectedFile, @NotNull String actual, @NotNull Function1 sanitizer) { - try { - String actualText = JetTestUtilsKt.trimTrailingWhitespacesAndAddNewlineAtEOF(StringUtil.convertLineSeparators(actual.trim())); - - if (!expectedFile.exists()) { - FileUtil.writeToFile(expectedFile, actualText); - Assert.fail("Expected data file did not exist. Generating: " + expectedFile); - } - String expected = FileUtil.loadFile(expectedFile, CharsetToolkit.UTF8, true); - - String expectedText = JetTestUtilsKt.trimTrailingWhitespacesAndAddNewlineAtEOF(StringUtil.convertLineSeparators(expected.trim())); - - if (!Comparing.equal(sanitizer.invoke(expectedText), sanitizer.invoke(actualText))) { - throw new FileComparisonFailure(message + ": " + expectedFile.getName(), - expected, actual, expectedFile.getAbsolutePath()); - } - } - catch (IOException e) { - throw ExceptionUtilsKt.rethrow(e); - } - } - - public static boolean compileKotlinWithJava( - @NotNull List javaFiles, - @NotNull List ktFiles, - @NotNull File outDir, - @NotNull Disposable disposable, - @Nullable File javaErrorFile - ) throws IOException { - if (!ktFiles.isEmpty()) { - KotlinCoreEnvironment environment = createEnvironmentWithFullJdkAndIdeaAnnotations(disposable); - CompilerTestLanguageVersionSettingsKt.setupLanguageVersionSettingsForMultifileCompilerTests(ktFiles, environment); - LoadDescriptorUtil.compileKotlinToDirAndGetModule(ktFiles, outDir, environment); - } - else { - boolean mkdirs = outDir.mkdirs(); - assert mkdirs : "Not created: " + outDir; - } - if (javaFiles.isEmpty()) return true; - - return compileJavaFiles(javaFiles, Arrays.asList( - "-classpath", outDir.getPath() + File.pathSeparator + ForTestCompileRuntime.runtimeJarForTests(), - "-d", outDir.getPath() - ), javaErrorFile); - } - - public interface TestFileFactory { - F createFile(@Nullable M module, @NotNull String fileName, @NotNull String text, @NotNull Map directives); - M createModule(@NotNull String name, @NotNull List dependencies, @NotNull List friends); - } - - public static abstract class TestFileFactoryNoModules implements TestFileFactory { - @Override - public final F createFile( - @Nullable Void module, - @NotNull String fileName, - @NotNull String text, - @NotNull Map directives - ) { - return create(fileName, text, directives); - } - - @NotNull - public abstract F create(@NotNull String fileName, @NotNull String text, @NotNull Map directives); - - @Override - public Void createModule(@NotNull String name, @NotNull List dependencies, @NotNull List friends) { - return null; - } - } - - @NotNull - public static List createTestFiles(@Nullable String testFileName, String expectedText, TestFileFactory factory) { - return createTestFiles(testFileName, expectedText, factory, false, ""); - } - - @NotNull - public static List createTestFiles(@Nullable String testFileName, String expectedText, TestFileFactory factory, String coroutinesPackage) { - return createTestFiles(testFileName, expectedText, factory, false, coroutinesPackage); - } - - @NotNull - public static List createTestFiles(String testFileName, String expectedText, TestFileFactory factory, - boolean preserveLocations, String coroutinesPackage) { - Map directives = parseDirectives(expectedText); - - List testFiles = Lists.newArrayList(); - Matcher matcher = FILE_OR_MODULE_PATTERN.matcher(expectedText); - boolean hasModules = false; - if (!matcher.find()) { - assert testFileName != null : "testFileName should not be null if no FILE directive defined"; - // One file - testFiles.add(factory.createFile(null, testFileName, expectedText, directives)); - } - else { - int processedChars = 0; - M module = null; - // Many files - while (true) { - String moduleName = matcher.group(1); - String moduleDependencies = matcher.group(2); - String moduleFriends = matcher.group(3); - if (moduleName != null) { - moduleName = moduleName.trim(); - hasModules = true; - module = factory.createModule(moduleName, parseModuleList(moduleDependencies), parseModuleList(moduleFriends)); - } - - String fileName = matcher.group(4); - int start = processedChars; - - boolean nextFileExists = matcher.find(); - int end; - if (nextFileExists) { - end = matcher.start(); - } - else { - end = expectedText.length(); - } - String fileText = preserveLocations ? - substringKeepingLocations(expectedText, start, end) : - expectedText.substring(start,end); - processedChars = end; - - testFiles.add(factory.createFile(module, fileName, fileText, directives)); - - if (!nextFileExists) break; - } - assert processedChars == expectedText.length() : "Characters skipped from " + - processedChars + - " to " + - (expectedText.length() - 1); - } - - if (isDirectiveDefined(expectedText, "WITH_COROUTINES")) { - M supportModule = hasModules ? factory.createModule("support", Collections.emptyList(), Collections.emptyList()) : null; - - boolean isReleaseCoroutines = - !coroutinesPackage.contains("experimental") && - !isDirectiveDefined(expectedText, "!LANGUAGE: -ReleaseCoroutines"); - - testFiles.add(factory.createFile(supportModule, - "CoroutineUtil.kt", - CoroutineTestUtilKt.createTextForHelpers(isReleaseCoroutines), - directives - )); - } - - return testFiles; - } - - private static String substringKeepingLocations(String string, int start, int end) { - Matcher matcher = LINE_SEPARATOR_PATTERN.matcher(string); - StringBuilder prefix = new StringBuilder(); - int lastLineOffset = 0; - while (matcher.find()) { - if (matcher.end() > start) { - break; - } - - lastLineOffset = matcher.end(); - prefix.append('\n'); - } - - while (lastLineOffset++ < start) { - prefix.append(' '); - } - - return prefix + string.substring(start, end); - } - - private static List parseModuleList(@Nullable String dependencies) { - if (dependencies == null) return Collections.emptyList(); - return StringsKt.split(dependencies, Pattern.compile(MODULE_DELIMITER), 0); - } - - @NotNull - public static Map parseDirectives(String expectedText) { - Map directives = new HashMap<>(); - Matcher directiveMatcher = DIRECTIVE_PATTERN.matcher(expectedText); - while (directiveMatcher.find()) { - String name = directiveMatcher.group(1); - String value = directiveMatcher.group(3); - String oldValue = directives.put(name, value); - Assert.assertNull("Directive overwritten: " + name + " old value: " + oldValue + " new value: " + value, oldValue); - } - return directives; - } - - public static List loadBeforeAfterText(String filePath) { - String content; - - try { - content = FileUtil.loadFile(new File(filePath), true); - } - catch (IOException e) { - throw new RuntimeException(e); - } - - List files = createTestFiles("", content, new TestFileFactoryNoModules() { - @NotNull - @Override - public String create(@NotNull String fileName, @NotNull String text, @NotNull Map directives) { - int firstLineEnd = text.indexOf('\n'); - return StringUtil.trimTrailing(text.substring(firstLineEnd + 1)); - } - }, ""); - - Assert.assertTrue("Exactly two files expected: ", files.size() == 2); - - return files; - } - - public static String getLastCommentedLines(@NotNull Document document) { - List resultLines = new ArrayList<>(); - for (int i = document.getLineCount() - 1; i >= 0; i--) { - int lineStart = document.getLineStartOffset(i); - int lineEnd = document.getLineEndOffset(i); - if (document.getCharsSequence().subSequence(lineStart, lineEnd).toString().trim().isEmpty()) { - continue; - } - - if ("//".equals(document.getCharsSequence().subSequence(lineStart, lineStart + 2).toString())) { - resultLines.add(document.getCharsSequence().subSequence(lineStart + 2, lineEnd)); - } - else { - break; - } - } - Collections.reverse(resultLines); - StringBuilder result = new StringBuilder(); - for (CharSequence line : resultLines) { - result.append(line).append("\n"); - } - result.delete(result.length() - 1, result.length()); - return result.toString(); - } - - public enum CommentType { - ALL, - LINE_COMMENT, - BLOCK_COMMENT - } - - @NotNull - public static String getLastCommentInFile(@NotNull KtFile file) { - return CollectionsKt.first(getLastCommentsInFile(file, CommentType.ALL, true)); - } - - @NotNull - public static List getLastCommentsInFile(@NotNull KtFile file, CommentType commentType, boolean assertMustExist) { - PsiElement lastChild = file.getLastChild(); - if (lastChild != null && lastChild.getNode().getElementType().equals(KtTokens.WHITE_SPACE)) { - lastChild = lastChild.getPrevSibling(); - } - assert lastChild != null; - - List comments = ContainerUtil.newArrayList(); - - while (true) { - if (lastChild.getNode().getElementType().equals(KtTokens.BLOCK_COMMENT)) { - if (commentType == CommentType.ALL || commentType == CommentType.BLOCK_COMMENT) { - String lastChildText = lastChild.getText(); - comments.add(lastChildText.substring(2, lastChildText.length() - 2).trim()); - } - } - else if (lastChild.getNode().getElementType().equals(KtTokens.EOL_COMMENT)) { - if (commentType == CommentType.ALL || commentType == CommentType.LINE_COMMENT) { - comments.add(lastChild.getText().substring(2).trim()); - } - } - else { - break; - } - - lastChild = lastChild.getPrevSibling(); - } - - if (comments.isEmpty() && assertMustExist) { - throw new AssertionError(String.format( - "Test file '%s' should end in a comment of type %s; last node was: %s", file.getName(), commentType, lastChild)); - } - - return comments; - } - - public static boolean compileJavaFiles(@NotNull Collection files, List options) throws IOException { - return compileJavaFiles(files, options, null); - } - - private static boolean compileJavaFiles(@NotNull Collection files, List options, @Nullable File javaErrorFile) throws IOException { - JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler(); - DiagnosticCollector diagnosticCollector = new DiagnosticCollector<>(); - try (StandardJavaFileManager fileManager = - javaCompiler.getStandardFileManager(diagnosticCollector, Locale.ENGLISH, Charset.forName("utf-8"))) { - Iterable javaFileObjectsFromFiles = fileManager.getJavaFileObjectsFromFiles(files); - - JavaCompiler.CompilationTask task = javaCompiler.getTask( - new StringWriter(), // do not write to System.err - fileManager, - diagnosticCollector, - options, - null, - javaFileObjectsFromFiles); - - Boolean success = task.call(); // do NOT inline this variable, call() should complete before errorsToString() - if (javaErrorFile == null || !javaErrorFile.exists()) { - Assert.assertTrue(errorsToString(diagnosticCollector, true), success); - } - else { - assertEqualsToFile(javaErrorFile, errorsToString(diagnosticCollector, false)); - } - return success; - } - } - - public static boolean compileJavaFilesExternallyWithJava9(@NotNull Collection files, @NotNull List options) { - List command = new ArrayList<>(); - command.add(new File(getJdk9Home(), "bin/javac").getPath()); - command.addAll(options); - for (File file : files) { - command.add(file.getPath()); - } - - try { - Process process = new ProcessBuilder().command(command).inheritIO().start(); - process.waitFor(); - return process.exitValue() == 0; - } - catch (Exception e) { - throw ExceptionUtilsKt.rethrow(e); - } - } - - @NotNull - private static String errorsToString(@NotNull DiagnosticCollector diagnosticCollector, boolean humanReadable) { - StringBuilder builder = new StringBuilder(); - for (javax.tools.Diagnostic diagnostic : diagnosticCollector.getDiagnostics()) { - if (diagnostic.getKind() != javax.tools.Diagnostic.Kind.ERROR) continue; - - if (humanReadable) { - builder.append(diagnostic).append("\n"); - } - else { - builder.append(new File(diagnostic.getSource().toUri()).getName()).append(":") - .append(diagnostic.getLineNumber()).append(":") - .append(diagnostic.getColumnNumber()).append(":") - .append(diagnostic.getCode()).append("\n"); - } - } - return builder.toString(); - } - - public static String navigationMetadata(@TestDataFile String testFile) { - return testFile; - } - - public interface DoTest { - void invoke(String filePath) throws Exception; - } - - // In this test runner version the `testDataFile` parameter is annotated by `TestDataFile`. - // So only file paths passed to this parameter will be used in navigation actions, like "Navigate to testdata" and "Related Symbol..." - public static void runTest(DoTest test, TargetBackend targetBackend, @TestDataFile String testDataFile) throws Exception { - runTest0(test, targetBackend, testDataFile); - } - - // In this test runner version, NONE of the parameters are annotated by `TestDataFile`. - // So DevKit will use test name to determine related files in navigation actions, like "Navigate to testdata" and "Related Symbol..." - // - // Pro: - // * in most cases, it shows all related files including generated js files, for example. - // Cons: - // * sometimes, for too common/general names, it shows many variants to navigate - // * it adds an additional step for navigation -- you must choose an exact file to navigate - public static void runTest0(DoTest test, TargetBackend targetBackend, String testDataFilePath) throws Exception { - File testDataFile = new File(testDataFilePath); - - boolean isIgnored = isIgnoredTarget(targetBackend, testDataFile); - - try { - test.invoke(testDataFilePath); - } - catch (Throwable e) { - - if (!isIgnored && AUTOMATICALLY_MUTE_FAILED_TESTS) { - String text = doLoadFile(testDataFile); - String directive = InTextDirectivesUtils.IGNORE_BACKEND_DIRECTIVE_PREFIX + targetBackend.name() + "\n"; - - String newText; - if (text.startsWith("// !")) { - StringBuilder prefixBuilder = new StringBuilder(); - int l = 0; - while (text.startsWith("// !", l)) { - int r = text.indexOf("\n", l) + 1; - if (r <= 0) r = text.length(); - prefixBuilder.append(text.substring(l, r)); - l = r; - } - prefixBuilder.append(directive); - prefixBuilder.append(text.substring(l)); - - newText = prefixBuilder.toString(); - } else { - newText = directive + text; - } - - if (!newText.equals(text)) { - System.err.println("\"" + directive + "\" was added to \"" + testDataFile + "\""); - FileUtil.writeToFile(testDataFile, newText); - } - } - - if (RUN_IGNORED_TESTS_AS_REGULAR || !isIgnored) { - throw e; - } - - if (PRINT_STACKTRACE_FOR_IGNORED_TESTS) { - e.printStackTrace(); - } - return; - } - - if (isIgnored) { - if (AUTOMATICALLY_UNMUTE_PASSED_TESTS) { - String text = doLoadFile(testDataFile); - String directive = InTextDirectivesUtils.IGNORE_BACKEND_DIRECTIVE_PREFIX + targetBackend.name(); - String newText = Pattern.compile("^" + directive + "\n", Pattern.MULTILINE).matcher(text).replaceAll(""); - - if (!newText.equals(text)) { - System.err.println("\"" + directive + "\" was removed from \"" + testDataFile + "\""); - FileUtil.writeToFile(testDataFile, newText); - } - } - - throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive."); - } - } - - public static String getTestsRoot(@NotNull Class testCaseClass) { - TestMetadata testClassMetadata = testCaseClass.getAnnotation(TestMetadata.class); - Assert.assertNotNull("No metadata for class: " + testCaseClass, testClassMetadata); - return testClassMetadata.value(); - } - - /** - * @return test data file name specified in the metadata of test method - */ - @Nullable - public static String getTestDataFileName(@NotNull Class testCaseClass, @NotNull String testName) { - try { - Method method = testCaseClass.getDeclaredMethod(testName); - return getMethodMetadata(method); - } - catch (NoSuchMethodException e) { - throw new RuntimeException(e); - } - } - - public static void assertAllTestsPresentByMetadata( - @NotNull Class testCaseClass, - @NotNull File testDataDir, - @NotNull Pattern filenamePattern, - @NotNull TargetBackend targetBackend, - boolean recursive, - @NotNull String... excludeDirs - ) { - File rootFile = new File(getTestsRoot(testCaseClass)); - - Set filePaths = collectPathsMetadata(testCaseClass); - Set exclude = SetsKt.setOf(excludeDirs); - - File[] files = testDataDir.listFiles(); - if (files != null) { - for (File file : files) { - if (file.isDirectory()) { - if (recursive && containsTestData(file, filenamePattern) && !exclude.contains(file.getName())) { - assertTestClassPresentByMetadata(testCaseClass, file); - } - } - else if (filenamePattern.matcher(file.getName()).matches() && isCompatibleTarget(targetBackend, file)) { - assertFilePathPresent(file, rootFile, filePaths); - } - } - } - } - - public static void assertAllTestsPresentInSingleGeneratedClass( - @NotNull Class testCaseClass, - @NotNull File testDataDir, - @NotNull Pattern filenamePattern, - @NotNull TargetBackend targetBackend - ) { - File rootFile = new File(getTestsRoot(testCaseClass)); - - Set filePaths = collectPathsMetadata(testCaseClass); - - FileUtil.processFilesRecursively(testDataDir, file -> { - if (file.isFile() && filenamePattern.matcher(file.getName()).matches() && isCompatibleTarget(targetBackend, file)) { - assertFilePathPresent(file, rootFile, filePaths); - } - - return true; - }); - } - - private static void assertFilePathPresent(File file, File rootFile, Set filePaths) { - String path = FileUtil.getRelativePath(rootFile, file); - if (path != null) { - String relativePath = nameToCompare(path); - if (!filePaths.contains(relativePath)) { - Assert.fail("Test data file missing from the generated test class: " + file + "\n" + PLEASE_REGENERATE_TESTS); - } - } - } - - private static Set collectPathsMetadata(Class testCaseClass) { - return ContainerUtil.newHashSet(ContainerUtil.map(collectMethodsMetadata(testCaseClass), KotlinTestUtils::nameToCompare)); - } - - @Nullable - private static String getMethodMetadata(Method method) { - TestMetadata testMetadata = method.getAnnotation(TestMetadata.class); - return (testMetadata != null) ? testMetadata.value() : null; - } - - private static Set collectMethodsMetadata(Class testCaseClass) { - Set filePaths = new HashSet<>(); - for (Method method : testCaseClass.getDeclaredMethods()) { - String path = getMethodMetadata(method); - if (path != null) { - filePaths.add(path); - } - } - return filePaths; - } - - private static boolean containsTestData(File dir, Pattern filenamePattern) { - File[] files = dir.listFiles(); - assert files != null; - for (File file : files) { - if (file.isDirectory()) { - if (containsTestData(file, filenamePattern)) { - return true; - } - } - else { - if (filenamePattern.matcher(file.getName()).matches()) { - return true; - } - } - } - return false; - } - - private static void assertTestClassPresentByMetadata(@NotNull Class outerClass, @NotNull File testDataDir) { - for (Class nestedClass : outerClass.getDeclaredClasses()) { - TestMetadata testMetadata = nestedClass.getAnnotation(TestMetadata.class); - if (testMetadata != null && testMetadata.value().equals(getFilePath(testDataDir))) { - return; - } - } - Assert.fail("Test data directory missing from the generated test class: " + testDataDir + "\n" + PLEASE_REGENERATE_TESTS); - } - - @NotNull - public static KtFile loadJetFile(@NotNull Project project, @NotNull File ioFile) throws IOException { - String text = FileUtil.loadFile(ioFile, true); - return KtPsiFactoryKt.KtPsiFactory(project).createPhysicalFile(ioFile.getName(), text); - } - - @NotNull - public static List loadToJetFiles(@NotNull KotlinCoreEnvironment environment, @NotNull List files) throws IOException { - List jetFiles = Lists.newArrayList(); - for (File file : files) { - jetFiles.add(loadJetFile(environment.getProject(), file)); - } - return jetFiles; - } - - @NotNull - public static ModuleDescriptorImpl createEmptyModule() { - return createEmptyModule(""); - } - - @NotNull - public static ModuleDescriptorImpl createEmptyModule(@NotNull String name) { - return createEmptyModule(name, DefaultBuiltIns.getInstance()); - } - - @NotNull - public static ModuleDescriptorImpl createEmptyModule(@NotNull String name, @NotNull KotlinBuiltIns builtIns) { - return new ModuleDescriptorImpl(Name.special(name), LockBasedStorageManager.NO_LOCKS, builtIns); - } - - @NotNull - public static File replaceExtension(@NotNull File file, @Nullable String newExtension) { - return new File(file.getParentFile(), FileUtil.getNameWithoutExtension(file) + (newExtension == null ? "" : "." + newExtension)); - } - - @NotNull - public static String replaceHashWithStar(@NotNull String string) { - return replaceHash(string, "*"); - } - - public static String replaceHash(@NotNull String string, @NotNull String replacement) { - //TODO: hashes are still used in SamWrapperCodegen - Matcher matcher = STRIP_PACKAGE_PART_HASH_PATTERN.matcher(string); - if (matcher.find()) { - return matcher.replaceAll("\\$" + replacement); - } - return string; - } - - public static boolean isAllFilesPresentTest(String testName) { - //noinspection SpellCheckingInspection - return testName.toLowerCase().startsWith("allfilespresentin"); - } - - public static String nameToCompare(@NotNull String name) { - return (SystemInfo.isFileSystemCaseSensitive ? name : name.toLowerCase()).replace('\\', '/'); - } - - public static boolean isMultiExtensionName(@NotNull String name) { - int firstDotIndex = name.indexOf('.'); - if (firstDotIndex == -1) { - return false; - } - // Several extension if name contains another dot - return name.indexOf('.', firstDotIndex + 1) != -1; - } -} diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/test/testFramework/KtParsingTestCase.java.173 b/compiler/tests-common/tests/org/jetbrains/kotlin/test/testFramework/KtParsingTestCase.java.173 deleted file mode 100644 index 657557f6f37..00000000000 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/test/testFramework/KtParsingTestCase.java.173 +++ /dev/null @@ -1,337 +0,0 @@ -/* - * Copyright 2000-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.test.testFramework; - -import com.intellij.core.CoreASTFactory; -import com.intellij.lang.*; -import com.intellij.lang.impl.PsiBuilderFactoryImpl; -import com.intellij.mock.*; -import com.intellij.openapi.Disposable; -import com.intellij.openapi.application.PathManager; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.EditorFactory; -import com.intellij.openapi.extensions.ExtensionPointName; -import com.intellij.openapi.extensions.Extensions; -import com.intellij.openapi.fileEditor.FileDocumentManager; -import com.intellij.openapi.fileEditor.impl.LoadTextUtil; -import com.intellij.openapi.fileTypes.FileTypeFactory; -import com.intellij.openapi.fileTypes.FileTypeManager; -import com.intellij.openapi.progress.EmptyProgressIndicator; -import com.intellij.openapi.progress.ProgressManager; -import com.intellij.openapi.progress.impl.CoreProgressManager; -import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.util.Key; -import com.intellij.openapi.util.TextRange; -import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.vfs.CharsetToolkit; -import com.intellij.pom.PomModel; -import com.intellij.pom.core.impl.PomModelImpl; -import com.intellij.pom.tree.TreeAspect; -import com.intellij.psi.*; -import com.intellij.psi.impl.*; -import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry; -import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistryImpl; -import com.intellij.psi.impl.source.text.BlockSupportImpl; -import com.intellij.psi.impl.source.text.DiffLog; -import com.intellij.psi.util.CachedValuesManager; -import com.intellij.testFramework.LightVirtualFile; -import com.intellij.testFramework.TestDataFile; -import com.intellij.util.CachedValuesManagerImpl; -import com.intellij.util.Function; -import com.intellij.util.messages.MessageBus; -import com.intellij.util.messages.MessageBusFactory; -import junit.framework.TestCase; -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.NotNull; -import org.picocontainer.ComponentAdapter; -import org.picocontainer.MutablePicoContainer; - -import java.io.File; -import java.io.IOException; -import java.util.Set; - -@SuppressWarnings("ALL") -public abstract class KtParsingTestCase extends KtPlatformLiteFixture { - public static final Key HARD_REF_TO_DOCUMENT_KEY = Key.create("HARD_REF_TO_DOCUMENT_KEY"); - protected String myFilePrefix = ""; - protected String myFileExt; - protected final String myFullDataPath; - protected PsiFile myFile; - private MockPsiManager myPsiManager; - private PsiFileFactoryImpl myFileFactory; - protected Language myLanguage; - private final ParserDefinition[] myDefinitions; - private final boolean myLowercaseFirstLetter; - - protected KtParsingTestCase(@NonNls @NotNull String dataPath, @NotNull String fileExt, @NotNull ParserDefinition... definitions) { - this(dataPath, fileExt, false, definitions); - } - - protected KtParsingTestCase(@NonNls @NotNull String dataPath, @NotNull String fileExt, boolean lowercaseFirstLetter, @NotNull ParserDefinition... definitions) { - myDefinitions = definitions; - myFullDataPath = getTestDataPath() + "/" + dataPath; - myFileExt = fileExt; - myLowercaseFirstLetter = lowercaseFirstLetter; - } - - @Override - protected void setUp() throws Exception { - super.setUp(); - initApplication(); - ComponentAdapter component = getApplication().getPicoContainer().getComponentAdapter(ProgressManager.class.getName()); - - Extensions.registerAreaClass("IDEA_PROJECT", null); - myProject = new MockProjectEx(getTestRootDisposable()); - myPsiManager = new MockPsiManager(myProject); - myFileFactory = new PsiFileFactoryImpl(myPsiManager); - MutablePicoContainer appContainer = getApplication().getPicoContainer(); - registerComponentInstance(appContainer, MessageBus.class, MessageBusFactory.newMessageBus(getApplication())); - final MockEditorFactory editorFactory = new MockEditorFactory(); - registerComponentInstance(appContainer, EditorFactory.class, editorFactory); - registerComponentInstance(appContainer, FileDocumentManager.class, new MockFileDocumentManagerImpl(new Function() { - @Override - public Document fun(CharSequence charSequence) { - return editorFactory.createDocument(charSequence); - } - }, HARD_REF_TO_DOCUMENT_KEY)); - registerComponentInstance(appContainer, PsiDocumentManager.class, new MockPsiDocumentManager()); - registerApplicationService(PsiBuilderFactory.class, new PsiBuilderFactoryImpl()); - registerApplicationService(DefaultASTFactory.class, new CoreASTFactory()); - registerApplicationService(ReferenceProvidersRegistry.class, new ReferenceProvidersRegistryImpl()); - - registerApplicationService(ProgressManager.class, new CoreProgressManager()); - - myProject.registerService(CachedValuesManager.class, new CachedValuesManagerImpl(myProject, new PsiCachedValuesFactory(myPsiManager))); - myProject.registerService(PsiManager.class, myPsiManager); - - this.registerExtensionPoint(FileTypeFactory.FILE_TYPE_FACTORY_EP, FileTypeFactory.class); - registerExtensionPoint(MetaLanguage.EP_NAME, MetaLanguage.class); - - for (ParserDefinition definition : myDefinitions) { - addExplicitExtension(LanguageParserDefinitions.INSTANCE, definition.getFileNodeType().getLanguage(), definition); - } - if (myDefinitions.length > 0) { - configureFromParserDefinition(myDefinitions[0], myFileExt); - } - - // That's for reparse routines - final PomModelImpl pomModel = new PomModelImpl(myProject); - myProject.registerService(PomModel.class, pomModel); - new TreeAspect(pomModel); - } - - public void configureFromParserDefinition(ParserDefinition definition, String extension) { - myLanguage = definition.getFileNodeType().getLanguage(); - myFileExt = extension; - addExplicitExtension(LanguageParserDefinitions.INSTANCE, this.myLanguage, definition); - registerComponentInstance( - getApplication().getPicoContainer(), FileTypeManager.class, - new MockFileTypeManager(new MockLanguageFileType(myLanguage, myFileExt))); - } - - protected void addExplicitExtension(final LanguageExtension instance, final Language language, final T object) { - instance.addExplicitExtension(language, object); - Disposer.register(myProject, new Disposable() { - @Override - public void dispose() { - instance.removeExplicitExtension(language, object); - } - }); - } - - @Override - protected void registerExtensionPoint(final ExtensionPointName extensionPointName, Class aClass) { - super.registerExtensionPoint(extensionPointName, aClass); - Disposer.register(myProject, new Disposable() { - @Override - public void dispose() { - Extensions.getRootArea().unregisterExtensionPoint(extensionPointName.getName()); - } - }); - } - - protected void registerApplicationService(final Class aClass, T object) { - getApplication().registerService(aClass, object); - Disposer.register(myProject, new Disposable() { - @Override - public void dispose() { - getApplication().getPicoContainer().unregisterComponent(aClass.getName()); - } - }); - } - - public MockProjectEx getProject() { - return myProject; - } - - public MockPsiManager getPsiManager() { - return myPsiManager; - } - - @Override - protected void tearDown() throws Exception { - super.tearDown(); - myFile = null; - myProject = null; - myPsiManager = null; - } - - protected String getTestDataPath() { - return PathManager.getHomePath(); - } - - @NotNull - public final String getTestName() { - return getTestName(myLowercaseFirstLetter); - } - - protected boolean includeRanges() { - return false; - } - - protected boolean skipSpaces() { - return false; - } - - protected boolean checkAllPsiRoots() { - return true; - } - - protected void doTest(boolean checkResult) { - String name = getTestName(); - try { - String text = loadFile(name + "." + myFileExt); - myFile = createPsiFile(name, text); - ensureParsed(myFile); - assertEquals("light virtual file text mismatch", text, ((LightVirtualFile)myFile.getVirtualFile()).getContent().toString()); - assertEquals("virtual file text mismatch", text, LoadTextUtil.loadText(myFile.getVirtualFile())); - assertEquals("doc text mismatch", text, myFile.getViewProvider().getDocument().getText()); - assertEquals("psi text mismatch", text, myFile.getText()); - ensureCorrectReparse(myFile); - if (checkResult){ - checkResult(name, myFile); - } - else{ - toParseTreeText(myFile, skipSpaces(), includeRanges()); - } - } - catch (IOException e) { - throw new RuntimeException(e); - } - } - - protected void doTest(String suffix) throws IOException { - String name = getTestName(); - String text = loadFile(name + "." + myFileExt); - myFile = createPsiFile(name, text); - ensureParsed(myFile); - assertEquals(text, myFile.getText()); - checkResult(name + suffix, myFile); - } - - protected void doCodeTest(String code) throws IOException { - String name = getTestName(); - myFile = createPsiFile("a", code); - ensureParsed(myFile); - assertEquals(code, myFile.getText()); - checkResult(myFilePrefix + name, myFile); - } - - protected PsiFile createPsiFile(String name, String text) { - return createFile(name + "." + myFileExt, text); - } - - protected PsiFile createFile(@NonNls String name, String text) { - LightVirtualFile virtualFile = new LightVirtualFile(name, myLanguage, text); - virtualFile.setCharset(CharsetToolkit.UTF8_CHARSET); - return createFile(virtualFile); - } - - protected PsiFile createFile(LightVirtualFile virtualFile) { - return myFileFactory.trySetupPsiForFile(virtualFile, myLanguage, true, false); - } - - protected void checkResult(@NonNls @TestDataFile String targetDataName, final PsiFile file) throws IOException { - doCheckResult(myFullDataPath, file, checkAllPsiRoots(), targetDataName, skipSpaces(), includeRanges()); - } - - public static void doCheckResult(String testDataDir, - PsiFile file, - boolean checkAllPsiRoots, - String targetDataName, - boolean skipSpaces, - boolean printRanges) throws IOException { - FileViewProvider provider = file.getViewProvider(); - Set languages = provider.getLanguages(); - - if (!checkAllPsiRoots || languages.size() == 1) { - doCheckResult(testDataDir, targetDataName + ".txt", toParseTreeText(file, skipSpaces, printRanges).trim()); - return; - } - - for (Language language : languages) { - PsiFile root = provider.getPsi(language); - String expectedName = targetDataName + "." + language.getID() + ".txt"; - doCheckResult(testDataDir, expectedName, toParseTreeText(root, skipSpaces, printRanges).trim()); - } - } - - protected void checkResult(String actual) throws IOException { - String name = getTestName(); - doCheckResult(myFullDataPath, myFilePrefix + name + ".txt", actual); - } - - protected void checkResult(@TestDataFile @NonNls String targetDataName, String actual) throws IOException { - doCheckResult(myFullDataPath, targetDataName, actual); - } - - public static void doCheckResult(String fullPath, String targetDataName, String actual) throws IOException { - String expectedFileName = fullPath + File.separatorChar + targetDataName; - KtUsefulTestCase.assertSameLinesWithFile(expectedFileName, actual); - } - - protected static String toParseTreeText(PsiElement file, boolean skipSpaces, boolean printRanges) { - return DebugUtil.psiToString(file, skipSpaces, printRanges); - } - - protected String loadFile(@NonNls @TestDataFile String name) throws IOException { - return loadFileDefault(myFullDataPath, name); - } - - public static String loadFileDefault(String dir, String name) throws IOException { - return FileUtil.loadFile(new File(dir, name), CharsetToolkit.UTF8, true).trim(); - } - - public static void ensureParsed(PsiFile file) { - file.accept(new PsiElementVisitor() { - @Override - public void visitElement(PsiElement element) { - element.acceptChildren(this); - } - }); - } - - public static void ensureCorrectReparse(@NotNull PsiFile file) { - String psiToStringDefault = DebugUtil.psiToString(file, false, false); - String fileText = file.getText(); - DiffLog diffLog = (new BlockSupportImpl(file.getProject())).reparseRange( - file, file.getNode(), TextRange.allOf(fileText), fileText, new EmptyProgressIndicator(), fileText); - diffLog.performActualPsiChange(file); - - TestCase.assertEquals(psiToStringDefault, DebugUtil.psiToString(file, false, false)); - } -} \ No newline at end of file diff --git a/gradle/versions.properties.173 b/gradle/versions.properties.173 deleted file mode 100644 index 5e5c9437187..00000000000 --- a/gradle/versions.properties.173 +++ /dev/null @@ -1,13 +0,0 @@ -versions.intellijSdk=173.4674.33 -versions.androidBuildTools=r23.0.1 -versions.idea.NodeJS=172.3757.32 -versions.jar.guava=21.0 -versions.jar.groovy-all=2.4.12 -versions.jar.lombok-ast=0.2.3 -versions.jar.swingx-core=1.6.2 -versions.jar.kxml2=2.3.0 -versions.jar.streamex=0.6.5 -versions.jar.gson=2.8.2 -versions.jar.snappy-in-java=0.5.1 -ignore.jar.lombok-ast-0.2.3=true -versions.gradle-api=4.0 diff --git a/idea/formatter/src/org/jetbrains/kotlin/idea/core/formatter/compatibility.kt.173 b/idea/formatter/src/org/jetbrains/kotlin/idea/core/formatter/compatibility.kt.173 deleted file mode 100644 index bb0f27982f9..00000000000 --- a/idea/formatter/src/org/jetbrains/kotlin/idea/core/formatter/compatibility.kt.173 +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license - * that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.idea.core.formatter - -import com.intellij.psi.codeStyle.CommonCodeStyleSettings -import com.intellij.psi.codeStyle.CommonCodeStyleSettingsManager - -/** - * Method copyFrom is absent in 173. - * BUNCH: 181 - */ -fun CommonCodeStyleSettings.copyFromEx(source: CommonCodeStyleSettings) { - @Suppress("IncompatibleAPI") - CommonCodeStyleSettingsManager.copy(source, this) -} \ No newline at end of file diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/PsiShortNamesCacheCompatibility.kt.173 b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/PsiShortNamesCacheCompatibility.kt.173 deleted file mode 100644 index 033f33f8cb1..00000000000 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/PsiShortNamesCacheCompatibility.kt.173 +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license - * that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.idea.caches - -import com.intellij.psi.search.PsiShortNamesCache - -typealias PsiShortNamesCacheWrapper = PsiShortNamesCacheCompatibility - -// Need to implement deprecated methods. Should be removed after abandoning 173 and AS 3.1 branch. -// BUNCH: 181 -@Suppress("OverridingDeprecatedMember", "DEPRECATION") -abstract class PsiShortNamesCacheCompatibility : PsiShortNamesCache() { - override fun getAllClassNames(dest: com.intellij.util.containers.HashSet) { - processAllClassNames(com.intellij.util.CommonProcessors.CollectProcessor(dest)) - } - - override fun getAllMethodNames(set: com.intellij.util.containers.HashSet) { - java.util.Collections.addAll(set, *allMethodNames) - } - - override fun getAllFieldNames(set: com.intellij.util.containers.HashSet) { - java.util.Collections.addAll(set, *allFieldNames) - } -} diff --git a/idea/idea-android/src/org/jetbrains/kotlin/android/KotlinAndroidLineMarkerProvider.kt.173 b/idea/idea-android/src/org/jetbrains/kotlin/android/KotlinAndroidLineMarkerProvider.kt.173 deleted file mode 100644 index fcbc1a1c179..00000000000 --- a/idea/idea-android/src/org/jetbrains/kotlin/android/KotlinAndroidLineMarkerProvider.kt.173 +++ /dev/null @@ -1,135 +0,0 @@ -/* - * 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.kotlin.android - -import com.android.SdkConstants -import com.android.resources.ResourceType -import com.intellij.codeHighlighting.Pass -import com.intellij.codeInsight.daemon.GutterIconNavigationHandler -import com.intellij.codeInsight.daemon.LineMarkerInfo -import com.intellij.codeInsight.daemon.LineMarkerProvider -import com.intellij.codeInsight.navigation.NavigationUtil -import com.intellij.icons.AllIcons -import com.intellij.ide.highlighter.XmlFileType -import com.intellij.navigation.GotoRelatedItem -import com.intellij.openapi.editor.markup.GutterIconRenderer -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiFile -import com.intellij.psi.xml.XmlAttributeValue -import com.intellij.ui.awt.RelativePoint -import com.intellij.util.Function -import org.jetbrains.android.dom.manifest.Manifest -import org.jetbrains.android.facet.AndroidFacet -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode -import java.awt.event.MouseEvent -import javax.swing.Icon - - -class KotlinAndroidLineMarkerProvider : LineMarkerProvider { - override fun getLineMarkerInfo(element: PsiElement): LineMarkerInfo<*>? = null - - override fun collectSlowLineMarkers(elements: List, result: MutableCollection>) { - elements.forEach { - (it as? KtClass)?.getLineMarkerInfo()?.let { marker -> result.add(marker) } - } - } - - private fun KtClass.getLineMarkerInfo(): LineMarkerInfo? { - val nameIdentifier = nameIdentifier ?: return null - val androidFacet = AndroidFacet.getInstance(this) ?: return null - val manifest = androidFacet.manifest ?: return null - val manifestItems = collectGoToRelatedManifestItems(manifest) - if (manifestItems.isEmpty() && !isClassWithLayoutXml()) { - return null - } - - return LineMarkerInfo( - nameIdentifier, - nameIdentifier.textRange, - AllIcons.FileTypes.Xml, - Pass.LINE_MARKERS, - Function { "Related XML file" }, - GutterIconNavigationHandler { e: MouseEvent, _: PsiElement -> - NavigationUtil - .getRelatedItemsPopup( - manifestItems + collectGoToRelatedLayoutItems(androidFacet), - "Go to Related Files") - .show(RelativePoint(e)) - }, - GutterIconRenderer.Alignment.RIGHT) - } - - private fun KtClass.collectGoToRelatedLayoutItems(androidFacet: AndroidFacet): List { - val resources = mutableSetOf() - accept(object: KtVisitorVoid() { - override fun visitKtElement(element: KtElement) { - element.acceptChildren(this) - } - - override fun visitReferenceExpression(expression: KtReferenceExpression) { - super.visitReferenceExpression(expression) - - val resClassName = ResourceType.LAYOUT.getName() - val info = (expression as? KtSimpleNameExpression)?.let { - getReferredResourceOrManifestField(androidFacet, it, resClassName, true) - } - - if (info == null || info.isFromManifest) { - return - } - - val files = androidFacet - .localResourceManager - .findResourcesByFieldName(resClassName, info.fieldName) - .filterIsInstance() - - resources.addAll(files) - } - }) - - return resources.map { GotoRelatedLayoutItem(it) } - } - - private fun KtClass.collectGoToRelatedManifestItems(manifest: Manifest): List = - findComponentDeclarationInManifest(manifest)?.xmlAttributeValue?.let { listOf(GotoManifestItem(it)) } ?: emptyList() - - private class GotoManifestItem(attributeValue: XmlAttributeValue) : GotoRelatedItem(attributeValue) { - override fun getCustomName(): String? = "AndroidManifest.xml" - override fun getCustomContainerName(): String? = "" - override fun getCustomIcon(): Icon? = XmlFileType.INSTANCE.icon - } - - private class GotoRelatedLayoutItem(private val file: PsiFile) : GotoRelatedItem(file, "Layout Files") { - override fun getCustomContainerName(): String? = "(${file.containingDirectory.name})" - } - - companion object { - private val CLASSES_WITH_LAYOUT_XML = arrayOf( - SdkConstants.CLASS_ACTIVITY, - SdkConstants.CLASS_FRAGMENT, - SdkConstants.CLASS_V4_FRAGMENT, - "android.widget.Adapter") - - private fun KtClass.isClassWithLayoutXml(): Boolean { - val type = (unsafeResolveToDescriptor(BodyResolveMode.PARTIAL) as? ClassDescriptor)?.defaultType ?: return false - return CLASSES_WITH_LAYOUT_XML.any { type.isSubclassOf(it, true) } - } - } -} \ No newline at end of file diff --git a/idea/idea-android/src/org/jetbrains/kotlin/android/ResourceReferenceAnnotatorUtil.java.173 b/idea/idea-android/src/org/jetbrains/kotlin/android/ResourceReferenceAnnotatorUtil.java.173 deleted file mode 100644 index 6e1d66d4ba1..00000000000 --- a/idea/idea-android/src/org/jetbrains/kotlin/android/ResourceReferenceAnnotatorUtil.java.173 +++ /dev/null @@ -1,270 +0,0 @@ -/* - * 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.kotlin.android; - - -import com.android.ide.common.rendering.api.ResourceValue; -import com.android.ide.common.resources.ResourceItem; -import com.android.ide.common.resources.ResourceRepository; -import com.android.ide.common.resources.ResourceResolver; -import com.android.resources.ResourceType; -import com.android.tools.idea.configurations.Configuration; -import com.android.tools.idea.res.AppResourceRepository; -import com.android.tools.idea.res.LocalResourceRepository; -import com.android.tools.idea.res.ResourceHelper; -import com.android.tools.idea.ui.resourcechooser.ColorPicker; -import com.android.utils.XmlUtils; -import com.google.common.base.Charsets; -import com.google.common.io.Files; -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.CommonDataKeys; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.markup.GutterIconRenderer; -import com.intellij.openapi.module.Module; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.psi.xml.XmlAttribute; -import com.intellij.psi.xml.XmlAttributeValue; -import com.intellij.psi.xml.XmlTag; -import com.intellij.util.ui.ColorIcon; -import com.intellij.util.ui.EmptyIcon; -import com.intellij.util.ui.JBUI; -import org.jetbrains.android.facet.AndroidFacet; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import javax.swing.*; -import java.awt.*; -import java.io.File; - -import static com.android.SdkConstants.*; -import static com.android.SdkConstants.ANDROID_URI; -import static com.android.SdkConstants.ATTR_DRAWABLE; -import static com.android.tools.idea.uibuilder.property.renderer.NlDefaultRenderer.ICON_SIZE; -import static org.jetbrains.android.AndroidColorAnnotator.pickLayoutFile; - -/** - * Contains copied privates from AndroidColorAnnotator, so we could use them for Kotlin AndroidResourceReferenceAnnotator - */ -public class ResourceReferenceAnnotatorUtil { - @Nullable - public static File pickBitmapFromXml(@NotNull File file, @NotNull ResourceResolver resourceResolver, @NotNull Project project) { - try { - String xml = Files.toString(file, Charsets.UTF_8); - Document document = XmlUtils.parseDocumentSilently(xml, true); - if (document != null && document.getDocumentElement() != null) { - Element root = document.getDocumentElement(); - String tag = root.getTagName(); - Element target = null; - String attribute = null; - if ("vector".equals(tag)) { - // Vectors are handled in the icon cache - return file; - } - else if ("bitmap".equals(tag) || "nine-patch".equals(tag)) { - target = root; - attribute = ATTR_SRC; - } - else if ("selector".equals(tag) || - "level-list".equals(tag) || - "layer-list".equals(tag) || - "transition".equals(tag)) { - NodeList children = root.getChildNodes(); - for (int i = children.getLength() - 1; i >= 0; i--) { - Node item = children.item(i); - if (item.getNodeType() == Node.ELEMENT_NODE && TAG_ITEM.equals(item.getNodeName())) { - target = (Element)item; - if (target.hasAttributeNS(ANDROID_URI, ATTR_DRAWABLE)) { - attribute = ATTR_DRAWABLE; - break; - } - } - } - } - else if ("clip".equals(tag) || "inset".equals(tag) || "scale".equals(tag)) { - target = root; - attribute = ATTR_DRAWABLE; - } else { - // etc - no bitmap to be found - return null; - } - if (attribute != null && target.hasAttributeNS(ANDROID_URI, attribute)) { - String src = target.getAttributeNS(ANDROID_URI, attribute); - ResourceValue value = resourceResolver.findResValue(src, false); - if (value != null) { - return ResourceHelper.resolveDrawable(resourceResolver, value, project); - - } - } - } - } catch (Throwable ignore) { - // Not logging for now; afraid to risk unexpected crashes in upcoming preview. TODO: Re-enable. - //Logger.getInstance(AndroidColorAnnotator.class).warn(String.format("Could not read/render icon image %1$s", file), e); - } - - return null; - } - - /** Looks up the resource item of the given type and name for the given configuration, if any */ - @Nullable - public static ResourceValue findResourceValue(ResourceType type, - String name, - boolean isFramework, - Module module, - Configuration configuration) { - if (isFramework) { - ResourceRepository frameworkResources = configuration.getFrameworkResources(); - if (frameworkResources == null) { - return null; - } - if (!frameworkResources.hasResourceItem(type, name)) { - return null; - } - ResourceItem item = frameworkResources.getResourceItem(type, name); - return item.getResourceValue(type, configuration.getFullConfig(), false); - } else { - LocalResourceRepository appResources = AppResourceRepository.getAppResources(module, true); - if (appResources == null) { - return null; - } - if (!appResources.hasResourceItem(type, name)) { - return null; - } - return appResources.getConfiguredValue(type, name, configuration.getFullConfig()); - } - } - - /** Picks a suitable configuration to use for resource resolution */ - @Nullable - public static Configuration pickConfiguration(AndroidFacet facet, Module module, PsiFile file) { - VirtualFile virtualFile = file.getVirtualFile(); - if (virtualFile == null) { - return null; - } - - VirtualFile parent = virtualFile.getParent(); - if (parent == null) { - return null; - } - VirtualFile layout; - String parentName = parent.getName(); - if (!parentName.startsWith(FD_RES_LAYOUT)) { - layout = pickLayoutFile(module, facet); - if (layout == null) { - return null; - } - } else { - layout = virtualFile; - } - - return facet.getConfigurationManager().getConfiguration(layout); - } - - public static class ColorRenderer extends GutterIconRenderer { - private final PsiElement myElement; - private final Color myColor; - - ColorRenderer(@NotNull PsiElement element, @Nullable Color color) { - myElement = element; - myColor = color; - } - - @NotNull - @Override - public Icon getIcon() { - Color color = getCurrentColor(); - return JBUI.scale(color == null ? EmptyIcon.create(ICON_SIZE) : new ColorIcon(ICON_SIZE, color)); - } - - @Nullable - private Color getCurrentColor() { - if (myColor != null) { - return myColor; - } else if (myElement instanceof XmlTag) { - return ResourceHelper.parseColor(((XmlTag)myElement).getValue().getText()); - } else if (myElement instanceof XmlAttributeValue) { - return ResourceHelper.parseColor(((XmlAttributeValue)myElement).getValue()); - } else { - return null; - } - } - - @Override - public AnAction getClickAction() { - if (myColor != null) { // Cannot set colors that were derived - return null; - } - return new AnAction() { - @Override - public void actionPerformed(AnActionEvent e) { - final Editor editor = CommonDataKeys.EDITOR.getData(e.getDataContext()); - if (editor != null) { - // Need ARGB support in platform color chooser; see - // https://youtrack.jetbrains.com/issue/IDEA-123498 - //final Color color = - // ColorChooser.chooseColor(editor.getComponent(), AndroidBundle.message("android.choose.color"), getCurrentColor()); - final Color color = ColorPicker.showDialog(editor.getComponent(), "Choose Color", getCurrentColor(), true, null, false); - if (color != null) { - ApplicationManager.getApplication().runWriteAction(new Runnable() { - @Override - public void run() { - if (myElement instanceof XmlTag) { - ((XmlTag)myElement).getValue().setText(ResourceHelper.colorToString(color)); - } else if (myElement instanceof XmlAttributeValue) { - XmlAttribute attribute = PsiTreeUtil.getParentOfType(myElement, XmlAttribute.class); - if (attribute != null) { - attribute.setValue(ResourceHelper.colorToString(color)); - } - } - } - }); - } - } - } - }; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - ColorRenderer that = (ColorRenderer)o; - // TODO: Compare with modification count in app resources (if not framework) - if (myColor != null ? !myColor.equals(that.myColor) : that.myColor != null) return false; - if (!myElement.equals(that.myElement)) return false; - - return true; - } - - @Override - public int hashCode() { - int result = myElement.hashCode(); - result = 31 * result + (myColor != null ? myColor.hashCode() : 0); - return result; - } - } -} diff --git a/idea/idea-android/src/org/jetbrains/kotlin/android/configure/KotlinAndroidGradleMPPModuleDataService.kt.173 b/idea/idea-android/src/org/jetbrains/kotlin/android/configure/KotlinAndroidGradleMPPModuleDataService.kt.173 deleted file mode 100644 index 317ef7a6038..00000000000 --- a/idea/idea-android/src/org/jetbrains/kotlin/android/configure/KotlinAndroidGradleMPPModuleDataService.kt.173 +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license - * that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.android.configure - -import com.android.tools.idea.gradle.project.model.AndroidModuleModel -import com.android.tools.idea.gradle.util.FilePaths -import com.intellij.openapi.diagnostic.Logger -import com.intellij.openapi.externalSystem.ExternalSystemModulePropertyManager -import com.intellij.openapi.externalSystem.model.DataNode -import com.intellij.openapi.externalSystem.model.ProjectKeys -import com.intellij.openapi.externalSystem.model.project.ModuleData -import com.intellij.openapi.externalSystem.model.project.ProjectData -import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider -import com.intellij.openapi.externalSystem.service.project.manage.AbstractProjectDataService -import com.intellij.openapi.externalSystem.service.project.manage.ContentRootDataService.CREATE_EMPTY_DIRECTORIES -import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil -import com.intellij.openapi.module.Module -import com.intellij.openapi.project.Project -import com.intellij.openapi.roots.DependencyScope -import com.intellij.openapi.roots.ModifiableRootModel -import com.intellij.openapi.vfs.VfsUtil -import com.intellij.util.containers.stream -import org.jetbrains.jps.model.java.JavaResourceRootType -import org.jetbrains.jps.model.java.JavaSourceRootType -import org.jetbrains.jps.model.module.JpsModuleSourceRootType -import org.jetbrains.kotlin.gradle.KotlinCompilation -import org.jetbrains.kotlin.gradle.KotlinPlatform -import org.jetbrains.kotlin.idea.configuration.GradleProjectImportHandler -import org.jetbrains.kotlin.idea.configuration.KotlinSourceSetDataService -import org.jetbrains.kotlin.idea.configuration.kotlinAndroidSourceSets -import org.jetbrains.kotlin.idea.facet.KotlinFacet -import java.io.File -import java.io.IOException - -class KotlinAndroidGradleMPPModuleDataService : AbstractProjectDataService() { - override fun getTargetDataKey() = ProjectKeys.MODULE - - private fun shouldCreateEmptySourceRoots( - moduleDataNode: DataNode, - module: Module - ): Boolean { - val projectDataNode = ExternalSystemApiUtil.findParent(moduleDataNode, ProjectKeys.PROJECT) ?: return false - if (projectDataNode.getUserData(CREATE_EMPTY_DIRECTORIES) == true) return true - - val projectSystemId = projectDataNode.data.owner - val externalSystemSettings = ExternalSystemApiUtil.getSettings(module.project, projectSystemId) - - val path = ExternalSystemModulePropertyManager.getInstance(module).getRootProjectPath() ?: return false - return externalSystemSettings.getLinkedProjectSettings(path)?.isCreateEmptyContentRootDirectories ?: false - } - - override fun postProcess( - toImport: MutableCollection>, - projectData: ProjectData?, - project: Project, - modelsProvider: IdeModifiableModelsProvider - ) { - for (nodeToImport in toImport) { - val projectNode = ExternalSystemApiUtil.findParent(nodeToImport, ProjectKeys.PROJECT) ?: continue - val moduleData = nodeToImport.data - val module = modelsProvider.findIdeModule(moduleData) ?: continue - val shouldCreateEmptySourceRoots = shouldCreateEmptySourceRoots(nodeToImport, module) - val rootModel = modelsProvider.getModifiableRootModel(module) - val kotlinAndroidSourceSets = nodeToImport.kotlinAndroidSourceSets ?: continue - for (sourceSetInfo in kotlinAndroidSourceSets) { - val compilation = sourceSetInfo.kotlinModule as? KotlinCompilation ?: continue - for (sourceSet in compilation.sourceSets) { - if (sourceSet.platform == KotlinPlatform.ANDROID) { - val sourceType = if (sourceSet.isTestModule) JavaSourceRootType.TEST_SOURCE else JavaSourceRootType.SOURCE - val resourceType = if (sourceSet.isTestModule) JavaResourceRootType.TEST_RESOURCE else JavaResourceRootType.RESOURCE - sourceSet.sourceDirs.forEach { addSourceRoot(it, sourceType, rootModel, shouldCreateEmptySourceRoots) } - sourceSet.resourceDirs.forEach { addSourceRoot(it, resourceType, rootModel, shouldCreateEmptySourceRoots) } - } - } - } - val androidModel = module.getAndroidModel(modelsProvider) ?: continue - val variantName = androidModel.selectedVariant.name - val activeSourceSetInfos = nodeToImport.kotlinAndroidSourceSets?.filter { it.kotlinModule.name.startsWith(variantName) } ?: emptyList() - for (activeSourceSetInfo in activeSourceSetInfos) { - val activeCompilation = activeSourceSetInfo.kotlinModule as? KotlinCompilation ?: continue - for (sourceSet in activeCompilation.sourceSets) { - if (sourceSet.platform != KotlinPlatform.ANDROID) { - val sourceSetId = activeSourceSetInfo.sourceSetIdsByName[sourceSet.name] ?: continue - val sourceSetData = ExternalSystemApiUtil.findFirstRecursively(projectNode) { - (it.data as? ModuleData)?.id == sourceSetId - }?.data as? ModuleData ?: continue - val sourceSetModule = modelsProvider.findIdeModule(sourceSetData) ?: continue - val existingEntry = rootModel.findModuleOrderEntry(sourceSetModule) - val dependencyScope = if (activeSourceSetInfo.isTestModule) DependencyScope.TEST else DependencyScope.COMPILE - if (existingEntry != null && existingEntry.scope == dependencyScope) continue - rootModel.addModuleOrderEntry(sourceSetModule).also { it.scope = dependencyScope } - } - } - } - val mainSourceSetInfo = activeSourceSetInfos.firstOrNull { it.kotlinModule.name == variantName } - if (mainSourceSetInfo != null) { - KotlinSourceSetDataService.configureFacet(moduleData, mainSourceSetInfo, nodeToImport, module, modelsProvider) - } - - val kotlinFacet = KotlinFacet.get(module) - if (kotlinFacet != null) { - GradleProjectImportHandler.getInstances(project).forEach { it.importByModule(kotlinFacet, nodeToImport) } - } - } - } - - private fun addSourceRoot( - sourceRoot: File, - type: JpsModuleSourceRootType<*>, - rootModel: ModifiableRootModel, - shouldCreateEmptySourceRoots: Boolean - ) { - val parent = FilePaths.findParentContentEntry(sourceRoot, rootModel.contentEntries) ?: return - val url = FilePaths.pathToIdeaUrl(sourceRoot) - parent.addSourceFolder(url, type) - if (shouldCreateEmptySourceRoots) { - ExternalSystemApiUtil.doWriteAction { - try { - VfsUtil.createDirectoryIfMissing(sourceRoot.path) - } catch (e: IOException) { - LOG.warn(String.format("Unable to create directory for the path: %s", sourceRoot.path), e) - } - } - } - } - - companion object { - private val LOG = Logger.getInstance(KotlinAndroidGradleMPPModuleDataService::class.java) - } -} \ No newline at end of file diff --git a/idea/idea-android/src/org/jetbrains/kotlin/android/configure/KotlinAndroidMPPGradleProjectResolver.kt.173 b/idea/idea-android/src/org/jetbrains/kotlin/android/configure/KotlinAndroidMPPGradleProjectResolver.kt.173 deleted file mode 100644 index 594e29d714b..00000000000 --- a/idea/idea-android/src/org/jetbrains/kotlin/android/configure/KotlinAndroidMPPGradleProjectResolver.kt.173 +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license - * that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.android.configure - -import com.android.builder.model.AndroidProject -import com.android.builder.model.NativeAndroidProject -import com.android.tools.idea.IdeInfo -import com.android.tools.idea.gradle.ImportedModule -import com.android.tools.idea.gradle.project.sync.idea.data.service.AndroidProjectKeys.IMPORTED_MODULE -import com.intellij.openapi.externalSystem.model.DataNode -import com.intellij.openapi.externalSystem.model.project.ModuleData -import com.intellij.openapi.externalSystem.model.project.ProjectData -import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil -import com.intellij.openapi.externalSystem.util.ExternalSystemConstants -import com.intellij.openapi.externalSystem.util.Order -import org.gradle.tooling.model.idea.IdeaModule -import org.jetbrains.kotlin.gradle.KotlinMPPGradleModel -import org.jetbrains.kotlin.gradle.KotlinMPPGradleModelBuilder -import org.jetbrains.kotlin.gradle.KotlinPlatform -import org.jetbrains.kotlin.idea.configuration.KotlinAndroidSourceSetData -import org.jetbrains.kotlin.idea.configuration.KotlinMPPGradleProjectResolver -import org.jetbrains.kotlin.idea.configuration.kotlinSourceSet -import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData -import org.jetbrains.plugins.gradle.service.project.AbstractProjectResolverExtension - -@Order(ExternalSystemConstants.UNORDERED - 1) -class KotlinAndroidMPPGradleProjectResolver : AbstractProjectResolverExtension() { - private val isAndroidProject by lazy { - resolverCtx.hasModulesWithModel(AndroidProject::class.java) - || resolverCtx.hasModulesWithModel(NativeAndroidProject::class.java) - } - - override fun getToolingExtensionsClasses(): Set> { - return setOf(KotlinMPPGradleModelBuilder::class.java, Unit::class.java) - } - - override fun getExtraProjectModelClasses(): Set> { - return setOf(KotlinMPPGradleModel::class.java) - } - - override fun createModule(gradleModule: IdeaModule, projectDataNode: DataNode): DataNode { - return super.createModule(gradleModule, projectDataNode).also { - initializeModuleData(gradleModule, it, projectDataNode) - } - } - - override fun populateModuleContentRoots(gradleModule: IdeaModule, ideModule: DataNode) { - super.populateModuleContentRoots(gradleModule, ideModule) - if (IdeInfo.getInstance().isAndroidStudio || isAndroidProject) { - KotlinMPPGradleProjectResolver.populateContentRoots(gradleModule, ideModule, resolverCtx) - // Work around module disposal service which discards modules without accompanying ImportedModule instance - for (childNode in ExternalSystemApiUtil.getChildren(ideModule, GradleSourceSetData.KEY)) { - if (childNode.kotlinSourceSet == null) continue - val moduleName = childNode.data.internalName - val importedModule = ImportedModule(gradleModule) - importedModuleNameField.set(importedModule, moduleName) - ideModule.createChild(IMPORTED_MODULE, importedModule) - } - } - } - - override fun populateModuleDependencies(gradleModule: IdeaModule, ideModule: DataNode, ideProject: DataNode) { - super.populateModuleDependencies(gradleModule, ideModule, ideProject) - if (isAndroidProject) { - KotlinMPPGradleProjectResolver.populateModuleDependencies(gradleModule, ideProject, ideModule, resolverCtx) - } - } - - private fun initializeModuleData( - gradleModule: IdeaModule, - mainModuleData: DataNode, - projectDataNode: DataNode - ) { - if (!isAndroidProject) return - - KotlinMPPGradleProjectResolver.initializeModuleData(gradleModule, mainModuleData, projectDataNode, resolverCtx) - - val mppModel = resolverCtx.getExtraProject(gradleModule, KotlinMPPGradleModel::class.java) ?: return - - val androidSourceSets = mppModel - .targets - .asSequence() - .flatMap { it.compilations.asSequence() } - .filter { it.platform == KotlinPlatform.ANDROID } - .mapNotNull { KotlinMPPGradleProjectResolver.createSourceSetInfo(it, gradleModule, resolverCtx) } - .toList() - mainModuleData.createChild(KotlinAndroidSourceSetData.KEY, KotlinAndroidSourceSetData(androidSourceSets)) - } - - companion object { - val importedModuleNameField by lazy { - ImportedModule::class.java.getDeclaredField("myName").apply { isAccessible = true } - } - } -} \ No newline at end of file diff --git a/idea/idea-android/src/org/jetbrains/kotlin/android/debugger/AndroidDexWrapper.kt.173 b/idea/idea-android/src/org/jetbrains/kotlin/android/debugger/AndroidDexWrapper.kt.173 deleted file mode 100644 index 0493c15ede7..00000000000 --- a/idea/idea-android/src/org/jetbrains/kotlin/android/debugger/AndroidDexWrapper.kt.173 +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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.kotlin.android.debugger - -import com.android.dx.cf.direct.DirectClassFile -import com.android.dx.cf.direct.StdAttributeFactory -import com.android.dx.dex.DexOptions -import com.android.dx.dex.cf.CfOptions -import com.android.dx.dex.cf.CfTranslator -import com.android.dx.dex.file.ClassDefItem -import com.android.dx.dex.file.DexFile -import com.intellij.ide.plugins.DynamicallyLoaded -import org.jetbrains.kotlin.idea.debugger.evaluate.classLoading.ClassToLoad -import java.lang.reflect.Modifier - -class AndroidDexWrapper { - @Suppress("unused") // Used in AndroidOClassLoadingAdapter#dex - fun dex(classes: Collection): ByteArray? { - val dexOptions = DexOptions() - val cfOptions = CfOptions() - - val dexFile = DexFile(dexOptions) - - val methodWithContext = CfTranslator::class.java.declaredMethods - .singleOrNull { it.name == "translate" && Modifier.isStatic(it.modifiers) && it.parameterCount == 6 } - - val dxContext = methodWithContext?.let { Class.forName("com.android.dx.command.dexer.DxContext").newInstance() } - - for ((_, relativeFileName, bytes) in classes) { - val cf = DirectClassFile(bytes, relativeFileName, true) - cf.setAttributeFactory(StdAttributeFactory.THE_ONE) - - val classDef = if (methodWithContext != null) { - methodWithContext( - null, - dxContext, - cf, - bytes, - cfOptions, - dexOptions, - dexFile - ) as ClassDefItem - } else { - CfTranslator.translate(cf, bytes, cfOptions, dexOptions, dexFile) - } - - dexFile.add(classDef) - } - - return dexFile.toDex(null, false) - } -} diff --git a/idea/idea-android/src/org/jetbrains/kotlin/android/debugger/AndroidDexerImpl.kt.173 b/idea/idea-android/src/org/jetbrains/kotlin/android/debugger/AndroidDexerImpl.kt.173 deleted file mode 100644 index 0cafa358089..00000000000 --- a/idea/idea-android/src/org/jetbrains/kotlin/android/debugger/AndroidDexerImpl.kt.173 +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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.kotlin.android.debugger - -import com.intellij.openapi.module.ModuleManager -import com.intellij.openapi.project.Project -import com.intellij.openapi.roots.ProjectRootModificationTracker -import com.intellij.psi.util.CachedValueProvider -import com.intellij.psi.util.CachedValuesManager -import org.jetbrains.android.facet.AndroidFacet -import org.jetbrains.kotlin.idea.debugger.evaluate.classLoading.AndroidDexer -import org.jetbrains.kotlin.idea.debugger.evaluate.classLoading.ClassToLoad -import java.io.File -import java.net.URLClassLoader -import java.security.ProtectionDomain - -class AndroidDexerImpl(val project: Project) : AndroidDexer { - private val cachedDexWrapper = CachedValuesManager.getManager(project).createCachedValue({ - val dexWrapper = doGetAndroidDexFile()?.let { dexJarFile -> - val androidDexWrapperName = AndroidDexWrapper::class.java.canonicalName - val classBytes = this.javaClass.classLoader.getResource( - androidDexWrapperName.replace('.', '/') + ".class").readBytes() - - val dexClassLoader = object : URLClassLoader(arrayOf(dexJarFile.toURI().toURL()), this::class.java.classLoader) { - init { - defineClass(androidDexWrapperName, classBytes, 0, classBytes.size, null as ProtectionDomain?) - } - } - - Class.forName(androidDexWrapperName, true, dexClassLoader).newInstance() - } - - CachedValueProvider.Result.createSingleDependency(dexWrapper, ProjectRootModificationTracker.getInstance(project)) - }, /* trackValue = */ false) - - override fun dex(classes: Collection): ByteArray? { - val dexWrapper = cachedDexWrapper.value - val dexMethod = dexWrapper::class.java.methods.firstOrNull { it.name == "dex" } ?: return null - return dexMethod.invoke(dexWrapper, classes) as? ByteArray ?: return null - } - - private fun doGetAndroidDexFile(): File? { - for (module in ModuleManager.getInstance(project).modules) { - val androidFacet = AndroidFacet.getInstance(module) ?: continue - val sdkData = androidFacet.sdkData ?: continue - val latestBuildTool = sdkData.getLatestBuildTool(/* allowPreview = */ false) - ?: sdkData.getLatestBuildTool(/* allowPreview = */ true) - ?: continue - - val dxJar = File(latestBuildTool.location, "lib/dx.jar") - if (dxJar.exists()) { - return dxJar - } - } - - return null - } -} \ No newline at end of file diff --git a/idea/idea-android/src/org/jetbrains/kotlin/android/folding/ResourceFoldingBuilder.kt.173 b/idea/idea-android/src/org/jetbrains/kotlin/android/folding/ResourceFoldingBuilder.kt.173 deleted file mode 100644 index 8d4992a0c04..00000000000 --- a/idea/idea-android/src/org/jetbrains/kotlin/android/folding/ResourceFoldingBuilder.kt.173 +++ /dev/null @@ -1,259 +0,0 @@ -/* - * 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.kotlin.android.folding - -import com.android.SdkConstants.* -import com.android.ide.common.resources.configuration.FolderConfiguration -import com.android.ide.common.resources.configuration.LocaleQualifier -import com.android.resources.ResourceType -import com.android.tools.idea.folding.AndroidFoldingSettings -import com.android.tools.idea.res.AppResourceRepository -import com.android.tools.idea.res.LocalResourceRepository -import com.intellij.lang.ASTNode -import com.intellij.lang.folding.FoldingBuilderEx -import com.intellij.lang.folding.FoldingDescriptor -import com.intellij.openapi.application.ApplicationManager -import com.intellij.openapi.components.ServiceManager -import com.intellij.openapi.editor.Document -import com.intellij.openapi.module.ModuleUtilCore -import com.intellij.openapi.util.text.StringUtil -import com.intellij.psi.PsiClass -import com.intellij.psi.PsiElement -import com.intellij.psi.impl.source.SourceTreeToPsiMap -import org.jetbrains.android.facet.AndroidFacet -import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.uast.* -import org.jetbrains.uast.visitor.AbstractUastVisitor -import java.util.regex.Pattern - - -class ResourceFoldingBuilder : FoldingBuilderEx() { - - companion object { - // See lint's StringFormatDetector - private val FORMAT = Pattern.compile("%(\\d+\\$)?([-+#, 0(<]*)?(\\d+)?(\\.\\d+)?([tT])?([a-zA-Z%])") - private val FOLD_MAX_LENGTH = 60 - private val FORCE_PROJECT_RESOURCE_LOADING = true - private val UNIT_TEST_MODE: Boolean = ApplicationManager.getApplication().isUnitTestMode - private val RESOURCE_TYPES = listOf(ResourceType.STRING, - ResourceType.DIMEN, - ResourceType.INTEGER, - ResourceType.PLURALS) - } - - private val isFoldingEnabled = AndroidFoldingSettings.getInstance().isCollapseAndroidStrings - - override fun getPlaceholderText(node: ASTNode): String? { - - tailrec fun UElement.unwrapReferenceAndGetValue(resources: LocalResourceRepository): String? = when (this) { - is UQualifiedReferenceExpression -> selector.unwrapReferenceAndGetValue(resources) - is UCallExpression -> (valueArguments.firstOrNull() as? UReferenceExpression)?.getAndroidResourceValue(resources, this) - else -> (this as? UReferenceExpression)?.getAndroidResourceValue(resources) - } - - val element = SourceTreeToPsiMap.treeElementToPsi(node) ?: return null - val appResources = getAppResources(element) ?: return null - val uastContext = ServiceManager.getService(element.project, UastContext::class.java) ?: return null - return uastContext.convertElement(element, null, null)?.unwrapReferenceAndGetValue(appResources) - } - - override fun buildFoldRegions(root: PsiElement, document: Document, quick: Boolean): Array { - if (root !is KtFile || quick && !UNIT_TEST_MODE || !isFoldingEnabled || AndroidFacet.getInstance(root) == null) { - return emptyArray() - } - - val file = root.toUElement() - val result = arrayListOf() - file?.accept(object : AbstractUastVisitor() { - override fun visitSimpleNameReferenceExpression(node: USimpleNameReferenceExpression): Boolean { - node.getFoldingDescriptor()?.let { result.add(it) } - return super.visitSimpleNameReferenceExpression(node) - } - }) - - return result.toTypedArray() - } - - override fun isCollapsedByDefault(node: ASTNode): Boolean = isFoldingEnabled - - private fun UReferenceExpression.getFoldingDescriptor(): FoldingDescriptor? { - val resolved = resolve() ?: return null - val resourceType = resolved.getAndroidResourceType() ?: return null - if (resourceType !in RESOURCE_TYPES) return null - - fun UElement.createFoldingDescriptor() = psi?.let { psi -> - val dependencies: Set = setOf(psi) - FoldingDescriptor(psi.node, psi.textRange, null, dependencies) - } - - val element = uastParent as? UQualifiedReferenceExpression ?: this - val getResourceValueCall = (element.uastParent as? UCallExpression)?.takeIf { it.isFoldableGetResourceValueCall() } - if (getResourceValueCall != null) { - val qualifiedCall = getResourceValueCall.uastParent as? UQualifiedReferenceExpression - if (qualifiedCall?.selector == getResourceValueCall) { - return qualifiedCall.createFoldingDescriptor() - } - - return getResourceValueCall.createFoldingDescriptor() - } - - return element.createFoldingDescriptor() - } - - private fun UCallExpression.isFoldableGetResourceValueCall(): Boolean { - return methodName == "getString" || - methodName == "getText" || - methodName == "getInteger" || - methodName?.startsWith("getDimension") ?: false || - methodName?.startsWith("getQuantityString") ?: false - } - - private fun PsiElement.getAndroidResourceType(): ResourceType? { - val elementType = parent as? PsiClass ?: return null - val elementPackage = elementType.parent as? PsiClass ?: return null - if (R_CLASS != elementPackage.name) return null - if (elementPackage.qualifiedName != "$ANDROID_PKG.$R_CLASS") { - return ResourceType.getEnum(elementType.name) - } - - return null - } - - private fun UReferenceExpression.getAndroidResourceValue(resources: LocalResourceRepository, call: UCallExpression? = null): String? { - val resourceType = resolve()?.getAndroidResourceType() ?: return null - val referenceConfig = FolderConfiguration().apply { localeQualifier = LocaleQualifier("xx") } - val key = resolvedName ?: return null - val resourceValue = resources.getResourceValue(resourceType, key, referenceConfig) ?: return null - val text = if (call != null) formatArguments(call, resourceValue) else resourceValue - - if (resourceType == ResourceType.STRING || resourceType == ResourceType.PLURALS) { - return '"' + StringUtil.shortenTextWithEllipsis(text, FOLD_MAX_LENGTH - 2, 0) + '"' - } - else if (text.length <= 1) { - // Don't just inline empty or one-character replacements: they can't be expanded by a mouse click - // so are hard to use without knowing about the folding keyboard shortcut to toggle folding. - // This is similar to how IntelliJ 14 handles call parameters - return key + ": " + text - } - - return StringUtil.shortenTextWithEllipsis(text, FOLD_MAX_LENGTH, 0) - } - - private tailrec fun LocalResourceRepository.getResourceValue( - type: ResourceType, - name: String, - referenceConfig: FolderConfiguration): String? { - val value = getConfiguredValue(type, name, referenceConfig)?.value ?: return null - if (!value.startsWith('@')) { - return value - } - - val (referencedTypeName, referencedName) = value.substring(1).split('/').takeIf { it.size == 2 } ?: return value - val referencedType = ResourceType.getEnum(referencedTypeName) ?: return value - return getResourceValue(referencedType, referencedName, referenceConfig) - } - - // Converted from com.android.tools.idea.folding.InlinedResource#insertArguments - private fun formatArguments(callExpression: UCallExpression, formatString: String): String { - if (!formatString.contains('%')) { - return formatString - } - - val args = callExpression.valueArguments - if (args.isEmpty() || !args.first().isPsiValid) { - return formatString - } - - val matcher = FORMAT.matcher(formatString) - var index = 0 - var prevIndex = 0 - var nextNumber = 1 - var start = 0 - val sb = StringBuilder(2 * formatString.length) - while (true) { - if (matcher.find(index)) { - if ("%" == matcher.group(6)) { - index = matcher.end() - continue - } - val matchStart = matcher.start() - // Make sure this is not an escaped '%' - while (prevIndex < matchStart) { - val c = formatString[prevIndex] - if (c == '\\') { - prevIndex++ - } - prevIndex++ - } - if (prevIndex > matchStart) { - // We're in an escape, ignore this result - index = prevIndex - continue - } - - index = matcher.end() - - // Shouldn't throw a number format exception since we've already - // matched the pattern in the regexp - val number: Int - var numberString: String? = matcher.group(1) - if (numberString != null) { - // Strip off trailing $ - numberString = numberString.substring(0, numberString.length - 1) - number = Integer.parseInt(numberString) - nextNumber = number + 1 - } - else { - number = nextNumber++ - } - - if (number > 0 && number < args.size) { - val argExpression = args[number] - var value: Any? = argExpression.evaluate() - - if (value == null) { - value = args[number].asSourceString() - } - - for (i in start..matchStart - 1) { - sb.append(formatString[i]) - } - - sb.append("{") - sb.append(value) - sb.append('}') - start = index - } - } - else { - var i = start - val n = formatString.length - while (i < n) { - sb.append(formatString[i]) - i++ - } - break - } - } - - return sb.toString() - } - - private fun getAppResources(element: PsiElement): LocalResourceRepository? = ModuleUtilCore.findModuleForPsiElement(element)?.let { - AppResourceRepository.getAppResources(it, FORCE_PROJECT_RESOURCE_LOADING) - } -} diff --git a/idea/idea-android/src/org/jetbrains/kotlin/android/inspection/TypeParameterFindViewByIdInspection.kt.173 b/idea/idea-android/src/org/jetbrains/kotlin/android/inspection/TypeParameterFindViewByIdInspection.kt.173 deleted file mode 100644 index 18d8a751604..00000000000 --- a/idea/idea-android/src/org/jetbrains/kotlin/android/inspection/TypeParameterFindViewByIdInspection.kt.173 +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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.kotlin.android.inspection - -import com.intellij.codeInspection.* -import com.intellij.openapi.project.Project -import com.intellij.psi.PsiElementVisitor -import org.jetbrains.android.facet.AndroidFacet -import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall -import org.jetbrains.kotlin.idea.inspections.AbstractKotlinInspection -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.KtPsiUtil.isUnsafeCast -import org.jetbrains.kotlin.psi.psiUtil.addTypeArgument - -class TypeParameterFindViewByIdInspection : AbstractKotlinInspection(), CleanupLocalInspectionTool { - override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor { - val compileSdk = AndroidFacet.getInstance(session.file)?.androidModuleInfo?.buildSdkVersion?.apiLevel - if (compileSdk == null || compileSdk < 26) { - return KtVisitorVoid() - } - - return object : KtVisitorVoid() { - override fun visitCallExpression(expression: KtCallExpression) { - super.visitCallExpression(expression) - if (expression.calleeExpression?.text != "findViewById" || expression.typeArguments.isNotEmpty()) { - return - } - - val parentCast = (expression.parent as? KtBinaryExpressionWithTypeRHS)?.takeIf { isUnsafeCast(it) } ?: return - val typeText = parentCast.right?.getTypeTextWithoutQuestionMark() ?: return - val callableDescriptor = expression.resolveToCall()?.resultingDescriptor ?: return - if (callableDescriptor.name.asString() != "findViewById" || callableDescriptor.typeParameters.size != 1) { - return - } - - holder.registerProblem( - parentCast, - "Can be converted to findViewById<$typeText>(...)", - ConvertCastToFindViewByIdWithTypeParameter()) - } - } - } - - class ConvertCastToFindViewByIdWithTypeParameter : LocalQuickFix { - override fun getFamilyName(): String = "Convert cast to findViewById with type parameter" - - override fun applyFix(project: Project, descriptor: ProblemDescriptor) { - val cast = descriptor.psiElement as? KtBinaryExpressionWithTypeRHS ?: return - val typeText = cast.right?.getTypeTextWithoutQuestionMark() ?: return - val call = cast.left as? KtCallExpression ?: return - - val newCall = call.copy() as KtCallExpression - val typeArgument = KtPsiFactory(call).createTypeArgument(typeText) - newCall.addTypeArgument(typeArgument) - - cast.replace(newCall) - } - } - - companion object { - fun KtTypeReference.getTypeTextWithoutQuestionMark(): String? = - (typeElement as? KtNullableType)?.innerType?.text ?: typeElement?.text - } -} \ No newline at end of file diff --git a/idea/idea-android/src/org/jetbrains/kotlin/android/navigation/KotlinAndroidGotoDeclarationHandler.java.173 b/idea/idea-android/src/org/jetbrains/kotlin/android/navigation/KotlinAndroidGotoDeclarationHandler.java.173 deleted file mode 100644 index 0410dfb1624..00000000000 --- a/idea/idea-android/src/org/jetbrains/kotlin/android/navigation/KotlinAndroidGotoDeclarationHandler.java.173 +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright 2010-2015 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.android.navigation; - -import com.android.resources.ResourceType; -import com.intellij.codeInsight.navigation.actions.GotoDeclarationHandler; -import com.intellij.openapi.actionSystem.DataContext; -import com.intellij.openapi.editor.Editor; -import com.intellij.psi.PsiElement; -import com.intellij.psi.xml.XmlElement; -import org.jetbrains.android.dom.AndroidAttributeValue; -import org.jetbrains.android.dom.manifest.Manifest; -import org.jetbrains.android.dom.manifest.ManifestElementWithRequiredName; -import org.jetbrains.android.dom.resources.Attr; -import org.jetbrains.android.dom.resources.DeclareStyleable; -import org.jetbrains.android.facet.AndroidFacet; -import org.jetbrains.android.resourceManagers.LocalResourceManager; -import org.jetbrains.android.resourceManagers.ResourceManager; -import org.jetbrains.android.util.AndroidResourceUtil; -import org.jetbrains.android.util.AndroidUtils; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.kotlin.android.AndroidUtilKt; -import org.jetbrains.kotlin.psi.KtSimpleNameExpression; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -// TODO: ask for extension point -// this class is mostly copied from org.jetbrains.android.AndroidGotoDeclarationHandler -public class KotlinAndroidGotoDeclarationHandler implements GotoDeclarationHandler { - @Override - public PsiElement[] getGotoDeclarationTargets(@Nullable PsiElement sourceElement, int offset, Editor editor) { - KtSimpleNameExpression referenceExpression = GotoResourceHelperKt.getReferenceExpression(sourceElement); - if (referenceExpression == null) { - return null; - } - - AndroidFacet facet = AndroidUtilKt.getAndroidFacetForFile(referenceExpression); - if (facet == null) { - return null; - } - - AndroidResourceUtil.MyReferredResourceFieldInfo info = GotoResourceHelperKt.getInfo(referenceExpression, facet); - - if (info == null) return null; - - String nestedClassName = info.getClassName(); - String fieldName = info.getFieldName(); - List resourceList = new ArrayList(); - - if (info.isFromManifest()) { - collectManifestElements(nestedClassName, fieldName, facet, resourceList); - } - else { - ResourceManager manager = info.isSystem() - ? facet.getSystemResourceManager(false) - : facet.getLocalResourceManager(); - if (manager == null) { - return null; - } - manager.collectLazyResourceElements(nestedClassName, fieldName, false, referenceExpression, resourceList); - - if (manager instanceof LocalResourceManager) { - LocalResourceManager lrm = (LocalResourceManager) manager; - - if (nestedClassName.equals(ResourceType.ATTR.getName())) { - for (Attr attr : lrm.findAttrs(fieldName)) { - resourceList.add(attr.getName().getXmlAttributeValue()); - } - } - else if (nestedClassName.equals(ResourceType.STYLEABLE.getName())) { - for (DeclareStyleable styleable : lrm.findStyleables(fieldName)) { - resourceList.add(styleable.getName().getXmlAttributeValue()); - } - - for (Attr styleable : lrm.findStyleableAttributesByFieldName(fieldName)) { - resourceList.add(styleable.getName().getXmlAttributeValue()); - } - } - } - } - - if (resourceList.size() > 1) { - // Sort to ensure the output is stable, and to prefer the base folders - Collections.sort(resourceList, AndroidResourceUtil.RESOURCE_ELEMENT_COMPARATOR); - } - - return resourceList.toArray(new PsiElement[resourceList.size()]); - } - - private static void collectManifestElements( - @NotNull String nestedClassName, - @NotNull String fieldName, - @NotNull AndroidFacet facet, - @NotNull List result - ) { - Manifest manifest = facet.getManifest(); - - if (manifest == null) { - return; - } - List list; - - if ("permission".equals(nestedClassName)) { - list = manifest.getPermissions(); - } - else if ("permission_group".equals(nestedClassName)) { - list = manifest.getPermissionGroups(); - } - else { - return; - } - for (ManifestElementWithRequiredName domElement : list) { - AndroidAttributeValue nameAttribute = domElement.getName(); - String name = nameAttribute.getValue(); - - if (AndroidUtils.equal(name, fieldName, false)) { - XmlElement psiElement = nameAttribute.getXmlAttributeValue(); - - if (psiElement != null) { - result.add(psiElement); - } - } - } - } - - @Override - public String getActionText(DataContext context) { - return null; - } -} diff --git a/idea/idea-android/src/org/jetbrains/kotlin/android/quickfix/AddTargetApiQuickFix.kt.173 b/idea/idea-android/src/org/jetbrains/kotlin/android/quickfix/AddTargetApiQuickFix.kt.173 deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/idea/idea-android/src/org/jetbrains/kotlin/android/quickfix/AddTargetVersionCheckQuickFix.kt.173 b/idea/idea-android/src/org/jetbrains/kotlin/android/quickfix/AddTargetVersionCheckQuickFix.kt.173 deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/idea/idea-android/src/org/jetbrains/kotlin/android/quickfix/ApiUtils.kt.173 b/idea/idea-android/src/org/jetbrains/kotlin/android/quickfix/ApiUtils.kt.173 deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/idea/idea-android/src/org/jetbrains/kotlin/android/quickfix/KotlinAndroidQuickFixProvider.kt.173 b/idea/idea-android/src/org/jetbrains/kotlin/android/quickfix/KotlinAndroidQuickFixProvider.kt.173 deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/idea/idea-android/src/org/jetbrains/kotlin/android/quickfix/ParcelableQuickFix.kt.173 b/idea/idea-android/src/org/jetbrains/kotlin/android/quickfix/ParcelableQuickFix.kt.173 deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/idea/idea-android/src/org/jetbrains/kotlin/android/quickfix/SuppressLintQuickFix.kt.173 b/idea/idea-android/src/org/jetbrains/kotlin/android/quickfix/SuppressLintQuickFix.kt.173 deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/idea/idea-android/tests/org/jetbrains/kotlin/android/lint/AbstractKotlinLintTest.kt.173 b/idea/idea-android/tests/org/jetbrains/kotlin/android/lint/AbstractKotlinLintTest.kt.173 deleted file mode 100644 index 0acc40b7c13..00000000000 --- a/idea/idea-android/tests/org/jetbrains/kotlin/android/lint/AbstractKotlinLintTest.kt.173 +++ /dev/null @@ -1,84 +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.kotlin.android.lint - -import com.intellij.codeInspection.InspectionProfileEntry -import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl -import com.intellij.util.PathUtil -import org.jetbrains.android.inspections.klint.AndroidLintInspectionBase -import org.jetbrains.kotlin.android.KotlinAndroidTestCase -import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil -import org.jetbrains.kotlin.test.InTextDirectivesUtils -import org.jetbrains.kotlin.test.InTextDirectivesUtils.findStringWithPrefixes -import java.io.File - -abstract class AbstractKotlinLintTest : KotlinAndroidTestCase() { - - override fun setUp() { - super.setUp() - AndroidLintInspectionBase.invalidateInspectionShortName2IssueMap() - (myFixture as CodeInsightTestFixtureImpl).setVirtualFileFilter { false } // Allow access to tree elements. - ConfigLibraryUtil.configureKotlinRuntime(myModule) - ConfigLibraryUtil.addLibrary(myModule, "androidExtensionsRuntime", "dist/kotlinc/lib", arrayOf("android-extensions-runtime.jar")) - } - - override fun tearDown() { - ConfigLibraryUtil.unConfigureKotlinRuntime(myModule) - ConfigLibraryUtil.removeLibrary(myModule, "androidExtensionsRuntime") - super.tearDown() - } - - fun doTest(path: String) { - val ktFile = File(path) - val fileText = ktFile.readText() - val mainInspectionClassName = findStringWithPrefixes(fileText, "// INSPECTION_CLASS: ") ?: error("Empty class name") - val dependencies = InTextDirectivesUtils.findLinesWithPrefixesRemoved(fileText, "// DEPENDENCY: ") - - val inspectionClassNames = mutableListOf(mainInspectionClassName) - for (i in 2..100) { - val className = findStringWithPrefixes(ktFile.readText(), "// INSPECTION_CLASS$i: ") ?: break - inspectionClassNames += className - } - - myFixture.enableInspections(*inspectionClassNames.map { className -> - val inspectionClass = Class.forName(className) - inspectionClass.newInstance() as InspectionProfileEntry - }.toTypedArray()) - - val additionalResourcesDir = File(ktFile.parentFile, getTestName(true)) - if (additionalResourcesDir.exists()) { - for (file in additionalResourcesDir.listFiles()) { - if (file.isFile) { - myFixture.copyFileToProject(file.absolutePath, file.name) - } - else if (file.isDirectory) { - myFixture.copyDirectoryToProject(file.absolutePath, file.name) - } - } - } - - val virtualFile = myFixture.copyFileToProject(ktFile.absolutePath, "src/${PathUtil.getFileName(path)}") - myFixture.configureFromExistingVirtualFile(virtualFile) - - dependencies.forEach { dependency -> - val (dependencyFile, dependencyTargetPath) = dependency.split(" -> ").map(String::trim) - myFixture.copyFileToProject("${PathUtil.getParentPath(path)}/$dependencyFile", "src/$dependencyTargetPath") - } - - myFixture.checkHighlighting(true, false, true) - } -} \ No newline at end of file diff --git a/idea/idea-android/tests/org/jetbrains/kotlin/android/quickfix/AbstractAndroidLintQuickfixTest.kt.173 b/idea/idea-android/tests/org/jetbrains/kotlin/android/quickfix/AbstractAndroidLintQuickfixTest.kt.173 deleted file mode 100644 index b46f1d76409..00000000000 --- a/idea/idea-android/tests/org/jetbrains/kotlin/android/quickfix/AbstractAndroidLintQuickfixTest.kt.173 +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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.kotlin.android.quickfix - -import com.intellij.codeInspection.InspectionProfileEntry -import com.intellij.openapi.util.io.FileUtil -import com.intellij.util.PathUtil -import org.jetbrains.android.inspections.klint.AndroidLintInspectionBase -import org.jetbrains.kotlin.android.KotlinAndroidTestCase -import org.jetbrains.kotlin.test.InTextDirectivesUtils -import java.io.File - - -abstract class AbstractAndroidLintQuickfixTest : KotlinAndroidTestCase() { - - override fun setUp() { - AndroidLintInspectionBase.invalidateInspectionShortName2IssueMap() - super.setUp() - } - - fun doTest(path: String) { - val fileText = FileUtil.loadFile(File(path), true) - val intentionText = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// INTENTION_TEXT: ") ?: error("Empty intention text") - val mainInspectionClassName = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// INSPECTION_CLASS: ") ?: error("Empty inspection class name") - val dependency = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// DEPENDENCY: ") - val intentionAvailable = !InTextDirectivesUtils.isDirectiveDefined(fileText, "// INTENTION_NOT_AVAILABLE") - - val inspection = Class.forName(mainInspectionClassName).newInstance() as InspectionProfileEntry - myFixture.enableInspections(inspection) - - val sourceFile = myFixture.copyFileToProject(path, "src/${PathUtil.getFileName(path)}") - myFixture.configureFromExistingVirtualFile(sourceFile) - - if (dependency != null) { - val (dependencyFile, dependencyTargetPath) = dependency.split(" -> ").map(String::trim) - myFixture.copyFileToProject("${PathUtil.getParentPath(path)}/$dependencyFile", "src/$dependencyTargetPath") - } - - if (intentionAvailable) { - val intention = myFixture.getAvailableIntention(intentionText) ?: error("Failed to find intention") - myFixture.launchAction(intention) - myFixture.checkResultByFile(path + ".expected") - } - else { - assertNull("Intention should not be available", myFixture.availableIntentions.find { it.text == intentionText }) - } - } -} \ No newline at end of file diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/GradleBuildScriptManipulator.kt.173 b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/GradleBuildScriptManipulator.kt.173 deleted file mode 100644 index f89534e77eb..00000000000 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/GradleBuildScriptManipulator.kt.173 +++ /dev/null @@ -1,107 +0,0 @@ -/* - * 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.kotlin.idea.configuration - -import com.intellij.openapi.roots.DependencyScope -import com.intellij.openapi.roots.ExternalLibraryDescriptor -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiFile -import org.gradle.util.GradleVersion -import org.jetbrains.kotlin.config.LanguageFeature -import org.jetbrains.kotlin.idea.util.application.runReadAction -import org.jetbrains.plugins.gradle.frameworkSupport.BuildScriptDataBuilder - -interface GradleBuildScriptManipulator { - val scriptFile: Psi - val preferNewSyntax: Boolean - - fun isConfiguredWithOldSyntax(kotlinPluginName: String): Boolean - fun isConfigured(kotlinPluginExpression: String): Boolean - - fun configureModuleBuildScript( - kotlinPluginName: String, - kotlinPluginExpression: String, - stdlibArtifactName: String, - version: String, - jvmTarget: String? - ): Boolean - - fun configureProjectBuildScript(kotlinPluginName: String, version: String): Boolean - - fun changeCoroutineConfiguration(coroutineOption: String): PsiElement? - - fun changeLanguageFeatureConfiguration(feature: LanguageFeature, state: LanguageFeature.State, forTests: Boolean): PsiElement? - - fun changeLanguageVersion(version: String, forTests: Boolean): PsiElement? - - fun changeApiVersion(version: String, forTests: Boolean): PsiElement? - - fun addKotlinLibraryToModuleBuildScript( - scope: DependencyScope, - libraryDescriptor: ExternalLibraryDescriptor - ) - - fun getKotlinStdlibVersion(): String? - - // For settings.gradle/settings.gradle.kts - - fun addMavenCentralPluginRepository() - fun addPluginRepository(repository: RepositoryDescription) - - fun addResolutionStrategy(pluginId: String) -} - - -// Kept for compatibility reasons (pre-181.3 IDEAs) -val BuildScriptDataBuilder.gradleVersion get() = GradleVersion.version("0.0") - -fun fetchGradleVersion(psiFile: PsiFile): GradleVersion { - return gradleVersionFromFile(psiFile) ?: GradleVersion.current() -} - -private fun gradleVersionFromFile(psiFile: PsiFile): GradleVersion? { - return null -} - -val MIN_GRADLE_VERSION_FOR_NEW_PLUGIN_SYNTAX = GradleVersion.version("4.4") - -fun GradleBuildScriptManipulator<*>.useNewSyntax(kotlinPluginName: String, gradleVersion: GradleVersion): Boolean { - if (!preferNewSyntax) return false - - if (gradleVersion < MIN_GRADLE_VERSION_FOR_NEW_PLUGIN_SYNTAX) return false - - if (isConfiguredWithOldSyntax(kotlinPluginName)) return false - - val fileText = runReadAction { scriptFile.text } - val hasOldApply = fileText.contains("apply plugin:") - - return !hasOldApply -} - -private val MIN_GRADLE_VERSION_FOR_API_AND_IMPLEMENTATION = GradleVersion.version("3.4") - -fun GradleVersion.scope(directive: String): String { - if (this < MIN_GRADLE_VERSION_FOR_API_AND_IMPLEMENTATION) { - return when (directive) { - "implementation" -> "compile" - "testImplementation" -> "testCompile" - else -> throw IllegalArgumentException("Unknown directive `$directive`") - } - } - - return directive -} \ No newline at end of file diff --git a/idea/idea-gradle/tests/org/jetbrains/kotlin/gradle/GradleMultiplatformWizardTest.kt.173 b/idea/idea-gradle/tests/org/jetbrains/kotlin/gradle/GradleMultiplatformWizardTest.kt.173 deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/codeInsight/gradle/GradleConfiguratorPlatformSpecificTest.kt.173 b/idea/idea-gradle/tests/org/jetbrains/kotlin/idea/codeInsight/gradle/GradleConfiguratorPlatformSpecificTest.kt.173 deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/ThreadTrackerPatcherForTeamCityTesting.kt.173 b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/ThreadTrackerPatcherForTeamCityTesting.kt.173 deleted file mode 100644 index 8c34aef9dde..00000000000 --- a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/ThreadTrackerPatcherForTeamCityTesting.kt.173 +++ /dev/null @@ -1,77 +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.kotlin.idea - -import com.intellij.concurrency.IdeaForkJoinWorkerThreadFactory -import com.intellij.testFramework.ThreadTracker -import java.lang.reflect.Modifier -import java.util.concurrent.ForkJoinPool -import java.util.concurrent.atomic.AtomicBoolean - -/* -Workaround for ThreadTracker.checkLeak() failures on TeamCity. - -Currently TeamCity runs tests in classloader without boot.jar where IdeaForkJoinWorkerThreadFactory is defined. That -makes ForkJoinPool.commonPool() silently ignores java.util.concurrent.ForkJoinPool.common.threadFactory -(because of java.lang.ClassNotFoundException) option during factory initialization. - -Standard names for ForkJoinPool threads doesn't pass ThreadTracker.checkLeak() check and that ruins tests constantly. -As it's allowed to reorder tests on TeamCity and any test can be first at some point, this patch should be applied at -some common place. - */ -object ThreadTrackerPatcherForTeamCityTesting { - private val patched = AtomicBoolean(false) - - fun patchThreadTracker() { - if (patched.get()) return - - patched.compareAndSet(false, true) - - IdeaForkJoinWorkerThreadFactory.setupForkJoinCommonPool() - - // Check setup was successful and patching isn't needed - val commonPoolFactoryName = ForkJoinPool.commonPool().factory::class.java.name - if (commonPoolFactoryName == IdeaForkJoinWorkerThreadFactory::class.java.name) { - return - } - - try { - val wellKnownOffendersField = try { - ThreadTracker::class.java.getDeclaredField("wellKnownOffenders") - } - catch (communityPropertyNotFoundEx: NoSuchFieldException) { - ThreadTracker::class.java.declaredFields.single { - Modifier.isStatic(it.modifiers) && MutableSet::class.java.isAssignableFrom(it.type) - } - } - - wellKnownOffendersField.isAccessible = true - - @Suppress("UNCHECKED_CAST") - val wellKnownOffenders = wellKnownOffendersField.get(null) as MutableSet - - wellKnownOffenders.add("ForkJoinPool.commonPool-worker-") - println("Patching ThreadTracker was successful") - } - catch (e: NoSuchFieldException) { - println("Patching ThreadTracker failed: " + e) - } - catch (e: IllegalAccessException) { - println("Patching ThreadTracker failed: " + e) - } - } -} \ No newline at end of file diff --git a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/KotlinDebuggerSettings.kt.173 b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/KotlinDebuggerSettings.kt.173 deleted file mode 100644 index 2da0e9f679a..00000000000 --- a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/debugger/KotlinDebuggerSettings.kt.173 +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license - * that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.idea.debugger - - -import com.intellij.openapi.components.State -import com.intellij.openapi.components.Storage -import com.intellij.openapi.options.Configurable -import com.intellij.openapi.options.SimpleConfigurable -import com.intellij.openapi.util.Getter -import com.intellij.util.xmlb.XmlSerializerUtil -import com.intellij.xdebugger.XDebuggerUtil -import com.intellij.xdebugger.settings.DebuggerSettingsCategory -import com.intellij.xdebugger.settings.XDebuggerSettings -import org.jetbrains.kotlin.idea.debugger.stepping.KotlinSteppingConfigurableUi - -@State(name = "KotlinDebuggerSettings", storages = arrayOf(Storage("kotlin_debug.xml"))) -class KotlinDebuggerSettings : XDebuggerSettings("kotlin_debugger"), Getter { - var DEBUG_RENDER_DELEGATED_PROPERTIES: Boolean = true - var DEBUG_DISABLE_KOTLIN_INTERNAL_CLASSES: Boolean = true - var DEBUG_IS_FILTER_FOR_STDLIB_ALREADY_ADDED: Boolean = false - - companion object { - fun getInstance(): KotlinDebuggerSettings { - return XDebuggerUtil.getInstance()?.getDebuggerSettings(KotlinDebuggerSettings::class.java)!! - } - } - - override fun createConfigurables(category: DebuggerSettingsCategory): Collection { - return when (category) { - DebuggerSettingsCategory.STEPPING -> - listOf(SimpleConfigurable.create( - "reference.idesettings.debugger.kotlin.stepping", - "Kotlin", - KotlinSteppingConfigurableUi::class.java, - this)) - DebuggerSettingsCategory.DATA_VIEWS -> - listOf(SimpleConfigurable.create( - "reference.idesettings.debugger.kotlin.data.view", - "Kotlin", - KotlinDelegatedPropertyRendererConfigurableUi::class.java, - this)) - else -> listOf() - } - } - - override fun getState() = this - override fun get() = this - - override fun loadState(state: KotlinDebuggerSettings?) { - if (state != null) XmlSerializerUtil.copyBean(state, this) - } -} diff --git a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/injection/KotlinLanguageInjector.kt.173 b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/injection/KotlinLanguageInjector.kt.173 deleted file mode 100644 index 5b4834bceba..00000000000 --- a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/injection/KotlinLanguageInjector.kt.173 +++ /dev/null @@ -1,442 +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.kotlin.idea.injection - -import com.intellij.codeInsight.AnnotationUtil -import com.intellij.lang.injection.MultiHostInjector -import com.intellij.lang.injection.MultiHostRegistrar -import com.intellij.openapi.application.ApplicationManager -import com.intellij.openapi.progress.ProgressManager -import com.intellij.openapi.project.Project -import com.intellij.openapi.util.Key -import com.intellij.openapi.util.text.StringUtilRt -import com.intellij.patterns.PatternCondition -import com.intellij.patterns.PatternConditionPlus -import com.intellij.patterns.PsiClassNamePatternCondition -import com.intellij.patterns.ValuePatternCondition -import com.intellij.psi.* -import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil -import com.intellij.psi.search.LocalSearchScope -import com.intellij.psi.search.searches.ReferencesSearch -import com.intellij.psi.util.CachedValueProvider -import com.intellij.psi.util.CachedValuesManager -import com.intellij.psi.util.PsiTreeUtil -import org.intellij.plugins.intelliLang.Configuration -import org.intellij.plugins.intelliLang.inject.InjectorUtils -import org.intellij.plugins.intelliLang.inject.LanguageInjectionSupport -import org.intellij.plugins.intelliLang.inject.TemporaryPlacesRegistry -import org.intellij.plugins.intelliLang.inject.config.BaseInjection -import org.intellij.plugins.intelliLang.inject.config.InjectionPlace -import org.intellij.plugins.intelliLang.inject.java.JavaLanguageInjectionSupport -import org.intellij.plugins.intelliLang.util.AnnotationUtilEx -import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.descriptors.annotations.Annotated -import org.jetbrains.kotlin.idea.caches.resolve.analyze -import org.jetbrains.kotlin.idea.patterns.KotlinFunctionPattern -import org.jetbrains.kotlin.idea.references.KtReference -import org.jetbrains.kotlin.idea.references.mainReference -import org.jetbrains.kotlin.idea.runInReadActionWithWriteActionPriority -import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor -import org.jetbrains.kotlin.idea.util.ProjectRootsUtil -import org.jetbrains.kotlin.idea.util.application.progressIndicatorNullable -import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.resolve.annotations.argumentValue -import org.jetbrains.kotlin.resolve.constants.StringValue -import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode -import org.jetbrains.kotlin.util.aliasImportMap -import org.jetbrains.kotlin.utils.SmartList -import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull -import org.jetbrains.kotlin.utils.addToStdlib.safeAs - -class KotlinLanguageInjector( - private val configuration: Configuration, - private val project: Project, - private val temporaryPlacesRegistry: TemporaryPlacesRegistry -) : MultiHostInjector { - companion object { - private val STRING_LITERALS_REGEXP = "\"([^\"]*)\"".toRegex() - private val ABSENT_KOTLIN_INJECTION = BaseInjection("ABSENT_KOTLIN_BASE_INJECTION") - } - - private val kotlinSupport: KotlinLanguageInjectionSupport? by lazy { - ArrayList(InjectorUtils.getActiveInjectionSupports()).filterIsInstance(KotlinLanguageInjectionSupport::class.java).firstOrNull() - } - - private data class KotlinCachedInjection(val modificationCount: Long, val baseInjection: BaseInjection) - - private var KtStringTemplateExpression.cachedInjectionWithModification: KotlinCachedInjection? by UserDataProperty( - Key.create("CACHED_INJECTION_WITH_MODIFICATION")) - - override fun getLanguagesToInject(registrar: MultiHostRegistrar, context: PsiElement) { - val ktHost: KtStringTemplateExpression = context as? KtStringTemplateExpression ?: return - if (!context.isValidHost) return - - val support = kotlinSupport ?: return - - if (!ProjectRootsUtil.isInProjectOrLibSource(ktHost.containingFile.originalFile)) return - - val needImmediateAnswer = with(ApplicationManager.getApplication()) { isDispatchThread && !isUnitTestMode } - val kotlinCachedInjection = ktHost.cachedInjectionWithModification - val modificationCount = PsiManager.getInstance(project).modificationTracker.modificationCount - - val baseInjection = when { - needImmediateAnswer -> { - // Can't afford long counting or typing will be laggy. Force cache reuse even if it's outdated. - kotlinCachedInjection?.baseInjection ?: ABSENT_KOTLIN_INJECTION - } - kotlinCachedInjection != null && (modificationCount == kotlinCachedInjection.modificationCount) -> - // Cache is up-to-date - kotlinCachedInjection.baseInjection - else -> { - fun computeAndCache(): BaseInjection { - val computedInjection = computeBaseInjection(ktHost, support, registrar) ?: ABSENT_KOTLIN_INJECTION - ktHost.cachedInjectionWithModification = KotlinCachedInjection(modificationCount, computedInjection) - return computedInjection - } - - if (ApplicationManager.getApplication().isReadAccessAllowed && ProgressManager.getInstance().progressIndicatorNullable == null) { - // The action cannot be canceled by caller and by internal checkCanceled() calls. - // Force creating new indicator that is canceled on write action start, otherwise there might be lags in typing. - runInReadActionWithWriteActionPriority(::computeAndCache) ?: kotlinCachedInjection?.baseInjection ?: ABSENT_KOTLIN_INJECTION - } - else { - computeAndCache() - } - } - } - - if (baseInjection == ABSENT_KOTLIN_INJECTION) { - return - } - - val language = InjectorUtils.getLanguageByString(baseInjection.injectedLanguageId) ?: return - - if (ktHost.hasInterpolation()) { - val file = ktHost.containingKtFile - val parts = splitLiteralToInjectionParts(baseInjection, ktHost) ?: return - - if (parts.ranges.isEmpty()) return - - InjectorUtils.registerInjection(language, parts.ranges, file, registrar) - InjectorUtils.registerSupport(support, false, registrar) - InjectorUtils.putInjectedFileUserData(registrar, InjectedLanguageUtil.FRANKENSTEIN_INJECTION, - if (parts.isUnparsable) java.lang.Boolean.TRUE else null) - } - else { - InjectorUtils.registerInjectionSimple(ktHost, baseInjection, support, registrar) - } - } - - @Suppress("FoldInitializerAndIfToElvis") - private fun computeBaseInjection( - ktHost: KtStringTemplateExpression, - support: KotlinLanguageInjectionSupport, - registrar: MultiHostRegistrar): BaseInjection? { - val containingFile = ktHost.containingFile - - val tempInjectedLanguage = temporaryPlacesRegistry.getLanguageFor(ktHost, containingFile) - if (tempInjectedLanguage != null) { - InjectorUtils.putInjectedFileUserData(registrar, LanguageInjectionSupport.TEMPORARY_INJECTED_LANGUAGE, tempInjectedLanguage) - return BaseInjection(support.id).apply { - injectedLanguageId = tempInjectedLanguage.id - prefix = tempInjectedLanguage.prefix - suffix = tempInjectedLanguage.suffix - } - } - - return findInjectionInfo(ktHost)?.toBaseInjection(support) - } - - override fun elementsToInjectIn(): List> { - return listOf(KtStringTemplateExpression::class.java) - } - - private fun findInjectionInfo(place: KtElement, originalHost: Boolean = true): InjectionInfo? { - return injectWithExplicitCodeInstruction(place) - ?: injectWithCall(place) - ?: injectReturnValue(place) - ?: injectInAnnotationCall(place) - ?: injectWithReceiver(place) - ?: injectWithVariableUsage(place, originalHost) - } - - private fun injectReturnValue(place: KtElement): InjectionInfo? { - val parent = place.parent - - tailrec fun findReturnExpression(expression: PsiElement?): KtReturnExpression? = when (expression) { - is KtReturnExpression -> expression - is KtBinaryExpression -> findReturnExpression(expression.takeIf { it.operationToken == KtTokens.ELVIS }?.parent) - is KtContainerNodeForControlStructureBody, is KtIfExpression -> findReturnExpression(expression.parent) - else -> null - } - - val returnExp = findReturnExpression(parent) ?: return null - - if (returnExp.labeledExpression != null) return null - - val callableDeclaration = PsiTreeUtil.getParentOfType(returnExp, KtDeclaration::class.java) as? KtCallableDeclaration ?: return null - if (callableDeclaration.annotationEntries.isEmpty()) return null - - val descriptor = callableDeclaration.descriptor ?: return null - return injectionInfoByAnnotation(descriptor) - } - - private fun injectWithExplicitCodeInstruction(host: KtElement): InjectionInfo? { - val support = kotlinSupport ?: return null - return InjectionInfo.fromBaseInjection(support.findCommentInjection(host)) ?: support.findAnnotationInjectionLanguageId(host) - } - - private fun injectWithReceiver(host: KtElement): InjectionInfo? { - val qualifiedExpression = host.parent as? KtDotQualifiedExpression ?: return null - if (qualifiedExpression.receiverExpression != host) return null - - val callExpression = qualifiedExpression.selectorExpression as? KtCallExpression ?: return null - val callee = callExpression.calleeExpression ?: return null - - if (isAnalyzeOff()) return null - - val kotlinInjections = configuration.getInjections(KOTLIN_SUPPORT_ID) - - val calleeName = callee.text - val possibleNames = collectPossibleNames(kotlinInjections) - - if (calleeName !in possibleNames) { - return null - } - - for (reference in callee.references) { - ProgressManager.checkCanceled() - - val resolvedTo = reference.resolve() - if (resolvedTo is KtFunction) { - val injectionInfo = findInjection(resolvedTo.receiverTypeReference, kotlinInjections) - if (injectionInfo != null) { - return injectionInfo - } - } - } - - return null - } - - private fun collectPossibleNames(injections: List): Set { - val result = HashSet() - - for (injection in injections) { - val injectionPlaces = injection.injectionPlaces - for (place in injectionPlaces) { - val placeStr = place.toString() - val literals = STRING_LITERALS_REGEXP.findAll(placeStr).map { it.groupValues[1] } - result.addAll(literals) - } - } - - return result - } - - private fun injectWithVariableUsage(host: KtElement, originalHost: Boolean): InjectionInfo? { - // Given place is not original host of the injection so we stop to prevent stepping through indirect references - if (!originalHost) return null - - val ktProperty = host.parent as? KtProperty ?: return null - if (ktProperty.initializer != host) return null - - if (isAnalyzeOff()) return null - - val searchScope = LocalSearchScope(arrayOf(ktProperty.containingFile), "", true) - return ReferencesSearch.search(ktProperty, searchScope).asSequence().mapNotNull { psiReference -> - val element = psiReference.element as? KtElement ?: return@mapNotNull null - findInjectionInfo(element, false) - }.firstOrNull() - } - - private fun injectWithCall(host: KtElement): InjectionInfo? { - val ktHost: KtElement = host - val argument = ktHost.parent as? KtValueArgument ?: return null - - val callExpression = PsiTreeUtil.getParentOfType(ktHost, KtCallElement::class.java) ?: return null - val callee = getNameReference(callExpression.calleeExpression) ?: return null - - if (isAnalyzeOff()) return null - - for (reference in callee.references) { - ProgressManager.checkCanceled() - - val resolvedTo = reference.resolve() - if (resolvedTo is PsiMethod) { - val injectionForJavaMethod = injectionForJavaMethod(argument, resolvedTo) - if (injectionForJavaMethod != null) { - return injectionForJavaMethod - } - } - else if (resolvedTo is KtFunction) { - val injectionForJavaMethod = injectionForKotlinCall(argument, resolvedTo, reference) - if (injectionForJavaMethod != null) { - return injectionForJavaMethod - } - } - } - - return null - } - - private fun getNameReference(callee: KtExpression?): KtNameReferenceExpression? { - if (callee is KtConstructorCalleeExpression) - return callee.constructorReferenceExpression as? KtNameReferenceExpression - return callee as? KtNameReferenceExpression - } - - private fun injectInAnnotationCall(host: KtElement): InjectionInfo? { - val argument = host.parent as? KtValueArgument ?: return null - val annotationEntry = argument.parent.parent as? KtCallElement ?: return null - if (!fastCheckInjectionsExists(annotationEntry)) return null - val calleeExpression = annotationEntry.calleeExpression ?: return null - val callee = getNameReference(calleeExpression)?.mainReference?.resolve() - when (callee) { - is PsiClass -> { - val psiClass = callee as? PsiClass ?: return null - val argumentName = argument.getArgumentName()?.asName?.identifier ?: "value" - val method = psiClass.findMethodsByName(argumentName, false).singleOrNull() ?: return null - return findInjection(method, configuration.getInjections(JavaLanguageInjectionSupport.JAVA_SUPPORT_ID)) - } - else -> return null - } - - } - - private fun injectionForJavaMethod(argument: KtValueArgument, javaMethod: PsiMethod): InjectionInfo? { - val argumentIndex = (argument.parent as KtValueArgumentList).arguments.indexOf(argument) - val psiParameter = javaMethod.parameterList.parameters.getOrNull(argumentIndex) ?: return null - - val injectionInfo = findInjection(psiParameter, configuration.getInjections(JavaLanguageInjectionSupport.JAVA_SUPPORT_ID)) - if (injectionInfo != null) { - return injectionInfo - } - - val annotations = AnnotationUtilEx.getAnnotationFrom( - psiParameter, - configuration.advancedConfiguration.languageAnnotationPair, - true) - - if (annotations.isNotEmpty()) { - return processAnnotationInjectionInner(annotations) - } - - return null - } - - private fun injectionForKotlinCall(argument: KtValueArgument, ktFunction: KtFunction, reference: PsiReference): InjectionInfo? { - val argumentIndex = (argument.parent as KtValueArgumentList).arguments.indexOf(argument) - val ktParameter = ktFunction.valueParameters.getOrNull(argumentIndex) ?: return null - - val patternInjection = findInjection(ktParameter, configuration.getInjections(KOTLIN_SUPPORT_ID)) - if (patternInjection != null) { - return patternInjection - } - - // Found psi element after resolve can be obtained from compiled declaration but annotations parameters are lost there. - // Search for original descriptor from reference. - val ktReference = reference as? KtReference ?: return null - val bindingContext = ktReference.element.analyze(BodyResolveMode.PARTIAL_WITH_DIAGNOSTICS) - val functionDescriptor = ktReference.resolveToDescriptors(bindingContext).singleOrNull() as? FunctionDescriptor ?: return null - - val parameterDescriptor = functionDescriptor.valueParameters.getOrNull(argumentIndex) ?: return null - return injectionInfoByAnnotation(parameterDescriptor) - } - - private fun injectionInfoByAnnotation(annotated: Annotated): InjectionInfo? { - val injectAnnotation = annotated.annotations.findAnnotation(FqName(AnnotationUtil.LANGUAGE)) ?: return null - - val languageId = injectAnnotation.argumentValue("value")?.safeAs()?.value ?: return null - val prefix = injectAnnotation.argumentValue("prefix")?.safeAs()?.value - val suffix = injectAnnotation.argumentValue("suffix")?.safeAs()?.value - - return InjectionInfo(languageId, prefix, suffix) - } - - private fun findInjection(element: PsiElement?, injections: List): InjectionInfo? { - for (injection in injections) { - if (injection.acceptsPsiElement(element)) { - return InjectionInfo(injection.injectedLanguageId, injection.prefix, injection.suffix) - } - } - - return null - } - - private fun isAnalyzeOff(): Boolean { - return configuration.advancedConfiguration.dfaOption == Configuration.DfaOption.OFF - } - - private fun processAnnotationInjectionInner(annotations: Array): InjectionInfo? { - val id = AnnotationUtilEx.calcAnnotationValue(annotations, "value") - val prefix = AnnotationUtilEx.calcAnnotationValue(annotations, "prefix") - val suffix = AnnotationUtilEx.calcAnnotationValue(annotations, "suffix") - - return InjectionInfo(id, prefix, suffix) - } - - private val injectableTargetClassShortNames = CachedValuesManager.getManager(project) - .createCachedValue({ - CachedValueProvider.Result.create(HashSet().apply { - for (injection in configuration.getInjections(JavaLanguageInjectionSupport.JAVA_SUPPORT_ID)) { - for (injectionPlace in injection.injectionPlaces) { - for (targetClassFQN in retrieveJavaPlaceTargetClassesFQNs(injectionPlace)) { - add(StringUtilRt.getShortName(targetClassFQN)) - } - } - } - for (injection in configuration.getInjections(org.jetbrains.kotlin.idea.injection.KOTLIN_SUPPORT_ID)) { - for (injectionPlace in injection.injectionPlaces) { - for (targetClassFQN in retrieveKotlinPlaceTargetClassesFQNs(injectionPlace)) { - add(StringUtilRt.getShortName(targetClassFQN)) - } - } - } - }, configuration) - }, false) - - private fun fastCheckInjectionsExists(annotationEntry: KtCallElement): Boolean { - val referencedName = getNameReference(annotationEntry.calleeExpression)?.getReferencedName() ?: return false - val annotationShortName = annotationEntry.containingKtFile.aliasImportMap()[referencedName].singleOrNull() ?: referencedName - return annotationShortName in injectableTargetClassShortNames.value - } - - private fun retrieveJavaPlaceTargetClassesFQNs(place: InjectionPlace): Collection { - val classCondition = place.elementPattern.condition.conditions.firstOrNull { it.debugMethodName == "definedInClass" } - as? PatternConditionPlus<*, *> ?: return emptyList() - val psiClassNamePatternCondition = classCondition.valuePattern.condition.conditions. - firstIsInstanceOrNull() ?: return emptyList() - val valuePatternCondition = psiClassNamePatternCondition.namePattern.condition.conditions.firstIsInstanceOrNull>() ?: return emptyList() - return valuePatternCondition.values - } - - private fun retrieveKotlinPlaceTargetClassesFQNs(place: InjectionPlace): Collection { - val classNames = SmartList() - fun collect(condition: PatternCondition<*>) { - when (condition) { - is PatternConditionPlus<*, *> -> condition.valuePattern.condition.conditions.forEach { collect(it) } - is KotlinFunctionPattern.DefinedInClassCondition -> classNames.add(condition.fqName) - } - } - place.elementPattern.condition.conditions.forEach { collect(it) } - return classNames - } - -} \ No newline at end of file diff --git a/idea/idea-maven/build.gradle.kts.173 b/idea/idea-maven/build.gradle.kts.173 deleted file mode 100644 index 39331142c17..00000000000 --- a/idea/idea-maven/build.gradle.kts.173 +++ /dev/null @@ -1,73 +0,0 @@ - -plugins { - kotlin("jvm") - id("jps-compatible") -} - -dependencies { - compile(project(":core:util.runtime")) - compile(project(":compiler:frontend")) - compile(project(":compiler:frontend.java")) - compile(project(":compiler:util")) - compile(project(":compiler:cli-common")) - compile(project(":kotlin-build-common")) - - compile(project(":js:js.frontend")) - - compile(project(":idea")) - compile(project(":idea:idea-jvm")) - compile(project(":idea:idea-jps-common")) - - compileOnly(intellijDep()) - excludeInAndroidStudio(rootProject) { compileOnly(intellijPluginDep("maven")) } - - testCompile(projectTests(":idea")) - testCompile(projectTests(":compiler:tests-common")) - testCompile(projectTests(":idea:idea-test-framework")) - - testCompileOnly(intellijDep()) - testCompileOnly(intellijPluginDep("maven")) - - testCompile(project(":idea:idea-native")) { isTransitive = false } - testRuntime(project(":kotlin-native:kotlin-native-library-reader")) { isTransitive = false } - testRuntime(project(":kotlin-native:kotlin-native-utils")) { isTransitive = false } - - testRuntime(project(":kotlin-reflect")) - testRuntime(project(":idea:idea-jvm")) - testRuntime(project(":idea:idea-android")) - testRuntime(project(":plugins:android-extensions-ide")) - testRuntime(project(":plugins:lint")) - testRuntime(project(":sam-with-receiver-ide-plugin")) - testRuntime(project(":allopen-ide-plugin")) - testRuntime(project(":noarg-ide-plugin")) - testRuntime(project(":kotlin-scripting-idea")) - testRuntime(project(":kotlinx-serialization-ide-plugin")) - - testRuntime(intellijDep()) - // TODO: the order of the plugins matters here, consider avoiding order-dependency - testRuntime(intellijPluginDep("junit")) - testRuntime(intellijPluginDep("testng")) - testRuntime(intellijPluginDep("properties")) - testRuntime(intellijPluginDep("gradle")) - testRuntime(intellijPluginDep("Groovy")) - testRuntime(intellijPluginDep("coverage")) - testRuntime(intellijPluginDep("maven")) - testRuntime(intellijPluginDep("android")) -} - -sourceSets { - "main" { projectDefault() } - "test" { projectDefault() } -} - -testsJar() - -projectTest { - workingDir = rootDir -} - -runtimeJar { - archiveName = "maven-ide.jar" -} - -ideaPlugin() \ No newline at end of file diff --git a/idea/idea-maven/src/org/jetbrains/kotlin/idea/maven/KotlinMavenImporter.kt.173 b/idea/idea-maven/src/org/jetbrains/kotlin/idea/maven/KotlinMavenImporter.kt.173 deleted file mode 100644 index f4bba6dbc65..00000000000 --- a/idea/idea-maven/src/org/jetbrains/kotlin/idea/maven/KotlinMavenImporter.kt.173 +++ /dev/null @@ -1,424 +0,0 @@ -/* - * 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.kotlin.idea.maven - -import com.intellij.openapi.components.PersistentStateComponent -import com.intellij.openapi.components.State -import com.intellij.openapi.components.Storage -import com.intellij.openapi.components.StoragePathMacros -import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider -import com.intellij.openapi.module.Module -import com.intellij.openapi.roots.* -import com.intellij.openapi.roots.impl.libraries.LibraryEx -import com.intellij.openapi.roots.libraries.Library -import com.intellij.openapi.util.AsyncResult -import com.intellij.util.PairConsumer -import com.intellij.util.PathUtil -import org.jdom.Element -import org.jdom.Text -import org.jetbrains.idea.maven.importing.MavenImporter -import org.jetbrains.idea.maven.importing.MavenRootModelAdapter -import org.jetbrains.idea.maven.model.MavenPlugin -import org.jetbrains.idea.maven.project.* -import org.jetbrains.jps.model.java.JavaSourceRootType -import org.jetbrains.jps.model.module.JpsModuleSourceRootType -import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments -import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments -import org.jetbrains.kotlin.cli.common.arguments.K2MetadataCompilerArguments -import org.jetbrains.kotlin.cli.common.arguments.parseCommandLineArguments -import org.jetbrains.kotlin.compilerRunner.ArgumentUtils -import org.jetbrains.kotlin.config.* -import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor -import org.jetbrains.kotlin.idea.facet.* -import org.jetbrains.kotlin.idea.framework.detectLibraryKind -import org.jetbrains.kotlin.idea.maven.configuration.KotlinMavenConfigurator -import org.jetbrains.kotlin.idea.platform.tooling -import org.jetbrains.kotlin.platform.IdePlatform -import org.jetbrains.kotlin.platform.IdePlatformKind -import org.jetbrains.kotlin.platform.impl.CommonIdePlatformKind -import org.jetbrains.kotlin.platform.impl.JsIdePlatformKind -import org.jetbrains.kotlin.platform.impl.JvmIdePlatformKind -import org.jetbrains.kotlin.platform.impl.isCommon -import org.jetbrains.kotlin.utils.SmartList -import org.jetbrains.kotlin.utils.addIfNotNull -import java.io.File -import java.util.* - -interface MavenProjectImportHandler { - companion object : ProjectExtensionDescriptor( - "org.jetbrains.kotlin.mavenProjectImportHandler", - MavenProjectImportHandler::class.java - ) - - operator fun invoke(facet: KotlinFacet, mavenProject: MavenProject) -} - -class KotlinMavenImporter : MavenImporter(KOTLIN_PLUGIN_GROUP_ID, KOTLIN_PLUGIN_ARTIFACT_ID) { - companion object { - const val KOTLIN_PLUGIN_GROUP_ID = "org.jetbrains.kotlin" - const val KOTLIN_PLUGIN_ARTIFACT_ID = "kotlin-maven-plugin" - - const val KOTLIN_PLUGIN_SOURCE_DIRS_CONFIG = "sourceDirs" - } - - override fun preProcess( - module: Module, - mavenProject: MavenProject, - changes: MavenProjectChanges, - modifiableModelsProvider: IdeModifiableModelsProvider - ) { - } - - override fun process( - modifiableModelsProvider: IdeModifiableModelsProvider, - module: Module, - rootModel: MavenRootModelAdapter, - mavenModel: MavenProjectsTree, - mavenProject: MavenProject, - changes: MavenProjectChanges, - mavenProjectToModuleName: MutableMap, - postTasks: MutableList - ) { - - if (changes.plugins) { - contributeSourceDirectories(mavenProject, module, rootModel) - } - } - - override fun postProcess( - module: Module, - mavenProject: MavenProject, - changes: MavenProjectChanges, - modifiableModelsProvider: IdeModifiableModelsProvider - ) { - super.postProcess(module, mavenProject, changes, modifiableModelsProvider) - - if (changes.dependencies) { - scheduleDownloadStdlibSources(mavenProject, module) - - val targetLibraryKind = detectPlatformByExecutions(mavenProject)?.tooling?.libraryKind - if (targetLibraryKind != null) { - modifiableModelsProvider.getModifiableRootModel(module).orderEntries().forEachLibrary { library -> - if ((library as LibraryEx).kind == null) { - val model = modifiableModelsProvider.getModifiableLibraryModel(library) as LibraryEx.ModifiableModelEx - detectLibraryKind(model.getFiles(OrderRootType.CLASSES))?.let { model.kind = it } - } - true - } - } - } - - configureFacet(mavenProject, modifiableModelsProvider, module) - } - - private fun scheduleDownloadStdlibSources(mavenProject: MavenProject, module: Module) { - // TODO: here we have to process all kotlin libraries but for now we only handle standard libraries - val artifacts = mavenProject.dependencyArtifactIndex.data[KOTLIN_PLUGIN_GROUP_ID]?.values?.flatMap { it.filter { it.isResolved } } - ?: emptyList() - - val librariesWithNoSources = ArrayList() - OrderEnumerator.orderEntries(module).forEachLibrary { library -> - if (library.modifiableModel.getFiles(OrderRootType.SOURCES).isEmpty()) { - librariesWithNoSources.add(library) - } - true - } - val libraryNames = librariesWithNoSources.mapTo(HashSet()) { it.name } - val toBeDownloaded = artifacts.filter { it.libraryName in libraryNames } - - if (toBeDownloaded.isNotEmpty()) { - MavenProjectsManager.getInstance(module.project) - .scheduleArtifactsDownloading(listOf(mavenProject), toBeDownloaded, true, false, AsyncResult()) - } - } - - private fun configureJSOutputPaths( - mavenProject: MavenProject, - modifiableRootModel: ModifiableRootModel, - facetSettings: KotlinFacetSettings, - mavenPlugin: MavenPlugin - ) { - fun parentPath(path: String): String = - File(path).absoluteFile.parentFile.absolutePath - - val sharedOutputFile = mavenPlugin.configurationElement?.getChild("outputFile")?.text - - val compilerModuleExtension = modifiableRootModel.getModuleExtension(CompilerModuleExtension::class.java) ?: return - val buildDirectory = mavenProject.buildDirectory - - val executions = mavenPlugin.executions - - executions.forEach { - val explicitOutputFile = it.configurationElement?.getChild("outputFile")?.text ?: sharedOutputFile - if (PomFile.KotlinGoals.Js in it.goals) { - // see org.jetbrains.kotlin.maven.K2JSCompilerMojo - val outputFilePath = PathUtil.toSystemDependentName(explicitOutputFile ?: "$buildDirectory/js/${mavenProject.mavenId.artifactId}.js") - compilerModuleExtension.setCompilerOutputPath(parentPath(outputFilePath)) - facetSettings.productionOutputPath = outputFilePath - } - if (PomFile.KotlinGoals.TestJs in it.goals) { - // see org.jetbrains.kotlin.maven.KotlinTestJSCompilerMojo - val outputFilePath = PathUtil.toSystemDependentName(explicitOutputFile ?: "$buildDirectory/test-js/${mavenProject.mavenId.artifactId}-tests.js") - compilerModuleExtension.setCompilerOutputPathForTests(parentPath(outputFilePath)) - facetSettings.testOutputPath = outputFilePath - } - } - } - - private fun getCompilerArgumentsByConfigurationElement( - mavenProject: MavenProject, - configuration: Element?, - platform: IdePlatform<*, *> - ): List { - val arguments = platform.createArguments() - - arguments.apiVersion = configuration?.getChild("apiVersion")?.text ?: - mavenProject.properties["kotlin.compiler.apiVersion"]?.toString() - arguments.languageVersion = configuration?.getChild("languageVersion")?.text ?: - mavenProject.properties["kotlin.compiler.languageVersion"]?.toString() - arguments.multiPlatform = configuration?.getChild("multiPlatform")?.text?.trim()?.toBoolean() ?: false - arguments.suppressWarnings = configuration?.getChild("nowarn")?.text?.trim()?.toBoolean() ?: false - - configuration?.getChild("experimentalCoroutines")?.text?.trim()?.let { - arguments.coroutinesState = it - } - - when (arguments) { - is K2JVMCompilerArguments -> { - arguments.classpath = configuration?.getChild("classpath")?.text - arguments.jdkHome = configuration?.getChild("jdkHome")?.text - arguments.jvmTarget = configuration?.getChild("jvmTarget")?.text ?: - mavenProject.properties["kotlin.compiler.jvmTarget"]?.toString() - arguments.javaParameters = configuration?.getChild("javaParameters")?.text?.toBoolean() ?: false - } - is K2JSCompilerArguments -> { - arguments.sourceMap = configuration?.getChild("sourceMap")?.text?.trim()?.toBoolean() ?: false - arguments.sourceMapPrefix = configuration?.getChild("sourceMapPrefix")?.text?.trim() ?: "" - arguments.sourceMapEmbedSources = configuration?.getChild("sourceMapEmbedSources")?.text?.trim() ?: "inlining" - arguments.outputFile = configuration?.getChild("outputFile")?.text - arguments.metaInfo = configuration?.getChild("metaInfo")?.text?.trim()?.toBoolean() ?: false - arguments.moduleKind = configuration?.getChild("moduleKind")?.text - arguments.main = configuration?.getChild("main")?.text - } - } - - val additionalArgs = SmartList().apply { - val argsElement = configuration?.getChild("args") - - argsElement?.content?.forEach { argElement -> - when (argElement) { - is Text -> { - argElement.text?.let { addAll(splitArgumentString(it)) } - } - is Element -> { - if (argElement.name == "arg") { - addIfNotNull(argElement.text) - } - } - } - } - } - parseCommandLineArguments(additionalArgs, arguments) - - return ArgumentUtils.convertArgumentsToStringList(arguments) - } - - private val compilationGoals = listOf( - PomFile.KotlinGoals.Compile, - PomFile.KotlinGoals.TestCompile, - PomFile.KotlinGoals.Js, - PomFile.KotlinGoals.TestJs, - PomFile.KotlinGoals.MetaData - ) - - private fun configureFacet(mavenProject: MavenProject, modifiableModelsProvider: IdeModifiableModelsProvider, module: Module) { - val mavenPlugin = mavenProject.findPlugin(KotlinMavenConfigurator.GROUP_ID, KotlinMavenConfigurator.MAVEN_PLUGIN_ID) ?: return - val compilerVersion = mavenPlugin.version ?: LanguageVersion.LATEST_STABLE.versionString - val kotlinFacet = module.getOrCreateFacet( - modifiableModelsProvider, - false, - ExternalProjectSystemRegistry.MAVEN_EXTERNAL_SOURCE_ID - ) - - // TODO There should be a way to figure out the correct platform version - val platform = detectPlatform(mavenProject)?.defaultPlatform - - kotlinFacet.configureFacet(compilerVersion, LanguageFeature.Coroutines.defaultState, platform, modifiableModelsProvider) - val facetSettings = kotlinFacet.configuration.settings - val configuredPlatform = kotlinFacet.configuration.settings.platform!! - val configuration = mavenPlugin.configurationElement - val sharedArguments = getCompilerArgumentsByConfigurationElement(mavenProject, configuration, configuredPlatform) - val executionArguments = mavenPlugin.executions - ?.firstOrNull { it.goals.any { it in compilationGoals } } - ?.configurationElement?.let { getCompilerArgumentsByConfigurationElement(mavenProject, it, configuredPlatform) } - parseCompilerArgumentsToFacet(sharedArguments, emptyList(), kotlinFacet, modifiableModelsProvider) - if (executionArguments != null) { - parseCompilerArgumentsToFacet(executionArguments, emptyList(), kotlinFacet, modifiableModelsProvider) - } - if (facetSettings.compilerArguments is K2JSCompilerArguments) { - configureJSOutputPaths(mavenProject, modifiableModelsProvider.getModifiableRootModel(module), facetSettings, mavenPlugin) - } - MavenProjectImportHandler.getInstances(module.project).forEach { it(kotlinFacet, mavenProject) } - setImplementedModuleName(kotlinFacet, mavenProject, module) - kotlinFacet.noVersionAutoAdvance() - } - - private fun detectPlatform(mavenProject: MavenProject) = - detectPlatformByExecutions(mavenProject) ?: detectPlatformByLibraries(mavenProject) - - private fun detectPlatformByExecutions(mavenProject: MavenProject): IdePlatformKind<*>? { - return mavenProject.findPlugin(KOTLIN_PLUGIN_GROUP_ID, KOTLIN_PLUGIN_ARTIFACT_ID)?.executions?.flatMap { it.goals } - ?.mapNotNull { goal -> - when (goal) { - PomFile.KotlinGoals.Compile, PomFile.KotlinGoals.TestCompile -> JvmIdePlatformKind - PomFile.KotlinGoals.Js, PomFile.KotlinGoals.TestJs -> JsIdePlatformKind - PomFile.KotlinGoals.MetaData -> CommonIdePlatformKind - else -> null - } - }?.distinct()?.singleOrNull() - } - - private fun detectPlatformByLibraries(mavenProject: MavenProject): IdePlatformKind<*>? { - for (kind in IdePlatformKind.ALL_KINDS) { - val mavenLibraryIds = kind.tooling.mavenLibraryIds - if (mavenLibraryIds.any { mavenProject.findDependencies(KOTLIN_PLUGIN_GROUP_ID, it).isNotEmpty() }) { - // TODO we could return here the correct version - return kind - } - } - - return null - } - - // TODO in theory it should work like this but it doesn't as it couldn't unmark source roots that are not roots anymore. - // I believe this is something should be done by the underlying maven importer implementation or somewhere else in the IDEA - // For now there is a contributeSourceDirectories implementation that deals with the issue - // see https://youtrack.jetbrains.com/issue/IDEA-148280 - - // override fun collectSourceRoots(mavenProject: MavenProject, result: PairConsumer>) { - // for ((type, dir) in collectSourceDirectories(mavenProject)) { - // val jpsType: JpsModuleSourceRootType<*> = when (type) { - // SourceType.PROD -> JavaSourceRootType.SOURCE - // SourceType.TEST -> JavaSourceRootType.TEST_SOURCE - // } - // - // result.consume(dir, jpsType) - // } - // } - - private fun contributeSourceDirectories(mavenProject: MavenProject, module: Module, rootModel: MavenRootModelAdapter) { - val directories = collectSourceDirectories(mavenProject) - - val toBeAdded = directories.map { it.second }.toSet() - val state = module.kotlinImporterComponent - - val isNonJvmModule = mavenProject - .plugins - .asSequence() - .filter { it.isKotlinPlugin() } - .flatMap { it.executions.asSequence() } - .flatMap { it.goals.asSequence() } - .any { it in PomFile.KotlinGoals.CompileGoals && it !in PomFile.KotlinGoals.JvmGoals } - - val prodSourceRootType: JpsModuleSourceRootType<*> = if (isNonJvmModule) KotlinSourceRootType.Source else JavaSourceRootType.SOURCE - val testSourceRootType: JpsModuleSourceRootType<*> = if (isNonJvmModule) KotlinSourceRootType.TestSource else JavaSourceRootType.TEST_SOURCE - - for ((type, dir) in directories) { - if (rootModel.getSourceFolder(File(dir)) == null) { - val jpsType: JpsModuleSourceRootType<*> = when (type) { - SourceType.TEST -> testSourceRootType - SourceType.PROD -> prodSourceRootType - } - - rootModel.addSourceFolder(dir, jpsType) - } - } - - if (isNonJvmModule) { - mavenProject.sources.forEach { rootModel.addSourceFolder(it, KotlinSourceRootType.Source) } - mavenProject.testSources.forEach { rootModel.addSourceFolder(it, KotlinSourceRootType.TestSource) } - mavenProject.resources.forEach { rootModel.addSourceFolder(it.directory, KotlinResourceRootType.Resource) } - mavenProject.testResources.forEach { rootModel.addSourceFolder(it.directory, KotlinResourceRootType.TestResource) } - } - - state.addedSources.filter { it !in toBeAdded }.forEach { - rootModel.unregisterAll(it, true, true) - state.addedSources.remove(it) - } - state.addedSources.addAll(toBeAdded) - } - - private fun collectSourceDirectories(mavenProject: MavenProject): List> = - mavenProject.plugins.filter { it.isKotlinPlugin() }.flatMap { plugin -> - plugin.configurationElement.sourceDirectories().map { SourceType.PROD to it } + - plugin.executions.flatMap { execution -> - execution.configurationElement.sourceDirectories().map { execution.sourceType() to it } - } - }.distinct() - - private fun setImplementedModuleName(kotlinFacet: KotlinFacet, mavenProject: MavenProject, module: Module) { - if (kotlinFacet.configuration.settings.platform.isCommon) { - kotlinFacet.configuration.settings.implementedModuleNames = emptyList() - } else { - val manager = MavenProjectsManager.getInstance(module.project) - val mavenDependencies = mavenProject.dependencies.mapNotNull { manager?.findProject(it) } - val implemented = mavenDependencies.filter { detectPlatformByExecutions(it).isCommon } - - kotlinFacet.configuration.settings.implementedModuleNames = implemented.map { manager.findModule(it)?.name ?: it.displayName } - } - } -} - -private fun MavenPlugin.isKotlinPlugin() = - groupId == KotlinMavenImporter.KOTLIN_PLUGIN_GROUP_ID && artifactId == KotlinMavenImporter.KOTLIN_PLUGIN_ARTIFACT_ID - -private fun Element?.sourceDirectories(): List = - this?.getChildren(KotlinMavenImporter.KOTLIN_PLUGIN_SOURCE_DIRS_CONFIG)?.flatMap { it.children ?: emptyList() }?.map { it.textTrim } - ?: emptyList() - -private fun MavenPlugin.Execution.sourceType() = - goals.map { if (isTestGoalName(it)) SourceType.TEST else SourceType.PROD } - .distinct() - .singleOrNull() ?: SourceType.PROD - -private fun isTestGoalName(goalName: String) = goalName.startsWith("test-") - -private enum class SourceType { - PROD, TEST -} - -@State( - name = "AutoImportedSourceRoots", - storages = [(Storage(id = "other", file = StoragePathMacros.MODULE_FILE))] -) -class KotlinImporterComponent : PersistentStateComponent { - class State(var directories: List = ArrayList()) - - val addedSources: MutableSet = Collections.synchronizedSet(HashSet()) - - override fun loadState(state: State) { - addedSources.clear() - addedSources.addAll(state.directories) - } - - override fun getState(): State { - return State(addedSources.sorted()) - } -} - -private val Module.kotlinImporterComponent: KotlinImporterComponent - get() = getComponent(KotlinImporterComponent::class.java) ?: throw IllegalStateException("No maven importer state configured") diff --git a/idea/idea-maven/testData/languageFeature/addKotlinReflect/pom.xml.after.173 b/idea/idea-maven/testData/languageFeature/addKotlinReflect/pom.xml.after.173 deleted file mode 100644 index 0236b164547..00000000000 --- a/idea/idea-maven/testData/languageFeature/addKotlinReflect/pom.xml.after.173 +++ /dev/null @@ -1,61 +0,0 @@ - - - 4.0.0 - - maventest - maventest - 1.0-SNAPSHOT - - $VERSION$ - - - - org.jetbrains.kotlin - kotlin-stdlib-jre8 - ${kotlin.version} - - - org.jetbrains.kotlin - kotlin-test - ${kotlin.version} - test - - - org.jetbrains.kotlin - kotlin-reflect - RELEASE - - - - - ${project.basedir}/src/main/kotlin - - - org.jetbrains.kotlin - kotlin-maven-plugin - ${kotlin.version} - - - compile - compile - - wrong-goal - compile - - - - test-compile - test-compile - - test-compile - - - - - - - - - \ No newline at end of file diff --git a/idea/idea-test-framework/test/org/jetbrains/kotlin/idea/test/fixTemplates.kt.173 b/idea/idea-test-framework/test/org/jetbrains/kotlin/idea/test/fixTemplates.kt.173 deleted file mode 100644 index ea6c26d417d..00000000000 --- a/idea/idea-test-framework/test/org/jetbrains/kotlin/idea/test/fixTemplates.kt.173 +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license - * that can be found in the license/LICENSE.txt file. - */ - -@file:Suppress("UnusedImport") - -package org.jetbrains.kotlin.idea.test - -import com.intellij.codeInsight.CodeInsightTestCase - -// Unneeded in 181, but used in 173 -// BUNCH: 181 -fun fixTemplates() { - CodeInsightTestCase.fixTemplates() -} \ No newline at end of file diff --git a/idea/kotlin-gradle-tooling/build.gradle.kts.173 b/idea/kotlin-gradle-tooling/build.gradle.kts.173 deleted file mode 100644 index 1b609295537..00000000000 --- a/idea/kotlin-gradle-tooling/build.gradle.kts.173 +++ /dev/null @@ -1,25 +0,0 @@ - -description = "Kotlin Gradle Tooling support" - -plugins { - kotlin("jvm") - id("jps-compatible") -} - -jvmTarget = "1.6" - -dependencies { - compile(project(":kotlin-stdlib")) - compile(project(":compiler:cli-common")) - compile(intellijPluginDep("gradle")) - compileOnly(intellijDep()) { includeJars("slf4j-api-1.7.10") } -} - -sourceSets { - "main" { projectDefault() } - "test" {} -} - -runtimeJar() - -ideaPlugin() diff --git a/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelBuilder.kt.173 b/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelBuilder.kt.173 deleted file mode 100644 index 39db8ee8983..00000000000 --- a/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelBuilder.kt.173 +++ /dev/null @@ -1,434 +0,0 @@ -/* - * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license - * that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.gradle - -import org.gradle.api.Named -import org.gradle.api.NamedDomainObjectContainer -import org.gradle.api.Project -import org.gradle.api.Task -import org.gradle.api.artifacts.Configuration -import org.gradle.api.artifacts.Dependency -import org.gradle.api.artifacts.component.ProjectComponentIdentifier -import org.gradle.api.file.FileCollection -import org.gradle.api.file.SourceDirectorySet -import org.gradle.api.logging.Logging -import org.jetbrains.plugins.gradle.model.* -import org.jetbrains.plugins.gradle.tooling.ErrorMessageBuilder -import org.jetbrains.plugins.gradle.tooling.ModelBuilderService -import org.jetbrains.plugins.gradle.tooling.util.DependencyResolver -import org.jetbrains.plugins.gradle.tooling.util.DependencyResolverImpl -import org.jetbrains.plugins.gradle.tooling.util.SourceSetCachedFinder -import java.io.File -import java.lang.reflect.Method - -class KotlinMPPGradleModelBuilder : ModelBuilderService { - override fun getErrorMessageBuilder(project: Project, e: Exception): ErrorMessageBuilder { - return ErrorMessageBuilder - .create(project, e, "Gradle import errors") - .withDescription("Unable to build Kotlin project configuration") - } - - override fun canBuild(modelName: String?): Boolean { - return modelName == KotlinMPPGradleModel::class.java.name - } - - override fun buildAll(modelName: String, project: Project): Any? { - val dependencyResolver = DependencyResolverImpl( - project, - false, - false, - true, - SourceSetCachedFinder(project) - ) - val sourceSets = buildSourceSets(dependencyResolver, project) ?: return null - val sourceSetMap = sourceSets.map { it.name to it }.toMap() - val targets = buildTargets(sourceSetMap, dependencyResolver, project) ?: return null - computeSourceSetsDeferredInfo(sourceSets, targets) - val coroutinesState = getCoroutinesState(project) - reportUnresolvedDependencies(targets) - return KotlinMPPGradleModelImpl(sourceSetMap, targets, ExtraFeaturesImpl(coroutinesState)) - } - - private fun reportUnresolvedDependencies(targets: Collection) { - targets - .asSequence() - .flatMap { it.compilations.asSequence() } - .flatMap { it.dependencies.asSequence() } - .mapNotNull { (it as? UnresolvedExternalDependency)?.failureMessage } - .toSet() - .forEach { logger.warn(it) } - } - - private fun getCoroutinesState(project: Project): String? { - val kotlinExt = project.extensions.findByName("kotlin") ?: return null - val getExperimental = kotlinExt.javaClass.getMethodOrNull("getExperimental") ?: return null - val experimentalExt = getExperimental(kotlinExt) ?: return null - val getCoroutines = experimentalExt.javaClass.getMethodOrNull("getCoroutines") ?: return null - return getCoroutines(experimentalExt) as? String - } - - private fun buildSourceSets(dependencyResolver: DependencyResolver, project: Project): Collection? { - val kotlinExt = project.extensions.findByName("kotlin") ?: return null - val getSourceSets = kotlinExt.javaClass.getMethodOrNull("getSourceSets") ?: return null - @Suppress("UNCHECKED_CAST") - val sourceSets = - (getSourceSets(kotlinExt) as? NamedDomainObjectContainer)?.asMap?.values ?: emptyList() - return sourceSets.mapNotNull { buildSourceSet(it, dependencyResolver, project) } - } - - private fun buildSourceSet( - gradleSourceSet: Named, - dependencyResolver: DependencyResolver, - project: Project - ): KotlinSourceSetImpl? { - val sourceSetClass = gradleSourceSet.javaClass - val getLanguageSettings = sourceSetClass.getMethodOrNull("getLanguageSettings") ?: return null - val getSourceDirSet = sourceSetClass.getMethodOrNull("getKotlin") ?: return null - val getResourceDirSet = sourceSetClass.getMethodOrNull("getResources") ?: return null - val getDependsOn = sourceSetClass.getMethodOrNull("getDependsOn") ?: return null - val languageSettings = getLanguageSettings(gradleSourceSet)?.let { buildLanguageSettings(it) } ?: return null - val sourceDirs = (getSourceDirSet(gradleSourceSet) as? SourceDirectorySet)?.srcDirs ?: emptySet() - val resourceDirs = (getResourceDirSet(gradleSourceSet) as? SourceDirectorySet)?.srcDirs ?: emptySet() - val dependencies = buildSourceSetDependencies(gradleSourceSet, dependencyResolver, project) - @Suppress("UNCHECKED_CAST") - val dependsOnSourceSets = (getDependsOn(gradleSourceSet) as? Set)?.mapTo(LinkedHashSet()) { it.name } ?: emptySet() - return KotlinSourceSetImpl(gradleSourceSet.name, languageSettings, sourceDirs, resourceDirs, dependencies, dependsOnSourceSets) - } - - private fun buildLanguageSettings(gradleLanguageSettings: Any): KotlinLanguageSettings? { - val languageSettingsClass = gradleLanguageSettings.javaClass - val getLanguageVersion = languageSettingsClass.getMethodOrNull("getLanguageVersion") ?: return null - val getApiVersion = languageSettingsClass.getMethodOrNull("getApiVersion") ?: return null - val getProgressiveMode = languageSettingsClass.getMethodOrNull("getProgressiveMode") ?: return null - val getEnabledLanguageFeatures = languageSettingsClass.getMethodOrNull("getEnabledLanguageFeatures") ?: return null - val getExperimentalAnnotationsInUse = languageSettingsClass.getMethodOrNull("getExperimentalAnnotationsInUse") - val getCompilerPluginArguments = languageSettingsClass.getMethodOrNull("getCompilerPluginArguments") - val getCompilerPluginClasspath = languageSettingsClass.getMethodOrNull("getCompilerPluginClasspath") - @Suppress("UNCHECKED_CAST") - return KotlinLanguageSettingsImpl( - getLanguageVersion(gradleLanguageSettings) as? String, - getApiVersion(gradleLanguageSettings) as? String, - getProgressiveMode(gradleLanguageSettings) as? Boolean ?: false, - getEnabledLanguageFeatures(gradleLanguageSettings) as? Set ?: emptySet(), - getExperimentalAnnotationsInUse?.invoke(gradleLanguageSettings) as? Set ?: emptySet(), - getCompilerPluginArguments?.invoke(gradleLanguageSettings) as? List ?: emptyList(), - (getCompilerPluginClasspath?.invoke(gradleLanguageSettings) as? FileCollection)?.files ?: emptySet() - ) - } - - private fun buildDependencies( - dependencyHolder: Any, - dependencyResolver: DependencyResolver, - configurationNameAccessor: String, - scope: String, - project: Project - ): Collection { - val dependencyHolderClass = dependencyHolder.javaClass - val getConfigurationName = dependencyHolderClass.getMethodOrNull(configurationNameAccessor) ?: return emptyList() - val configurationName = getConfigurationName(dependencyHolder) as? String ?: return emptyList() - val configuration = project.configurations.findByName(configurationName) ?: return emptyList() - if (!configuration.isCanBeResolved) return emptyList() - - val dependencyAdjuster = DependencyAdjuster(configuration, scope, project) - - val resolvedDependencies = dependencyResolver - .resolveDependencies(configuration) - .apply { - forEach { (it as? AbstractExternalDependency)?.scope = scope } - } - .flatMap(dependencyAdjuster::adjustDependency) - val singleDependencyFiles = resolvedDependencies.mapNotNullTo(LinkedHashSet()) { - (it as? FileCollectionDependency)?.files?.singleOrNull() - } - // Workaround for duplicated dependencies specified as a file collection (KT-26675) - // Drop this code when the issue is fixed in the platform - return resolvedDependencies.filter { dependency -> - if (dependency !is FileCollectionDependency) return@filter true - val files = dependency.files - if (files.size <= 1) return@filter true - (files.any { it !in singleDependencyFiles }) - } - } - - private fun buildTargets( - sourceSetMap: Map, - dependencyResolver: DependencyResolver, - project: Project - ): Collection? { - return project.getTargets()?.mapNotNull { buildTarget(it, sourceSetMap, dependencyResolver, project) } - } - - private fun buildTarget( - gradleTarget: Named, - sourceSetMap: Map, - dependencyResolver: DependencyResolver, - project: Project - ): KotlinTarget? { - val targetClass = gradleTarget.javaClass - val getPlatformType = targetClass.getMethodOrNull("getPlatformType") ?: return null - val getCompilations = targetClass.getMethodOrNull("getCompilations") ?: return null - val getDisambiguationClassifier = targetClass.getMethodOrNull("getDisambiguationClassifier") ?: return null - val platformId = (getPlatformType.invoke(gradleTarget) as? Named)?.name ?: return null - val platform = KotlinPlatform.byId(platformId) ?: return null - val disambiguationClassifier = getDisambiguationClassifier(gradleTarget) as? String - @Suppress("UNCHECKED_CAST") - val gradleCompilations = - (getCompilations.invoke(gradleTarget) as? NamedDomainObjectContainer)?.asMap?.values ?: emptyList() - val compilations = gradleCompilations.mapNotNull { - buildCompilation(it, disambiguationClassifier, sourceSetMap, dependencyResolver, project) - } - val jar = buildTargetJar(gradleTarget, project) - val target = KotlinTargetImpl(gradleTarget.name, null, disambiguationClassifier, platform, compilations, jar) - compilations.forEach { it.target = target } - return target - } - - private fun buildTargetJar(gradleTarget: Named, project: Project): KotlinTargetJar? { - val targetClass = gradleTarget.javaClass - val getArtifactsTaskName = targetClass.getMethodOrNull("getArtifactsTaskName") ?: return null - val artifactsTaskName = getArtifactsTaskName(gradleTarget) as? String ?: return null - val jarTask = project.tasks.findByName(artifactsTaskName) ?: return null - val jarTaskClass = jarTask.javaClass - val getArchivePath = jarTaskClass.getMethodOrNull("getArchivePath") - val archiveFile = getArchivePath?.invoke(jarTask) as? File? - return KotlinTargetJarImpl(archiveFile) - } - - private fun buildCompilation( - gradleCompilation: Named, - classifier: String?, - sourceSetMap: Map, - dependencyResolver: DependencyResolver, - project: Project - ): KotlinCompilationImpl? { - val compilationClass = gradleCompilation.javaClass - val getKotlinSourceSets = compilationClass.getMethodOrNull("getKotlinSourceSets") ?: return null - @Suppress("UNCHECKED_CAST") - val kotlinGradleSourceSets = (getKotlinSourceSets(gradleCompilation) as? Collection) ?: return null - val kotlinSourceSets = kotlinGradleSourceSets.mapNotNull { sourceSetMap[it.name] } - val getCompileKotlinTaskName = compilationClass.getMethodOrNull("getCompileKotlinTaskName") ?: return null - @Suppress("UNCHECKED_CAST") - val compileKotlinTaskName = (getCompileKotlinTaskName(gradleCompilation) as? String) ?: return null - val compileKotlinTask = project.tasks.findByName(compileKotlinTaskName) ?: return null - val output = buildCompilationOutput(gradleCompilation, compileKotlinTask) ?: return null - val arguments = buildCompilationArguments(compileKotlinTask) ?: return null - val dependencyClasspath = buildDependencyClasspath(compileKotlinTask) - val dependencies = buildCompilationDependencies(gradleCompilation, classifier, sourceSetMap, dependencyResolver, project) - return KotlinCompilationImpl(gradleCompilation.name, kotlinSourceSets, dependencies, output, arguments, dependencyClasspath) - } - - private fun buildCompilationDependencies( - gradleCompilation: Named, - classifier: String?, - sourceSetMap: Map, - dependencyResolver: DependencyResolver, - project: Project - ): Set { - return LinkedHashSet().apply { - this += buildDependencies( - gradleCompilation, dependencyResolver, "getCompileDependencyConfigurationName", "COMPILE", project - ) - this += buildDependencies( - gradleCompilation, dependencyResolver, "getRuntimeDependencyConfigurationName", "RUNTIME", project - ) - this += sourceSetMap[compilationFullName(gradleCompilation.name, classifier)]?.dependencies ?: emptySet() - } - } - - private fun buildSourceSetDependencies( - gradleSourceSet: Named, - dependencyResolver: DependencyResolver, - project: Project - ): Set { - return LinkedHashSet().apply { - this += buildDependencies( - gradleSourceSet, dependencyResolver, "getApiMetadataConfigurationName", "COMPILE", project - ) - this += buildDependencies( - gradleSourceSet, dependencyResolver, "getImplementationMetadataConfigurationName", "COMPILE", project - ) - this += buildDependencies( - gradleSourceSet, dependencyResolver, "getCompileOnlyMetadataConfigurationName", "COMPILE", project - ) - this += buildDependencies( - gradleSourceSet, dependencyResolver, "getRuntimeOnlyMetadataConfigurationName", "RUNTIME", project - ) - } - } - - @Suppress("UNCHECKED_CAST") - private fun safelyGetArguments(compileKotlinTask: Task, accessor: Method?) = try { - accessor?.invoke(compileKotlinTask) as? List - } catch (e: Exception) { - logger.info(e.message, e) - null - } ?: emptyList() - - private fun buildCompilationArguments(compileKotlinTask: Task): KotlinCompilationArguments? { - val compileTaskClass = compileKotlinTask.javaClass - val getCurrentArguments = compileTaskClass.getMethodOrNull("getSerializedCompilerArguments") - val getDefaultArguments = compileTaskClass.getMethodOrNull("getDefaultSerializedCompilerArguments") - val currentArguments = safelyGetArguments(compileKotlinTask, getCurrentArguments) - val defaultArguments = safelyGetArguments(compileKotlinTask, getDefaultArguments) - return KotlinCompilationArgumentsImpl(defaultArguments, currentArguments) - } - - private fun buildDependencyClasspath(compileKotlinTask: Task): List { - val abstractKotlinCompileClass = - compileKotlinTask.javaClass.classLoader.loadClass(AbstractKotlinGradleModelBuilder.ABSTRACT_KOTLIN_COMPILE_CLASS) - val getCompileClasspath = - abstractKotlinCompileClass.getDeclaredMethodOrNull("getCompileClasspath") ?: return emptyList() - @Suppress("UNCHECKED_CAST") - return (getCompileClasspath(compileKotlinTask) as? Collection)?.map { it.path } ?: emptyList() - } - - private fun buildCompilationOutput( - gradleCompilation: Named, - compileKotlinTask: Task - ): KotlinCompilationOutput? { - val compilationClass = gradleCompilation.javaClass - val getOutput = compilationClass.getMethodOrNull("getOutput") ?: return null - val gradleOutput = getOutput(gradleCompilation) ?: return null - val gradleOutputClass = gradleOutput.javaClass - val getClassesDirs = gradleOutputClass.getMethodOrNull("getClassesDirs") ?: return null - val getResourcesDir = gradleOutputClass.getMethodOrNull("getResourcesDir") ?: return null - val compileKotlinTaskClass = compileKotlinTask.javaClass - val getDestinationDir = compileKotlinTaskClass.getMethodOrNull("getDestinationDir") ?: return null - val classesDirs = getClassesDirs(gradleOutput) as? FileCollection ?: return null - val resourcesDir = getResourcesDir(gradleOutput) as? File ?: return null - val destinationDir = getDestinationDir(compileKotlinTask) as? File - return KotlinCompilationOutputImpl(classesDirs.files, destinationDir, resourcesDir) - } - - private fun computeSourceSetsDeferredInfo( - sourceSets: Collection, - targets: Collection - ) { - val sourceSetToCompilations = LinkedHashMap>() - for (target in targets) { - for (compilation in target.compilations) { - for (sourceSet in compilation.sourceSets) { - sourceSetToCompilations.getOrPut(sourceSet) { LinkedHashSet() } += compilation - } - } - } - for (sourceSet in sourceSets) { - val name = sourceSet.name - if (name == KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME) { - sourceSet.platform = KotlinPlatform.COMMON - sourceSet.isTestModule = false - continue - } - if (name == KotlinSourceSet.COMMON_TEST_SOURCE_SET_NAME) { - sourceSet.platform = KotlinPlatform.COMMON - sourceSet.isTestModule = true - continue - } - - val compilations = sourceSetToCompilations[sourceSet] - if (compilations != null) { - sourceSet.platform = compilations.map { it.platform }.distinct().singleOrNull() ?: KotlinPlatform.COMMON - sourceSet.isTestModule = compilations.all { it.isTestModule } - } else { - // TODO: change me after design about it - sourceSet.isTestModule = "Test" in sourceSet.name - } - } - } - - private class DependencyAdjuster( - private val configuration: Configuration, - private val scope: String, - private val project: Project - ) { - private val adjustmentMap = HashMap>() - - val dependenciesByProjectPath by lazy { - configuration - .resolvedConfiguration - .lenientConfiguration - .allModuleDependencies - .mapNotNull { dependency -> - val artifact = dependency.moduleArtifacts.firstOrNull { - it.id.componentIdentifier is ProjectComponentIdentifier - } ?: return@mapNotNull null - dependency to artifact - } - .groupBy { (it.second.id.componentIdentifier as ProjectComponentIdentifier).projectPath } - } - - private fun wrapDependency(dependency: ExternalProjectDependency, newConfigurationName: String): ExternalProjectDependency { - return DefaultExternalProjectDependency(dependency).apply { - this.configurationName = newConfigurationName - - val nestedDependencies = this.dependencies.flatMap(::adjustDependency) - this.dependencies.clear() - this.dependencies.addAll(nestedDependencies) - } - } - - fun adjustDependency(dependency: ExternalDependency): List { - return adjustmentMap.getOrPut(dependency) { - if (dependency !is ExternalProjectDependency - || dependency.configurationName != Dependency.DEFAULT_CONFIGURATION - ) return@getOrPut listOf(dependency) - val artifacts = dependenciesByProjectPath[dependency.projectPath] ?: return@getOrPut listOf(dependency) - val artifactConfiguration = artifacts.mapTo(LinkedHashSet()) { - it.first.configuration - }.singleOrNull() ?: return@getOrPut listOf(dependency) - val taskGetterName = when (scope) { - "COMPILE" -> "getApiElementsConfigurationName" - "RUNTIME" -> "getRuntimeElementsConfigurationName" - else -> return@getOrPut listOf(dependency) - } - val dependencyProject = - if (project.rootProject.path == dependency.projectPath) - project.rootProject - else - project.rootProject.getChildProjectByPath(dependency.projectPath) - - val targets = dependencyProject?.getTargets() ?: return@getOrPut listOf(dependency) - val gradleTarget = targets.firstOrNull { - val getter = it.javaClass.getMethodOrNull(taskGetterName) ?: return@firstOrNull false - getter(it) == artifactConfiguration - } ?: return@getOrPut listOf(dependency) - val classifier = gradleTarget.javaClass.getMethodOrNull("getDisambiguationClassifier")?.invoke(gradleTarget) as? String - ?: return@getOrPut listOf(dependency) - val platformDependency = if (classifier != KotlinTarget.METADATA_TARGET_NAME) { - wrapDependency(dependency, compilationFullName(KotlinCompilation.MAIN_COMPILATION_NAME, classifier)) - } else null - val commonDependency = wrapDependency(dependency, KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME) - return if (platformDependency != null) listOf(platformDependency, commonDependency) else listOf(commonDependency) - } - } - } - - companion object { - private val logger = Logging.getLogger(KotlinMPPGradleModelBuilder::class.java) - - fun Project.getTargets(): Collection? { - val kotlinExt = project.extensions.findByName("kotlin") ?: return null - val getTargets = kotlinExt.javaClass.getMethodOrNull("getTargets") ?: return null - @Suppress("UNCHECKED_CAST") - return (getTargets.invoke(kotlinExt) as? NamedDomainObjectContainer)?.asMap?.values ?: emptyList() - } - } -} - -private fun Project.getChildProjectByPath(path: String): Project? { - var project = this - for (name in path.split(":").asSequence().drop(1)) { - project = project.childProjects[name] ?: return null - } - return project -} - -private fun Project.getTargets(): Collection? { - val kotlinExt = project.extensions.findByName("kotlin") ?: return null - val getTargets = kotlinExt.javaClass.getMethodOrNull("getTargets") ?: return null - @Suppress("UNCHECKED_CAST") - return (getTargets.invoke(kotlinExt) as? NamedDomainObjectContainer)?.asMap?.values ?: emptyList() -} \ No newline at end of file diff --git a/idea/resources/META-INF/android-lint.xml.173 b/idea/resources/META-INF/android-lint.xml.173 deleted file mode 100644 index dd099603e07..00000000000 --- a/idea/resources/META-INF/android-lint.xml.173 +++ /dev/null @@ -1,118 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/idea/resources/META-INF/android.xml.173 b/idea/resources/META-INF/android.xml.173 deleted file mode 100644 index 6eebd823d99..00000000000 --- a/idea/resources/META-INF/android.xml.173 +++ /dev/null @@ -1,108 +0,0 @@ - - - - - - - - - - - - - - - - - - - org.jetbrains.kotlin.android.intention.KotlinAndroidAddStringResource - Kotlin Android - - - - org.jetbrains.kotlin.android.intention.AddActivityToManifest - Kotlin Android - - - - org.jetbrains.kotlin.android.intention.AddServiceToManifest - Kotlin Android - - - - org.jetbrains.kotlin.android.intention.AddBroadcastReceiverToManifest - Kotlin Android - - - org.jetbrains.kotlin.android.intention.ImplementParcelableAction - Kotlin Android - - - - org.jetbrains.kotlin.android.intention.RemoveParcelableAction - Kotlin Android - - - - org.jetbrains.kotlin.android.intention.RedoParcelableAction - Kotlin Android - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/idea/resources/META-INF/gradle.xml.173 b/idea/resources/META-INF/gradle.xml.173 deleted file mode 100644 index eef578d0514..00000000000 --- a/idea/resources/META-INF/gradle.xml.173 +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/idea/resources/META-INF/plugin.xml.173 b/idea/resources/META-INF/plugin.xml.173 deleted file mode 100644 index 62452139416..00000000000 --- a/idea/resources/META-INF/plugin.xml.173 +++ /dev/null @@ -1,73 +0,0 @@ - - org.jetbrains.kotlin - - Kotlin - -Getting Started in IntelliJ IDEA
-Getting Started in Android Studio
-Public Slack
-Issue tracker
-]]>
- @snapshot@ - JetBrains - - - - com.intellij.modules.platform - com.intellij.modules.remoteServers - - - org.jetbrains.kotlin.native.platform.deps - - JUnit - org.jetbrains.plugins.gradle - org.jetbrains.idea.maven - TestNG-J - com.intellij.copyright - org.jetbrains.android - Coverage - com.intellij.java-i18n - org.intellij.intelliLang - org.jetbrains.java.decompiler - Git4Idea - - - - - com.intellij.modules.java - JavaScriptDebugger - - - - - - - - - - - - - - - - org.jetbrains.kotlin.idea.caches.ProjectRootModificationTrackerFixer - - - - - - - - - - - - - - -
diff --git a/idea/src/org/jetbrains/kotlin/idea/KotlinQuickDocumentationProvider.kt.173 b/idea/src/org/jetbrains/kotlin/idea/KotlinQuickDocumentationProvider.kt.173 deleted file mode 100644 index c9a38682eb4..00000000000 --- a/idea/src/org/jetbrains/kotlin/idea/KotlinQuickDocumentationProvider.kt.173 +++ /dev/null @@ -1,366 +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.kotlin.idea - -import com.google.common.html.HtmlEscapers -import com.intellij.codeInsight.documentation.DocumentationManagerUtil -import com.intellij.codeInsight.javadoc.JavaDocInfoGeneratorFactory -import com.intellij.lang.documentation.AbstractDocumentationProvider -import com.intellij.lang.java.JavaDocumentationProvider -import com.intellij.openapi.diagnostic.Logger -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiManager -import com.intellij.psi.PsiWhiteSpace -import org.jetbrains.kotlin.asJava.LightClassUtil -import org.jetbrains.kotlin.asJava.elements.KtLightDeclaration -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.idea.caches.resolve.analyze -import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade -import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny -import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde -import org.jetbrains.kotlin.idea.core.completion.DeclarationLookupObject -import org.jetbrains.kotlin.idea.decompiler.navigation.SourceNavigationHelper -import org.jetbrains.kotlin.idea.kdoc.KDocRenderer -import org.jetbrains.kotlin.idea.kdoc.findKDoc -import org.jetbrains.kotlin.idea.kdoc.isBoringBuiltinClass -import org.jetbrains.kotlin.idea.kdoc.resolveKDocLink -import org.jetbrains.kotlin.idea.references.mainReference -import org.jetbrains.kotlin.idea.resolve.frontendService -import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi -import org.jetbrains.kotlin.kdoc.psi.api.KDoc -import org.jetbrains.kotlin.kdoc.psi.impl.KDocSection -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.* -import org.jetbrains.kotlin.renderer.ClassifierNamePolicy -import org.jetbrains.kotlin.renderer.DescriptorRenderer -import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.DescriptorUtils -import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver -import org.jetbrains.kotlin.resolve.deprecation.deprecatedByAnnotationReplaceWithExpression -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe -import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny -import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode -import org.jetbrains.kotlin.utils.addToStdlib.constant - -class HtmlClassifierNamePolicy(val base: ClassifierNamePolicy) : ClassifierNamePolicy { - override fun renderClassifier(classifier: ClassifierDescriptor, renderer: DescriptorRenderer): String { - if (DescriptorUtils.isAnonymousObject(classifier)) { - - val supertypes = classifier.typeConstructor.supertypes - return buildString { - append("<anonymous object") - if (supertypes.isNotEmpty()) { - append(" : ") - supertypes.joinTo(this) { - val ref = it.constructor.declarationDescriptor - if (ref != null) - renderClassifier(ref, renderer) - else - "<ERROR CLASS>" - } - } - append(">") - } - } - - val name = base.renderClassifier(classifier, renderer) - if (classifier.isBoringBuiltinClass()) - return name - return buildString { - val ref = classifier.fqNameUnsafe.toString() - DocumentationManagerUtil.createHyperlink(this, ref, name, true) - } - } -} - -class KotlinQuickDocumentationProvider : AbstractDocumentationProvider() { - - override fun getQuickNavigateInfo(element: PsiElement?, originalElement: PsiElement?): String? { - return if (element == null) null else getText(element, originalElement, true) - } - - override fun generateDoc(element: PsiElement, originalElement: PsiElement?): String? { - return getText(element, originalElement, false) - } - - override fun getDocumentationElementForLink(psiManager: PsiManager, link: String, context: PsiElement?): PsiElement? { - val navElement = context?.navigationElement as? KtElement ?: return null - val bindingContext = navElement.analyze(BodyResolveMode.PARTIAL) - val contextDescriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, navElement] ?: return null - val descriptors = resolveKDocLink(bindingContext, navElement.getResolutionFacade(), - contextDescriptor, null, link.split('.')) - val target = descriptors.firstOrNull() ?: return null - return DescriptorToSourceUtilsIde.getAnyDeclaration(psiManager.project, target) - } - - override fun getDocumentationElementForLookupItem(psiManager: PsiManager, `object`: Any?, element: PsiElement?): PsiElement? { - if (`object` is DeclarationLookupObject) { - `object`.psiElement?.let { return it } - `object`.descriptor?.let { descriptor -> - return DescriptorToSourceUtilsIde.getAnyDeclaration(psiManager.project, descriptor) - } - } - return null - } - - companion object { - private val LOG = Logger.getInstance(KotlinQuickDocumentationProvider::class.java) - - private val DESCRIPTOR_RENDERER = DescriptorRenderer.HTML.withOptions { - classifierNamePolicy = HtmlClassifierNamePolicy(ClassifierNamePolicy.SHORT) - renderCompanionObjectName = true - } - - private fun renderEnumSpecialFunction(element: KtClass, functionDescriptor: FunctionDescriptor, quickNavigation: Boolean): String { - var renderedDecl = DESCRIPTOR_RENDERER.render(functionDescriptor) - - if (quickNavigation) return renderedDecl - - val declarationDescriptor = element.resolveToDescriptorIfAny() - val enumDescriptor = declarationDescriptor?.getSuperClassNotAny() ?: return renderedDecl - - val enumDeclaration = - DescriptorToSourceUtilsIde.getAnyDeclaration(element.project, enumDescriptor) as? KtDeclaration ?: return renderedDecl - - val enumSource = SourceNavigationHelper.getNavigationElement(enumDeclaration) - val functionName = functionDescriptor.fqNameSafe.shortName().asString() - val kdoc = enumSource.findDescendantOfType { - it.getChildrenOfType().any { it.findTagByName(functionName) != null } - } - - if (kdoc != null) { - val renderedComment = KDocRenderer.renderKDoc(kdoc.getDefaultSection()) - if (renderedComment.startsWith("

")) { - renderedDecl += renderedComment - } - else { - renderedDecl = "$renderedDecl
$renderedComment" - } - } - - return renderedDecl - } - - private fun renderEnum(element: KtClass, originalElement: PsiElement?, quickNavigation: Boolean): String? { - val referenceExpression = originalElement?.getNonStrictParentOfType() - if (referenceExpression != null) { - // When caret on special enum function (e.g SomeEnum.values()) - // element is not an KtReferenceExpression, but KtClass of enum - // so reference extracted from originalElement - val context = referenceExpression.analyze(BodyResolveMode.PARTIAL) - (context[BindingContext.REFERENCE_TARGET, referenceExpression] ?: - context[BindingContext.REFERENCE_TARGET, referenceExpression.getChildOfType()])?.let { - if (it is FunctionDescriptor) // To protect from SomeEnum.values() - return renderEnumSpecialFunction(element, it, quickNavigation) - } - } - return renderKotlinDeclaration(element, quickNavigation) - } - - private fun getText(element: PsiElement, originalElement: PsiElement?, quickNavigation: Boolean): String? { - if (element is PsiWhiteSpace) { - val itElement = findElementWithText(originalElement, "it") - val itReference = itElement?.getParentOfType(false) - if (itReference != null) { - return getText(itReference, originalElement, quickNavigation) - } - } - - if (element is KtTypeReference) { - val declaration = element.parent - if (declaration is KtCallableDeclaration && declaration.receiverTypeReference == element) { - val thisElement = findElementWithText(originalElement, "this") - if (thisElement != null) { - return getText(declaration, originalElement, quickNavigation) - } - } - } - - if (element is KtClass && element.isEnum()) { - // When caret on special enum function (e.g SomeEnum.values()) - // element is not an KtReferenceExpression, but KtClass of enum - return renderEnum(element, originalElement, quickNavigation) - } - else if (element is KtEnumEntry && !quickNavigation) { - val ordinal = element.containingClassOrObject?.getBody()?.run { getChildrenOfType().indexOf(element) } - - return buildString { - append(renderKotlinDeclaration(element, quickNavigation)) - ordinal?.let { - wrapTag("b") { - append("Enum constant ordinal: $ordinal") - } - } - } - } - else if (element is KtDeclaration) { - return renderKotlinDeclaration(element, quickNavigation) - } - else if (element is KtNameReferenceExpression && element.getReferencedName() == "it") { - return renderKotlinImplicitLambdaParameter(element, quickNavigation) - } - else if (element is KtLightDeclaration<*, *>) { - val origin = element.kotlinOrigin ?: return null - return renderKotlinDeclaration(origin, quickNavigation) - } - - if (quickNavigation) { - val referenceExpression = originalElement?.getNonStrictParentOfType() - if (referenceExpression != null) { - val context = referenceExpression.analyze(BodyResolveMode.PARTIAL) - val declarationDescriptor = context[BindingContext.REFERENCE_TARGET, referenceExpression] - if (declarationDescriptor != null) { - return mixKotlinToJava(declarationDescriptor, element, originalElement) - } - } - } - else { - // This element was resolved to non-kotlin element, it will be rendered with own provider - } - - return null - } - - private fun renderKotlinDeclaration(declaration: KtExpression, quickNavigation: Boolean): String { - val context = declaration.analyze(BodyResolveMode.PARTIAL) - val declarationDescriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, declaration] - - if (declarationDescriptor == null) { - LOG.info("Failed to find descriptor for declaration " + declaration.getElementTextWithContext()) - return "No documentation available" - } - - return renderKotlin(context, declarationDescriptor, quickNavigation, declaration) - } - - private fun renderKotlinImplicitLambdaParameter(element: KtReferenceExpression, quickNavigation: Boolean): String? { - val context = element.analyze(BodyResolveMode.PARTIAL) - val target = element.mainReference.resolveToDescriptors(context).singleOrNull() as? ValueParameterDescriptor? ?: return null - return renderKotlin(context, target, quickNavigation, element) - } - - private fun renderKotlin( - context: BindingContext, - declarationDescriptor: DeclarationDescriptor, - quickNavigation: Boolean, - ktElement: KtElement - ): String { - @Suppress("NAME_SHADOWING") - var declarationDescriptor = declarationDescriptor - if (declarationDescriptor is ValueParameterDescriptor) { - val property = context[BindingContext.VALUE_PARAMETER_AS_PROPERTY, declarationDescriptor] - if (property != null) { - declarationDescriptor = property - } - } - - var renderedDecl = DESCRIPTOR_RENDERER.withOptions { - withDefinedIn = !DescriptorUtils.isLocal(declarationDescriptor) - }.render(declarationDescriptor) - - if (!quickNavigation) { - renderedDecl = "

$renderedDecl
" - } - - val deprecationProvider = ktElement.getResolutionFacade().frontendService() - renderedDecl += renderDeprecationInfo(declarationDescriptor, deprecationProvider) - - if (!quickNavigation) { - val comment = declarationDescriptor.findKDoc { DescriptorToSourceUtilsIde.getAnyDeclaration(ktElement.project, it) } - if (comment != null) { - val renderedComment = KDocRenderer.renderKDoc(comment) - if (renderedComment.startsWith("

")) { - renderedDecl += renderedComment - } - else { - renderedDecl = "$renderedDecl
$renderedComment" - } - } - else { - if (declarationDescriptor is CallableDescriptor) { // If we couldn't find KDoc, try to find javadoc in one of super's - val psi = declarationDescriptor.findPsi() as? KtFunction - if (psi != null) { - val lightElement = LightClassUtil.getLightClassMethod(psi) // Light method for super's scan in javadoc info gen - val javaDocInfoGenerator = JavaDocInfoGeneratorFactory.create(psi.project, lightElement) - val builder = StringBuilder() - if (javaDocInfoGenerator.generateDocInfoCore(builder, false)) - renderedDecl += builder.toString().substringAfter("") // Cut off light method signature - } - } - } - } - - return renderedDecl - } - - private fun renderDeprecationInfo( - declarationDescriptor: DeclarationDescriptor, - deprecationResolver: DeprecationResolver - ): String { - val deprecation = deprecationResolver.getDeprecations(declarationDescriptor).firstOrNull() ?: return "" - - return buildString { - wrapTag("DL") { - deprecation.message?.let { message -> - wrapTag("DT") { wrapTag("b") { append("Deprecated:") } } - wrapTag("DD") { - append(message.htmlEscape()) - } - } - deprecation.deprecatedByAnnotationReplaceWithExpression()?.let { replaceWith -> - wrapTag("DT") { wrapTag("b") { append("Replace with:") } } - wrapTag("DD") { - wrapTag("code") { append(replaceWith.htmlEscape()) } - } - } - } - } - } - - private fun String.htmlEscape(): String = HtmlEscapers.htmlEscaper().escape(this) - - private inline fun StringBuilder.wrap(prefix: String, postfix: String, crossinline body: () -> Unit) { - this.append(prefix) - body() - this.append(postfix) - } - - private inline fun StringBuilder.wrapTag(tag: String, crossinline body: () -> Unit) { - wrap("<$tag>", "", body) - } - - private fun mixKotlinToJava(declarationDescriptor: DeclarationDescriptor, element: PsiElement, originalElement: PsiElement?): String? { - val originalInfo = JavaDocumentationProvider().getQuickNavigateInfo(element, originalElement) - if (originalInfo != null) { - val renderedDecl = constant { DESCRIPTOR_RENDERER.withOptions { withDefinedIn = false } }.render(declarationDescriptor) - return renderedDecl + "
Java declaration:
" + originalInfo - } - - return null - } - - private fun findElementWithText(element: PsiElement?, text: String): PsiElement? { - return when { - element == null -> null - element.text == text -> element - element.prevLeaf()?.text == text -> element.prevLeaf() - else -> null - } - } - } -} diff --git a/idea/src/org/jetbrains/kotlin/idea/editor/KotlinStringTemplateBackspaceHandler.kt.173 b/idea/src/org/jetbrains/kotlin/idea/editor/KotlinStringTemplateBackspaceHandler.kt.173 deleted file mode 100644 index 10fbd523476..00000000000 --- a/idea/src/org/jetbrains/kotlin/idea/editor/KotlinStringTemplateBackspaceHandler.kt.173 +++ /dev/null @@ -1,44 +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.kotlin.idea.editor - -import com.intellij.codeInsight.CodeInsightSettings -import com.intellij.codeInsight.editorActions.BackspaceHandlerDelegate -import com.intellij.openapi.editor.Editor -import com.intellij.openapi.editor.ex.EditorEx -import com.intellij.psi.PsiFile -import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.psi.KtFile - -class KotlinStringTemplateBackspaceHandler : BackspaceHandlerDelegate() { - override fun beforeCharDeleted(c: Char, file: PsiFile?, editor: Editor?) { - if (c != '{' || file !is KtFile || !CodeInsightSettings.getInstance().AUTOINSERT_PAIR_BRACKET) return - - val offset = editor?.caretModel?.offset ?: return - - val highlighter = (editor as EditorEx).highlighter - val iterator = highlighter.createIterator(offset) - if (iterator.tokenType != KtTokens.LONG_TEMPLATE_ENTRY_END) return - iterator.retreat() - if (iterator.tokenType != KtTokens.LONG_TEMPLATE_ENTRY_START) return - editor.document.deleteString(offset, offset + 1) - } - - override fun charDeleted(c: Char, file: PsiFile?, editor: Editor?): Boolean { - return false - } -} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/kdoc/KDocRenderer.kt.173 b/idea/src/org/jetbrains/kotlin/idea/kdoc/KDocRenderer.kt.173 deleted file mode 100644 index 8f91da47253..00000000000 --- a/idea/src/org/jetbrains/kotlin/idea/kdoc/KDocRenderer.kt.173 +++ /dev/null @@ -1,323 +0,0 @@ -/* - * Copyright 2010-2015 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.idea.kdoc - -import com.intellij.codeInsight.documentation.DocumentationManagerUtil -import com.intellij.psi.PsiElement -import org.intellij.markdown.IElementType -import org.intellij.markdown.MarkdownElementTypes -import org.intellij.markdown.MarkdownTokenTypes -import org.intellij.markdown.ast.ASTNode -import org.intellij.markdown.flavours.commonmark.CommonMarkFlavourDescriptor -import org.intellij.markdown.parser.MarkdownParser -import org.jetbrains.kotlin.idea.references.mainReference -import org.jetbrains.kotlin.idea.util.wrapTag -import org.jetbrains.kotlin.kdoc.psi.impl.KDocLink -import org.jetbrains.kotlin.kdoc.psi.impl.KDocName -import org.jetbrains.kotlin.kdoc.psi.impl.KDocSection -import org.jetbrains.kotlin.kdoc.psi.impl.KDocTag -import org.jetbrains.kotlin.psi.KtBlockExpression -import org.jetbrains.kotlin.psi.KtDeclarationWithBody -import org.jetbrains.kotlin.psi.psiUtil.getChildrenOfType - -object KDocRenderer { - fun renderKDoc(docComment: KDocTag): String { - val content = docComment.getContent() - val result = StringBuilder() - result.append(markdownToHtml(content, allowSingleParagraph = true)) - if (docComment is KDocSection) { - result.append("\n") - renderTag(docComment.findTagByName("receiver"), "Receiver", result) - val paramTags = docComment.findTagsByName("param").filter { it.getSubjectName() != null } - renderTagList(paramTags, "Parameters", result) - - renderTag(docComment.findTagByName("return"), "Returns", result) - - val throwsTags = (docComment.findTagsByName("exception").union(docComment.findTagsByName("throws"))) - .filter { it.getSubjectName() != null } - renderTagList(throwsTags, "Throws", result) - - renderTag(docComment.findTagByName("author"), "Author", result) - renderTag(docComment.findTagByName("since"), "Since", result) - - renderSeeAlso(docComment, result) - - val sampleTags = docComment.findTagsByName("sample").filter { it.getSubjectLink() != null } - renderSamplesList(sampleTags, result) - } - return result.toString() - } - - private fun KDocLink.createHyperlink(to: StringBuilder) { - DocumentationManagerUtil.createHyperlink(to, getLinkText(), getLinkText(), false) - } - - private fun KDocLink.getTargetElement(): PsiElement? { - return this.getChildrenOfType().last().mainReference.resolve() - } - - private fun PsiElement.extractExampleText() = when (this) { - is KtDeclarationWithBody -> { - val bodyExpression = bodyExpression - when (bodyExpression) { - is KtBlockExpression -> bodyExpression.text.removeSurrounding("{", "}") - else -> bodyExpression!!.text - } - } - else -> text - } - - private fun trimCommonIndent(text: String): String { - fun String.leadingIndent() = indexOfFirst { !it.isWhitespace() } - - val lines = text.split('\n') - val minIndent = lines.filter { it.trim().isNotEmpty() }.map(String::leadingIndent).min() ?: 0 - return lines.joinToString("\n") { it.drop(minIndent) } - } - - - private fun renderSamplesList(sampleTags: List, to: StringBuilder) { - if (sampleTags.isEmpty()) return - to.apply { - wrapTag("dl") { - append("

Samples:
") - sampleTags.forEach { - wrapTag("dd") { - it.getSubjectLink()?.let { subjectLink -> - subjectLink.createHyperlink(to) - val target = subjectLink.getTargetElement() - wrapTag("pre") { - wrapTag("code") { - if (target == null) - to.append("// Unresolved") - else { - to.append(trimCommonIndent(target.extractExampleText())) - } - } - } - } - } - } - } - } - } - - private fun renderSeeAlso(docComment: KDocSection, to: StringBuilder) { - val seeTags = docComment.findTagsByName("see") - if (seeTags.isEmpty()) return - to.append("
") - to.append("
").append("See Also:").append("") - to.append("
") - seeTags.forEachIndexed { index, tag -> - val subjectName = tag.getSubjectName() - if (subjectName != null) { - DocumentationManagerUtil.createHyperlink(to, subjectName, subjectName, false) - } - else { - to.append(tag.getContent()) - } - if (index < seeTags.size - 1) { - to.append(", ") - } - } - to.append("
") - } - - private fun renderTagList(tags: List, title: String, to: StringBuilder) { - if (tags.isEmpty()) { - return - } - to.append("
$title:
") - tags.forEach { - to.append("
${it.getSubjectName()} - ${markdownToHtml(it.getContent().trimStart())}
") - } - to.append("
\n") - } - - private fun renderTag(tag: KDocTag?, title: String, to: StringBuilder) { - if (tag != null) { - to.append("
$title:
") - to.append("
${markdownToHtml(tag.getContent())}
") - to.append("
\n") - } - } - - fun markdownToHtml(markdown: String, allowSingleParagraph: Boolean = false): String { - val markdownTree = MarkdownParser(CommonMarkFlavourDescriptor()).buildMarkdownTreeFromString(markdown) - val markdownNode = MarkdownNode(markdownTree, null, markdown) - - // Avoid wrapping the entire converted contents in a

tag if it's just a single paragraph - val maybeSingleParagraph = markdownNode.children.singleOrNull { it.type != MarkdownTokenTypes.EOL } - return if (maybeSingleParagraph != null && !allowSingleParagraph) { - maybeSingleParagraph.children.joinToString("") { - if (it.text == "\n") " " else it.toHtml() - } - } - else { - markdownNode.toHtml() - } - } - - class MarkdownNode(val node: ASTNode, val parent: MarkdownNode?, val markdown: String) { - val children: List = node.children.map { MarkdownNode(it, this, markdown) } - val endOffset: Int get() = node.endOffset - val startOffset: Int get() = node.startOffset - val type: IElementType get() = node.type - val text: String get() = markdown.substring(startOffset, endOffset) - fun child(type: IElementType): MarkdownNode? = children.firstOrNull { it.type == type } - } - - private fun MarkdownNode.visit(action: (MarkdownNode, () -> Unit) -> Unit) { - action(this) { - for (child in children) { - child.visit(action) - } - } - } - - private fun MarkdownNode.toHtml(): String { - if (node.type == MarkdownTokenTypes.WHITE_SPACE) { - return text // do not trim trailing whitespace - } - - val sb = StringBuilder() - visit { node, processChildren -> - fun wrapChildren(tag: String, newline: Boolean = false) { - sb.append("<$tag>") - processChildren() - sb.append("") - if (newline) sb.appendln() - } - - val nodeType = node.type - val nodeText = node.text - when (nodeType) { - MarkdownElementTypes.UNORDERED_LIST -> wrapChildren("ul", newline = true) - MarkdownElementTypes.ORDERED_LIST -> wrapChildren("ol", newline = true) - MarkdownElementTypes.LIST_ITEM -> wrapChildren("li") - MarkdownElementTypes.EMPH -> wrapChildren("em") - MarkdownElementTypes.STRONG -> wrapChildren("strong") - MarkdownElementTypes.ATX_1 -> wrapChildren("h1") - MarkdownElementTypes.ATX_2 -> wrapChildren("h2") - MarkdownElementTypes.ATX_3 -> wrapChildren("h3") - MarkdownElementTypes.ATX_4 -> wrapChildren("h4") - MarkdownElementTypes.ATX_5 -> wrapChildren("h5") - MarkdownElementTypes.ATX_6 -> wrapChildren("h6") - MarkdownElementTypes.BLOCK_QUOTE -> wrapChildren("blockquote") - MarkdownElementTypes.PARAGRAPH -> { - sb.trimEnd() - wrapChildren("p", newline = true) - } - MarkdownElementTypes.CODE_SPAN -> { - val startDelimiter = node.child(MarkdownTokenTypes.BACKTICK)?.text - if (startDelimiter != null) { - val text = node.text.substring(startDelimiter.length).removeSuffix(startDelimiter) - sb.append("").append(text.htmlEscape()).append("") - } - } - MarkdownElementTypes.CODE_BLOCK, - MarkdownElementTypes.CODE_FENCE -> { - sb.trimEnd() - sb.append("

")
-                    processChildren()
-                    sb.append("
") - } - MarkdownElementTypes.SHORT_REFERENCE_LINK, - MarkdownElementTypes.FULL_REFERENCE_LINK -> { - val linkLabelNode = node.child(MarkdownElementTypes.LINK_LABEL) - val linkLabelContent = linkLabelNode?.children - ?.dropWhile { it.type == MarkdownTokenTypes.LBRACKET } - ?.dropLastWhile { it.type == MarkdownTokenTypes.RBRACKET } - if (linkLabelContent != null) { - val label = linkLabelContent.joinToString(separator = "") { it.text } - val linkText = node.child(MarkdownElementTypes.LINK_TEXT)?.toHtml() ?: label - DocumentationManagerUtil.createHyperlink(sb, label, linkText, true) - } - else { - sb.append(node.text) - } - } - MarkdownElementTypes.INLINE_LINK -> { - val label = node.child(MarkdownElementTypes.LINK_TEXT)?.toHtml() - val destination = node.child(MarkdownElementTypes.LINK_DESTINATION)?.text - if (label != null && destination != null) { - sb.append("$label") - } - else { - sb.append(node.text) - } - } - MarkdownTokenTypes.TEXT, - MarkdownTokenTypes.WHITE_SPACE, - MarkdownTokenTypes.COLON, - MarkdownTokenTypes.SINGLE_QUOTE, - MarkdownTokenTypes.DOUBLE_QUOTE, - MarkdownTokenTypes.LPAREN, - MarkdownTokenTypes.RPAREN, - MarkdownTokenTypes.LBRACKET, - MarkdownTokenTypes.RBRACKET, - MarkdownTokenTypes.EXCLAMATION_MARK -> { - sb.append(nodeText) - } - MarkdownTokenTypes.CODE_LINE -> { - sb.append(nodeText.removePrefix(KDocTag.indentationWhiteSpaces).htmlEscape()) - } - MarkdownTokenTypes.CODE_FENCE_CONTENT -> { - sb.append(nodeText.htmlEscape()) - } - MarkdownTokenTypes.EOL -> { - val parentType = node.parent?.type - if (parentType == MarkdownElementTypes.CODE_BLOCK || parentType == MarkdownElementTypes.CODE_FENCE) { - sb.append("\n") - } - else { - sb.append(" ") - } - } - MarkdownTokenTypes.GT -> sb.append(">") - MarkdownTokenTypes.LT -> sb.append("<") - - MarkdownElementTypes.LINK_TEXT -> { - val childrenWithoutBrackets = node.children.drop(1).dropLast(1) - for (child in childrenWithoutBrackets) { - sb.append(child.toHtml()) - } - } - - MarkdownTokenTypes.EMPH -> { - val parentNodeType = node.parent?.type - if (parentNodeType != MarkdownElementTypes.EMPH && parentNodeType != MarkdownElementTypes.STRONG) { - sb.append(node.text) - } - } - - else -> { - processChildren() - } - } - } - return sb.toString().trimEnd() - } - - private fun StringBuilder.trimEnd() { - while (length > 0 && this[length - 1] == ' ') { - deleteCharAt(length - 1) - } - } - - private fun String.htmlEscape(): String = replace("&", "&").replace("<", "<").replace(">", ">") -} diff --git a/idea/src/org/jetbrains/kotlin/idea/kdoc/KDocTemplate.kt.173 b/idea/src/org/jetbrains/kotlin/idea/kdoc/KDocTemplate.kt.173 deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/crossLanguage/KotlinElementActionsFactory.kt.173 b/idea/src/org/jetbrains/kotlin/idea/quickfix/crossLanguage/KotlinElementActionsFactory.kt.173 deleted file mode 100644 index 45c29abf0f9..00000000000 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/crossLanguage/KotlinElementActionsFactory.kt.173 +++ /dev/null @@ -1,397 +0,0 @@ -/* - * 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.kotlin.idea.quickfix.crossLanguage - -import com.intellij.codeInsight.intention.IntentionAction -import com.intellij.codeInsight.intention.QuickFixFactory -import com.intellij.lang.jvm.* -import com.intellij.lang.jvm.actions.* -import com.intellij.openapi.project.Project -import com.intellij.psi.* -import com.intellij.psi.impl.source.tree.java.PsiReferenceExpressionImpl -import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade -import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration -import org.jetbrains.kotlin.asJava.toLightMethods -import org.jetbrains.kotlin.asJava.unwrapped -import org.jetbrains.kotlin.caches.resolve.KotlinCacheService -import org.jetbrains.kotlin.descriptors.ClassKind -import org.jetbrains.kotlin.descriptors.Modality -import org.jetbrains.kotlin.descriptors.SourceElement -import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor -import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl -import org.jetbrains.kotlin.descriptors.impl.MutablePackageFragmentDescriptor -import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade -import org.jetbrains.kotlin.idea.core.appendModifier -import org.jetbrains.kotlin.idea.quickfix.AddModifierFix -import org.jetbrains.kotlin.idea.quickfix.RemoveModifierFix -import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.* -import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createCallable.CreateCallableFromUsageFix -import org.jetbrains.kotlin.idea.resolve.ResolutionFacade -import org.jetbrains.kotlin.idea.util.approximateFlexibleTypes -import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.load.java.JvmAbi.JVM_FIELD_ANNOTATION_FQ_NAME -import org.jetbrains.kotlin.load.java.components.TypeUsage -import org.jetbrains.kotlin.load.java.lazy.JavaResolverComponents -import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext -import org.jetbrains.kotlin.load.java.lazy.TypeParameterResolver -import org.jetbrains.kotlin.load.java.lazy.child -import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaTypeParameterDescriptor -import org.jetbrains.kotlin.load.java.lazy.types.JavaTypeAttributes -import org.jetbrains.kotlin.load.java.lazy.types.JavaTypeResolver -import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter -import org.jetbrains.kotlin.load.java.structure.impl.JavaTypeImpl -import org.jetbrains.kotlin.load.java.structure.impl.JavaTypeParameterImpl -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.resolve.annotations.JVM_STATIC_ANNOTATION_FQ_NAME -import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform -import org.jetbrains.kotlin.storage.LockBasedStorageManager -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.Variance -import org.jetbrains.kotlin.types.typeUtil.supertypes - -class KotlinElementActionsFactory : JvmElementActionsFactory() { - companion object { - val javaPsiModifiersMapping = mapOf( - JvmModifier.PRIVATE to KtTokens.PRIVATE_KEYWORD, - JvmModifier.PUBLIC to KtTokens.PUBLIC_KEYWORD, - JvmModifier.PROTECTED to KtTokens.PUBLIC_KEYWORD, - JvmModifier.ABSTRACT to KtTokens.ABSTRACT_KEYWORD - ) - } - - private class FakeExpressionFromParameter(private val psiParam: PsiParameter) : PsiReferenceExpressionImpl() { - override fun getText(): String = psiParam.name!! - override fun getProject(): Project = psiParam.project - override fun getParent(): PsiElement = psiParam.parent - override fun getType(): PsiType? = psiParam.type - override fun isValid(): Boolean = true - override fun getContainingFile(): PsiFile = psiParam.containingFile - override fun getReferenceName(): String? = psiParam.name - override fun resolve(): PsiElement? = psiParam - } - - private class ModifierBuilder( - private val targetContainer: KtElement, - private val allowJvmStatic: Boolean = true - ) { - private val psiFactory = KtPsiFactory(targetContainer.project) - - val modifierList = psiFactory.createEmptyModifierList() - - private fun JvmModifier.transformAndAppend(): Boolean { - javaPsiModifiersMapping[this]?.let { - modifierList.appendModifier(it) - return true - } - - when (this) { - JvmModifier.STATIC -> { - if (allowJvmStatic && targetContainer is KtClassOrObject) { - addAnnotation(JVM_STATIC_ANNOTATION_FQ_NAME) - } - } - JvmModifier.ABSTRACT -> modifierList.appendModifier(KtTokens.ABSTRACT_KEYWORD) - JvmModifier.FINAL -> modifierList.appendModifier(KtTokens.FINAL_KEYWORD) - else -> return false - } - - return true - } - - var isValid = true - private set - - fun addJvmModifier(modifier: JvmModifier) { - isValid = isValid && modifier.transformAndAppend() - } - - fun addJvmModifiers(modifiers: Iterable) { - modifiers.forEach { addJvmModifier(it) } - } - - fun addAnnotation(fqName: FqName) { - if (!isValid) return - modifierList.add(psiFactory.createAnnotationEntry("@${fqName.asString()}")) - } - } - - class CreatePropertyFix( - private val targetClass: JvmClass, - contextElement: KtElement, - propertyInfo: PropertyInfo - ) : CreateCallableFromUsageFix(contextElement, listOf(propertyInfo)) { - override fun getFamilyName() = "Add property" - override fun getText(): String { - val info = callableInfos.first() as PropertyInfo - return buildString { - append("Add '") - if (info.isLateinitPreferred) { - append("lateinit ") - } - append(if (info.writable) "var" else "val") - append("' property '${info.name}' to '${targetClass.name}'") - } - } - } - - private fun JvmClass.toKtClassOrFile(): KtElement? { - val psi = sourceElement - return when (psi) { - is KtClassOrObject -> psi - is KtLightClassForSourceDeclaration -> psi.kotlinOrigin - is KtLightClassForFacade -> psi.files.firstOrNull() - else -> null - } - } - - private inline fun JvmElement.toKtElement() = sourceElement?.unwrapped as? T - - private fun fakeParametersExpressions(parameters: List, project: Project): Array? = - when { - parameters.isEmpty() -> emptyArray() - else -> JavaPsiFacade - .getElementFactory(project) - .createParameterList( - parameters.map { it.name }.toTypedArray(), - parameters.map { it.type as? PsiType ?: return null }.toTypedArray() - ) - .parameters - .map(::FakeExpressionFromParameter) - .toTypedArray() - } - - private fun PsiType.collectTypeParameters(): List { - val results = ArrayList() - accept( - object : PsiTypeVisitor() { - override fun visitArrayType(arrayType: PsiArrayType) { - arrayType.componentType.accept(this) - } - - override fun visitClassType(classType: PsiClassType) { - (classType.resolve() as? PsiTypeParameter)?.let { results += it } - classType.parameters.forEach { it.accept(this) } - } - - override fun visitWildcardType(wildcardType: PsiWildcardType) { - wildcardType.bound?.accept(this) - } - } - ) - return results - } - - private fun PsiType.resolveToKotlinType(resolutionFacade: ResolutionFacade): KotlinType? { - val typeParameters = collectTypeParameters() - val components = resolutionFacade.getFrontendService(JavaResolverComponents::class.java) - val rootContext = LazyJavaResolverContext(components, TypeParameterResolver.EMPTY) { null } - val dummyPackageDescriptor = MutablePackageFragmentDescriptor(resolutionFacade.moduleDescriptor, FqName("dummy")) - val dummyClassDescriptor = ClassDescriptorImpl( - dummyPackageDescriptor, - Name.identifier("Dummy"), - Modality.FINAL, - ClassKind.CLASS, - emptyList(), - SourceElement.NO_SOURCE, - false, - LockBasedStorageManager.NO_LOCKS - ) - val typeParameterResolver = object : TypeParameterResolver { - override fun resolveTypeParameter(javaTypeParameter: JavaTypeParameter): TypeParameterDescriptor? { - val psiTypeParameter = (javaTypeParameter as JavaTypeParameterImpl).psi - val index = typeParameters.indexOf(psiTypeParameter) - if (index < 0) return null - return LazyJavaTypeParameterDescriptor(rootContext.child(this), javaTypeParameter, index, dummyClassDescriptor) - } - } - val typeResolver = JavaTypeResolver(rootContext, typeParameterResolver) - val attributes = JavaTypeAttributes(TypeUsage.COMMON) - return typeResolver.transformJavaType(JavaTypeImpl.create(this), attributes).approximateFlexibleTypes(preferNotNull = true) - } - - private fun ExpectedTypes.toKotlinTypeInfo(resolutionFacade: ResolutionFacade): TypeInfo { - val candidateTypes = flatMapTo(LinkedHashSet()) { - val ktType = (it.theType as? PsiType)?.resolveToKotlinType(resolutionFacade) ?: return@flatMapTo emptyList() - when (it.theKind) { - ExpectedType.Kind.EXACT, ExpectedType.Kind.SUBTYPE -> listOf(ktType) - ExpectedType.Kind.SUPERTYPE -> listOf(ktType) + ktType.supertypes() - } - } - if (candidateTypes.isEmpty()) { - val nullableAnyType = resolutionFacade.moduleDescriptor.builtIns.nullableAnyType - return TypeInfo(nullableAnyType, Variance.INVARIANT) - } - return TypeInfo.ByExplicitCandidateTypes(candidateTypes.toList()) - } - - override fun createChangeModifierActions(target: JvmModifiersOwner, request: MemberRequest.Modifier): List { - val kModifierOwner = target.toKtElement() ?: return emptyList() - - val modifier = request.modifier - val shouldPresent = request.shouldPresent - val (kToken, shouldPresentMapped) = if (JvmModifier.FINAL == modifier) - KtTokens.OPEN_KEYWORD to !shouldPresent - else - javaPsiModifiersMapping[modifier] to shouldPresent - if (kToken == null) return emptyList() - - val action = if (shouldPresentMapped) - AddModifierFix.createIfApplicable(kModifierOwner, kToken) - else - RemoveModifierFix(kModifierOwner, kToken, false) - return listOfNotNull(action) - } - - override fun createAddConstructorActions(targetClass: JvmClass, request: MemberRequest.Constructor): List { - val targetKtClass = targetClass.toKtClassOrFile() as? KtClass ?: return emptyList() - - if (request.typeParameters.isNotEmpty()) return emptyList() - - val modifierBuilder = ModifierBuilder(targetKtClass).apply { addJvmModifiers(request.modifiers) } - if (!modifierBuilder.isValid) return emptyList() - - val resolutionFacade = targetKtClass.getResolutionFacade() - val nullableAnyType = resolutionFacade.moduleDescriptor.builtIns.nullableAnyType - val parameterInfos = request.parameters.mapIndexed { index, param -> - val ktType = (param.type as? PsiType)?.resolveToKotlinType(resolutionFacade) ?: nullableAnyType - val name = param.name ?: "arg${index + 1}" - ParameterInfo(TypeInfo(ktType, Variance.IN_VARIANCE), listOf(name)) - } - val needPrimary = !targetKtClass.hasExplicitPrimaryConstructor() - val constructorInfo = ConstructorInfo( - parameterInfos, - targetKtClass, - isPrimary = needPrimary, - modifierList = modifierBuilder.modifierList, - withBody = true - ) - val targetClassName = targetClass.name - val addConstructorAction = object : CreateCallableFromUsageFix(targetKtClass, listOf(constructorInfo)) { - override fun getFamilyName() = "Add method" - override fun getText() = "Add ${if (needPrimary) "primary" else "secondary"} constructor to '$targetClassName'" - } - - val changePrimaryConstructorAction = run { - val primaryConstructor = targetKtClass.primaryConstructor ?: return@run null - val lightMethod = primaryConstructor.toLightMethods().firstOrNull() ?: return@run null - val project = targetKtClass.project - val fakeParametersExpressions = fakeParametersExpressions(request.parameters, project) ?: return@run null - QuickFixFactory.getInstance() - .createChangeMethodSignatureFromUsageFix( - lightMethod, - fakeParametersExpressions, - PsiSubstitutor.EMPTY, - targetKtClass, - false, - 2 - ).takeIf { it.isAvailable(project, null, targetKtClass.containingFile) } - } - - return listOfNotNull(changePrimaryConstructorAction, addConstructorAction) - } - - override fun createAddPropertyActions(targetClass: JvmClass, request: MemberRequest.Property): List { - val targetContainer = targetClass.toKtClassOrFile() ?: return emptyList() - - val modifierBuilder = ModifierBuilder(targetContainer).apply { addJvmModifier(request.visibilityModifier) } - if (!modifierBuilder.isValid) return emptyList() - - val resolutionFacade = targetContainer.getResolutionFacade() - val nullableAnyType = resolutionFacade.moduleDescriptor.builtIns.nullableAnyType - val ktType = (request.propertyType as? PsiType)?.resolveToKotlinType(resolutionFacade) ?: nullableAnyType - val propertyInfo = PropertyInfo( - request.propertyName, - TypeInfo.Empty, - TypeInfo(ktType, Variance.INVARIANT), - request.setterRequired, - listOf(targetContainer), - modifierList = modifierBuilder.modifierList, - withInitializer = true - ) - val propertyInfos = if (request.setterRequired) { - listOf(propertyInfo, propertyInfo.copyProperty(isLateinitPreferred = true)) - } - else { - listOf(propertyInfo) - } - return propertyInfos.map { CreatePropertyFix(targetClass, targetContainer, it) } - } - - override fun createAddFieldActions(targetClass: JvmClass, request: CreateFieldRequest): List { - val targetContainer = targetClass.toKtClassOrFile() ?: return emptyList() - - val modifierBuilder = ModifierBuilder(targetContainer, allowJvmStatic = false).apply { - addJvmModifiers(request.modifiers) - addAnnotation(JVM_FIELD_ANNOTATION_FQ_NAME) - } - if (!modifierBuilder.isValid) return emptyList() - - val resolutionFacade = targetContainer.getResolutionFacade() - val typeInfo = request.fieldType.toKotlinTypeInfo(resolutionFacade) - val writable = JvmModifier.FINAL !in request.modifiers - val propertyInfo = PropertyInfo( - request.fieldName, - TypeInfo.Empty, - typeInfo, - writable, - listOf(targetContainer), - isForCompanion = JvmModifier.STATIC in request.modifiers, - modifierList = modifierBuilder.modifierList, - withInitializer = true - ) - val propertyInfos = if (writable) { - listOf(propertyInfo, propertyInfo.copyProperty(isLateinitPreferred = true)) - } - else { - listOf(propertyInfo) - } - return propertyInfos.map { CreatePropertyFix(targetClass, targetContainer, it) } - } - - override fun createAddMethodActions(targetClass: JvmClass, request: CreateMethodRequest): List { - val targetContainer = targetClass.toKtClassOrFile() ?: return emptyList() - - val modifierBuilder = ModifierBuilder(targetContainer).apply { addJvmModifiers(request.modifiers) } - if (!modifierBuilder.isValid) return emptyList() - - val resolutionFacade = KotlinCacheService.getInstance(targetContainer.project) - .getResolutionFacadeByFile(targetContainer.containingFile, JvmPlatform) ?: return emptyList() - val returnTypeInfo = request.returnType.toKotlinTypeInfo(resolutionFacade) - val parameterInfos = request.parameters.map { (suggestedNames, expectedTypes) -> - ParameterInfo(expectedTypes.toKotlinTypeInfo(resolutionFacade), suggestedNames.names.toList()) - } - val methodName = request.methodName - val functionInfo = FunctionInfo( - methodName, - TypeInfo.Empty, - returnTypeInfo, - listOf(targetContainer), - parameterInfos, - isForCompanion = JvmModifier.STATIC in request.modifiers, - modifierList = modifierBuilder.modifierList, - preferEmptyBody = true - ) - val targetClassName = targetClass.name - val action = object : CreateCallableFromUsageFix(targetContainer, listOf(functionInfo)) { - override fun getFamilyName() = "Add method" - override fun getText() = "Add method '$methodName' to '$targetClassName'" - } - return listOf(action) - } -} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/ui/KotlinCallerChooser.kt.173 b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/ui/KotlinCallerChooser.kt.173 deleted file mode 100644 index ec465aa70ae..00000000000 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/ui/KotlinCallerChooser.kt.173 +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2010-2015 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.idea.refactoring.changeSignature.ui - -import com.intellij.openapi.project.Project -import com.intellij.psi.PsiClassOwner -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiMethod -import com.intellij.psi.PsiReference -import com.intellij.psi.search.searches.MethodReferencesSearch -import com.intellij.psi.search.searches.ReferencesSearch -import com.intellij.refactoring.changeSignature.CallerChooserBase -import com.intellij.refactoring.changeSignature.MethodNodeBase -import com.intellij.ui.ColoredTreeCellRenderer -import com.intellij.ui.JBColor -import com.intellij.ui.SimpleTextAttributes -import com.intellij.ui.treeStructure.Tree -import com.intellij.util.Consumer -import com.intellij.util.ui.UIUtil -import org.jetbrains.kotlin.asJava.getRepresentativeLightMethod -import org.jetbrains.kotlin.asJava.namedUnwrappedElement -import org.jetbrains.kotlin.asJava.toLightMethods -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.idea.KotlinFileType -import org.jetbrains.kotlin.idea.caches.resolve.util.getJavaMethodDescriptor -import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor -import org.jetbrains.kotlin.idea.hierarchy.calls.CalleeReferenceProcessor -import org.jetbrains.kotlin.idea.hierarchy.calls.KotlinCallHierarchyNodeDescriptor -import org.jetbrains.kotlin.psi.KtClass -import org.jetbrains.kotlin.psi.KtFunction -import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext -import java.util.* - -class KotlinCallerChooser( - declaration: PsiElement, - project: Project, - title: String, - previousTree: Tree?, - callback: Consumer> -): CallerChooserBase(declaration, project, title, previousTree, "dummy." + KotlinFileType.EXTENSION, callback) { - override fun createTreeNode(method: PsiElement?, called: com.intellij.util.containers.HashSet, cancelCallback: Runnable): KotlinMethodNode { - return KotlinMethodNode(method, called, myProject, cancelCallback) - } - - override fun findDeepestSuperMethods(method: PsiElement) = - method.toLightMethods().singleOrNull()?.findDeepestSuperMethods() - - override fun getEmptyCallerText() = - "Caller text \nwith highlighted callee call would be shown here" - - override fun getEmptyCalleeText() = - "Callee text would be shown here" -} - -class KotlinMethodNode( - method: PsiElement?, - called: HashSet, - project: Project, - cancelCallback: Runnable -): MethodNodeBase(method?.namedUnwrappedElement ?: method, called, project, cancelCallback) { - override fun createNode(caller: PsiElement, called: HashSet) = - KotlinMethodNode(caller, called, myProject, myCancelCallback) - - override fun customizeRendererText(renderer: ColoredTreeCellRenderer) { - val descriptor = when (myMethod) { - is KtFunction -> myMethod.unsafeResolveToDescriptor() as FunctionDescriptor - is KtClass -> (myMethod.unsafeResolveToDescriptor() as ClassDescriptor).unsubstitutedPrimaryConstructor ?: return - is PsiMethod -> myMethod.getJavaMethodDescriptor() ?: return - else -> throw AssertionError("Invalid declaration: ${myMethod.getElementTextWithContext()}") - } - val containerName = generateSequence(descriptor) { it.containingDeclaration } - .firstOrNull { it is ClassDescriptor } - ?.name - - val renderedFunction = KotlinCallHierarchyNodeDescriptor.renderNamedFunction(descriptor) - val renderedFunctionWithContainer = - containerName?.let { - "${if (it.isSpecial) "[Anonymous]" else it.asString()}.$renderedFunction" - } ?: renderedFunction - - val attributes = if (isEnabled) - SimpleTextAttributes(SimpleTextAttributes.STYLE_PLAIN, UIUtil.getTreeForeground()) - else - SimpleTextAttributes.EXCLUDED_ATTRIBUTES - renderer.append(renderedFunctionWithContainer, attributes) - - val packageName = (myMethod.containingFile as? PsiClassOwner)?.packageName ?: "" - renderer.append(" ($packageName)", SimpleTextAttributes(SimpleTextAttributes.STYLE_ITALIC, JBColor.GRAY)) - } - - override fun computeCallers(): List { - if (myMethod == null) return emptyList() - - val callers = LinkedHashSet() - - val processor = object: CalleeReferenceProcessor(false) { - override fun onAccept(ref: PsiReference, element: PsiElement) { - if ((element is KtFunction || element is KtClass || element is PsiMethod) && element !in myCalled) { - callers.add(element) - } - } - } - val query = myMethod.getRepresentativeLightMethod()?.let { MethodReferencesSearch.search(it, it.useScope, true) } - ?: ReferencesSearch.search(myMethod, myMethod.useScope) - query.forEach { processor.process(it) } - return callers.toList() - } -} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/copy/CopyKotlinDeclarationDialog.kt.173 b/idea/src/org/jetbrains/kotlin/idea/refactoring/copy/CopyKotlinDeclarationDialog.kt.173 deleted file mode 100644 index 89ae37cbb27..00000000000 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/copy/CopyKotlinDeclarationDialog.kt.173 +++ /dev/null @@ -1,184 +0,0 @@ -/* - * 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.kotlin.idea.refactoring.copy - -import com.intellij.ide.util.DirectoryChooser -import com.intellij.openapi.project.Project -import com.intellij.openapi.roots.JavaProjectRootsUtil -import com.intellij.openapi.ui.DialogWrapper -import com.intellij.openapi.ui.Messages -import com.intellij.openapi.vfs.VirtualFile -import com.intellij.psi.PsiDirectory -import com.intellij.psi.PsiManager -import com.intellij.refactoring.HelpID -import com.intellij.refactoring.MoveDestination -import com.intellij.refactoring.PackageWrapper -import com.intellij.refactoring.RefactoringBundle -import com.intellij.refactoring.copy.CopyFilesOrDirectoriesDialog -import com.intellij.refactoring.ui.PackageNameReferenceEditorCombo -import com.intellij.ui.EditorTextField -import com.intellij.ui.RecentsManager -import com.intellij.ui.ReferenceEditorComboWithBrowseButton -import com.intellij.usageView.UsageViewUtil -import com.intellij.util.IncorrectOperationException -import com.intellij.util.ui.FormBuilder -import com.intellij.util.ui.UIUtil -import org.jetbrains.annotations.NonNls -import org.jetbrains.kotlin.idea.core.getPackage -import org.jetbrains.kotlin.idea.refactoring.Pass -import org.jetbrains.kotlin.idea.refactoring.hasIdentifiersOnly -import org.jetbrains.kotlin.idea.refactoring.ui.KotlinDestinationFolderComboBox -import org.jetbrains.kotlin.idea.util.sourceRoot -import org.jetbrains.kotlin.name.FqNameUnsafe -import org.jetbrains.kotlin.psi.KtNamedDeclaration -import java.awt.BorderLayout -import java.awt.Font -import javax.swing.JComponent -import javax.swing.JLabel -import javax.swing.JPanel - -// Based on com.intellij.refactoring.copy.CopyClassDialog -class CopyKotlinDeclarationDialog( - declaration: KtNamedDeclaration, - private val defaultTargetDirectory: PsiDirectory?, - private val project: Project -) : DialogWrapper(project, true) { - private val informationLabel = JLabel() - private val classNameField = EditorTextField("") - private val packageLabel = JLabel() - private lateinit var packageNameField: ReferenceEditorComboWithBrowseButton - private val openInEditorCheckBox = CopyFilesOrDirectoriesDialog.createOpenInEditorCB() - private val destinationComboBox = object : KotlinDestinationFolderComboBox() { - override fun getTargetPackage() = packageNameField.text.trim() - override fun reportBaseInTestSelectionInSource() = true - } - - private val originalFile = declaration.containingFile - - var targetDirectory: MoveDestination? = null - private set - - val targetSourceRoot: VirtualFile? - get() = ((destinationComboBox.comboBox.selectedItem as? DirectoryChooser.ItemWrapper)?.directory ?: originalFile).sourceRoot - - init { - informationLabel.text = RefactoringBundle.message("copy.class.copy.0.1", UsageViewUtil.getType(declaration), UsageViewUtil.getLongName(declaration)) - informationLabel.font = informationLabel.font.deriveFont(Font.BOLD) - - init() - - destinationComboBox.setData( - project, - defaultTargetDirectory, - Pass { setErrorText(it, destinationComboBox) }, - packageNameField.childComponent - ) - classNameField.text = UsageViewUtil.getShortName(declaration) - classNameField.selectAll() - } - - override fun getPreferredFocusedComponent() = classNameField - - override fun createCenterPanel() = JPanel(BorderLayout()) - - override fun createNorthPanel(): JComponent? { - val qualifiedName = qualifiedName - packageNameField = PackageNameReferenceEditorCombo(qualifiedName, project, RECENTS_KEY, RefactoringBundle.message("choose.destination.package")) - packageNameField.setTextFieldPreferredWidth(Math.max(qualifiedName.length + 5, 40)) - packageLabel.text = RefactoringBundle.message("destination.package") - packageLabel.labelFor = packageNameField - - val label = JLabel(RefactoringBundle.message("target.destination.folder")) - val isMultipleSourceRoots = JavaProjectRootsUtil.getSuitableDestinationSourceRoots(project).size > 1 - destinationComboBox.isVisible = isMultipleSourceRoots - label.isVisible = isMultipleSourceRoots - label.labelFor = destinationComboBox - - val panel = JPanel(BorderLayout()) - panel.add(openInEditorCheckBox, BorderLayout.EAST) - return FormBuilder.createFormBuilder() - .addComponent(informationLabel) - .addLabeledComponent(RefactoringBundle.message("copy.files.new.name.label"), classNameField, UIUtil.LARGE_VGAP) - .addLabeledComponent(packageLabel, packageNameField) - .addLabeledComponent(label, destinationComboBox) - .addComponent(panel) - .panel - } - - private val qualifiedName: String - get() = defaultTargetDirectory?.getPackage()?.qualifiedName ?: "" - - val newName: String? - get() = classNameField.text - - val openInEditor: Boolean - get() = openInEditorCheckBox.isSelected - - private fun checkForErrors(): String? { - val packageName = packageNameField.text - val newName = newName - - val manager = PsiManager.getInstance(project) - - if (packageName.isNotEmpty() && !FqNameUnsafe(packageName).hasIdentifiersOnly()) { - return RefactoringBundle.message("invalid.target.package.name.specified") - } - - if (newName.isNullOrEmpty()) { - return RefactoringBundle.message("no.class.name.specified") - } - - try { - targetDirectory = destinationComboBox.selectDirectory(PackageWrapper(manager, packageName), false) - } - catch (e: IncorrectOperationException) { - return e.message - } - - targetDirectory?.getTargetIfExists(defaultTargetDirectory)?.let { - val targetFileName = newName + "." + originalFile.virtualFile.extension - if (it.findFile(targetFileName) == originalFile) { - return "Can't copy class to the containing file" - } - } - - return null - } - - override fun doOKAction() { - val packageName = packageNameField.text - - val errorString = checkForErrors() - if (errorString != null) { - if (errorString.isNotEmpty()) { - Messages.showMessageDialog(project, errorString, RefactoringBundle.message("error.title"), Messages.getErrorIcon()) - } - classNameField.requestFocusInWindow() - return - } - - RecentsManager.getInstance(project).registerRecentEntry(RECENTS_KEY, packageName) - CopyFilesOrDirectoriesDialog.saveOpenInEditorState(openInEditorCheckBox.isSelected) - - super.doOKAction() - } - - override fun getHelpId() = HelpID.COPY_CLASS - - companion object { - @NonNls private val RECENTS_KEY = "CopyKotlinDeclarationDialog.RECENTS_KEY" - } -} diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveClassesOrPackages/KotlinAwareMoveClassesOrPackagesToNewDirectoryDialog.kt.173 b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveClassesOrPackages/KotlinAwareMoveClassesOrPackagesToNewDirectoryDialog.kt.173 deleted file mode 100644 index 4a822f93164..00000000000 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveClassesOrPackages/KotlinAwareMoveClassesOrPackagesToNewDirectoryDialog.kt.173 +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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.kotlin.idea.refactoring.move.moveClassesOrPackages - -import com.intellij.psi.PsiDirectory -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiPackage -import com.intellij.refactoring.MoveDestination -import com.intellij.refactoring.move.MoveCallback -import com.intellij.refactoring.move.moveClassesOrPackages.MoveClassesOrPackagesToNewDirectoryDialog - -class KotlinAwareMoveClassesOrPackagesToNewDirectoryDialog( - directory: PsiDirectory, - elementsToMove: Array, - moveCallback: MoveCallback? -) : MoveClassesOrPackagesToNewDirectoryDialog(directory, elementsToMove, moveCallback) { - override fun createDestination(aPackage: PsiPackage, directory: PsiDirectory): MoveDestination { - val delegate = super.createDestination(aPackage, directory) - return KotlinAwareDelegatingMoveDestination(delegate, aPackage, directory) - } -} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveDeclarationsDelegate.kt.173 b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveDeclarationsDelegate.kt.173 deleted file mode 100644 index a00f51ac7ff..00000000000 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveDeclarationsDelegate.kt.173 +++ /dev/null @@ -1,182 +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.kotlin.idea.refactoring.move.moveDeclarations - -import com.intellij.psi.PsiElement -import com.intellij.refactoring.move.moveInner.MoveInnerClassUsagesHandler -import com.intellij.refactoring.util.MoveRenameUsageInfo -import com.intellij.usageView.UsageInfo -import com.intellij.util.containers.MultiMap -import org.jetbrains.kotlin.asJava.toLightClass -import org.jetbrains.kotlin.asJava.unwrapped -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor -import org.jetbrains.kotlin.idea.codeInsight.shorten.isToBeShortened -import org.jetbrains.kotlin.idea.refactoring.move.* -import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers -import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject -import org.jetbrains.kotlin.resolve.descriptorUtil.isSubclassOf - -sealed class MoveDeclarationsDelegate { - abstract fun getContainerChangeInfo(originalDeclaration: KtNamedDeclaration, moveTarget: KotlinMoveTarget): ContainerChangeInfo - - open fun findInternalUsages(descriptor: MoveDeclarationsDescriptor): List = emptyList() - - open fun collectConflicts( - descriptor: MoveDeclarationsDescriptor, - internalUsages: MutableSet, - conflicts: MultiMap - ) { - - } - - open fun preprocessDeclaration(descriptor: MoveDeclarationsDescriptor, originalDeclaration: KtNamedDeclaration) { - - } - - open fun preprocessUsages(descriptor: MoveDeclarationsDescriptor, usages: List) { - - } - - object TopLevel : MoveDeclarationsDelegate() { - override fun getContainerChangeInfo(originalDeclaration: KtNamedDeclaration, moveTarget: KotlinMoveTarget): ContainerChangeInfo { - val sourcePackage = ContainerInfo.Package(originalDeclaration.containingKtFile.packageFqName) - val targetPackage = moveTarget.targetContainerFqName?.let { ContainerInfo.Package(it) } ?: ContainerInfo.UnknownPackage - return ContainerChangeInfo(sourcePackage, targetPackage) - } - } - - class NestedClass( - val newClassName: String? = null, - val outerInstanceParameterName: String? = null - ) : MoveDeclarationsDelegate() { - override fun getContainerChangeInfo(originalDeclaration: KtNamedDeclaration, moveTarget: KotlinMoveTarget): ContainerChangeInfo { - val originalInfo = ContainerInfo.Class(originalDeclaration.containingClassOrObject!!.fqName!!) - val movingToClass = (moveTarget as? KotlinMoveTargetForExistingElement)?.targetElement is KtClassOrObject - val targetContainerFqName = moveTarget.targetContainerFqName - val newInfo = when { - targetContainerFqName == null -> ContainerInfo.UnknownPackage - movingToClass -> ContainerInfo.Class(targetContainerFqName) - else -> ContainerInfo.Package(targetContainerFqName) - } - return ContainerChangeInfo(originalInfo, newInfo) - } - - override fun findInternalUsages(descriptor: MoveDeclarationsDescriptor): List { - val classToMove = descriptor.moveSource.elementsToMove.singleOrNull() as? KtClass ?: return emptyList() - return collectOuterInstanceReferences(classToMove) - } - - private fun isValidTargetForImplicitCompanionAsDispatchReceiver( - moveDescriptor: MoveDeclarationsDescriptor, - companionDescriptor: ClassDescriptor - ): Boolean { - val moveTarget = moveDescriptor.moveTarget - return when (moveTarget) { - is KotlinMoveTargetForCompanion -> true - is KotlinMoveTargetForExistingElement -> { - val targetClass = moveTarget.targetElement as? KtClassOrObject ?: return false - val targetClassDescriptor = targetClass.unsafeResolveToDescriptor() as ClassDescriptor - val companionClassDescriptor = companionDescriptor.containingDeclaration as? ClassDescriptor ?: return false - targetClassDescriptor.isSubclassOf(companionClassDescriptor) - } - else -> false - } - } - - override fun collectConflicts( - descriptor: MoveDeclarationsDescriptor, - internalUsages: MutableSet, - conflicts: MultiMap - ) { - val usageIterator = internalUsages.iterator() - while (usageIterator.hasNext()) { - val usage = usageIterator.next() - val element = usage.element ?: continue - - val isConflict = when (usage) { - is ImplicitCompanionAsDispatchReceiverUsageInfo -> { - if (!isValidTargetForImplicitCompanionAsDispatchReceiver(descriptor, usage.companionDescriptor)) { - conflicts.putValue(element, "Implicit companion object will be inaccessible: ${element.text}") - } - true - } - - is OuterInstanceReferenceUsageInfo -> usage.reportConflictIfAny(conflicts) - - else -> false - } - if (isConflict) { - usageIterator.remove() - } - } - } - - override fun preprocessDeclaration(descriptor: MoveDeclarationsDescriptor, originalDeclaration: KtNamedDeclaration) { - with(originalDeclaration) { - newClassName?.let { setName(it) } - - if (this is KtClass) { - if ((descriptor.moveTarget as? KotlinMoveTargetForExistingElement)?.targetElement !is KtClassOrObject) { - if (hasModifier(KtTokens.INNER_KEYWORD)) removeModifier(KtTokens.INNER_KEYWORD) - if (hasModifier(KtTokens.PROTECTED_KEYWORD)) removeModifier(KtTokens.PROTECTED_KEYWORD) - } - - if (outerInstanceParameterName != null) { - val type = (containingClassOrObject!!.unsafeResolveToDescriptor() as ClassDescriptor).defaultType - val parameter = KtPsiFactory(project) - .createParameter("private val $outerInstanceParameterName: ${IdeDescriptorRenderers.SOURCE_CODE.renderType(type)}") - createPrimaryConstructorParameterListIfAbsent().addParameter(parameter).isToBeShortened = true - } - } - } - } - - override fun preprocessUsages(descriptor: MoveDeclarationsDescriptor, usages: List) { - if (outerInstanceParameterName == null) return - val psiFactory = KtPsiFactory(descriptor.project) - val newOuterInstanceRef = psiFactory.createExpression(outerInstanceParameterName) - val classToMove = descriptor.moveSource.elementsToMove.singleOrNull() as? KtClass - - for (usage in usages) { - if (usage is MoveRenameUsageInfo) { - val referencedNestedClass = usage.referencedElement?.unwrapped as? KtClassOrObject - if (referencedNestedClass == classToMove) { - val outerClass = referencedNestedClass?.containingClassOrObject - val lightOuterClass = outerClass?.toLightClass() - if (lightOuterClass != null) { - MoveInnerClassUsagesHandler.EP_NAME - .forLanguage(usage.element!!.language) - ?.correctInnerClassUsage(usage, lightOuterClass) - } - } - } - - when (usage) { - is OuterInstanceReferenceUsageInfo.ExplicitThis -> { - usage.expression?.replace(newOuterInstanceRef) - } - is OuterInstanceReferenceUsageInfo.ImplicitReceiver -> { - usage.callElement?.let { it.replace(psiFactory.createExpressionByPattern("$0.$1", outerInstanceParameterName, it)) } - } - } - } - } - } -} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveFilesOrDirectories/KotlinMoveDirectoryWithClassesHelper.kt.173 b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveFilesOrDirectories/KotlinMoveDirectoryWithClassesHelper.kt.173 deleted file mode 100644 index de3600c69ae..00000000000 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveFilesOrDirectories/KotlinMoveDirectoryWithClassesHelper.kt.173 +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright 2010-2015 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.idea.refactoring.move.moveFilesOrDirectories - -import com.intellij.openapi.project.Project -import com.intellij.psi.PsiDirectory -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiFile -import com.intellij.refactoring.listeners.RefactoringElementListener -import com.intellij.refactoring.move.moveClassesOrPackages.MoveDirectoryWithClassesHelper -import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesUtil -import com.intellij.usageView.UsageInfo -import com.intellij.util.Function -import com.intellij.util.containers.MultiMap -import org.jetbrains.kotlin.idea.core.getPackage -import org.jetbrains.kotlin.idea.core.quoteIfNeeded -import org.jetbrains.kotlin.idea.refactoring.invokeOnceOnCommandFinish -import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.KotlinDirectoryMoveTarget -import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.MoveKotlinDeclarationsProcessor -import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.analyzeConflictsInFile -import org.jetbrains.kotlin.idea.runSynchronouslyWithProgress -import org.jetbrains.kotlin.idea.util.application.runReadAction -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.psi.KtFile -import java.util.* - -class KotlinMoveDirectoryWithClassesHelper : MoveDirectoryWithClassesHelper() { - private data class FileUsagesWrapper( - val psiFile: KtFile, - val usages: List, - val moveDeclarationsProcessor: MoveKotlinDeclarationsProcessor? - ) : UsageInfo(psiFile) - - private class MoveContext( - val newParent: PsiDirectory, - val moveDeclarationsProcessor: MoveKotlinDeclarationsProcessor? - ) - - private val fileHandler = MoveKotlinFileHandler() - - private var fileToMoveContext: MutableMap? = null - - private fun getOrCreateMoveContextMap(): MutableMap { - return fileToMoveContext ?: HashMap().apply { - fileToMoveContext = this - invokeOnceOnCommandFinish { fileToMoveContext = null } - } - } - - override fun findUsages( - filesToMove: MutableCollection, - directoriesToMove: Array, - result: MutableCollection, - searchInComments: Boolean, - searchInNonJavaFiles: Boolean, - project: Project) { - filesToMove - .filterIsInstance() - .mapTo(result) { FileUsagesWrapper(it, fileHandler.findUsages(it, null, false), null) } - } - - override fun preprocessUsages( - project: Project, - files: MutableSet, - infos: Array, - directory: PsiDirectory?, - conflicts: MultiMap - ) { - val psiPackage = directory?.getPackage() ?: return - val moveTarget = KotlinDirectoryMoveTarget(FqName(psiPackage.qualifiedName), directory) - for ((index, usageInfo) in infos.withIndex()) { - if (usageInfo !is FileUsagesWrapper) continue - - project.runSynchronouslyWithProgress("Analyzing conflicts in ${usageInfo.psiFile.name}", false) { - runReadAction { - analyzeConflictsInFile(usageInfo.psiFile, usageInfo.usages, moveTarget, files, conflicts) { - infos[index] = usageInfo.copy(usages = it) - } - } - } - } - } - - override fun beforeMove(psiFile: PsiFile) { - - } - - // Actual move logic is implemented in postProcessUsages since usages are not available here - override fun move( - file: PsiFile, - moveDestination: PsiDirectory, - oldToNewElementsMapping: MutableMap, - movedFiles: MutableList, - listener: RefactoringElementListener? - ): Boolean { - if (file !is KtFile) return false - - val moveDeclarationsProcessor = fileHandler.initMoveProcessor(file, moveDestination, false) - val moveContextMap = getOrCreateMoveContextMap() - moveContextMap[file] = MoveContext(moveDestination, moveDeclarationsProcessor) - if (moveDeclarationsProcessor != null) { - moveDestination.getPackage()?.let { newPackage -> - file.packageDirective?.fqName = FqName(newPackage.qualifiedName).quoteIfNeeded() - } - } - return true - } - - override fun afterMove(newElement: PsiElement) { - - } - - override fun postProcessUsages(usages: Array, newDirMapper: Function) { - val fileToMoveContext = fileToMoveContext ?: return - try { - val usagesToProcess = ArrayList() - usages - .filterIsInstance() - .forEach body@ { - val file = it.psiFile - val moveContext = fileToMoveContext[file] ?: return@body - - MoveFilesOrDirectoriesUtil.doMoveFile(file, moveContext.newParent) - - val moveDeclarationsProcessor = moveContext.moveDeclarationsProcessor ?: return@body - val movedFile = moveContext.newParent.findFile(file.name) ?: return@body - - usagesToProcess += FileUsagesWrapper(movedFile as KtFile, it.usages, moveDeclarationsProcessor) - } - usagesToProcess.forEach { fileHandler.retargetUsages(it.usages, it.moveDeclarationsProcessor!!) } - } - finally { - this.fileToMoveContext = null - } - } -} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinClassifierProcessor.kt.173 b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinClassifierProcessor.kt.173 deleted file mode 100644 index df27f800aa8..00000000000 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinClassifierProcessor.kt.173 +++ /dev/null @@ -1,144 +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.kotlin.idea.refactoring.rename - -import com.intellij.openapi.editor.Editor -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiReference -import com.intellij.refactoring.JavaRefactoringSettings -import com.intellij.refactoring.listeners.RefactoringElementListener -import com.intellij.refactoring.rename.RenamePsiElementProcessor -import com.intellij.usageView.UsageInfo -import org.jetbrains.kotlin.asJava.classes.KtLightClass -import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade -import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration -import org.jetbrains.kotlin.asJava.namedUnwrappedElement -import org.jetbrains.kotlin.descriptors.ClassifierDescriptor -import org.jetbrains.kotlin.idea.caches.resolve.analyze -import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor -import org.jetbrains.kotlin.idea.refactoring.withExpectedActuals -import org.jetbrains.kotlin.idea.references.KtSimpleNameReference -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode -import org.jetbrains.kotlin.utils.SmartList -import java.util.* - -class RenameKotlinClassifierProcessor : RenameKotlinPsiProcessor() { - override fun canProcessElement(element: PsiElement): Boolean { - return element is KtClassOrObject || element is KtLightClass || element is KtConstructor<*> || element is KtTypeAlias - } - - override fun isToSearchInComments(psiElement: PsiElement) = JavaRefactoringSettings.getInstance().RENAME_SEARCH_IN_COMMENTS_FOR_CLASS - - override fun setToSearchInComments(element: PsiElement, enabled: Boolean) { - JavaRefactoringSettings.getInstance().RENAME_SEARCH_IN_COMMENTS_FOR_CLASS = enabled - } - - override fun isToSearchForTextOccurrences(element: PsiElement) = JavaRefactoringSettings.getInstance().RENAME_SEARCH_FOR_TEXT_FOR_CLASS - - override fun setToSearchForTextOccurrences(element: PsiElement, enabled: Boolean) { - JavaRefactoringSettings.getInstance().RENAME_SEARCH_FOR_TEXT_FOR_CLASS = enabled - } - - override fun substituteElementToRename(element: PsiElement, editor: Editor?) = getClassOrObject(element) - - override fun prepareRenaming(element: PsiElement, newName: String, allRenames: MutableMap) { - super.prepareRenaming(element, newName, allRenames) - - val classOrObject = getClassOrObject(element) as? KtClassOrObject ?: return - - classOrObject.withExpectedActuals().forEach { - val file = it.containingKtFile - val virtualFile = file.virtualFile - if (virtualFile != null) { - val nameWithoutExtensions = virtualFile.nameWithoutExtension - if (nameWithoutExtensions == it.name) { - val newFileName = newName + "." + virtualFile.extension - allRenames.put(file, newFileName) - RenamePsiElementProcessor.forElement(file).prepareRenaming(file, newFileName, allRenames) - } - } - } - } - - override fun findReferences(element: PsiElement): Collection { - if (element is KtObjectDeclaration && element.isCompanion()) { - return super.findReferences(element).filter { !it.isCompanionObjectClassReference() } - } - return super.findReferences(element) - } - - private fun PsiReference.isCompanionObjectClassReference(): Boolean { - if (this !is KtSimpleNameReference) { - return false - } - val bindingContext = element.analyze(BodyResolveMode.PARTIAL) - return bindingContext[BindingContext.SHORT_REFERENCE_TO_COMPANION_OBJECT, element] != null - } - - override fun findCollisions( - element: PsiElement, - newName: String?, - allRenames: MutableMap, - result: MutableList - ) { - if (newName == null) return - val declaration = element.namedUnwrappedElement as? KtNamedDeclaration ?: return - val descriptor = declaration.unsafeResolveToDescriptor() as ClassifierDescriptor - - val collisions = SmartList() - checkRedeclarations(descriptor, newName, collisions) - checkOriginalUsagesRetargeting(declaration, newName, result, collisions) - checkNewNameUsagesRetargeting(declaration, newName, collisions) - result += collisions - } - - private fun getClassOrObject(element: PsiElement?): PsiElement? = when (element) { - is KtLightClass -> - when (element) { - is KtLightClassForSourceDeclaration -> element.kotlinOrigin - is KtLightClassForFacade -> element - else -> throw AssertionError("Should not be suggested to rename element of type " + element::class.java + " " + element) - } - - is KtConstructor<*> -> - element.getContainingClassOrObject() - - is KtClassOrObject, is KtTypeAlias -> element - - else -> null - } - - override fun renameElement(element: PsiElement, newName: String?, usages: Array, listener: RefactoringElementListener?) { - val simpleUsages = ArrayList(usages.size) - val ambiguousImportUsages = com.intellij.util.SmartList() - for (usage in usages) { - if (usage.isAmbiguousImportUsage()) { - ambiguousImportUsages += usage - } - else { - simpleUsages += usage - } - } - element.ambiguousImportUsages = ambiguousImportUsages - - super.renameElement(element, newName, simpleUsages.toTypedArray(), listener) - - usages.forEach { (it as? KtResolvableCollisionUsageInfo)?.apply() } - } -} diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinFileProcessor.kt.173 b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinFileProcessor.kt.173 deleted file mode 100644 index 4f7246abf72..00000000000 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinFileProcessor.kt.173 +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2010-2015 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.idea.refactoring.rename - -import com.intellij.openapi.fileTypes.FileTypeManager -import com.intellij.openapi.module.ModuleUtilCore -import com.intellij.psi.JavaPsiFacade -import com.intellij.psi.PsiReference -import com.intellij.psi.PsiElement -import com.intellij.psi.search.GlobalSearchScope -import com.intellij.psi.search.SearchScope -import com.intellij.refactoring.rename.RenamePsiFileProcessor -import org.jetbrains.kotlin.asJava.classes.KtLightClass -import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil -import org.jetbrains.kotlin.idea.KotlinFileType -import org.jetbrains.kotlin.idea.util.ProjectRootsUtil -import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils -import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.statistics.KotlinIdeRefactoringTrigger -import org.jetbrains.kotlin.statistics.KotlinStatisticsTrigger - -class RenameKotlinFileProcessor : RenamePsiFileProcessor() { - class FileRenamingPsiClassWrapper( - private val psiClass: KtLightClass, - private val file: KtFile - ) : KtLightClass by psiClass { - override fun isValid() = file.isValid - } - - override fun canProcessElement(element: PsiElement) = - element is KtFile && ProjectRootsUtil.isInProjectSource(element, includeScriptsOutsideSourceRoots = true) - - override fun prepareRenaming(element: PsiElement?, - newName: String, - allRenames: MutableMap, - scope: SearchScope) { - val jetFile = element as? KtFile ?: return - if (FileTypeManager.getInstance().getFileTypeByFileName(newName) != KotlinFileType.INSTANCE) { - return - } - - val module = ModuleUtilCore.findModuleForPsiElement(element) ?: return - - val fileInfo = JvmFileClassUtil.getFileClassInfoNoResolve(jetFile) - if (!fileInfo.withJvmName) { - val facadeFqName = fileInfo.facadeClassFqName - val project = jetFile.project - val facadeClass = JavaPsiFacade.getInstance(project) - .findClass(facadeFqName.asString(), GlobalSearchScope.moduleScope(module)) as? KtLightClass - if (facadeClass != null) { - allRenames[FileRenamingPsiClassWrapper(facadeClass, jetFile)] = PackagePartClassUtils.getFilePartShortName(newName) - } - } - } - override fun findReferences(element: PsiElement): MutableCollection { - return super.findReferences(element).also { - KotlinStatisticsTrigger.trigger(KotlinIdeRefactoringTrigger::class.java, this::class.java.name) - } - } - - override fun findReferences(element: PsiElement, searchInCommentsAndStrings: Boolean): MutableCollection { - return super.findReferences(element, searchInCommentsAndStrings).also { - KotlinStatisticsTrigger.trigger(KotlinIdeRefactoringTrigger::class.java, this::class.java.name) - } - } -} diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinFunctionProcessor.kt.173 b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinFunctionProcessor.kt.173 deleted file mode 100644 index d86e522d867..00000000000 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinFunctionProcessor.kt.173 +++ /dev/null @@ -1,248 +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.kotlin.idea.refactoring.rename - -import com.intellij.openapi.editor.Editor -import com.intellij.openapi.project.Project -import com.intellij.openapi.util.Pass -import com.intellij.psi.* -import com.intellij.psi.search.SearchScope -import com.intellij.refactoring.JavaRefactoringSettings -import com.intellij.refactoring.listeners.RefactoringElementListener -import com.intellij.refactoring.rename.RenameDialog -import com.intellij.refactoring.rename.RenameJavaMethodProcessor -import com.intellij.refactoring.rename.RenameProcessor -import com.intellij.refactoring.rename.RenameUtil -import com.intellij.refactoring.util.RefactoringUtil -import com.intellij.usageView.UsageInfo -import com.intellij.util.SmartList -import org.jetbrains.kotlin.asJava.LightClassUtil -import org.jetbrains.kotlin.asJava.elements.KtLightElement -import org.jetbrains.kotlin.asJava.elements.KtLightMethod -import org.jetbrains.kotlin.asJava.namedUnwrappedElement -import org.jetbrains.kotlin.asJava.unwrapped -import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor -import org.jetbrains.kotlin.idea.refactoring.Pass -import org.jetbrains.kotlin.idea.refactoring.checkSuperMethods -import org.jetbrains.kotlin.idea.refactoring.checkSuperMethodsWithPopup -import org.jetbrains.kotlin.idea.refactoring.dropOverrideKeywordIfNecessary -import org.jetbrains.kotlin.idea.references.KtReference -import org.jetbrains.kotlin.idea.search.declarationsSearch.findDeepestSuperMethodsKotlinAware -import org.jetbrains.kotlin.idea.search.declarationsSearch.findDeepestSuperMethodsNoWrapping -import org.jetbrains.kotlin.idea.search.declarationsSearch.forEachOverridingMethod -import org.jetbrains.kotlin.idea.util.application.runReadAction -import org.jetbrains.kotlin.idea.util.liftToExpected -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.resolve.DescriptorUtils -import java.lang.IllegalStateException -import java.util.* - -class RenameKotlinFunctionProcessor : RenameKotlinPsiProcessor() { - private val javaMethodProcessorInstance = RenameJavaMethodProcessor() - - override fun canProcessElement(element: PsiElement): Boolean { - return element is KtNamedFunction || (element is KtLightMethod && element.kotlinOrigin is KtNamedFunction) || element is FunctionWithSupersWrapper - } - - override fun isToSearchInComments(psiElement: PsiElement) = JavaRefactoringSettings.getInstance().RENAME_SEARCH_IN_COMMENTS_FOR_METHOD - - override fun setToSearchInComments(element: PsiElement, enabled: Boolean) { - JavaRefactoringSettings.getInstance().RENAME_SEARCH_IN_COMMENTS_FOR_METHOD = enabled - } - - override fun isToSearchForTextOccurrences(element: PsiElement) = JavaRefactoringSettings.getInstance().RENAME_SEARCH_FOR_TEXT_FOR_METHOD - - override fun setToSearchForTextOccurrences(element: PsiElement, enabled: Boolean) { - JavaRefactoringSettings.getInstance().RENAME_SEARCH_FOR_TEXT_FOR_METHOD = enabled - } - - private fun getJvmName(element: PsiElement): String? { - val descriptor = (element.unwrapped as? KtFunction)?.unsafeResolveToDescriptor() as? FunctionDescriptor ?: return null - return DescriptorUtils.getJvmName(descriptor) - } - - override fun findReferences(element: PsiElement): Collection { - val allReferences = super.findReferences(element) - return when { - getJvmName(element) == null -> allReferences - element is KtElement -> allReferences.filter { it is KtReference } - element is KtLightElement<*, *> -> allReferences.filterNot { it is KtReference } - else -> emptyList() - } - } - - override fun findCollisions( - element: PsiElement, - newName: String?, - allRenames: Map, - result: MutableList - ) { - if (newName == null) return - val declaration = element.unwrapped as? KtNamedFunction ?: return - val descriptor = declaration.unsafeResolveToDescriptor() - checkConflictsAndReplaceUsageInfos(element, allRenames, result) - result += SmartList().also { collisions -> - checkRedeclarations(descriptor, newName, collisions) - checkOriginalUsagesRetargeting(declaration, newName, result, collisions) - checkNewNameUsagesRetargeting(declaration, newName, collisions) - } - } - - class FunctionWithSupersWrapper( - val originalDeclaration: KtNamedFunction, - val supers: List - ) : KtLightElement, PsiNamedElement by originalDeclaration { - override val kotlinOrigin: KtNamedFunction? - get() = originalDeclaration - override val clsDelegate: KtNamedFunction - get() = originalDeclaration - } - - private fun substituteForExpectOrActual(element: PsiElement?) = (element?.namedUnwrappedElement as? KtNamedDeclaration)?.liftToExpected() - - override fun substituteElementToRename(element: PsiElement?, editor: Editor?): PsiElement? { - substituteForExpectOrActual(element)?.let { return it } - - val wrappedMethod = wrapPsiMethod(element) ?: return element - - val deepestSuperMethods = findDeepestSuperMethodsKotlinAware(wrappedMethod) - val substitutedJavaElement = when { - deepestSuperMethods.isEmpty() -> return element - wrappedMethod.isConstructor || deepestSuperMethods.size == 1 || element !is KtNamedFunction -> { - javaMethodProcessorInstance.substituteElementToRename(wrappedMethod, editor) - } - else -> { - val chosenElements = checkSuperMethods(element, null, "rename") - if (chosenElements.size > 1) FunctionWithSupersWrapper(element, chosenElements) else wrappedMethod - } - } - - if (substitutedJavaElement is KtLightMethod && element is KtDeclaration) { - return substitutedJavaElement.kotlinOrigin as? KtNamedFunction - } - - return substitutedJavaElement - } - - override fun substituteElementToRename(element: PsiElement, editor: Editor, renameCallback: Pass) { - fun preprocessAndPass(substitutedJavaElement: PsiElement) { - val elementToProcess = if (substitutedJavaElement is KtLightMethod && element is KtDeclaration) { - substitutedJavaElement.kotlinOrigin as? KtNamedFunction - } - else { - substitutedJavaElement - } - renameCallback.pass(elementToProcess) - } - - substituteForExpectOrActual(element)?.let { return preprocessAndPass(it) } - - val wrappedMethod = wrapPsiMethod(element) - val deepestSuperMethods = if (wrappedMethod != null) { - findDeepestSuperMethodsKotlinAware(wrappedMethod) - } else { - findDeepestSuperMethodsNoWrapping(element) - } - when { - deepestSuperMethods.isEmpty() -> preprocessAndPass(element) - wrappedMethod != null && (wrappedMethod.isConstructor || element !is KtNamedFunction) -> { - javaMethodProcessorInstance.substituteElementToRename(wrappedMethod, editor, Pass(::preprocessAndPass)) - } - else -> { - val declaration = element.unwrapped as? KtNamedFunction ?: return - checkSuperMethodsWithPopup(declaration, deepestSuperMethods.toList(), "Rename", editor) { - preprocessAndPass(if (it.size > 1) FunctionWithSupersWrapper(declaration, it) else wrappedMethod ?: element) - } - } - } - } - - override fun createRenameDialog(project: Project, element: PsiElement, nameSuggestionContext: PsiElement?, editor: Editor?): RenameDialog { - val elementForDialog = (element as? FunctionWithSupersWrapper)?.originalDeclaration ?: element - return object : RenameDialog(project, elementForDialog, nameSuggestionContext, editor) { - override fun createRenameProcessor(newName: String) = RenameProcessor(getProject(), element, newName, isSearchInComments, isSearchInNonJavaFiles) - } - } - - override fun prepareRenaming(element: PsiElement, newName: String?, allRenames: MutableMap, scope: SearchScope) { - super.prepareRenaming(element, newName, allRenames, scope) - - if (newName == null) return - - if (element is KtLightMethod && getJvmName(element) == null) { - (element.kotlinOrigin as? KtNamedFunction)?.let { allRenames[it] = newName } - } - if (element is FunctionWithSupersWrapper) { - allRenames.remove(element) - } - for (declaration in ((element as? FunctionWithSupersWrapper)?.supers ?: listOf(element))) { - val psiMethod = wrapPsiMethod(declaration) ?: continue - allRenames[declaration] = newName - if (psiMethod.containingClass != null) { - psiMethod.forEachOverridingMethod { it -> - val overrider = (it as? PsiMirrorElement)?.prototype as? PsiMethod ?: it - - if (overrider is SyntheticElement) return@forEachOverridingMethod true - - val overriderName = overrider.name - val baseName = psiMethod.name - val newOverriderName = RefactoringUtil.suggestNewOverriderName(overriderName, baseName, newName) - if (newOverriderName != null) { - RenameProcessor.assertNonCompileElement(overrider) - allRenames.put(overrider, newOverriderName) - } - return@forEachOverridingMethod true - } - javaMethodProcessorInstance.prepareRenaming(psiMethod, newName, allRenames, scope) - } - } - } - - override fun renameElement(element: PsiElement, newName: String?, usages: Array, listener: RefactoringElementListener?) { - val simpleUsages = ArrayList(usages.size) - val ambiguousImportUsages = SmartList() - for (usage in usages) { - if (usage is LostDefaultValuesInOverridingFunctionUsageInfo) { - usage.apply() - continue - } - - if (usage.isAmbiguousImportUsage()) { - ambiguousImportUsages += usage - } - else { - simpleUsages += usage - } - } - element.ambiguousImportUsages = ambiguousImportUsages - - RenameUtil.doRenameGenericNamedElement(element, newName, simpleUsages.toTypedArray(), listener) - - usages.forEach { (it as? KtResolvableCollisionUsageInfo)?.apply() } - - (element.unwrapped as? KtNamedDeclaration)?.let(::dropOverrideKeywordIfNecessary) - } - - private fun wrapPsiMethod(element: PsiElement?): PsiMethod? = when (element) { - is PsiMethod -> element - is KtNamedFunction, is KtSecondaryConstructor -> runReadAction { - LightClassUtil.getLightClassMethod(element as KtFunction) - } - else -> throw IllegalStateException("Can't be for element $element there because of canProcessElement()") - } -} diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinParameterProcessor.kt.173 b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinParameterProcessor.kt.173 deleted file mode 100644 index 377548707bd..00000000000 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinParameterProcessor.kt.173 +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2010-2015 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.idea.refactoring.rename - -import com.intellij.psi.PsiElement -import com.intellij.refactoring.JavaRefactoringSettings -import com.intellij.refactoring.listeners.RefactoringElementListener -import com.intellij.usageView.UsageInfo -import org.jetbrains.kotlin.asJava.namedUnwrappedElement -import org.jetbrains.kotlin.descriptors.VariableDescriptor -import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor -import org.jetbrains.kotlin.psi.KtFunction -import org.jetbrains.kotlin.psi.KtNamedDeclaration -import org.jetbrains.kotlin.psi.KtParameter -import org.jetbrains.kotlin.utils.SmartList - -class RenameKotlinParameterProcessor : RenameKotlinPsiProcessor() { - override fun canProcessElement(element: PsiElement) = element is KtParameter && element.ownerFunction is KtFunction - - override fun isToSearchInComments(psiElement: PsiElement) = JavaRefactoringSettings.getInstance().RENAME_SEARCH_IN_COMMENTS_FOR_VARIABLE - - override fun setToSearchInComments(element: PsiElement, enabled: Boolean) { - JavaRefactoringSettings.getInstance().RENAME_SEARCH_IN_COMMENTS_FOR_VARIABLE = enabled - } - - override fun findCollisions( - element: PsiElement, - newName: String?, - allRenames: MutableMap, - result: MutableList - ) { - if (newName == null) return - val declaration = element.namedUnwrappedElement as? KtNamedDeclaration ?: return - val descriptor = declaration.unsafeResolveToDescriptor() as VariableDescriptor - - val collisions = SmartList() - checkRedeclarations(descriptor, newName, collisions) - checkOriginalUsagesRetargeting(declaration, newName, result, collisions) - checkNewNameUsagesRetargeting(declaration, newName, collisions) - result += collisions - } - - override fun renameElement(element: PsiElement, newName: String?, usages: Array, listener: RefactoringElementListener?) { - super.renameElement(element, newName, usages, listener) - - usages.forEach { (it as? KtResolvableCollisionUsageInfo)?.apply() } - } -} diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinPropertyProcessor.kt.173 b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinPropertyProcessor.kt.173 deleted file mode 100644 index 6e1bc177eac..00000000000 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinPropertyProcessor.kt.173 +++ /dev/null @@ -1,479 +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.kotlin.idea.refactoring.rename - -import com.intellij.navigation.NavigationItem -import com.intellij.openapi.application.ApplicationManager -import com.intellij.openapi.editor.Editor -import com.intellij.openapi.ui.Messages -import com.intellij.openapi.util.Pass -import com.intellij.psi.* -import com.intellij.psi.search.SearchScope -import com.intellij.psi.search.searches.DirectClassInheritorsSearch -import com.intellij.psi.search.searches.OverridingMethodsSearch -import com.intellij.refactoring.JavaRefactoringSettings -import com.intellij.refactoring.listeners.RefactoringElementListener -import com.intellij.refactoring.rename.RenameProcessor -import com.intellij.refactoring.util.MoveRenameUsageInfo -import com.intellij.refactoring.util.RefactoringUtil -import com.intellij.usageView.UsageInfo -import com.intellij.usageView.UsageViewUtil -import org.jetbrains.kotlin.asJava.* -import org.jetbrains.kotlin.asJava.classes.KtLightClass -import org.jetbrains.kotlin.asJava.elements.KtLightDeclaration -import org.jetbrains.kotlin.asJava.elements.KtLightMethod -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.PropertyDescriptor -import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor -import org.jetbrains.kotlin.descriptors.VariableDescriptor -import org.jetbrains.kotlin.idea.caches.resolve.analyze -import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor -import org.jetbrains.kotlin.idea.core.getDeepestSuperDeclarations -import org.jetbrains.kotlin.idea.core.isEnumCompanionPropertyWithEntryConflict -import org.jetbrains.kotlin.idea.core.unquote -import org.jetbrains.kotlin.idea.refactoring.checkSuperMethodsWithPopup -import org.jetbrains.kotlin.idea.refactoring.dropOverrideKeywordIfNecessary -import org.jetbrains.kotlin.idea.references.KtDestructuringDeclarationReference -import org.jetbrains.kotlin.idea.references.KtReference -import org.jetbrains.kotlin.idea.references.KtSimpleNameReference -import org.jetbrains.kotlin.idea.references.mainReference -import org.jetbrains.kotlin.idea.util.application.runReadAction -import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.load.java.JvmAbi -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject -import org.jetbrains.kotlin.psi.psiUtil.findPropertyByName -import org.jetbrains.kotlin.psi.psiUtil.quoteIfNeeded -import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.DataClassDescriptorResolver -import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils -import org.jetbrains.kotlin.resolve.DescriptorUtils -import org.jetbrains.kotlin.resolve.source.getPsi -import org.jetbrains.kotlin.util.findCallableMemberBySignature -import org.jetbrains.kotlin.utils.DFS -import org.jetbrains.kotlin.utils.SmartList - -class RenameKotlinPropertyProcessor : RenameKotlinPsiProcessor() { - override fun canProcessElement(element: PsiElement): Boolean { - val namedUnwrappedElement = element.namedUnwrappedElement - return namedUnwrappedElement is KtProperty || (namedUnwrappedElement is KtParameter && namedUnwrappedElement.hasValOrVar()) - } - - override fun isToSearchInComments(psiElement: PsiElement) = JavaRefactoringSettings.getInstance().RENAME_SEARCH_IN_COMMENTS_FOR_FIELD - - override fun setToSearchInComments(element: PsiElement, enabled: Boolean) { - JavaRefactoringSettings.getInstance().RENAME_SEARCH_IN_COMMENTS_FOR_FIELD = enabled - } - - override fun isToSearchForTextOccurrences(element: PsiElement) = JavaRefactoringSettings.getInstance().RENAME_SEARCH_FOR_TEXT_FOR_FIELD - - override fun setToSearchForTextOccurrences(element: PsiElement, enabled: Boolean) { - JavaRefactoringSettings.getInstance().RENAME_SEARCH_FOR_TEXT_FOR_FIELD = enabled - } - - private fun getJvmNames(element: PsiElement): Pair { - val descriptor = (element.unwrapped as? KtDeclaration)?.unsafeResolveToDescriptor() as? PropertyDescriptor ?: return null to null - val getterName = descriptor.getter?.let { DescriptorUtils.getJvmName(it) } - val setterName = descriptor.setter?.let { DescriptorUtils.getJvmName(it) } - return getterName to setterName - } - - override fun findReferences(element: PsiElement): Collection { - val allReferences = super.findReferences(element).filterNot { it is KtDestructuringDeclarationReference } - val (getterJvmName, setterJvmName) = getJvmNames(element) - return when { - getterJvmName == null && setterJvmName == null -> allReferences - element is KtElement -> allReferences.filter { - it is KtReference - || (getterJvmName == null && (it.resolve() as? PsiNamedElement)?.name != setterJvmName) - || (setterJvmName == null && (it.resolve() as? PsiNamedElement)?.name != getterJvmName) - } - element is KtLightDeclaration<*, *> -> { - val name = element.name - if (name == getterJvmName || name == setterJvmName) allReferences.filterNot { it is KtReference } else allReferences - } - else -> emptyList() - } - } - - private fun checkAccidentalOverrides( - declaration: KtNamedDeclaration, - newName: String, - descriptor: VariableDescriptor, - result: MutableList - ) { - fun reportAccidentalOverride(candidate: PsiNamedElement) { - val what = UsageViewUtil.getType(declaration).capitalize() - val withWhat = candidate.renderDescription() - val where = candidate.representativeContainer()?.renderDescription() ?: return - val message = "$what after rename will clash with existing $withWhat in $where" - result += BasicUnresolvableCollisionUsageInfo(candidate, candidate, message) - } - - if (descriptor !is PropertyDescriptor) return - val initialClass = declaration.containingClassOrObject ?: return - val initialClassDescriptor = descriptor.containingDeclaration as? ClassDescriptor ?: return - - val prototype = object : PropertyDescriptor by descriptor { - override fun getName() = Name.guessByFirstCharacter(newName) - } - - DFS.dfs( - listOf(initialClassDescriptor), - DFS.Neighbors { DescriptorUtils.getSuperclassDescriptors(it) }, - object : DFS.AbstractNodeHandler() { - override fun beforeChildren(current: ClassDescriptor): Boolean { - if (current == initialClassDescriptor) return true - (current.findCallableMemberBySignature(prototype))?.let { candidateDescriptor -> - val candidate = candidateDescriptor.source.getPsi() as? PsiNamedElement ?: return false - reportAccidentalOverride(candidate) - return false - } - return true - } - - override fun result() { - - } - } - ) - - if (!declaration.hasModifier(KtTokens.PRIVATE_KEYWORD)) { - val initialPsiClass = initialClass.toLightClass() ?: return - val prototypes = declaration.toLightMethods().mapNotNull { - it as KtLightMethod - val methodName = accessorNameByPropertyName(newName, it) ?: return@mapNotNull null - object : KtLightMethod by it { - override fun getName() = methodName - } - } - DFS.dfs( - listOf(initialPsiClass), - DFS.Neighbors { DirectClassInheritorsSearch.search(it) }, - object : DFS.AbstractNodeHandler() { - override fun beforeChildren(current: PsiClass): Boolean { - if (current == initialPsiClass) return true - - if (current is KtLightClass) { - val property = current.kotlinOrigin?.findPropertyByName(newName) ?: return true - reportAccidentalOverride(property) - return false - } - - for (psiMethod in prototypes) { - current.findMethodBySignature(psiMethod, false)?.let { - val candidate = it.unwrapped as? PsiNamedElement ?: return true - reportAccidentalOverride(candidate) - return false - } - } - - return true - } - - override fun result() { - - } - } - ) - } - } - - override fun findCollisions( - element: PsiElement, - newName: String?, - allRenames: MutableMap, - result: MutableList - ) { - if (newName == null) return - val declaration = element.namedUnwrappedElement as? KtNamedDeclaration ?: return - val descriptor = declaration.unsafeResolveToDescriptor() as VariableDescriptor - - val collisions = SmartList() - checkRedeclarations(descriptor, newName, collisions) - checkAccidentalOverrides(declaration, newName, descriptor, collisions) - checkOriginalUsagesRetargeting(declaration, newName, result, collisions) - checkNewNameUsagesRetargeting(declaration, newName, collisions) - result += collisions - } - - private fun chooseCallableToRename(callableDeclaration: KtCallableDeclaration): KtCallableDeclaration? { - val deepestSuperDeclaration = findDeepestOverriddenDeclaration(callableDeclaration) - if (deepestSuperDeclaration == null || deepestSuperDeclaration == callableDeclaration) { - return callableDeclaration - } - - if (ApplicationManager.getApplication()!!.isUnitTestMode) return deepestSuperDeclaration - - val containsText: String? = - deepestSuperDeclaration.fqName?.parent()?.asString() ?: - (deepestSuperDeclaration.parent as? KtClassOrObject)?.name - - val result = Messages.showYesNoCancelDialog( - deepestSuperDeclaration.project, - if (containsText != null) "Do you want to rename base property from \n$containsText" else "Do you want to rename base property", - "Rename warning", - Messages.getQuestionIcon()) - - return when (result) { - Messages.YES -> deepestSuperDeclaration - Messages.NO -> callableDeclaration - else -> /* Cancel rename */ null - } - } - - override fun substituteElementToRename(element: PsiElement?, editor: Editor?): PsiElement? { - val namedUnwrappedElement = element?.namedUnwrappedElement ?: return null - - val callableDeclaration = namedUnwrappedElement as? KtCallableDeclaration - ?: throw IllegalStateException("Can't be for element $element there because of canProcessElement()") - - val declarationToRename = chooseCallableToRename(callableDeclaration) ?: return null - - val (getterJvmName, setterJvmName) = getJvmNames(namedUnwrappedElement) - if (element is KtLightMethod) { - val name = element.name - if (element.name != getterJvmName && element.name != setterJvmName) return declarationToRename - return declarationToRename.toLightMethods().firstOrNull { it.name == name } - } - - return declarationToRename - } - - override fun substituteElementToRename(element: PsiElement, editor: Editor, renameCallback: Pass) { - val namedUnwrappedElement = element.namedUnwrappedElement ?: return - - val callableDeclaration = namedUnwrappedElement as? KtCallableDeclaration - ?: throw IllegalStateException("Can't be for element $element there because of canProcessElement()") - - fun preprocessAndPass(substitutedJavaElement: PsiElement) { - val (getterJvmName, setterJvmName) = getJvmNames(namedUnwrappedElement) - val elementToProcess = if (element is KtLightMethod) { - val name = element.name - if (element.name != getterJvmName && element.name != setterJvmName) { - substitutedJavaElement - } - else { - substitutedJavaElement.toLightMethods().firstOrNull { it.name == name } - } - } - else substitutedJavaElement - renameCallback.pass(elementToProcess) - } - - val deepestSuperDeclaration = findDeepestOverriddenDeclaration(callableDeclaration) - if (deepestSuperDeclaration == null || deepestSuperDeclaration == callableDeclaration) { - return preprocessAndPass(callableDeclaration) - } - - val superPsiMethods = listOfNotNull(deepestSuperDeclaration.getRepresentativeLightMethod()) - checkSuperMethodsWithPopup(callableDeclaration, superPsiMethods, "Rename", editor) { - preprocessAndPass(if (it.size > 1) deepestSuperDeclaration else callableDeclaration) - } - } - - class PropertyMethodWrapper(private val propertyMethod: PsiMethod) : PsiNamedElement by propertyMethod, NavigationItem by propertyMethod { - override fun getName() = propertyMethod.name - override fun setName(name: String) = this - override fun copy() = this - } - - override fun prepareRenaming(element: PsiElement, newName: String?, allRenames: MutableMap, scope: SearchScope) { - super.prepareRenaming(element, newName, allRenames, scope) - - val namedUnwrappedElement = element.namedUnwrappedElement - val propertyMethods = when(namedUnwrappedElement) { - is KtProperty -> runReadAction { LightClassUtil.getLightClassPropertyMethods(namedUnwrappedElement) } - is KtParameter -> runReadAction { LightClassUtil.getLightClassPropertyMethods(namedUnwrappedElement) } - else -> throw IllegalStateException("Can't be for element $element there because of canProcessElement()") - } - - val newPropertyName = if (newName != null && element is KtLightMethod) propertyNameByAccessor(newName, element) else newName - - val (getterJvmName, setterJvmName) = getJvmNames(namedUnwrappedElement) - - val getter = propertyMethods.getter as? KtLightMethod - val setter = propertyMethods.setter as? KtLightMethod - if (newPropertyName != null - && getter != null && setter != null - && (element == getter || element == setter) - && propertyNameByAccessor(getter.name, getter) == propertyNameByAccessor(setter.name, setter)) { - val accessorToRename = if (element == getter) setter else getter - val newAccessorName = if (element == getter) JvmAbi.setterName(newPropertyName) else JvmAbi.getterName(newPropertyName) - if (ApplicationManager.getApplication().isUnitTestMode - || Messages.showYesNoDialog("Do you want to rename ${accessorToRename.name}() as well?", - "Rename", - Messages.getQuestionIcon()) == Messages.YES) { - allRenames[accessorToRename] = newAccessorName - } - } - - for (propertyMethod in propertyMethods) { - if (element is KtDeclaration && newPropertyName != null) { - val wrapper = PropertyMethodWrapper(propertyMethod) - when { - JvmAbi.isGetterName(propertyMethod.name) && getterJvmName == null -> - allRenames[wrapper] = JvmAbi.getterName(newPropertyName) - JvmAbi.isSetterName(propertyMethod.name) && setterJvmName == null -> - allRenames[wrapper] = JvmAbi.setterName(newPropertyName) - } - } - addRenameElements(propertyMethod, (element as PsiNamedElement).name, newPropertyName, allRenames, scope) - } - } - - private enum class UsageKind { - SIMPLE_PROPERTY_USAGE, - GETTER_USAGE, - SETTER_USAGE - } - - override tailrec fun renameElement(element: PsiElement, newName: String, usages: Array, listener: RefactoringElementListener?) { - val newNameUnquoted = newName.unquote() - if (element is KtLightMethod) { - if (element.modifierList.findAnnotation(DescriptorUtils.JVM_NAME.asString()) != null) { - return super.renameElement(element, newName, usages, listener) - } - - val origin = element.kotlinOrigin - val newPropertyName = propertyNameByAccessor(newNameUnquoted, element) - // Kotlin references to Kotlin property should not use accessor name - if (newPropertyName != null && (origin is KtProperty || origin is KtParameter)) { - val (ktUsages, otherUsages) = usages.partition { it.reference is KtSimpleNameReference } - super.renameElement(element, newName, otherUsages.toTypedArray(), listener) - renameElement(origin, newPropertyName.quoteIfNeeded(), ktUsages.toTypedArray(), listener) - return - } - } - - if (element !is KtProperty && element !is KtParameter) { - super.renameElement(element, newName, usages, listener) - return - } - - val name = (element as KtNamedDeclaration).name!! - val oldGetterName = JvmAbi.getterName(name) - val oldSetterName = JvmAbi.setterName(name) - - if (isEnumCompanionPropertyWithEntryConflict(element, newNameUnquoted)) { - for ((i, usage) in usages.withIndex()) { - if (usage !is MoveRenameUsageInfo) continue - val ref = usage.reference ?: continue - // TODO: Enum value can't be accessed from Java in case of conflict with companion member - if (ref is KtReference) { - val newRef = (ref.bindToElement(element) as? KtSimpleNameExpression)?.mainReference ?: continue - usages[i] = MoveRenameUsageInfo(newRef, usage.referencedElement) - } - } - } - - val adjustedUsages = if (element is KtParameter) usages.filterNot { - val refTarget = it.reference?.resolve() - refTarget is KtLightMethod && DataClassDescriptorResolver.isComponentLike(Name.guessByFirstCharacter(refTarget.name)) - } else usages.toList() - - val refKindUsages = adjustedUsages.groupBy { usage: UsageInfo -> - val refElement = usage.reference?.resolve() - if (refElement is PsiMethod) { - when (refElement.name) { - oldGetterName -> UsageKind.GETTER_USAGE - oldSetterName -> UsageKind.SETTER_USAGE - else -> UsageKind.SIMPLE_PROPERTY_USAGE - } - } - else { - UsageKind.SIMPLE_PROPERTY_USAGE - } - } - - super.renameElement(element, JvmAbi.setterName(newNameUnquoted).quoteIfNeeded(), - refKindUsages[UsageKind.SETTER_USAGE]?.toTypedArray() ?: arrayOf(), - null) - - super.renameElement(element, JvmAbi.getterName(newNameUnquoted).quoteIfNeeded(), - refKindUsages[UsageKind.GETTER_USAGE]?.toTypedArray() ?: arrayOf(), - null) - - super.renameElement(element, newName, - refKindUsages[UsageKind.SIMPLE_PROPERTY_USAGE]?.toTypedArray() ?: arrayOf(), - null) - - usages.forEach { (it as? KtResolvableCollisionUsageInfo)?.apply() } - - dropOverrideKeywordIfNecessary(element) - - listener?.elementRenamed(element) - } - - private fun addRenameElements(psiMethod: PsiMethod?, - oldName: String?, - newName: String?, - allRenames: MutableMap, - scope: SearchScope) { - if (psiMethod == null) return - - OverridingMethodsSearch.search(psiMethod, scope, true).forEach { overrider -> - val overriderElement = overrider.namedUnwrappedElement - - if (overriderElement != null && overriderElement !is SyntheticElement) { - RenameProcessor.assertNonCompileElement(overriderElement) - - val overriderName = overriderElement.name - - if (overriderElement is PsiMethod) { - if (newName != null && Name.isValidIdentifier(newName)) { - val isGetter = overriderElement.parameterList.parametersCount == 0 - allRenames[overriderElement] = if (isGetter) JvmAbi.getterName(newName) else JvmAbi.setterName(newName) - } - } - else { - val newOverriderName = RefactoringUtil.suggestNewOverriderName(overriderName, oldName, newName) - if (newOverriderName != null) { - allRenames[overriderElement] = newOverriderName - } - } - } - } - } - - private fun findDeepestOverriddenDeclaration(declaration: KtCallableDeclaration): KtCallableDeclaration? { - if (declaration.modifierList?.hasModifier(KtTokens.OVERRIDE_KEYWORD) == true) { - val bindingContext = declaration.analyze() - var descriptor = bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, declaration] - if (descriptor is ValueParameterDescriptor) { - descriptor = bindingContext[BindingContext.VALUE_PARAMETER_AS_PROPERTY, descriptor] - ?: return declaration - } - - if (descriptor != null) { - assert(descriptor is PropertyDescriptor) { "Property descriptor is expected" } - - val supers = (descriptor as PropertyDescriptor).getDeepestSuperDeclarations() - - // Take one of supers for now - API doesn't support substitute to several elements (IDEA-48796) - val deepest = supers.first() - if (deepest != descriptor) { - val superPsiElement = DescriptorToSourceUtils.descriptorToDeclaration(deepest) - return superPsiElement as? KtCallableDeclaration - } - } - } - - return null - } -} diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinPsiProcessor.kt.173 b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinPsiProcessor.kt.173 deleted file mode 100644 index cc19aa554c2..00000000000 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinPsiProcessor.kt.173 +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2010-2015 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.idea.refactoring.rename - -import com.intellij.openapi.util.Key -import com.intellij.psi.* -import com.intellij.psi.search.SearchScope -import com.intellij.psi.search.searches.MethodReferencesSearch -import com.intellij.psi.search.searches.ReferencesSearch -import com.intellij.psi.util.PsiUtilCore -import com.intellij.refactoring.listeners.RefactoringElementListener -import com.intellij.refactoring.rename.RenamePsiElementProcessor -import com.intellij.usageView.UsageInfo -import org.jetbrains.kotlin.asJava.namedUnwrappedElement -import org.jetbrains.kotlin.asJava.toLightMethods -import org.jetbrains.kotlin.asJava.unwrapped -import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchOptions -import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchParameters -import org.jetbrains.kotlin.idea.search.or -import org.jetbrains.kotlin.idea.search.projectScope -import org.jetbrains.kotlin.idea.util.actualsForExpected -import org.jetbrains.kotlin.idea.util.liftToExpected -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType -import org.jetbrains.kotlin.psi.psiUtil.isIdentifier -import org.jetbrains.kotlin.psi.psiUtil.parents -import org.jetbrains.kotlin.psi.psiUtil.quoteIfNeeded -import org.jetbrains.kotlin.resolve.ImportPath -import org.jetbrains.kotlin.statistics.KotlinIdeRefactoringTrigger -import org.jetbrains.kotlin.statistics.KotlinStatisticsTrigger - -abstract class RenameKotlinPsiProcessor : RenamePsiElementProcessor() { - override fun canProcessElement(element: PsiElement): Boolean = element is KtNamedDeclaration - - override fun findReferences(element: PsiElement): Collection { - KotlinStatisticsTrigger.trigger(KotlinIdeRefactoringTrigger::class.java, this.javaClass.simpleName) - - val searchParameters = KotlinReferencesSearchParameters( - element, - element.project.projectScope() or element.useScope, - kotlinOptions = KotlinReferencesSearchOptions(searchForComponentConventions = false) - ) - val references = ReferencesSearch.search(searchParameters).toMutableList() - if (element is KtNamedFunction - || (element is KtProperty && !element.isLocal) - || (element is KtParameter && element.hasValOrVar())) { - element.toLightMethods().flatMapTo(references) { MethodReferencesSearch.search(it) } - } - return references - } - - override fun getElementToSearchInStringsAndComments(element: PsiElement?): PsiElement? { - val unwrapped = element?.unwrapped ?: return null - if ((unwrapped is KtDeclaration) && KtPsiUtil.isLocal(unwrapped as KtDeclaration)) return null - return element - } - - override fun getQualifiedNameAfterRename(element: PsiElement, newName: String?, nonJava: Boolean): String? { - if (!nonJava) return newName - - val qualifiedName = when (element) { - is KtNamedDeclaration -> element.fqName?.asString() ?: element.name - is PsiClass -> element.qualifiedName ?: element.name - else -> return null - } - return PsiUtilCore.getQualifiedNameAfterRename(qualifiedName, newName) - } - - override fun prepareRenaming(element: PsiElement, newName: String?, allRenames: MutableMap, scope: SearchScope) { - if (newName == null) return - - val safeNewName = newName.quoteIfNeeded() - - if (!newName.isIdentifier()) { - allRenames[element] = safeNewName - } - - val declaration = element.namedUnwrappedElement as? KtNamedDeclaration - if (declaration != null) { - declaration.liftToExpected()?.let { expectDeclaration -> - allRenames[expectDeclaration] = safeNewName - expectDeclaration.actualsForExpected().forEach { allRenames[it] = safeNewName } - } - } - } - - protected var PsiElement.ambiguousImportUsages: List? by UserDataProperty(Key.create("AMBIGUOUS_IMPORT_USAGES")) - - protected fun UsageInfo.isAmbiguousImportUsage(): Boolean { - val ref = reference as? PsiPolyVariantReference ?: return false - val refElement = ref.element - return refElement.parents.any { (it is KtImportDirective && !it.isAllUnder) || (it is PsiImportStaticStatement && !it.isOnDemand) } - && ref.multiResolve(false).mapNotNullTo(HashSet()) { it.element?.unwrapped }.size > 1 - } - - override fun getPostRenameCallback(element: PsiElement, newName: String?, elementListener: RefactoringElementListener?): Runnable? { - if (newName == null) return null - - return Runnable { - element.ambiguousImportUsages?.forEach { - val ref = it.reference as? PsiPolyVariantReference ?: return@forEach - if (ref.multiResolve(false).isEmpty()) { - ref.handleElementRename(newName) - } - else { - ref.element?.getStrictParentOfType()?.let { importDirective -> - val fqName = importDirective.importedFqName!! - val newFqName = fqName.parent().child(Name.identifier(newName)) - val importList = importDirective.parent as KtImportList - if (importList.imports.none { it.importedFqName == newFqName }) { - val newImportDirective = KtPsiFactory(element).createImportDirective(ImportPath(newFqName, false)) - importDirective.parent.addAfter(newImportDirective, importDirective) - } - } - } - } - element.ambiguousImportUsages = null - } - } -} diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinTypeParameterProcessor.kt.173 b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinTypeParameterProcessor.kt.173 deleted file mode 100644 index 65a37b4b31e..00000000000 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinTypeParameterProcessor.kt.173 +++ /dev/null @@ -1,38 +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.kotlin.idea.refactoring.rename - -import com.intellij.psi.PsiElement -import com.intellij.usageView.UsageInfo -import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor -import org.jetbrains.kotlin.psi.KtTypeParameter - -class RenameKotlinTypeParameterProcessor : RenameKotlinPsiProcessor() { - override fun canProcessElement(element: PsiElement) = element is KtTypeParameter - - override fun findCollisions( - element: PsiElement, - newName: String?, - allRenames: MutableMap, - result: MutableList - ) { - if (newName == null) return - val declaration = element as? KtTypeParameter ?: return - val descriptor = declaration.unsafeResolveToDescriptor() - checkRedeclarations(descriptor, newName, result) - } -} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/safeDelete/KotlinSafeDeleteProcessor.kt.173 b/idea/src/org/jetbrains/kotlin/idea/refactoring/safeDelete/KotlinSafeDeleteProcessor.kt.173 deleted file mode 100644 index d0d84956969..00000000000 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/safeDelete/KotlinSafeDeleteProcessor.kt.173 +++ /dev/null @@ -1,496 +0,0 @@ -/* - * Copyright 2010-2015 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.idea.refactoring.safeDelete - -import com.intellij.openapi.application.ApplicationManager -import com.intellij.openapi.module.Module -import com.intellij.openapi.project.Project -import com.intellij.openapi.ui.Messages -import com.intellij.openapi.util.Condition -import com.intellij.openapi.util.Conditions -import com.intellij.openapi.util.Key -import com.intellij.psi.* -import com.intellij.psi.search.searches.ReferencesSearch -import com.intellij.refactoring.RefactoringBundle -import com.intellij.refactoring.safeDelete.JavaSafeDeleteProcessor -import com.intellij.refactoring.safeDelete.NonCodeUsageSearchInfo -import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteOverrideAnnotation -import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteOverridingMethodUsageInfo -import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteReferenceJavaDeleteUsageInfo -import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteReferenceSimpleDeleteUsageInfo -import com.intellij.usageView.UsageInfo -import org.jetbrains.annotations.TestOnly -import org.jetbrains.kotlin.asJava.* -import org.jetbrains.kotlin.asJava.elements.KtLightField -import org.jetbrains.kotlin.asJava.elements.KtLightFieldImpl -import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor -import org.jetbrains.kotlin.descriptors.Modality -import org.jetbrains.kotlin.idea.KotlinBundle -import org.jetbrains.kotlin.idea.caches.resolve.analyze -import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall -import org.jetbrains.kotlin.idea.core.deleteElementAndCleanParent -import org.jetbrains.kotlin.idea.refactoring.checkSuperMethods -import org.jetbrains.kotlin.idea.refactoring.formatClass -import org.jetbrains.kotlin.idea.refactoring.formatFunction -import org.jetbrains.kotlin.idea.refactoring.withExpectedActuals -import org.jetbrains.kotlin.idea.refactoring.isTrueJavaMethod -import org.jetbrains.kotlin.idea.references.KtReference -import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchOptions -import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchParameters -import org.jetbrains.kotlin.idea.search.projectScope -import org.jetbrains.kotlin.idea.search.usagesSearch.processDelegationCallConstructorUsages -import org.jetbrains.kotlin.idea.util.isExpectDeclaration -import org.jetbrains.kotlin.idea.util.liftToExpected -import org.jetbrains.kotlin.idea.util.runOnExpectAndAllActuals -import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType -import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypeAndBranch -import org.jetbrains.kotlin.psi.psiUtil.hasActualModifier -import org.jetbrains.kotlin.psi.psiUtil.parameterIndex -import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode -import org.jetbrains.kotlin.utils.SmartSet -import org.jetbrains.kotlin.utils.ifEmpty -import java.util.* - -class KotlinSafeDeleteProcessor : JavaSafeDeleteProcessor() { - companion object { - @set:TestOnly - internal var Project.ALLOW_LIFTING_ACTUAL_PARAMETER_TO_EXPECTED - by NotNullableUserDataProperty(Key.create("ALLOW_LIFTING_ACTUAL_PARAMETER_TO_EXPECTED"), true) - - private var KtDeclaration.dropActualModifier: Boolean? by UserDataProperty(Key.create("DROP_ACTUAL_MODIFIER")) - } - - override fun handlesElement(element: PsiElement): Boolean = element.canDeleteElement() - - override fun findUsages( - element: PsiElement, allElementsToDelete: Array, usages: MutableList - ): NonCodeUsageSearchInfo { - val deleteSet = SmartSet.create() - deleteSet.addAll(allElementsToDelete) - - fun getIgnoranceCondition() = Condition { - if (it is KtFile) return@Condition false - deleteSet.any { element -> JavaSafeDeleteProcessor.isInside(it, element.unwrapped) } - } - - fun getSearchInfo(element: PsiElement) = NonCodeUsageSearchInfo(getIgnoranceCondition(), element) - - fun searchKotlinDeclarationReferences(declaration: KtDeclaration): Sequence { - val elementsToSearch = if (declaration is KtParameter) declaration.withExpectedActuals() else listOf(declaration) - return elementsToSearch.asSequence().flatMap { - val searchParameters = KotlinReferencesSearchParameters( - it, - if (it.hasActualModifier()) it.project.projectScope() else it.useScope, - kotlinOptions = KotlinReferencesSearchOptions(acceptCallableOverrides = true) - ) - ReferencesSearch.search(searchParameters) - .asSequence() - .filterNot { reference -> getIgnoranceCondition().value(reference.element) } - } - } - - fun findKotlinParameterUsages(parameter: KtParameter) { - val ownerFunction = parameter.ownerFunction as? KtFunction ?: return - val index = parameter.parameterIndex() - for (reference in searchKotlinDeclarationReferences(ownerFunction)) { - val callee = reference.element as? KtExpression ?: continue - val resolvedCall = callee.resolveToCall(BodyResolveMode.FULL) ?: continue - val parameterDescriptor = resolvedCall.candidateDescriptor.valueParameters.getOrNull(index) ?: continue - val resolvedArgument = resolvedCall.valueArguments[parameterDescriptor] ?: continue - val arguments = resolvedArgument.arguments.filterIsInstance() - if (arguments.isEmpty()) continue - - usages.add(SafeDeleteValueArgumentListUsageInfo(parameter, *arguments.toTypedArray())) - } - } - - fun findKotlinDeclarationUsages(declaration: KtDeclaration): NonCodeUsageSearchInfo { - searchKotlinDeclarationReferences(declaration).mapNotNullTo(usages) { reference -> - val refElement = reference.element ?: return@mapNotNullTo null - refElement.getNonStrictParentOfType()?.let { importDirective -> - SafeDeleteImportDirectiveUsageInfo(importDirective, element) - } ?: SafeDeleteReferenceSimpleDeleteUsageInfo(refElement, declaration, false) - } - - if (declaration is KtParameter) { - findKotlinParameterUsages(declaration) - } - - return getSearchInfo(declaration) - } - - fun asLightElements(ktElements: Array) = - ktElements.flatMap { (it as? KtElement)?.toLightElements() ?: listOf(it) }.toTypedArray() - - fun findUsagesByJavaProcessor(element: PsiElement, forceReferencedElementUnwrapping: Boolean): NonCodeUsageSearchInfo? { - val javaUsages = ArrayList() - - val elementToPassToJava = when (element) { - is KtLightFieldImpl<*> -> object : KtLightField by element { - // Suppress walking through initializer compiled PSI (it doesn't contain any reference expressions anyway) - override fun getInitializer() = null - } - else -> element - } - val searchInfo = super.findUsages(elementToPassToJava, asLightElements(allElementsToDelete), javaUsages) - - javaUsages.filterIsInstance().mapNotNullTo(deleteSet) { it.element } - - val ignoranceCondition = getIgnoranceCondition() - - javaUsages.mapNotNullTo(usages) { usageInfo -> - when (usageInfo) { - is SafeDeleteOverridingMethodUsageInfo -> - usageInfo.smartPointer.element?.let { usageElement -> - KotlinSafeDeleteOverridingUsageInfo(usageElement, usageInfo.referencedElement) - } - - is SafeDeleteOverrideAnnotation -> - usageInfo.smartPointer.element?.let { usageElement -> - when { - usageElement.isTrueJavaMethod() -> usageInfo - usageElement.toLightMethods().all { method -> method.findSuperMethods().isEmpty() } -> { - KotlinSafeDeleteOverrideAnnotation(usageElement, usageInfo.referencedElement) as UsageInfo - } - else -> null - } - } - - is SafeDeleteReferenceJavaDeleteUsageInfo -> - usageInfo.element?.let { usageElement -> - when { - usageElement.getNonStrictParentOfType() != null -> null - ignoranceCondition.value(usageElement) -> null - else -> { - usageElement.getNonStrictParentOfType()?.let { importDirective -> - SafeDeleteImportDirectiveUsageInfo(importDirective, element) - } ?: usageElement.getParentOfTypeAndBranch { typeReference }?.let { - if (element is PsiClass && element.isInterface) SafeDeleteSuperTypeUsageInfo(it, element) else usageInfo - } ?: if (forceReferencedElementUnwrapping) { - SafeDeleteReferenceJavaDeleteUsageInfo(usageElement, element.unwrapped, usageInfo.isSafeDelete) - } else usageInfo - } - } - } - - else -> usageInfo - } - } - - return searchInfo - } - - fun findUsagesByJavaProcessor(elements: Sequence, insideDeleted: Condition): Condition = - elements - .mapNotNull { element -> findUsagesByJavaProcessor(element, true)?.insideDeletedCondition } - .fold(insideDeleted) { condition1, condition2 -> Conditions.or(condition1, condition2) } - - fun findUsagesByJavaProcessor(ktDeclaration: KtDeclaration): NonCodeUsageSearchInfo { - val lightElements = ktDeclaration.toLightElements() - if (lightElements.isEmpty()) { - return findKotlinDeclarationUsages(ktDeclaration) - } - return NonCodeUsageSearchInfo( - findUsagesByJavaProcessor( - lightElements.asSequence(), - getIgnoranceCondition() - ), - ktDeclaration - ) - } - - fun findTypeParameterUsages(parameter: KtTypeParameter) { - val owner = parameter.getNonStrictParentOfType() ?: return - - val parameterList = owner.typeParameters - val parameterIndex = parameterList.indexOf(parameter) - - for (reference in ReferencesSearch.search(owner)) { - if (reference !is KtReference) continue - - val referencedElement = reference.element - - val argList = referencedElement.getNonStrictParentOfType()?.typeArgumentList - ?: referencedElement.getNonStrictParentOfType()?.typeArgumentList - - if (argList != null) { - val projections = argList.arguments - if (parameterIndex < projections.size) { - usages.add(SafeDeleteTypeArgumentListUsageInfo(projections[parameterIndex], parameter)) - } - } - } - } - - fun findDelegationCallUsages(element: PsiElement) { - val constructors = when (element) { - is PsiClass -> element.constructors - is PsiMethod -> arrayOf(element) - else -> return - } - for (constructor in constructors) { - constructor.processDelegationCallConstructorUsages(constructor.useScope) { - if (!getIgnoranceCondition().value(it)) { - usages.add(SafeDeleteReferenceSimpleDeleteUsageInfo(it, element, false)) - } - true - } - } - } - - return when (element) { - is KtClassOrObject -> { - element.toLightClass()?.let { klass -> - findDelegationCallUsages(klass) - findUsagesByJavaProcessor(klass, false) - } ?: findKotlinDeclarationUsages(element) - } - - is KtSecondaryConstructor -> { - if (element.hasActualModifier()) { - findKotlinDeclarationUsages(element) - } else { - element.getRepresentativeLightMethod()?.let { method -> - findDelegationCallUsages(method) - findUsagesByJavaProcessor(method, false) - } ?: findKotlinDeclarationUsages(element) - } - } - - is KtNamedFunction -> { - if (element.isLocal || element.hasActualModifier()) { - findKotlinDeclarationUsages(element) - } - else { - val lightMethods = element.toLightMethods() - if (lightMethods.isNotEmpty()) { - lightMethods.map { method -> findUsagesByJavaProcessor(method, false) }.firstOrNull() - } - else { - findKotlinDeclarationUsages(element) - } - } - } - - is PsiMethod -> { - findUsagesByJavaProcessor(element, false) - } - - is PsiClass -> { - findUsagesByJavaProcessor(element, false) - } - - is KtProperty -> { - if (element.isLocal || element.hasActualModifier()) { - findKotlinDeclarationUsages(element) - } - else { - findUsagesByJavaProcessor(element) - } - } - - is KtTypeParameter -> { - findTypeParameterUsages(element) - findUsagesByJavaProcessor(element) - } - - is KtParameter -> - findUsagesByJavaProcessor(element) - - is KtTypeAlias -> { - findKotlinDeclarationUsages(element) - } - - else -> null - } ?: getSearchInfo(element) - } - - override fun findConflicts(element: PsiElement, allElementsToDelete: Array): MutableCollection? { - if (element is KtNamedFunction || element is KtProperty) { - val jetClass = element.getNonStrictParentOfType() - if (jetClass == null || jetClass.getBody() != element.parent) return null - - val modifierList = jetClass.modifierList - if (modifierList != null && modifierList.hasModifier(KtTokens.ABSTRACT_KEYWORD)) return null - - val bindingContext = (element as KtElement).analyze() - - val declarationDescriptor = - bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, element] as? CallableMemberDescriptor ?: return null - - return declarationDescriptor.overriddenDescriptors - .asSequence() - .filter { overridenDescriptor -> overridenDescriptor.modality == Modality.ABSTRACT } - .mapTo(ArrayList()) { overridenDescriptor -> - KotlinBundle.message( - "x.implements.y", - formatFunction(declarationDescriptor, true), - formatClass(declarationDescriptor.containingDeclaration, true), - formatFunction(overridenDescriptor, true), - formatClass(overridenDescriptor.containingDeclaration, true) - ) - } - } - - return super.findConflicts(element, allElementsToDelete) - } - - /* - * Mostly copied from JavaSafeDeleteProcessor.preprocessUsages - * Revision: d4fc033 - * (replaced original dialog) - */ - override fun preprocessUsages(project: Project, usages: Array): Array? { - val result = ArrayList() - val overridingMethodUsages = ArrayList() - - for (usage in usages) { - if (usage is KotlinSafeDeleteOverridingUsageInfo) { - overridingMethodUsages.add(usage) - } else { - result.add(usage) - } - } - - if (!overridingMethodUsages.isEmpty()) { - if (ApplicationManager.getApplication()!!.isUnitTestMode) { - result.addAll(overridingMethodUsages) - } else { - val dialog = KotlinOverridingDialog(project, overridingMethodUsages) - dialog.show() - - if (!dialog.isOK) return null - - result.addAll(dialog.selected) - } - } - - return result.toTypedArray() - } - - private fun KtDeclaration.removeOrClean() { - when (this) { - is KtParameter -> { - (parent as? KtParameterList)?.removeParameter(this) - } - is KtCallableDeclaration, is KtClassOrObject, is KtTypeAlias -> { - delete() - } - else -> { - removeModifier(KtTokens.IMPL_KEYWORD) - removeModifier(KtTokens.ACTUAL_KEYWORD) - } - } - } - - override fun prepareForDeletion(element: PsiElement) { - if (element is KtDeclaration) { - element.runOnExpectAndAllActuals(checkExpect = false) { it.removeOrClean() } - } - - when (element) { - is PsiMethod -> element.cleanUpOverrides() - - is KtNamedFunction -> - if (!element.isLocal) { - element.getRepresentativeLightMethod()?.cleanUpOverrides() - } - - is KtProperty -> - if (!element.isLocal) { - element.toLightMethods().forEach(PsiMethod::cleanUpOverrides) - } - - is KtTypeParameter -> - element.deleteElementAndCleanParent() - - is KtParameter -> { - element.ownerFunction?.let { - if (it.dropActualModifier == true) { - it.removeModifier(KtTokens.IMPL_KEYWORD) - it.removeModifier(KtTokens.ACTUAL_KEYWORD) - it.dropActualModifier = null - } - } - (element.parent as KtParameterList).removeParameter(element) - } - } - } - - private fun shouldAllowPropagationToExpected(parameter: KtParameter): Boolean { - if (ApplicationManager.getApplication().isUnitTestMode) return parameter.project.ALLOW_LIFTING_ACTUAL_PARAMETER_TO_EXPECTED - - return Messages.showYesNoDialog( - "Do you want to delete this parameter in expected declaration and all related actual ones?", - RefactoringBundle.message("safe.delete.title"), - Messages.getQuestionIcon() - ) == Messages.YES - } - - private fun shouldAllowPropagationToExpected(): Boolean { - if (ApplicationManager.getApplication().isUnitTestMode) return true - - return Messages.showYesNoDialog( - "Do you want to delete expected declaration together with all related actual ones?", - RefactoringBundle.message("safe.delete.title"), - Messages.getQuestionIcon() - ) == Messages.YES - } - - override fun getElementsToSearch( - element: PsiElement, module: Module?, allElementsToDelete: Collection - ): Collection? { - when (element) { - is KtParameter -> { - val expectParameter = element.liftToExpected() - if (expectParameter != null && expectParameter != element) { - if (shouldAllowPropagationToExpected(element)) { - return listOf(expectParameter) - } else { - element.ownerFunction?.dropActualModifier = true - return listOf(element) - } - } - - return element.toPsiParameters().flatMap { psiParameter -> - checkParametersInMethodHierarchy(psiParameter) ?: emptyList() - }.ifEmpty { listOf(element) } - } - - is KtDeclaration -> { - if (element.hasActualModifier() || element.isExpectDeclaration()) { - if (!shouldAllowPropagationToExpected()) { - return null - } - } - } - - is PsiParameter -> - return checkParametersInMethodHierarchy(element) - } - - if (ApplicationManager.getApplication()!!.isUnitTestMode) return Collections.singletonList(element) - - return when (element) { - is KtNamedFunction, is KtProperty -> checkSuperMethods(element as KtDeclaration, allElementsToDelete, "delete (with usage search)") - else -> super.getElementsToSearch(element, module, allElementsToDelete) - } - } -} diff --git a/idea/testData/android/lint/alarm.kt.173 b/idea/testData/android/lint/alarm.kt.173 deleted file mode 100644 index eaa7dfb1f70..00000000000 --- a/idea/testData/android/lint/alarm.kt.173 +++ /dev/null @@ -1,23 +0,0 @@ -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintShortAlarmInspection - -import android.app.AlarmManager - -@Suppress("UsePropertyAccessSyntax", "UNUSED_VARIABLE", "unused", "UNUSED_PARAMETER", "DEPRECATION") -class TestAlarm { - fun test(alarmManager: AlarmManager) { - alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME, 5000, 60000, null); // OK - alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME, 6000, 70000, null); // OK - alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME, 50, 10, null); // ERROR - - alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME, 5000, // ERROR - OtherClass.MY_INTERVAL, null); // ERROR - - val interval = 10; - val interval2 = 2L * interval; - alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME, 5000, interval2, null); // ERROR - } - - private object OtherClass { - val MY_INTERVAL = 1000L; - } -} \ No newline at end of file diff --git a/idea/testData/android/lint/apiCheck.kt.173 b/idea/testData/android/lint/apiCheck.kt.173 deleted file mode 100644 index fb8e110aaea..00000000000 --- a/idea/testData/android/lint/apiCheck.kt.173 +++ /dev/null @@ -1,486 +0,0 @@ - -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection -// INSPECTION_CLASS2: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintInlinedApiInspection -// INSPECTION_CLASS3: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintOverrideInspection - -import android.animation.RectEvaluator -import android.annotation.SuppressLint -import android.annotation.TargetApi -import org.w3c.dom.DOMError -import org.w3c.dom.DOMErrorHandler -import org.w3c.dom.DOMLocator - -import android.view.View -import android.view.ViewGroup -import android.view.ViewGroup.LayoutParams -import android.app.Activity -import android.app.ApplicationErrorReport -import android.graphics.drawable.VectorDrawable -import android.graphics.Path -import android.graphics.PorterDuff -import android.graphics.Rect -import android.os.Build -import android.widget.* -import dalvik.bytecode.OpcodeInfo - -import android.os.Build.VERSION -import android.os.Build.VERSION.SDK_INT -import android.os.Build.VERSION_CODES -import android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH -import android.os.Build.VERSION_CODES.JELLY_BEAN -import android.os.Bundle -import android.os.Parcelable -import android.system.ErrnoException -import android.widget.TextView - -@Suppress("SENSELESS_COMPARISON", "UNUSED_EXPRESSION", "UsePropertyAccessSyntax", "UNUSED_VARIABLE", "unused", "UNUSED_PARAMETER", "DEPRECATION", "USELESS_CAST") -class ApiCallTest: Activity() { - - fun method(chronometer: Chronometer, locator: DOMLocator) { - chronometer.setBackground(null) - - // Ok - Bundle().getInt("") - - View.SYSTEM_UI_FLAG_FULLSCREEN - - // Virtual call - getActionBar() // API 11 - actionBar // API 11 - - // Class references (no call or field access) - val error: DOMError? = null // API 8 - val clz = DOMErrorHandler::class // API 8 - - // Method call - chronometer.onChronometerTickListener // API 3 - - // Inherited method call (from TextView - chronometer.setTextIsSelectable(true) // API 11 - - GridLayout::class - - // Field access - val field = OpcodeInfo.MAXIMUM_VALUE // API 11 - - - val fillParent = LayoutParams.FILL_PARENT // API 1 - // This is a final int, which means it gets inlined - val matchParent = LayoutParams.MATCH_PARENT // API 8 - // Field access: non final - val batteryInfo = report!!.batteryInfo - - // Enum access - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP) { - val mode = PorterDuff.Mode.OVERLAY // API 11 - } - } - - fun test(rect: Rect) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - RectEvaluator(rect); // OK - } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - if (rect != null) { - RectEvaluator(rect); // OK - } - } - } - - fun test2(rect: Rect) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - RectEvaluator(rect); // OK - } - } - - fun test3(rect: Rect) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { - RectEvaluator(); // ERROR - } - } - - fun test4(rect: Rect) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - System.out.println("Something"); - RectEvaluator(rect); // OK - } else { - RectEvaluator(rect); // ERROR - } - } - - fun test5(rect: Rect) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.CUPCAKE) { - RectEvaluator(rect); // ERROR - } else { - RectEvaluator(rect); // ERROR - } - } - - fun test(priority: Boolean, layout: ViewGroup) { - if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { - GridLayout(null).getOrientation(); // Not flagged - } else { - GridLayout(null).getOrientation(); // Flagged - } - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { - GridLayout(null).getOrientation(); // Not flagged - } else { - GridLayout(null).getOrientation(); // Flagged - } - - if (SDK_INT >= ICE_CREAM_SANDWICH) { - GridLayout(null).getOrientation(); // Not flagged - } else { - GridLayout(null).getOrientation(); // Flagged - } - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { - GridLayout(null).getOrientation(); // Not flagged - } else { - GridLayout(null).getOrientation(); // Flagged - } - - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) { - GridLayout(null).getOrientation(); // Flagged - } else { - GridLayout(null).getOrientation(); // Not flagged - } - - if (Build.VERSION.SDK_INT >= 14) { - GridLayout(null).getOrientation(); // Not flagged - } else { - GridLayout(null).getOrientation(); // Flagged - } - - if (VERSION.SDK_INT >= VERSION_CODES.ICE_CREAM_SANDWICH) { - GridLayout(null).getOrientation(); // Not flagged - } else { - GridLayout(null).getOrientation(); // Flagged - } - - // Nested conditionals - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - if (priority) { - GridLayout(null).getOrientation(); // Flagged - } else { - GridLayout(null).getOrientation(); // Flagged - } - } else { - GridLayout(null).getOrientation(); // Flagged - } - - // Nested conditionals 2 - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - if (priority) { - GridLayout(null).getOrientation(); // Not flagged - } else { - GridLayout(null).getOrientation(); // Not flagged - } - } else { - GridLayout(null); // Flagged - } - } - - fun test2(priority: Boolean) { - if (android.os.Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) { - GridLayout(null).getOrientation(); // Not flagged - } else { - GridLayout(null); // Flagged - } - - if (android.os.Build.VERSION.SDK_INT >= 16) { - GridLayout(null).getOrientation(); // Not flagged - } else { - GridLayout(null); // Flagged - } - - if (android.os.Build.VERSION.SDK_INT >= 13) { - GridLayout(null).getOrientation(); // Flagged - } else { - GridLayout(null); // Flagged - } - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - GridLayout(null).getOrientation(); // Not flagged - } else { - GridLayout(null); // Flagged - } - - if (SDK_INT >= JELLY_BEAN) { - GridLayout(null).getOrientation(); // Not flagged - } else { - GridLayout(null); // Flagged - } - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - GridLayout(null).getOrientation(); // Not flagged - } else { - GridLayout(null); // Flagged - } - - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { - GridLayout(null); // Flagged - } else { - GridLayout(null).getOrientation(); // Not flagged - } - - if (Build.VERSION.SDK_INT >= 16) { - GridLayout(null).getOrientation(); // Not flagged - } else { - GridLayout(null); // Flagged - } - - if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) { - GridLayout(null).getOrientation(); // Not flagged - } else { - GridLayout(null); // Flagged - } - } - - fun test(textView: TextView) { - if (textView.isSuggestionsEnabled()) { - //ERROR - } - if (textView.isSuggestionsEnabled) { - //ERROR - } - - if (SDK_INT >= JELLY_BEAN && textView.isSuggestionsEnabled()) { - //NO ERROR - } - - if (SDK_INT >= JELLY_BEAN && textView.isSuggestionsEnabled) { - //NO ERROR - } - - if (SDK_INT >= JELLY_BEAN && (textView.text != "" || textView.isSuggestionsEnabled)) { - //NO ERROR - } - - if (SDK_INT < JELLY_BEAN && (textView.text != "" || textView.isSuggestionsEnabled)) { - //ERROR - } - - if (SDK_INT < JELLY_BEAN && textView.isSuggestionsEnabled()) { - //ERROR - } - - if (SDK_INT < JELLY_BEAN && textView.isSuggestionsEnabled) { - //ERROR - } - - if (SDK_INT < JELLY_BEAN || textView.isSuggestionsEnabled) { - //NO ERROR - } - - if (SDK_INT > JELLY_BEAN || textView.isSuggestionsEnabled) { - //ERROR - } - - - // getActionBar() API 11 - if (SDK_INT <= 10 || getActionBar() == null) { - //NO ERROR - } - - if (SDK_INT < 10 || getActionBar() == null) { - //ERROR - } - - if (SDK_INT < 11 || getActionBar() == null) { - //NO ERROR - } - - if (SDK_INT != 11 || getActionBar() == null) { - //NO ERROR - } - - if (SDK_INT != 12 || getActionBar() == null) { - //ERROR - } - - if (SDK_INT <= 11 || getActionBar() == null) { - //NO ERROR - } - - if (SDK_INT < 12 || getActionBar() == null) { - //NO ERROR - } - - if (SDK_INT <= 12 || getActionBar() == null) { - //NO ERROR - } - - if (SDK_INT < 9 || getActionBar() == null) { - //ERROR - } - - if (SDK_INT <= 9 || getActionBar() == null) { - //ERROR - } - } - - fun testReturn() { - if (SDK_INT < 11) { - return - } - - // No Error - val actionBar = getActionBar() - } - - fun testThrow() { - if (SDK_INT < 11) { - throw IllegalStateException() - } - - // No Error - val actionBar = getActionBar() - } - - fun testError() { - if (SDK_INT < 11) { - error("Api") - } - - // No Error - val actionBar = getActionBar() - } - - fun testWithoutAnnotation(textView: TextView) { - if (textView.isSuggestionsEnabled()) { - - } - - if (textView.isSuggestionsEnabled) { - - } - } - - @TargetApi(JELLY_BEAN) - fun testWithTargetApiAnnotation(textView: TextView) { - if (textView.isSuggestionsEnabled()) { - //NO ERROR, annotation - } - - if (textView.isSuggestionsEnabled) { - //NO ERROR, annotation - } - } - - @SuppressLint("NewApi") - fun testWithSuppressLintAnnotation(textView: TextView) { - if (textView.isSuggestionsEnabled()) { - //NO ERROR, annotation - } - - if (textView.isSuggestionsEnabled) { - //NO ERROR, annotation - } - } - - fun testCatch() { - try { - - } catch (e: ErrnoException) { - - } - } - - fun testOverload() { - // this overloaded addOval available only on API Level 21 - Path().addOval(0f, 0f, 0f, 0f, Path.Direction.CW) - } - - // KT-14737 False error with short-circuit evaluation - fun testShortCircuitEvaluation() { - getDrawable(0) // error here as expected - if(Build.VERSION.SDK_INT >= 23 - && null == getDrawable(0)) // error here should not occur - { - getDrawable(0) // no error here as expected - } - } - - // KT-1482 Kotlin Lint: "Calling new methods on older versions" does not report call on receiver in extension function - private fun Bundle.caseE1a() { getBinder("") } - - private fun Bundle.caseE1c() { this.getBinder("") } - - private fun caseE1b(bundle: Bundle) { bundle.getBinder("") } - - // KT-12023 Kotlin Lint: Cast doesn't trigger minSdk error - fun testCast(layout: ViewGroup) { - if (layout is LinearLayout) {} // OK API 1 - layout as? LinearLayout // OK API 1 - layout as LinearLayout // OK API 1 - - if (layout !is GridLayout) {} - layout as? GridLayout - layout as GridLayout - - val grid = layout as? GridLayout - val linear = layout as LinearLayout // OK API 1 - } - - abstract class ErrorVectorDravable : VectorDrawable(), Parcelable - - @TargetApi(21) - class MyVectorDravable : VectorDrawable() - - fun testTypes() { - GridLayout(this) - val c = VectorDrawable::class.java - } - - fun testCallWithApiAnnotation(textView: TextView) { - MyVectorDravable() - testWithTargetApiAnnotation(textView) - } - - companion object : Activity() { - fun test() { - getDrawable(0) - } - } - - // Return type - internal // API 14 - val gridLayout: GridLayout? - get() = null - - private val report: ApplicationErrorReport? - get() = null -} - -object O: Activity() { - fun test() { - getDrawable(0) - } -} - -fun testJava8() { - // Error, Api 24, Java8 - mutableListOf(1, 2, 3).removeIf { - true - } - - // Ok, Kotlin - mutableListOf(1, 2, 3).removeAll { - true - } - - // Error, Api 24, Java8 - mapOf(1 to 2).forEach { key, value -> key + value } - - // Ok, Kotlin - mapOf(1 to 2).forEach { (key, value) -> key + value } -} - -interface WithDefault { - // Should be ok - fun methodWithBody() { - return - } -} \ No newline at end of file diff --git a/idea/testData/android/lint/callSuper.kt.173 b/idea/testData/android/lint/callSuper.kt.173 deleted file mode 100644 index df30cfe7670..00000000000 --- a/idea/testData/android/lint/callSuper.kt.173 +++ /dev/null @@ -1,97 +0,0 @@ -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintMissingSuperCallInspection - -package android.support.annotation - -@Retention(AnnotationRetention.BINARY) -@Target(AnnotationTarget.FUNCTION) -annotation class CallSuper - -@Suppress("UsePropertyAccessSyntax", "UNUSED_VARIABLE", "unused", "UNUSED_PARAMETER", "DEPRECATION") -class CallSuperTest { - private class Child : Parent() { - override fun test1() { - // ERROR - } - - override fun test2() { - // ERROR - } - - override fun test3() { - // ERROR - } - - override fun test4(arg: Int) { - // ERROR - } - - override fun test4(arg: String) { - // OK - } - - - override fun test5(arg1: Int, arg2: Boolean, arg3: Map, *>, // ERROR - arg4: Array, vararg arg5: Int) { - } - - override fun test5() { - // ERROR - super.test6() // (wrong super) - } - - override fun test6() { - // OK - val x = 5 - super.test6() - System.out.println(x) - } - } - - private open class Parent : ParentParent() { - @CallSuper - protected open fun test1() { - } - - override fun test3() { - super.test3() - } - - @CallSuper - protected open fun test4(arg: Int) { - } - - protected open fun test4(arg: String) { - } - - @CallSuper - protected open fun test5() { - } - - @CallSuper - protected open fun test5(arg1: Int, arg2: Boolean, arg3: Map, *>, - arg4: Array, vararg arg5: Int) { - } - } - - private open class ParentParent : ParentParentParent() { - @CallSuper - protected open fun test2() { - } - - @CallSuper - protected open fun test3() { - } - - @CallSuper - protected open fun test6() { - } - - @CallSuper - protected fun test7() { - } - - - } - - private open class ParentParentParent -} diff --git a/idea/testData/android/lint/closeCursor.kt.173 b/idea/testData/android/lint/closeCursor.kt.173 deleted file mode 100644 index ca26201fd01..00000000000 --- a/idea/testData/android/lint/closeCursor.kt.173 +++ /dev/null @@ -1,36 +0,0 @@ -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintRecycleInspection - -@file:Suppress("UNUSED_VARIABLE") - -import android.app.Activity -import android.os.Bundle - -class MainActivity : Activity() { - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - val cursor = contentResolver.query(null, null, null, null, null) - - // WARNING - contentResolver.query(null, null, null, null, null) - - // OK, closed in chained call - contentResolver.query(null, null, null, null, null).close() - - // KT-14677: Kotlin Lint: "Missing recycle() calls" report cursor with `use()` call - val cursorUsed = contentResolver.query(null, null, null, null, null) - cursorUsed.use { } - - // OK, used in chained call - contentResolver.query(null, null, null, null, null).use { - - } - - // KT-13372: Android Lint for Kotlin: false positive "Cursor should be freed" inside 'if' expression - if (true) { - val c = contentResolver.query(null, null, null, null, null) - c.close() - } - } -} diff --git a/idea/testData/android/lint/commitFragment.kt.173 b/idea/testData/android/lint/commitFragment.kt.173 deleted file mode 100644 index fc6f33303dc..00000000000 --- a/idea/testData/android/lint/commitFragment.kt.173 +++ /dev/null @@ -1,41 +0,0 @@ -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintCommitTransactionInspection - -@file:Suppress("UNUSED_VARIABLE") - -import android.app.Activity -import android.app.FragmentTransaction -import android.app.FragmentManager -import android.os.Bundle - -class MainActivity : Activity() { - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - //OK - val transaction = fragmentManager.beginTransaction() - val transaction2: FragmentTransaction - transaction2 = fragmentManager.beginTransaction() - transaction.commit() - transaction2.commit() - - //WARNING - val transaction3 = fragmentManager.beginTransaction() - - //OK - fragmentManager.beginTransaction().commit() - fragmentManager.beginTransaction().add(null, "A").commit() - - //OK KT-14470 - Runnable { - val a = fragmentManager.beginTransaction() - a.commit() - } - } - - // KT-14780: Kotlin Lint: "Missing commit() calls" false positive when the result of `commit()` is assigned or used as receiver - fun testResultOfCommit(fm: FragmentManager) { - val r1 = fm.beginTransaction().hide(fm.findFragmentByTag("aTag")).commit() - val r2 = fm.beginTransaction().hide(fm.findFragmentByTag("aTag")).commit().toString() - } -} diff --git a/idea/testData/android/lint/javaPerformance.kt.173 b/idea/testData/android/lint/javaPerformance.kt.173 deleted file mode 100644 index b3cddced1f8..00000000000 --- a/idea/testData/android/lint/javaPerformance.kt.173 +++ /dev/null @@ -1,193 +0,0 @@ -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintDrawAllocationInspection -// INSPECTION_CLASS2: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintUseSparseArraysInspection -// INSPECTION_CLASS3: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintUseValueOfInspection - -import android.annotation.SuppressLint -import java.util.HashMap -import android.content.Context -import android.graphics.* -import android.util.AttributeSet -import android.util.SparseArray -import android.widget.Button - -@SuppressWarnings("unused") -@Suppress("UsePropertyAccessSyntax", "UNUSED_VARIABLE", "unused", "UNUSED_PARAMETER", "DEPRECATION") -class JavaPerformanceTest(context: Context, attrs: AttributeSet, defStyle: Int) : Button(context, attrs, defStyle) { - - private var cachedRect: Rect? = null - private var shader: LinearGradient? = null - private var lastHeight: Int = 0 - private var lastWidth: Int = 0 - - override fun onDraw(canvas: android.graphics.Canvas) { - super.onDraw(canvas) - - // Various allocations: - java.lang.String("foo") - val s = java.lang.String("bar") - - // This one should not be reported: - @SuppressLint("DrawAllocation") - val i = 5 - - // Cached object initialized lazily: should not complain about these - if (cachedRect == null) { - cachedRect = Rect(0, 0, 100, 100) - } - if (cachedRect == null || cachedRect!!.width() != 50) { - cachedRect = Rect(0, 0, 50, 100) - } - - val b = java.lang.Boolean.valueOf(true)!! // auto-boxing - dummy(1, 2) - - // Non-allocations - super.animate() - dummy2(1, 2) - - // This will involve allocations, but we don't track - // inter-procedural stuff here - someOtherMethod() - } - - internal fun dummy(foo: Int?, bar: Int) { - dummy2(foo!!, bar) - } - - internal fun dummy2(foo: Int, bar: Int) { - } - - internal fun someOtherMethod() { - // Allocations are okay here - java.lang.String("foo") - val s = java.lang.String("bar") - val b = java.lang.Boolean.valueOf(true)!! // auto-boxing - - - // Sparse array candidates - val myMap = HashMap() - // Should use SparseBooleanArray - val myBoolMap = HashMap() - // Should use SparseIntArray - val myIntMap = java.util.HashMap() - - // This one should not be reported: - @SuppressLint("UseSparseArrays") - val myOtherMap = HashMap() - } - - protected fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int, - x: Boolean) { - // wrong signature - java.lang.String("not an error") - } - - protected fun onMeasure(widthMeasureSpec: Int) { - // wrong signature - java.lang.String("not an error") - } - - protected fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, - bottom: Int, wrong: Int) { - // wrong signature - java.lang.String("not an error") - } - - protected fun onLayout(changed: Boolean, left: Int, top: Int, right: Int) { - // wrong signature - java.lang.String("not an error") - } - - override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, - bottom: Int) { - java.lang.String("flag me") - } - - @SuppressWarnings("null") // not real code - override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { - java.lang.String("flag me") - - // Forbidden factory methods: - Bitmap.createBitmap(100, 100, null) - android.graphics.Bitmap.createScaledBitmap(null, 100, 100, false) - BitmapFactory.decodeFile(null) - val canvas: Canvas? = null - canvas!!.getClipBounds() // allocates on your behalf - canvas.clipBounds // allocates on your behalf - canvas.getClipBounds(null) // NOT an error - - val layoutWidth = width - val layoutHeight = height - if (mAllowCrop && (mOverlay == null || mOverlay!!.width != layoutWidth || - mOverlay!!.height != layoutHeight)) { - mOverlay = Bitmap.createBitmap(layoutWidth, layoutHeight, Bitmap.Config.ARGB_8888) - mOverlayCanvas = Canvas(mOverlay!!) - } - - if (widthMeasureSpec == 42) { - throw IllegalStateException("Test") // NOT an allocation - } - - // More lazy init tests - var initialized = false - if (!initialized) { - java.lang.String("foo") - initialized = true - } - - // NOT lazy initialization - if (!initialized || mOverlay == null) { - java.lang.String("foo") - } - } - - internal fun factories() { - val i1 = 42 - val l1 = 42L - val b1 = true - val c1 = 'c' - val f1 = 1.0f - val d1 = 1.0 - - // The following should not generate errors: - val i3 = Integer.valueOf(42) - } - - private val mAllowCrop: Boolean = false - private var mOverlayCanvas: Canvas? = null - private var mOverlay: Bitmap? = null - - override fun layout(l: Int, t: Int, r: Int, b: Int) { - // Using "this." to reference fields - if (this.shader == null) - this.shader = LinearGradient(0f, 0f, width.toFloat(), 0f, intArrayOf(0), null, - Shader.TileMode.REPEAT) - - val width = width - val height = height - - if (shader == null || lastWidth != width || lastHeight != height) { - lastWidth = width - lastHeight = height - - shader = LinearGradient(0f, 0f, width.toFloat(), 0f, intArrayOf(0), null, Shader.TileMode.REPEAT) - } - } - - fun inefficientSparseArray() { - SparseArray() // Use SparseIntArray instead - SparseArray() // Use SparseLongArray instead - SparseArray() // Use SparseBooleanArray instead - SparseArray() // OK - } - - fun longSparseArray() { - // but only minSdkVersion >= 17 or if has v4 support lib - val myStringMap = HashMap() - } - - fun byteSparseArray() { - // bytes easily apply to ints - val myByteMap = HashMap() - } -} diff --git a/idea/testData/android/lint/javaScriptInterface.kt.173 b/idea/testData/android/lint/javaScriptInterface.kt.173 deleted file mode 100644 index 8d425594a56..00000000000 --- a/idea/testData/android/lint/javaScriptInterface.kt.173 +++ /dev/null @@ -1,66 +0,0 @@ -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintJavascriptInterfaceInspection - -import android.annotation.SuppressLint -import android.webkit.JavascriptInterface -import android.webkit.WebView - -@Suppress("UsePropertyAccessSyntax", "UNUSED_VARIABLE", "UNUSED_VALUE", "unused", "UNUSED_PARAMETER", "DEPRECATION") -class JavaScriptTestK { - fun test(webview: WebView) { - webview.addJavascriptInterface(AnnotatedObject(), "myobj") - - webview.addJavascriptInterface(InheritsFromAnnotated(), "myobj") - webview.addJavascriptInterface(NonAnnotatedObject(), "myobj") - - webview.addJavascriptInterface(null, "nothing") - webview.addJavascriptInterface(object : Any() { @JavascriptInterface fun method() {} }, "nothing") - webview.addJavascriptInterface(JavascriptFace(), "nothing") - - var o: Any = NonAnnotatedObject() - webview.addJavascriptInterface(o, "myobj") - o = InheritsFromAnnotated() - webview.addJavascriptInterface(o, "myobj") - } - - fun test(webview: WebView, object1: AnnotatedObject, object2: NonAnnotatedObject) { - webview.addJavascriptInterface(object1, "myobj") - webview.addJavascriptInterface(object2, "myobj") - } - - @SuppressLint("JavascriptInterface") - fun testSuppressed(webview: WebView) { - webview.addJavascriptInterface(NonAnnotatedObject(), "myobj") - } - - fun testLaterReassignment(webview: WebView) { - var o: Any = NonAnnotatedObject() - val t = o - webview.addJavascriptInterface(t, "myobj") - o = AnnotatedObject() - } - - class NonAnnotatedObject() { - fun test1() {} - fun test2() {} - } - - open class AnnotatedObject { - @JavascriptInterface - open fun test1() {} - - open fun test2() {} - - @JavascriptInterface - fun test3() {} - } - - class InheritsFromAnnotated : AnnotatedObject() { - override fun test1() {} - override fun test2() {} - } - -} - -class JavascriptFace { - fun method() {} -} \ No newline at end of file diff --git a/idea/testData/android/lint/layoutInflation.kt.173 b/idea/testData/android/lint/layoutInflation.kt.173 deleted file mode 100644 index 65bd1e77cf5..00000000000 --- a/idea/testData/android/lint/layoutInflation.kt.173 +++ /dev/null @@ -1,50 +0,0 @@ -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintInflateParamsInspection - -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.BaseAdapter - -@Suppress("UsePropertyAccessSyntax", "UNUSED_VARIABLE", "unused", "UNUSED_PARAMETER", "DEPRECATION") -abstract class LayoutInflationTest : BaseAdapter() { - lateinit var mInflater: LayoutInflater - - override fun getView(position: Int, convertView: View, parent: ViewGroup): View { - var view = convertView - view = mInflater.inflate(R.layout.your_layout, null) - view = mInflater.inflate(R.layout.your_layout, null, true) - view = mInflater.inflate(R.layout.your_layout, parent) - view = WeirdInflater.inflate(view, null) - - return view - } - - object WeirdInflater { - fun inflate(view: View, parent: View?) = view - } - - object R { - object layout { - val your_layout = 1 - } - } -} - -@Suppress("UsePropertyAccessSyntax", "UNUSED_VARIABLE", "unused", "UNUSED_PARAMETER", "DEPRECATION") -abstract class LayoutInflationTest2 : BaseAdapter() { - lateinit var mInflater: LayoutInflater - - override fun getView(position: Int, convertView: View, parent: ViewGroup): View? { - return if (true) { - mInflater.inflate(R.layout.your_layout, parent) - } else { - null - } - } - - object R { - object layout { - val your_layout = 1 - } - } -} \ No newline at end of file diff --git a/idea/testData/android/lint/log.kt.173 b/idea/testData/android/lint/log.kt.173 deleted file mode 100644 index cc9e5e959c2..00000000000 --- a/idea/testData/android/lint/log.kt.173 +++ /dev/null @@ -1,111 +0,0 @@ -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintLogConditionalInspection -// INSPECTION_CLASS2: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintLogTagMismatchInspection -// INSPECTION_CLASS3: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintLongLogTagInspection - -import android.annotation.SuppressLint -import android.util.Log -import android.util.Log.DEBUG - -@SuppressWarnings("UnusedDeclaration") -@Suppress("UsePropertyAccessSyntax", "UNUSED_VARIABLE", "unused", "UNUSED_PARAMETER", "DEPRECATION") -class LogTest { - - fun checkConditional(m: String) { - Log.d(TAG1, "message") // ok: unconditional, but not performing computation - Log.d(TAG1, m) // ok: unconditional, but not performing computation - Log.d(TAG1, "a" + "b") // ok: unconditional, but not performing non-constant computation - Log.d(TAG1, Constants.MY_MESSAGE) // ok: unconditional, but constant string - Log.i(TAG1, "message" + m) // error: unconditional w/ computation - Log.i(TAG1, toString()) // error: unconditional w/ computation - Log.e(TAG1, toString()) // ok: only flagging debug/info messages - Log.w(TAG1, toString()) // ok: only flagging debug/info messages - Log.wtf(TAG1, toString()) // ok: only flagging debug/info messages - if (Log.isLoggable(TAG1, 0)) { - Log.d(TAG1, toString()) // ok: conditional - } - } - - fun checkWrongTag(tag: String) { - if (Log.isLoggable(TAG1, Log.DEBUG)) { - Log.d(TAG2, "message") // warn: mismatched tags! - } - if (Log.isLoggable("my_tag", Log.DEBUG)) { - Log.d("other_tag", "message") // warn: mismatched tags! - } - if (Log.isLoggable("my_tag", Log.DEBUG)) { - Log.d("my_tag", "message") // ok: strings equal - } - if (Log.isLoggable(tag, Log.DEBUG)) { - Log.d(tag, "message") // ok: same variable - } - } - - fun checkLongTag(shouldLog: Boolean) { - if (shouldLog) { - // String literal tags - Log.d("short_tag", "message") // ok: short - Log.d("really_really_really_really_really_long_tag", "message") // error: too long - - // Resolved field tags - Log.d(TAG1, "message") // ok: short - Log.d(TAG22, "message") // ok: short - Log.d(TAG23, "message") // ok: threshold - Log.d(TAG24, "message") // error: too long - Log.d(LONG_TAG, "message") // error: way too long - - // Locally defined variable tags - val LOCAL_TAG = "MyReallyReallyReallyReallyReallyLongTag" - Log.d(LOCAL_TAG, "message") // error: too long - - // Concatenated tags - Log.d(TAG22 + TAG1, "message") // error: too long - Log.d(TAG22 + "MyTag", "message") // error: too long - } - } - - fun checkWrongLevel(tag: String) { - if (Log.isLoggable(TAG1, Log.DEBUG)) { - Log.d(TAG1, "message") // ok: right level - } - if (Log.isLoggable(TAG1, Log.INFO)) { - Log.i(TAG1, "message") // ok: right level - } - if (Log.isLoggable(TAG1, Log.DEBUG)) { - Log.v(TAG1, "message") // warn: wrong level - } - if (Log.isLoggable(TAG1, DEBUG)) { - // static import of level - Log.v(TAG1, "message") // warn: wrong level - } - if (Log.isLoggable(TAG1, Log.VERBOSE)) { - Log.d(TAG1, "message") // warn? verbose is a lower logging level, which includes debug - } - if (Log.isLoggable(TAG1, Constants.MY_LEVEL)) { - Log.d(TAG1, "message") // ok: unknown level alias - } - } - - @SuppressLint("all") - fun suppressed1() { - Log.d(TAG1, "message") // ok: suppressed - } - - @SuppressLint("LogConditional") - fun suppressed2() { - Log.d(TAG1, "message") // ok: suppressed - } - - private object Constants { - val MY_MESSAGE = "My Message" - val MY_LEVEL = 5 - } - - companion object { - private val TAG1 = "MyTag1" - private val TAG2 = "MyTag2" - private val TAG22 = "1234567890123456789012" - private val TAG23 = "12345678901234567890123" - private val TAG24 = "123456789012345678901234" - private val LONG_TAG = "MyReallyReallyReallyReallyReallyLongTag" - } -} \ No newline at end of file diff --git a/idea/testData/android/lint/noInternationalSms.kt.173 b/idea/testData/android/lint/noInternationalSms.kt.173 deleted file mode 100644 index 31fecc25918..00000000000 --- a/idea/testData/android/lint/noInternationalSms.kt.173 +++ /dev/null @@ -1,19 +0,0 @@ -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintUnlocalizedSmsInspection - -import android.content.Context -import android.telephony.SmsManager - -@Suppress("UsePropertyAccessSyntax", "UNUSED_VARIABLE", "unused", "UNUSED_PARAMETER", "DEPRECATION") -class NonInternationalizedSmsDetectorTest { - private fun sendLocalizedMessage(context: Context) { - // Don't warn here - val sms = SmsManager.getDefault() - sms.sendTextMessage("+1234567890", null, null, null, null) - } - - private fun sendAlternativeCountryPrefix(context: Context) { - // Do warn here - val sms = SmsManager.getDefault() - sms.sendMultipartTextMessage("001234567890", null, null, null, null) - } -} \ No newline at end of file diff --git a/idea/testData/android/lint/overrideConcrete.kt.173 b/idea/testData/android/lint/overrideConcrete.kt.173 deleted file mode 100644 index 55a5bb3c228..00000000000 --- a/idea/testData/android/lint/overrideConcrete.kt.173 +++ /dev/null @@ -1,61 +0,0 @@ -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintOverrideAbstractInspection - -import android.annotation.SuppressLint -import android.annotation.TargetApi -import android.os.Build -import android.service.notification.NotificationListenerService -import android.service.notification.StatusBarNotification - -@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) -@Suppress("UsePropertyAccessSyntax", "UNUSED_VARIABLE", "unused", "UNUSED_PARAMETER", "DEPRECATION") -class OverrideConcreteTest2 { - // OK: This one specifies both methods - private open class MyNotificationListenerService1 : NotificationListenerService() { - override fun onNotificationPosted(statusBarNotification: StatusBarNotification) { - } - - override fun onNotificationRemoved(statusBarNotification: StatusBarNotification) { - } - } - - // Error: Misses onNotificationPosted - private class MyNotificationListenerService2 : NotificationListenerService() { - override fun onNotificationRemoved(statusBarNotification: StatusBarNotification) { - } - } - - // Error: Misses onNotificationRemoved - private open class MyNotificationListenerService3 : NotificationListenerService() { - override fun onNotificationPosted(statusBarNotification: StatusBarNotification) { - } - } - - // Error: Missing both; wrong signatures (first has wrong arg count, second has wrong type) - private class MyNotificationListenerService4 : NotificationListenerService() { - fun onNotificationPosted(statusBarNotification: StatusBarNotification, flags: Int) { - } - - fun onNotificationRemoved(statusBarNotification: Int) { - } - } - - // OK: Inherits from a class which define both - private class MyNotificationListenerService5 : MyNotificationListenerService1() - - // OK: Inherits from a class which defines only one, but the other one is defined here - private class MyNotificationListenerService6 : MyNotificationListenerService3() { - override fun onNotificationRemoved(statusBarNotification: StatusBarNotification) { - } - } - - // Error: Inheriting from a class which only defines one - private class MyNotificationListenerService7 : MyNotificationListenerService3() - - // OK: Has target api setting a local version that is high enough - @TargetApi(21) - private class MyNotificationListenerService8 : NotificationListenerService() - - // OK: Suppressed - @SuppressLint("OverrideAbstract") - private class MyNotificationListenerService9 : MyNotificationListenerService1() -} \ No newline at end of file diff --git a/idea/testData/android/lint/parcel.kt.173 b/idea/testData/android/lint/parcel.kt.173 deleted file mode 100644 index 84e3e4faba6..00000000000 --- a/idea/testData/android/lint/parcel.kt.173 +++ /dev/null @@ -1,104 +0,0 @@ -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintParcelCreatorInspection - -@file:Suppress("UsePropertyAccessSyntax", "UNUSED_VARIABLE", "unused", "UNUSED_PARAMETER", "DEPRECATION") -import android.os.Parcel -import android.os.Parcelable -import kotlinx.android.parcel.Parcelize - -class MyParcelable1 : Parcelable { - override fun describeContents() = 0 - override fun writeToParcel(arg0: Parcel, arg1: Int) {} -} - -internal class MyParcelable2 : Parcelable { - override fun describeContents() = 0 - - override fun writeToParcel(arg0: Parcel, arg1: Int) {} - - companion object { - @JvmField - val CREATOR: Parcelable.Creator = object : Parcelable.Creator { - override fun newArray(size: Int) = null!! - override fun createFromParcel(source: Parcel?) = null!! - } - } -} - -internal class MyParcelable3 : Parcelable { - override fun describeContents() = 0 - override fun writeToParcel(arg0: Parcel, arg1: Int) {} - - companion object { - @JvmField - val CREATOR = 0 // Wrong type - } -} - -class RecyclerViewScrollPosition(val position: Int, val topOffset: Int): Parcelable { - override fun describeContents(): Int = 0 - override fun writeToParcel(dest: Parcel, flags: Int) { - dest.writeInt(position) - dest.writeInt(topOffset) - } - - companion object { - @JvmField - val CREATOR = object : Parcelable.Creator { - override fun createFromParcel(parcel: Parcel): RecyclerViewScrollPosition { - val position = parcel.readInt() - val topOffset = parcel.readInt() - return RecyclerViewScrollPosition(position, topOffset) - } - - override fun newArray(size: Int): Array = arrayOfNulls(size) - } - - } -} - -class RecyclerViewScrollPositionWithoutJvmF(val position: Int, val topOffset: Int): Parcelable { - override fun describeContents(): Int = 0 - override fun writeToParcel(dest: Parcel, flags: Int) { - dest.writeInt(position) - dest.writeInt(topOffset) - } - - companion object { - val CREATOR = object : Parcelable.Creator { - override fun createFromParcel(parcel: Parcel): RecyclerViewScrollPosition { - val position = parcel.readInt() - val topOffset = parcel.readInt() - return RecyclerViewScrollPosition(position, topOffset) - } - - override fun newArray(size: Int): Array = arrayOfNulls(size) - } - - } -} - -class RecyclerViewScrollPosition2(val position: Int, val topOffset: Int): Parcelable { - override fun describeContents(): Int = 0 - override fun writeToParcel(dest: Parcel, flags: Int) { - dest.writeInt(position) - dest.writeInt(topOffset) - } - - companion object CREATOR: Parcelable.Creator { - override fun createFromParcel(parcel: Parcel): RecyclerViewScrollPosition { - val position = parcel.readInt() - val topOffset = parcel.readInt() - return RecyclerViewScrollPosition(position, topOffset) - } - - override fun newArray(size: Int): Array = arrayOfNulls(size) - } -} - -internal abstract class MyParcelable4 : Parcelable { - override fun describeContents() = 0 - override fun writeToParcel(arg0: Parcel, arg1: Int) {} -} - -@Parcelize -class ParcelizeUser(val firstName: String, val lastName: String) : Parcelable \ No newline at end of file diff --git a/idea/testData/android/lint/sdCardTest.kt.173 b/idea/testData/android/lint/sdCardTest.kt.173 deleted file mode 100644 index ffc534f68bd..00000000000 --- a/idea/testData/android/lint/sdCardTest.kt.173 +++ /dev/null @@ -1,45 +0,0 @@ -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintSdCardPathInspection - -import java.io.File -import android.content.Intent -import android.net.Uri - -/** - * Ignore comments - create("/sdcard/foo") - */ -@Suppress("UsePropertyAccessSyntax", "UNUSED_VARIABLE", "unused", "UNUSED_PARAMETER", "DEPRECATION") -class SdCardTest { - internal var deviceDir = File("/sdcard/vr") - - init { - if (PROFILE_STARTUP) { - android.os.Debug.startMethodTracing("/sdcard/launcher") - } - - if (File("/sdcard").exists()) { - } - val FilePath = "/sdcard/" + File("test") - System.setProperty("foo.bar", "file://sdcard") - - - val intent = Intent(Intent.ACTION_PICK) - intent.setDataAndType(Uri.parse("file://sdcard/foo.json"), "application/bar-json") - intent.putExtra("path-filter", "/sdcard(/.+)*") - intent.putExtra("start-dir", "/sdcard") - val mypath = "/data/data/foo" - val base = "/data/data/foo.bar/test-profiling" - val s = "file://sdcard/foo" - - val sdCardPath by lazy { "/sdcard" } - fun localPropertyTest() { - val sdCardPathLocal by lazy { "/sdcard" } - } -} - -companion object { - private val PROFILE_STARTUP = true - private val SDCARD_TEST_HTML = "/sdcard/test.html" - val SDCARD_ROOT = "/sdcard" - val PACKAGES_PATH = "/sdcard/o/packages/" -} -} diff --git a/idea/testData/android/lint/setJavaScriptEnabled.kt.173 b/idea/testData/android/lint/setJavaScriptEnabled.kt.173 deleted file mode 100644 index 2c115572e2a..00000000000 --- a/idea/testData/android/lint/setJavaScriptEnabled.kt.173 +++ /dev/null @@ -1,24 +0,0 @@ -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintSetJavaScriptEnabledInspection - -import android.annotation.SuppressLint -import android.app.Activity -import android.webkit.WebView - -@Suppress("UsePropertyAccessSyntax", "UNUSED_VARIABLE", "unused", "UNUSED_PARAMETER", "DEPRECATION") -public class HelloWebApp : Activity() { - - fun test(webView: WebView) { - webView.settings.javaScriptEnabled = true // bad - webView.getSettings().setJavaScriptEnabled(true) // bad - webView.getSettings().setJavaScriptEnabled(false) // good - webView.loadUrl("file:///android_asset/www/index.html") - } - - @SuppressLint("SetJavaScriptEnabled") - fun suppressed(webView: WebView) { - webView.getSettings().javaScriptEnabled = true; // bad - webView.getSettings().setJavaScriptEnabled(true) // bad - webView.getSettings().setJavaScriptEnabled(false); // good - webView.loadUrl("file:///android_asset/www/index.html"); - } -} \ No newline at end of file diff --git a/idea/testData/android/lint/sharedPrefs.kt.173 b/idea/testData/android/lint/sharedPrefs.kt.173 deleted file mode 100644 index 790c9fd9310..00000000000 --- a/idea/testData/android/lint/sharedPrefs.kt.173 +++ /dev/null @@ -1,127 +0,0 @@ -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintCommitPrefEditsInspection - -import android.app.Activity -import android.content.Context -import android.os.Bundle -import android.preference.PreferenceManager - -@Suppress("UsePropertyAccessSyntax", "UNUSED_VARIABLE", "unused", "UNUSED_PARAMETER", "DEPRECATION") -class SharedPrefsText(context: Context) : Activity() { - // OK 1 - fun onCreate1(savedInstanceState: Bundle) { - super.onCreate(savedInstanceState) - val preferences = PreferenceManager.getDefaultSharedPreferences(this) - val editor = preferences.edit() - editor.putString("foo", "bar") - editor.putInt("bar", 42) - editor.commit() - } - - // OK 2 - fun onCreate2(savedInstanceState: Bundle, apply: Boolean) { - super.onCreate(savedInstanceState) - val preferences = PreferenceManager.getDefaultSharedPreferences(this) - val editor = preferences.edit() - editor.putString("foo", "bar") - editor.putInt("bar", 42) - if (apply) { - editor.apply() - } - } - - // OK using with lambda - fun withLambda() { - val preferences = PreferenceManager.getDefaultSharedPreferences(this) - with(preferences.edit()) { - putString("foo", "bar") - putInt("bar", 42) - apply() - } - } - - // OK using apply lambda - fun testApplyLambda() { - PreferenceManager.getDefaultSharedPreferences(this).edit().apply { - putString("foo", "bar") - putInt("bar", 42) - apply() - } - } - - // OK using also lambda - fun testAlsoLambda() { - val preferences = PreferenceManager.getDefaultSharedPreferences(this) - preferences.edit().also { - it.putString("foo", "bar") - it.putInt("bar", 42) - it.apply() - } - } - - // Not a bug - fun test(foo: Foo) { - val bar1 = foo.edit() - val bar3 = edit() - apply() - } - - internal fun apply() { - - } - - fun edit(): Bar { - return Bar() - } - - class Foo { - internal fun edit(): Bar { - return Bar() - } - } - - class Bar - - // Bug - fun bug1(savedInstanceState: Bundle) { - super.onCreate(savedInstanceState) - val preferences = PreferenceManager.getDefaultSharedPreferences(this) - val editor = preferences.edit() - editor.putString("foo", "bar") - editor.putInt("bar", 42) - } - - // Bug missing commit in apply lambda - fun applyLambdaMissingCommit() { - PreferenceManager.getDefaultSharedPreferences(this).edit().apply { - putString("foo", "bar") - putInt("bar", 42) - } - } - - // Bug missing commit in also lambda - fun alsoLambdaMissingCommit() { - PreferenceManager.getDefaultSharedPreferences(this).edit().also { - it.putString("foo", "bar") - it.putInt("bar", 42) - } - } - - // Bug missing commit in with lambda - fun withLambdaMissingCommit() { - with(PreferenceManager.getDefaultSharedPreferences(this).edit()) { - putString("foo", "bar") - putInt("bar", 42) - } - } - - init { - val preferences = PreferenceManager.getDefaultSharedPreferences(context) - val editor = preferences.edit() - editor.putString("foo", "bar") - } - - fun testResultOfCommit() { - val r1 = PreferenceManager.getDefaultSharedPreferences(this).edit().putString("wat", "wat").commit() - val r2 = PreferenceManager.getDefaultSharedPreferences(this).edit().putString("wat", "wat").commit().toString() - } -} \ No newline at end of file diff --git a/idea/testData/android/lint/showDiagnosticsWhenFileIsRed.kt.173 b/idea/testData/android/lint/showDiagnosticsWhenFileIsRed.kt.173 deleted file mode 100644 index 5623005ea68..00000000000 --- a/idea/testData/android/lint/showDiagnosticsWhenFileIsRed.kt.173 +++ /dev/null @@ -1,9 +0,0 @@ -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintSQLiteStringInspection - -import android.database.sqlite.SQLiteDatabase - -fun test(db: SQLiteDatabase) { - val a: String = 1 - - db.execSQL("CREATE TABLE COMPANY(NAME STRING)") -} \ No newline at end of file diff --git a/idea/testData/android/lint/sqlite.kt.173 b/idea/testData/android/lint/sqlite.kt.173 deleted file mode 100644 index 93eab539d4e..00000000000 --- a/idea/testData/android/lint/sqlite.kt.173 +++ /dev/null @@ -1,7 +0,0 @@ -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintSQLiteStringInspection - -import android.database.sqlite.SQLiteDatabase - -fun test(db: SQLiteDatabase) { - db.execSQL("CREATE TABLE COMPANY(NAME STRING)") -} \ No newline at end of file diff --git a/idea/testData/android/lint/supportAnnotation.kt.173 b/idea/testData/android/lint/supportAnnotation.kt.173 deleted file mode 100644 index d6fae75c4c2..00000000000 --- a/idea/testData/android/lint/supportAnnotation.kt.173 +++ /dev/null @@ -1,36 +0,0 @@ -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintSupportAnnotationUsageInspection -// DEPENDENCY: IntRange.java -> android/support/annotation/IntRange.java -// DEPENDENCY: RequiresPermission.java -> android/support/annotation/RequiresPermission.java - - -import android.support.annotation.IntRange -import android.support.annotation.RequiresPermission -import android.Manifest -import android.view.View - -const val constantVal = 0L - -@IntRange(from = 10, to = 0) -fun invalidRange1a(): Int = 5 - -@IntRange(from = constantVal, to = 10) // ok -fun invalidRange0b(): Int = 5 - -@IntRange(from = 10, to = constantVal) -fun invalidRange1b(): Int = 5 - - -// should be ok, KT-16600 -@RequiresPermission(anyOf = arrayOf(Manifest.permission.ACCESS_CHECKIN_PROPERTIES, - Manifest.permission.ACCESS_FINE_LOCATION)) -fun needsPermissions1() { } - -// should be ok, KT-16600 -@RequiresPermission(Manifest.permission.ACCESS_CHECKIN_PROPERTIES) -fun needsPermissions2() { } - -// error -@RequiresPermission( - value = Manifest.permission.ACCESS_CHECKIN_PROPERTIES, - anyOf = arrayOf(Manifest.permission.ACCESS_CHECKIN_PROPERTIES, Manifest.permission.ACCESS_FINE_LOCATION)) -fun needsPermissions3() { } \ No newline at end of file diff --git a/idea/testData/android/lint/systemServices.kt.173 b/idea/testData/android/lint/systemServices.kt.173 deleted file mode 100644 index 2e6860502b0..00000000000 --- a/idea/testData/android/lint/systemServices.kt.173 +++ /dev/null @@ -1,29 +0,0 @@ -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintServiceCastInspection - -import android.content.ClipboardManager -import android.app.Activity -import android.app.WallpaperManager -import android.content.Context -import android.hardware.display.DisplayManager -import android.service.wallpaper.WallpaperService - -@Suppress("UsePropertyAccessSyntax", "UNUSED_VARIABLE", "unused", "UNUSED_PARAMETER", "DEPRECATION") -class SystemServiceTest : Activity() { - - fun test1() { - val displayServiceOk = getSystemService(DISPLAY_SERVICE) as DisplayManager - val displayServiceWrong = getSystemService(DEVICE_POLICY_SERVICE) as DisplayManager - val wallPaperOk = getSystemService(WALLPAPER_SERVICE) as WallpaperService - val wallPaperWrong = getSystemService(WALLPAPER_SERVICE) as WallpaperManager - } - - fun test2(context: Context) { - val displayServiceOk = context.getSystemService(DISPLAY_SERVICE) as DisplayManager - val displayServiceWrong = context.getSystemService(DEVICE_POLICY_SERVICE) as DisplayManager - } - - fun clipboard(context: Context) { - val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager - val clipboard2 = context.getSystemService(Context.CLIPBOARD_SERVICE) as android.content.ClipboardManager - } -} \ No newline at end of file diff --git a/idea/testData/android/lint/toast.kt.173 b/idea/testData/android/lint/toast.kt.173 deleted file mode 100644 index 0623d189d20..00000000000 --- a/idea/testData/android/lint/toast.kt.173 +++ /dev/null @@ -1,75 +0,0 @@ -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintShowToastInspection - -import android.app.Activity -import android.content.Context -import android.widget.Toast - -@Suppress("UsePropertyAccessSyntax", "UNUSED_VARIABLE", "unused", "UNUSED_PARAMETER", "DEPRECATION") -class ToastTest(context: Context) : Activity() { - private fun createToast(context: Context): Toast { - // Don't warn here - return Toast.makeText(context, "foo", Toast.LENGTH_LONG) - } - - private fun insideRunnable(context: Context) { - Runnable { - Toast.makeText(context, "foo", Toast.LENGTH_LONG).show() - } - - Runnable { - val toast = Toast.makeText(context, "foo", Toast.LENGTH_LONG) - if (5 > 3) { - toast.show() - } - } - - Runnable { - Toast.makeText(context, "foo", Toast.LENGTH_LONG) - } - } - - private fun showToast(context: Context) { - // Don't warn here - val toast = Toast.makeText(context, "foo", Toast.LENGTH_LONG) - System.out.println("Other intermediate code here") - val temp = 5 + 2 - toast.show() - } - - private fun showToast2(context: Context) { - // Don't warn here - val duration = Toast.LENGTH_LONG - Toast.makeText(context, "foo", Toast.LENGTH_LONG).show() - Toast.makeText(context, R.string.app_name, duration).show() - } - - private fun broken(context: Context) { - // Errors - Toast.makeText(context, "foo", Toast.LENGTH_LONG) - val toast = Toast.makeText(context, R.string.app_name, 5000) - toast.duration - } - - init { - Toast.makeText(context, "foo", Toast.LENGTH_LONG) - } - - @android.annotation.SuppressLint("ShowToast") - private fun checkSuppress1(context: Context) { - val toast = Toast.makeText(this, "MyToast", Toast.LENGTH_LONG) - } - - private fun checkSuppress2(context: Context) { - @android.annotation.SuppressLint("ShowToast") - val toast1 = Toast.makeText(this, "MyToast", Toast.LENGTH_LONG) - - @android.annotation.SuppressLint("ShowToast", "Lorem ipsum") - val toast2 = Toast.makeText(this, "MyToast", Toast.LENGTH_LONG) - } - - class R { - object string { - val app_name = 1 - } - } -} \ No newline at end of file diff --git a/idea/testData/android/lint/valueOf.kt.173 b/idea/testData/android/lint/valueOf.kt.173 deleted file mode 100644 index 1702302715f..00000000000 --- a/idea/testData/android/lint/valueOf.kt.173 +++ /dev/null @@ -1,8 +0,0 @@ -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintUseValueOfInspection - -@Suppress("UsePropertyAccessSyntax", "UNUSED_VARIABLE", "unused", "UNUSED_PARAMETER", "DEPRECATION") -class Simple { - fun test() { - Integer(5) - } -} \ No newline at end of file diff --git a/idea/testData/android/lint/velocityTrackerRecycle.kt.173 b/idea/testData/android/lint/velocityTrackerRecycle.kt.173 deleted file mode 100644 index 73a5933636d..00000000000 --- a/idea/testData/android/lint/velocityTrackerRecycle.kt.173 +++ /dev/null @@ -1,23 +0,0 @@ -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintRecycleInspection - -@file:Suppress("UNUSED_VARIABLE") - -import android.app.Activity -import android.os.Bundle -import android.view.VelocityTracker - -class MainActivity : Activity() { - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - VelocityTracker.obtain() - - VelocityTracker.obtain().recycle() - - val v1 = VelocityTracker.obtain() - - val v2 = VelocityTracker.obtain() - v2.recycle() - } -} diff --git a/idea/testData/android/lint/viewConstructor.kt.173 b/idea/testData/android/lint/viewConstructor.kt.173 deleted file mode 100644 index 2087cee75c4..00000000000 --- a/idea/testData/android/lint/viewConstructor.kt.173 +++ /dev/null @@ -1,32 +0,0 @@ -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintViewConstructorInspection - -import android.content.Context -import android.util.AttributeSet -import android.view.View -import android.widget.TextView - -class View1(context: Context?) : View(context) -class View2(context: Context?, attrs: AttributeSet?) : View(context, attrs) -class View3(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : TextView(context, attrs, defStyleAttr) - -// Error -class View4(int: Int, context: Context?) : View(context) - -// Error -class View5(context: Context?, attrs: AttributeSet?, val name: String) : View(context, attrs) - -class View6 : View { - constructor(context: Context) : super(context) { - - } -} - -class View7 : View { - constructor(context: Context) : super(context) - constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) -} - -// Error -class View8 : View { - constructor(context: Context, a: Int) : super(context) -} \ No newline at end of file diff --git a/idea/testData/android/lint/viewHolder.kt.173 b/idea/testData/android/lint/viewHolder.kt.173 deleted file mode 100644 index 057b2d07aa8..00000000000 --- a/idea/testData/android/lint/viewHolder.kt.173 +++ /dev/null @@ -1,154 +0,0 @@ -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintViewHolderInspection - -@file:Suppress("NAME_SHADOWING", "unused", "UNUSED_VALUE", "VARIABLE_WITH_REDUNDANT_INITIALIZER", "UNUSED_VARIABLE") - -import android.content.Context -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.BaseAdapter -import android.widget.LinearLayout -import android.widget.TextView -import java.util.ArrayList - -@SuppressWarnings("ConstantConditions", "UnusedDeclaration") -abstract class ViewHolderTest : BaseAdapter() { - override fun getCount() = 0 - override fun getItem(position: Int) = null - override fun getItemId(position: Int) = 0L - - class Adapter1 : ViewHolderTest() { - override fun getView(position: Int, convertView: View, parent: ViewGroup) = null - } - - class Adapter2 : ViewHolderTest() { - lateinit var mInflater: LayoutInflater - - override fun getView(position: Int, convertView: View, parent: ViewGroup): View { - var convertView = convertView - // Should use View Holder pattern here - convertView = mInflater.inflate(R.layout.your_layout, null) - - val text: TextView = convertView.findViewById(R.id.text) - text.text = "Position " + position - - return convertView - } - } - - class Adapter3 : ViewHolderTest() { - lateinit var mInflater: LayoutInflater - - override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { - var convertView = convertView - // Already using View Holder pattern - if (convertView == null) { - convertView = mInflater.inflate(R.layout.your_layout, null) - } - - val text: TextView = convertView!!.findViewById(R.id.text) - text.text = "Position " + position - - return convertView - } - } - - class Adapter4 : ViewHolderTest() { - lateinit var mInflater: LayoutInflater - - override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { - var convertView = convertView - // Already using View Holder pattern - //noinspection StatementWithEmptyBody - if (convertView != null) { - } else { - convertView = mInflater.inflate(R.layout.your_layout, null) - } - - val text: TextView = convertView!!.findViewById(R.id.text) - text.text = "Position " + position - - return convertView - } - } - - class Adapter5 : ViewHolderTest() { - lateinit var mInflater: LayoutInflater - - override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { - var convertView = convertView - // Already using View Holder pattern - convertView = if (convertView == null) mInflater.inflate(R.layout.your_layout, null) else convertView - - val text: TextView = convertView!!.findViewById(R.id.text) - text.text = "Position " + position - - return convertView - } - } - - class Adapter6 : ViewHolderTest() { - private val mContext: Context? = null - private var mLayoutInflator: LayoutInflater? = null - private lateinit var mLapTimes: ArrayList - - override fun getView(position: Int, convertView: View, parent: ViewGroup): View { - if (mLayoutInflator == null) - mLayoutInflator = mContext!!.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater - - var v: View? = convertView - if (v == null) v = mLayoutInflator!!.inflate(R.layout.your_layout, null) - - val listItemHolder: LinearLayout = v!!.findViewById(R.id.laptimes_list_item_holder) - listItemHolder.removeAllViews() - - for (i in 1..5) { - val lapItemView: View = mLayoutInflator!!.inflate(R.layout.laptime_item, null) - if (i == 0) { - val t: TextView = lapItemView.findViewById(R.id.laptime_text) - } - - val t2: TextView = lapItemView.findViewById(R.id.laptime_text2) - if (i < mLapTimes.size - 1 && mLapTimes.size > 1) { - var laptime = mLapTimes[i] - mLapTimes[i + 1] - if (laptime < 0) laptime = mLapTimes[i] - } - - listItemHolder.addView(lapItemView) - - } - return v - } - } - - class Adapter7 : ViewHolderTest() { - lateinit var inflater: LayoutInflater - - override fun getView(position: Int, convertView: View, parent: ViewGroup): View { - var rootView: View? = convertView - val itemViewType = getItemViewType(position) - when (itemViewType) { - 0 -> { - if (rootView != null) - return rootView - rootView = inflater.inflate(android.R.layout.simple_list_item_1, parent, false) - } - } - return rootView!! - } - } - - class R { - object layout { - val your_layout = 1 - val laptime_item = 2 - } - - object id { - val laptime_text = 1 - val laptime_text2 = 2 - val laptimes_list_item_holder = 3 - val text = 4 - } - } -} \ No newline at end of file diff --git a/idea/testData/android/lint/wrongAnnotation.kt.173 b/idea/testData/android/lint/wrongAnnotation.kt.173 deleted file mode 100644 index 163256a6b51..00000000000 --- a/idea/testData/android/lint/wrongAnnotation.kt.173 +++ /dev/null @@ -1,42 +0,0 @@ -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintLocalSuppressInspection - -import android.annotation.SuppressLint -import android.view.View - -@Suppress("UsePropertyAccessSyntax", "UNUSED_VARIABLE", "unused", "UNUSED_PARAMETER", "DEPRECATION") -class WrongAnnotation2 { - @SuppressLint("NewApi") - private val field1: Int = 0 - - @SuppressLint("NewApi") - private val field2 = 5 - - companion object { - @SuppressLint("NewApi") // Valid: class-file check on method - fun foobar(view: View, @SuppressLint("NewApi") foo: Int) { - // Invalid: class-file check - @SuppressLint("NewApi") // Invalid - val a: Boolean - - @SuppressLint("SdCardPath", "NewApi") // TODO: Invalid, class-file based check on local variable - val b: Boolean - - @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") - val localvar = 5 - } - - private fun test() { - @SuppressLint("NewApi") // Invalid - val a = View.MEASURED_STATE_MASK - } - } -} diff --git a/idea/testData/android/lint/wrongImport.kt.173 b/idea/testData/android/lint/wrongImport.kt.173 deleted file mode 100644 index b688362b490..00000000000 --- a/idea/testData/android/lint/wrongImport.kt.173 +++ /dev/null @@ -1,8 +0,0 @@ -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintSuspiciousImportInspection - -//Warning -import android.R - -fun a() { - R.id.button1 -} \ No newline at end of file diff --git a/idea/testData/android/lint/wrongViewCall.kt.173 b/idea/testData/android/lint/wrongViewCall.kt.173 deleted file mode 100644 index 0ee6e922d91..00000000000 --- a/idea/testData/android/lint/wrongViewCall.kt.173 +++ /dev/null @@ -1,23 +0,0 @@ -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintWrongCallInspection - -import android.content.Context -import android.graphics.Canvas -import android.util.AttributeSet -import android.widget.FrameLayout -import android.widget.LinearLayout - -abstract class WrongViewCall(context: Context, attrs: AttributeSet, defStyle: Int) : LinearLayout(context, attrs, defStyle) { - private val child: MyChild? = null - - override fun onDraw(canvas: Canvas) { - super.onDraw(canvas) - child?.onDraw(canvas) - } - - private inner class MyChild(context: Context, attrs: AttributeSet, defStyle: Int) : FrameLayout(context, attrs, defStyle) { - - public override fun onDraw(canvas: Canvas) { - super.onDraw(canvas) - } - } -} diff --git a/idea/testData/android/lintQuickfix/parcelable/missingCreator.kt.173 b/idea/testData/android/lintQuickfix/parcelable/missingCreator.kt.173 deleted file mode 100644 index 6274bc4d340..00000000000 --- a/idea/testData/android/lintQuickfix/parcelable/missingCreator.kt.173 +++ /dev/null @@ -1,14 +0,0 @@ -// INTENTION_TEXT: Add Parcelable Implementation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintParcelCreatorInspection -import android.os.Parcel -import android.os.Parcelable - -class MissingCreator : Parcelable { - override fun writeToParcel(dest: Parcel?, flags: Int) { - TODO("not implemented") - } - - override fun describeContents(): Int { - TODO("not implemented") - } -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/parcelable/missingCreator.kt.expected.173 b/idea/testData/android/lintQuickfix/parcelable/missingCreator.kt.expected.173 deleted file mode 100644 index c4ccf101b42..00000000000 --- a/idea/testData/android/lintQuickfix/parcelable/missingCreator.kt.expected.173 +++ /dev/null @@ -1,27 +0,0 @@ -// INTENTION_TEXT: Add Parcelable Implementation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintParcelCreatorInspection -import android.os.Parcel -import android.os.Parcelable - -class MissingCreator() : Parcelable { - constructor(parcel: Parcel) : this() { - } - - override fun writeToParcel(dest: Parcel?, flags: Int) { - TODO("not implemented") - } - - override fun describeContents(): Int { - TODO("not implemented") - } - - companion object CREATOR : Parcelable.Creator { - override fun createFromParcel(parcel: Parcel): MissingCreator { - return MissingCreator(parcel) - } - - override fun newArray(size: Int): Array { - return arrayOfNulls(size) - } - } -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/parcelable/noImplementation.kt.173 b/idea/testData/android/lintQuickfix/parcelable/noImplementation.kt.173 deleted file mode 100644 index e045a311575..00000000000 --- a/idea/testData/android/lintQuickfix/parcelable/noImplementation.kt.173 +++ /dev/null @@ -1,5 +0,0 @@ -// INTENTION_TEXT: Add Parcelable Implementation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintParcelCreatorInspection -import android.os.Parcelable - -class NoImplementation : Parcelable \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/parcelable/noImplementation.kt.expected.173 b/idea/testData/android/lintQuickfix/parcelable/noImplementation.kt.expected.173 deleted file mode 100644 index 6ebc78fbe7e..00000000000 --- a/idea/testData/android/lintQuickfix/parcelable/noImplementation.kt.expected.173 +++ /dev/null @@ -1,27 +0,0 @@ -// INTENTION_TEXT: Add Parcelable Implementation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintParcelCreatorInspection -import android.os.Parcel -import android.os.Parcelable - -class NoImplementation() : Parcelable { - constructor(parcel: Parcel) : this() { - } - - override fun writeToParcel(parcel: Parcel, flags: Int) { - - } - - override fun describeContents(): Int { - return 0 - } - - companion object CREATOR : Parcelable.Creator { - override fun createFromParcel(parcel: Parcel): NoImplementation { - return NoImplementation(parcel) - } - - override fun newArray(size: Int): Array { - return arrayOfNulls(size) - } - } -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/requiresApi/companion.kt.173 b/idea/testData/android/lintQuickfix/requiresApi/companion.kt.173 deleted file mode 100644 index d3325230e28..00000000000 --- a/idea/testData/android/lintQuickfix/requiresApi/companion.kt.173 +++ /dev/null @@ -1,11 +0,0 @@ -// INTENTION_TEXT: Add @RequiresApi(LOLLIPOP) Annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection -// DEPENDENCY: RequiresApi.java -> android/support/annotation/RequiresApi.java - -import android.graphics.drawable.VectorDrawable - -class VectorDrawableProvider { - companion object { - val VECTOR_DRAWABLE = VectorDrawable() - } -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/requiresApi/companion.kt.expected.173 b/idea/testData/android/lintQuickfix/requiresApi/companion.kt.expected.173 deleted file mode 100644 index 1858d14b757..00000000000 --- a/idea/testData/android/lintQuickfix/requiresApi/companion.kt.expected.173 +++ /dev/null @@ -1,14 +0,0 @@ -// INTENTION_TEXT: Add @RequiresApi(LOLLIPOP) Annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection -// DEPENDENCY: RequiresApi.java -> android/support/annotation/RequiresApi.java - -import android.graphics.drawable.VectorDrawable -import android.os.Build -import android.support.annotation.RequiresApi - -class VectorDrawableProvider { - companion object { - @RequiresApi(Build.VERSION_CODES.LOLLIPOP) - val VECTOR_DRAWABLE = VectorDrawable() - } -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/requiresApi/defaultParameter.kt.173 b/idea/testData/android/lintQuickfix/requiresApi/defaultParameter.kt.173 deleted file mode 100644 index 9f7d6c647aa..00000000000 --- a/idea/testData/android/lintQuickfix/requiresApi/defaultParameter.kt.173 +++ /dev/null @@ -1,10 +0,0 @@ -// INTENTION_TEXT: Add @RequiresApi(LOLLIPOP) Annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection -// DEPENDENCY: RequiresApi.java -> android/support/annotation/RequiresApi.java - -import android.graphics.drawable.VectorDrawable - - -fun withDefaultParameter(vector: VectorDrawable = VectorDrawable()) { - -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/requiresApi/defaultParameter.kt.expected.173 b/idea/testData/android/lintQuickfix/requiresApi/defaultParameter.kt.expected.173 deleted file mode 100644 index 31602b7a3ab..00000000000 --- a/idea/testData/android/lintQuickfix/requiresApi/defaultParameter.kt.expected.173 +++ /dev/null @@ -1,13 +0,0 @@ -// INTENTION_TEXT: Add @RequiresApi(LOLLIPOP) Annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection -// DEPENDENCY: RequiresApi.java -> android/support/annotation/RequiresApi.java - -import android.graphics.drawable.VectorDrawable -import android.os.Build -import android.support.annotation.RequiresApi - - -@RequiresApi(Build.VERSION_CODES.LOLLIPOP) -fun withDefaultParameter(vector: VectorDrawable = VectorDrawable()) { - -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/requiresApi/extend.kt.173 b/idea/testData/android/lintQuickfix/requiresApi/extend.kt.173 deleted file mode 100644 index 7b955856b4b..00000000000 --- a/idea/testData/android/lintQuickfix/requiresApi/extend.kt.173 +++ /dev/null @@ -1,9 +0,0 @@ -// INTENTION_TEXT: Add @RequiresApi(LOLLIPOP) Annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection -// DEPENDENCY: RequiresApi.java -> android/support/annotation/RequiresApi.java - -import android.graphics.drawable.VectorDrawable - -class MyVectorDrawable : VectorDrawable() { - -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/requiresApi/extend.kt.expected.173 b/idea/testData/android/lintQuickfix/requiresApi/extend.kt.expected.173 deleted file mode 100644 index 1965006bd62..00000000000 --- a/idea/testData/android/lintQuickfix/requiresApi/extend.kt.expected.173 +++ /dev/null @@ -1,12 +0,0 @@ -// INTENTION_TEXT: Add @RequiresApi(LOLLIPOP) Annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection -// DEPENDENCY: RequiresApi.java -> android/support/annotation/RequiresApi.java - -import android.graphics.drawable.VectorDrawable -import android.os.Build -import android.support.annotation.RequiresApi - -@RequiresApi(Build.VERSION_CODES.LOLLIPOP) -class MyVectorDrawable : VectorDrawable() { - -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/requiresApi/functionLiteral.kt.173 b/idea/testData/android/lintQuickfix/requiresApi/functionLiteral.kt.173 deleted file mode 100644 index 9b04c508ebe..00000000000 --- a/idea/testData/android/lintQuickfix/requiresApi/functionLiteral.kt.173 +++ /dev/null @@ -1,13 +0,0 @@ -// INTENTION_TEXT: Add @RequiresApi(LOLLIPOP) Annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection -// DEPENDENCY: RequiresApi.java -> android/support/annotation/RequiresApi.java - -import android.graphics.drawable.VectorDrawable - -class VectorDrawableProvider { - fun getVectorDrawable(): VectorDrawable { - with(this) { - return VectorDrawable() - } - } -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/requiresApi/functionLiteral.kt.expected.173 b/idea/testData/android/lintQuickfix/requiresApi/functionLiteral.kt.expected.173 deleted file mode 100644 index fad5bf9a068..00000000000 --- a/idea/testData/android/lintQuickfix/requiresApi/functionLiteral.kt.expected.173 +++ /dev/null @@ -1,16 +0,0 @@ -// INTENTION_TEXT: Add @RequiresApi(LOLLIPOP) Annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection -// DEPENDENCY: RequiresApi.java -> android/support/annotation/RequiresApi.java - -import android.graphics.drawable.VectorDrawable -import android.os.Build -import android.support.annotation.RequiresApi - -class VectorDrawableProvider { - @RequiresApi(Build.VERSION_CODES.LOLLIPOP) - fun getVectorDrawable(): VectorDrawable { - with(this) { - return VectorDrawable() - } - } -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/requiresApi/inlinedConstant.kt.173 b/idea/testData/android/lintQuickfix/requiresApi/inlinedConstant.kt.173 deleted file mode 100644 index ee42d761ab0..00000000000 --- a/idea/testData/android/lintQuickfix/requiresApi/inlinedConstant.kt.173 +++ /dev/null @@ -1,9 +0,0 @@ -// INTENTION_TEXT: Add @RequiresApi(KITKAT) Annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintInlinedApiInspection -// DEPENDENCY: RequiresApi.java -> android/support/annotation/RequiresApi.java - -class Test { - fun foo(): Int { - return android.R.attr.windowTranslucentStatus - } -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/requiresApi/inlinedConstant.kt.expected.173 b/idea/testData/android/lintQuickfix/requiresApi/inlinedConstant.kt.expected.173 deleted file mode 100644 index c94e41a56aa..00000000000 --- a/idea/testData/android/lintQuickfix/requiresApi/inlinedConstant.kt.expected.173 +++ /dev/null @@ -1,13 +0,0 @@ -import android.os.Build -import android.support.annotation.RequiresApi - -// INTENTION_TEXT: Add @RequiresApi(KITKAT) Annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintInlinedApiInspection -// DEPENDENCY: RequiresApi.java -> android/support/annotation/RequiresApi.java - -class Test { - @RequiresApi(Build.VERSION_CODES.KITKAT) - fun foo(): Int { - return android.R.attr.windowTranslucentStatus - } -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/requiresApi/method.kt.173 b/idea/testData/android/lintQuickfix/requiresApi/method.kt.173 deleted file mode 100644 index 79068fceb87..00000000000 --- a/idea/testData/android/lintQuickfix/requiresApi/method.kt.173 +++ /dev/null @@ -1,11 +0,0 @@ -// INTENTION_TEXT: Add @RequiresApi(LOLLIPOP) Annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection -// DEPENDENCY: RequiresApi.java -> android/support/annotation/RequiresApi.java - -import android.graphics.drawable.VectorDrawable - -class VectorDrawableProvider { - fun getVectorDrawable(): VectorDrawable { - return VectorDrawable() - } -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/requiresApi/method.kt.expected.173 b/idea/testData/android/lintQuickfix/requiresApi/method.kt.expected.173 deleted file mode 100644 index 97c45ca4729..00000000000 --- a/idea/testData/android/lintQuickfix/requiresApi/method.kt.expected.173 +++ /dev/null @@ -1,14 +0,0 @@ -// INTENTION_TEXT: Add @RequiresApi(LOLLIPOP) Annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection -// DEPENDENCY: RequiresApi.java -> android/support/annotation/RequiresApi.java - -import android.graphics.drawable.VectorDrawable -import android.os.Build -import android.support.annotation.RequiresApi - -class VectorDrawableProvider { - @RequiresApi(Build.VERSION_CODES.LOLLIPOP) - fun getVectorDrawable(): VectorDrawable { - return VectorDrawable() - } -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/requiresApi/property.kt.173 b/idea/testData/android/lintQuickfix/requiresApi/property.kt.173 deleted file mode 100644 index d4c0ae8be3a..00000000000 --- a/idea/testData/android/lintQuickfix/requiresApi/property.kt.173 +++ /dev/null @@ -1,9 +0,0 @@ -// INTENTION_TEXT: Add @RequiresApi(LOLLIPOP) Annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection -// DEPENDENCY: RequiresApi.java -> android/support/annotation/RequiresApi.java - -import android.graphics.drawable.VectorDrawable - -class VectorDrawableProvider { - val VECTOR_DRAWABLE = VectorDrawable() -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/requiresApi/property.kt.expected.173 b/idea/testData/android/lintQuickfix/requiresApi/property.kt.expected.173 deleted file mode 100644 index 09a6dbc8157..00000000000 --- a/idea/testData/android/lintQuickfix/requiresApi/property.kt.expected.173 +++ /dev/null @@ -1,12 +0,0 @@ -// INTENTION_TEXT: Add @RequiresApi(LOLLIPOP) Annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection -// DEPENDENCY: RequiresApi.java -> android/support/annotation/RequiresApi.java - -import android.graphics.drawable.VectorDrawable -import android.os.Build -import android.support.annotation.RequiresApi - -class VectorDrawableProvider { - @RequiresApi(Build.VERSION_CODES.LOLLIPOP) - val VECTOR_DRAWABLE = VectorDrawable() -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/requiresApi/topLevelProperty.kt.173 b/idea/testData/android/lintQuickfix/requiresApi/topLevelProperty.kt.173 deleted file mode 100644 index d7f7f1f349a..00000000000 --- a/idea/testData/android/lintQuickfix/requiresApi/topLevelProperty.kt.173 +++ /dev/null @@ -1,7 +0,0 @@ -// INTENTION_TEXT: Add @RequiresApi(M) Annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection -// DEPENDENCY: RequiresApi.java -> android/support/annotation/RequiresApi.java -import android.app.Activity - -val top: Int - get() = Activity().checkSelfPermission(READ_CONTACTS) \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/requiresApi/topLevelProperty.kt.expected.173 b/idea/testData/android/lintQuickfix/requiresApi/topLevelProperty.kt.expected.173 deleted file mode 100644 index 3460d7b564f..00000000000 --- a/idea/testData/android/lintQuickfix/requiresApi/topLevelProperty.kt.expected.173 +++ /dev/null @@ -1,10 +0,0 @@ -// INTENTION_TEXT: Add @RequiresApi(M) Annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection -// DEPENDENCY: RequiresApi.java -> android/support/annotation/RequiresApi.java -import android.app.Activity -import android.os.Build -import android.support.annotation.RequiresApi - -val top: Int - @RequiresApi(Build.VERSION_CODES.M) - get() = Activity().checkSelfPermission(READ_CONTACTS) \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/requiresApi/when.kt.173 b/idea/testData/android/lintQuickfix/requiresApi/when.kt.173 deleted file mode 100644 index 67d45b87a8a..00000000000 --- a/idea/testData/android/lintQuickfix/requiresApi/when.kt.173 +++ /dev/null @@ -1,15 +0,0 @@ -// INTENTION_TEXT: Add @RequiresApi(LOLLIPOP) Annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection -// DEPENDENCY: RequiresApi.java -> android/support/annotation/RequiresApi.java - -import android.graphics.drawable.VectorDrawable - -class VectorDrawableProvider { - val flag = false - fun getVectorDrawable(): VectorDrawable { - return when (flag) { - true -> VectorDrawable() - else -> VectorDrawable() - } - } -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/requiresApi/when.kt.expected.173 b/idea/testData/android/lintQuickfix/requiresApi/when.kt.expected.173 deleted file mode 100644 index 3126a6e75be..00000000000 --- a/idea/testData/android/lintQuickfix/requiresApi/when.kt.expected.173 +++ /dev/null @@ -1,18 +0,0 @@ -// INTENTION_TEXT: Add @RequiresApi(LOLLIPOP) Annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection -// DEPENDENCY: RequiresApi.java -> android/support/annotation/RequiresApi.java - -import android.graphics.drawable.VectorDrawable -import android.os.Build -import android.support.annotation.RequiresApi - -class VectorDrawableProvider { - val flag = false - @RequiresApi(Build.VERSION_CODES.LOLLIPOP) - fun getVectorDrawable(): VectorDrawable { - return when (flag) { - true -> VectorDrawable() - else -> VectorDrawable() - } - } -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/suppressLint/activityMethod.kt.173 b/idea/testData/android/lintQuickfix/suppressLint/activityMethod.kt.173 deleted file mode 100644 index 34cac7d0d3a..00000000000 --- a/idea/testData/android/lintQuickfix/suppressLint/activityMethod.kt.173 +++ /dev/null @@ -1,10 +0,0 @@ -// INTENTION_TEXT: Suppress: Add @SuppressLint("SdCardPath") annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintSdCardPathInspection - -import android.app.Activity -import android.os.Environment - - -class MainActivity : Activity() { - fun getSdCard(fromEnvironment: Boolean) = if (fromEnvironment) Environment.getExternalStorageDirectory().path else "/sdcard" -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/suppressLint/activityMethod.kt.expected.173 b/idea/testData/android/lintQuickfix/suppressLint/activityMethod.kt.expected.173 deleted file mode 100644 index 846afb93f20..00000000000 --- a/idea/testData/android/lintQuickfix/suppressLint/activityMethod.kt.expected.173 +++ /dev/null @@ -1,12 +0,0 @@ -// INTENTION_TEXT: Suppress: Add @SuppressLint("SdCardPath") annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintSdCardPathInspection - -import android.annotation.SuppressLint -import android.app.Activity -import android.os.Environment - - -class MainActivity : Activity() { - @SuppressLint("SdCardPath") - fun getSdCard(fromEnvironment: Boolean) = if (fromEnvironment) Environment.getExternalStorageDirectory().path else "/sdcard" -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/suppressLint/addToExistingAnnotation.kt.173 b/idea/testData/android/lintQuickfix/suppressLint/addToExistingAnnotation.kt.173 deleted file mode 100644 index a0a917d5854..00000000000 --- a/idea/testData/android/lintQuickfix/suppressLint/addToExistingAnnotation.kt.173 +++ /dev/null @@ -1,12 +0,0 @@ -// INTENTION_TEXT: Suppress: Add @SuppressLint("SdCardPath") annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintSdCardPathInspection - -import android.annotation.SuppressLint -import android.app.Activity -import android.os.Environment - - -class MainActivity : Activity() { - @SuppressLint("Something") - fun getSdCard(fromEnvironment: Boolean) = if (fromEnvironment) Environment.getExternalStorageDirectory().path else "/sdcard" -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/suppressLint/addToExistingAnnotation.kt.expected.173 b/idea/testData/android/lintQuickfix/suppressLint/addToExistingAnnotation.kt.expected.173 deleted file mode 100644 index c434eea2f1e..00000000000 --- a/idea/testData/android/lintQuickfix/suppressLint/addToExistingAnnotation.kt.expected.173 +++ /dev/null @@ -1,12 +0,0 @@ -// INTENTION_TEXT: Suppress: Add @SuppressLint("SdCardPath") annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintSdCardPathInspection - -import android.annotation.SuppressLint -import android.app.Activity -import android.os.Environment - - -class MainActivity : Activity() { - @SuppressLint("Something", "SdCardPath") - fun getSdCard(fromEnvironment: Boolean) = if (fromEnvironment) Environment.getExternalStorageDirectory().path else "/sdcard" -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/suppressLint/constructorParameter.kt.173 b/idea/testData/android/lintQuickfix/suppressLint/constructorParameter.kt.173 deleted file mode 100644 index bfed3b9be56..00000000000 --- a/idea/testData/android/lintQuickfix/suppressLint/constructorParameter.kt.173 +++ /dev/null @@ -1,4 +0,0 @@ -// INTENTION_TEXT: Suppress: Add @SuppressLint("SdCardPath") annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintSdCardPathInspection - -class SdCard(val path: String = "/sdcard") \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/suppressLint/constructorParameter.kt.expected.173 b/idea/testData/android/lintQuickfix/suppressLint/constructorParameter.kt.expected.173 deleted file mode 100644 index 68149e8eef5..00000000000 --- a/idea/testData/android/lintQuickfix/suppressLint/constructorParameter.kt.expected.173 +++ /dev/null @@ -1,6 +0,0 @@ -import android.annotation.SuppressLint - -// INTENTION_TEXT: Suppress: Add @SuppressLint("SdCardPath") annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintSdCardPathInspection - -class SdCard(@SuppressLint("SdCardPath") val path: String = "/sdcard") \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/suppressLint/destructuringDeclaration.kt.173 b/idea/testData/android/lintQuickfix/suppressLint/destructuringDeclaration.kt.173 deleted file mode 100644 index 346336db2f8..00000000000 --- a/idea/testData/android/lintQuickfix/suppressLint/destructuringDeclaration.kt.173 +++ /dev/null @@ -1,9 +0,0 @@ -// INTENTION_TEXT: Suppress: Add @SuppressLint("SdCardPath") annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintSdCardPathInspection - -fun foo() { - val (a: String, b: String) = "/sdcard" -} - -operator fun CharSequence.component1(): String = "component1" -operator fun CharSequence.component2(): String = "component2" diff --git a/idea/testData/android/lintQuickfix/suppressLint/destructuringDeclaration.kt.expected.173 b/idea/testData/android/lintQuickfix/suppressLint/destructuringDeclaration.kt.expected.173 deleted file mode 100644 index 52c9012bfb0..00000000000 --- a/idea/testData/android/lintQuickfix/suppressLint/destructuringDeclaration.kt.expected.173 +++ /dev/null @@ -1,12 +0,0 @@ -import android.annotation.SuppressLint - -// INTENTION_TEXT: Suppress: Add @SuppressLint("SdCardPath") annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintSdCardPathInspection - -@SuppressLint("SdCardPath") -fun foo() { - val (a: String, b: String) = "/sdcard" -} - -operator fun CharSequence.component1(): String = "component1" -operator fun CharSequence.component2(): String = "component2" diff --git a/idea/testData/android/lintQuickfix/suppressLint/lambdaArgument.kt.173 b/idea/testData/android/lintQuickfix/suppressLint/lambdaArgument.kt.173 deleted file mode 100644 index 08556f1ec6c..00000000000 --- a/idea/testData/android/lintQuickfix/suppressLint/lambdaArgument.kt.173 +++ /dev/null @@ -1,10 +0,0 @@ -// INTENTION_TEXT: Suppress: Add @SuppressLint("SdCardPath") annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintSdCardPathInspection - -fun foo(l: Any) = l - -fun bar() { - foo() { - "/sdcard" - } -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/suppressLint/lambdaArgument.kt.expected.173 b/idea/testData/android/lintQuickfix/suppressLint/lambdaArgument.kt.expected.173 deleted file mode 100644 index 34e862ad244..00000000000 --- a/idea/testData/android/lintQuickfix/suppressLint/lambdaArgument.kt.expected.173 +++ /dev/null @@ -1,13 +0,0 @@ -import android.annotation.SuppressLint - -// INTENTION_TEXT: Suppress: Add @SuppressLint("SdCardPath") annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintSdCardPathInspection - -fun foo(l: Any) = l - -@SuppressLint("SdCardPath") -fun bar() { - foo() { - "/sdcard" - } -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/suppressLint/lambdaArgumentProperty.kt.173 b/idea/testData/android/lintQuickfix/suppressLint/lambdaArgumentProperty.kt.173 deleted file mode 100644 index 233767c23ce..00000000000 --- a/idea/testData/android/lintQuickfix/suppressLint/lambdaArgumentProperty.kt.173 +++ /dev/null @@ -1,6 +0,0 @@ -// INTENTION_TEXT: Suppress: Add @SuppressLint("SdCardPath") annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintSdCardPathInspection - -fun foo(l: Any) = l - -val bar = foo() { "/sdcard" } \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/suppressLint/lambdaArgumentProperty.kt.expected.173 b/idea/testData/android/lintQuickfix/suppressLint/lambdaArgumentProperty.kt.expected.173 deleted file mode 100644 index 575e18d9392..00000000000 --- a/idea/testData/android/lintQuickfix/suppressLint/lambdaArgumentProperty.kt.expected.173 +++ /dev/null @@ -1,9 +0,0 @@ -import android.annotation.SuppressLint - -// INTENTION_TEXT: Suppress: Add @SuppressLint("SdCardPath") annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintSdCardPathInspection - -fun foo(l: Any) = l - -@SuppressLint("SdCardPath") -val bar = foo() { "/sdcard" } \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/suppressLint/methodParameter.kt.173 b/idea/testData/android/lintQuickfix/suppressLint/methodParameter.kt.173 deleted file mode 100644 index 854638e52c2..00000000000 --- a/idea/testData/android/lintQuickfix/suppressLint/methodParameter.kt.173 +++ /dev/null @@ -1,4 +0,0 @@ -// INTENTION_TEXT: Suppress: Add @SuppressLint("SdCardPath") annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintSdCardPathInspection - -fun foo(path: String = "/sdcard") = path \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/suppressLint/methodParameter.kt.expected.173 b/idea/testData/android/lintQuickfix/suppressLint/methodParameter.kt.expected.173 deleted file mode 100644 index 481ddf3fff0..00000000000 --- a/idea/testData/android/lintQuickfix/suppressLint/methodParameter.kt.expected.173 +++ /dev/null @@ -1,6 +0,0 @@ -import android.annotation.SuppressLint - -// INTENTION_TEXT: Suppress: Add @SuppressLint("SdCardPath") annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintSdCardPathInspection - -fun foo(@SuppressLint("SdCardPath") path: String = "/sdcard") = path \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/suppressLint/propertyWithLambda.kt.173 b/idea/testData/android/lintQuickfix/suppressLint/propertyWithLambda.kt.173 deleted file mode 100644 index 8afada5c2d6..00000000000 --- a/idea/testData/android/lintQuickfix/suppressLint/propertyWithLambda.kt.173 +++ /dev/null @@ -1,4 +0,0 @@ -// INTENTION_TEXT: Suppress: Add @SuppressLint("SdCardPath") annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintSdCardPathInspection - -val getPath = { "/sdcard" } \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/suppressLint/propertyWithLambda.kt.expected.173 b/idea/testData/android/lintQuickfix/suppressLint/propertyWithLambda.kt.expected.173 deleted file mode 100644 index 65e05d26d97..00000000000 --- a/idea/testData/android/lintQuickfix/suppressLint/propertyWithLambda.kt.expected.173 +++ /dev/null @@ -1,7 +0,0 @@ -import android.annotation.SuppressLint - -// INTENTION_TEXT: Suppress: Add @SuppressLint("SdCardPath") annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintSdCardPathInspection - -@SuppressLint("SdCardPath") -val getPath = { "/sdcard" } \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/suppressLint/simpleProperty.kt.173 b/idea/testData/android/lintQuickfix/suppressLint/simpleProperty.kt.173 deleted file mode 100644 index c4fee12198d..00000000000 --- a/idea/testData/android/lintQuickfix/suppressLint/simpleProperty.kt.173 +++ /dev/null @@ -1,4 +0,0 @@ -// INTENTION_TEXT: Suppress: Add @SuppressLint("SdCardPath") annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintSdCardPathInspection - -val path = "/sdcard" \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/suppressLint/simpleProperty.kt.expected.173 b/idea/testData/android/lintQuickfix/suppressLint/simpleProperty.kt.expected.173 deleted file mode 100644 index 1b00a0a7951..00000000000 --- a/idea/testData/android/lintQuickfix/suppressLint/simpleProperty.kt.expected.173 +++ /dev/null @@ -1,7 +0,0 @@ -import android.annotation.SuppressLint - -// INTENTION_TEXT: Suppress: Add @SuppressLint("SdCardPath") annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintSdCardPathInspection - -@SuppressLint("SdCardPath") -val path = "/sdcard" \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/targetApi/companion.kt.173 b/idea/testData/android/lintQuickfix/targetApi/companion.kt.173 deleted file mode 100644 index a35ae52f4bc..00000000000 --- a/idea/testData/android/lintQuickfix/targetApi/companion.kt.173 +++ /dev/null @@ -1,10 +0,0 @@ -// INTENTION_TEXT: Add @TargetApi(LOLLIPOP) Annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection - -import android.graphics.drawable.VectorDrawable - -class VectorDrawableProvider { - companion object { - val VECTOR_DRAWABLE = VectorDrawable() - } -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/targetApi/companion.kt.expected.173 b/idea/testData/android/lintQuickfix/targetApi/companion.kt.expected.173 deleted file mode 100644 index 570322550cb..00000000000 --- a/idea/testData/android/lintQuickfix/targetApi/companion.kt.expected.173 +++ /dev/null @@ -1,13 +0,0 @@ -// INTENTION_TEXT: Add @TargetApi(LOLLIPOP) Annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection - -import android.annotation.TargetApi -import android.graphics.drawable.VectorDrawable -import android.os.Build - -class VectorDrawableProvider { - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - companion object { - val VECTOR_DRAWABLE = VectorDrawable() - } -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/targetApi/defaultParameter.kt.173 b/idea/testData/android/lintQuickfix/targetApi/defaultParameter.kt.173 deleted file mode 100644 index 8cff109b6cd..00000000000 --- a/idea/testData/android/lintQuickfix/targetApi/defaultParameter.kt.173 +++ /dev/null @@ -1,9 +0,0 @@ -// INTENTION_TEXT: Add @TargetApi(LOLLIPOP) Annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection - -import android.graphics.drawable.VectorDrawable - - -fun withDefaultParameter(vector: VectorDrawable = VectorDrawable()) { - -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/targetApi/defaultParameter.kt.expected.173 b/idea/testData/android/lintQuickfix/targetApi/defaultParameter.kt.expected.173 deleted file mode 100644 index 1b00e2bc819..00000000000 --- a/idea/testData/android/lintQuickfix/targetApi/defaultParameter.kt.expected.173 +++ /dev/null @@ -1,12 +0,0 @@ -// INTENTION_TEXT: Add @TargetApi(LOLLIPOP) Annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection - -import android.annotation.TargetApi -import android.graphics.drawable.VectorDrawable -import android.os.Build - - -@TargetApi(Build.VERSION_CODES.LOLLIPOP) -fun withDefaultParameter(vector: VectorDrawable = VectorDrawable()) { - -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/targetApi/extend.kt.173 b/idea/testData/android/lintQuickfix/targetApi/extend.kt.173 deleted file mode 100644 index b47ea573746..00000000000 --- a/idea/testData/android/lintQuickfix/targetApi/extend.kt.173 +++ /dev/null @@ -1,8 +0,0 @@ -// INTENTION_TEXT: Add @TargetApi(LOLLIPOP) Annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection - -import android.graphics.drawable.VectorDrawable - -class MyVectorDrawable : VectorDrawable() { - -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/targetApi/extend.kt.expected.173 b/idea/testData/android/lintQuickfix/targetApi/extend.kt.expected.173 deleted file mode 100644 index 6ea867dfef8..00000000000 --- a/idea/testData/android/lintQuickfix/targetApi/extend.kt.expected.173 +++ /dev/null @@ -1,11 +0,0 @@ -// INTENTION_TEXT: Add @TargetApi(LOLLIPOP) Annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection - -import android.annotation.TargetApi -import android.graphics.drawable.VectorDrawable -import android.os.Build - -@TargetApi(Build.VERSION_CODES.LOLLIPOP) -class MyVectorDrawable : VectorDrawable() { - -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/targetApi/functionLiteral.kt.173 b/idea/testData/android/lintQuickfix/targetApi/functionLiteral.kt.173 deleted file mode 100644 index ea1b9c2c64b..00000000000 --- a/idea/testData/android/lintQuickfix/targetApi/functionLiteral.kt.173 +++ /dev/null @@ -1,12 +0,0 @@ -// INTENTION_TEXT: Add @TargetApi(LOLLIPOP) Annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection - -import android.graphics.drawable.VectorDrawable - -class VectorDrawableProvider { - fun getVectorDrawable(): VectorDrawable { - with(this) { - return VectorDrawable() - } - } -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/targetApi/functionLiteral.kt.expected.173 b/idea/testData/android/lintQuickfix/targetApi/functionLiteral.kt.expected.173 deleted file mode 100644 index 3c31dd270f4..00000000000 --- a/idea/testData/android/lintQuickfix/targetApi/functionLiteral.kt.expected.173 +++ /dev/null @@ -1,15 +0,0 @@ -// INTENTION_TEXT: Add @TargetApi(LOLLIPOP) Annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection - -import android.annotation.TargetApi -import android.graphics.drawable.VectorDrawable -import android.os.Build - -class VectorDrawableProvider { - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - fun getVectorDrawable(): VectorDrawable { - with(this) { - return VectorDrawable() - } - } -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/targetApi/inlinedConstant.kt.173 b/idea/testData/android/lintQuickfix/targetApi/inlinedConstant.kt.173 deleted file mode 100644 index ed8cd3c35d9..00000000000 --- a/idea/testData/android/lintQuickfix/targetApi/inlinedConstant.kt.173 +++ /dev/null @@ -1,8 +0,0 @@ -// INTENTION_TEXT: Add @TargetApi(KITKAT) Annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintInlinedApiInspection - -class Test { - fun foo(): Int { - return android.R.attr.windowTranslucentStatus - } -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/targetApi/inlinedConstant.kt.expected.173 b/idea/testData/android/lintQuickfix/targetApi/inlinedConstant.kt.expected.173 deleted file mode 100644 index 5e788aca384..00000000000 --- a/idea/testData/android/lintQuickfix/targetApi/inlinedConstant.kt.expected.173 +++ /dev/null @@ -1,12 +0,0 @@ -import android.annotation.TargetApi -import android.os.Build - -// INTENTION_TEXT: Add @TargetApi(KITKAT) Annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintInlinedApiInspection - -class Test { - @TargetApi(Build.VERSION_CODES.KITKAT) - fun foo(): Int { - return android.R.attr.windowTranslucentStatus - } -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/targetApi/method.kt.173 b/idea/testData/android/lintQuickfix/targetApi/method.kt.173 deleted file mode 100644 index 4df86f64ee4..00000000000 --- a/idea/testData/android/lintQuickfix/targetApi/method.kt.173 +++ /dev/null @@ -1,10 +0,0 @@ -// INTENTION_TEXT: Add @TargetApi(LOLLIPOP) Annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection - -import android.graphics.drawable.VectorDrawable - -class VectorDrawableProvider { - fun getVectorDrawable(): VectorDrawable { - return VectorDrawable() - } -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/targetApi/method.kt.expected.173 b/idea/testData/android/lintQuickfix/targetApi/method.kt.expected.173 deleted file mode 100644 index 8e27e69701f..00000000000 --- a/idea/testData/android/lintQuickfix/targetApi/method.kt.expected.173 +++ /dev/null @@ -1,13 +0,0 @@ -// INTENTION_TEXT: Add @TargetApi(LOLLIPOP) Annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection - -import android.annotation.TargetApi -import android.graphics.drawable.VectorDrawable -import android.os.Build - -class VectorDrawableProvider { - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - fun getVectorDrawable(): VectorDrawable { - return VectorDrawable() - } -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/targetApi/property.kt.173 b/idea/testData/android/lintQuickfix/targetApi/property.kt.173 deleted file mode 100644 index 0cc187c454d..00000000000 --- a/idea/testData/android/lintQuickfix/targetApi/property.kt.173 +++ /dev/null @@ -1,8 +0,0 @@ -// INTENTION_TEXT: Add @TargetApi(LOLLIPOP) Annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection - -import android.graphics.drawable.VectorDrawable - -class VectorDrawableProvider { - val VECTOR_DRAWABLE = VectorDrawable() -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/targetApi/property.kt.expected.173 b/idea/testData/android/lintQuickfix/targetApi/property.kt.expected.173 deleted file mode 100644 index 9b8f9a4119e..00000000000 --- a/idea/testData/android/lintQuickfix/targetApi/property.kt.expected.173 +++ /dev/null @@ -1,11 +0,0 @@ -// INTENTION_TEXT: Add @TargetApi(LOLLIPOP) Annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection - -import android.annotation.TargetApi -import android.graphics.drawable.VectorDrawable -import android.os.Build - -@TargetApi(Build.VERSION_CODES.LOLLIPOP) -class VectorDrawableProvider { - val VECTOR_DRAWABLE = VectorDrawable() -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/targetApi/topLevelProperty.kt.173 b/idea/testData/android/lintQuickfix/targetApi/topLevelProperty.kt.173 deleted file mode 100644 index 1721eb0a819..00000000000 --- a/idea/testData/android/lintQuickfix/targetApi/topLevelProperty.kt.173 +++ /dev/null @@ -1,6 +0,0 @@ -// INTENTION_TEXT: Add @TargetApi(M) Annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection -import android.app.Activity - -val top: Int - get() = Activity().checkSelfPermission(READ_CONTACTS) \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/targetApi/topLevelProperty.kt.expected.173 b/idea/testData/android/lintQuickfix/targetApi/topLevelProperty.kt.expected.173 deleted file mode 100644 index 869d8ab43ef..00000000000 --- a/idea/testData/android/lintQuickfix/targetApi/topLevelProperty.kt.expected.173 +++ /dev/null @@ -1,9 +0,0 @@ -// INTENTION_TEXT: Add @TargetApi(M) Annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection -import android.annotation.TargetApi -import android.app.Activity -import android.os.Build - -val top: Int - @TargetApi(Build.VERSION_CODES.M) - get() = Activity().checkSelfPermission(READ_CONTACTS) \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/targetApi/when.kt.173 b/idea/testData/android/lintQuickfix/targetApi/when.kt.173 deleted file mode 100644 index 27a59191406..00000000000 --- a/idea/testData/android/lintQuickfix/targetApi/when.kt.173 +++ /dev/null @@ -1,14 +0,0 @@ -// INTENTION_TEXT: Add @TargetApi(LOLLIPOP) Annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection - -import android.graphics.drawable.VectorDrawable - -class VectorDrawableProvider { - val flag = false - fun getVectorDrawable(): VectorDrawable { - return when (flag) { - true -> VectorDrawable() - else -> VectorDrawable() - } - } -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/targetApi/when.kt.expected.173 b/idea/testData/android/lintQuickfix/targetApi/when.kt.expected.173 deleted file mode 100644 index 4ca486cdcbb..00000000000 --- a/idea/testData/android/lintQuickfix/targetApi/when.kt.expected.173 +++ /dev/null @@ -1,17 +0,0 @@ -// INTENTION_TEXT: Add @TargetApi(LOLLIPOP) Annotation -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection - -import android.annotation.TargetApi -import android.graphics.drawable.VectorDrawable -import android.os.Build - -class VectorDrawableProvider { - val flag = false - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - fun getVectorDrawable(): VectorDrawable { - return when (flag) { - true -> VectorDrawable() - else -> VectorDrawable() - } - } -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/targetVersionCheck/annotation.kt.173 b/idea/testData/android/lintQuickfix/targetVersionCheck/annotation.kt.173 deleted file mode 100644 index e052b68c6e6..00000000000 --- a/idea/testData/android/lintQuickfix/targetVersionCheck/annotation.kt.173 +++ /dev/null @@ -1,12 +0,0 @@ -// INTENTION_TEXT: Surround with if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { ... } -// INTENTION_NOT_AVAILABLE -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection - -import android.graphics.drawable.VectorDrawable -import kotlin.reflect.KClass - -annotation class SomeAnnotationWithClass(val cls: KClass<*>) - -@SomeAnnotationWithClass(VectorDrawable::class) -class VectorDrawableProvider { -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/targetVersionCheck/defaultParameter.kt.173 b/idea/testData/android/lintQuickfix/targetVersionCheck/defaultParameter.kt.173 deleted file mode 100644 index 97f5da238fa..00000000000 --- a/idea/testData/android/lintQuickfix/targetVersionCheck/defaultParameter.kt.173 +++ /dev/null @@ -1,10 +0,0 @@ -// INTENTION_TEXT: Surround with if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { ... } -// INTENTION_NOT_AVAILABLE -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection - -import android.graphics.drawable.VectorDrawable - - -fun withDefaultParameter(vector: VectorDrawable = VectorDrawable()) { - -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/targetVersionCheck/destructuringDeclaration.kt.173 b/idea/testData/android/lintQuickfix/targetVersionCheck/destructuringDeclaration.kt.173 deleted file mode 100644 index 8aee1d9d670..00000000000 --- a/idea/testData/android/lintQuickfix/targetVersionCheck/destructuringDeclaration.kt.173 +++ /dev/null @@ -1,12 +0,0 @@ -// INTENTION_TEXT: Surround with if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { ... } -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection - -import android.app.Activity -import android.graphics.drawable.VectorDrawable - -data class ValueProvider(var p1: VectorDrawable, val p2: Int) - -val activity = Activity() -fun foo() { - val (v1, v2) = ValueProvider(VectorDrawable(), 0) -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/targetVersionCheck/destructuringDeclaration.kt.expected.173 b/idea/testData/android/lintQuickfix/targetVersionCheck/destructuringDeclaration.kt.expected.173 deleted file mode 100644 index dd2eb2154bc..00000000000 --- a/idea/testData/android/lintQuickfix/targetVersionCheck/destructuringDeclaration.kt.expected.173 +++ /dev/null @@ -1,17 +0,0 @@ -// INTENTION_TEXT: Surround with if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { ... } -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection - -import android.app.Activity -import android.graphics.drawable.VectorDrawable -import android.os.Build - -data class ValueProvider(var p1: VectorDrawable, val p2: Int) - -val activity = Activity() -fun foo() { - val (v1, v2) = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - ValueProvider(VectorDrawable(), 0) - } else { - TODO("VERSION.SDK_INT < LOLLIPOP") - } -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/targetVersionCheck/expressionBody.kt.173 b/idea/testData/android/lintQuickfix/targetVersionCheck/expressionBody.kt.173 deleted file mode 100644 index 16ee93fa998..00000000000 --- a/idea/testData/android/lintQuickfix/targetVersionCheck/expressionBody.kt.173 +++ /dev/null @@ -1,8 +0,0 @@ -// INTENTION_TEXT: Surround with if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { ... } -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection - -import android.graphics.drawable.VectorDrawable - -class VectorDrawableProvider { - fun getVectorDrawable(): VectorDrawable = VectorDrawable() -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/targetVersionCheck/expressionBody.kt.expected.173 b/idea/testData/android/lintQuickfix/targetVersionCheck/expressionBody.kt.expected.173 deleted file mode 100644 index 878163aab0f..00000000000 --- a/idea/testData/android/lintQuickfix/targetVersionCheck/expressionBody.kt.expected.173 +++ /dev/null @@ -1,13 +0,0 @@ -// INTENTION_TEXT: Surround with if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { ... } -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection - -import android.graphics.drawable.VectorDrawable -import android.os.Build - -class VectorDrawableProvider { - fun getVectorDrawable(): VectorDrawable = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - VectorDrawable() - } else { - TODO("VERSION.SDK_INT < LOLLIPOP") - } -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/targetVersionCheck/functionLiteral.kt.173 b/idea/testData/android/lintQuickfix/targetVersionCheck/functionLiteral.kt.173 deleted file mode 100644 index 915c5c697a8..00000000000 --- a/idea/testData/android/lintQuickfix/targetVersionCheck/functionLiteral.kt.173 +++ /dev/null @@ -1,12 +0,0 @@ -// INTENTION_TEXT: Surround with if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { ... } -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection - -import android.graphics.drawable.VectorDrawable - -class VectorDrawableProvider { - fun getVectorDrawable(): VectorDrawable { - with(this) { - return VectorDrawable() - } - } -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/targetVersionCheck/functionLiteral.kt.expected.173 b/idea/testData/android/lintQuickfix/targetVersionCheck/functionLiteral.kt.expected.173 deleted file mode 100644 index a6165526117..00000000000 --- a/idea/testData/android/lintQuickfix/targetVersionCheck/functionLiteral.kt.expected.173 +++ /dev/null @@ -1,17 +0,0 @@ -// INTENTION_TEXT: Surround with if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { ... } -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection - -import android.graphics.drawable.VectorDrawable -import android.os.Build - -class VectorDrawableProvider { - fun getVectorDrawable(): VectorDrawable { - with(this) { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - VectorDrawable() - } else { - TODO("VERSION.SDK_INT < LOLLIPOP") - } - } - } -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/targetVersionCheck/getterWIthExpressionBody.kt.173 b/idea/testData/android/lintQuickfix/targetVersionCheck/getterWIthExpressionBody.kt.173 deleted file mode 100644 index 79651954230..00000000000 --- a/idea/testData/android/lintQuickfix/targetVersionCheck/getterWIthExpressionBody.kt.173 +++ /dev/null @@ -1,7 +0,0 @@ -// INTENTION_TEXT: Surround with if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { ... } -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection - -import android.graphics.drawable.VectorDrawable - -val v: VectorDrawable - get() = VectorDrawable() \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/targetVersionCheck/getterWIthExpressionBody.kt.expected.173 b/idea/testData/android/lintQuickfix/targetVersionCheck/getterWIthExpressionBody.kt.expected.173 deleted file mode 100644 index 01d2adcc812..00000000000 --- a/idea/testData/android/lintQuickfix/targetVersionCheck/getterWIthExpressionBody.kt.expected.173 +++ /dev/null @@ -1,12 +0,0 @@ -// INTENTION_TEXT: Surround with if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { ... } -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection - -import android.graphics.drawable.VectorDrawable -import android.os.Build - -val v: VectorDrawable - get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - VectorDrawable() - } else { - TODO("VERSION.SDK_INT < LOLLIPOP") - } \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/targetVersionCheck/if.kt.173 b/idea/testData/android/lintQuickfix/targetVersionCheck/if.kt.173 deleted file mode 100644 index e2f81f2bbc0..00000000000 --- a/idea/testData/android/lintQuickfix/targetVersionCheck/if.kt.173 +++ /dev/null @@ -1,12 +0,0 @@ -// INTENTION_TEXT: Surround with if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { ... } -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection - -import android.graphics.drawable.VectorDrawable - -class VectorDrawableProvider { - val flag = false - fun getVectorDrawable(): VectorDrawable { - if (flag) - return VectorDrawable() - } -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/targetVersionCheck/if.kt.expected.173 b/idea/testData/android/lintQuickfix/targetVersionCheck/if.kt.expected.173 deleted file mode 100644 index 960340e8eca..00000000000 --- a/idea/testData/android/lintQuickfix/targetVersionCheck/if.kt.expected.173 +++ /dev/null @@ -1,17 +0,0 @@ -// INTENTION_TEXT: Surround with if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { ... } -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection - -import android.graphics.drawable.VectorDrawable -import android.os.Build - -class VectorDrawableProvider { - val flag = false - fun getVectorDrawable(): VectorDrawable { - if (flag) - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - VectorDrawable() - } else { - TODO("VERSION.SDK_INT < LOLLIPOP") - } - } -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/targetVersionCheck/ifWithBlock.kt.173 b/idea/testData/android/lintQuickfix/targetVersionCheck/ifWithBlock.kt.173 deleted file mode 100644 index c74f3ee3ab6..00000000000 --- a/idea/testData/android/lintQuickfix/targetVersionCheck/ifWithBlock.kt.173 +++ /dev/null @@ -1,13 +0,0 @@ -// INTENTION_TEXT: Surround with if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { ... } -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection - -import android.graphics.drawable.VectorDrawable - -class VectorDrawableProvider { - val flag = false - fun getVectorDrawable(): VectorDrawable { - if (flag) { - return VectorDrawable() - } - } -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/targetVersionCheck/ifWithBlock.kt.expected.173 b/idea/testData/android/lintQuickfix/targetVersionCheck/ifWithBlock.kt.expected.173 deleted file mode 100644 index 224a8f295f8..00000000000 --- a/idea/testData/android/lintQuickfix/targetVersionCheck/ifWithBlock.kt.expected.173 +++ /dev/null @@ -1,18 +0,0 @@ -// INTENTION_TEXT: Surround with if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { ... } -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection - -import android.graphics.drawable.VectorDrawable -import android.os.Build - -class VectorDrawableProvider { - val flag = false - fun getVectorDrawable(): VectorDrawable { - if (flag) { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - VectorDrawable() - } else { - TODO("VERSION.SDK_INT < LOLLIPOP") - } - } - } -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/targetVersionCheck/inlinedConstant.kt.173 b/idea/testData/android/lintQuickfix/targetVersionCheck/inlinedConstant.kt.173 deleted file mode 100644 index febb06d9b65..00000000000 --- a/idea/testData/android/lintQuickfix/targetVersionCheck/inlinedConstant.kt.173 +++ /dev/null @@ -1,8 +0,0 @@ -// INTENTION_TEXT: Surround with if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) { ... } -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintInlinedApiInspection - -class Test { - fun foo(): Int { - return android.R.attr.windowTranslucentStatus - } -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/targetVersionCheck/inlinedConstant.kt.expected.173 b/idea/testData/android/lintQuickfix/targetVersionCheck/inlinedConstant.kt.expected.173 deleted file mode 100644 index 80f478a30d7..00000000000 --- a/idea/testData/android/lintQuickfix/targetVersionCheck/inlinedConstant.kt.expected.173 +++ /dev/null @@ -1,14 +0,0 @@ -import android.os.Build - -// INTENTION_TEXT: Surround with if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) { ... } -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintInlinedApiInspection - -class Test { - fun foo(): Int { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - android.R.attr.windowTranslucentStatus - } else { - TODO("VERSION.SDK_INT < KITKAT") - } - } -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/targetVersionCheck/method.kt.173 b/idea/testData/android/lintQuickfix/targetVersionCheck/method.kt.173 deleted file mode 100644 index a1bbff234ae..00000000000 --- a/idea/testData/android/lintQuickfix/targetVersionCheck/method.kt.173 +++ /dev/null @@ -1,10 +0,0 @@ -// INTENTION_TEXT: Surround with if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { ... } -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection - -import android.graphics.drawable.VectorDrawable - -class VectorDrawableProvider { - fun getVectorDrawable(): VectorDrawable { - return VectorDrawable() - } -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/targetVersionCheck/method.kt.expected.173 b/idea/testData/android/lintQuickfix/targetVersionCheck/method.kt.expected.173 deleted file mode 100644 index 6685b74c231..00000000000 --- a/idea/testData/android/lintQuickfix/targetVersionCheck/method.kt.expected.173 +++ /dev/null @@ -1,15 +0,0 @@ -// INTENTION_TEXT: Surround with if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { ... } -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection - -import android.graphics.drawable.VectorDrawable -import android.os.Build - -class VectorDrawableProvider { - fun getVectorDrawable(): VectorDrawable { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - VectorDrawable() - } else { - TODO("VERSION.SDK_INT < LOLLIPOP") - } - } -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/targetVersionCheck/when.kt.173 b/idea/testData/android/lintQuickfix/targetVersionCheck/when.kt.173 deleted file mode 100644 index 11474aca918..00000000000 --- a/idea/testData/android/lintQuickfix/targetVersionCheck/when.kt.173 +++ /dev/null @@ -1,14 +0,0 @@ -// INTENTION_TEXT: Surround with if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { ... } -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection - -import android.graphics.drawable.VectorDrawable - -class VectorDrawableProvider { - val flag = false - fun getVectorDrawable(): VectorDrawable { - return when (flag) { - true -> VectorDrawable() - else -> VectorDrawable() - } - } -} \ No newline at end of file diff --git a/idea/testData/android/lintQuickfix/targetVersionCheck/when.kt.expected.173 b/idea/testData/android/lintQuickfix/targetVersionCheck/when.kt.expected.173 deleted file mode 100644 index bfe5397edec..00000000000 --- a/idea/testData/android/lintQuickfix/targetVersionCheck/when.kt.expected.173 +++ /dev/null @@ -1,19 +0,0 @@ -// INTENTION_TEXT: Surround with if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { ... } -// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection - -import android.graphics.drawable.VectorDrawable -import android.os.Build - -class VectorDrawableProvider { - val flag = false - fun getVectorDrawable(): VectorDrawable { - return when (flag) { - true -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - VectorDrawable() - } else { - TODO("VERSION.SDK_INT < LOLLIPOP") - } - else -> VectorDrawable() - } - } -} \ No newline at end of file diff --git a/idea/testData/copyPaste/plainTextConversion/IntoComment.expected.kt.173 b/idea/testData/copyPaste/plainTextConversion/IntoComment.expected.kt.173 deleted file mode 100644 index aeb948e53f0..00000000000 --- a/idea/testData/copyPaste/plainTextConversion/IntoComment.expected.kt.173 +++ /dev/null @@ -1,2 +0,0 @@ -// ArrayList list = new ArrayList(); -// NO_CONVERSION_EXPECTED \ No newline at end of file diff --git a/idea/testData/editor/quickDoc/AnonymousObjectLocalVariable.kt.173 b/idea/testData/editor/quickDoc/AnonymousObjectLocalVariable.kt.173 deleted file mode 100644 index 886d34b5118..00000000000 --- a/idea/testData/editor/quickDoc/AnonymousObjectLocalVariable.kt.173 +++ /dev/null @@ -1,9 +0,0 @@ -interface OurFace -open class OurClass - -fun context() { - val v = object : OurClass(), OurFace {} - v -} - -//INFO:
val v: <anonymous object : OurClass, OurFace>
diff --git a/idea/testData/editor/quickDoc/AtConstantWithUnderscore.kt.173 b/idea/testData/editor/quickDoc/AtConstantWithUnderscore.kt.173 deleted file mode 100644 index 81ca171d352..00000000000 --- a/idea/testData/editor/quickDoc/AtConstantWithUnderscore.kt.173 +++ /dev/null @@ -1,12 +0,0 @@ -class C { - /** Use [SOME_REFERENCED_VAL] to do something */ - fun foo() { - - } - - companion object { - val SOME_REFERENCED_VAL = 1 - } -} - -//INFO:
public final fun foo(): Unit defined in C

Use SOME_REFERENCED_VAL to do something

diff --git a/idea/testData/editor/quickDoc/AtFunctionParameter.kt.173 b/idea/testData/editor/quickDoc/AtFunctionParameter.kt.173 deleted file mode 100644 index 2c63d9afe0a..00000000000 --- a/idea/testData/editor/quickDoc/AtFunctionParameter.kt.173 +++ /dev/null @@ -1,3 +0,0 @@ -fun some(f: (Int) -> String) : String? = null - -//INFO:
value-parameter f: (Int) → String
diff --git a/idea/testData/editor/quickDoc/AtImplicitLambdaParametEnd.kt.173 b/idea/testData/editor/quickDoc/AtImplicitLambdaParametEnd.kt.173 deleted file mode 100644 index a2116c0cda2..00000000000 --- a/idea/testData/editor/quickDoc/AtImplicitLambdaParametEnd.kt.173 +++ /dev/null @@ -1,7 +0,0 @@ -fun foo() { - listOf(1).forEach { - println(it) - } -} - -//INFO:
value-parameter it: Int
diff --git a/idea/testData/editor/quickDoc/AtImplicitLambdaParameter.kt.173 b/idea/testData/editor/quickDoc/AtImplicitLambdaParameter.kt.173 deleted file mode 100644 index 9e988b29111..00000000000 --- a/idea/testData/editor/quickDoc/AtImplicitLambdaParameter.kt.173 +++ /dev/null @@ -1,7 +0,0 @@ -fun foo() { - listOf(1).forEach { - println(it) - } -} - -//INFO:
value-parameter it: Int
diff --git a/idea/testData/editor/quickDoc/AtLocalFunction.kt.173 b/idea/testData/editor/quickDoc/AtLocalFunction.kt.173 deleted file mode 100644 index 63bb7dce809..00000000000 --- a/idea/testData/editor/quickDoc/AtLocalFunction.kt.173 +++ /dev/null @@ -1,9 +0,0 @@ -fun context() { - fun local() { - - } - - local() -} - -//INFO:
local final fun local(): Unit
diff --git a/idea/testData/editor/quickDoc/AtTypeParameter.kt.173 b/idea/testData/editor/quickDoc/AtTypeParameter.kt.173 deleted file mode 100644 index bb239791a0b..00000000000 --- a/idea/testData/editor/quickDoc/AtTypeParameter.kt.173 +++ /dev/null @@ -1,5 +0,0 @@ -interface Base - -class Some<T: Base> - -//INFO:
<T : Base> defined in Some
diff --git a/idea/testData/editor/quickDoc/AtVariableDeclaration.kt.173 b/idea/testData/editor/quickDoc/AtVariableDeclaration.kt.173 deleted file mode 100644 index 61e7d6aae90..00000000000 --- a/idea/testData/editor/quickDoc/AtVariableDeclaration.kt.173 +++ /dev/null @@ -1,8 +0,0 @@ -fun some() : String? = null - -fun test() { - val test = some() -} - - -//INFO:
val test: String?
diff --git a/idea/testData/editor/quickDoc/ConstructorVarParameter.kt.173 b/idea/testData/editor/quickDoc/ConstructorVarParameter.kt.173 deleted file mode 100644 index e0550f31bc9..00000000000 --- a/idea/testData/editor/quickDoc/ConstructorVarParameter.kt.173 +++ /dev/null @@ -1,7 +0,0 @@ -class C(var v: Int) { - fun foo() { - print(v) - } -} - -//INFO:
public final var v: Int defined in C
diff --git a/idea/testData/editor/quickDoc/EscapeHtmlInsideCodeBlocks.kt.173 b/idea/testData/editor/quickDoc/EscapeHtmlInsideCodeBlocks.kt.173 deleted file mode 100644 index 4a2c308b672..00000000000 --- a/idea/testData/editor/quickDoc/EscapeHtmlInsideCodeBlocks.kt.173 +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Code block: - * ``` kotlin - * A - * ``` - * Code span: - * `` is type parameter - */ -class A - -//INFO:
public final class A<T> defined in root package in file EscapeHtmlInsideCodeBlocks.kt

Code block:

-//INFO:

-//INFO: A<T>
-//INFO: 

Code span: <T> is type parameter

diff --git a/idea/testData/editor/quickDoc/ExtensionReceiver.kt.173 b/idea/testData/editor/quickDoc/ExtensionReceiver.kt.173 deleted file mode 100644 index b48eb25c8f6..00000000000 --- a/idea/testData/editor/quickDoc/ExtensionReceiver.kt.173 +++ /dev/null @@ -1,10 +0,0 @@ - -interface Foo - -fun foo(a: Any) {} - -fun Foo.bar() { - foo(this) -} - -//INFO:
public fun Foo.bar(): Unit defined in root package in file ExtensionReceiver.kt
diff --git a/idea/testData/editor/quickDoc/ExtensionReceiverEnd.kt.173 b/idea/testData/editor/quickDoc/ExtensionReceiverEnd.kt.173 deleted file mode 100644 index d3e5b5e5d0e..00000000000 --- a/idea/testData/editor/quickDoc/ExtensionReceiverEnd.kt.173 +++ /dev/null @@ -1,10 +0,0 @@ - -interface Foo - -fun foo(a: Any) {} - -fun Foo.bar() { - foo(this) -} - -//INFO:
public fun Foo.bar(): Unit defined in root package in file ExtensionReceiverEnd.kt
diff --git a/idea/testData/editor/quickDoc/IndentedCodeBlock.kt.173 b/idea/testData/editor/quickDoc/IndentedCodeBlock.kt.173 deleted file mode 100644 index c854f80022f..00000000000 --- a/idea/testData/editor/quickDoc/IndentedCodeBlock.kt.173 +++ /dev/null @@ -1,22 +0,0 @@ -/** - * val a = A() - * println(a) // comment - * ``` - * Code_block - * ``` - * val b = B() - * println(b) - * some text content - * - * Indented code block with tab - * Second line - */ -class A - -//INFO:
public final class A defined in root package in file IndentedCodeBlock.kt

val a = A()
-//INFO: println(a) // comment

-//INFO: <fenced>Code_block</fenced>
-//INFO: 
val b = B()
-//INFO: println(b)

some text content

-//INFO:
Indented code block with tab
-//INFO: 	Second line
diff --git a/idea/testData/editor/quickDoc/JavaClassUsedInKotlin.kt.173 b/idea/testData/editor/quickDoc/JavaClassUsedInKotlin.kt.173 deleted file mode 100644 index f905d3ee993..00000000000 --- a/idea/testData/editor/quickDoc/JavaClassUsedInKotlin.kt.173 +++ /dev/null @@ -1,8 +0,0 @@ -fun testing() { - SomeClass>() -} - -//INFO:
public class SomeClass<T extends List>
-//INFO: extends Object
-//INFO: Some Java Class -//INFO:
Type parameters:
<T> -
diff --git a/idea/testData/editor/quickDoc/JavaDocFromOverridenClass.kt.173 b/idea/testData/editor/quickDoc/JavaDocFromOverridenClass.kt.173 deleted file mode 100644 index 6d54330807d..00000000000 --- a/idea/testData/editor/quickDoc/JavaDocFromOverridenClass.kt.173 +++ /dev/null @@ -1,9 +0,0 @@ -class A : OverrideMe() { - override fun overrideMe() { - } -} - - -//INFO:
protected open fun overrideMe(): Unit defined in A
Description copied from class: OverrideMe
-//INFO: Some comment -//INFO:
Overrides:
overrideMe in class OverrideMe
diff --git a/idea/testData/editor/quickDoc/JavaDocFromOverridenInterface.kt.173 b/idea/testData/editor/quickDoc/JavaDocFromOverridenInterface.kt.173 deleted file mode 100644 index 3581f116c53..00000000000 --- a/idea/testData/editor/quickDoc/JavaDocFromOverridenInterface.kt.173 +++ /dev/null @@ -1,9 +0,0 @@ -class A : OverrideMe { - override fun overrideMe() { - } -} - - -//INFO:
public open fun overrideMe(): Unit defined in A
Description copied from interface: OverrideMe
-//INFO: Some comment -//INFO:
Specified by:
overrideMe in interface OverrideMe
diff --git a/idea/testData/editor/quickDoc/JavaMethodUsedInKotlin.kt.173 b/idea/testData/editor/quickDoc/JavaMethodUsedInKotlin.kt.173 deleted file mode 100644 index 4d95c59736e..00000000000 --- a/idea/testData/editor/quickDoc/JavaMethodUsedInKotlin.kt.173 +++ /dev/null @@ -1,13 +0,0 @@ -fun ktTest() { - Test.foo("SomeTest") -} - -//INFO: Test
@Contract(pure = true) 
-//INFO: @NotNull 
-//INFO: public static Object[] foo(String param)
-//INFO: Java Method -//INFO: -//INFO: Inferred annotations available:
-//INFO: diff --git a/idea/testData/editor/quickDoc/KotlinClassUsedFromJava.java.173 b/idea/testData/editor/quickDoc/KotlinClassUsedFromJava.java.173 deleted file mode 100644 index cf31cfc0c75..00000000000 --- a/idea/testData/editor/quickDoc/KotlinClassUsedFromJava.java.173 +++ /dev/null @@ -1,9 +0,0 @@ -import testing.Test; - -class KotlinClassUsedFromJava { - void test() { - Test(); - } -} - -//INFO:
public final class Test defined in testing in file KotlinClassUsedFromJava_Data.kt

Some comment

diff --git a/idea/testData/editor/quickDoc/KotlinPackageClassUsedFromJava.java.173 b/idea/testData/editor/quickDoc/KotlinPackageClassUsedFromJava.java.173 deleted file mode 100644 index 1471e1049a4..00000000000 --- a/idea/testData/editor/quickDoc/KotlinPackageClassUsedFromJava.java.173 +++ /dev/null @@ -1,10 +0,0 @@ -import testing.KotlinPackageClassUsedFromJava_DataKt; - -class KotlinPackageClassUsedFromJava { - void test() { - KotlinPackageClassUsedFromJava_DataKt.foo(); - } -} - -//INFO: testing
public final class testing.KotlinPackageClassUsedFromJava_DataKt
-//INFO: extends Object
diff --git a/idea/testData/editor/quickDoc/MethodFromStdLib.kt.173 b/idea/testData/editor/quickDoc/MethodFromStdLib.kt.173 deleted file mode 100644 index 132a734ce0d..00000000000 --- a/idea/testData/editor/quickDoc/MethodFromStdLib.kt.173 +++ /dev/null @@ -1,5 +0,0 @@ -fun test() { - listOf(1, 2, 4).filter { it > 0 } -} - -//INFO:
public inline fun <T> Iterable<T>.filter(predicate: (T) → Boolean): List<T> defined in kotlin.collections in file CollectionsKt.class

Returns a list containing only elements matching the given predicate.

diff --git a/idea/testData/editor/quickDoc/OnClassDeclarationWithNoPackage.kt.173 b/idea/testData/editor/quickDoc/OnClassDeclarationWithNoPackage.kt.173 deleted file mode 100644 index 62c5d412472..00000000000 --- a/idea/testData/editor/quickDoc/OnClassDeclarationWithNoPackage.kt.173 +++ /dev/null @@ -1,6 +0,0 @@ -/** - * Useful comment - */ -class Some - -//INFO:
public final class Some defined in root package in file OnClassDeclarationWithNoPackage.kt

Useful comment

diff --git a/idea/testData/editor/quickDoc/OnEnumClassReference.kt.173 b/idea/testData/editor/quickDoc/OnEnumClassReference.kt.173 deleted file mode 100644 index dfb14429e45..00000000000 --- a/idea/testData/editor/quickDoc/OnEnumClassReference.kt.173 +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Useless one - */ -enum class SomeEnum - -fun use() { - SomeEnum::class -} - -//INFO:
public final enum class SomeEnum : Enum<SomeEnum> defined in root package in file OnEnumClassReference.kt

Useless one

diff --git a/idea/testData/editor/quickDoc/OnEnumDeclaration.kt.173 b/idea/testData/editor/quickDoc/OnEnumDeclaration.kt.173 deleted file mode 100644 index fa04d7a560a..00000000000 --- a/idea/testData/editor/quickDoc/OnEnumDeclaration.kt.173 +++ /dev/null @@ -1,6 +0,0 @@ -/** - * Useless one - */ -enum class SomeEnum - -//INFO:
public final enum class SomeEnum : Enum<SomeEnum> defined in root package in file OnEnumDeclaration.kt

Useless one

diff --git a/idea/testData/editor/quickDoc/OnEnumEntry.kt.173 b/idea/testData/editor/quickDoc/OnEnumEntry.kt.173 deleted file mode 100644 index bfd7d3bd39b..00000000000 --- a/idea/testData/editor/quickDoc/OnEnumEntry.kt.173 +++ /dev/null @@ -1,7 +0,0 @@ -enum class TestEnum{ - A, B, C -} - - - -//INFO:
enum entry C defined in TestEnum
Enum constant ordinal: 2 diff --git a/idea/testData/editor/quickDoc/OnEnumEntryUsage.kt.173 b/idea/testData/editor/quickDoc/OnEnumEntryUsage.kt.173 deleted file mode 100644 index 0c1419055c7..00000000000 --- a/idea/testData/editor/quickDoc/OnEnumEntryUsage.kt.173 +++ /dev/null @@ -1,9 +0,0 @@ -enum class TestEnum{ - A, B, C -} - -fun test() { - TestEnum.C -} - -//INFO:
enum entry C defined in TestEnum
Enum constant ordinal: 2 diff --git a/idea/testData/editor/quickDoc/OnEnumUsage.kt.173 b/idea/testData/editor/quickDoc/OnEnumUsage.kt.173 deleted file mode 100644 index 117618fc88f..00000000000 --- a/idea/testData/editor/quickDoc/OnEnumUsage.kt.173 +++ /dev/null @@ -1,12 +0,0 @@ -/** - * Enum of 1, 2 - */ -enum class SomeEnum(val i: Int) { - One(1), Two(2); -} - -fun use() { - SomeEnum.One -} - -//INFO:
public final enum class SomeEnum : Enum<SomeEnum> defined in root package in file OnEnumUsage.kt

Enum of 1, 2

diff --git a/idea/testData/editor/quickDoc/OnEnumValueOfFunction.kt.173 b/idea/testData/editor/quickDoc/OnEnumValueOfFunction.kt.173 deleted file mode 100644 index cf38cac14f0..00000000000 --- a/idea/testData/editor/quickDoc/OnEnumValueOfFunction.kt.173 +++ /dev/null @@ -1,11 +0,0 @@ -enum class E { - A -} - -fun use() { - E.valueOf("A") -} - - -//INFO: public final fun valueOf(value: String): E defined in E

Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)

-//INFO:
Throws:
IllegalArgumentException - if this enum type has no constant with the specified name
diff --git a/idea/testData/editor/quickDoc/OnEnumValuesFunction.kt.173 b/idea/testData/editor/quickDoc/OnEnumValuesFunction.kt.173 deleted file mode 100644 index ed70854ab83..00000000000 --- a/idea/testData/editor/quickDoc/OnEnumValuesFunction.kt.173 +++ /dev/null @@ -1,9 +0,0 @@ -enum class E { - -} - -fun use() { - E.values() -} - -//INFO: public final fun values(): Array<E> defined in E

Returns an array containing the constants of this enum type, in the order they're declared. This method may be used to iterate over the constants.

diff --git a/idea/testData/editor/quickDoc/OnFunctionDeclarationWithPackage.kt.173 b/idea/testData/editor/quickDoc/OnFunctionDeclarationWithPackage.kt.173 deleted file mode 100644 index b5695d06cf8..00000000000 --- a/idea/testData/editor/quickDoc/OnFunctionDeclarationWithPackage.kt.173 +++ /dev/null @@ -1,16 +0,0 @@ -package test - -/** - - * - * - * Test function - - * - * @param first Some - * @param second Other - */ -fun testFun(first: String, second: Int) = 12 - -//INFO:
public fun testFun(first: String, second: Int): Int defined in test in file OnFunctionDeclarationWithPackage.kt

Test function

-//INFO:
Parameters:
first - Some
second - Other
diff --git a/idea/testData/editor/quickDoc/OnInheritedMethodUsage.kt.173 b/idea/testData/editor/quickDoc/OnInheritedMethodUsage.kt.173 deleted file mode 100644 index ceb71bce1fa..00000000000 --- a/idea/testData/editor/quickDoc/OnInheritedMethodUsage.kt.173 +++ /dev/null @@ -1,17 +0,0 @@ -open class C() { - /** - * This method returns zero. - */ - open fun foo(): Int = 0 -} - -class D(): C() { - override fun foo(): Int = 1 -} - - -fun test() { - D().foo() -} - -//INFO:
public open fun foo(): Int defined in D

This method returns zero.

diff --git a/idea/testData/editor/quickDoc/OnInheritedPropertyUsage.kt.173 b/idea/testData/editor/quickDoc/OnInheritedPropertyUsage.kt.173 deleted file mode 100644 index ab9c857aa27..00000000000 --- a/idea/testData/editor/quickDoc/OnInheritedPropertyUsage.kt.173 +++ /dev/null @@ -1,17 +0,0 @@ -open class C() { - /** - * This property returns zero. - */ - open val foo: Int get() = 0 -} - -class D(): C() { - override val foo: Int get() = 1 -} - - -fun test() { - D().foo -} - -//INFO:
public open val foo: Int defined in D

This property returns zero.

diff --git a/idea/testData/editor/quickDoc/OnMethodUsage.kt.173 b/idea/testData/editor/quickDoc/OnMethodUsage.kt.173 deleted file mode 100644 index d7dd575d3a8..00000000000 --- a/idea/testData/editor/quickDoc/OnMethodUsage.kt.173 +++ /dev/null @@ -1,16 +0,0 @@ -/** -Some documentation - - * @param a Some int - * @param b String - */ -fun testMethod(a: Int, b: String) { - -} - -fun test() { - testMethod(1, "value") -} - -//INFO:
public fun testMethod(a: Int, b: String): Unit defined in root package in file OnMethodUsage.kt

Some documentation

-//INFO:
Parameters:
a - Some int
b - String
diff --git a/idea/testData/editor/quickDoc/OnMethodUsageMultiline.kt.173 b/idea/testData/editor/quickDoc/OnMethodUsageMultiline.kt.173 deleted file mode 100644 index 38bac449780..00000000000 --- a/idea/testData/editor/quickDoc/OnMethodUsageMultiline.kt.173 +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Some documentation - * on two lines. - */ -fun testMethod() { - -} - -fun test() { - testMethod() -} - -//INFO:
public fun testMethod(): Unit defined in root package in file OnMethodUsageMultiline.kt

Some documentation on two lines.

diff --git a/idea/testData/editor/quickDoc/OnMethodUsageWithBracketsInParam.kt.173 b/idea/testData/editor/quickDoc/OnMethodUsageWithBracketsInParam.kt.173 deleted file mode 100644 index f2ed28dcccf..00000000000 --- a/idea/testData/editor/quickDoc/OnMethodUsageWithBracketsInParam.kt.173 +++ /dev/null @@ -1,16 +0,0 @@ -/** -Some documentation - - * @param[a] Some int - * @param[b] String - */ -fun testMethod(a: Int, b: String) { - -} - -fun test() { - testMethod(1, "value") -} - -//INFO:
public fun testMethod(a: Int, b: String): Unit defined in root package in file OnMethodUsageWithBracketsInParam.kt

Some documentation

-//INFO:
Parameters:
a - Some int
b - String
diff --git a/idea/testData/editor/quickDoc/OnMethodUsageWithCodeBlock.kt.173 b/idea/testData/editor/quickDoc/OnMethodUsageWithCodeBlock.kt.173 deleted file mode 100644 index a1b336ec2e9..00000000000 --- a/idea/testData/editor/quickDoc/OnMethodUsageWithCodeBlock.kt.173 +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Some documentation. - * - * ``` - * Code block - * Second line - * - * Third line - * ``` - * - * Text between code blocks. - * ``` - * ``` - * Text after code block. - */ -fun testMethod() { - -} - -class C { -} - -fun test() { - testMethod(1, "value") -} - -//INFO:
public fun testMethod(): Unit defined in root package in file OnMethodUsageWithCodeBlock.kt

Some documentation.

-//INFO:

-//INFO: Code block
-//INFO:     Second line
-//INFO:
-//INFO: Third line
-//INFO: 

Text between code blocks.

-//INFO:

-//INFO: 

Text after code block.

diff --git a/idea/testData/editor/quickDoc/OnMethodUsageWithMarkdown.kt.173 b/idea/testData/editor/quickDoc/OnMethodUsageWithMarkdown.kt.173 deleted file mode 100644 index 654a5126fdc..00000000000 --- a/idea/testData/editor/quickDoc/OnMethodUsageWithMarkdown.kt.173 +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Some documentation. **Bold** *underline* `code` foo: bar (baz) [quux] 'apos' - * - * [Kotlin](http://www.kotlinlang.org) - * [a**b**__d__ kas ](http://www.ibm.com) - * - * [C] - * - * [See **this** class][C] - * - * This is _emphasized text_ but text_with_underscores has to preserve the underscores. - * Single stars embedded in a word like Embedded*Star have to be preserved as well. - * - * Exclamation marks are also important! Also in `code blocks!` - * - * bt+ : ``prefix ` postfix`` - * backslash: `\` - */ -fun testMethod() { - -} - -class C { -} - -fun test() { - testMethod(1, "value") -} - -//INFO:
public fun testMethod(): Unit defined in root package in file OnMethodUsageWithMarkdown.kt

Some documentation. Bold underline code foo: bar (baz) quux 'apos'

-//INFO:

Kotlin abd kas

-//INFO:

C

-//INFO:

See this class

-//INFO:

This is emphasized text but text_with_underscores has to preserve the underscores. Single stars embedded in a word like Embedded*Star have to be preserved as well.

-//INFO:

Exclamation marks are also important! Also in code blocks!

-//INFO:

bt+ : prefix ` postfix backslash: \

diff --git a/idea/testData/editor/quickDoc/OnMethodUsageWithMultilineParam.kt.173 b/idea/testData/editor/quickDoc/OnMethodUsageWithMultilineParam.kt.173 deleted file mode 100644 index ff2fb1dd5c5..00000000000 --- a/idea/testData/editor/quickDoc/OnMethodUsageWithMultilineParam.kt.173 +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Some documentation - * on two lines. - * - * @param test String - * on two lines - */ -fun testMethod(test: String) { -} - -fun test() { - testMethod("") -} - -//INFO:
public fun testMethod(test: String): Unit defined in root package in file OnMethodUsageWithMultilineParam.kt

Some documentation on two lines.

-//INFO:
Parameters:
test - String on two lines
\ No newline at end of file diff --git a/idea/testData/editor/quickDoc/OnMethodUsageWithReceiver.kt.173 b/idea/testData/editor/quickDoc/OnMethodUsageWithReceiver.kt.173 deleted file mode 100644 index 104f1be6ad4..00000000000 --- a/idea/testData/editor/quickDoc/OnMethodUsageWithReceiver.kt.173 +++ /dev/null @@ -1,19 +0,0 @@ -/** -Some documentation - - * @receiver Some int - * @param b String - * @return Return [a] and nothing else - */ -fun Int.testMethod(b: String) { - -} - -fun test() { - 1.testMethod("value") -} - -//INFO:
public fun Int.testMethod(b: String): Unit defined in root package in file OnMethodUsageWithReceiver.kt

Some documentation

-//INFO:
Receiver:
Some int
-//INFO:
Parameters:
b - String
-//INFO:
Returns:
Return a and nothing else
diff --git a/idea/testData/editor/quickDoc/OnMethodUsageWithReturnAndLink.kt.173 b/idea/testData/editor/quickDoc/OnMethodUsageWithReturnAndLink.kt.173 deleted file mode 100644 index ee1b9160c38..00000000000 --- a/idea/testData/editor/quickDoc/OnMethodUsageWithReturnAndLink.kt.173 +++ /dev/null @@ -1,18 +0,0 @@ -/** -Some documentation - - * @param a Some int - * @param b String - * @return Return [a] and nothing else - */ -fun testMethod(a: Int, b: String) { - -} - -fun test() { - testMethod(1, "value") -} - -//INFO:
public fun testMethod(a: Int, b: String): Unit defined in root package in file OnMethodUsageWithReturnAndLink.kt

Some documentation

-//INFO:
Parameters:
a - Some int
b - String
-//INFO:
Returns:
Return a and nothing else
diff --git a/idea/testData/editor/quickDoc/OnMethodUsageWithReturnAndThrows.kt.173 b/idea/testData/editor/quickDoc/OnMethodUsageWithReturnAndThrows.kt.173 deleted file mode 100644 index e868dfa30c3..00000000000 --- a/idea/testData/editor/quickDoc/OnMethodUsageWithReturnAndThrows.kt.173 +++ /dev/null @@ -1,20 +0,0 @@ -/** -Some documentation - - * @param a Some int - * @param b String - * @return Return value - * @throws IllegalArgumentException if the weather is bad - */ -fun testMethod(a: Int, b: String) { - -} - -fun test() { - testMethod(1, "value") -} - -//INFO:
public fun testMethod(a: Int, b: String): Unit defined in root package in file OnMethodUsageWithReturnAndThrows.kt

Some documentation

-//INFO:
Parameters:
a - Some int
b - String
-//INFO:
Returns:
Return value
-//INFO:
Throws:
IllegalArgumentException - if the weather is bad
diff --git a/idea/testData/editor/quickDoc/OnMethodUsageWithSee.kt.173 b/idea/testData/editor/quickDoc/OnMethodUsageWithSee.kt.173 deleted file mode 100644 index 65956d8f011..00000000000 --- a/idea/testData/editor/quickDoc/OnMethodUsageWithSee.kt.173 +++ /dev/null @@ -1,21 +0,0 @@ -/** - * @see C - * @see D - * @see kotlin - */ -fun testMethod() { - -} - -class C { -} - -class D { -} - -fun test() { - testMethod(1, "value") -} - -//INFO:
public fun testMethod(): Unit defined in root package in file OnMethodUsageWithSee.kt

-//INFO:
See Also:
C, D, kotlin
diff --git a/idea/testData/editor/quickDoc/OnMethodUsageWithTypeParameter.kt.173 b/idea/testData/editor/quickDoc/OnMethodUsageWithTypeParameter.kt.173 deleted file mode 100644 index eab08dbc61f..00000000000 --- a/idea/testData/editor/quickDoc/OnMethodUsageWithTypeParameter.kt.173 +++ /dev/null @@ -1,17 +0,0 @@ -/** -Some documentation - - * @param T the type parameter - * @param a Some int - * @param b String - */ -fun testMethod(a: Int, b: String) { - -} - -fun test() { - testMethod(1, "value") -} - -//INFO:
public fun <T> testMethod(a: Int, b: String): Unit defined in root package in file OnMethodUsageWithTypeParameter.kt

Some documentation

-//INFO:
Parameters:
T - the type parameter
a - Some int
b - String
diff --git a/idea/testData/editor/quickDoc/Samples.kt.173 b/idea/testData/editor/quickDoc/Samples.kt.173 deleted file mode 100644 index d285fdc3487..00000000000 --- a/idea/testData/editor/quickDoc/Samples.kt.173 +++ /dev/null @@ -1,28 +0,0 @@ -package magic - -object Samples { - fun sampleMagic() { - castTextSpell("[asd] [dse] [asz]") - } -} - -fun sampleScroll() { - val reader = Scroll("[asd] [dse] [asz]").reader() - castTextSpell(reader.readAll()) -} - -/** - * @sample Samples.sampleMagic - * @sample sampleScroll - */ -fun castTextSpell(spell: String) { - throw SecurityException("Magic prohibited outside Hogwarts") -} - -//INFO:
public fun castTextSpell(spell: String): Unit defined in magic in file Samples.kt

-//INFO:
Samples:
Samples.sampleMagic

-//INFO: castTextSpell("[asd] [dse] [asz]")
-//INFO: 
sampleScroll

-//INFO: val reader = Scroll("[asd] [dse] [asz]").reader()
-//INFO: castTextSpell(reader.readAll())
-//INFO: 
diff --git a/idea/testData/editor/quickDoc/TopLevelMethodFromJava.java.173 b/idea/testData/editor/quickDoc/TopLevelMethodFromJava.java.173 deleted file mode 100644 index 7e8e13aa306..00000000000 --- a/idea/testData/editor/quickDoc/TopLevelMethodFromJava.java.173 +++ /dev/null @@ -1,11 +0,0 @@ -package server - -import some.TopLevelMethodFromJava_DataKt - -class Testing { - void test() { - TopLevelMethodFromJava_DataKt.foo(12); - } -} - -//INFO:
public fun foo(bar: Int): Unit defined in some in file TopLevelMethodFromJava_Data.kt

KDoc foo

diff --git a/idea/testData/editor/quickDoc/TypeNamesFromStdLibNavigation.kt.173 b/idea/testData/editor/quickDoc/TypeNamesFromStdLibNavigation.kt.173 deleted file mode 100644 index 37a73ee27b1..00000000000 --- a/idea/testData/editor/quickDoc/TypeNamesFromStdLibNavigation.kt.173 +++ /dev/null @@ -1,11 +0,0 @@ -class A { - -} - -fun foo(x : A) { } - -fun main(args: Array) { - foo() -} - -//INFO:
public fun foo(x: A): Unit defined in root package in file TypeNamesFromStdLibNavigation.kt
diff --git a/idea/testData/quickfix/abstract/abstractFunctionWithBodyWithComments2.kt.after.173 b/idea/testData/quickfix/abstract/abstractFunctionWithBodyWithComments2.kt.after.173 deleted file mode 100644 index cb337570a03..00000000000 --- a/idea/testData/quickfix/abstract/abstractFunctionWithBodyWithComments2.kt.after.173 +++ /dev/null @@ -1,5 +0,0 @@ -// "Remove function body" "true" -abstract class A() { - /*1*/ - abstract fun foo() // 3 -} diff --git a/idea/testData/quickfix/unusedSuppressAnnotation/simple.kt.173 b/idea/testData/quickfix/unusedSuppressAnnotation/simple.kt.173 deleted file mode 100644 index 70b02417c61..00000000000 --- a/idea/testData/quickfix/unusedSuppressAnnotation/simple.kt.173 +++ /dev/null @@ -1,7 +0,0 @@ -// "Suppress for declarations annotated by 'xxx.XXX'" "true" -package xxx - -annotation class XXX - -@XXX -class UnusedClass diff --git a/idea/testData/quickfix/unusedSuppressAnnotation/simple.kt.after.173 b/idea/testData/quickfix/unusedSuppressAnnotation/simple.kt.after.173 deleted file mode 100644 index 70b02417c61..00000000000 --- a/idea/testData/quickfix/unusedSuppressAnnotation/simple.kt.after.173 +++ /dev/null @@ -1,7 +0,0 @@ -// "Suppress for declarations annotated by 'xxx.XXX'" "true" -package xxx - -annotation class XXX - -@XXX -class UnusedClass diff --git a/idea/testData/refactoring/move/java/moveClass/callableReferences/nestedToTopLevel/after/foo/NestedJava.java.173 b/idea/testData/refactoring/move/java/moveClass/callableReferences/nestedToTopLevel/after/foo/NestedJava.java.173 deleted file mode 100644 index 7838151aaca..00000000000 --- a/idea/testData/refactoring/move/java/moveClass/callableReferences/nestedToTopLevel/after/foo/NestedJava.java.173 +++ /dev/null @@ -1,3 +0,0 @@ -package foo; - -public class NestedJava {} \ No newline at end of file diff --git a/idea/testData/refactoring/move/java/moveClass/callableReferences/nestedToTopLevelAndAnotherPackage/after/bar/NestedJava.java.173 b/idea/testData/refactoring/move/java/moveClass/callableReferences/nestedToTopLevelAndAnotherPackage/after/bar/NestedJava.java.173 deleted file mode 100644 index 38714288dad..00000000000 --- a/idea/testData/refactoring/move/java/moveClass/callableReferences/nestedToTopLevelAndAnotherPackage/after/bar/NestedJava.java.173 +++ /dev/null @@ -1,3 +0,0 @@ -package bar; - -public class NestedJava {} \ No newline at end of file diff --git a/idea/testData/refactoring/move/java/moveClass/moveInnerToTop/moveNestedClassToTopLevelInAnotherPackage/after/b/X.java.173 b/idea/testData/refactoring/move/java/moveClass/moveInnerToTop/moveNestedClassToTopLevelInAnotherPackage/after/b/X.java.173 deleted file mode 100644 index ebc16c54769..00000000000 --- a/idea/testData/refactoring/move/java/moveClass/moveInnerToTop/moveNestedClassToTopLevelInAnotherPackage/after/b/X.java.173 +++ /dev/null @@ -1,5 +0,0 @@ -package b; - -public class X { - -} \ No newline at end of file diff --git a/idea/testData/refactoring/move/java/moveClass/moveInnerToTop/moveNestedClassToTopLevelInTheSamePackage/after/a/X.java.173 b/idea/testData/refactoring/move/java/moveClass/moveInnerToTop/moveNestedClassToTopLevelInTheSamePackage/after/a/X.java.173 deleted file mode 100644 index 76a017d26d4..00000000000 --- a/idea/testData/refactoring/move/java/moveClass/moveInnerToTop/moveNestedClassToTopLevelInTheSamePackage/after/a/X.java.173 +++ /dev/null @@ -1,5 +0,0 @@ -package a; - -public class X { - -} \ No newline at end of file diff --git a/idea/testData/refactoring/move/java/moveClass/moveInnerToTop/moveNestedClassToTopLevelInTheSamePackageAndAddOuterInstance/after/a/X.java.173 b/idea/testData/refactoring/move/java/moveClass/moveInnerToTop/moveNestedClassToTopLevelInTheSamePackageAndAddOuterInstance/after/a/X.java.173 deleted file mode 100644 index 81517efca14..00000000000 --- a/idea/testData/refactoring/move/java/moveClass/moveInnerToTop/moveNestedClassToTopLevelInTheSamePackageAndAddOuterInstance/after/a/X.java.173 +++ /dev/null @@ -1,10 +0,0 @@ -package a; - -public class X { - private A outer; - - public X(A outer, String s) { - this.outer = outer; - System.out.println(s); - } -} \ No newline at end of file diff --git a/idea/testData/refactoring/move/java/moveClass/moveInnerToTop/moveNestedClassToTopLevelInTheSamePackageAndAddOuterInstanceWithLambda/after/a/X.java.173 b/idea/testData/refactoring/move/java/moveClass/moveInnerToTop/moveNestedClassToTopLevelInTheSamePackageAndAddOuterInstanceWithLambda/after/a/X.java.173 deleted file mode 100644 index 1209b9aa3d4..00000000000 --- a/idea/testData/refactoring/move/java/moveClass/moveInnerToTop/moveNestedClassToTopLevelInTheSamePackageAndAddOuterInstanceWithLambda/after/a/X.java.173 +++ /dev/null @@ -1,12 +0,0 @@ -package a; - -import kotlin.jvm.functions.Function0; - -public class X { - private A outer; - - public X(A outer, Function0 f) { - this.outer = outer; - System.out.println(f.invoke()); - } -} \ No newline at end of file diff --git a/idea/testData/refactoring/move/java/moveClass/moveInnerToTop/moveNestedClassToTopLevelInTheSamePackageAndRename/after/a/Y.java.173 b/idea/testData/refactoring/move/java/moveClass/moveInnerToTop/moveNestedClassToTopLevelInTheSamePackageAndRename/after/a/Y.java.173 deleted file mode 100644 index 9e6d828af80..00000000000 --- a/idea/testData/refactoring/move/java/moveClass/moveInnerToTop/moveNestedClassToTopLevelInTheSamePackageAndRename/after/a/Y.java.173 +++ /dev/null @@ -1,5 +0,0 @@ -package a; - -public class Y { - -} \ No newline at end of file diff --git a/idea/testData/refactoring/safeDelete/deleteClass/kotlinClass/trait2.kt.messages.173 b/idea/testData/refactoring/safeDelete/deleteClass/kotlinClass/trait2.kt.messages.173 deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/idea/tests/org/jetbrains/kotlin/asJava/KtFileLightClassTest.kt.173 b/idea/tests/org/jetbrains/kotlin/asJava/KtFileLightClassTest.kt.173 deleted file mode 100644 index f910a608643..00000000000 --- a/idea/tests/org/jetbrains/kotlin/asJava/KtFileLightClassTest.kt.173 +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2010-2015 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.asJava - -import com.intellij.psi.search.GlobalSearchScope -import com.intellij.testFramework.LightProjectDescriptor -import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase -import org.jetbrains.kotlin.idea.test.KotlinLightProjectDescriptor -import org.jetbrains.kotlin.idea.test.PluginTestCaseBase -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.psi.KtFile - -class KtFileLightClassTest : KotlinLightCodeInsightFixtureTestCase() { - override fun getProjectDescriptor(): LightProjectDescriptor = KotlinLightProjectDescriptor.INSTANCE - - fun testSimple() { - val file = myFixture.configureByText("A.kt", "class C {}\nobject O {}") as KtFile - val classes = file.classes - assertEquals(2, classes.size) - assertEquals("C", classes[0].qualifiedName) - assertEquals("O", classes[1].qualifiedName) - } - - fun testFileClass() { - val file = myFixture.configureByText("A.kt", "fun f() {}") as KtFile - val classes = file.classes - assertEquals(1, classes.size) - assertEquals("AKt", classes[0].qualifiedName) - } - - fun testMultifileClass() { - val file = myFixture.configureByFiles("multifile1.kt", "multifile2.kt")[0] as KtFile - val aClass = file.classes.single() - assertEquals(1, aClass.findMethodsByName("foo", false).size) - assertEquals(1, aClass.findMethodsByName("bar", false).size) - } - - fun testAliasesOnly() { - val file = myFixture.configureByFile("aliasesOnly.kt") as KtFile - val aClass = file.classes.single() - assertEquals(0, aClass.getMethods().size) - } - - fun testNoFacadeForScript() { - val file = myFixture.configureByText("foo.kts", "package foo") as KtFile - assertEquals(0, file.classes.size) - val facadeFiles = KotlinAsJavaSupport.getInstance(project).findFilesForFacade(FqName("foo.FooKt"), GlobalSearchScope.allScope(project)) - assertEquals(0, facadeFiles.size) - } - - fun testNoFacadeForHeaderClass() { - val file = myFixture.configureByText("foo.kt", "header fun foo(): Int") as KtFile - assertEquals(0, file.classes.size) - val facadeFiles = KotlinAsJavaSupport.getInstance(project).findFilesForFacade(FqName("foo.FooKt"), GlobalSearchScope.allScope(project)) - assertEquals(0, facadeFiles.size) - } - - override fun getTestDataPath(): String { - return PluginTestCaseBase.getTestDataPathBase() + "/asJava/fileLightClass/" - } -} diff --git a/idea/tests/org/jetbrains/kotlin/asJava/KtLightAnnotationTest.kt.173 b/idea/tests/org/jetbrains/kotlin/asJava/KtLightAnnotationTest.kt.173 deleted file mode 100644 index 78f9c10df93..00000000000 --- a/idea/tests/org/jetbrains/kotlin/asJava/KtLightAnnotationTest.kt.173 +++ /dev/null @@ -1,778 +0,0 @@ -/* - * 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.kotlin.asJava - -import com.intellij.openapi.application.WriteAction -import com.intellij.openapi.application.runWriteAction -import com.intellij.openapi.command.CommandProcessor -import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProviderImpl -import com.intellij.psi.* -import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReference -import com.intellij.psi.search.GlobalSearchScope -import com.intellij.testFramework.LightProjectDescriptor -import com.intellij.testFramework.UsefulTestCase -import junit.framework.TestCase -import org.jetbrains.kotlin.asJava.elements.KtLightAnnotationForSourceEntry -import org.jetbrains.kotlin.asJava.elements.KtLightPsiArrayInitializerMemberValue -import org.jetbrains.kotlin.config.LanguageFeature -import org.jetbrains.kotlin.idea.completion.test.assertInstanceOf -import org.jetbrains.kotlin.idea.facet.configureFacet -import org.jetbrains.kotlin.idea.facet.getOrCreateFacet -import org.jetbrains.kotlin.idea.search.projectScope -import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase -import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor - -class KtLightAnnotationTest : KotlinLightCodeInsightFixtureTestCase() { - - override fun getProjectDescriptor(): LightProjectDescriptor = KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE - - fun testBooleanAnnotationDefaultValue() { - myFixture.addClass(""" - import java.lang.annotation.ElementType; - import java.lang.annotation.Target; - - @Target(ElementType.FIELD) - public @interface Autowired { - boolean required() default true; - } - """.trimIndent()) - - myFixture.configureByText("AnnotatedClass.kt", """ - class AnnotatedClass{ - @Autowired - lateinit var bean: String - } - """.trimIndent()) - myFixture.testHighlighting("Autowired.java", "AnnotatedClass.kt") - - val annotations = myFixture.findClass("AnnotatedClass").fields.single() - .expectAnnotations(2).single { it.qualifiedName == "Autowired" } - val annotationAttributeVal = annotations.findAttributeValue("required") as PsiElement - assertTextRangeAndValue("true", true, annotationAttributeVal) - } - - fun testStringAnnotationWithUnnamedParameter() { - myFixture.addClass(""" - import java.lang.annotation.ElementType; - import java.lang.annotation.Target; - - @Target(ElementType.PARAMETER) - public @interface Qualifier { - String value(); - } - """.trimIndent()) - - myFixture.configureByText("AnnotatedClass.kt", """ - class AnnotatedClass { - fun bar(@Qualifier("foo") param: String){} - } - """.trimIndent()) - myFixture.testHighlighting("Qualifier.java", "AnnotatedClass.kt") - - val annotation = myFixture.findClass("AnnotatedClass").methods.first { it.name == "bar" }.parameterList.parameters.single() - .expectAnnotations(2).single { it.qualifiedName == "Qualifier" } - val annotationAttributeVal = annotation.findAttributeValue("value") as PsiExpression - TestCase.assertTrue(annotationAttributeVal.isPhysical) - assertTextRangeAndValue("\"foo\"", "foo", annotationAttributeVal) - TestCase.assertEquals( - PsiType.getJavaLangString(psiManager, GlobalSearchScope.everythingScope(project)), - annotationAttributeVal.type - ) - } - - fun testAnnotationsInAnnotationsDeclarations() { - myFixture.addClass(""" - public @interface OuterAnnotation { - InnerAnnotation attribute(); - @interface InnerAnnotation { - } - } - """.trimIndent()) - - myFixture.configureByText("AnnotatedClass.kt", """ - @OuterAnnotation(attribute = OuterAnnotation.InnerAnnotation()) - open class AnnotatedClass - """.trimIndent()) - myFixture.testHighlighting("OuterAnnotation.java", "AnnotatedClass.kt") - - val annotations = myFixture.findClass("AnnotatedClass").expectAnnotations(1) - val annotationAttributeVal = annotations.first().findAttributeValue("attribute") as PsiElement - assertTextAndRange("InnerAnnotation()", annotationAttributeVal) - UsefulTestCase.assertInstanceOf(annotationAttributeVal.parent, PsiNameValuePair::class.java) - } - - fun testConstants() { - myFixture.addClass( - """ - public @interface StringAnnotation { - String value(); - } - """.trimIndent() - ) - myFixture.addClass( - """ - public class Constants { - - public static final String MY_CONSTANT = "67"; - } - - """.trimIndent() - ) - - myFixture.configureByText( - "AnnotatedClass.kt", """ - @StringAnnotation(Constants.MY_CONSTANT) - open class AnnotatedClass - """.trimIndent() - ) - myFixture.testHighlighting("AnnotatedClass.kt") - - val annotations = myFixture.findClass("AnnotatedClass").expectAnnotations(1) - val annotationAttributeVal = annotations.first().findAttributeValue("value") as PsiLiteral - assertTextAndRange("Constants.MY_CONSTANT", annotationAttributeVal) - TestCase.assertEquals("67", annotationAttributeVal.value) - TestCase.assertEquals( - PsiType.getJavaLangString(psiManager, GlobalSearchScope.everythingScope(project)), - (annotationAttributeVal as PsiExpression).type - ) - } - - - fun testLiteralReplace() { - myFixture.addClass( - """ - public @interface StringAnnotation { - String value(); - } - """.trimIndent() - ) - - myFixture.configureByText( - "AnnotatedClass.kt", """ - @StringAnnotation("oldValue") - open class AnnotatedClass - """.trimIndent() - ) - myFixture.testHighlighting("AnnotatedClass.kt") - - val annotations = myFixture.findClass("AnnotatedClass").expectAnnotations(1) - val annotationAttributeVal = annotations.first().findAttributeValue("value") as PsiLiteral - assertTextAndRange("\"oldValue\"", annotationAttributeVal) - TestCase.assertEquals("oldValue", annotationAttributeVal.value) - runWriteAction { - CommandProcessor.getInstance().runUndoTransparentAction { - annotationAttributeVal.replace( - JavaPsiFacade.getElementFactory(project).createExpressionFromText("\"newValue\"", annotationAttributeVal) - ) - } - } - myFixture.checkResult( - """ - @StringAnnotation("newValue") - open class AnnotatedClass - """.trimIndent() - ) - } - - fun testReferences() { - myFixture.addClass( - """ - public @interface StringAnnotation { - String value(); - } - """.trimIndent() - ) - - myFixture.configureByText( - "AnnotatedClass.kt", """ - @StringAnnotation("someText") - open class AnnotatedClass - """.trimIndent() - ) - myFixture.testHighlighting("AnnotatedClass.kt") - - val annotations = myFixture.findClass("AnnotatedClass").expectAnnotations(1) - val annotationAttributeVal = annotations.first().findAttributeValue("value") as PsiLiteral - assertTextAndRange("\"someText\"", annotationAttributeVal) - TestCase.assertTrue( - "String literal references should be available via light literal", - annotationAttributeVal.references.any { - /* FileReferences are injected in every string, so we use them as indicator that KtElement references are available there */ - it is FileReference - }) - } - - fun testClassLiteral() { - myFixture.addClass( - """ - public @interface ClazzAnnotation { - Class cls(); - } - """.trimIndent() - ) - - myFixture.configureByText( - "AnnotatedClass.kt", """ - @ClazzAnnotation(cls = String::class) - class AnnotatedClass - """.trimIndent() - ) - myFixture.testHighlighting("AnnotatedClass.kt") - - val annotations = myFixture.findClass("AnnotatedClass").expectAnnotations(1) - val annotationAttributeVal = annotations.first().findAttributeValue("cls") as PsiClassObjectAccessExpression - assertTextAndRange("String::class", annotationAttributeVal) - TestCase.assertEquals( - PsiType.getJavaLangString(myFixture.psiManager, GlobalSearchScope.everythingScope(project)), - annotationAttributeVal.operand.type - ) - } - - fun testArrayOfClassLiterals() { - myFixture.addClass( - """ - public @interface ClazzAnnotation { - Class[] cls(); - } - """.trimIndent() - ) - - myFixture.configureByText( - "AnnotatedClass.kt", """ - @ClazzAnnotation(cls = [String::class, Throwable::class, ShortArray::class, Array>::class, Long::class, Unit::class]) - class AnnotatedClass - """.trimIndent() - ) - myFixture.testHighlighting("AnnotatedClass.kt") - - val annotations = myFixture.findClass("AnnotatedClass").expectAnnotations(1) - val annotationAttributeVal = annotations.first().findAttributeValue("cls") as KtLightPsiArrayInitializerMemberValue - assertTextAndRange( - "[String::class, Throwable::class, ShortArray::class, Array>::class, Long::class, Unit::class]", - annotationAttributeVal - ) - val classLiterals = annotationAttributeVal.initializers.toList().map { it as PsiClassObjectAccessExpression } - val scope = GlobalSearchScope.everythingScope(project) - TestCase.assertEquals( - listOf( - PsiType.getJavaLangString(myFixture.psiManager, scope), - PsiType.getTypeByName("java.lang.Throwable", project, scope), - PsiType.SHORT.createArrayType(), - PsiType.getTypeByName("java.lang.Integer", project, scope).createArrayType().createArrayType(), - PsiType.LONG, - PsiType.getTypeByName("kotlin.Unit", project, scope) - ), - classLiterals.map { it.operand.type } - ) - } - - fun testAnnotationsInAnnotationsArrayDeclarations() { - myFixture.addClass(""" - public @interface OuterAnnotation { - InnerAnnotation[] attributes(); - @interface InnerAnnotation { - } - } - """.trimIndent()) - - myFixture.configureByText("AnnotatedClass.kt", """ - @OuterAnnotation(attributes = arrayOf(OuterAnnotation.InnerAnnotation())) - open class AnnotatedClass - """.trimIndent()) - myFixture.testHighlighting("OuterAnnotation.java", "AnnotatedClass.kt") - - val annotations = myFixture.findClass("AnnotatedClass").expectAnnotations(1) - val annotationAttributeVal = annotations.first().findAttributeValue("attributes") as PsiArrayInitializerMemberValue - assertTextAndRange("arrayOf(OuterAnnotation.InnerAnnotation())", annotationAttributeVal) - assertTextAndRange("InnerAnnotation()", annotationAttributeVal.initializers[0]) - } - - - fun testAnnotationsInAnnotationsFinalDeclarations() { - myFixture.addClass(""" - public @interface OuterAnnotation { - InnerAnnotation attribute(); - @interface InnerAnnotation { - } - } - """.trimIndent()) - - myFixture.configureByText("AnnotatedClass.kt", """ - @OuterAnnotation(attribute = OuterAnnotation.InnerAnnotation()) - class AnnotatedClass - """.trimIndent()) - myFixture.testHighlighting("OuterAnnotation.java", "AnnotatedClass.kt") - - val annotations = myFixture.findClass("AnnotatedClass").expectAnnotations(1) - val annotationAttributeVal = annotations.first().findAttributeValue("attribute") as PsiElement - assertTextAndRange("InnerAnnotation()", annotationAttributeVal) - UsefulTestCase.assertInstanceOf(annotationAttributeVal.parent, PsiNameValuePair::class.java) - } - - fun testAnnotationsInAnnotationsInAnnotationsDeclarations() { - myFixture.addClass(""" - public @interface OuterAnnotation { - InnerAnnotation attribute(); - @interface InnerAnnotation { - InnerInnerAnnotation attribute(); - @interface InnerInnerAnnotation { - } - } - } - """.trimIndent()) - - myFixture.configureByText("AnnotatedClass.kt", """ - @OuterAnnotation(attribute = OuterAnnotation.InnerAnnotation(attribute = OuterAnnotation.InnerAnnotation.InnerInnerAnnotation())) - open class AnnotatedClass //There is another exception if class is not open - """.trimIndent()) - myFixture.testHighlighting("OuterAnnotation.java", "AnnotatedClass.kt") - - val annotations = myFixture.findClass("AnnotatedClass").expectAnnotations(1) - val annotationAttributeVal = annotations.first().findAttributeValue("attribute") as PsiElement - assertTextAndRange("InnerAnnotation(attribute = OuterAnnotation.InnerAnnotation.InnerInnerAnnotation())", annotationAttributeVal) - - annotationAttributeVal as PsiAnnotation - val innerAnnotationAttributeVal = annotationAttributeVal.findAttributeValue("attribute") as PsiElement - assertTextAndRange("InnerInnerAnnotation()", innerAnnotationAttributeVal) - } - - fun testKotlinAnnotations() { - myFixture.configureByText("AnnotatedClass.kt", """ - annotation class Anno1(val anno2: Anno2) - annotation class Anno2(val anno3: Anno3) - annotation class Anno3 - - @Anno1(Anno2(Anno3())) - class AnnotatedClass - """.trimIndent()) - myFixture.testHighlighting("AnnotatedClass.kt") - - val annotations = myFixture.findClass("AnnotatedClass").expectAnnotations(1) - val annotationAttributeVal = annotations.first().findAttributeValue("anno2") as PsiElement - assertTextAndRange("Anno2(Anno3())", annotationAttributeVal) - - annotationAttributeVal as PsiAnnotation - val innerAnnotationAttributeVal = annotationAttributeVal.findAttributeValue("anno3") as PsiElement - assertTextAndRange("Anno3()", innerAnnotationAttributeVal) - assertIsKtLightAnnotation("Anno3()", innerAnnotationAttributeVal) - } - - fun testKotlinAnnotationWithStringArray() { - myFixture.configureByText("AnnotatedClass.kt", """ - annotation class Anno(val params: Array) - @Anno(arrayOf("abc", "def")) - class AnnotatedClass - """.trimIndent()) - myFixture.testHighlighting("AnnotatedClass.kt") - - val annotations = myFixture.findClass("AnnotatedClass").expectAnnotations(1) - val annotationAttributeVal = annotations.first().findAttributeValue("params") as PsiElement - UsefulTestCase.assertInstanceOf(annotationAttributeVal.parent, PsiNameValuePair::class.java) - TestCase.assertTrue(annotations.first().parameterList.attributes.any { (it.value == annotationAttributeVal) }) - assertTextAndRange("arrayOf(\"abc\", \"def\")", annotationAttributeVal) - - annotationAttributeVal as PsiArrayInitializerMemberValue - assertTextAndRange("\"abc\"", annotationAttributeVal.initializers[0]) - assertTextAndRange("\"def\"", annotationAttributeVal.initializers[1]) - } - - fun testKotlinAnnotationWithStringArrayLiteral() { - configureKotlinVersion("1.2") - myFixture.configureByText("AnnotatedClass.kt", """ - annotation class Anno(val params: Array) - @Anno(params = ["abc", "def"]) - class AnnotatedClass - """.trimIndent()) - myFixture.testHighlighting("AnnotatedClass.kt") - - val annotations = myFixture.findClass("AnnotatedClass").expectAnnotations(1) - val annotationAttributeVal = annotations.first().findAttributeValue("params") as PsiElement - assertTextAndRange("[\"abc\", \"def\"]", annotationAttributeVal) - - annotationAttributeVal as PsiArrayInitializerMemberValue - assertTextAndRange("\"abc\"", annotationAttributeVal.initializers[0].assertInstanceOf()) - assertTextAndRange("\"def\"", annotationAttributeVal.initializers[1]) - } - - - fun testKotlinAnnotationsArray() { - myFixture.configureByText("AnnotatedClass.kt", """ - annotation class Anno1(val anno2: Array) - annotation class Anno2(val v:Int) - - @Anno1(anno2 = arrayOf(Anno2(1), Anno2(2))) - class AnnotatedClass - """.trimIndent()) - myFixture.testHighlighting("AnnotatedClass.kt") - - val annotation = myFixture.findClass("AnnotatedClass").expectAnnotations(1).single() - - val annotationAttributeVal = annotation.findAttributeValue("anno2") as PsiArrayInitializerMemberValue - annotationAttributeVal.parent.assertInstanceOf().let { pair -> - TestCase.assertEquals("anno2", pair.name) - } - - assertTextAndRange("arrayOf(Anno2(1), Anno2(2))", annotationAttributeVal) - annotationAttributeVal.initializers[0].let { innerAnnotationAttributeVal -> - assertTextAndRange("Anno2(1)", innerAnnotationAttributeVal) - assertIsKtLightAnnotation("Anno2(1)", innerAnnotationAttributeVal) - innerAnnotationAttributeVal as PsiAnnotation - val value = innerAnnotationAttributeVal.findAttributeValue("v").assertInstanceOf() - assertTextAndRange("1", value) - TestCase.assertEquals(PsiType.INT, value.assertInstanceOf().type) - } - - - val attributeValueFromParameterList = annotation.parameterList.attributes.single().value as PsiArrayInitializerMemberValue - assertTextAndRange("arrayOf(Anno2(1), Anno2(2))", attributeValueFromParameterList) - attributeValueFromParameterList.initializers[0].let { innerAnnotationAttributeVal -> - assertTextAndRange("Anno2(1)", innerAnnotationAttributeVal) - assertIsKtLightAnnotation("Anno2(1)", innerAnnotationAttributeVal) - } - - } - - fun testVarargAnnotation() { - - myFixture.configureByText("Outer.java", """ - @interface Outer{ - Inner[] value() default {}; - } - - @interface Inner{ - } - """) - myFixture.configureByText("AnnotatedClass.kt", """ - @Outer(Inner()) - class MyAnnotated {} - """.trimIndent()) - - val annotations = myFixture.findClass("MyAnnotated").expectAnnotations(1) - annotations[0].let { annotation -> - val annotationAttributeVal = annotation.findAttributeValue("value") as PsiElement - assertTextAndRange("Inner()", annotationAttributeVal) - annotationAttributeVal as PsiArrayInitializerMemberValue - annotationAttributeVal.initializers[0].let { innerAnnotationAttributeVal -> - assertTextAndRange("Inner()", innerAnnotationAttributeVal) - assertIsKtLightAnnotation("Inner()", innerAnnotationAttributeVal) - } - UsefulTestCase.assertInstanceOf(annotationAttributeVal.parent, PsiNameValuePair::class.java) - TestCase.assertTrue(annotation.parameterList.attributes.any { it.value == annotationAttributeVal }) - } - - } - - private fun doVarargTest(type: String, parameters: List) { - val paramsJoined = parameters.joinToString(", ") - - myFixture.addClass( - """ - public @interface Annotation { - $type[] value() default {}; - } - """.trimIndent() - ) - - myFixture.configureByText( - "AnnotatedClass.kt", """ - @Annotation($paramsJoined) - open class AnnotatedClass - """.trimIndent() - ) - myFixture.testHighlighting("Annotation.java", "AnnotatedClass.kt") - - val annotations = myFixture.findClass("AnnotatedClass").expectAnnotations(1) - val annotationAttributeVal = annotations.first().findAttributeValue("value") as PsiArrayInitializerMemberValue - assertTextAndRange("($paramsJoined)", annotationAttributeVal) - UsefulTestCase.assertInstanceOf(annotationAttributeVal.parent, PsiNameValuePair::class.java) - for ((i, arg) in parameters.withIndex()) { - assertTextAndRange(arg, annotationAttributeVal.initializers[i]) - } - } - - - fun testVarargInt() = doVarargTest("int", listOf("1", "2", "3")) - - fun testVarargClasses() = doVarargTest("""Class""", listOf("Any::class", "String::class", "Int::class")) - - fun testVarargWithSpread() { - myFixture.addClass(""" - public @interface Annotation { - String[] value(); - } - """.trimIndent()) - - myFixture.configureByText("AnnotatedClass.kt", """ - @Annotation(value = *arrayOf("a", "b", "c")) - open class AnnotatedClass - """.trimIndent()) - myFixture.testHighlighting("Annotation.java", "AnnotatedClass.kt") - - val annotations = myFixture.findClass("AnnotatedClass").expectAnnotations(1) - val annotationAttributeVal = annotations.first().findAttributeValue("value") as PsiArrayInitializerMemberValue - assertTextAndRange("arrayOf(\"a\", \"b\", \"c\")", annotationAttributeVal) - UsefulTestCase.assertInstanceOf(annotationAttributeVal.parent, PsiNameValuePair::class.java) - for ((i, arg) in listOf("\"a\"", "\"b\"", "\"c\"").withIndex()) { - assertTextAndRange(arg, annotationAttributeVal.initializers[i]) - } - } - - fun testVarargWithSpreadComplex() { - myFixture.addClass(""" - public @interface Annotation { - String[] value(); - } - """.trimIndent()) - - myFixture.configureByText("AnnotatedClass.kt", """ - @Annotation(value = arrayOf(*arrayOf("a", "b"), "c", *arrayOf("d", "e"))) - open class AnnotatedClass - """.trimIndent()) - myFixture.testHighlighting("Annotation.java", "AnnotatedClass.kt") - - val annotations = myFixture.findClass("AnnotatedClass").expectAnnotations(1) - val annotationAttributeVal = annotations.first().findAttributeValue("value") as PsiArrayInitializerMemberValue - assertTextAndRange("arrayOf(*arrayOf(\"a\", \"b\"), \"c\", *arrayOf(\"d\", \"e\"))", annotationAttributeVal) - UsefulTestCase.assertInstanceOf(annotationAttributeVal.parent, PsiNameValuePair::class.java) - for ((i, arg) in listOf("arrayOf(\"a\", \"b\")", "\"c\"", "arrayOf(\"d\", \"e\")").withIndex()) { - assertTextAndRange(arg, annotationAttributeVal.initializers[i]) - } - } - - fun testVarargWithArrayLiteral() { - myFixture.addClass(""" - public @interface Annotation { - String[] value(); - } - """.trimIndent()) - - myFixture.configureByText("AnnotatedClass.kt", """ - @Annotation(value = ["a", "b", "c"]) - open class AnnotatedClass - """.trimIndent()) - myFixture.testHighlighting("Annotation.java", "AnnotatedClass.kt") - - val annotations = myFixture.findClass("AnnotatedClass").expectAnnotations(1) - val annotationAttributeVal = annotations.first().findAttributeValue("value") as PsiArrayInitializerMemberValue - assertTextAndRange("[\"a\", \"b\", \"c\"]", annotationAttributeVal) - UsefulTestCase.assertInstanceOf(annotationAttributeVal.parent, PsiNameValuePair::class.java) - for ((i, arg) in listOf("\"a\"", "\"b\"", "\"c\"").withIndex()) { - assertTextAndRange(arg, annotationAttributeVal.initializers[i]) - } - } - - fun testVarargWithSingleArg() { - myFixture.addClass(""" - public @interface Annotation { - String[] value(); - } - """.trimIndent()) - - myFixture.configureByText("AnnotatedClass.kt", """ - @Annotation(value = "a") - open class AnnotatedClass - """.trimIndent()) - myFixture.testHighlighting("Annotation.java", "AnnotatedClass.kt") - - val annotations = myFixture.findClass("AnnotatedClass").expectAnnotations(1) - val annotationAttributeVal = annotations.first().findAttributeValue("value") as PsiArrayInitializerMemberValue - assertTextAndRange("\"a\"", annotationAttributeVal) - UsefulTestCase.assertInstanceOf(annotationAttributeVal.parent, PsiNameValuePair::class.java) - for ((i, arg) in listOf("\"a\"").withIndex()) { - assertTextAndRange(arg, annotationAttributeVal.initializers[i]) - } - } - - fun testVarargWithArrayLiteralAndSpread() { - myFixture.addClass(""" - public @interface Annotation { - String[] value(); - } - """.trimIndent()) - - myFixture.configureByText("AnnotatedClass.kt", """ - @Annotation(*["a", "b", "c"]) - open class AnnotatedClass - """.trimIndent()) - myFixture.testHighlighting("Annotation.java", "AnnotatedClass.kt") - - val annotations = myFixture.findClass("AnnotatedClass").expectAnnotations(1) - val annotationAttributeVal = annotations.first().findAttributeValue("value") as PsiArrayInitializerMemberValue - assertTextAndRange("[\"a\", \"b\", \"c\"]", annotationAttributeVal) - for ((i, arg) in listOf("\"a\"", "\"b\"", "\"c\"").withIndex()) { - assertTextAndRange(arg, annotationAttributeVal.initializers[i]) - } - } - - fun testRepeatableAnnotationsArray() { - - myFixture.configureByText("RAnno.java", """ - import java.lang.annotation.Repeatable; - - @interface RContainer{ - RAnno[] value() default {}; - } - - @Repeatable(RContainer.class) - public @interface RAnno { - String[] value() default {}; - } - """) - myFixture.configureByText("AnnotatedClass.kt", """ - @RAnno() - @RAnno("1") - @RAnno("1", "2") - class AnnotatedClass - """.trimIndent()) - - val annotations = myFixture.findClass("AnnotatedClass").expectAnnotations(3) - annotations[0].let { annotation -> - val annotationAttributeVal = annotation.findAttributeValue("value") as PsiElement - assertTextAndRange("{}", annotationAttributeVal) - annotationAttributeVal as PsiArrayInitializerMemberValue - TestCase.assertTrue(annotationAttributeVal.initializers.isEmpty()) - } - annotations[1].let { annotation -> - val annotationAttributeVal = annotation.findAttributeValue("value") as PsiElement - assertTextAndRange("\"1\"", annotationAttributeVal) - annotationAttributeVal as PsiArrayInitializerMemberValue - annotationAttributeVal.initializers[0].let { innerAnnotationAttributeVal -> - assertTextAndRange("\"1\"", innerAnnotationAttributeVal) - } - } - annotations[2].let { annotation -> - val annotationAttributeVal = annotation.findAttributeValue("value") as PsiElement - assertTextAndRange("(\"1\", \"2\")", annotationAttributeVal) - annotationAttributeVal as PsiArrayInitializerMemberValue - annotationAttributeVal.initializers[0].let { innerAnnotationAttributeVal -> - assertTextAndRange("\"1\"", innerAnnotationAttributeVal) - } - annotationAttributeVal.initializers[1].let { innerAnnotationAttributeVal -> - assertTextAndRange("\"2\"", innerAnnotationAttributeVal) - } - } - - } - - fun testJavaKeywordsInName() { - myFixture.configureByText( - "AnnotatedClass.kt", """ - package my.public.place - - annotation class Anno1(val import: String) - - @Anno1(import = "full") - class AnnotatedClass - """.trimIndent() - ) - - val annotations = myFixture.findClass("my.public.place.AnnotatedClass").expectAnnotations(1) - val annotation = annotations.first() - TestCase.assertEquals("my.public.place.Anno1", annotation.qualifiedName) - assertTextAndRange("\"full\"", annotation.findAttributeValue("import")!!) - } - - fun testWrongNamesPassed() { - myFixture.configureByText("AnnotatedClass.kt", """ - annotation class Anno1(val i:Int , val j: Int) - - @Anno1(k = 3, l = 5) - class AnnotatedClass - """.trimIndent()) - - val annotations = myFixture.findClass("AnnotatedClass").expectAnnotations(1) - val annotation = annotations.first() - TestCase.assertNull(annotation.findAttributeValue("k")) - TestCase.assertNull(annotation.findAttributeValue("l")) - TestCase.assertNull(annotation.findAttributeValue("i")) - TestCase.assertNull(annotation.findAttributeValue("j")) - } - - fun testWrongValuesPassed() { - myFixture.configureByText("AnnotatedClass.kt", """ - annotation class Anno1(val i: Int , val j: Int) - - @Anno1(i = true, j = false) - class AnnotatedClass - """.trimIndent()) - - val annotations = myFixture.findClass("AnnotatedClass").expectAnnotations(1) - val annotation = annotations.first() - assertTextAndRange("true", annotation.findAttributeValue("i")!!) - assertTextAndRange("false", annotation.findAttributeValue("j")!!) - } - - fun testDuplicateParameters() { - myFixture.configureByText("AnnotatedClass.kt", """ - annotation class Anno1(val i:Int , val i: Boolean) - - @Anno1(i = true, i = 3) - class AnnotatedClass - """.trimIndent()) - - val annotations = myFixture.findClass("AnnotatedClass").expectAnnotations(1) - val annotation = annotations.first() - assertTextAndRange("true", annotation.findAttributeValue("i")!!) - } - - fun testMissingDefault() { - myFixture.configureByText("AnnotatedClass.kt", """ - annotation class Anno1(val i: Int = 0) - - @Anno1() - class AnnotatedClass - """.trimIndent()) - - val (annotation) = myFixture.findClass("AnnotatedClass").expectAnnotations(1) - assertTextAndRange("0", annotation.findAttributeValue("i")!!) - } - - private fun assertTextAndRange(expected: String, psiElement: PsiElement) { - TestCase.assertEquals("mismatch for $psiElement of ${psiElement.javaClass}", expected, psiElement.text) - TestCase.assertEquals(expected, psiElement.textRange.substring(psiElement.containingFile.text)) - } - - private fun assertIsKtLightAnnotation(expected: String, psiElement: PsiElement) { - TestCase.assertEquals(expected, (psiElement as KtLightAnnotationForSourceEntry).kotlinOrigin.text) - } - - private fun assertTextRangeAndValue(expected: String, value: Any?, psiElement: PsiElement) { - assertTextAndRange(expected, psiElement) - val result = JavaPsiFacade.getInstance(project).constantEvaluationHelper.computeConstantExpression(psiElement) - TestCase.assertEquals(value, result) - val smartPointer = SmartPointerManager.getInstance(psiElement.project).createSmartPsiElementPointer(psiElement) - assertTextAndRange(expected, smartPointer.element!!) - } - - private fun PsiModifierListOwner.expectAnnotations(number: Int): Array = - this.modifierList!!.annotations.apply { - assertEquals( - "expected $number annotation(s), found [${this.joinToString(", ") { it.qualifiedName ?: "unknown" }}]", - number, size - ) - } - - private fun configureKotlinVersion(version: String) { - WriteAction.run { - val modelsProvider = IdeModifiableModelsProviderImpl(project) - val facet = module.getOrCreateFacet(modelsProvider, useProjectSettings = false) - facet.configureFacet(version, LanguageFeature.State.DISABLED, null, modelsProvider) - modelsProvider.commit() - } - } - -} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/configuration/AbstractConfigureKotlinInTempDirTest.kt.173 b/idea/tests/org/jetbrains/kotlin/idea/configuration/AbstractConfigureKotlinInTempDirTest.kt.173 deleted file mode 100644 index 4c62b7c502c..00000000000 --- a/idea/tests/org/jetbrains/kotlin/idea/configuration/AbstractConfigureKotlinInTempDirTest.kt.173 +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license - * that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.idea.configuration - -import com.intellij.openapi.util.io.FileUtil -import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime -import org.junit.Assert -import java.io.File -import java.io.IOException - -abstract class AbstractConfigureKotlinInTempDirTest : AbstractConfigureKotlinTest() { - @Throws(IOException::class) - override fun getIprFile(): File { - val tempDir = FileUtil.generateRandomTemporaryPath() - FileUtil.createTempDirectory("temp", null) - - FileUtil.copyDir(File(projectRoot), tempDir) - - val kotlinRuntime = File(tempDir, "lib/kotlin-stdlib.jar") - if (getTestName(true).toLowerCase().contains("latestruntime") && kotlinRuntime.exists()) { - ForTestCompileRuntime.runtimeJarForTests().copyTo(kotlinRuntime, overwrite = true) - } - - val projectRoot = tempDir.path - - val projectFilePath = projectRoot + "/projectFile.ipr" - if (!File(projectFilePath).exists()) { - val dotIdeaPath = projectRoot + "/.idea" - Assert.assertTrue("Project file or '.idea' dir should exists in " + projectRoot, File(dotIdeaPath).exists()) - return File(projectRoot) - } - return File(projectFilePath) - } -} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/configuration/AbstractConfigureKotlinTest.kt.173 b/idea/tests/org/jetbrains/kotlin/idea/configuration/AbstractConfigureKotlinTest.kt.173 deleted file mode 100644 index 90c0a8985d6..00000000000 --- a/idea/tests/org/jetbrains/kotlin/idea/configuration/AbstractConfigureKotlinTest.kt.173 +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Copyright 2010-2015 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.idea.configuration - -import com.intellij.openapi.application.ApplicationManager -import com.intellij.openapi.application.PathMacros -import com.intellij.openapi.module.Module -import com.intellij.openapi.module.ModuleManager -import com.intellij.openapi.project.Project -import com.intellij.openapi.projectRoots.ProjectJdkTable -import com.intellij.openapi.projectRoots.Sdk -import com.intellij.openapi.roots.ProjectRootManager -import com.intellij.openapi.util.io.FileUtil -import com.intellij.openapi.util.io.FileUtilRt -import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess -import com.intellij.testFramework.PlatformTestCase -import com.intellij.testFramework.UsefulTestCase -import junit.framework.TestCase -import org.jetbrains.kotlin.idea.configuration.KotlinWithLibraryConfigurator.FileState -import org.jetbrains.kotlin.idea.framework.KotlinSdkType -import org.jetbrains.kotlin.idea.test.PluginTestCaseBase -import org.jetbrains.kotlin.test.KotlinTestUtils -import org.jetbrains.kotlin.utils.PathUtil -import java.io.File -import java.io.IOException - -abstract class AbstractConfigureKotlinTest : PlatformTestCase() { - override fun setUp() { - super.setUp() - - VfsRootAccess.allowRootAccess(KotlinTestUtils.getHomeDirectory()) - } - - @Throws(Exception::class) - override fun tearDown() { - VfsRootAccess.disallowRootAccess(KotlinTestUtils.getHomeDirectory()) - PathMacros.getInstance().removeMacro(TEMP_DIR_MACRO_KEY) - - super.tearDown() - } - - @Throws(Exception::class) - override fun initApplication() { - super.initApplication() - - KotlinSdkType.setUpIfNeeded() - - ApplicationManager.getApplication().runWriteAction { - ProjectJdkTable.getInstance().addJdk(PluginTestCaseBase.mockJdk6()) - ProjectJdkTable.getInstance().addJdk(PluginTestCaseBase.mockJdk8()) - ProjectJdkTable.getInstance().addJdk(PluginTestCaseBase.mockJdk9()) - } - - PluginTestCaseBase.clearSdkTable(testRootDisposable) - - val tempLibDir = FileUtil.createTempDirectory("temp", null) - PathMacros.getInstance().setMacro(TEMP_DIR_MACRO_KEY, FileUtilRt.toSystemDependentName(tempLibDir.absolutePath)) - } - - protected fun doTestConfigureModulesWithNonDefaultSetup(configurator: KotlinWithLibraryConfigurator) { - assertNoFilesInDefaultPaths() - - val modules = modules - for (module in modules) { - assertNotConfigured(module, configurator) - } - - configurator.configure(myProject, emptyList()) - - assertNoFilesInDefaultPaths() - - for (module in modules) { - assertProperlyConfigured(module, configurator) - } - } - - protected fun doTestOneJavaModule(jarState: FileState) { - doTestOneModule(jarState, JAVA_CONFIGURATOR) - } - - protected fun doTestOneJsModule(jarState: FileState) { - doTestOneModule(jarState, JS_CONFIGURATOR) - } - - private fun doTestOneModule(jarState: FileState, configurator: KotlinWithLibraryConfigurator) { - val module = module - - assertNotConfigured(module, configurator) - configure(module, jarState, configurator) - assertProperlyConfigured(module, configurator) - } - - override fun getModule(): Module { - val modules = ModuleManager.getInstance(myProject).modules - assert(modules.size == 1) { "One module should be loaded " + modules.size } - myModule = modules[0] - return super.getModule() - } - - val modules: Array - get() = ModuleManager.getInstance(myProject).modules - - @Throws(IOException::class) - override fun getIprFile(): File { - val projectFilePath = projectRoot + "/projectFile.ipr" - TestCase.assertTrue("Project file should exists " + projectFilePath, File(projectFilePath).exists()) - return File(projectFilePath) - } - - @Throws(Exception::class) - override fun doCreateProject(projectFile: File): Project? { - return myProjectManager.loadProject(projectFile.path) - } - - private val projectName: String - get() { - val testName = getTestName(true) - return if (testName.contains("_")) { - testName.substring(0, testName.indexOf("_")) - } - else testName - } - - protected val projectRoot: String - get() = BASE_PATH + projectName - - override fun setUpModule() {} - - private fun assertNoFilesInDefaultPaths() { - UsefulTestCase.assertDoesntExist(File(JAVA_CONFIGURATOR.getDefaultPathToJarFile(project))) - UsefulTestCase.assertDoesntExist(File(JS_CONFIGURATOR.getDefaultPathToJarFile(project))) - } - - companion object { - private val BASE_PATH = "idea/testData/configuration/" - private val TEMP_DIR_MACRO_KEY = "TEMP_TEST_DIR" - protected val JAVA_CONFIGURATOR: KotlinJavaModuleConfigurator by lazy { - object : KotlinJavaModuleConfigurator() { - override fun getDefaultPathToJarFile(project: Project) = getPathRelativeToTemp("default_jvm_lib") - } - } - - protected val JS_CONFIGURATOR: KotlinJsModuleConfigurator by lazy { - object : KotlinJsModuleConfigurator() { - override fun getDefaultPathToJarFile(project: Project) = getPathRelativeToTemp("default_js_lib") - } - } - - private fun configure( - modules: List, - runtimeState: FileState, - configurator: KotlinWithLibraryConfigurator, - jarFromDist: String, - jarFromTemp: String - ) { - val project = modules.first().project - val collector = createConfigureKotlinNotificationCollector(project) - - val pathToJar = getPathToJar(runtimeState, jarFromDist, jarFromTemp) - for (module in modules) { - configurator.configureModule(module, pathToJar, pathToJar, collector, runtimeState) - } - collector.showNotification() - } - - private fun getPathToJar(runtimeState: FileState, jarFromDist: String, jarFromTemp: String) = when (runtimeState) { - KotlinWithLibraryConfigurator.FileState.EXISTS -> jarFromDist - KotlinWithLibraryConfigurator.FileState.COPY -> jarFromTemp - KotlinWithLibraryConfigurator.FileState.DO_NOT_COPY -> jarFromDist - } - - protected fun configure(module: Module, jarState: FileState, configurator: KotlinProjectConfigurator) { - if (configurator is KotlinJavaModuleConfigurator) { - configure(listOf(module), jarState, - configurator as KotlinWithLibraryConfigurator, - pathToExistentRuntimeJar, pathToNonexistentRuntimeJar) - } - if (configurator is KotlinJsModuleConfigurator) { - configure(listOf(module), jarState, - configurator as KotlinWithLibraryConfigurator, - pathToExistentJsJar, pathToNonexistentJsJar) - } - } - - private val pathToNonexistentRuntimeJar: String - get() { - val pathToTempKotlinRuntimeJar = FileUtil.getTempDirectory() + "/" + PathUtil.KOTLIN_JAVA_STDLIB_JAR - PlatformTestCase.myFilesToDelete.add(File(pathToTempKotlinRuntimeJar)) - return pathToTempKotlinRuntimeJar - } - - private val pathToNonexistentJsJar: String - get() { - val pathToTempKotlinRuntimeJar = FileUtil.getTempDirectory() + "/" + PathUtil.JS_LIB_JAR_NAME - PlatformTestCase.myFilesToDelete.add(File(pathToTempKotlinRuntimeJar)) - return pathToTempKotlinRuntimeJar - } - - private val pathToExistentRuntimeJar: String - get() = PathUtil.kotlinPathsForDistDirectory.stdlibPath.parent - - private val pathToExistentJsJar: String - get() = PathUtil.kotlinPathsForDistDirectory.jsStdLibJarPath.parent - - protected fun assertNotConfigured(module: Module, configurator: KotlinWithLibraryConfigurator) { - TestCase.assertFalse( - String.format("Module %s should not be configured as %s Module", module.name, configurator.presentableText), - configurator.isConfigured(module)) - } - - protected fun assertConfigured(module: Module, configurator: KotlinWithLibraryConfigurator) { - TestCase.assertTrue(String.format("Module %s should be configured with configurator '%s'", module.name, - configurator.presentableText), - configurator.isConfigured(module)) - } - - protected fun assertProperlyConfigured(module: Module, configurator: KotlinWithLibraryConfigurator) { - assertConfigured(module, configurator) - assertNotConfigured(module, getOppositeConfigurator(configurator)) - } - - private fun getOppositeConfigurator(configurator: KotlinWithLibraryConfigurator): KotlinWithLibraryConfigurator { - if (configurator === JAVA_CONFIGURATOR) return JS_CONFIGURATOR - if (configurator === JS_CONFIGURATOR) return JAVA_CONFIGURATOR - - throw IllegalArgumentException("Only JS_CONFIGURATOR and JAVA_CONFIGURATOR are supported") - } - - private fun getPathRelativeToTemp(relativePath: String): String { - val tempPath = PathMacros.getInstance().getValue(TEMP_DIR_MACRO_KEY) - return tempPath + '/' + relativePath - } - } - - override fun getTestProjectJdk(): Sdk { - val projectRootManager = ProjectRootManager.getInstance(project) - return projectRootManager.projectSdk ?: throw IllegalStateException("SDK ${projectRootManager.projectSdkName} was not found") - } -} diff --git a/idea/tests/org/jetbrains/kotlin/idea/configuration/ConfigureKotlinInTempDirTest.kt.173 b/idea/tests/org/jetbrains/kotlin/idea/configuration/ConfigureKotlinInTempDirTest.kt.173 deleted file mode 100644 index 8b51d3748b9..00000000000 --- a/idea/tests/org/jetbrains/kotlin/idea/configuration/ConfigureKotlinInTempDirTest.kt.173 +++ /dev/null @@ -1,128 +0,0 @@ -/* - * 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.kotlin.idea.configuration - -import com.intellij.openapi.application.ApplicationManager -import com.intellij.openapi.application.impl.ApplicationImpl -import org.jetbrains.kotlin.config.ApiVersion -import org.jetbrains.kotlin.config.KotlinFacetSettingsProvider -import org.jetbrains.kotlin.config.LanguageVersion -import org.jetbrains.kotlin.idea.compiler.configuration.Kotlin2JsCompilerArgumentsHolder -import org.jetbrains.kotlin.idea.compiler.configuration.KotlinCommonCompilerArgumentsHolder -import org.jetbrains.kotlin.idea.project.getLanguageVersionSettings -import org.jetbrains.kotlin.idea.project.languageVersionSettings -import org.junit.Assert -import java.io.IOException - -open class ConfigureKotlinInTempDirTest : AbstractConfigureKotlinInTempDirTest() { - @Throws(IOException::class) - fun testNoKotlincExistsNoSettingsRuntime10() { - val application = ApplicationManager.getApplication() as ApplicationImpl - application.doNotSave(false) - Assert.assertEquals(LanguageVersion.KOTLIN_1_0, module.languageVersionSettings.languageVersion) - Assert.assertEquals(LanguageVersion.KOTLIN_1_0, myProject.getLanguageVersionSettings(null).languageVersion) - application.saveAll() - Assert.assertTrue(project.baseDir.findFileByRelativePath(".idea/kotlinc.xml") == null) - } - - fun testNoKotlincExistsNoSettingsLatestRuntime() { - val application = ApplicationManager.getApplication() as ApplicationImpl - application.doNotSave(false) - Assert.assertEquals(LanguageVersion.LATEST_STABLE, module.languageVersionSettings.languageVersion) - Assert.assertEquals(LanguageVersion.LATEST_STABLE, myProject.getLanguageVersionSettings(null).languageVersion) - application.saveAll() - Assert.assertTrue(project.baseDir.findFileByRelativePath(".idea/kotlinc.xml") == null) - } - - fun testKotlincExistsNoSettingsLatestRuntimeNoVersionAutoAdvance() { - val application = ApplicationManager.getApplication() as ApplicationImpl - application.doNotSave(false) - Assert.assertEquals(LanguageVersion.LATEST_STABLE, module.languageVersionSettings.languageVersion) - Assert.assertEquals(LanguageVersion.LATEST_STABLE, myProject.getLanguageVersionSettings(null).languageVersion) - KotlinCommonCompilerArgumentsHolder.getInstance(project).update { - autoAdvanceLanguageVersion = false - autoAdvanceApiVersion = false - } - application.saveAll() - Assert.assertTrue(project.baseDir.findFileByRelativePath(".idea/kotlinc.xml") != null) - } - - fun testDropKotlincOnVersionAutoAdvance() { - val application = ApplicationManager.getApplication() as ApplicationImpl - application.doNotSave(false) - Assert.assertEquals(LanguageVersion.LATEST_STABLE, module.languageVersionSettings.languageVersion) - KotlinCommonCompilerArgumentsHolder.getInstance(project).update { - autoAdvanceLanguageVersion = true - autoAdvanceApiVersion = true - } - application.saveAll() - Assert.assertTrue(project.baseDir.findFileByRelativePath(".idea/kotlinc.xml") == null) - } - - fun testProject106InconsistentVersionInConfig() { - val settings = KotlinFacetSettingsProvider.getInstance(myProject).getInitializedSettings(module) - Assert.assertEquals(false, settings.useProjectSettings) - Assert.assertEquals("1.0", settings.languageLevel!!.description) - Assert.assertEquals("1.0", settings.apiLevel!!.description) - } - - fun testProject107InconsistentVersionInConfig() { - val settings = KotlinFacetSettingsProvider.getInstance(myProject).getInitializedSettings(module) - Assert.assertEquals(false, settings.useProjectSettings) - Assert.assertEquals("1.0", settings.languageLevel!!.description) - Assert.assertEquals("1.0", settings.apiLevel!!.description) - } - - fun testFacetWithProjectSettings() { - val settings = KotlinFacetSettingsProvider.getInstance(myProject).getInitializedSettings(module) - Assert.assertEquals(true, settings.useProjectSettings) - Assert.assertEquals("1.1", settings.languageLevel!!.description) - Assert.assertEquals("1.1", settings.apiLevel!!.description) - Assert.assertEquals("-version -Xallow-kotlin-package -Xskip-metadata-version-check", settings.compilerSettings!!.additionalArguments) - } - - fun testLoadAndSaveProjectWithV2FacetConfig() { - val moduleFileContentBefore = String(module.moduleFile!!.contentsToByteArray()) - val application = ApplicationManager.getApplication() as ApplicationImpl - application.doNotSave(false) - application.saveAll() - val moduleFileContentAfter = String(module.moduleFile!!.contentsToByteArray()) - Assert.assertEquals(moduleFileContentBefore, moduleFileContentAfter) - } - - fun testApiVersionWithoutLanguageVersion() { - KotlinCommonCompilerArgumentsHolder.getInstance(myProject) - val settings = myProject.getLanguageVersionSettings() - Assert.assertEquals(ApiVersion.KOTLIN_1_1, settings.apiVersion) - } - - fun testNoKotlincExistsNoSettingsLatestRuntimeNullizeEmptyStrings() { - val application = ApplicationManager.getApplication() as ApplicationImpl - application.doNotSave(false) - Kotlin2JsCompilerArgumentsHolder.getInstance(project).update { - sourceMapPrefix = "" - sourceMapEmbedSources = "" - } - application.saveAll() - Assert.assertTrue(project.baseDir.findFileByRelativePath(".idea/kotlinc.xml") == null) - } - - //todo[Sedunov]: wait for fix in platform to avoid misunderstood from Java newbies (also PluginStartupComponent) - /*fun testKotlinSdkAdded() { - Assert.assertTrue(ProjectJdkTable.getInstance().allJdks.any { it.sdkType is KotlinSdkType }) - }*/ -} diff --git a/idea/tests/org/jetbrains/kotlin/idea/conversion/copy/AbstractJavaToKotlinCopyPasteConversionTest.kt.173 b/idea/tests/org/jetbrains/kotlin/idea/conversion/copy/AbstractJavaToKotlinCopyPasteConversionTest.kt.173 deleted file mode 100644 index 0dc5c73e8c9..00000000000 --- a/idea/tests/org/jetbrains/kotlin/idea/conversion/copy/AbstractJavaToKotlinCopyPasteConversionTest.kt.173 +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2010-2015 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.idea.conversion.copy - -import com.intellij.openapi.actionSystem.IdeActions -import org.jetbrains.kotlin.idea.AbstractCopyPasteTest -import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor -import org.jetbrains.kotlin.idea.test.PluginTestCaseBase -import org.jetbrains.kotlin.idea.editor.KotlinEditorOptions -import org.jetbrains.kotlin.test.InTextDirectivesUtils -import org.jetbrains.kotlin.test.KotlinTestUtils -import java.io.File -import kotlin.test.assertEquals - -abstract class AbstractJavaToKotlinCopyPasteConversionTest : AbstractCopyPasteTest() { - private val BASE_PATH = PluginTestCaseBase.getTestDataPathBase() + "/copyPaste/conversion" - - private var oldEditorOptions: KotlinEditorOptions? = null - - override fun getTestDataPath() = BASE_PATH - - override fun getProjectDescriptor() = KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE - - override fun setUp() { - super.setUp() - oldEditorOptions = KotlinEditorOptions.getInstance().state - KotlinEditorOptions.getInstance().isEnableJavaToKotlinConversion = true - KotlinEditorOptions.getInstance().isDonTShowConversionDialog = true - } - - override fun tearDown() { - KotlinEditorOptions.getInstance().loadState(oldEditorOptions) - super.tearDown() - } - - fun doTest(path: String) { - myFixture.testDataPath = BASE_PATH - val testName = getTestName(false) - myFixture.configureByFiles(testName + ".java") - - val fileText = myFixture.editor.document.text - val noConversionExpected = InTextDirectivesUtils.findListWithPrefixes(fileText, "// NO_CONVERSION_EXPECTED").isNotEmpty() - - myFixture.performEditorAction(IdeActions.ACTION_COPY) - - configureByDependencyIfExists(testName + ".dependency.kt") - configureByDependencyIfExists(testName + ".dependency.java") - - configureTargetFile(testName + ".to.kt") - - ConvertJavaCopyPasteProcessor.conversionPerformed = false - - myFixture.performEditorAction(IdeActions.ACTION_PASTE) - - assertEquals(noConversionExpected, !ConvertJavaCopyPasteProcessor.conversionPerformed, - if (noConversionExpected) "Conversion to Kotlin should not be suggested" else "No conversion to Kotlin suggested") - - KotlinTestUtils.assertEqualsToFile(File(path.replace(".java", ".expected.kt")), myFixture.file.text) - } -} diff --git a/idea/tests/org/jetbrains/kotlin/idea/conversion/copy/AbstractTextJavaToKotlinCopyPasteConversionTest.kt.173 b/idea/tests/org/jetbrains/kotlin/idea/conversion/copy/AbstractTextJavaToKotlinCopyPasteConversionTest.kt.173 deleted file mode 100644 index 4e2f9ade559..00000000000 --- a/idea/tests/org/jetbrains/kotlin/idea/conversion/copy/AbstractTextJavaToKotlinCopyPasteConversionTest.kt.173 +++ /dev/null @@ -1,74 +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.kotlin.idea.conversion.copy - -import com.intellij.openapi.actionSystem.IdeActions -import org.jetbrains.kotlin.idea.AbstractCopyPasteTest -import org.jetbrains.kotlin.idea.editor.KotlinEditorOptions -import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor -import org.jetbrains.kotlin.idea.test.PluginTestCaseBase -import org.jetbrains.kotlin.test.InTextDirectivesUtils -import org.jetbrains.kotlin.test.KotlinTestUtils -import java.io.File - -abstract class AbstractTextJavaToKotlinCopyPasteConversionTest : AbstractCopyPasteTest() { - private val BASE_PATH = PluginTestCaseBase.getTestDataPathBase() + "/copyPaste/plainTextConversion" - - private var oldEditorOptions: KotlinEditorOptions? = null - - override fun getTestDataPath() = BASE_PATH - - override fun getProjectDescriptor() = KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE - - override fun setUp() { - super.setUp() - oldEditorOptions = KotlinEditorOptions.getInstance().state - KotlinEditorOptions.getInstance().isEnableJavaToKotlinConversion = true - KotlinEditorOptions.getInstance().isDonTShowConversionDialog = true - } - - override fun tearDown() { - KotlinEditorOptions.getInstance().loadState(oldEditorOptions) - super.tearDown() - } - - fun doTest(path: String) { - myFixture.testDataPath = BASE_PATH - val testName = getTestName(false) - myFixture.configureByFiles(testName + ".txt") - - val fileText = myFixture.editor.document.text - val noConversionExpected = InTextDirectivesUtils.findListWithPrefixes(fileText, "// NO_CONVERSION_EXPECTED").isNotEmpty() - - myFixture.editor.selectionModel.setSelection(0, fileText.length) - myFixture.performEditorAction(IdeActions.ACTION_COPY) - - configureByDependencyIfExists(testName + ".dependency.kt") - configureByDependencyIfExists(testName + ".dependency.java") - - configureTargetFile(testName + ".to.kt") - - ConvertTextJavaCopyPasteProcessor.conversionPerformed = false - - myFixture.performEditorAction(IdeActions.ACTION_PASTE) - - kotlin.test.assertEquals(noConversionExpected, !ConvertTextJavaCopyPasteProcessor.conversionPerformed, - if (noConversionExpected) "Conversion to Kotlin should not be suggested" else "No conversion to Kotlin suggested") - - KotlinTestUtils.assertEqualsToFile(File(path.replace(".txt", ".expected.kt")), myFixture.file.text) - } -} diff --git a/idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinDebuggerTestCase.java.173 b/idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinDebuggerTestCase.java.173 deleted file mode 100644 index 8f9bc5a033f..00000000000 --- a/idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinDebuggerTestCase.java.173 +++ /dev/null @@ -1,421 +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.kotlin.idea.debugger; - -import com.google.common.collect.Lists; -import com.intellij.compiler.impl.CompilerUtil; -import com.intellij.debugger.DebuggerManagerEx; -import com.intellij.debugger.impl.DescriptorTestCase; -import com.intellij.debugger.impl.OutputChecker; -import com.intellij.execution.ExecutionTestCase; -import com.intellij.execution.configurations.JavaParameters; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.projectRoots.Sdk; -import com.intellij.openapi.roots.ModifiableRootModel; -import com.intellij.openapi.roots.ModuleRootManager; -import com.intellij.openapi.roots.OrderRootType; -import com.intellij.openapi.roots.ui.configuration.libraryEditor.NewLibraryEditor; -import com.intellij.openapi.util.Computable; -import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.vfs.VfsUtil; -import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess; -import com.intellij.pom.java.LanguageLevel; -import com.intellij.psi.JavaPsiFacade; -import com.intellij.psi.PsiClass; -import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.testFramework.EdtTestUtil; -import com.intellij.testFramework.IdeaTestUtil; -import com.intellij.util.indexing.FileBasedIndex; -import com.intellij.xdebugger.XDebugSession; -import kotlin.Unit; -import kotlin.collections.CollectionsKt; -import kotlin.io.FilesKt; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.kotlin.asJava.classes.FakeLightClassForFileOfPackage; -import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade; -import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime; -import org.jetbrains.kotlin.idea.compiler.configuration.Kotlin2JvmCompilerArgumentsHolder; -import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil; -import org.jetbrains.kotlin.idea.test.PluginTestCaseBase; -import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils; -import org.jetbrains.kotlin.name.FqName; -import org.jetbrains.kotlin.psi.KtFile; -import org.jetbrains.kotlin.test.KotlinTestUtils; -import org.jetbrains.kotlin.test.MockLibraryUtil; -import org.jetbrains.kotlin.test.TestMetadata; -import org.jetbrains.kotlin.test.util.JetTestUtilsKt; -import org.jetbrains.kotlin.utils.ExceptionUtilsKt; -import org.jetbrains.kotlin.utils.PathUtil; -import org.junit.Assert; -import org.junit.ComparisonFailure; - -import java.io.File; -import java.io.IOException; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; - -public abstract class KotlinDebuggerTestCase extends DescriptorTestCase { - private static final String TINY_APP = PluginTestCaseBase.getTestDataPathBase() + "/debugger/tinyApp"; - private static final File TINY_APP_SRC = new File(TINY_APP, "src"); - private static boolean IS_TINY_APP_COMPILED = false; - - // Caches are auto-invalidated when file modification in TINY_APP_SRC detected (through File.lastModified()). - // LOCAL_CACHE_DIR removing can be used to force caches invalidating as well. - private static final boolean LOCAL_CACHE_REUSE = true; - - private static final File LOCAL_CACHE_DIR = new File("out/debuggerTinyApp"); - private static final File LOCAL_CACHE_JAR_DIR = new File(LOCAL_CACHE_DIR, "jar"); - private static final File LOCAL_CACHE_APP_DIR = new File(LOCAL_CACHE_DIR, "app"); - private static final File LOCAL_CACHE_LAST_MODIFIED_FILE = new File(LOCAL_CACHE_DIR, "lastModified.txt"); - - private static File CUSTOM_LIBRARY_JAR; - private static final File CUSTOM_LIBRARY_SOURCES = - new File(PluginTestCaseBase.getTestDataPathBase() + "/debugger/customLibraryForTinyApp"); - - protected static final String KOTLIN_LIBRARY_NAME = "KotlinLibrary"; - private static final String CUSTOM_LIBRARY_NAME = "CustomLibrary"; - - @Nullable - private String oldJvmTarget = null; - - @Override - protected OutputChecker initOutputChecker() { - return new KotlinOutputChecker( - this.getClass().getAnnotation(TestMetadata.class).value(), getTestAppPath(), getAppOutputPath()); - } - - @NotNull - @Override - protected String getTestAppPath() { - return TINY_APP; - } - - @SuppressWarnings("AssignmentToStaticFieldFromInstanceMethod") - @Override - protected void setUp() throws Exception { - if (LOCAL_CACHE_REUSE) { - boolean localCacheRebuild = false; - - if (LOCAL_CACHE_DIR.exists()) { - if (isLocalCacheOutdated()) { - System.out.println("-- Local caches outdated --"); - deleteLocalCacheDirectory(true); - localCacheRebuild = true; - } - } - else { - localCacheRebuild = true; - } - - overrideTempOutputDirectory(); - CUSTOM_LIBRARY_JAR = new File(LOCAL_CACHE_DIR, "debuggerCustomLibrary.jar"); - IS_TINY_APP_COMPILED = !localCacheRebuild; - } - - VfsRootAccess.allowRootAccess(KotlinTestUtils.getHomeDirectory()); - if (DexLikeBytecodePatchKt.needDexPatch(getTestName(true))) { - NoStrataPositionManagerHelperKt.setEmulateDexDebugInTests(true); - } - super.setUp(); - - Kotlin2JvmCompilerArgumentsHolder.Companion.getInstance(myProject).update(s -> { - oldJvmTarget = s.getJvmTarget(); - s.setJvmTarget("1.8"); - return Unit.INSTANCE; - }); - } - - @Override - protected void runTest() throws Throwable { - super.runTest(); - if(getDebugProcess() != null) { - getDebugProcess().getProcessHandler().startNotify(); - waitProcess(getDebugProcess().getProcessHandler()); - waitForCompleted(); - //disposeSession(myDebuggerSession); - assertNull(DebuggerManagerEx.getInstanceEx(myProject).getDebugProcess(getDebugProcess().getProcessHandler())); - myDebuggerSession = null; - } - - if (getChecker().contains("JVMTI_ERROR_WRONG_PHASE(112)")) { - myRestart.incrementAndGet(); - if (needsRestart()) { - return; - } - } else { - myRestart.set(0); - } - - throwExceptionsIfAny(); - checkTestOutput(); - } - - private boolean needsRestart() { - int restart = myRestart.get(); - return restart > 0 && restart <= 3; - } - - private static void deleteLocalCacheDirectory(boolean assertDeleteSuccess) { - System.out.println("-- Remove local cache directory --"); - boolean deleteResult = FilesKt.deleteRecursively(LOCAL_CACHE_DIR); - if (assertDeleteSuccess) { - Assert.assertTrue("Failed to delete local cache!", deleteResult); - } - } - - private static long cachedDataTimeStamp() { - File testDataLastModifiedFile = JetTestUtilsKt.findLastModifiedFile( - TINY_APP_SRC, - file -> FilesKt.getExtension(file).equals("out") || file.isDirectory() - ); - - File distLibLastModifiedFile = JetTestUtilsKt.findLastModifiedFile( - PathUtil.getKotlinPathsForDistDirectory().getLibPath(), file -> false); - - return Math.max(testDataLastModifiedFile.lastModified(), distLibLastModifiedFile.lastModified()); - } - - private static boolean isLocalCacheOutdated() { - if (!LOCAL_CACHE_LAST_MODIFIED_FILE.exists()) return true; - - String text; - try { - text = FileUtil.loadFile(LOCAL_CACHE_LAST_MODIFIED_FILE); - } - catch (IOException e) { - throw ExceptionUtilsKt.rethrow(e); - } - - long cachedFor = Long.parseLong(text); - long currentLastDate = cachedDataTimeStamp(); - - return currentLastDate != cachedFor; - } - - private static void overrideTempOutputDirectory() { - try { - Field ourOutputRootField = ExecutionTestCase.class.getDeclaredField("ourOutputRoot"); - ourOutputRootField.setAccessible(true); - - if (!LOCAL_CACHE_DIR.exists()) { - - LOCAL_CACHE_JAR_DIR.mkdirs(); - LOCAL_CACHE_APP_DIR.mkdirs(); - - boolean result = - LOCAL_CACHE_DIR.exists() && - LOCAL_CACHE_JAR_DIR.exists() && - LOCAL_CACHE_APP_DIR.exists(); - - Assert.assertTrue("Failure on local cache directories creation", result); - - boolean createFileResult = LOCAL_CACHE_LAST_MODIFIED_FILE.createNewFile(); - Assert.assertTrue("Failure on " + LOCAL_CACHE_LAST_MODIFIED_FILE.getName() + " creation", createFileResult); - - long lastModificationDate = cachedDataTimeStamp(); - FileUtil.writeToFile(LOCAL_CACHE_LAST_MODIFIED_FILE, Long.toString(lastModificationDate)); - } - - ourOutputRootField.set(null, LOCAL_CACHE_APP_DIR); - } - catch (NoSuchFieldException | IOException | IllegalAccessException e) { - throw ExceptionUtilsKt.rethrow(e); - } - } - - private static void configureLibrary( - @NotNull ModifiableRootModel model, - @NotNull String libraryName, - @NotNull File classes, - @NotNull File sources - ) { - NewLibraryEditor customLibEditor = new NewLibraryEditor(); - customLibEditor.setName(libraryName); - - customLibEditor.addRoot(VfsUtil.getUrlForLibraryRoot(classes), OrderRootType.CLASSES); - customLibEditor.addRoot(VfsUtil.getUrlForLibraryRoot(sources), OrderRootType.SOURCES); - - ConfigLibraryUtil.INSTANCE.addLibrary(customLibEditor, model, null); - } - - @Override - protected void tearDown() throws Exception { - Kotlin2JvmCompilerArgumentsHolder.Companion.getInstance(myProject).update(s -> { - s.setJvmTarget(oldJvmTarget); - return Unit.INSTANCE; - }); - - if (DexLikeBytecodePatchKt.needDexPatch(getTestName(true))) { - NoStrataPositionManagerHelperKt.setEmulateDexDebugInTests(false); - } - - EdtTestUtil.runInEdtAndWait(() -> { - ConfigLibraryUtil.INSTANCE.removeLibrary(getModule(), CUSTOM_LIBRARY_NAME); - ConfigLibraryUtil.INSTANCE.removeLibrary(getModule(), KOTLIN_LIBRARY_NAME); - }); - - super.tearDown(); - VfsRootAccess.disallowRootAccess(KotlinTestUtils.getHomeDirectory()); - } - - @SuppressWarnings("AssignmentToStaticFieldFromInstanceMethod") - @Override - protected void setUpModule() { - super.setUpModule(); - - IdeaTestUtil.setModuleLanguageLevel(myModule, LanguageLevel.JDK_1_8); - - String outputDirPath = getAppOutputPath(); - File outDir = new File(outputDirPath); - - if (!IS_TINY_APP_COMPILED) { - try { - String modulePath = getTestAppPath(); - - //noinspection ConstantConditions - File jarDir = LOCAL_CACHE_REUSE ? LOCAL_CACHE_DIR : KotlinTestUtils.tmpDir("debuggerCustomLibrary"); - - CUSTOM_LIBRARY_JAR = MockLibraryUtil.compileLibraryToJar(CUSTOM_LIBRARY_SOURCES.getPath(), jarDir, "debuggerCustomLibrary"); - - String sourcesDir = modulePath + File.separator + "src"; - - MockLibraryUtil.compileKotlin(sourcesDir, outDir, CollectionsKt.listOf("-jvm-target", "1.8"), CUSTOM_LIBRARY_JAR.getPath()); - - List options = - Arrays.asList("-d", outputDirPath, "-classpath", - ForTestCompileRuntime.runtimeJarForTests().getPath() + File.pathSeparator + - ForTestCompileRuntime.jetbrainsAnnotationsForTests().getPath(), - "-g"); - KotlinTestUtils.compileJavaFiles(findJavaFiles(new File(sourcesDir)), options); - - DexLikeBytecodePatchKt.patchDexTests(outDir); - - IS_TINY_APP_COMPILED = true; - } - catch (Throwable e) { - deleteLocalCacheDirectory(false); - throw new RuntimeException(e); - } - } - - CompilerUtil.refreshOutputRoots(Lists.newArrayList(outputDirPath)); - - ApplicationManager.getApplication().runWriteAction(() -> { - ModifiableRootModel model = ModuleRootManager.getInstance(myModule).getModifiableModel(); - configureLibrary(model, CUSTOM_LIBRARY_NAME, CUSTOM_LIBRARY_JAR, CUSTOM_LIBRARY_SOURCES); - configureLibrary(model, KOTLIN_LIBRARY_NAME, ForTestCompileRuntime.runtimeJarForTests(), new File("libraries/stdlib/src")); - model.commit(); - }); - - if (!outDir.exists()) { - deleteLocalCacheDirectory(false); - Assert.fail("Output directory for module wasn't created: " + outDir.getAbsolutePath()); - } - } - - private static List findJavaFiles(@NotNull File directory) { - List result = new ArrayList<>(); - if (directory.isDirectory()) { - File[] files = directory.listFiles(); - if (files != null) { - for (File file : files) { - if (file.isDirectory()) { - result.addAll(findJavaFiles(file)); - } - else if (file.getName().endsWith(".java")) { - result.add(file); - } - } - } - } - return result; - } - - @Override - protected JavaParameters createJavaParameters(String mainClass) { - JavaParameters parameters = super.createJavaParameters(mainClass); - parameters.getClassPath().add(ForTestCompileRuntime.runtimeJarForTests()); - parameters.getClassPath().add(CUSTOM_LIBRARY_JAR); - return parameters; - } - - @Override - protected void createBreakpoints(String className) { - PsiClass[] psiClasses = ApplicationManager.getApplication().runReadAction( - (Computable) () -> JavaPsiFacade.getInstance(myProject) - .findClasses(className, GlobalSearchScope.allScope(myProject))); - - for (PsiClass psiClass : psiClasses) { - if (psiClass instanceof KtLightClassForFacade) { - Collection files = ((KtLightClassForFacade) psiClass).getFiles(); - for (KtFile jetFile : files) { - createBreakpoints(jetFile); - } - } - else if (psiClass instanceof FakeLightClassForFileOfPackage) { - // skip, because we already create breakpoints using KotlinLightClassForPackage - } - else { - createBreakpoints(psiClass.getContainingFile()); - } - } - } - - @SuppressWarnings("MethodMayBeStatic") - protected void createDebugProcess(@NotNull String path) throws Exception { - File file = new File(path); - //noinspection ConstantConditions - FileBasedIndex.getInstance().requestReindex(VfsUtil.findFileByIoFile(file, true)); - String packageName = file.getName().replace(".kt", ""); - FqName packageFQN = new FqName(packageName); - String mainClassName = PackagePartClassUtils.getPackagePartFqName(packageFQN, file.getName()).asString(); - createLocalProcess(mainClassName); - } - - @Override - protected Sdk getTestProjectJdk() { - return PluginTestCaseBase.fullJdk(); - } - - @Override - protected void checkTestOutput() throws Exception { - if (KotlinTestUtils.isAllFilesPresentTest(getTestName(false))) { - return; - } - - try { - super.checkTestOutput(); - } - catch (ComparisonFailure e) { - KotlinTestUtils.assertEqualsToFile( - new File(this.getClass().getAnnotation(TestMetadata.class).value(), getTestName(true) + ".out"), - e.getActual()); - } - } - - @Override - public Object getData(String dataId) { - if (XDebugSession.DATA_KEY.is(dataId)) { - return myDebuggerSession == null ? null : myDebuggerSession.getXDebugSession(); - } - return super.getData(dataId); - } -} diff --git a/idea/tests/org/jetbrains/kotlin/idea/debugger/sequence/dsl/KotlinDslTest.kt.173 b/idea/tests/org/jetbrains/kotlin/idea/debugger/sequence/dsl/KotlinDslTest.kt.173 deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/CommonIntentionActionsTest.kt.173 b/idea/tests/org/jetbrains/kotlin/idea/quickfix/CommonIntentionActionsTest.kt.173 deleted file mode 100644 index 29d91ecd36f..00000000000 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/CommonIntentionActionsTest.kt.173 +++ /dev/null @@ -1,350 +0,0 @@ -/* - * 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.kotlin.idea.quickfix - -import com.intellij.codeInsight.intention.IntentionAction -import com.intellij.lang.jvm.JvmElement -import com.intellij.lang.jvm.JvmModifier -import com.intellij.lang.jvm.actions.* -import com.intellij.lang.jvm.types.JvmSubstitutor -import com.intellij.openapi.project.Project -import com.intellij.psi.JavaPsiFacade -import com.intellij.psi.PsiJvmSubstitutor -import com.intellij.psi.PsiSubstitutor -import com.intellij.psi.PsiType -import com.intellij.psi.codeStyle.SuggestedNameInfo -import com.intellij.testFramework.fixtures.CodeInsightTestFixture -import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase -import org.jetbrains.kotlin.idea.search.allScope -import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor -import org.jetbrains.uast.UParameter -import org.jetbrains.uast.UastContext -import org.jetbrains.uast.toUElement -import org.junit.Assert - -class CommonIntentionActionsTest : LightPlatformCodeInsightFixtureTestCase() { - private class SimpleMethodRequest( - project: Project, - override val methodName: String, - override val modifiers: Collection = emptyList(), - override val returnType: ExpectedTypes = emptyList(), - override val annotations: Collection = emptyList(), - override val parameters: List = emptyList(), - override val targetSubstitutor: JvmSubstitutor = PsiJvmSubstitutor(project, PsiSubstitutor.EMPTY) - ) : CreateMethodRequest { - override val isValid: Boolean = true - } - - private class NameInfo(vararg names: String) : SuggestedNameInfo(names) - - override fun getProjectDescriptor() = KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE_FULL_JDK - - fun testMakeNotFinal() { - myFixture.configureByText("foo.kt", """ - class Foo { - fun bar(){} - } - """) - - myFixture.launchAction( - createModifierActions( - myFixture.atCaret(), MemberRequest.Modifier(JvmModifier.FINAL, false) - ).findWithText("Make 'bar' open") - ) - myFixture.checkResult(""" - class Foo { - open fun bar(){} - } - """) - } - - fun testMakePrivate() { - myFixture.configureByText("foo.kt", """ - class Foo { - fun bar(){} - } - """) - - myFixture.launchAction( - createModifierActions( - myFixture.atCaret(), MemberRequest.Modifier(JvmModifier.PRIVATE, true) - ).findWithText("Make 'Foo' private") - ) - myFixture.checkResult(""" - private class Foo { - fun bar(){} - } - """) - } - - fun testMakeNotPrivate() { - myFixture.configureByText("foo.kt", """ - private class Foo { - fun bar(){} - } - """.trim()) - - myFixture.launchAction( - createModifierActions( - myFixture.atCaret(), MemberRequest.Modifier(JvmModifier.PRIVATE, false) - ).findWithText("Remove 'private' modifier") - ) - myFixture.checkResult(""" - class Foo { - fun bar(){} - } - """.trim(), true) - } - - fun testDontMakeFunInObjectsOpen() { - myFixture.configureByText("foo.kt", """ - object Foo { - fun bar(){} - } - """.trim()) - Assert.assertTrue(createModifierActions(myFixture.atCaret(), MemberRequest.Modifier(JvmModifier.FINAL, false)).isEmpty()) - } - - fun testAddVoidVoidMethod() { - myFixture.configureByText("foo.kt", """ - |class Foo { - | fun bar() {} - |} - """.trim().trimMargin()) - - myFixture.launchAction( - createMethodActions( - myFixture.atCaret(), - methodRequest(project, "baz", JvmModifier.PRIVATE, PsiType.VOID) - ).findWithText("Add method 'baz' to 'Foo'") - ) - myFixture.checkResult(""" - |class Foo { - | fun bar() {} - | private fun baz() { - | - | } - |} - """.trim().trimMargin(), true) - } - - fun testAddIntIntMethod() { - myFixture.configureByText("foo.kt", """ - |class Foo { - | fun bar() {} - |} - """.trim().trimMargin()) - - myFixture.launchAction( - createMethodActions( - myFixture.atCaret(), - SimpleMethodRequest(project, - methodName = "baz", - modifiers = listOf(JvmModifier.PUBLIC), - returnType = expectedTypes(PsiType.INT), - parameters = expectedParams(PsiType.INT)) - ).findWithText("Add method 'baz' to 'Foo'") - ) - myFixture.checkResult(""" - |class Foo { - | fun bar() {} - | fun baz(param0: Int): Int { - | TODO("not implemented") //To change body of created functions use File | Settings | File Templates. - | } - |} - """.trim().trimMargin(), true) - } - - fun testAddIntPrimaryConstructor() { - myFixture.configureByText("foo.kt", """ - |class Foo { - |} - """.trim().trimMargin()) - - myFixture.launchAction( - createConstructorActions( - myFixture.atCaret(), - MemberRequest.Constructor(parameters = makeParams(PsiType.INT)) - ).findWithText("Add primary constructor to 'Foo'") - ) - myFixture.checkResult(""" - |class Foo(param0: Int) { - |} - """.trim().trimMargin(), true) - } - - fun testAddIntSecondaryConstructor() { - myFixture.configureByText("foo.kt", """ - |class Foo() { - |} - """.trim().trimMargin()) - - myFixture.launchAction( - createConstructorActions( - myFixture.atCaret(), - MemberRequest.Constructor(parameters = makeParams(PsiType.INT)) - ).findWithText("Add secondary constructor to 'Foo'") - ) - myFixture.checkResult(""" - |class Foo() { - | constructor(param0: Int) { - | - | } - |} - """.trim().trimMargin(), true) - } - - fun testChangePrimaryConstructorInt() { - myFixture.configureByText("foo.kt", """ - |class Foo() { - |} - """.trim().trimMargin()) - - myFixture.launchAction( - createConstructorActions( - myFixture.atCaret(), - MemberRequest.Constructor(parameters = makeParams(PsiType.INT)) - ).findWithText("Add 'int' as 1st parameter to method 'Foo'") - ) - myFixture.checkResult(""" - |class Foo(param0: Int) { - |} - """.trim().trimMargin(), true) - } - - fun testRemoveConstructorParameters() { - myFixture.configureByText("foo.kt", """ - |class Foo(i: Int) { - |} - """.trim().trimMargin()) - - myFixture.launchAction( - createConstructorActions( - myFixture.atCaret(), - MemberRequest.Constructor() - ).findWithText("Remove 1st parameter from method 'Foo'") - ) - myFixture.checkResult(""" - |class Foo() { - |} - """.trim().trimMargin(), true) - } - - fun testAddStringVarProperty() { - myFixture.configureByText("foo.kt", """ - |class Foo { - | fun bar() {} - |} - """.trim().trimMargin()) - - myFixture.launchAction( - createPropertyActions( - myFixture.atCaret(), - MemberRequest.Property( - propertyName = "baz", - visibilityModifier = JvmModifier.PUBLIC, - propertyType = PsiType.getTypeByName("java.lang.String", project, project.allScope()), - getterRequired = true, - setterRequired = true - ) - ).findWithText("Add 'var' property 'baz' to 'Foo'") - ) - myFixture.checkResult(""" - |class Foo { - | var baz: String = TODO("initialize me") - | - | fun bar() {} - |} - """.trim().trimMargin(), true) - } - - fun testAddLateInitStringVarProperty() { - myFixture.configureByText("foo.kt", """ - |class Foo { - | fun bar() {} - |} - """.trim().trimMargin()) - - myFixture.launchAction( - createPropertyActions( - myFixture.atCaret(), - MemberRequest.Property( - propertyName = "baz", - visibilityModifier = JvmModifier.PUBLIC, - propertyType = PsiType.getTypeByName("java.lang.String", project, project.allScope()), - getterRequired = true, - setterRequired = true - ) - ).findWithText("Add 'lateinit var' property 'baz' to 'Foo'") - ) - myFixture.checkResult(""" - |class Foo { - | lateinit var baz: String - | - | fun bar() {} - |} - """.trim().trimMargin(), true) - } - - fun testAddStringValProperty() { - myFixture.configureByText("foo.kt", """ - |class Foo { - | fun bar() {} - |} - """.trim().trimMargin()) - - myFixture.launchAction( - createPropertyActions( - myFixture.atCaret(), - MemberRequest.Property( - propertyName = "baz", - visibilityModifier = JvmModifier.PUBLIC, - propertyType = PsiType.getTypeByName("java.lang.String", project, project.allScope()), - getterRequired = true, - setterRequired = false - ) - ).findWithText("Add 'val' property 'baz' to 'Foo'") - ) - myFixture.checkResult(""" - |class Foo { - | val baz: String = TODO("initialize me") - | - | fun bar() {} - |} - """.trim().trimMargin(), true) - } - - private fun makeParams(vararg psyTypes: PsiType): List { - val uastContext = UastContext(myFixture.project) - val factory = JavaPsiFacade.getElementFactory(myFixture.project) - val parameters = psyTypes.mapIndexed { index, psiType -> factory.createParameter("param$index", psiType) } - return parameters.map { uastContext.convertElement(it, null, UParameter::class.java) as UParameter } - } - - private fun expectedTypes(vararg psiTypes: PsiType) = psiTypes.map { expectedType(it) } - - private fun expectedParams(vararg psyTypes: PsiType) = - psyTypes.mapIndexed { index, psiType -> NameInfo("param$index") to expectedTypes(psiType) } - - private inline fun CodeInsightTestFixture.atCaret() = elementAtCaret.toUElement() as T - - @Suppress("CAST_NEVER_SUCCEEDS") - private fun List.findWithText(text: String): IntentionAction = - this.firstOrNull { it.text == text } ?: - Assert.fail("intention with text '$text' was not found, only ${this.joinToString { "\"${it.text}\"" }} available") as Nothing -} - diff --git a/idea/tests/org/jetbrains/kotlin/idea/run/RunConfigurationTest.kt.173 b/idea/tests/org/jetbrains/kotlin/idea/run/RunConfigurationTest.kt.173 deleted file mode 100644 index 398b4f71652..00000000000 --- a/idea/tests/org/jetbrains/kotlin/idea/run/RunConfigurationTest.kt.173 +++ /dev/null @@ -1,291 +0,0 @@ -/* - * Copyright 2010-2015 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.idea.run - -import com.intellij.execution.Location -import com.intellij.execution.PsiLocation -import com.intellij.execution.actions.ConfigurationContext -import com.intellij.openapi.module.Module -import com.intellij.openapi.projectRoots.Sdk -import com.intellij.openapi.roots.ModuleRootModificationUtil -import com.intellij.openapi.vfs.VirtualFile -import com.intellij.psi.JavaPsiFacade -import com.intellij.psi.PsiComment -import com.intellij.psi.PsiDocumentManager -import com.intellij.psi.PsiManager -import com.intellij.refactoring.RefactoringFactory -import com.intellij.testFramework.MapDataContext -import com.intellij.testFramework.PlatformTestCase -import com.intellij.testFramework.PsiTestUtil -import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl -import org.jetbrains.kotlin.idea.MainFunctionDetector -import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny -import org.jetbrains.kotlin.idea.search.allScope -import org.jetbrains.kotlin.idea.stubindex.KotlinFullClassNameIndex -import org.jetbrains.kotlin.idea.stubindex.KotlinTopLevelFunctionFqnNameIndex -import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil -import org.jetbrains.kotlin.idea.test.KotlinCodeInsightTestCase -import org.jetbrains.kotlin.idea.test.PluginTestCaseBase.* -import org.jetbrains.kotlin.idea.test.configureLanguageAndApiVersion -import org.jetbrains.kotlin.idea.util.application.runWriteAction -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.allChildren -import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType -import org.junit.Assert -import java.io.File -import java.util.* - -private val RUN_PREFIX = "// RUN:" - -class RunConfigurationTest: KotlinCodeInsightTestCase() { - fun getTestProject() = myProject!! - override fun getModule() = myModule!! - - fun testMainInTest() { - val createResult = configureModule(moduleDirPath("module"), getTestProject().baseDir!!) - configureLanguageAndApiVersion( - createResult.module.project, createResult.module, LanguageVersionSettingsImpl.DEFAULT.languageVersion.versionString - ) - ConfigLibraryUtil.configureKotlinRuntimeAndSdk(createResult.module, addJdk(testRootDisposable, ::mockJdk)) - - val runConfiguration = createConfigurationFromMain("some.main") - val javaParameters = getJavaRunParameters(runConfiguration) - - Assert.assertTrue(javaParameters.classPath.rootDirs.contains(createResult.srcOutputDir)) - Assert.assertTrue(javaParameters.classPath.rootDirs.contains(createResult.testOutputDir)) - - fun functionVisitor(function: KtNamedFunction) { - val options = function.bodyExpression?.allChildren?.filterIsInstance()?.map { it.text.trim().replace("//", "").trim() }?.filter { it.isNotBlank() }?.toList() ?: emptyList() - if (options.isNotEmpty()) { - val assertIsMain = "yes" in options - val assertIsNotMain = "no" in options - - val isMainFunction = - MainFunctionDetector(LanguageVersionSettingsImpl.DEFAULT) { it.resolveToDescriptorIfAny() }.isMain(function) - - if (assertIsMain) { - Assert.assertTrue("The function ${function.fqName?.asString()} should be main", isMainFunction) - } - if (assertIsNotMain) { - Assert.assertFalse("The function ${function.fqName?.asString()} should NOT be main", isMainFunction) - } - - if (isMainFunction) { - createConfigurationFromMain(function.fqName?.asString()!!).checkConfiguration() - - Assert.assertNotNull("Kotlin configuration producer should produce configuration for ${function.fqName?.asString()}", - KotlinRunConfigurationProducer.getEntryPointContainer(function)) - } else { - try { - createConfigurationFromMain(function.fqName?.asString()!!).checkConfiguration() - Assert.fail("configuration for function ${function.fqName?.asString()} at least shouldn't pass checkConfiguration()") - } catch (expected: Throwable) { - } - - if (function.containingFile.text.startsWith("// entryPointExists")) { - Assert.assertNotNull( - "Kotlin configuration producer should produce configuration for ${function.fqName?.asString()}", - KotlinRunConfigurationProducer.getEntryPointContainer(function) - ) - } else { - Assert.assertNull( - "Kotlin configuration producer shouldn't produce configuration for ${function.fqName?.asString()}", - KotlinRunConfigurationProducer.getEntryPointContainer(function) - ) - } - } - } - } - - createResult.srcDir.children.filter { it.extension == "kt" }.forEach { - val psiFile = PsiManager.getInstance(createResult.module.project).findFile(it) - if (psiFile is KtFile) { - psiFile.acceptChildren(object : KtVisitorVoid() { - override fun visitNamedFunction(function: KtNamedFunction) { - functionVisitor(function) - } - }) - } - } - } - - fun testDependencyModuleClasspath() { - val dependencyModuleSrcDir = configureModule(moduleDirPath("module"), getTestProject().baseDir!!).srcOutputDir - - val moduleWithDependencyDir = runWriteAction { getTestProject().baseDir!!.createChildDirectory(this, "moduleWithDependency") } - - val moduleWithDependency = createModule("moduleWithDependency") - ModuleRootModificationUtil.setModuleSdk(moduleWithDependency, testProjectJdk) - - val moduleWithDependencySrcDir = configureModule( - moduleDirPath("moduleWithDependency"), moduleWithDependencyDir, configModule = moduleWithDependency).srcOutputDir - - ModuleRootModificationUtil.addDependency(moduleWithDependency, module) - - val kotlinRunConfiguration = createConfigurationFromMain("some.test.main") - kotlinRunConfiguration.setModule(moduleWithDependency) - - val javaParameters = getJavaRunParameters(kotlinRunConfiguration) - - Assert.assertTrue(javaParameters.classPath.rootDirs.contains(dependencyModuleSrcDir)) - Assert.assertTrue(javaParameters.classPath.rootDirs.contains(moduleWithDependencySrcDir)) - } - - fun testClassesAndObjects() { - doTest(ConfigLibraryUtil::configureKotlinRuntimeAndSdk) - } - - fun testInJsModule() { - doTest(ConfigLibraryUtil::configureKotlinJsRuntimeAndSdk) - } - - fun testUpdateOnClassRename() { - val createModuleResult = configureModule(moduleDirPath("module"), getTestProject().baseDir!!) - ConfigLibraryUtil.configureKotlinRuntimeAndSdk(createModuleResult.module, addJdk(testRootDisposable, ::mockJdk)) - - val runConfiguration = createConfigurationFromObject("renameTest.Foo", save = true) - - val obj = KotlinFullClassNameIndex.getInstance().get("renameTest.Foo", getTestProject(), getTestProject().allScope()).single() - val rename = RefactoringFactory.getInstance(getTestProject()).createRename(obj, "Bar") - rename.run() - - Assert.assertEquals("renameTest.Bar", runConfiguration.MAIN_CLASS_NAME) - } - - fun testUpdateOnPackageRename() { - val createModuleResult = configureModule(moduleDirPath("module"), getTestProject().baseDir!!) - ConfigLibraryUtil.configureKotlinRuntimeAndSdk(createModuleResult.module, addJdk(testRootDisposable, ::mockJdk)) - - val runConfiguration = createConfigurationFromObject("renameTest.Foo", save = true) - - val pkg = JavaPsiFacade.getInstance(getTestProject()).findPackage("renameTest") - val rename = RefactoringFactory.getInstance(getTestProject()).createRename(pkg, "afterRenameTest") - rename.run() - - Assert.assertEquals("afterRenameTest.Foo", runConfiguration.MAIN_CLASS_NAME) - } - - fun testWithModuleForJdk6() { - checkModuleInfoName(null, addJdk(testRootDisposable, ::mockJdk)) - } - - fun testWithModuleForJdk9() { - checkModuleInfoName("MAIN", addJdk(testRootDisposable, ::mockJdk9)) - } - - fun testWithModuleForJdk9WithoutModuleInfo() { - checkModuleInfoName(null, addJdk(testRootDisposable, ::mockJdk9)) - } - - private fun checkModuleInfoName(moduleName: String?, sdk: Sdk) { - val module = configureModule(moduleDirPath("module"), getTestProject().baseDir!!).module - ConfigLibraryUtil.configureKotlinRuntimeAndSdk(module, sdk) - - val javaParameters = getJavaRunParameters(createConfigurationFromMain("some.main")) - - Assert.assertEquals(moduleName, javaParameters.moduleName) - } - - private fun doTest(configureRuntime: (Module, Sdk) -> Unit) { - val baseDir = getTestProject().baseDir!! - val createModuleResult = configureModule(moduleDirPath("module"), baseDir) - val srcDir = createModuleResult.srcDir - - configureRuntime(createModuleResult.module, addJdk(testRootDisposable, ::mockJdk)) - - try { - val expectedClasses = ArrayList() - val actualClasses = ArrayList() - - val testFile = PsiManager.getInstance(getTestProject()).findFile(srcDir.findFileByRelativePath("test.kt")!!)!! - testFile.accept( - object : KtTreeVisitorVoid() { - override fun visitComment(comment: PsiComment) { - val declaration = comment.getStrictParentOfType()!! - val text = comment.text ?: return - if (!text.startsWith(RUN_PREFIX)) return - - val expectedClass = text.substring(RUN_PREFIX.length).trim() - if (expectedClass.isNotEmpty()) expectedClasses.add(expectedClass) - - val dataContext = MapDataContext() - dataContext.put(Location.DATA_KEY, PsiLocation(getTestProject(), declaration)) - val context = ConfigurationContext.getFromContext(dataContext) - val actualClass = (context.configuration?.configuration as? KotlinRunConfiguration)?.runClass - if (actualClass != null) { - actualClasses.add(actualClass) - } - } - } - ) - Assert.assertEquals(expectedClasses, actualClasses) - } - finally { - ConfigLibraryUtil.unConfigureKotlinRuntimeAndSdk(createModuleResult.module, mockJdk()) - } - } - - private fun createConfigurationFromMain(mainFqn: String): KotlinRunConfiguration { - val mainFunction = KotlinTopLevelFunctionFqnNameIndex.getInstance().get(mainFqn, getTestProject(), getTestProject().allScope()).first() - - return createConfigurationFromElement(mainFunction) as KotlinRunConfiguration - } - - private fun createConfigurationFromObject(objectFqn: String, save: Boolean = false): KotlinRunConfiguration { - val obj = KotlinFullClassNameIndex.getInstance().get(objectFqn, getTestProject(), getTestProject().allScope()).single() - val mainFunction = obj.declarations.single { it is KtFunction && it.getName() == "main" } - return createConfigurationFromElement(mainFunction, save) as KotlinRunConfiguration - } - - private fun configureModule(moduleDir: String, outputParentDir: VirtualFile, configModule: Module = module): CreateModuleResult { - val srcPath = moduleDir + "/src" - val srcDir = PsiTestUtil.createTestProjectStructure(project, configModule, srcPath, PlatformTestCase.myFilesToDelete, true) - - val testPath = moduleDir + "/test" - if (File(testPath).exists()) { - val testDir = PsiTestUtil.createTestProjectStructure(project, configModule, testPath, PlatformTestCase.myFilesToDelete, false) - PsiTestUtil.addSourceRoot(module, testDir, true) - } - - val (srcOutDir, testOutDir) = runWriteAction { - val outDir = outputParentDir.createChildDirectory(this, "out") - val srcOutDir = outDir.createChildDirectory(this, "production") - val testOutDir = outDir.createChildDirectory(this, "test") - - PsiTestUtil.setCompilerOutputPath(configModule, srcOutDir.url, false) - PsiTestUtil.setCompilerOutputPath(configModule, testOutDir.url, true) - - Pair(srcOutDir, testOutDir) - } - - PsiDocumentManager.getInstance(getTestProject()).commitAllDocuments() - - return CreateModuleResult(configModule, srcDir, srcOutDir, testOutDir) - } - - private fun moduleDirPath(moduleName: String) = "${testDataPath}${getTestName(false)}/$moduleName" - - override fun getTestDataPath() = getTestDataPathBase() + "/run/" - override fun getTestProjectJdk() = mockJdk() - - private class CreateModuleResult( - val module: Module, - val srcDir: VirtualFile, - val srcOutputDir: VirtualFile, - val testOutputDir: VirtualFile - ) -} diff --git a/idea/tests/org/jetbrains/kotlin/psi/AbstractInjectionTest.kt.173 b/idea/tests/org/jetbrains/kotlin/psi/AbstractInjectionTest.kt.173 deleted file mode 100644 index b7ad1e09644..00000000000 --- a/idea/tests/org/jetbrains/kotlin/psi/AbstractInjectionTest.kt.173 +++ /dev/null @@ -1,128 +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.kotlin.psi - -import com.intellij.injected.editor.DocumentWindowImpl -import com.intellij.injected.editor.EditorWindow -import com.intellij.openapi.util.TextRange -import com.intellij.psi.injection.Injectable -import com.intellij.testFramework.LightProjectDescriptor -import junit.framework.TestCase -import org.intellij.lang.annotations.Language -import org.intellij.plugins.intelliLang.Configuration -import org.intellij.plugins.intelliLang.inject.InjectLanguageAction -import org.intellij.plugins.intelliLang.inject.UnInjectLanguageAction -import org.intellij.plugins.intelliLang.references.FileReferenceInjector -import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase -import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCaseBase -import org.jetbrains.kotlin.idea.test.KotlinLightProjectDescriptor -import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor - -abstract class AbstractInjectionTest : KotlinLightCodeInsightFixtureTestCase() { - override fun getProjectDescriptor(): LightProjectDescriptor { - val testName = getTestName(true) - return when { - testName.endsWith("WithAnnotation") -> KotlinLightProjectDescriptor.INSTANCE - testName.endsWith("WithRuntime") -> KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE - else -> KotlinLightCodeInsightFixtureTestCaseBase.JAVA_LATEST - } - } - - data class ShredInfo( - val range: TextRange, - val hostRange: TextRange, - val prefix: String = "", - val suffix: String = "") { - } - - protected fun doInjectionPresentTest( - @Language("kotlin") text: String, @Language("Java") javaText: String? = null, - languageId: String? = null, unInjectShouldBePresent: Boolean = true, - shreds: List? = null) { - if (javaText != null) { - myFixture.configureByText("${getTestName(true)}.java", javaText.trimIndent()) - } - - myFixture.configureByText("${getTestName(true)}.kt", text.trimIndent()) - - assertInjectionPresent(languageId, unInjectShouldBePresent) - - if (shreds != null) { - val actualShreds = (editor.document as DocumentWindowImpl).shreds.map { - ShredInfo(it.range, it.rangeInsideHost, it.prefix, it.suffix) - } - - assertOrderedEquals( - actualShreds.sortedBy { it.range.startOffset }, - shreds.sortedBy { it.range.startOffset }) - } - } - - protected fun assertInjectionPresent(languageId: String?, unInjectShouldBePresent: Boolean) { - TestCase.assertFalse("Injection action is available. There's probably no injection at caret place", - InjectLanguageAction().isAvailable(project, myFixture.editor, myFixture.file)) - - if (languageId != null) { - val injectedFile = (editor as? EditorWindow)?.injectedFile - assertEquals("Wrong injection language", languageId, injectedFile?.language?.id) - } - - if (unInjectShouldBePresent) { - TestCase.assertTrue("UnInjection action is not available. There's no injection at caret place or some other troubles.", - UnInjectLanguageAction().isAvailable(project, myFixture.editor, myFixture.file)) - } - } - - protected fun assertNoInjection(@Language("kotlin") text: String) { - myFixture.configureByText("${getTestName(true)}.kt", text.trimIndent()) - - TestCase.assertTrue("Injection action is not available. There's probably some injection but nothing was expected.", - InjectLanguageAction().isAvailable(project, myFixture.editor, myFixture.file)) - } - - protected fun doRemoveInjectionTest(@Language("kotlin") before: String, @Language("kotlin") after: String) { - myFixture.setCaresAboutInjection(false) - - myFixture.configureByText("${getTestName(true)}.kt", before.trimIndent()) - - TestCase.assertTrue(UnInjectLanguageAction().isAvailable(project, myFixture.editor, myFixture.file)) - UnInjectLanguageAction.invokeImpl(project, myFixture.editor, myFixture.file) - - myFixture.checkResult(after.trimIndent()) - } - - protected fun doFileReferenceInjectTest(@Language("kotlin") before: String, @Language("kotlin") after: String) { - doTest(FileReferenceInjector(), before, after) - } - - protected fun doTest(injectable: Injectable, @Language("kotlin") before: String, @Language("kotlin") after: String) { - val configuration = Configuration.getProjectInstance(project).advancedConfiguration - val allowed = configuration.isSourceModificationAllowed - - configuration.isSourceModificationAllowed = true - try { - myFixture.configureByText("${getTestName(true)}.kt", before.trimIndent()) - InjectLanguageAction.invokeImpl(project, myFixture.editor, myFixture.file, injectable) - myFixture.checkResult(after.trimIndent()) - } - finally { - configuration.isSourceModificationAllowed = allowed - } - } - - fun range(start: Int, end: Int) = TextRange.create(start, end) -} \ No newline at end of file diff --git a/include/kotlin-compiler/build.gradle.kts.173 b/include/kotlin-compiler/build.gradle.kts.173 deleted file mode 100644 index c5fff47f1b7..00000000000 --- a/include/kotlin-compiler/build.gradle.kts.173 +++ /dev/null @@ -1,44 +0,0 @@ - -plugins { - kotlin("jvm") -} - -val compile by configurations -val fatJarContents by configurations.creating -val fatJarContentsStripMetadata by configurations.creating -val fatJarContentsStripServices by configurations.creating - -val compilerModules: Array by rootProject.extra - -dependencies { - compilerModules.forEach { module -> - compile(project(module)) { isTransitive = false } - } - - fatJarContents(project(":core:builtins", configuration = "builtins")) - fatJarContents(commonDep("javax.inject")) - fatJarContents(commonDep("org.jline", "jline")) - fatJarContents(commonDep("org.fusesource.jansi", "jansi")) - fatJarContents(protobufFull()) - fatJarContents(commonDep("com.google.code.findbugs", "jsr305")) - fatJarContents(commonDep("io.javaslang", "javaslang")) - fatJarContents(commonDep("org.jetbrains.kotlinx", "kotlinx-coroutines-core")) { isTransitive = false } - - fatJarContents(intellijCoreDep()) { includeJars("intellij-core") } - fatJarContents(intellijDep()) { includeIntellijCoreJarDependencies(project, { !(it.startsWith("jdom") || it.startsWith("log4j")) }) } - fatJarContents(intellijDep()) { includeJars("jna-platform") } - fatJarContentsStripServices(intellijDep("jps-standalone")) { includeJars("jps-model") } - fatJarContentsStripMetadata(intellijDep()) { includeJars("oromatcher", "jdom", "log4j") } -} - -val jar: Jar by tasks -jar.apply { - dependsOn(fatJarContents) - from(compile.filter { it.extension == "jar" }.map { zipTree(it) }) - from(fatJarContents.map { zipTree(it) }) - from(fatJarContentsStripServices.map { zipTree(it) }) { exclude("META-INF/services/**") } - from(fatJarContentsStripMetadata.map { zipTree(it) }) { exclude("META-INF/jb/** META-INF/LICENSE") } - - manifest.attributes["Class-Path"] = compilerManifestClassPath - manifest.attributes["Main-Class"] = "org.jetbrains.kotlin.cli.jvm.K2JVMCompiler" -} \ No newline at end of file diff --git a/jps-plugin/jps-tests/test/org/jetbrains/kotlin/jps/build/IncrementalConstantSearchTest.kt.173 b/jps-plugin/jps-tests/test/org/jetbrains/kotlin/jps/build/IncrementalConstantSearchTest.kt.173 deleted file mode 100644 index 7a05d9e9c08..00000000000 --- a/jps-plugin/jps-tests/test/org/jetbrains/kotlin/jps/build/IncrementalConstantSearchTest.kt.173 +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2010-2015 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.jps.build - -import org.jetbrains.jps.builders.java.dependencyView.Callbacks -import com.intellij.util.concurrency.FixedFuture -import java.io.File -import java.util.concurrent.Future - -class IncrementalConstantSearchTest : AbstractIncrementalJpsTest() { - fun testJavaConstantChangedUsedInKotlin() { - doTest("jps-plugin/testData/incremental/custom/javaConstantChangedUsedInKotlin/") - } - - fun testJavaConstantUnchangedUsedInKotlin() { - doTest("jps-plugin/testData/incremental/custom/javaConstantUnchangedUsedInKotlin/") - } - - fun testKotlinConstantChangedUsedInJava() { - doTest("jps-plugin/testData/incremental/custom/kotlinConstantChangedUsedInJava/") - } - - fun testKotlinJvmFieldChangedUsedInJava() { - doTest("jps-plugin/testData/incremental/custom/kotlinJvmFieldChangedUsedInJava/") - } - - fun testKotlinConstantUnchangedUsedInJava() { - doTest("jps-plugin/testData/incremental/custom/kotlinConstantUnchangedUsedInJava/") - } - - fun testKotlinJvmFieldUnchangedUsedInJava() { - doTest("jps-plugin/testData/incremental/custom/kotlinJvmFieldUnchangedUsedInJava/") - } - - override val mockConstantSearch: Callbacks.ConstantAffectionResolver? - get() = object : Callbacks.ConstantAffectionResolver { - override fun request( - ownerClassName: String?, - fieldName: String?, - accessFlags: Int, - fieldRemoved: Boolean, - accessChanged: Boolean - ): Future { - // We emulate how constant affection service works in IDEA: - // it is able to find Kotlin usages of Java constant, but can't find Java usages of Kotlin constant - val affectedFiles = - when { - ownerClassName == "JavaClass" && fieldName == "CONST" -> listOf(File(workDir, "src/usage.kt")) - ownerClassName == "test.Klass" && fieldName == "CONST" -> listOf(File(workDir, "src/Usage.java")) - else -> emptyList() - } - - return FixedFuture(Callbacks.ConstantAffection(affectedFiles)) - } - } -} \ No newline at end of file diff --git a/jps-plugin/jps-tests/test/org/jetbrains/kotlin/jps/build/MockJavaConstantSearch.kt.173 b/jps-plugin/jps-tests/test/org/jetbrains/kotlin/jps/build/MockJavaConstantSearch.kt.173 deleted file mode 100644 index 72084d3482e..00000000000 --- a/jps-plugin/jps-tests/test/org/jetbrains/kotlin/jps/build/MockJavaConstantSearch.kt.173 +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license - * that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.jps.build - -import com.intellij.util.concurrency.FixedFuture -import org.jetbrains.jps.builders.java.dependencyView.Callbacks -import java.io.File -import java.util.concurrent.Future - -class MockJavaConstantSearch(private val workDir: File) : Callbacks.ConstantAffectionResolver { - override fun request( - ownerClassName: String, - fieldName: String, - accessFlags: Int, - fieldRemoved: Boolean, - accessChanged: Boolean - ): Future { - val affectedFiles = workDir.walk().filter { it.isFile && it.isNameUsage() } - return FixedFuture(Callbacks.ConstantAffection(affectedFiles.toList())) - } - - private fun File.isNameUsage(): Boolean = - name.equals("usage.kt", ignoreCase = true) - || name.equals("usage.java", ignoreCase = true) -} \ No newline at end of file diff --git a/jps-plugin/resources/META-INF/services/org.jetbrains.jps.builders.java.JavaBuilderExtension.173 b/jps-plugin/resources/META-INF/services/org.jetbrains.jps.builders.java.JavaBuilderExtension.173 deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinJavaBuilderExtension.kt.173 b/jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinJavaBuilderExtension.kt.173 deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/jps-plugin/src/org/jetbrains/kotlin/jps/build/ideaPlatform.kt.173 b/jps-plugin/src/org/jetbrains/kotlin/jps/build/ideaPlatform.kt.173 deleted file mode 100644 index c014f4b30fa..00000000000 --- a/jps-plugin/src/org/jetbrains/kotlin/jps/build/ideaPlatform.kt.173 +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license - * that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.jps.build - -import org.jetbrains.jps.incremental.CompileContext -import org.jetbrains.jps.incremental.messages.CompilerMessage - -fun jpsReportInternalBuilderError(context: CompileContext, error: Throwable) { - KotlinBuilder.LOG.info(error) -} \ No newline at end of file diff --git a/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/model/impl/AndroidModuleInfoProviderImpl.kt.173 b/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/model/impl/AndroidModuleInfoProviderImpl.kt.173 deleted file mode 100644 index 548206fdc8e..00000000000 --- a/plugins/android-extensions/android-extensions-idea/src/org/jetbrains/kotlin/android/model/impl/AndroidModuleInfoProviderImpl.kt.173 +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license - * that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.android.model.impl - -import com.android.builder.model.SourceProvider -import com.android.tools.idea.gradle.project.GradleProjectInfo -import com.android.tools.idea.gradle.project.model.AndroidModuleModel -import com.intellij.openapi.module.Module -import com.intellij.openapi.vfs.VirtualFile -import org.jetbrains.android.facet.AndroidFacet -import org.jetbrains.kotlin.android.model.AndroidModuleInfoProvider -import java.io.File - -class AndroidModuleInfoProviderImpl(override val module: Module) : AndroidModuleInfoProvider { - private val androidFacet: AndroidFacet? - get() = AndroidFacet.getInstance(module) - - private val androidModuleModel: AndroidModuleModel? - get() = AndroidModuleModel.get(module) - - override fun isAndroidModule() = androidFacet != null - override fun isGradleModule() = GradleProjectInfo.getInstance(module.project).isBuildWithGradle - - override fun getAllResourceDirectories(): List { - return androidFacet?.allResourceDirectories ?: emptyList() - } - - override fun getApplicationPackage() = androidFacet?.manifest?.`package`?.toString() - - override fun getMainSourceProvider(): AndroidModuleInfoProvider.SourceProviderMirror? { - return androidFacet?.mainSourceProvider?.let(::SourceProviderMirrorImpl) - } - - override fun getApplicationResourceDirectories(createIfNecessary: Boolean): Collection { - return androidFacet?.getAppResources(createIfNecessary)?.resourceDirs ?: emptyList() - } - - override fun getAllSourceProviders(): List { - val androidModuleModel = this.androidModuleModel ?: return emptyList() - return androidModuleModel.allSourceProviders.map(::SourceProviderMirrorImpl) - } - - override fun getActiveSourceProviders(): List { - val androidModuleModel = this.androidModuleModel ?: return emptyList() - return androidModuleModel.activeSourceProviders.map(::SourceProviderMirrorImpl) - } - - override fun getFlavorSourceProviders(): List { - val androidModuleModel = this.androidModuleModel ?: return emptyList() - - val getFlavorSourceProvidersMethod = try { - AndroidFacet::class.java.getMethod("getFlavorSourceProviders") - } catch (e: NoSuchMethodException) { - null - } - - return if (getFlavorSourceProvidersMethod != null) { - @Suppress("UNCHECKED_CAST") - val sourceProviders = getFlavorSourceProvidersMethod.invoke(androidFacet) as? List - sourceProviders?.map(::SourceProviderMirrorImpl) ?: emptyList() - } else { - androidModuleModel.flavorSourceProviders.map(::SourceProviderMirrorImpl) - } - } - - private class SourceProviderMirrorImpl(val sourceProvider: SourceProvider) : - AndroidModuleInfoProvider.SourceProviderMirror { - override val name: String - get() = sourceProvider.name - - override val resDirectories: Collection - get() = sourceProvider.resDirectories - } -} \ No newline at end of file diff --git a/plugins/lint/android-annotations/src/com/android/annotations/NonNull.java.173 b/plugins/lint/android-annotations/src/com/android/annotations/NonNull.java.173 deleted file mode 100644 index d16451b60a9..00000000000 --- a/plugins/lint/android-annotations/src/com/android/annotations/NonNull.java.173 +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2011 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.annotations; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.*; - -/** - * Denotes that a parameter, field or method return value can never be null. - *

- * This is a marker annotation and it has no specific attributes. - */ -@Documented -@Retention(RetentionPolicy.CLASS) -@Target({METHOD,PARAMETER,LOCAL_VARIABLE,FIELD}) -public @interface NonNull { -} diff --git a/plugins/lint/android-annotations/src/com/android/annotations/NonNullByDefault.java.173 b/plugins/lint/android-annotations/src/com/android/annotations/NonNullByDefault.java.173 deleted file mode 100644 index 9ce54d86833..00000000000 --- a/plugins/lint/android-annotations/src/com/android/annotations/NonNullByDefault.java.173 +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2011 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.annotations; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.PACKAGE; -import static java.lang.annotation.ElementType.TYPE; - -/** - * Denotes that all parameters, fields or methods within a class or method by - * default can not be null. This can be overridden by adding specific - * {@link com.android.annotations.Nullable} annotations on fields, parameters or - * methods that should not use the default. - *

- * NOTE: Eclipse does not yet handle defaults well (in particular, if - * you add this on a class which implements Comparable, then it will insist - * that your compare method is changing the nullness of the compare parameter, - * so you'll need to add @Nullable on it, which also is not right (since - * the method should have implied @NonNull and you do not need to check - * the parameter.). For now, it's best to individually annotate methods, - * parameters and fields. - *

- * This is a marker annotation and it has no specific attributes. - */ -@Documented -@Retention(RetentionPolicy.CLASS) -@Target({PACKAGE, TYPE}) -public @interface NonNullByDefault { -} diff --git a/plugins/lint/android-annotations/src/com/android/annotations/Nullable.java.173 b/plugins/lint/android-annotations/src/com/android/annotations/Nullable.java.173 deleted file mode 100644 index a0377cb6704..00000000000 --- a/plugins/lint/android-annotations/src/com/android/annotations/Nullable.java.173 +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2011 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.annotations; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.*; - -/** - * Denotes that a parameter, field or method return value can be null. - * Note: this is the default assumption for most Java APIs and the - * default assumption made by most static code checking tools, so usually you - * don't need to use this annotation; its primary use is to override a default - * wider annotation like {@link NonNullByDefault}. - *

- * When decorating a method call parameter, this denotes the parameter can - * legitimately be null and the method will gracefully deal with it. Typically - * used on optional parameters. - *

- * When decorating a method, this denotes the method might legitimately return - * null. - *

- * This is a marker annotation and it has no specific attributes. - */ -@Documented -@Retention(RetentionPolicy.CLASS) -@Target({METHOD, PARAMETER, LOCAL_VARIABLE, FIELD}) -public @interface Nullable { -} diff --git a/plugins/lint/android-annotations/src/com/android/annotations/VisibleForTesting.java.173 b/plugins/lint/android-annotations/src/com/android/annotations/VisibleForTesting.java.173 deleted file mode 100644 index 7f41d70e0f5..00000000000 --- a/plugins/lint/android-annotations/src/com/android/annotations/VisibleForTesting.java.173 +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2011 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.annotations; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * Denotes that the class, method or field has its visibility relaxed so - * that unit tests can access it. - *

- * The visibility argument can be used to specific what the original - * visibility should have been if it had not been made public or package-private for testing. - * The default is to consider the element private. - */ -@Retention(RetentionPolicy.SOURCE) -public @interface VisibleForTesting { - /** - * Intended visibility if the element had not been made public or package-private for - * testing. - */ - enum Visibility { - /** The element should be considered protected. */ - PROTECTED, - /** The element should be considered package-private. */ - PACKAGE, - /** The element should be considered private. */ - PRIVATE - } - - /** - * Intended visibility if the element had not been made public or package-private for testing. - * If not specified, one should assume the element originally intended to be private. - */ - Visibility visibility() default Visibility.PRIVATE; -} diff --git a/plugins/lint/android-annotations/src/com/android/annotations/concurrency/GuardedBy.java.173 b/plugins/lint/android-annotations/src/com/android/annotations/concurrency/GuardedBy.java.173 deleted file mode 100644 index 5a151acc8b8..00000000000 --- a/plugins/lint/android-annotations/src/com/android/annotations/concurrency/GuardedBy.java.173 +++ /dev/null @@ -1,30 +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 com.android.annotations.concurrency; - -import java.lang.annotation.*; - -/** - * Indicates that the target field or method should only be accessed - * with the specified lock being held. - */ -@Documented -@Retention(RetentionPolicy.CLASS) -@Target({ElementType.METHOD, ElementType.FIELD}) -public @interface GuardedBy { - String value(); -} diff --git a/plugins/lint/android-annotations/src/com/android/annotations/concurrency/Immutable.java.173 b/plugins/lint/android-annotations/src/com/android/annotations/concurrency/Immutable.java.173 deleted file mode 100644 index c83f9f0ffc9..00000000000 --- a/plugins/lint/android-annotations/src/com/android/annotations/concurrency/Immutable.java.173 +++ /dev/null @@ -1,29 +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 com.android.annotations.concurrency; - -import java.lang.annotation.*; - -/** - * Indicates that the target class to which this annotation is applied - * is immutable. - */ -@Documented -@Retention(RetentionPolicy.CLASS) -@Target(ElementType.TYPE) -public @interface Immutable { -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/AndroidReference.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/client/api/AndroidReference.java.173 deleted file mode 100644 index db26881cc6f..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/AndroidReference.java.173 +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2016 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.client.api; - -import static com.android.SdkConstants.ANDROID_PKG; - -import com.android.annotations.NonNull; -import com.android.resources.ResourceType; - -import org.jetbrains.uast.UExpression; - -public class AndroidReference { - public final UExpression node; - - private final String rPackage; - - private final ResourceType type; - - private final String name; - - // getPackage() can be empty if not a package-qualified import (e.g. android.R.id.name). - @NonNull - public String getPackage() { - return rPackage; - } - - @NonNull - public ResourceType getType() { - return type; - } - - @NonNull - public String getName() { - return name; - } - - boolean isFramework() { - return rPackage.equals(ANDROID_PKG); - } - - public AndroidReference( - UExpression node, - String rPackage, - ResourceType type, - String name) { - this.node = node; - this.rPackage = rPackage; - this.type = type; - this.name = name; - } -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/AsmVisitor.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/client/api/AsmVisitor.java.173 deleted file mode 100644 index 9c8c8611bab..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/AsmVisitor.java.173 +++ /dev/null @@ -1,202 +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.client.api; - -import com.android.annotations.NonNull; -import com.android.tools.klint.detector.api.ClassContext; -import com.android.tools.klint.detector.api.Detector; -import com.android.tools.klint.detector.api.Detector.ClassScanner; -import com.google.common.annotations.Beta; - -import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode; -import org.jetbrains.org.objectweb.asm.tree.ClassNode; -import org.jetbrains.org.objectweb.asm.tree.InsnList; -import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode; -import org.jetbrains.org.objectweb.asm.tree.MethodNode; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Specialized visitor for running detectors on a class object model. - *

- * It operates in two phases: - *

    - *
  1. First, it computes a set of maps where it generates a map from each - * significant method name to a list of detectors to consult for that method - * name. The set of method names that a detector is interested in is provided - * by the detectors themselves. - *
  2. Second, it iterates over the DOM a single time. For each method call it finds, - * it dispatches to any check that has registered interest in that method name. - *
  3. Finally, it runs a full check on those class scanners that do not register - * specific method names to be checked. This is intended for those detectors - * that do custom work, not related specifically to method calls. - *
- * It also notifies all the detectors before and after the document is processed - * such that they can do pre- and post-processing. - *

- * NOTE: This is not a public or final API; if you rely on this be prepared - * to adjust your code for the next tools release. - */ -@Beta -class AsmVisitor { - /** - * Number of distinct node types specified in {@link AbstractInsnNode}. Sadly - * there isn't a max-constant there, so update this along with ASM library - * updates. - */ - private static final int TYPE_COUNT = AbstractInsnNode.LINE + 1; - private final Map> mMethodNameToChecks = - new HashMap>(); - private final Map> mMethodOwnerToChecks = - new HashMap>(); - private final List mFullClassChecks = new ArrayList(); - - private final List mAllDetectors; - private List[] mNodeTypeDetectors; - - // Really want this: - // & Detector.ClassScanner> ClassVisitor(T xmlDetectors) { - // but it makes client code tricky and ugly. - @SuppressWarnings("unchecked") - AsmVisitor(@NonNull LintClient client, @NonNull List classDetectors) { - mAllDetectors = classDetectors; - - // TODO: Check appliesTo() for files, and find a quick way to enable/disable - // rules when running through a full project! - for (Detector detector : classDetectors) { - Detector.ClassScanner scanner = (Detector.ClassScanner) detector; - - boolean checkFullClass = true; - - Collection names = scanner.getApplicableCallNames(); - if (names != null) { - checkFullClass = false; - for (String element : names) { - List list = mMethodNameToChecks.get(element); - if (list == null) { - list = new ArrayList(); - mMethodNameToChecks.put(element, list); - } - list.add(scanner); - } - } - - Collection owners = scanner.getApplicableCallOwners(); - if (owners != null) { - checkFullClass = false; - for (String element : owners) { - List list = mMethodOwnerToChecks.get(element); - if (list == null) { - list = new ArrayList(); - mMethodOwnerToChecks.put(element, list); - } - list.add(scanner); - } - } - - int[] types = scanner.getApplicableAsmNodeTypes(); - if (types != null) { - checkFullClass = false; - for (int type : types) { - if (type < 0 || type >= TYPE_COUNT) { - // Can't support this node type: looks like ASM wasn't updated correctly. - client.log(null, "Out of range node type %1$d from detector %2$s", - type, scanner); - continue; - } - if (mNodeTypeDetectors == null) { - mNodeTypeDetectors = new List[TYPE_COUNT]; - } - List checks = mNodeTypeDetectors[type]; - if (checks == null) { - checks = new ArrayList(); - mNodeTypeDetectors[type] = checks; - } - checks.add(scanner); - } - } - - if (checkFullClass) { - mFullClassChecks.add(detector); - } - } - } - - @SuppressWarnings("rawtypes") // ASM API uses raw types - void runClassDetectors(ClassContext context) { - ClassNode classNode = context.getClassNode(); - - for (Detector detector : mAllDetectors) { - detector.beforeCheckFile(context); - } - - for (Detector detector : mFullClassChecks) { - Detector.ClassScanner scanner = (Detector.ClassScanner) detector; - scanner.checkClass(context, classNode); - detector.afterCheckFile(context); - } - - if (!mMethodNameToChecks.isEmpty() || !mMethodOwnerToChecks.isEmpty() || - mNodeTypeDetectors != null && mNodeTypeDetectors.length > 0) { - List methodList = classNode.methods; - for (Object m : methodList) { - MethodNode method = (MethodNode) m; - InsnList nodes = method.instructions; - for (int i = 0, n = nodes.size(); i < n; i++) { - AbstractInsnNode instruction = nodes.get(i); - int type = instruction.getType(); - if (type == AbstractInsnNode.METHOD_INSN) { - MethodInsnNode call = (MethodInsnNode) instruction; - - String owner = call.owner; - List scanners = mMethodOwnerToChecks.get(owner); - if (scanners != null) { - for (ClassScanner scanner : scanners) { - scanner.checkCall(context, classNode, method, call); - } - } - - String name = call.name; - scanners = mMethodNameToChecks.get(name); - if (scanners != null) { - for (ClassScanner scanner : scanners) { - scanner.checkCall(context, classNode, method, call); - } - } - } - - if (mNodeTypeDetectors != null && type < mNodeTypeDetectors.length) { - List scanners = mNodeTypeDetectors[type]; - if (scanners != null) { - for (ClassScanner scanner : scanners) { - scanner.checkInstruction(context, classNode, method, instruction); - } - } - } - } - } - } - - for (Detector detector : mAllDetectors) { - detector.afterCheckFile(context); - } - } -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/CircularDependencyException.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/client/api/CircularDependencyException.java.173 deleted file mode 100644 index 94020e080df..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/CircularDependencyException.java.173 +++ /dev/null @@ -1,81 +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.client.api; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.tools.klint.detector.api.Location; -import com.android.tools.klint.detector.api.Project; -import com.google.common.annotations.Beta; - -/** - * Exception thrown when there is a circular dependency, such as a circular dependency - * of library mProject references - *

- * NOTE: This is not a public or final API; if you rely on this be prepared - * to adjust your code for the next tools release. - */ -@Beta -public class CircularDependencyException extends RuntimeException { - @Nullable - private Project mProject; - - @Nullable - private Location mLocation; - - CircularDependencyException(@NonNull String message) { - super(message); - } - - /** - * Returns the associated project, if any - * - * @return the associated project, if any - */ - @Nullable - public Project getProject() { - return mProject; - } - - /** - * Sets the associated project, if any - * - * @param project the associated project, if any - */ - public void setProject(@Nullable Project project) { - mProject = project; - } - - /** - * Returns the associated location, if any - * - * @return the associated location, if any - */ - @Nullable - public Location getLocation() { - return mLocation; - } - - /** - * Sets the associated location, if any - * - * @param location the associated location, if any - */ - public void setLocation(@Nullable Location location) { - mLocation = location; - } -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/ClassEntry.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/client/api/ClassEntry.java.173 deleted file mode 100644 index 4e3a74f7502..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/ClassEntry.java.173 +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Copyright (C) 2015 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.client.api; - -import static com.android.SdkConstants.DOT_CLASS; -import static com.android.SdkConstants.DOT_JAR; -import static org.jetbrains.org.objectweb.asm.Opcodes.API_VERSION; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.annotations.VisibleForTesting; -import com.google.common.collect.Maps; -import com.google.common.io.ByteStreams; -import com.google.common.io.Closeables; - -import org.jetbrains.org.objectweb.asm.ClassReader; -import org.jetbrains.org.objectweb.asm.ClassVisitor; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; - -/** A class, present either as a .class file on disk, or inside a .jar file. */ -@VisibleForTesting -class ClassEntry implements Comparable { - public final File file; - public final File jarFile; - public final File binDir; - public final byte[] bytes; - - @VisibleForTesting - ClassEntry( - @NonNull File file, - @Nullable File jarFile, - @NonNull File binDir, - @NonNull byte[] bytes) { - super(); - this.file = file; - this.jarFile = jarFile; - this.binDir = binDir; - this.bytes = bytes; - } - - @NonNull - public String path() { - if (jarFile != null) { - return jarFile.getPath() + ':' + file.getPath(); - } else { - return file.getPath(); - } - } - - @Override - public int compareTo(@NonNull ClassEntry other) { - String p1 = file.getPath(); - String p2 = other.file.getPath(); - int m1 = p1.length(); - int m2 = p2.length(); - if (m1 == m2 && p1.equals(p2)) { - return 0; - } - int m = Math.min(m1, m2); - - for (int i = 0; i < m; i++) { - char c1 = p1.charAt(i); - char c2 = p2.charAt(i); - if (c1 != c2) { - // Sort Foo$Bar.class *after* Foo.class, even though $ < . - if (c1 == '.' && c2 == '$') { - return -1; - } - if (c1 == '$' && c2 == '.') { - return 1; - } - return c1 - c2; - } - } - - return (m == m1) ? -1 : 1; - } - - @Override - public String toString() { - return file.getPath(); - } - - /** - * Creates a list of class entries from the given class path. - * - * @param client the client to report errors to and to use to read files - * @param classPath the class path (directories and jar files) to scan - * @param sort if true, sort the results - * @return the list of class entries, never null. - */ - @NonNull - public static List fromClassPath( - @NonNull LintClient client, - @NonNull List classPath, - boolean sort) { - if (!classPath.isEmpty()) { - List libraryEntries = new ArrayList(64); - addEntries(client, libraryEntries, classPath); - if (sort) { - Collections.sort(libraryEntries); - } - return libraryEntries; - } else { - return Collections.emptyList(); - } - } - - /** - * Creates a list of class entries from the given class path and specific set of - * files within it. - * - * @param client the client to report errors to and to use to read files - * @param classFiles the specific set of class files to look for - * @param classFolders the list of class folders to look in (to determine the - * package root) - * @param sort if true, sort the results - * @return the list of class entries, never null. - */ - @NonNull - public static List fromClassFiles( - @NonNull LintClient client, - @NonNull List classFiles, @NonNull List classFolders, - boolean sort) { - List entries = new ArrayList(classFiles.size()); - - if (!classFolders.isEmpty()) { - for (File file : classFiles) { - String path = file.getPath(); - if (file.isFile() && path.endsWith(DOT_CLASS)) { - try { - byte[] bytes = client.readBytes(file); - for (File dir : classFolders) { - if (path.startsWith(dir.getPath())) { - entries.add(new ClassEntry(file, null /* jarFile*/, dir, - bytes)); - break; - } - } - } catch (IOException e) { - client.log(e, null); - } - } - } - - if (sort && !entries.isEmpty()) { - Collections.sort(entries); - } - } - - return entries; - } - - /** - * Given a classpath, add all the class files found within the directories and inside jar files - */ - private static void addEntries( - @NonNull LintClient client, - @NonNull List entries, - @NonNull List classPath) { - for (File classPathEntry : classPath) { - if (classPathEntry.getName().endsWith(DOT_JAR)) { - //noinspection UnnecessaryLocalVariable - File jarFile = classPathEntry; - if (!jarFile.exists()) { - continue; - } - ZipInputStream zis = null; - try { - FileInputStream fis = new FileInputStream(jarFile); - try { - zis = new ZipInputStream(fis); - ZipEntry entry = zis.getNextEntry(); - while (entry != null) { - String name = entry.getName(); - if (name.endsWith(DOT_CLASS)) { - try { - byte[] bytes = ByteStreams.toByteArray(zis); - if (bytes != null) { - File file = new File(entry.getName()); - entries.add(new ClassEntry(file, jarFile, jarFile, bytes)); - } - } catch (Exception e) { - client.log(e, null); - continue; - } - } - - entry = zis.getNextEntry(); - } - } finally { - Closeables.close(fis, true); - } - } catch (IOException e) { - client.log(e, "Could not read jar file contents from %1$s", jarFile); - } finally { - try { - Closeables.close(zis, true); - } catch (IOException e) { - // cannot happen - } - } - } else if (classPathEntry.isDirectory()) { - //noinspection UnnecessaryLocalVariable - File binDir = classPathEntry; - List classFiles = new ArrayList(); - addClassFiles(binDir, classFiles); - - for (File file : classFiles) { - try { - byte[] bytes = client.readBytes(file); - entries.add(new ClassEntry(file, null /* jarFile*/, binDir, bytes)); - } catch (IOException e) { - client.log(e, null); - } - } - } else { - client.log(null, "Ignoring class path entry %1$s", classPathEntry); - } - } - } - - /** Adds in all the .class files found recursively in the given directory */ - private static void addClassFiles(@NonNull File dir, @NonNull List classFiles) { - // Process the resource folder - File[] files = dir.listFiles(); - if (files != null && files.length > 0) { - for (File file : files) { - if (file.isFile() && file.getName().endsWith(DOT_CLASS)) { - classFiles.add(file); - } else if (file.isDirectory()) { - // Recurse - addClassFiles(file, classFiles); - } - } - } - } - - /** - * Creates a super class map (from class to its super class) for the given set of entries - * - * @param client the client to report errors to and to use to access files - * @param libraryEntries the set of library entries to consult - * @param classEntries the set of class entries to consult - * @return a map from name to super class internal names - */ - @NonNull - public static Map createSuperClassMap( - @NonNull LintClient client, - @NonNull List libraryEntries, - @NonNull List classEntries) { - int size = libraryEntries.size() + classEntries.size(); - Map map = Maps.newHashMapWithExpectedSize(size); - SuperclassVisitor visitor = new SuperclassVisitor(map); - addSuperClasses(client, visitor, libraryEntries); - addSuperClasses(client, visitor, classEntries); - return map; - } - - /** - * Creates a super class map (from class to its super class) for the given set of entries - * - * @param client the client to report errors to and to use to access files - * @param entries the set of library entries to consult - * @return a map from name to super class internal names - */ - @NonNull - public static Map createSuperClassMap( - @NonNull LintClient client, - @NonNull List entries) { - Map map = Maps.newHashMapWithExpectedSize(entries.size()); - SuperclassVisitor visitor = new SuperclassVisitor(map); - addSuperClasses(client, visitor, entries); - return map; - } - - /** Adds in all the super classes found for the given class entries into the given map */ - private static void addSuperClasses( - @NonNull LintClient client, - @NonNull SuperclassVisitor visitor, - @NonNull List entries) { - for (ClassEntry entry : entries) { - try { - ClassReader reader = new ClassReader(entry.bytes); - int flags = ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG - | ClassReader.SKIP_FRAMES; - reader.accept(visitor, flags); - } catch (Throwable t) { - client.log(null, "Error processing %1$s: broken class file?", entry.path()); - } - } - } - - /** Visitor skimming classes and initializing a map of super classes */ - private static class SuperclassVisitor extends ClassVisitor { - private final Map mMap; - - public SuperclassVisitor(Map map) { - super(API_VERSION); - mMap = map; - } - - @Override - public void visit(int version, int access, String name, String signature, String superName, - String[] interfaces) { - // Record super class in the map (but don't waste space on java.lang.Object) - if (superName != null && !"java/lang/Object".equals(superName)) { - mMap.put(name, superName); - } - } - } -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/CompositeIssueRegistry.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/client/api/CompositeIssueRegistry.java.173 deleted file mode 100644 index b66a8418d6f..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/CompositeIssueRegistry.java.173 +++ /dev/null @@ -1,52 +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 com.android.tools.klint.client.api; - -import com.android.annotations.NonNull; -import com.android.tools.klint.detector.api.Issue; -import com.google.common.collect.Lists; - -import java.util.List; - -/** - * Registry which merges many issue registries into one, and presents a unified list - * of issues. - *

- * NOTE: This is not a public or final API; if you rely on this be prepared - * to adjust your code for the next tools release. - */ -class CompositeIssueRegistry extends IssueRegistry { - private final List myRegistries; - private List myIssues; - - public CompositeIssueRegistry(@NonNull List registries) { - myRegistries = registries; - } - - @NonNull - @Override - public List getIssues() { - if (myIssues == null) { - List issues = Lists.newArrayListWithExpectedSize(200); - for (IssueRegistry registry : myRegistries) { - issues.addAll(registry.getIssues()); - } - myIssues = issues; - } - - return myIssues; - } -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/Configuration.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/client/api/Configuration.java.173 deleted file mode 100644 index 5952b101f6b..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/Configuration.java.173 +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2011 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.client.api; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.tools.klint.detector.api.Context; -import com.android.tools.klint.detector.api.Issue; -import com.android.tools.klint.detector.api.Location; -import com.android.tools.klint.detector.api.Severity; -import com.google.common.annotations.Beta; - -/** - * Lint configuration for an Android project such as which specific rules to include, - * which specific rules to exclude, and which specific errors to ignore. - *

- * NOTE: This is not a public or final API; if you rely on this be prepared - * to adjust your code for the next tools release. - */ -@Beta -public abstract class Configuration { - /** - * Checks whether this issue should be ignored because the user has already - * suppressed the error? Note that this refers to individual issues being - * suppressed/ignored, not a whole detector being disabled via something - * like {@link #isEnabled(Issue)}. - * - * @param context the context used by the detector when the issue was found - * @param issue the issue that was found - * @param location the location of the issue - * @param message the associated user message - * @return true if this issue should be suppressed - */ - public boolean isIgnored( - @NonNull Context context, - @NonNull Issue issue, - @Nullable Location location, - @NonNull String message) { - return false; - } - - /** - * Returns false if the given issue has been disabled. This is just - * a convenience method for {@code getSeverity(issue) != Severity.IGNORE}. - * - * @param issue the issue to check - * @return false if the issue has been disabled - */ - public boolean isEnabled(@NonNull Issue issue) { - return getSeverity(issue) != Severity.IGNORE; - } - - /** - * Returns the severity for a given issue. This is the same as the - * {@link Issue#getDefaultSeverity()} unless the user has selected a custom - * severity (which is tool context dependent). - * - * @param issue the issue to look up the severity from - * @return the severity use for issues for the given detector - */ - public Severity getSeverity(@NonNull Issue issue) { - return issue.getDefaultSeverity(); - } - - // Editing configurations - - /** - * Marks the given warning as "ignored". - * - * @param context The scanning context - * @param issue the issue to be ignored - * @param location The location to ignore the warning at, if any - * @param message The message for the warning - */ - public abstract void ignore( - @NonNull Context context, - @NonNull Issue issue, - @Nullable Location location, - @NonNull String message); - - /** - * Sets the severity to be used for this issue. - * - * @param issue the issue to set the severity for - * @param severity the severity to associate with this issue, or null to - * reset the severity to the default - */ - public abstract void setSeverity(@NonNull Issue issue, @Nullable Severity severity); - - // Bulk editing support - - /** - * Marks the beginning of a "bulk" editing operation with repeated calls to - * {@link #setSeverity} or {@link #ignore}. After all the values have been - * set, the client must call {@link #finishBulkEditing()}. This - * allows configurations to avoid doing expensive I/O (such as writing out a - * config XML file) for each and every editing operation when they are - * applied in bulk, such as from a configuration dialog's "Apply" action. - */ - public void startBulkEditing() { - } - - /** - * Marks the end of a "bulk" editing operation, where values should be - * committed to persistent storage. See {@link #startBulkEditing()} for - * details. - */ - public void finishBulkEditing() { - } -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/DefaultConfiguration.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/client/api/DefaultConfiguration.java.173 deleted file mode 100644 index eb2d9f09ae6..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/DefaultConfiguration.java.173 +++ /dev/null @@ -1,608 +0,0 @@ -/* - * Copyright (C) 2011 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.client.api; - -import static com.android.SdkConstants.CURRENT_PLATFORM; -import static com.android.SdkConstants.PLATFORM_WINDOWS; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.tools.klint.detector.api.Context; -import com.android.tools.klint.detector.api.Issue; -import com.android.tools.klint.detector.api.Location; -import com.android.tools.klint.detector.api.Project; -import com.android.tools.klint.detector.api.Severity; -import com.android.tools.klint.detector.api.TextFormat; -import com.android.utils.XmlUtils; -import com.google.common.annotations.Beta; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Splitter; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.xml.sax.SAXParseException; - -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.Writer; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.regex.PatternSyntaxException; - -/** - * Default implementation of a {@link Configuration} which reads and writes - * configuration data into {@code lint.xml} in the project directory. - *

- * NOTE: This is not a public or final API; if you rely on this be prepared - * to adjust your code for the next tools release. - */ -@Beta -public class DefaultConfiguration extends Configuration { - private final LintClient mClient; - /** Default name of the configuration file */ - public static final String CONFIG_FILE_NAME = "lint.xml"; //$NON-NLS-1$ - - // Lint XML File - @NonNull - private static final String TAG_ISSUE = "issue"; //$NON-NLS-1$ - @NonNull - private static final String ATTR_ID = "id"; //$NON-NLS-1$ - @NonNull - private static final String ATTR_SEVERITY = "severity"; //$NON-NLS-1$ - @NonNull - private static final String ATTR_PATH = "path"; //$NON-NLS-1$ - @NonNull - private static final String ATTR_REGEXP = "regexp"; //$NON-NLS-1$ - @NonNull - private static final String TAG_IGNORE = "ignore"; //$NON-NLS-1$ - @NonNull - private static final String VALUE_ALL = "all"; //$NON-NLS-1$ - - private final Configuration mParent; - private final Project mProject; - private final File mConfigFile; - private boolean mBulkEditing; - - /** Map from id to list of project-relative paths for suppressed warnings */ - private Map> mSuppressed; - - /** Map from id to regular expressions. */ - @Nullable - private Map> mRegexps; - - /** - * Map from id to custom {@link Severity} override - */ - private Map mSeverity; - - protected DefaultConfiguration( - @NonNull LintClient client, - @Nullable Project project, - @Nullable Configuration parent, - @NonNull File configFile) { - mClient = client; - mProject = project; - mParent = parent; - mConfigFile = configFile; - } - - protected DefaultConfiguration( - @NonNull LintClient client, - @NonNull Project project, - @Nullable Configuration parent) { - this(client, project, parent, new File(project.getDir(), CONFIG_FILE_NAME)); - } - - /** - * Creates a new {@link DefaultConfiguration} - * - * @param client the client to report errors to etc - * @param project the associated project - * @param parent the parent/fallback configuration or null - * @return a new configuration - */ - @NonNull - public static DefaultConfiguration create( - @NonNull LintClient client, - @NonNull Project project, - @Nullable Configuration parent) { - return new DefaultConfiguration(client, project, parent); - } - - /** - * Creates a new {@link DefaultConfiguration} for the given lint config - * file, not affiliated with a project. This is used for global - * configurations. - * - * @param client the client to report errors to etc - * @param lintFile the lint file containing the configuration - * @return a new configuration - */ - @NonNull - public static DefaultConfiguration create(@NonNull LintClient client, @NonNull File lintFile) { - return new DefaultConfiguration(client, null /*project*/, null /*parent*/, lintFile); - } - - @Override - public boolean isIgnored( - @NonNull Context context, - @NonNull Issue issue, - @Nullable Location location, - @NonNull String message) { - ensureInitialized(); - - String id = issue.getId(); - List paths = mSuppressed.get(id); - if (paths == null) { - paths = mSuppressed.get(VALUE_ALL); - } - if (paths != null && location != null) { - File file = location.getFile(); - String relativePath = context.getProject().getRelativePath(file); - for (String suppressedPath : paths) { - if (suppressedPath.equals(relativePath)) { - return true; - } - // Also allow a prefix - if (relativePath.startsWith(suppressedPath)) { - return true; - } - } - } - - if (mRegexps != null) { - List regexps = mRegexps.get(id); - if (regexps == null) { - regexps = mRegexps.get(VALUE_ALL); - } - if (regexps != null && location != null) { - // Check message - for (Pattern regexp : regexps) { - Matcher matcher = regexp.matcher(message); - if (matcher.find()) { - return true; - } - } - - // Check location - File file = location.getFile(); - String relativePath = context.getProject().getRelativePath(file); - boolean checkUnixPath = false; - for (Pattern regexp : regexps) { - Matcher matcher = regexp.matcher(relativePath); - if (matcher.find()) { - return true; - } else if (regexp.pattern().indexOf('/') != -1) { - checkUnixPath = true; - } - } - - if (checkUnixPath && CURRENT_PLATFORM == PLATFORM_WINDOWS) { - relativePath = relativePath.replace('\\', '/'); - for (Pattern regexp : regexps) { - Matcher matcher = regexp.matcher(relativePath); - if (matcher.find()) { - return true; - } - } - } - } - } - - return mParent != null && mParent.isIgnored(context, issue, location, message); - } - - @NonNull - protected Severity getDefaultSeverity(@NonNull Issue issue) { - if (!issue.isEnabledByDefault()) { - return Severity.IGNORE; - } - - return issue.getDefaultSeverity(); - } - - @Override - @NonNull - public Severity getSeverity(@NonNull Issue issue) { - ensureInitialized(); - - Severity severity = mSeverity.get(issue.getId()); - if (severity == null) { - severity = mSeverity.get(VALUE_ALL); - } - - if (severity != null) { - return severity; - } - - if (mParent != null) { - return mParent.getSeverity(issue); - } - - return getDefaultSeverity(issue); - } - - private void ensureInitialized() { - if (mSuppressed == null) { - readConfig(); - } - } - - private void formatError(String message, Object... args) { - if (args != null && args.length > 0) { - message = String.format(message, args); - } - message = "Failed to parse `lint.xml` configuration file: " + message; - LintDriver driver = new LintDriver(new IssueRegistry() { - @Override @NonNull public List getIssues() { - return Collections.emptyList(); - } - }, mClient); - mClient.report(new Context(driver, mProject, mProject, mConfigFile), - IssueRegistry.LINT_ERROR, - mProject.getConfiguration(driver).getSeverity(IssueRegistry.LINT_ERROR), - Location.create(mConfigFile), message, TextFormat.RAW); - } - - private void readConfig() { - mSuppressed = new HashMap>(); - mSeverity = new HashMap(); - - if (!mConfigFile.exists()) { - return; - } - - try { - Document document = XmlUtils.parseUtfXmlFile(mConfigFile, false); - NodeList issues = document.getElementsByTagName(TAG_ISSUE); - Splitter splitter = Splitter.on(',').trimResults().omitEmptyStrings(); - for (int i = 0, count = issues.getLength(); i < count; i++) { - Node node = issues.item(i); - Element element = (Element) node; - String idList = element.getAttribute(ATTR_ID); - if (idList.isEmpty()) { - formatError("Invalid lint config file: Missing required issue id attribute"); - continue; - } - Iterable ids = splitter.split(idList); - - NamedNodeMap attributes = node.getAttributes(); - for (int j = 0, n = attributes.getLength(); j < n; j++) { - Node attribute = attributes.item(j); - String name = attribute.getNodeName(); - String value = attribute.getNodeValue(); - if (ATTR_ID.equals(name)) { - // already handled - } else if (ATTR_SEVERITY.equals(name)) { - for (Severity severity : Severity.values()) { - if (value.equalsIgnoreCase(severity.name())) { - for (String id : ids) { - mSeverity.put(id, severity); - } - break; - } - } - } else { - formatError("Unexpected attribute \"%1$s\"", name); - } - } - - // Look up ignored errors - NodeList childNodes = element.getChildNodes(); - if (childNodes.getLength() > 0) { - for (int j = 0, n = childNodes.getLength(); j < n; j++) { - Node child = childNodes.item(j); - if (child.getNodeType() == Node.ELEMENT_NODE) { - Element ignore = (Element) child; - String path = ignore.getAttribute(ATTR_PATH); - if (path.isEmpty()) { - String regexp = ignore.getAttribute(ATTR_REGEXP); - if (regexp.isEmpty()) { - formatError("Missing required attribute %1$s or %2$s under %3$s", - ATTR_PATH, ATTR_REGEXP, idList); - } else { - addRegexp(idList, ids, n, regexp, false); - } - } else { - // Normalize path format to File.separator. Also - // handle the file format containing / or \. - if (File.separatorChar == '/') { - path = path.replace('\\', '/'); - } else { - path = path.replace('/', File.separatorChar); - } - - if (path.indexOf('*') != -1) { - String regexp = globToRegexp(path); - addRegexp(idList, ids, n, regexp, false); - } else { - for (String id : ids) { - List paths = mSuppressed.get(id); - if (paths == null) { - paths = new ArrayList(n / 2 + 1); - mSuppressed.put(id, paths); - } - paths.add(path); - } - } - } - } - } - } - } - } catch (SAXParseException e) { - formatError(e.getMessage()); - } catch (Exception e) { - mClient.log(e, null); - } - } - - @NonNull - public static String globToRegexp(@NonNull String glob) { - StringBuilder sb = new StringBuilder(glob.length() * 2); - int begin = 0; - sb.append('^'); - for (int i = 0, n = glob.length(); i < n; i++) { - char c = glob.charAt(i); - if (c == '*') { - begin = appendQuoted(sb, glob, begin, i) + 1; - if (i < n - 1 && glob.charAt(i + 1) == '*') { - i++; - begin++; - } - sb.append(".*?"); - } else if (c == '?') { - begin = appendQuoted(sb, glob, begin, i) + 1; - sb.append(".?"); - } - } - appendQuoted(sb, glob, begin, glob.length()); - sb.append('$'); - return sb.toString(); - } - - private static int appendQuoted(StringBuilder sb, String s, int from, int to) { - if (to > from) { - boolean isSimple = true; - for (int i = from; i < to; i++) { - char c = s.charAt(i); - if (!Character.isLetterOrDigit(c) && c != '/' && c != ' ') { - isSimple = false; - break; - } - } - if (isSimple) { - for (int i = from; i < to; i++) { - sb.append(s.charAt(i)); - } - return to; - } - sb.append(Pattern.quote(s.substring(from, to))); - } - return to; - } - - private void addRegexp(@NonNull String idList, @NonNull Iterable ids, int n, - @NonNull String regexp, boolean silent) { - try { - if (mRegexps == null) { - mRegexps = new HashMap>(); - } - Pattern pattern = Pattern.compile(regexp); - for (String id : ids) { - List paths = mRegexps.get(id); - if (paths == null) { - paths = new ArrayList(n / 2 + 1); - mRegexps.put(id, paths); - } - paths.add(pattern); - } - } catch (PatternSyntaxException e) { - if (!silent) { - formatError("Invalid pattern %1$s under %2$s: %3$s", - regexp, idList, e.getDescription()); - } - } - } - - private void writeConfig() { - try { - // Write the contents to a new file first such that we don't clobber the - // existing file if some I/O error occurs. - File file = new File(mConfigFile.getParentFile(), - mConfigFile.getName() + ".new"); //$NON-NLS-1$ - - Writer writer = new BufferedWriter(new FileWriter(file)); - writer.write( - "\n" + //$NON-NLS-1$ - "\n"); //$NON-NLS-1$ - - if (!mSuppressed.isEmpty() || !mSeverity.isEmpty()) { - // Process the maps in a stable sorted order such that if the - // files are checked into version control with the project, - // there are no random diffs just because hashing algorithms - // differ: - Set idSet = new HashSet(); - for (String id : mSuppressed.keySet()) { - idSet.add(id); - } - for (String id : mSeverity.keySet()) { - idSet.add(id); - } - List ids = new ArrayList(idSet); - Collections.sort(ids); - - for (String id : ids) { - writer.write(" <"); //$NON-NLS-1$ - writer.write(TAG_ISSUE); - writeAttribute(writer, ATTR_ID, id); - Severity severity = mSeverity.get(id); - if (severity != null) { - writeAttribute(writer, ATTR_SEVERITY, - severity.name().toLowerCase(Locale.US)); - } - - List regexps = mRegexps != null ? mRegexps.get(id) : null; - List paths = mSuppressed.get(id); - if (paths != null && !paths.isEmpty() - || regexps != null && !regexps.isEmpty()) { - writer.write('>'); - writer.write('\n'); - // The paths are already kept in sorted order when they are modified - // by ignore(...) - if (paths != null) { - for (String path : paths) { - writer.write(" <"); //$NON-NLS-1$ - writer.write(TAG_IGNORE); - writeAttribute(writer, ATTR_PATH, path.replace('\\', '/')); - writer.write(" />\n"); //$NON-NLS-1$ - } - } - if (regexps != null) { - for (Pattern regexp : regexps) { - writer.write(" <"); //$NON-NLS-1$ - writer.write(TAG_IGNORE); - writeAttribute(writer, ATTR_REGEXP, regexp.pattern()); - writer.write(" />\n"); //$NON-NLS-1$ - } - } - writer.write(" '); - writer.write('\n'); - } else { - writer.write(" />\n"); //$NON-NLS-1$ - } - } - } - - writer.write(""); //$NON-NLS-1$ - writer.close(); - - // Move file into place: move current version to lint.xml~ (removing the old ~ file - // if it exists), then move the new version to lint.xml. - File oldFile = new File(mConfigFile.getParentFile(), - mConfigFile.getName() + '~'); //$NON-NLS-1$ - if (oldFile.exists()) { - oldFile.delete(); - } - if (mConfigFile.exists()) { - mConfigFile.renameTo(oldFile); - } - boolean ok = file.renameTo(mConfigFile); - if (ok && oldFile.exists()) { - oldFile.delete(); - } - } catch (Exception e) { - mClient.log(e, null); - } - } - - private static void writeAttribute( - @NonNull Writer writer, @NonNull String name, @NonNull String value) - throws IOException { - writer.write(' '); - writer.write(name); - writer.write('='); - writer.write('"'); - writer.write(value); - writer.write('"'); - } - - @Override - public void ignore( - @NonNull Context context, - @NonNull Issue issue, - @Nullable Location location, - @NonNull String message) { - // This configuration only supports suppressing warnings on a per-file basis - if (location != null) { - ignore(issue, location.getFile()); - } - } - - /** - * Marks the given issue and file combination as being ignored. - * - * @param issue the issue to be ignored in the given file - * @param file the file to ignore the issue in - */ - public void ignore(@NonNull Issue issue, @NonNull File file) { - ensureInitialized(); - - String path = mProject != null ? mProject.getRelativePath(file) : file.getPath(); - - List paths = mSuppressed.get(issue.getId()); - if (paths == null) { - paths = new ArrayList(); - mSuppressed.put(issue.getId(), paths); - } - paths.add(path); - - // Keep paths sorted alphabetically; makes XML output stable - Collections.sort(paths); - - if (!mBulkEditing) { - writeConfig(); - } - } - - @Override - public void setSeverity(@NonNull Issue issue, @Nullable Severity severity) { - ensureInitialized(); - - String id = issue.getId(); - if (severity == null) { - mSeverity.remove(id); - } else { - mSeverity.put(id, severity); - } - - if (!mBulkEditing) { - writeConfig(); - } - } - - @Override - public void startBulkEditing() { - mBulkEditing = true; - } - - @Override - public void finishBulkEditing() { - mBulkEditing = false; - writeConfig(); - } - - @VisibleForTesting - File getConfigFile() { - return mConfigFile; - } -} \ No newline at end of file diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/DefaultSdkInfo.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/client/api/DefaultSdkInfo.java.173 deleted file mode 100644 index cc7b157a2c4..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/DefaultSdkInfo.java.173 +++ /dev/null @@ -1,288 +0,0 @@ -/* - * Copyright (C) 2011 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.client.api; - -import static com.android.SdkConstants.ABSOLUTE_LAYOUT; -import static com.android.SdkConstants.ABS_LIST_VIEW; -import static com.android.SdkConstants.ABS_SEEK_BAR; -import static com.android.SdkConstants.ABS_SPINNER; -import static com.android.SdkConstants.ADAPTER_VIEW; -import static com.android.SdkConstants.AUTO_COMPLETE_TEXT_VIEW; -import static com.android.SdkConstants.BUTTON; -import static com.android.SdkConstants.CHECKABLE; -import static com.android.SdkConstants.CHECKED_TEXT_VIEW; -import static com.android.SdkConstants.CHECK_BOX; -import static com.android.SdkConstants.COMPOUND_BUTTON; -import static com.android.SdkConstants.EDIT_TEXT; -import static com.android.SdkConstants.EXPANDABLE_LIST_VIEW; -import static com.android.SdkConstants.FRAME_LAYOUT; -import static com.android.SdkConstants.GALLERY; -import static com.android.SdkConstants.GRID_VIEW; -import static com.android.SdkConstants.HORIZONTAL_SCROLL_VIEW; -import static com.android.SdkConstants.IMAGE_BUTTON; -import static com.android.SdkConstants.IMAGE_VIEW; -import static com.android.SdkConstants.LINEAR_LAYOUT; -import static com.android.SdkConstants.LIST_VIEW; -import static com.android.SdkConstants.MULTI_AUTO_COMPLETE_TEXT_VIEW; -import static com.android.SdkConstants.PROGRESS_BAR; -import static com.android.SdkConstants.RADIO_BUTTON; -import static com.android.SdkConstants.RADIO_GROUP; -import static com.android.SdkConstants.RELATIVE_LAYOUT; -import static com.android.SdkConstants.SCROLL_VIEW; -import static com.android.SdkConstants.SEEK_BAR; -import static com.android.SdkConstants.SPINNER; -import static com.android.SdkConstants.SURFACE_VIEW; -import static com.android.SdkConstants.SWITCH; -import static com.android.SdkConstants.TABLE_LAYOUT; -import static com.android.SdkConstants.TABLE_ROW; -import static com.android.SdkConstants.TAB_HOST; -import static com.android.SdkConstants.TAB_WIDGET; -import static com.android.SdkConstants.TEXT_VIEW; -import static com.android.SdkConstants.TOGGLE_BUTTON; -import static com.android.SdkConstants.VIEW; -import static com.android.SdkConstants.VIEW_ANIMATOR; -import static com.android.SdkConstants.VIEW_GROUP; -import static com.android.SdkConstants.VIEW_PKG_PREFIX; -import static com.android.SdkConstants.VIEW_STUB; -import static com.android.SdkConstants.VIEW_SWITCHER; -import static com.android.SdkConstants.WEB_VIEW; -import static com.android.SdkConstants.WIDGET_PKG_PREFIX; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.google.common.annotations.Beta; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -/** - * Default simple implementation of an {@link SdkInfo} - *

- * NOTE: This is not a public or final API; if you rely on this be prepared - * to adjust your code for the next tools release. - */ -@Beta -class DefaultSdkInfo extends SdkInfo { - @Override - @Nullable - public String getParentViewName(@NonNull String name) { - name = getRawType(name); - - return PARENTS.get(name); - } - - @Override - @Nullable - public String getParentViewClass(@NonNull String fqcn) { - int index = fqcn.lastIndexOf('.'); - if (index != -1) { - fqcn = fqcn.substring(index + 1); - } - - String parent = PARENTS.get(fqcn); - if (parent == null) { - return null; - } - // The map only stores class names internally; correct for full package paths - if (parent.equals(VIEW) || parent.equals(VIEW_GROUP) || parent.equals(SURFACE_VIEW)) { - return VIEW_PKG_PREFIX + parent; - } else { - return WIDGET_PKG_PREFIX + parent; - } - } - - @Override - public boolean isSubViewOf(@NonNull String parentType, @NonNull String childType) { - String parent = getRawType(parentType); - String child = getRawType(childType); - - // Do analysis just on non-fqcn paths - if (parent.indexOf('.') != -1) { - parent = parent.substring(parent.lastIndexOf('.') + 1); - } - if (child.indexOf('.') != -1) { - child = child.substring(child.lastIndexOf('.') + 1); - } - - if (parent.equals(VIEW)) { - return true; - } - - while (!child.equals(VIEW)) { - if (parent.equals(child)) { - return true; - } - if (implementsInterface(child, parent)) { - return true; - } - child = PARENTS.get(child); - if (child == null) { - // Unknown view - err on the side of caution - return true; - } - } - - return false; - } - - private static boolean implementsInterface(String className, String interfaceName) { - return interfaceName.equals(INTERFACES.get(className)); - } - - // Strip off type parameters, e.g. AdapterView ⇒ AdapterView - private static String getRawType(String type) { - if (type != null) { - int index = type.indexOf('<'); - if (index != -1) { - type = type.substring(0, index); - } - } - - return type; - } - - @Override - public boolean isLayout(@NonNull String tag) { - // TODO: Read in widgets.txt from the platform install area to look up this information - // dynamically instead! - - if (super.isLayout(tag)) { - return true; - } - - return LAYOUTS.contains(tag); - } - - private static final int CLASS_COUNT = 59; - private static final int LAYOUT_COUNT = 20; - - private static final Map PARENTS = Maps.newHashMapWithExpectedSize(CLASS_COUNT); - private static final Set LAYOUTS = Sets.newHashSetWithExpectedSize(CLASS_COUNT); - - static { - PARENTS.put(COMPOUND_BUTTON, BUTTON); - PARENTS.put(ABS_SPINNER, ADAPTER_VIEW); - PARENTS.put(ABS_LIST_VIEW, ADAPTER_VIEW); - PARENTS.put(ABS_SEEK_BAR, ADAPTER_VIEW); - PARENTS.put(ADAPTER_VIEW, VIEW_GROUP); - PARENTS.put(VIEW_GROUP, VIEW); - - PARENTS.put(TEXT_VIEW, VIEW); - PARENTS.put(CHECKED_TEXT_VIEW, TEXT_VIEW); - PARENTS.put(RADIO_BUTTON, COMPOUND_BUTTON); - PARENTS.put(SPINNER, ABS_SPINNER); - PARENTS.put(IMAGE_BUTTON, IMAGE_VIEW); - PARENTS.put(IMAGE_VIEW, VIEW); - PARENTS.put(EDIT_TEXT, TEXT_VIEW); - PARENTS.put(PROGRESS_BAR, VIEW); - PARENTS.put(TOGGLE_BUTTON, COMPOUND_BUTTON); - PARENTS.put(VIEW_STUB, VIEW); - PARENTS.put(BUTTON, TEXT_VIEW); - PARENTS.put(SEEK_BAR, ABS_SEEK_BAR); - PARENTS.put(CHECK_BOX, COMPOUND_BUTTON); - PARENTS.put(SWITCH, COMPOUND_BUTTON); - PARENTS.put(GALLERY, ABS_SPINNER); - PARENTS.put(SURFACE_VIEW, VIEW); - PARENTS.put(ABSOLUTE_LAYOUT, VIEW_GROUP); - PARENTS.put(LINEAR_LAYOUT, VIEW_GROUP); - PARENTS.put(RELATIVE_LAYOUT, VIEW_GROUP); - PARENTS.put(LIST_VIEW, ABS_LIST_VIEW); - PARENTS.put(VIEW_SWITCHER, VIEW_ANIMATOR); - PARENTS.put(FRAME_LAYOUT, VIEW_GROUP); - PARENTS.put(HORIZONTAL_SCROLL_VIEW, FRAME_LAYOUT); - PARENTS.put(VIEW_ANIMATOR, FRAME_LAYOUT); - PARENTS.put(TAB_HOST, FRAME_LAYOUT); - PARENTS.put(TABLE_ROW, LINEAR_LAYOUT); - PARENTS.put(RADIO_GROUP, LINEAR_LAYOUT); - PARENTS.put(TAB_WIDGET, LINEAR_LAYOUT); - PARENTS.put(EXPANDABLE_LIST_VIEW, LIST_VIEW); - PARENTS.put(TABLE_LAYOUT, LINEAR_LAYOUT); - PARENTS.put(SCROLL_VIEW, FRAME_LAYOUT); - PARENTS.put(GRID_VIEW, ABS_LIST_VIEW); - PARENTS.put(WEB_VIEW, ABSOLUTE_LAYOUT); - PARENTS.put(AUTO_COMPLETE_TEXT_VIEW, EDIT_TEXT); - PARENTS.put(MULTI_AUTO_COMPLETE_TEXT_VIEW, AUTO_COMPLETE_TEXT_VIEW); - PARENTS.put(CHECKED_TEXT_VIEW, TEXT_VIEW); - - PARENTS.put("MediaController", FRAME_LAYOUT); //$NON-NLS-1$ - PARENTS.put("SlidingDrawer", VIEW_GROUP); //$NON-NLS-1$ - PARENTS.put("DialerFilter", RELATIVE_LAYOUT); //$NON-NLS-1$ - PARENTS.put("DigitalClock", TEXT_VIEW); //$NON-NLS-1$ - PARENTS.put("Chronometer", TEXT_VIEW); //$NON-NLS-1$ - PARENTS.put("ImageSwitcher", VIEW_SWITCHER); //$NON-NLS-1$ - PARENTS.put("TextSwitcher", VIEW_SWITCHER); //$NON-NLS-1$ - PARENTS.put("AnalogClock", VIEW); //$NON-NLS-1$ - PARENTS.put("TwoLineListItem", RELATIVE_LAYOUT); //$NON-NLS-1$ - PARENTS.put("ZoomControls", LINEAR_LAYOUT); //$NON-NLS-1$ - PARENTS.put("DatePicker", FRAME_LAYOUT); //$NON-NLS-1$ - PARENTS.put("TimePicker", FRAME_LAYOUT); //$NON-NLS-1$ - PARENTS.put("VideoView", SURFACE_VIEW); //$NON-NLS-1$ - PARENTS.put("ZoomButton", IMAGE_BUTTON); //$NON-NLS-1$ - PARENTS.put("RatingBar", ABS_SEEK_BAR); //$NON-NLS-1$ - PARENTS.put("ViewFlipper", VIEW_ANIMATOR); //$NON-NLS-1$ - PARENTS.put("NumberPicker", LINEAR_LAYOUT); //$NON-NLS-1$ - - assert PARENTS.size() <= CLASS_COUNT : PARENTS.size(); - - /* - // Check that all widgets lead to the root view - if (LintUtils.assertionsEnabled()) { - for (String key : PARENTS.keySet()) { - String parent = PARENTS.get(key); - if (!parent.equals(VIEW)) { - String grandParent = PARENTS.get(parent); - assert grandParent != null : parent; - } - } - } - */ - - LAYOUTS.add(TAB_HOST); - LAYOUTS.add(HORIZONTAL_SCROLL_VIEW); - LAYOUTS.add(VIEW_SWITCHER); - LAYOUTS.add(TAB_WIDGET); - LAYOUTS.add(VIEW_ANIMATOR); - LAYOUTS.add(SCROLL_VIEW); - LAYOUTS.add(GRID_VIEW); - LAYOUTS.add(TABLE_ROW); - LAYOUTS.add(RADIO_GROUP); - LAYOUTS.add(LIST_VIEW); - LAYOUTS.add(EXPANDABLE_LIST_VIEW); - LAYOUTS.add("MediaController"); //$NON-NLS-1$ - LAYOUTS.add("DialerFilter"); //$NON-NLS-1$ - LAYOUTS.add("ViewFlipper"); //$NON-NLS-1$ - LAYOUTS.add("SlidingDrawer"); //$NON-NLS-1$ - LAYOUTS.add("StackView"); //$NON-NLS-1$ - LAYOUTS.add("SearchView"); //$NON-NLS-1$ - LAYOUTS.add("TextSwitcher"); //$NON-NLS-1$ - LAYOUTS.add("AdapterViewFlipper"); //$NON-NLS-1$ - LAYOUTS.add("ImageSwitcher"); //$NON-NLS-1$ - assert LAYOUTS.size() <= LAYOUT_COUNT : LAYOUTS.size(); - } - - // Currently using a map; this should really be a list, but using a map until we actually - // start adding more than one item - @NonNull - private static final Map INTERFACES = new HashMap(2); - static { - INTERFACES.put(CHECKED_TEXT_VIEW, CHECKABLE); - INTERFACES.put(COMPOUND_BUTTON, CHECKABLE); - } -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/ExternalReferenceExpression.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/client/api/ExternalReferenceExpression.java.173 deleted file mode 100644 index c7e19a6fee1..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/ExternalReferenceExpression.java.173 +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2016 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.client.api; - -import com.android.annotations.Nullable; -import com.intellij.psi.PsiElement; - -public interface ExternalReferenceExpression { - @Nullable - PsiElement resolve(PsiElement context); -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/IssueRegistry.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/client/api/IssueRegistry.java.173 deleted file mode 100644 index bc822ec73c0..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/IssueRegistry.java.173 +++ /dev/null @@ -1,346 +0,0 @@ -/* - * Copyright (C) 2011 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.client.api; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.tools.klint.detector.api.Category; -import com.android.tools.klint.detector.api.Detector; -import com.android.tools.klint.detector.api.Implementation; -import com.android.tools.klint.detector.api.Issue; -import com.android.tools.klint.detector.api.Scope; -import com.android.tools.klint.detector.api.Severity; -import com.google.common.annotations.Beta; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Registry which provides a list of checks to be performed on an Android project - *

- * NOTE: This is not a public or final API; if you rely on this be prepared - * to adjust your code for the next tools release. - */ -@Beta -public abstract class IssueRegistry { - private static volatile List sCategories; - private static volatile Map sIdToIssue; - private static Map, List> sScopeIssues = Maps.newHashMap(); - - /** - * Creates a new {@linkplain IssueRegistry} - */ - protected IssueRegistry() { - } - - private static final Implementation DUMMY_IMPLEMENTATION = new Implementation(Detector.class, - EnumSet.noneOf(Scope.class)); - /** - * Issue reported by lint (not a specific detector) when it cannot even - * parse an XML file prior to analysis - */ - @NonNull - public static final Issue PARSER_ERROR = Issue.create( - "ParserError", //$NON-NLS-1$ - "Parser Errors", - "Lint will ignore any files that contain fatal parsing errors. These may contain " + - "other errors, or contain code which affects issues in other files.", - Category.CORRECTNESS, - 10, - Severity.ERROR, - DUMMY_IMPLEMENTATION); - - /** - * Issue reported by lint for various other issues which prevents lint from - * running normally when it's not necessarily an error in the user's code base. - */ - @NonNull - public static final Issue LINT_ERROR = Issue.create( - "LintError", //$NON-NLS-1$ - "Lint Failure", - "This issue type represents a problem running lint itself. Examples include " + - "failure to find bytecode for source files (which means certain detectors " + - "could not be run), parsing errors in lint configuration files, etc." + - "\n" + - "These errors are not errors in your own code, but they are shown to make " + - "it clear that some checks were not completed.", - - Category.LINT, - 10, - Severity.ERROR, - DUMMY_IMPLEMENTATION); - - /** - * Issue reported when lint is canceled - */ - @NonNull - public static final Issue CANCELLED = Issue.create( - "LintCanceled", //$NON-NLS-1$ - "Lint Canceled", - "Lint canceled by user; the issue report may not be complete.", - - Category.LINT, - 0, - Severity.INFORMATIONAL, - DUMMY_IMPLEMENTATION); - - /** - * Returns the list of issues that can be found by all known detectors. - * - * @return the list of issues to be checked (including those that may be - * disabled!) - */ - @NonNull - public abstract List getIssues(); - - /** - * Get an approximate issue count for a given scope. This is just an optimization, - * so the number does not have to be accurate. - * - * @param scope the scope set - * @return an approximate ceiling of the number of issues expected for a given scope set - */ - protected int getIssueCapacity(@NonNull EnumSet scope) { - return 20; - } - - /** - * Returns all available issues of a given scope (regardless of whether - * they are actually enabled for a given configuration etc) - * - * @param scope the applicable scope set - * @return a list of issues - */ - @NonNull - protected List getIssuesForScope(@NonNull EnumSet scope) { - List list = sScopeIssues.get(scope); - if (list == null) { - List issues = getIssues(); - if (scope.equals(Scope.ALL)) { - list = issues; - } else { - list = new ArrayList(getIssueCapacity(scope)); - for (Issue issue : issues) { - // Determine if the scope matches - if (issue.getImplementation().isAdequate(scope)) { - list.add(issue); - } - } - } - sScopeIssues.put(scope, list); - } - - return list; - } - - /** - * Creates a list of detectors applicable to the given scope, and with the - * given configuration. - * - * @param client the client to report errors to - * @param configuration the configuration to look up which issues are - * enabled etc from - * @param scope the scope for the analysis, to filter out detectors that - * require wider analysis than is currently being performed - * @param scopeToDetectors an optional map which (if not null) will be - * filled by this method to contain mappings from each scope to - * the applicable detectors for that scope - * @return a list of new detector instances - */ - @NonNull - final List createDetectors( - @NonNull LintClient client, - @NonNull Configuration configuration, - @NonNull EnumSet scope, - @Nullable Map> scopeToDetectors) { - - List issues = getIssuesForScope(scope); - if (issues.isEmpty()) { - return Collections.emptyList(); - } - - Set> detectorClasses = new HashSet>(); - Map, EnumSet> detectorToScope = - new HashMap, EnumSet>(); - - for (Issue issue : issues) { - Implementation implementation = issue.getImplementation(); - Class detectorClass = implementation.getDetectorClass(); - EnumSet issueScope = implementation.getScope(); - if (!detectorClasses.contains(detectorClass)) { - // Determine if the issue is enabled - if (!configuration.isEnabled(issue)) { - continue; - } - - assert implementation.isAdequate(scope); // Ensured by getIssuesForScope above - - detectorClass = client.replaceDetector(detectorClass); - - assert detectorClass != null : issue.getId(); - detectorClasses.add(detectorClass); - } - - if (scopeToDetectors != null) { - EnumSet s = detectorToScope.get(detectorClass); - if (s == null) { - detectorToScope.put(detectorClass, issueScope); - } else if (!s.containsAll(issueScope)) { - EnumSet union = EnumSet.copyOf(s); - union.addAll(issueScope); - detectorToScope.put(detectorClass, union); - } - } - } - - List detectors = new ArrayList(detectorClasses.size()); - for (Class clz : detectorClasses) { - try { - Detector detector = clz.newInstance(); - detectors.add(detector); - - if (scopeToDetectors != null) { - EnumSet union = detectorToScope.get(clz); - for (Scope s : union) { - List list = scopeToDetectors.get(s); - if (list == null) { - list = new ArrayList(); - scopeToDetectors.put(s, list); - } - list.add(detector); - } - - } - } catch (Throwable t) { - client.log(t, "Can't initialize detector %1$s", clz.getName()); //$NON-NLS-1$ - } - } - - return detectors; - } - - /** - * Returns true if the given id represents a valid issue id - * - * @param id the id to be checked - * @return true if the given id is valid - */ - public final boolean isIssueId(@NonNull String id) { - return getIssue(id) != null; - } - - /** - * Returns true if the given category is a valid category - * - * @param name the category name to be checked - * @return true if the given string is a valid category - */ - public final boolean isCategoryName(@NonNull String name) { - for (Category category : getCategories()) { - if (category.getName().equals(name) || category.getFullName().equals(name)) { - return true; - } - } - - return false; - } - - /** - * Returns the available categories - * - * @return an iterator for all the categories, never null - */ - @SuppressWarnings("AssignmentToStaticFieldFromInstanceMethod") - @NonNull - public List getCategories() { - List categories = sCategories; - if (categories == null) { - synchronized (IssueRegistry.class) { - categories = sCategories; - if (categories == null) { - sCategories = categories = Collections.unmodifiableList(createCategoryList()); - } - } - } - - return categories; - } - - @NonNull - private List createCategoryList() { - Set categorySet = Sets.newHashSetWithExpectedSize(20); - for (Issue issue : getIssues()) { - categorySet.add(issue.getCategory()); - } - List sorted = new ArrayList(categorySet); - Collections.sort(sorted); - return sorted; - } - - /** - * Returns the issue for the given id, or null if it's not a valid id - * - * @param id the id to be checked - * @return the corresponding issue, or null - */ - @SuppressWarnings("AssignmentToStaticFieldFromInstanceMethod") - @Nullable - public final Issue getIssue(@NonNull String id) { - Map map = sIdToIssue; - if (map == null) { - synchronized (IssueRegistry.class) { - map = sIdToIssue; - if (map == null) { - map = createIdToIssueMap(); - sIdToIssue = map; - } - } - } - - return map.get(id); - } - - @NonNull - private Map createIdToIssueMap() { - List issues = getIssues(); - Map map = Maps.newHashMapWithExpectedSize(issues.size() + 2); - for (Issue issue : issues) { - map.put(issue.getId(), issue); - } - - map.put(PARSER_ERROR.getId(), PARSER_ERROR); - map.put(LINT_ERROR.getId(), LINT_ERROR); - return map; - } - - /** - * Reset the registry such that it recomputes its available issues. - */ - protected static void reset() { - sIdToIssue = null; - sCategories = null; - sScopeIssues = Maps.newHashMap(); - } -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/JarFileIssueRegistry.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/client/api/JarFileIssueRegistry.java.173 deleted file mode 100644 index 79b4dca57b5..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/JarFileIssueRegistry.java.173 +++ /dev/null @@ -1,236 +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 com.android.tools.klint.client.api; - -import static com.android.SdkConstants.DOT_CLASS; - -import com.android.annotations.NonNull; -import com.android.tools.klint.detector.api.Issue; -import com.android.tools.klint.detector.api.Scope; -import com.android.tools.klint.detector.api.Severity; -import com.android.utils.SdkUtils; -import com.google.common.collect.Lists; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.lang.ref.SoftReference; -import java.lang.reflect.Method; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.jar.Attributes; -import java.util.jar.JarFile; -import java.util.jar.JarInputStream; -import java.util.jar.Manifest; -import java.util.zip.ZipEntry; - -/** - *

An {@link IssueRegistry} for a custom lint rule jar file. The rule jar should provide a - * manifest entry with the key {@code Lint-Registry} and the value of the fully qualified name of an - * implementation of {@link IssueRegistry} (with a default constructor).

- * - *

NOTE: The custom issue registry should not extend this file; it should be a plain - * IssueRegistry! This file is used internally to wrap the given issue registry.

- */ -class JarFileIssueRegistry extends IssueRegistry { - /** - * Manifest constant for declaring an issue provider. Example: Lint-Registry: - * foo.bar.CustomIssueRegistry - */ - private static final String MF_LINT_REGISTRY_OLD = "Lint-Registry"; //$NON-NLS-1$ - private static final String MF_LINT_REGISTRY = "Lint-Registry-v2"; //$NON-NLS-1$ - - private static Map> sCache; - - private final List myIssues; - - private boolean mHasLegacyDetectors; - - /** True if one or more java detectors were found that use the old Lombok-based API */ - public boolean hasLegacyDetectors() { - return mHasLegacyDetectors; - } - - @NonNull - static JarFileIssueRegistry get(@NonNull LintClient client, @NonNull File jarFile) - throws IOException, ClassNotFoundException, IllegalAccessException, - InstantiationException { - if (sCache == null) { - sCache = new HashMap>(); - } else { - SoftReference reference = sCache.get(jarFile); - if (reference != null) { - JarFileIssueRegistry registry = reference.get(); - if (registry != null) { - return registry; - } - } - } - - // Ensure that the scope-to-detector map doesn't return stale results - IssueRegistry.reset(); - - JarFileIssueRegistry registry = new JarFileIssueRegistry(client, jarFile); - sCache.put(jarFile, new SoftReference(registry)); - return registry; - } - - private JarFileIssueRegistry(@NonNull LintClient client, @NonNull File file) - throws IOException, ClassNotFoundException, IllegalAccessException, - InstantiationException { - myIssues = Lists.newArrayList(); - JarFile jarFile = null; - try { - //noinspection IOResourceOpenedButNotSafelyClosed - jarFile = new JarFile(file); - Manifest manifest = jarFile.getManifest(); - Attributes attrs = manifest.getMainAttributes(); - Object object = attrs.get(new Attributes.Name(MF_LINT_REGISTRY)); - boolean isLegacy = false; - if (object == null) { - object = attrs.get(new Attributes.Name(MF_LINT_REGISTRY_OLD)); - //noinspection VariableNotUsedInsideIf - if (object != null) { - // It's an old rule. We don't yet conclude that - // mHasLegacyDetectors=true - // because the lint checks may not be Java related. - isLegacy = true; - } - } - if (object instanceof String) { - String className = (String) object; - // Make a class loader for this jar - URL url = SdkUtils.fileToUrl(file); - ClassLoader loader = client.createUrlClassLoader(new URL[]{url}, - JarFileIssueRegistry.class.getClassLoader()); - Class registryClass = Class.forName(className, true, loader); - IssueRegistry registry = (IssueRegistry) registryClass.newInstance(); - myIssues.addAll(registry.getIssues()); - - if (isLegacy) { - // If it's an old registry, look through the issues to see if it - // provides Java scanning and if so create the old style visitors - for (Issue issue : myIssues) { - EnumSet scope = issue.getImplementation().getScope(); - if (scope.contains(Scope.JAVA_FILE) || scope.contains(Scope.JAVA_LIBRARIES) - || scope.contains(Scope.ALL_JAVA_FILES)) { - mHasLegacyDetectors = true; - break; - } - } - } - - if (loader instanceof URLClassLoader) { - loadAndCloseURLClassLoader(client, file, (URLClassLoader)loader); - } - } else { - client.log(Severity.ERROR, null, - "Custom lint rule jar %1$s does not contain a valid registry manifest key " + - "(%2$s).\n" + - "Either the custom jar is invalid, or it uses an outdated API not supported " + - "this lint client", file.getPath(), MF_LINT_REGISTRY); - } - } finally { - if (jarFile != null) { - jarFile.close(); - } - } - } - - /** - * Work around http://bugs.java.com/bugdatabase/view_bug.do?bug_id=5041014 : - * URLClassLoader, on Windows, locks the .jar file forever. - * As of Java 7, there's a workaround: you can call close() when you're "done" - * with the file. We'll do that here. However, the whole point of the - * {@linkplain JarFileIssueRegistry} is that when lint is run over and over again - * as the user is editing in the IDE and we're background checking the code, we - * don't to keep loading the custom view classes over and over again: we want to - * cache them. Therefore, just closing the URLClassLoader right away isn't great - * either. However, it turns out it's safe to close the URLClassLoader once you've - * loaded the classes you need, since the URLClassLoader will continue to serve - * those classes even after its close() methods has been called. - *

- * Therefore, if we can call close() on this URLClassLoader, we'll proactively load - * all class files we find in the .jar file, then close it. - * - * @param client the client to report errors to - * @param file the .jar file - * @param loader the URLClassLoader we should close - */ - private static void loadAndCloseURLClassLoader( - @NonNull LintClient client, - @NonNull File file, - @NonNull URLClassLoader loader) { - try { - // Proactively close out the .jar file. This is only available on Java 7. - Method closeMethod = loader.getClass().getDeclaredMethod("close"); - - // But first, proactively load all classes: - try { - InputStream inputStream = new FileInputStream(file); - try { - JarInputStream jarInputStream = new JarInputStream(inputStream); - try { - ZipEntry entry = jarInputStream.getNextEntry(); - while (entry != null) { - String name = entry.getName(); - // Load non-inner-classes - if (name.endsWith(DOT_CLASS)) { - // Strip .class suffix and change .jar file path (/) - // to class name (.'s). - name = name.substring(0, - name.length() - DOT_CLASS.length()); - name = name.replace('/', '.'); - try { - Class.forName(name, true, loader); - } catch (Throwable e) { - client.log(Severity.ERROR, e, - "Failed to prefetch " + name + " from " + file); - } - } - entry = jarInputStream.getNextEntry(); - } - } finally { - jarInputStream.close(); - } - } finally { - inputStream.close(); - } - } catch (Throwable ignore) { - } finally { - // Finally close the URL class loader - try { - closeMethod.invoke(loader); - } catch (Throwable ignore) { - // Couldn't close. This is unlikely. - } - } - } catch (NoSuchMethodException ignore) { - // No close method - we're on 1.6 - } - } - - @NonNull - @Override - public List getIssues() { - return myIssues; - } -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/JavaEvaluator.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/client/api/JavaEvaluator.java.173 deleted file mode 100644 index 46eeb1f5ade..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/JavaEvaluator.java.173 +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright (C) 2016 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.client.api; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.tools.klint.detector.api.ClassContext; -import com.intellij.psi.PsiAnnotation; -import com.intellij.psi.PsiAnonymousClass; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiClassType; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiMember; -import com.intellij.psi.PsiMethod; -import com.intellij.psi.PsiMethodCallExpression; -import com.intellij.psi.PsiModifier; -import com.intellij.psi.PsiModifierList; -import com.intellij.psi.PsiModifierListOwner; -import com.intellij.psi.PsiParameter; -import com.intellij.psi.PsiParameterList; -import com.intellij.psi.PsiReference; -import com.intellij.psi.PsiType; -import com.intellij.psi.util.InheritanceUtil; - -import java.io.File; - -@SuppressWarnings("MethodMayBeStatic") // Some of these methods may be overridden by LintClients -public abstract class JavaEvaluator { - public boolean isMemberInSubClassOf( - @NonNull PsiMember method, - @NonNull String className, - boolean strict) { - PsiClass containingClass = method.getContainingClass(); - return containingClass != null && InheritanceUtil.isInheritor(containingClass, strict, className); - } - - public static boolean isMemberInClass( - @Nullable PsiMember method, - @NonNull String className) { - if (method == null) { - return false; - } - PsiClass containingClass = method.getContainingClass(); - return containingClass != null && className.equals(containingClass.getQualifiedName()); - } - - public int getParameterCount(@NonNull PsiMethod method) { - return method.getParameterList().getParametersCount(); - } - - /** - * Returns true if the given method (which is typically looked up by resolving a method call) is - * either a method in the exact given class, or if {@code allowInherit} is true, a method in a - * class possibly extending the given class, and if the parameter types are the exact types - * specified. - * - * @param method the method in question - * @param className the class name the method should be defined in or inherit from (or - * if null, allow any class) - * @param allowInherit whether we allow checking for inheritance - * @param argumentTypes the names of the types of the parameters - * @return true if this method is defined in the given class and with the given parameters - */ - public boolean methodMatches( - @NonNull PsiMethod method, - @Nullable String className, - boolean allowInherit, - @NonNull String... argumentTypes) { - if (className != null && allowInherit) { - if (!isMemberInSubClassOf(method, className, false)) { - return false; - } - } - - return parametersMatch(method, argumentTypes); - } - - /** - * Returns true if the given method's parameters are the exact types specified. - * - * @param method the method in question - * @param argumentTypes the names of the types of the parameters - * @return true if this method is defined in the given class and with the given parameters - */ - public boolean parametersMatch( - @NonNull PsiMethod method, - @NonNull String... argumentTypes) { - PsiParameterList parameterList = method.getParameterList(); - if (parameterList.getParametersCount() != argumentTypes.length) { - return false; - } - PsiParameter[] parameters = parameterList.getParameters(); - for (int i = 0; i < parameters.length; i++) { - PsiType type = parameters[i].getType(); - if (!type.getCanonicalText().equals(argumentTypes[i])) { - return false; - } - } - - return true; - } - - /** Returns true if the given type matches the given fully qualified type name */ - public boolean parameterHasType( - @Nullable PsiMethod method, - int parameterIndex, - @NonNull String typeName) { - if (method == null) { - return false; - } - PsiParameterList parameterList = method.getParameterList(); - return parameterList.getParametersCount() > parameterIndex - && typeMatches(parameterList.getParameters()[parameterIndex].getType(), typeName); - } - - /** Returns true if the given type matches the given fully qualified type name */ - public boolean typeMatches( - @Nullable PsiType type, - @NonNull String typeName) { - return type != null && type.getCanonicalText().equals(typeName); - - } - - @Nullable - public PsiElement resolve(@NonNull PsiElement element) { - if (element instanceof PsiReference) { - return ((PsiReference)element).resolve(); - } else if (element instanceof PsiMethodCallExpression) { - PsiElement resolved = ((PsiMethodCallExpression) element).resolveMethod(); - if (resolved != null) { - return resolved; - } - } - return null; - } - - public boolean isPublic(@Nullable PsiModifierListOwner owner) { - if (owner != null) { - PsiModifierList modifierList = owner.getModifierList(); - return modifierList != null && modifierList.hasModifierProperty(PsiModifier.PUBLIC); - } - return false; - } - - public boolean isStatic(@Nullable PsiModifierListOwner owner) { - if (owner != null) { - PsiModifierList modifierList = owner.getModifierList(); - return modifierList != null && modifierList.hasModifierProperty(PsiModifier.STATIC); - } - return false; - } - - public boolean isPrivate(@Nullable PsiModifierListOwner owner) { - if (owner != null) { - PsiModifierList modifierList = owner.getModifierList(); - return modifierList != null && modifierList.hasModifierProperty(PsiModifier.PRIVATE); - } - return false; - } - - public boolean isAbstract(@Nullable PsiModifierListOwner owner) { - if (owner != null) { - PsiModifierList modifierList = owner.getModifierList(); - return modifierList != null && modifierList.hasModifierProperty(PsiModifier.ABSTRACT); - } - return false; - } - - public boolean isFinal(@Nullable PsiModifierListOwner owner) { - if (owner != null) { - PsiModifierList modifierList = owner.getModifierList(); - return modifierList != null && modifierList.hasModifierProperty(PsiModifier.FINAL); - } - return false; - } - - @Nullable - public PsiMethod getSuperMethod(@Nullable PsiMethod method) { - if (method == null) { - return null; - } - final PsiMethod[] superMethods = method.findSuperMethods(); - if (superMethods.length > 0) { - return superMethods[0]; - } - return null; - } - - @NonNull - public String getInternalName(@NonNull PsiClass psiClass) { - String qualifiedName = psiClass.getQualifiedName(); - if (qualifiedName == null) { - qualifiedName = psiClass.getName(); - if (qualifiedName == null) { - assert psiClass instanceof PsiAnonymousClass; - //noinspection ConstantConditions - return getInternalName(psiClass.getContainingClass()); - } - } - return ClassContext.getInternalName(qualifiedName); - } - - @NonNull - public String getInternalName(@NonNull PsiClassType psiClassType) { - return ClassContext.getInternalName(psiClassType.getCanonicalText()); - } - - @Nullable - public abstract PsiClass findClass(@NonNull String qualifiedName); - - @Nullable - public abstract PsiClassType getClassType(@Nullable PsiClass psiClass); - - @NonNull - public abstract PsiAnnotation[] getAllAnnotations(@NonNull PsiModifierListOwner owner); - - @Nullable - public abstract PsiAnnotation findAnnotationInHierarchy( - @NonNull PsiModifierListOwner listOwner, - @NonNull String... annotationNames); - - @Nullable - public abstract PsiAnnotation findAnnotation( - @Nullable PsiModifierListOwner listOwner, - @NonNull String... annotationNames); - - @Nullable - public abstract File getFile(@NonNull PsiFile file); -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/JavaParser.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/client/api/JavaParser.java.173 deleted file mode 100644 index 96763856e15..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/JavaParser.java.173 +++ /dev/null @@ -1,1078 +0,0 @@ -/* - * Copyright (C) 2011 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.client.api; - -import static com.android.SdkConstants.ATTR_VALUE; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -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.Detector.JavaPsiScanner; -import com.android.tools.klint.detector.api.JavaContext; -import com.android.tools.klint.detector.api.Location; -import com.android.tools.klint.detector.api.Position; -import com.google.common.annotations.Beta; -import com.google.common.base.Splitter; -import com.intellij.mock.MockProject; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.TextRange; -import com.intellij.openapi.vfs.VfsUtilCore; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.PsiComment; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiJavaFile; -import com.intellij.psi.PsiType; - -import org.jetbrains.uast.UElement; -import org.jetbrains.uast.UFile; -import org.jetbrains.uast.UastContext; - -import java.io.File; -import java.lang.reflect.Modifier; -import java.util.Collections; -import java.util.List; - -import lombok.ast.Catch; -import lombok.ast.For; -import lombok.ast.Identifier; -import lombok.ast.If; -import lombok.ast.Node; -import lombok.ast.Return; -import lombok.ast.StrictListAccessor; -import lombok.ast.Switch; -import lombok.ast.Throw; -import lombok.ast.TypeReference; -import lombok.ast.TypeReferencePart; -import lombok.ast.While; - -/** - * A wrapper for a Java parser. This allows tools integrating lint to map directly - * to builtin services, such as already-parsed data structures in Java editors. - *

- * NOTE: This is not public or final API; if you rely on this be prepared - * to adjust your code for the next tools release. - */ -// Currently ships with deprecated API support -@SuppressWarnings({"deprecation", "UnusedParameters"}) -@Beta -public abstract class JavaParser { - public static final String TYPE_OBJECT = "java.lang.Object"; - public static final String TYPE_STRING = "java.lang.String"; - public static final String TYPE_INT = "int"; - public static final String TYPE_LONG = "long"; - public static final String TYPE_CHAR = "char"; - public static final String TYPE_FLOAT = "float"; - public static final String TYPE_DOUBLE = "double"; - public static final String TYPE_BOOLEAN = "boolean"; - public static final String TYPE_SHORT = "short"; - public static final String TYPE_BYTE = "byte"; - public static final String TYPE_NULL = "null"; - public static final String TYPE_INTEGER_WRAPPER = "java.lang.Integer"; - public static final String TYPE_BOOLEAN_WRAPPER = "java.lang.Boolean"; - public static final String TYPE_BYTE_WRAPPER = "java.lang.Byte"; - public static final String TYPE_SHORT_WRAPPER = "java.lang.Short"; - public static final String TYPE_LONG_WRAPPER = "java.lang.Long"; - public static final String TYPE_DOUBLE_WRAPPER = "java.lang.Double"; - public static final String TYPE_FLOAT_WRAPPER = "java.lang.Float"; - public static final String TYPE_CHARACTER_WRAPPER = "java.lang.Character"; - - /** - * Prepare to parse the given contexts. This method will be called before - * a series of {@link #parseJava(JavaContext)} calls, which allows some - * parsers to do up front global computation in case they want to more - * efficiently process multiple files at the same time. This allows a single - * type-attribution pass for example, which is a lot more efficient than - * performing global type analysis over and over again for each individual - * file - * - * @param contexts a list of contexts to be parsed - */ - public abstract void prepareJavaParse(@NonNull List contexts); - - /** - * Parse the file pointed to by the given context. - * - * @param context the context pointing to the file to be parsed, typically - * via {@link Context#getContents()} but the file handle ( - * {@link Context#file} can also be used to map to an existing - * editor buffer in the surrounding tool, etc) - * @return the compilation unit node for the file - * @deprecated Use {@link #parseJavaToPsi(JavaContext)} instead - */ - @Deprecated - @Nullable - public Node parseJava(@NonNull JavaContext context) { - return null; - } - - /** - * Parse the file pointed to by the given context. - * - * @param context the context pointing to the file to be parsed, typically - * via {@link Context#getContents()} but the file handle ( - * {@link Context#file} can also be used to map to an existing - * editor buffer in the surrounding tool, etc) - * @return the compilation unit node for the file - */ - @Nullable - public abstract PsiJavaFile parseJavaToPsi(@NonNull JavaContext context); - - /** - * Returns an evaluator which can perform various resolution tasks, - * evaluate inheritance lookup etc. - * - * @return an evaluator - */ - @NonNull - public abstract JavaEvaluator getEvaluator(); - - public abstract Project getIdeaProject(); - - public abstract UastContext getUastContext(); - - /** - * Returns a {@link Location} for the given node - * - * @param context information about the file being parsed - * @param node the node to create a location for - * @return a location for the given node - * @deprecated Use {@link #getNameLocation(JavaContext, PsiElement)} instead - */ - @Deprecated - @NonNull - public Location getLocation(@NonNull JavaContext context, @NonNull Node node) { - // No longer mandatory to override for children; this is a deprecated API - return Location.NONE; - } - - /** - * Returns a {@link Location} for the given element - * - * @param context information about the file being parsed - * @param element the element to create a location for - * @return a location for the given node - */ - @SuppressWarnings("MethodMayBeStatic") // subclasses may want to override/optimize - @NonNull - public Location getLocation(@NonNull JavaContext context, @NonNull PsiElement element) { - TextRange range = element.getTextRange(); - UFile uFile = (UFile) getUastContext().convertElementWithParent(element.getContainingFile(), UFile.class); - if (uFile == null) { - return Location.NONE; - } - - PsiFile containingFile = uFile.getPsi(); - File file = context.file; - if (containingFile != context.getUFile().getPsi()) { - // Reporting an error in a different file. - if (context.getDriver().getScope().size() == 1) { - // Don't bother with this error if it's in a different file during single-file analysis - return Location.NONE; - } - VirtualFile virtualFile = containingFile.getVirtualFile(); - if (virtualFile == null) { - return Location.NONE; - } - file = VfsUtilCore.virtualToIoFile(virtualFile); - } - return Location.create(file, context.getContents(), range.getStartOffset(), - range.getEndOffset()); - } - - /** - * Returns a {@link Location} for the given node range (from the starting offset of the first - * node to the ending offset of the second node). - * - * @param context information about the file being parsed - * @param from the AST node to get a starting location from - * @param fromDelta Offset delta to apply to the starting offset - * @param to the AST node to get a ending location from - * @param toDelta Offset delta to apply to the ending offset - * @return a location for the given node - * @deprecated Use {@link #getRangeLocation(JavaContext, PsiElement, int, PsiElement, int)} - * instead - */ - @Deprecated - @NonNull - public abstract Location getRangeLocation( - @NonNull JavaContext context, - @NonNull Node from, - int fromDelta, - @NonNull Node to, - int toDelta); - - /** - * Returns a {@link Location} for the given node range (from the starting offset of the first - * node to the ending offset of the second node). - * - * @param context information about the file being parsed - * @param from the AST node to get a starting location from - * @param fromDelta Offset delta to apply to the starting offset - * @param to the AST node to get a ending location from - * @param toDelta Offset delta to apply to the ending offset - * @return a location for the given node - */ - @SuppressWarnings("MethodMayBeStatic") // subclasses may want to override/optimize - @NonNull - public Location getRangeLocation( - @NonNull JavaContext context, - @NonNull PsiElement from, - int fromDelta, - @NonNull PsiElement to, - int toDelta) { - String contents = context.getContents(); - int start = Math.max(0, from.getTextRange().getStartOffset() + fromDelta); - int end = Math.min(contents == null ? Integer.MAX_VALUE : contents.length(), - to.getTextRange().getEndOffset() + toDelta); - return Location.create(context.file, contents, start, end); - } - - /** - * Like {@link #getRangeLocation(JavaContext, PsiElement, int, PsiElement, int)} - * but both offsets are relative to the starting offset of the given node. This is - * sometimes more convenient than operating relative to the ending offset when you - * have a fixed range in mind. - * - * @param context information about the file being parsed - * @param from the AST node to get a starting location from - * @param fromDelta Offset delta to apply to the starting offset - * @param toDelta Offset delta to apply to the starting offset - * @return a location for the given node - */ - @SuppressWarnings("MethodMayBeStatic") // subclasses may want to override/optimize - @NonNull - public Location getRangeLocation( - @NonNull JavaContext context, - @NonNull PsiElement from, - int fromDelta, - int toDelta) { - return getRangeLocation(context, from, fromDelta, from, - -(from.getTextRange().getLength() - toDelta)); - } - - /** - * Returns a {@link Location} for the given node. This attempts to pick a shorter - * location range than the entire node; for a class or method for example, it picks - * the name node (if found). For statement constructs such as a {@code switch} statement - * it will highlight the keyword, etc. - * - * @param context information about the file being parsed - * @param node the node to create a location for - * @return a location for the given node - * @deprecated Use {@link #getNameLocation(JavaContext, PsiElement)} instead - */ - @Deprecated - @NonNull - public Location getNameLocation(@NonNull JavaContext context, @NonNull Node node) { - Node nameNode = JavaContext.findNameNode(node); - if (nameNode != null) { - node = nameNode; - } else { - if (node instanceof Switch - || node instanceof For - || node instanceof If - || node instanceof While - || node instanceof Throw - || node instanceof Return) { - // Lint doesn't want to highlight the entire statement/block associated - // with this node, it wants to just highlight the keyword. - Location location = getLocation(context, node); - Position start = location.getStart(); - if (start != null) { - // The Lombok classes happen to have the same length as the target keyword - int length = node.getClass().getSimpleName().length(); - return Location.create(location.getFile(), start, - new DefaultPosition(start.getLine(), start.getColumn() + length, - start.getOffset() + length)); - } - } - } - - return getLocation(context, node); - } - - /** - * Returns a {@link Location} for the given node. This attempts to pick a shorter - * location range than the entire node; for a class or method for example, it picks - * the name node (if found). For statement constructs such as a {@code switch} statement - * it will highlight the keyword, etc. - * - * @param context information about the file being parsed - * @param element the node to create a location for - * @return a location for the given node - */ - @NonNull - public Location getNameLocation(@NonNull JavaContext context, @NonNull PsiElement element) { - PsiElement nameNode = JavaContext.findNameElement(element); - if (nameNode != null) { - element = nameNode; - } - - return getLocation(context, element); - } - /** - * Creates a light-weight handle to a location for the given node. It can be - * turned into a full fledged location by - * {@link com.android.tools.lint.detector.api.Location.Handle#resolve()}. - * - * @param context the context providing the node - * @param node the node (element or attribute) to create a location handle - * for - * @return a location handle - * @deprecated Use PSI instead (where handles aren't necessary; use PsiElement directly) - */ - @Deprecated - @NonNull - public abstract Location.Handle createLocationHandle(@NonNull JavaContext context, - @NonNull Node node); - - /** - * Dispose any data structures held for the given context. - * @param context information about the file previously parsed - * @param compilationUnit the compilation unit being disposed - * @deprecated Use {@link #dispose(JavaContext, PsiJavaFile)} instead - */ - @Deprecated - public void dispose(@NonNull JavaContext context, @NonNull Node compilationUnit) { - } - - /** - * Dispose any data structures held for the given context. - * @param context information about the file previously parsed - * @param compilationUnit the compilation unit being disposed - */ - public void dispose(@NonNull JavaContext context, @NonNull PsiFile compilationUnit) { - } - - /** - * Dispose any data structures held for the given context. - * @param context information about the file previously parsed - * @param compilationUnit the compilation unit being disposed - */ - public void dispose(@NonNull JavaContext context, @NonNull UFile compilationUnit) { - } - - /** - * Dispose any remaining data structures held for all contexts. - * Typically frees up any resources allocated by - * {@link #prepareJavaParse(List)} - */ - public void dispose() { - } - - /** - * Resolves the given expression node: computes the declaration for the given symbol - * - * @param context information about the file being parsed - * @param node the node to resolve - * @return a node representing the resolved fully type: class/interface/annotation, - * field, method or variable - * @deprecated Use {@link JavaPsiScanner} APIs instead - */ - @Deprecated - @Nullable - public ResolvedNode resolve(@NonNull JavaContext context, @NonNull Node node) { - return null; - } - - /** - * Finds the given type, if possible (which should be reachable from the compilation - * patch of the given node. - * - * @param context information about the file being parsed - * @param fullyQualifiedName the fully qualified name of the class to look up - * @return the class, or null if not found - */ - @Nullable - public ResolvedClass findClass( - @NonNull JavaContext context, - @NonNull String fullyQualifiedName) { - return null; - } - - /** - * Returns the set of exception types handled by the given catch block. - *

- * This is a workaround for the fact that the Lombok AST API (and implementation) - * doesn't support multi-catch statements. - * @deprecated Use {@link JavaPsiScanner} APIs instead - */ - @Deprecated - public List getCatchTypes(@NonNull JavaContext context, - @NonNull Catch catchBlock) { - TypeReference typeReference = catchBlock.astExceptionDeclaration().astTypeReference(); - return Collections.singletonList(new DefaultTypeDescriptor( - typeReference.getTypeName())); - } - - /** - * Gets the type of the given node - * - * @param context information about the file being parsed - * @param node the node to look up the type for - * @return the type of the node, if known - * @deprecated Use {@link JavaPsiScanner} APIs instead - */ - @Deprecated - @Nullable - public TypeDescriptor getType(@NonNull JavaContext context, @NonNull Node node) { - return null; - } - - /** - * Runs the given runnable under a readlock such that it can access the PSI - * - * @param runnable the runnable to be run - */ - public abstract void runReadAction(@NonNull Runnable runnable); - - /** - * A description of a type, such as a primitive int or the android.app.Activity class - * @deprecated Use {@link PsiType} instead - */ - @SuppressWarnings("unused") - @Deprecated - public abstract static class TypeDescriptor { - /** - * Returns the fully qualified name of the type, such as "int" or "android.app.Activity" - * */ - @NonNull public abstract String getName(); - - /** Returns the simple name of this class */ - @NonNull - public String getSimpleName() { - // This doesn't handle inner classes properly, so subclasses with more - // accurate type information will override to handle it correctly. - String name = getName(); - int index = name.lastIndexOf('.'); - if (index != -1) { - return name.substring(index + 1); - } - return name; - } - - /** - * Returns the full signature of the type, which is normally the same as {@link #getName()} - * but for arrays can include []'s, for generic methods can include generics parameters - * etc - */ - @NonNull public abstract String getSignature(); - - /** - * Computes the internal class name of the given fully qualified class name. - * For example, it converts foo.bar.Foo.Bar into foo/bar/Foo$Bar. - * This should only be called for class types, not primitives. - * - * @return the internal class name - */ - @NonNull public String getInternalName() { - return ClassContext.getInternalName(getName()); - } - - public abstract boolean matchesName(@NonNull String name); - - /** - * Returns true if the given TypeDescriptor represents an array - * @return true if this type represents an array - */ - public abstract boolean isArray(); - - /** - * Returns true if the given TypeDescriptor represents a primitive - * @return true if this type represents a primitive - */ - public abstract boolean isPrimitive(); - - public abstract boolean matchesSignature(@NonNull String signature); - - @NonNull - public TypeReference getNode() { - TypeReference typeReference = new TypeReference(); - StrictListAccessor parts = typeReference.astParts(); - for (String part : Splitter.on('.').split(getName())) { - Identifier identifier = Identifier.of(part); - parts.addToEnd(new TypeReferencePart().astIdentifier(identifier)); - } - - return typeReference; - } - - /** If the type is not primitive, returns the class of the type if known */ - @Nullable - public abstract ResolvedClass getTypeClass(); - - @Override - public abstract boolean equals(Object o); - - @Override - public String toString() { - return getName(); - } - } - - /** - * Convenience implementation of {@link TypeDescriptor} - * @deprecated Use {@link JavaPsiScanner} APIs instead - */ - @Deprecated - public static class DefaultTypeDescriptor extends TypeDescriptor { - - private String mName; - - public DefaultTypeDescriptor(String name) { - mName = name; - } - - @NonNull - @Override - public String getName() { - return mName; - } - - @NonNull - @Override - public String getSignature() { - return getName(); - } - - @Override - public boolean matchesName(@NonNull String name) { - return mName.equals(name); - } - - @Override - public boolean isArray() { - return mName.endsWith("[]"); - } - - @Override - public boolean isPrimitive() { - return mName.indexOf('.') != -1; - } - - @Override - public boolean matchesSignature(@NonNull String signature) { - return matchesName(signature); - } - - @Override - public String toString() { - return getSignature(); - } - - @Override - @Nullable - public ResolvedClass getTypeClass() { - return null; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - DefaultTypeDescriptor that = (DefaultTypeDescriptor) o; - - return !(mName != null ? !mName.equals(that.mName) : that.mName != null); - - } - - @Override - public int hashCode() { - return mName != null ? mName.hashCode() : 0; - } - } - - /** - * A resolved declaration from an AST Node reference - * @deprecated Use {@link JavaPsiScanner} APIs instead - */ - @SuppressWarnings("unused") - @Deprecated - public abstract static class ResolvedNode { - @NonNull - public abstract String getName(); - - /** Returns the signature of the resolved node */ - public abstract String getSignature(); - - public abstract int getModifiers(); - - @Override - public String toString() { - return getSignature(); - } - - /** Returns any annotations defined on this node */ - @NonNull - public abstract Iterable getAnnotations(); - - /** - * Searches for the annotation of the given type on this node - * - * @param type the fully qualified name of the annotation to check - * @return the annotation, or null if not found - */ - @Nullable - public ResolvedAnnotation getAnnotation(@NonNull String type) { - for (ResolvedAnnotation annotation : getAnnotations()) { - if (annotation.getType().matchesSignature(type)) { - return annotation; - } - } - - return null; - } - - /** - * Returns true if this element is in the given package (or optionally, in one of its sub - * packages) - * - * @param pkg the package name - * @param includeSubPackages whether to include subpackages - * @return true if the element is in the given package - */ - public boolean isInPackage(@NonNull String pkg, boolean includeSubPackages) { - return getSignature().startsWith(pkg); - } - - /** - * Attempts to find the corresponding AST node, if possible. This won't work if for example - * the resolved node is from a binary (such as a compiled class in a .jar) or if the - * underlying parser doesn't support it. - *

- * Note that looking up the AST node can result in different instances for each lookup. - * - * @return an AST node, if possible. - */ - @Nullable - public Node findAstNode() { - return null; - } - } - - /** - * A resolved class declaration (class, interface, enumeration or annotation) - * @deprecated Use {@link JavaPsiScanner} APIs instead - */ - @SuppressWarnings("unused") - @Deprecated - public abstract static class ResolvedClass extends ResolvedNode { - /** Returns the fully qualified name of this class */ - @Override - @NonNull - public abstract String getName(); - - /** Returns the simple name of this class */ - @NonNull - public abstract String getSimpleName(); - - /** Returns the package name of this class */ - @NonNull - public String getPackageName() { - String name = getName(); - String simpleName = getSimpleName(); - if (name.length() > simpleName.length() + 1) { - return name.substring(0, name.length() - simpleName.length() - 1); - } - return name; - } - - /** Returns whether this class' fully qualified name matches the given name */ - public abstract boolean matches(@NonNull String name); - - @Nullable - public abstract ResolvedClass getSuperClass(); - - @NonNull - public abstract Iterable getInterfaces(); - - @Nullable - public abstract ResolvedClass getContainingClass(); - - public abstract boolean isInterface(); - public abstract boolean isEnum(); - - public TypeDescriptor getType() { - return new DefaultTypeDescriptor(getName()); - } - - /** - * Determines whether this class extends the given name. If strict is true, - * it will not consider C extends C true. - *

- * The target must be a class; to check whether this class extends an interface, - * use {@link #isImplementing(String,boolean)} instead. If you're not sure, use - * {@link #isInheritingFrom(String, boolean)}. - * - * @param name the fully qualified class name - * @param strict if true, do not consider a class to be extending itself - * @return true if this class extends the given class - */ - public abstract boolean isSubclassOf(@NonNull String name, boolean strict); - - /** - * Determines whether this is implementing the given interface. - *

- * The target must be an interface; to check whether this class extends a class, - * use {@link #isSubclassOf(String, boolean)} instead. If you're not sure, use - * {@link #isInheritingFrom(String, boolean)}. - * - * @param name the fully qualified interface name - * @param strict if true, do not consider a class to be extending itself - * @return true if this class implements the given interface - */ - public abstract boolean isImplementing(@NonNull String name, boolean strict); - - /** - * Determines whether this class extends or implements the class of the given name. - * If strict is true, it will not consider C extends C true. - *

- * For performance reasons, if you know that the target is a class, consider using - * {@link #isSubclassOf(String, boolean)} instead, and if the target is an interface, - * consider using {@link #isImplementing(String,boolean)}. - * - * @param name the fully qualified class name - * @param strict if true, do not consider a class to be inheriting from itself - * @return true if this class extends or implements the given class - */ - public abstract boolean isInheritingFrom(@NonNull String name, boolean strict); - - @NonNull - public abstract Iterable getConstructors(); - - /** Returns the methods defined in this class, and optionally any methods inherited from any superclasses as well */ - @NonNull - public abstract Iterable getMethods(boolean includeInherited); - - /** Returns the methods of a given name defined in this class, and optionally any methods inherited from any superclasses as well */ - @NonNull - public abstract Iterable getMethods(@NonNull String name, boolean includeInherited); - - /** Returns the fields defined in this class, and optionally any fields declared in any superclasses as well */ - @NonNull - public abstract Iterable getFields(boolean includeInherited); - - /** Returns the named field defined in this class, or optionally inherited from a superclass */ - @Nullable - public abstract ResolvedField getField(@NonNull String name, boolean includeInherited); - - /** Returns the package containing this class */ - @Nullable - public abstract ResolvedPackage getPackage(); - - @Override - public boolean isInPackage(@NonNull String pkg, boolean includeSubPackages) { - String packageName = getPackageName(); - - //noinspection SimplifiableIfStatement - if (pkg.equals(packageName)) { - return true; - } - - return includeSubPackages && packageName.length() > pkg.length() && - packageName.charAt(pkg.length()) == '.' && - packageName.startsWith(pkg); - } - } - - /** - * A method or constructor declaration - * @deprecated Use {@link JavaPsiScanner} APIs instead - */ - @SuppressWarnings("unused") - @Deprecated - public abstract static class ResolvedMethod extends ResolvedNode { - @Override - @NonNull - public abstract String getName(); - - /** Returns whether this method name matches the given name */ - public abstract boolean matches(@NonNull String name); - - @NonNull - public abstract ResolvedClass getContainingClass(); - - public abstract int getArgumentCount(); - - @NonNull - public abstract TypeDescriptor getArgumentType(int index); - - /** Returns true if the parameter at the given index matches the given type signature */ - public boolean argumentMatchesType(int index, @NonNull String signature) { - return getArgumentType(index).matchesSignature(signature); - } - - @Nullable - public abstract TypeDescriptor getReturnType(); - - public boolean isConstructor() { - return getReturnType() == null; - } - - /** Returns any annotations defined on the given parameter of this method */ - @NonNull - public abstract Iterable getParameterAnnotations(int index); - - /** - * Searches for the annotation of the given type on the method - * - * @param type the fully qualified name of the annotation to check - * @param parameterIndex the index of the parameter to look up - * @return the annotation, or null if not found - */ - @Nullable - public ResolvedAnnotation getParameterAnnotation(@NonNull String type, - int parameterIndex) { - for (ResolvedAnnotation annotation : getParameterAnnotations(parameterIndex)) { - if (annotation.getType().matchesSignature(type)) { - return annotation; - } - } - - return null; - } - - /** Returns the super implementation of the given method, if any */ - @Nullable - public ResolvedMethod getSuperMethod() { - if ((getModifiers() & Modifier.PRIVATE) != 0) { - // Private methods aren't overriding anything - return null; - } - ResolvedClass cls = getContainingClass().getSuperClass(); - if (cls != null) { - String methodName = getName(); - int argCount = getArgumentCount(); - for (ResolvedMethod method : cls.getMethods(methodName, true)) { - if (argCount != method.getArgumentCount()) { - continue; - } - boolean sameTypes = true; - for (int arg = 0; arg < argCount; arg++) { - if (!method.getArgumentType(arg).equals(getArgumentType(arg))) { - sameTypes = false; - break; - } - } - if (sameTypes) { - if ((method.getModifiers() & Modifier.PRIVATE) != 0) { - // Normally can't override private methods - unless they're - // in the same compilation unit where the compiler will create - // an accessor method to trampoline over to it. - // - // Compare compilation units: - if (haveSameCompilationUnit(getContainingClass(), - method.getContainingClass())) { - return method; - } else { - // We can stop the search; this is invalid (you can't have a - // private method in the middle of a chain; the compiler would - // complain about weaker access) - return null; - } - } - return method; - } - } - } - - return null; - } - - @Override - public boolean isInPackage(@NonNull String pkg, boolean includeSubPackages) { - String packageName = getContainingClass().getPackageName(); - - //noinspection SimplifiableIfStatement - if (pkg.equals(packageName)) { - return true; - } - - return includeSubPackages && packageName.length() > pkg.length() && - packageName.charAt(pkg.length()) == '.' && - packageName.startsWith(pkg); - } - } - - /** - * @deprecated Use {@link JavaPsiScanner} APIs instead - */ - @Deprecated - private static boolean haveSameCompilationUnit(@Nullable ResolvedClass cls1, - @Nullable ResolvedClass cls2) { - if (cls1 == null || cls2 == null) { - return false; - } - //noinspection ConstantConditions - while (cls1.getContainingClass() != null) { - cls1 = cls1.getContainingClass(); - } - //noinspection ConstantConditions - while (cls2.getContainingClass() != null) { - cls2 = cls2.getContainingClass(); - } - return cls1.equals(cls2); - } - - /** - * A field declaration - * @deprecated Use {@link JavaPsiScanner} APIs instead - */ - @Deprecated - public abstract static class ResolvedField extends ResolvedNode { - @Override - @NonNull - public abstract String getName(); - - /** Returns whether this field name matches the given name */ - public abstract boolean matches(@NonNull String name); - - @NonNull - public abstract TypeDescriptor getType(); - - @Nullable - public abstract ResolvedClass getContainingClass(); - - @Nullable - public abstract Object getValue(); - - @Nullable - public String getContainingClassName() { - ResolvedClass containingClass = getContainingClass(); - return containingClass != null ? containingClass.getName() : null; - } - - @Override - public boolean isInPackage(@NonNull String pkg, boolean includeSubPackages) { - ResolvedClass containingClass = getContainingClass(); - if (containingClass == null) { - return false; - } - - String packageName = containingClass.getPackageName(); - - //noinspection SimplifiableIfStatement - if (pkg.equals(packageName)) { - return true; - } - - return includeSubPackages && packageName.length() > pkg.length() && - packageName.charAt(pkg.length()) == '.' && - packageName.startsWith(pkg); - } - } - - /** - * An annotation reference. Note that this refers to a usage of an annotation, - * not a declaraton of an annotation. You can call {@link #getClassType()} to - * find the declaration for the annotation. - * @deprecated Use {@link JavaPsiScanner} APIs instead - */ - @Deprecated - public abstract static class ResolvedAnnotation extends ResolvedNode { - @Override - @NonNull - public abstract String getName(); - - /** Returns whether this field name matches the given name */ - public abstract boolean matches(@NonNull String name); - - @NonNull - public abstract TypeDescriptor getType(); - - /** Returns the {@link ResolvedClass} which defines the annotation */ - @Nullable - public abstract ResolvedClass getClassType(); - - public static class Value { - @NonNull public final String name; - @Nullable public final Object value; - - public Value(@NonNull String name, @Nullable Object value) { - this.name = name; - this.value = value; - } - } - - @NonNull - public abstract List getValues(); - - @Nullable - public Object getValue(@NonNull String name) { - for (Value value : getValues()) { - if (name.equals(value.name)) { - return value.value; - } - } - return null; - } - - @Nullable - public Object getValue() { - return getValue(ATTR_VALUE); - } - - @NonNull - @Override - public Iterable getAnnotations() { - return Collections.emptyList(); - } - } - - /** - * A package declaration - * @deprecated Use {@link JavaPsiScanner} APIs instead - */ - @SuppressWarnings("unused") - @Deprecated - public abstract static class ResolvedPackage extends ResolvedNode { - /** Returns the parent package of this package, if any. */ - @Nullable - public abstract ResolvedPackage getParentPackage(); - - @NonNull - @Override - public Iterable getAnnotations() { - return Collections.emptyList(); - } - } - - /** - * A local variable or parameter declaration - * @deprecated Use {@link JavaPsiScanner} APIs instead - */ - @Deprecated - public abstract static class ResolvedVariable extends ResolvedNode { - @Override - @NonNull - public abstract String getName(); - - /** Returns whether this variable name matches the given name */ - public abstract boolean matches(@NonNull String name); - - @NonNull - public abstract TypeDescriptor getType(); - } -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/JavaPsiVisitor.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/client/api/JavaPsiVisitor.java.173 deleted file mode 100644 index 772ca31508b..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/JavaPsiVisitor.java.173 +++ /dev/null @@ -1,1716 +0,0 @@ -/* - * Copyright (C) 2016 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.client.api; - -import static com.android.SdkConstants.ANDROID_PKG; -import static com.android.SdkConstants.R_CLASS; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.annotations.VisibleForTesting; -import com.android.resources.ResourceType; -import com.android.tools.klint.detector.api.Detector; -import com.android.tools.klint.detector.api.Detector.JavaPsiScanner; -import com.android.tools.klint.detector.api.Detector.XmlScanner; -import com.android.tools.klint.detector.api.JavaContext; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import com.intellij.openapi.progress.ProcessCanceledException; -import com.intellij.psi.ImplicitVariable; -import com.intellij.psi.JavaElementVisitor; -import com.intellij.psi.JavaRecursiveElementVisitor; -import com.intellij.psi.PsiAnnotation; -import com.intellij.psi.PsiAnnotationMethod; -import com.intellij.psi.PsiAnnotationParameterList; -import com.intellij.psi.PsiAnonymousClass; -import com.intellij.psi.PsiArrayAccessExpression; -import com.intellij.psi.PsiArrayInitializerExpression; -import com.intellij.psi.PsiArrayInitializerMemberValue; -import com.intellij.psi.PsiAssertStatement; -import com.intellij.psi.PsiAssignmentExpression; -import com.intellij.psi.PsiBinaryExpression; -import com.intellij.psi.PsiBlockStatement; -import com.intellij.psi.PsiBreakStatement; -import com.intellij.psi.PsiCallExpression; -import com.intellij.psi.PsiCatchSection; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiClassInitializer; -import com.intellij.psi.PsiClassObjectAccessExpression; -import com.intellij.psi.PsiCodeBlock; -import com.intellij.psi.PsiConditionalExpression; -import com.intellij.psi.PsiContinueStatement; -import com.intellij.psi.PsiDeclarationStatement; -import com.intellij.psi.PsiDoWhileStatement; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiEmptyStatement; -import com.intellij.psi.PsiEnumConstant; -import com.intellij.psi.PsiEnumConstantInitializer; -import com.intellij.psi.PsiExpression; -import com.intellij.psi.PsiExpressionList; -import com.intellij.psi.PsiExpressionListStatement; -import com.intellij.psi.PsiExpressionStatement; -import com.intellij.psi.PsiField; -import com.intellij.psi.PsiForStatement; -import com.intellij.psi.PsiForeachStatement; -import com.intellij.psi.PsiIdentifier; -import com.intellij.psi.PsiIfStatement; -import com.intellij.psi.PsiImportList; -import com.intellij.psi.PsiImportStatement; -import com.intellij.psi.PsiImportStaticReferenceElement; -import com.intellij.psi.PsiImportStaticStatement; -import com.intellij.psi.PsiInstanceOfExpression; -import com.intellij.psi.PsiJavaCodeReferenceElement; -import com.intellij.psi.PsiJavaFile; -import com.intellij.psi.PsiJavaToken; -import com.intellij.psi.PsiKeyword; -import com.intellij.psi.PsiLabeledStatement; -import com.intellij.psi.PsiLambdaExpression; -import com.intellij.psi.PsiLiteralExpression; -import com.intellij.psi.PsiLocalVariable; -import com.intellij.psi.PsiMethod; -import com.intellij.psi.PsiMethodCallExpression; -import com.intellij.psi.PsiMethodReferenceExpression; -import com.intellij.psi.PsiModifierList; -import com.intellij.psi.PsiNameValuePair; -import com.intellij.psi.PsiNewExpression; -import com.intellij.psi.PsiPackage; -import com.intellij.psi.PsiPackageStatement; -import com.intellij.psi.PsiParameter; -import com.intellij.psi.PsiParameterList; -import com.intellij.psi.PsiParenthesizedExpression; -import com.intellij.psi.PsiPolyadicExpression; -import com.intellij.psi.PsiPostfixExpression; -import com.intellij.psi.PsiPrefixExpression; -import com.intellij.psi.PsiReceiverParameter; -import com.intellij.psi.PsiReferenceExpression; -import com.intellij.psi.PsiReferenceList; -import com.intellij.psi.PsiReferenceParameterList; -import com.intellij.psi.PsiResourceList; -import com.intellij.psi.PsiResourceVariable; -import com.intellij.psi.PsiReturnStatement; -import com.intellij.psi.PsiStatement; -import com.intellij.psi.PsiSuperExpression; -import com.intellij.psi.PsiSwitchLabelStatement; -import com.intellij.psi.PsiSwitchStatement; -import com.intellij.psi.PsiSynchronizedStatement; -import com.intellij.psi.PsiThisExpression; -import com.intellij.psi.PsiThrowStatement; -import com.intellij.psi.PsiTryStatement; -import com.intellij.psi.PsiTypeCastExpression; -import com.intellij.psi.PsiTypeElement; -import com.intellij.psi.PsiTypeParameter; -import com.intellij.psi.PsiTypeParameterList; -import com.intellij.psi.PsiVariable; -import com.intellij.psi.PsiWhileStatement; -import com.intellij.psi.javadoc.PsiDocComment; -import com.intellij.psi.javadoc.PsiDocTag; -import com.intellij.psi.javadoc.PsiDocTagValue; -import com.intellij.psi.javadoc.PsiDocToken; -import com.intellij.psi.javadoc.PsiInlineDocTag; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Specialized visitor for running detectors on a Java AST. - * It operates in three phases: - *

    - *
  1. First, it computes a set of maps where it generates a map from each - * significant AST attribute (such as method call names) to a list - * of detectors to consult whenever that attribute is encountered. - * Examples of "attributes" are method names, Android resource identifiers, - * and general AST node types such as "cast" nodes etc. These are - * defined on the {@link JavaPsiScanner} interface. - *
  2. Second, it iterates over the document a single time, delegating to - * the detectors found at each relevant AST attribute. - *
  3. Finally, it calls the remaining visitors (those that need to process a - * whole document on their own). - *
- * It also notifies all the detectors before and after the document is processed - * such that they can do pre- and post-processing. - */ -public class JavaPsiVisitor { - /** Default size of lists holding detectors of the same type for a given node type */ - private static final int SAME_TYPE_COUNT = 8; - - private final Map> mMethodDetectors = - Maps.newHashMapWithExpectedSize(80); - private final Map> mConstructorDetectors = - Maps.newHashMapWithExpectedSize(12); - private final Map> mReferenceDetectors = - Maps.newHashMapWithExpectedSize(10); - private Set mConstructorSimpleNames; - private final List mResourceFieldDetectors = - new ArrayList(); - private final List mAllDetectors; - private final List mFullTreeDetectors; - private final Map, List> mNodePsiTypeDetectors = - new HashMap, List>(16); - private final JavaParser mParser; - private final Map> mSuperClassDetectors = - new HashMap>(); - - /** - * Number of fatal exceptions (internal errors, usually from ECJ) we've - * encountered; we don't log each and every one to avoid massive log spam - * in code which triggers this condition - */ - private static int sExceptionCount; - /** Max number of logs to include */ - private static final int MAX_REPORTED_CRASHES = 20; - - JavaPsiVisitor(@NonNull JavaParser parser, @NonNull List detectors) { - mParser = parser; - mAllDetectors = new ArrayList(detectors.size()); - mFullTreeDetectors = new ArrayList(detectors.size()); - - for (Detector detector : detectors) { - JavaPsiScanner javaPsiScanner = (JavaPsiScanner) detector; - VisitingDetector v = new VisitingDetector(detector, javaPsiScanner); - mAllDetectors.add(v); - - List applicableSuperClasses = detector.applicableSuperClasses(); - if (applicableSuperClasses != null) { - for (String fqn : applicableSuperClasses) { - List list = mSuperClassDetectors.get(fqn); - if (list == null) { - list = new ArrayList(SAME_TYPE_COUNT); - mSuperClassDetectors.put(fqn, list); - } - list.add(v); - } - continue; - } - - List> nodePsiTypes = detector.getApplicablePsiTypes(); - if (nodePsiTypes != null) { - for (Class type : nodePsiTypes) { - List list = mNodePsiTypeDetectors.get(type); - if (list == null) { - list = new ArrayList(SAME_TYPE_COUNT); - mNodePsiTypeDetectors.put(type, list); - } - list.add(v); - } - } - - List names = detector.getApplicableMethodNames(); - if (names != null) { - // not supported in Java visitors; adding a method invocation node is trivial - // for that case. - assert names != XmlScanner.ALL; - - for (String name : names) { - List list = mMethodDetectors.get(name); - if (list == null) { - list = new ArrayList(SAME_TYPE_COUNT); - mMethodDetectors.put(name, list); - } - list.add(v); - } - } - - List types = detector.getApplicableConstructorTypes(); - if (types != null) { - // not supported in Java visitors; adding a method invocation node is trivial - // for that case. - assert types != XmlScanner.ALL; - if (mConstructorSimpleNames == null) { - mConstructorSimpleNames = Sets.newHashSet(); - } - for (String type : types) { - List list = mConstructorDetectors.get(type); - if (list == null) { - list = new ArrayList(SAME_TYPE_COUNT); - mConstructorDetectors.put(type, list); - mConstructorSimpleNames.add(type.substring(type.lastIndexOf('.')+1)); - } - list.add(v); - } - } - - List referenceNames = detector.getApplicableReferenceNames(); - if (referenceNames != null) { - // not supported in Java visitors; adding a method invocation node is trivial - // for that case. - assert referenceNames != XmlScanner.ALL; - - for (String name : referenceNames) { - List list = mReferenceDetectors.get(name); - if (list == null) { - list = new ArrayList(SAME_TYPE_COUNT); - mReferenceDetectors.put(name, list); - } - list.add(v); - } - } - - if (detector.appliesToResourceRefs()) { - mResourceFieldDetectors.add(v); - } else if ((referenceNames == null || referenceNames.isEmpty()) - && (nodePsiTypes == null || nodePsiTypes.isEmpty()) - && (types == null || types.isEmpty())) { - mFullTreeDetectors.add(v); - } - } - } - - void visitFile(@NonNull final JavaContext context) { - try { - final PsiJavaFile javaFile = mParser.parseJavaToPsi(context); - if (javaFile == null) { - // No need to log this; the parser should be reporting - // a full warning (such as IssueRegistry#PARSER_ERROR) - // with details, location, etc. - return; - } - try { - context.setJavaFile(javaFile); - - mParser.runReadAction(new Runnable() { - @Override - public void run() { - for (VisitingDetector v : mAllDetectors) { - v.setContext(context); - v.getDetector().beforeCheckFile(context); - } - } - }); - - if (!mSuperClassDetectors.isEmpty()) { - mParser.runReadAction(new Runnable() { - @Override - public void run() { - SuperclassPsiVisitor visitor = new SuperclassPsiVisitor(context); - javaFile.accept(visitor); - } - }); - } - - for (final VisitingDetector v : mFullTreeDetectors) { - mParser.runReadAction(new Runnable() { - @Override - public void run() { - JavaElementVisitor visitor = v.getVisitor(); - javaFile.accept(visitor); - } - }); - } - - if (!mMethodDetectors.isEmpty() - || !mResourceFieldDetectors.isEmpty() - || !mConstructorDetectors.isEmpty() - || !mReferenceDetectors.isEmpty()) { - mParser.runReadAction(new Runnable() { - @Override - public void run() { - // TODO: Do we need to break this one up into finer grain - // locking units - JavaElementVisitor visitor = new DelegatingPsiVisitor(context); - javaFile.accept(visitor); - } - }); - } else { - if (!mNodePsiTypeDetectors.isEmpty()) { - mParser.runReadAction(new Runnable() { - @Override - public void run() { - // TODO: Do we need to break this one up into finer grain - // locking units - JavaElementVisitor visitor = new DispatchPsiVisitor(); - javaFile.accept(visitor); - } - }); - } - } - - mParser.runReadAction(new Runnable() { - @Override - public void run() { - for (VisitingDetector v : mAllDetectors) { - v.getDetector().afterCheckFile(context); - } - } - }); - } finally { - mParser.dispose(context, javaFile); - context.setJavaFile(null); - } - } catch (ProcessCanceledException ignore) { - // Cancelling inspections in the IDE - } catch (RuntimeException e) { - if (sExceptionCount++ > MAX_REPORTED_CRASHES) { - // No need to keep spamming the user that a lot of the files - // are tripping up ECJ, they get the picture. - return; - } - - if (e.getClass().getSimpleName().equals("IndexNotReadyException")) { - // Attempting to access PSI during startup before indices are ready; ignore these. - // See http://b.android.com/176644 for an example. - return; - } - - // Work around ECJ bugs; see https://code.google.com/p/android/issues/detail?id=172268 - // Don't allow lint bugs to take down the whole build. TRY to log this as a - // lint error instead! - StringBuilder sb = new StringBuilder(100); - sb.append("Unexpected failure during lint analysis of "); - sb.append(context.file.getName()); - sb.append(" (this is a bug in lint or one of the libraries it depends on)\n"); - - sb.append(e.getClass().getSimpleName()); - sb.append(':'); - StackTraceElement[] stackTrace = e.getStackTrace(); - int count = 0; - for (StackTraceElement frame : stackTrace) { - if (count > 0) { - sb.append("<-"); - } - - String className = frame.getClassName(); - sb.append(className.substring(className.lastIndexOf('.') + 1)); - sb.append('.').append(frame.getMethodName()); - sb.append('('); - sb.append(frame.getFileName()).append(':').append(frame.getLineNumber()); - sb.append(')'); - count++; - // Only print the top 3-4 frames such that we can identify the bug - if (count == 4) { - break; - } - } - Throwable throwable = null; // NOT e: this makes for very noisy logs - //noinspection ConstantConditions - context.log(throwable, sb.toString()); - } - } - - /** - * For testing only: returns the number of exceptions thrown during Java AST analysis - * - * @return the number of internal errors found - */ - @VisibleForTesting - public static int getCrashCount() { - return sExceptionCount; - } - - /** - * For testing only: clears the crash counter - */ - @VisibleForTesting - public static void clearCrashCount() { - sExceptionCount = 0; - } - - public void prepare(@NonNull List contexts) { - mParser.prepareJavaParse(contexts); - } - - public void dispose() { - mParser.dispose(); - } - - @Nullable - private static Set getInterfaceNames( - @Nullable Set addTo, - @NonNull PsiClass cls) { - for (PsiClass resolvedInterface : cls.getInterfaces()) { - String name = resolvedInterface.getQualifiedName(); - if (addTo == null) { - addTo = Sets.newHashSet(); - } else if (addTo.contains(name)) { - // Superclasses can explicitly implement the same interface, - // so keep track of visited interfaces as we traverse up the - // super class chain to avoid checking the same interface - // more than once. - continue; - } - addTo.add(name); - getInterfaceNames(addTo, resolvedInterface); - } - - return addTo; - } - - private static class VisitingDetector { - private JavaElementVisitor mVisitor; - private JavaContext mContext; - public final Detector mDetector; - public final JavaPsiScanner mJavaScanner; - - public VisitingDetector(@NonNull Detector detector, @NonNull JavaPsiScanner javaScanner) { - mDetector = detector; - mJavaScanner = javaScanner; - } - - @NonNull - public Detector getDetector() { - return mDetector; - } - - @Nullable - public JavaPsiScanner getJavaScanner() { - return mJavaScanner; - } - - public void setContext(@NonNull JavaContext context) { - mContext = context; - - // The visitors are one-per-context, so clear them out here and construct - // lazily only if needed - mVisitor = null; - } - - @NonNull - JavaElementVisitor getVisitor() { - if (mVisitor == null) { - mVisitor = mDetector.createPsiVisitor(mContext); - assert !(mVisitor instanceof JavaRecursiveElementVisitor) : - "Your visitor (returned by " + mDetector.getClass().getSimpleName() - + "#createPsiVisitor(...) should *not* extend " - + " JavaRecursiveElementVisitor; use a plain " - + "JavaElementVisitor instead. The lint infrastructure does its own " - + "recursion calling *just* your visit methods specified in " - + "getApplicablePsiTypes"; - if (mVisitor == null) { - mVisitor = new JavaElementVisitor() { - @Override - public void visitElement(PsiElement element) { - // No-op. Workaround for super currently calling - // ProgressIndicatorProvider.checkCanceled(); - } - }; - } - } - return mVisitor; - } - } - - private class SuperclassPsiVisitor extends JavaRecursiveElementVisitor { - private JavaContext mContext; - - public SuperclassPsiVisitor(@NonNull JavaContext context) { - mContext = context; - } - - @Override - public void visitClass(@NonNull PsiClass node) { - super.visitClass(node); - checkClass(node); - } - - private void checkClass(@NonNull PsiClass node) { - if (node instanceof PsiTypeParameter) { - // Not included: explained in javadoc for JavaPsiScanner#checkClass - return; - } - - PsiClass cls = node; - int depth = 0; - while (cls != null) { - List list = mSuperClassDetectors.get(cls.getQualifiedName()); - if (list != null) { - for (VisitingDetector v : list) { - JavaPsiScanner javaPsiScanner = v.getJavaScanner(); - if (javaPsiScanner != null) { - javaPsiScanner.checkClass(mContext, node); - } - } - } - - // Check interfaces too - Set interfaceNames = getInterfaceNames(null, cls); - if (interfaceNames != null) { - for (String name : interfaceNames) { - list = mSuperClassDetectors.get(name); - if (list != null) { - for (VisitingDetector v : list) { - JavaPsiScanner javaPsiScanner = v.getJavaScanner(); - if (javaPsiScanner != null) { - javaPsiScanner.checkClass(mContext, node); - } - } - } - } - } - - cls = cls.getSuperClass(); - depth++; - if (depth == 500) { - // Shouldn't happen in practice; this prevents the IDE from - // hanging if the user has accidentally typed in an incorrect - // super class which creates a cycle. - break; - } - } - } - } - - private class DispatchPsiVisitor extends JavaRecursiveElementVisitor { - - @Override - public void visitAnonymousClass(PsiAnonymousClass node) { - List list = mNodePsiTypeDetectors.get(PsiAnonymousClass.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitAnonymousClass(node); - } - } - super.visitAnonymousClass(node); - } - - @Override - public void visitArrayAccessExpression(PsiArrayAccessExpression node) { - List list = mNodePsiTypeDetectors.get(PsiArrayAccessExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitArrayAccessExpression(node); - } - } - super.visitArrayAccessExpression(node); - } - - @Override - public void visitArrayInitializerExpression(PsiArrayInitializerExpression node) { - List list = mNodePsiTypeDetectors - .get(PsiArrayInitializerExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitArrayInitializerExpression(node); - } - } - super.visitArrayInitializerExpression(node); - } - - @Override - public void visitAssertStatement(PsiAssertStatement node) { - List list = mNodePsiTypeDetectors.get(PsiAssertStatement.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitAssertStatement(node); - } - } - super.visitAssertStatement(node); - } - - @Override - public void visitAssignmentExpression(PsiAssignmentExpression node) { - List list = mNodePsiTypeDetectors.get(PsiAssignmentExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitAssignmentExpression(node); - } - } - super.visitAssignmentExpression(node); - } - - @Override - public void visitBinaryExpression(PsiBinaryExpression node) { - List list = mNodePsiTypeDetectors.get(PsiBinaryExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitBinaryExpression(node); - } - } - super.visitBinaryExpression(node); - } - - @Override - public void visitBlockStatement(PsiBlockStatement node) { - List list = mNodePsiTypeDetectors.get(PsiBlockStatement.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitBlockStatement(node); - } - } - super.visitBlockStatement(node); - } - - @Override - public void visitBreakStatement(PsiBreakStatement node) { - List list = mNodePsiTypeDetectors.get(PsiBreakStatement.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitBreakStatement(node); - } - } - super.visitBreakStatement(node); - } - - @Override - public void visitClass(PsiClass node) { - List list = mNodePsiTypeDetectors.get(PsiClass.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitClass(node); - } - } - super.visitClass(node); - } - - @Override - public void visitClassInitializer(PsiClassInitializer node) { - List list = mNodePsiTypeDetectors.get(PsiClassInitializer.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitClassInitializer(node); - } - } - super.visitClassInitializer(node); - } - - @Override - public void visitClassObjectAccessExpression(PsiClassObjectAccessExpression node) { - List list = mNodePsiTypeDetectors - .get(PsiClassObjectAccessExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitClassObjectAccessExpression(node); - } - } - super.visitClassObjectAccessExpression(node); - } - - @Override - public void visitCodeBlock(PsiCodeBlock node) { - List list = mNodePsiTypeDetectors.get(PsiCodeBlock.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitCodeBlock(node); - } - } - super.visitCodeBlock(node); - } - - @Override - public void visitConditionalExpression(PsiConditionalExpression node) { - List list = mNodePsiTypeDetectors.get(PsiConditionalExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitConditionalExpression(node); - } - } - super.visitConditionalExpression(node); - } - - @Override - public void visitContinueStatement(PsiContinueStatement node) { - List list = mNodePsiTypeDetectors.get(PsiContinueStatement.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitContinueStatement(node); - } - } - super.visitContinueStatement(node); - } - - @Override - public void visitDeclarationStatement(PsiDeclarationStatement node) { - List list = mNodePsiTypeDetectors.get(PsiDeclarationStatement.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitDeclarationStatement(node); - } - } - super.visitDeclarationStatement(node); - } - - @Override - public void visitDocComment(PsiDocComment node) { - List list = mNodePsiTypeDetectors.get(PsiDocComment.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitDocComment(node); - } - } - super.visitDocComment(node); - } - - @Override - public void visitDocTag(PsiDocTag node) { - List list = mNodePsiTypeDetectors.get(PsiDocTag.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitDocTag(node); - } - } - super.visitDocTag(node); - } - - @Override - public void visitDocTagValue(PsiDocTagValue node) { - List list = mNodePsiTypeDetectors.get(PsiDocTagValue.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitDocTagValue(node); - } - } - super.visitDocTagValue(node); - } - - @Override - public void visitDoWhileStatement(PsiDoWhileStatement node) { - List list = mNodePsiTypeDetectors.get(PsiDoWhileStatement.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitDoWhileStatement(node); - } - } - super.visitDoWhileStatement(node); - } - - @Override - public void visitEmptyStatement(PsiEmptyStatement node) { - List list = mNodePsiTypeDetectors.get(PsiEmptyStatement.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitEmptyStatement(node); - } - } - super.visitEmptyStatement(node); - } - - @Override - public void visitExpression(PsiExpression node) { - List list = mNodePsiTypeDetectors.get(PsiExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitExpression(node); - } - } - super.visitExpression(node); - } - - @Override - public void visitExpressionList(PsiExpressionList node) { - List list = mNodePsiTypeDetectors.get(PsiExpressionList.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitExpressionList(node); - } - } - super.visitExpressionList(node); - } - - @Override - public void visitExpressionListStatement(PsiExpressionListStatement node) { - List list = mNodePsiTypeDetectors - .get(PsiExpressionListStatement.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitExpressionListStatement(node); - } - } - super.visitExpressionListStatement(node); - } - - @Override - public void visitExpressionStatement(PsiExpressionStatement node) { - List list = mNodePsiTypeDetectors.get(PsiExpressionStatement.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitExpressionStatement(node); - } - } - super.visitExpressionStatement(node); - } - - @Override - public void visitField(PsiField node) { - List list = mNodePsiTypeDetectors.get(PsiField.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitField(node); - } - } - super.visitField(node); - } - - @Override - public void visitForStatement(PsiForStatement node) { - List list = mNodePsiTypeDetectors.get(PsiForStatement.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitForStatement(node); - } - } - super.visitForStatement(node); - } - - @Override - public void visitForeachStatement(PsiForeachStatement node) { - List list = mNodePsiTypeDetectors.get(PsiForeachStatement.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitForeachStatement(node); - } - } - super.visitForeachStatement(node); - } - - @Override - public void visitIdentifier(PsiIdentifier node) { - List list = mNodePsiTypeDetectors.get(PsiIdentifier.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitIdentifier(node); - } - } - super.visitIdentifier(node); - } - - @Override - public void visitIfStatement(PsiIfStatement node) { - List list = mNodePsiTypeDetectors.get(PsiIfStatement.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitIfStatement(node); - } - } - super.visitIfStatement(node); - } - - @Override - public void visitImportList(PsiImportList node) { - List list = mNodePsiTypeDetectors.get(PsiImportList.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitImportList(node); - } - } - super.visitImportList(node); - } - - @Override - public void visitImportStatement(PsiImportStatement node) { - List list = mNodePsiTypeDetectors.get(PsiImportStatement.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitImportStatement(node); - } - } - super.visitImportStatement(node); - } - - @Override - public void visitImportStaticStatement(PsiImportStaticStatement node) { - List list = mNodePsiTypeDetectors.get(PsiImportStaticStatement.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitImportStaticStatement(node); - } - } - super.visitImportStaticStatement(node); - } - - @Override - public void visitInlineDocTag(PsiInlineDocTag node) { - List list = mNodePsiTypeDetectors.get(PsiInlineDocTag.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitInlineDocTag(node); - } - } - super.visitInlineDocTag(node); - } - - @Override - public void visitInstanceOfExpression(PsiInstanceOfExpression node) { - List list = mNodePsiTypeDetectors.get(PsiInstanceOfExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitInstanceOfExpression(node); - } - } - super.visitInstanceOfExpression(node); - } - - @Override - public void visitJavaToken(PsiJavaToken node) { - List list = mNodePsiTypeDetectors.get(PsiJavaToken.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitJavaToken(node); - } - } - super.visitJavaToken(node); - } - - @Override - public void visitKeyword(PsiKeyword node) { - List list = mNodePsiTypeDetectors.get(PsiKeyword.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitKeyword(node); - } - } - super.visitKeyword(node); - } - - @Override - public void visitLabeledStatement(PsiLabeledStatement node) { - List list = mNodePsiTypeDetectors.get(PsiLabeledStatement.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitLabeledStatement(node); - } - } - super.visitLabeledStatement(node); - } - - @Override - public void visitLiteralExpression(PsiLiteralExpression node) { - List list = mNodePsiTypeDetectors.get(PsiLiteralExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitLiteralExpression(node); - } - } - super.visitLiteralExpression(node); - } - - @Override - public void visitLocalVariable(PsiLocalVariable node) { - List list = mNodePsiTypeDetectors.get(PsiLocalVariable.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitLocalVariable(node); - } - } - super.visitLocalVariable(node); - } - - @Override - public void visitMethod(PsiMethod node) { - List list = mNodePsiTypeDetectors.get(PsiMethod.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitMethod(node); - } - } - super.visitMethod(node); - } - - @Override - public void visitMethodCallExpression(PsiMethodCallExpression node) { - List list = mNodePsiTypeDetectors.get(PsiMethodCallExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitMethodCallExpression(node); - } - } - super.visitMethodCallExpression(node); - } - - @Override - public void visitCallExpression(PsiCallExpression node) { - List list = mNodePsiTypeDetectors.get(PsiCallExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitCallExpression(node); - } - } - super.visitCallExpression(node); - } - - @Override - public void visitModifierList(PsiModifierList node) { - List list = mNodePsiTypeDetectors.get(PsiModifierList.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitModifierList(node); - } - } - super.visitModifierList(node); - } - - @Override - public void visitNewExpression(PsiNewExpression node) { - List list = mNodePsiTypeDetectors.get(PsiNewExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitNewExpression(node); - } - } - super.visitNewExpression(node); - } - - @Override - public void visitPackage(PsiPackage node) { - List list = mNodePsiTypeDetectors.get(PsiPackage.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitPackage(node); - } - } - super.visitPackage(node); - } - - @Override - public void visitPackageStatement(PsiPackageStatement node) { - List list = mNodePsiTypeDetectors.get(PsiPackageStatement.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitPackageStatement(node); - } - } - super.visitPackageStatement(node); - } - - @Override - public void visitParameter(PsiParameter node) { - List list = mNodePsiTypeDetectors.get(PsiParameter.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitParameter(node); - } - } - super.visitParameter(node); - } - - @Override - public void visitReceiverParameter(PsiReceiverParameter node) { - List list = mNodePsiTypeDetectors.get(PsiReceiverParameter.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitReceiverParameter(node); - } - } - super.visitReceiverParameter(node); - } - - @Override - public void visitParameterList(PsiParameterList node) { - List list = mNodePsiTypeDetectors.get(PsiParameterList.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitParameterList(node); - } - } - super.visitParameterList(node); - } - - @Override - public void visitParenthesizedExpression(PsiParenthesizedExpression node) { - List list = mNodePsiTypeDetectors - .get(PsiParenthesizedExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitParenthesizedExpression(node); - } - } - super.visitParenthesizedExpression(node); - } - - @Override - public void visitPostfixExpression(PsiPostfixExpression node) { - List list = mNodePsiTypeDetectors.get(PsiPostfixExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitPostfixExpression(node); - } - } - super.visitPostfixExpression(node); - } - - @Override - public void visitPrefixExpression(PsiPrefixExpression node) { - List list = mNodePsiTypeDetectors.get(PsiPrefixExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitPrefixExpression(node); - } - } - super.visitPrefixExpression(node); - } - - @Override - public void visitReferenceElement(PsiJavaCodeReferenceElement node) { - List list = mNodePsiTypeDetectors - .get(PsiJavaCodeReferenceElement.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitReferenceElement(node); - } - } - super.visitReferenceElement(node); - } - - @Override - public void visitImportStaticReferenceElement(PsiImportStaticReferenceElement node) { - List list = mNodePsiTypeDetectors - .get(PsiImportStaticReferenceElement.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitImportStaticReferenceElement(node); - } - } - super.visitImportStaticReferenceElement(node); - } - - @Override - public void visitReferenceExpression(PsiReferenceExpression node) { - List list = mNodePsiTypeDetectors.get(PsiReferenceExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitReferenceExpression(node); - } - } - super.visitReferenceExpression(node); - } - - @Override - public void visitMethodReferenceExpression(PsiMethodReferenceExpression node) { - List list = mNodePsiTypeDetectors - .get(PsiMethodReferenceExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitMethodReferenceExpression(node); - } - } - super.visitMethodReferenceExpression(node); - } - - @Override - public void visitReferenceList(PsiReferenceList node) { - List list = mNodePsiTypeDetectors.get(PsiReferenceList.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitReferenceList(node); - } - } - super.visitReferenceList(node); - } - - @Override - public void visitReferenceParameterList(PsiReferenceParameterList node) { - List list = mNodePsiTypeDetectors - .get(PsiReferenceParameterList.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitReferenceParameterList(node); - } - } - super.visitReferenceParameterList(node); - } - - @Override - public void visitTypeParameterList(PsiTypeParameterList node) { - List list = mNodePsiTypeDetectors.get(PsiTypeParameterList.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitTypeParameterList(node); - } - } - super.visitTypeParameterList(node); - } - - @Override - public void visitReturnStatement(PsiReturnStatement node) { - List list = mNodePsiTypeDetectors.get(PsiReturnStatement.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitReturnStatement(node); - } - } - super.visitReturnStatement(node); - } - - @Override - public void visitStatement(PsiStatement node) { - List list = mNodePsiTypeDetectors.get(PsiStatement.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitStatement(node); - } - } - super.visitStatement(node); - } - - @Override - public void visitSuperExpression(PsiSuperExpression node) { - List list = mNodePsiTypeDetectors.get(PsiSuperExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitSuperExpression(node); - } - } - super.visitSuperExpression(node); - } - - @Override - public void visitSwitchLabelStatement(PsiSwitchLabelStatement node) { - List list = mNodePsiTypeDetectors.get(PsiSwitchLabelStatement.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitSwitchLabelStatement(node); - } - } - super.visitSwitchLabelStatement(node); - } - - @Override - public void visitSwitchStatement(PsiSwitchStatement node) { - List list = mNodePsiTypeDetectors.get(PsiSwitchStatement.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitSwitchStatement(node); - } - } - super.visitSwitchStatement(node); - } - - @Override - public void visitSynchronizedStatement(PsiSynchronizedStatement node) { - List list = mNodePsiTypeDetectors.get(PsiSynchronizedStatement.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitSynchronizedStatement(node); - } - } - super.visitSynchronizedStatement(node); - } - - @Override - public void visitThisExpression(PsiThisExpression node) { - List list = mNodePsiTypeDetectors.get(PsiThisExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitThisExpression(node); - } - } - super.visitThisExpression(node); - } - - @Override - public void visitThrowStatement(PsiThrowStatement node) { - List list = mNodePsiTypeDetectors.get(PsiThrowStatement.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitThrowStatement(node); - } - } - super.visitThrowStatement(node); - } - - @Override - public void visitTryStatement(PsiTryStatement node) { - List list = mNodePsiTypeDetectors.get(PsiTryStatement.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitTryStatement(node); - } - } - super.visitTryStatement(node); - } - - @Override - public void visitCatchSection(PsiCatchSection node) { - List list = mNodePsiTypeDetectors.get(PsiCatchSection.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitCatchSection(node); - } - } - super.visitCatchSection(node); - } - - @Override - public void visitResourceList(PsiResourceList node) { - List list = mNodePsiTypeDetectors.get(PsiResourceList.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitResourceList(node); - } - } - super.visitResourceList(node); - } - - @Override - public void visitResourceVariable(PsiResourceVariable node) { - List list = mNodePsiTypeDetectors.get(PsiResourceVariable.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitResourceVariable(node); - } - } - super.visitResourceVariable(node); - } - - @Override - public void visitTypeElement(PsiTypeElement node) { - List list = mNodePsiTypeDetectors.get(PsiTypeElement.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitTypeElement(node); - } - } - super.visitTypeElement(node); - } - - @Override - public void visitTypeCastExpression(PsiTypeCastExpression node) { - List list = mNodePsiTypeDetectors.get(PsiTypeCastExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitTypeCastExpression(node); - } - } - super.visitTypeCastExpression(node); - } - - @Override - public void visitVariable(PsiVariable node) { - List list = mNodePsiTypeDetectors.get(PsiVariable.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitVariable(node); - } - } - super.visitVariable(node); - } - - @Override - public void visitWhileStatement(PsiWhileStatement node) { - List list = mNodePsiTypeDetectors.get(PsiWhileStatement.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitWhileStatement(node); - } - } - super.visitWhileStatement(node); - } - - @Override - public void visitJavaFile(PsiJavaFile node) { - List list = mNodePsiTypeDetectors.get(PsiJavaFile.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitJavaFile(node); - } - } - super.visitJavaFile(node); - } - - @Override - public void visitImplicitVariable(ImplicitVariable node) { - List list = mNodePsiTypeDetectors.get(ImplicitVariable.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitImplicitVariable(node); - } - } - super.visitImplicitVariable(node); - } - - @Override - public void visitDocToken(PsiDocToken node) { - List list = mNodePsiTypeDetectors.get(PsiDocToken.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitDocToken(node); - } - } - super.visitDocToken(node); - } - - @Override - public void visitTypeParameter(PsiTypeParameter node) { - List list = mNodePsiTypeDetectors.get(PsiTypeParameter.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitTypeParameter(node); - } - } - super.visitTypeParameter(node); - } - - @Override - public void visitAnnotation(PsiAnnotation node) { - List list = mNodePsiTypeDetectors.get(PsiAnnotation.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitAnnotation(node); - } - } - super.visitAnnotation(node); - } - - @Override - public void visitAnnotationParameterList(PsiAnnotationParameterList node) { - List list = mNodePsiTypeDetectors - .get(PsiAnnotationParameterList.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitAnnotationParameterList(node); - } - } - super.visitAnnotationParameterList(node); - } - - @Override - public void visitAnnotationArrayInitializer(PsiArrayInitializerMemberValue node) { - List list = mNodePsiTypeDetectors - .get(PsiArrayInitializerMemberValue.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitAnnotationArrayInitializer(node); - } - } - super.visitAnnotationArrayInitializer(node); - } - - @Override - public void visitNameValuePair(PsiNameValuePair node) { - List list = mNodePsiTypeDetectors.get(PsiNameValuePair.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitNameValuePair(node); - } - } - super.visitNameValuePair(node); - } - - @Override - public void visitAnnotationMethod(PsiAnnotationMethod node) { - List list = mNodePsiTypeDetectors.get(PsiAnnotationMethod.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitAnnotationMethod(node); - } - } - super.visitAnnotationMethod(node); - } - - @Override - public void visitEnumConstant(PsiEnumConstant node) { - List list = mNodePsiTypeDetectors.get(PsiEnumConstant.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitEnumConstant(node); - } - } - super.visitEnumConstant(node); - } - - @Override - public void visitEnumConstantInitializer(PsiEnumConstantInitializer node) { - List list = mNodePsiTypeDetectors - .get(PsiEnumConstantInitializer.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitEnumConstantInitializer(node); - } - } - super.visitEnumConstantInitializer(node); - } - - @Override - public void visitPolyadicExpression(PsiPolyadicExpression node) { - List list = mNodePsiTypeDetectors.get(PsiPolyadicExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitPolyadicExpression(node); - } - } - super.visitPolyadicExpression(node); - } - - @Override - public void visitLambdaExpression(PsiLambdaExpression node) { - List list = mNodePsiTypeDetectors.get(PsiLambdaExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitLambdaExpression(node); - } - } - super.visitLambdaExpression(node); - } - } - - /** Performs common AST searches for method calls and R-type-field references. - * Note that this is a specialized form of the {@link DispatchPsiVisitor}. */ - private class DelegatingPsiVisitor extends DispatchPsiVisitor { - private final JavaContext mContext; - private final boolean mVisitResources; - private final boolean mVisitMethods; - private final boolean mVisitConstructors; - private final boolean mVisitReferences; - - public DelegatingPsiVisitor(JavaContext context) { - mContext = context; - - mVisitMethods = !mMethodDetectors.isEmpty(); - mVisitConstructors = !mConstructorDetectors.isEmpty(); - mVisitResources = !mResourceFieldDetectors.isEmpty(); - mVisitReferences = !mReferenceDetectors.isEmpty(); - } - - @Override - public void visitReferenceElement(PsiJavaCodeReferenceElement element) { - if (mVisitReferences) { - String name = element.getReferenceName(); - if (name != null) { - List list = mReferenceDetectors.get(name); - if (list != null) { - PsiElement referenced = element.resolve(); - if (referenced != null) { - for (VisitingDetector v : list) { - JavaPsiScanner javaPsiScanner = v.getJavaScanner(); - if (javaPsiScanner != null) { - javaPsiScanner.visitReference(mContext, v.getVisitor(), - element, referenced); - } - } - } - } - } - } - - super.visitReferenceElement(element); - } - - @Override - public void visitReferenceExpression(PsiReferenceExpression node) { - if (mVisitResources) { - // R.type.name - if (node.getQualifier() instanceof PsiReferenceExpression) { - PsiReferenceExpression select = (PsiReferenceExpression) node.getQualifier(); - if (select.getQualifier() instanceof PsiReferenceExpression) { - PsiReferenceExpression reference = (PsiReferenceExpression) select.getQualifier(); - if (R_CLASS.equals(reference.getReferenceName())) { - String typeName = select.getReferenceName(); - String name = node.getReferenceName(); - - ResourceType type = ResourceType.getEnum(typeName); - if (type != null) { - boolean isFramework = - reference.getQualifier() instanceof PsiReferenceExpression - && ANDROID_PKG.equals(((PsiReferenceExpression)reference. - getQualifier()).getReferenceName()); - - for (VisitingDetector v : mResourceFieldDetectors) { - JavaPsiScanner detector = v.getJavaScanner(); - if (detector != null) { - //noinspection ConstantConditions - detector.visitResourceReference(mContext, v.getVisitor(), - node, type, name, isFramework); - } - } - } - - return; - } - } - } - - // Arbitrary packages -- android.R.type.name, foo.bar.R.type.name - if (R_CLASS.equals(node.getReferenceName())) { - PsiElement parent = node.getParent(); - if (parent instanceof PsiReferenceExpression) { - PsiElement grandParent = parent.getParent(); - if (grandParent instanceof PsiReferenceExpression) { - PsiReferenceExpression select = (PsiReferenceExpression) grandParent; - String name = select.getReferenceName(); - PsiElement typeOperand = select.getQualifier(); - if (name != null && typeOperand instanceof PsiReferenceExpression) { - PsiReferenceExpression typeSelect = - (PsiReferenceExpression) typeOperand; - String typeName = typeSelect.getReferenceName(); - ResourceType type = typeName != null - ? ResourceType.getEnum(typeName) - : null; - if (type != null) { - boolean isFramework = node.getQualifier().getText().equals( - ANDROID_PKG); - for (VisitingDetector v : mResourceFieldDetectors) { - JavaPsiScanner detector = v.getJavaScanner(); - if (detector != null) { - detector.visitResourceReference(mContext, - v.getVisitor(), - node, type, name, isFramework); - } - } - } - - return; - } - } - } - } - } - - super.visitReferenceExpression(node); - } - - @Override - public void visitMethodCallExpression(PsiMethodCallExpression node) { - super.visitMethodCallExpression(node); - - if (mVisitMethods) { - String methodName = node.getMethodExpression().getReferenceName(); - if (methodName != null) { - List list = mMethodDetectors.get(methodName); - if (list != null) { - PsiMethod method = node.resolveMethod(); - if (method != null) { - for (VisitingDetector v : list) { - JavaPsiScanner javaPsiScanner = v.getJavaScanner(); - if (javaPsiScanner != null) { - javaPsiScanner.visitMethod(mContext, v.getVisitor(), node, - method); - } - } - } - } - } - } - } - - @Override - public void visitNewExpression(PsiNewExpression node) { - super.visitNewExpression(node); - - if (mVisitConstructors) { - PsiJavaCodeReferenceElement typeReference = node.getClassReference(); - if (typeReference != null) { - String type = typeReference.getQualifiedName(); - if (type != null) { - List list = mConstructorDetectors.get(type); - if (list != null) { - PsiMethod method = node.resolveMethod(); - if (method != null) { - for (VisitingDetector v : list) { - JavaPsiScanner javaPsiScanner = v.getJavaScanner(); - if (javaPsiScanner != null) { - javaPsiScanner.visitConstructor(mContext, - v.getVisitor(), node, method); - } - } - } - } - } - } - } - } - } -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/JavaVisitor.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/client/api/JavaVisitor.java.173 deleted file mode 100644 index e683aea6c7c..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/JavaVisitor.java.173 +++ /dev/null @@ -1,1400 +0,0 @@ -/* - * Copyright (C) 2011 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.client.api; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.annotations.VisibleForTesting; -import com.android.tools.klint.client.api.JavaParser.ResolvedClass; -import com.android.tools.klint.client.api.JavaParser.ResolvedMethod; -import com.android.tools.klint.client.api.JavaParser.ResolvedNode; -import com.android.tools.klint.detector.api.Detector; -import com.android.tools.klint.detector.api.Detector.JavaScanner; -import com.android.tools.klint.detector.api.Detector.XmlScanner; -import com.android.tools.klint.detector.api.JavaContext; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import lombok.ast.*; -import org.jetbrains.kotlin.utils.ExceptionUtilsKt; - -import java.util.*; - -import static com.android.SdkConstants.ANDROID_PKG; -import static com.android.SdkConstants.R_CLASS; - -/** - * Specialized visitor for running detectors on a Java AST. - * It operates in three phases: - *
    - *
  1. First, it computes a set of maps where it generates a map from each - * significant AST attribute (such as method call names) to a list - * of detectors to consult whenever that attribute is encountered. - * Examples of "attributes" are method names, Android resource identifiers, - * and general AST node types such as "cast" nodes etc. These are - * defined on the {@link JavaScanner} interface. - *
  2. Second, it iterates over the document a single time, delegating to - * the detectors found at each relevant AST attribute. - *
  3. Finally, it calls the remaining visitors (those that need to process a - * whole document on their own). - *
- * It also notifies all the detectors before and after the document is processed - * such that they can do pre- and post-processing. - */ -public class JavaVisitor { - /** Default size of lists holding detectors of the same type for a given node type */ - private static final int SAME_TYPE_COUNT = 8; - - private final Map> mMethodDetectors = - Maps.newHashMapWithExpectedSize(40); - private final Map> mConstructorDetectors = - Maps.newHashMapWithExpectedSize(12); - private Set mConstructorSimpleNames; - private final List mResourceFieldDetectors = - new ArrayList(); - private final List mAllDetectors; - private final List mFullTreeDetectors; - private final Map, List> mNodeTypeDetectors = - new HashMap, List>(16); - private final JavaParser mParser; - private final Map> mSuperClassDetectors = - new HashMap>(); - - /** - * Number of fatal exceptions (internal errors, usually from ECJ) we've - * encountered; we don't log each and every one to avoid massive log spam - * in code which triggers this condition - */ - private static int sExceptionCount; - /** Max number of logs to include */ - private static final int MAX_REPORTED_CRASHES = 20; - - JavaVisitor(@NonNull JavaParser parser, @NonNull List detectors) { - mParser = parser; - mAllDetectors = new ArrayList(detectors.size()); - mFullTreeDetectors = new ArrayList(detectors.size()); - - for (Detector detector : detectors) { - VisitingDetector v = new VisitingDetector(detector, (JavaScanner) detector); - mAllDetectors.add(v); - - List applicableSuperClasses = detector.applicableSuperClasses(); - if (applicableSuperClasses != null) { - for (String fqn : applicableSuperClasses) { - List list = mSuperClassDetectors.get(fqn); - if (list == null) { - list = new ArrayList(SAME_TYPE_COUNT); - mSuperClassDetectors.put(fqn, list); - } - list.add(v); - } - continue; - } - - List> nodeTypes = detector.getApplicableNodeTypes(); - if (nodeTypes != null) { - for (Class type : nodeTypes) { - List list = mNodeTypeDetectors.get(type); - if (list == null) { - list = new ArrayList(SAME_TYPE_COUNT); - mNodeTypeDetectors.put(type, list); - } - list.add(v); - } - } - - List names = detector.getApplicableMethodNames(); - if (names != null) { - // not supported in Java visitors; adding a method invocation node is trivial - // for that case. - assert names != XmlScanner.ALL; - - for (String name : names) { - List list = mMethodDetectors.get(name); - if (list == null) { - list = new ArrayList(SAME_TYPE_COUNT); - mMethodDetectors.put(name, list); - } - list.add(v); - } - } - - List types = detector.getApplicableConstructorTypes(); - if (types != null) { - // not supported in Java visitors; adding a method invocation node is trivial - // for that case. - assert types != XmlScanner.ALL; - if (mConstructorSimpleNames == null) { - mConstructorSimpleNames = Sets.newHashSet(); - } - for (String type : types) { - List list = mConstructorDetectors.get(type); - if (list == null) { - list = new ArrayList(SAME_TYPE_COUNT); - mConstructorDetectors.put(type, list); - mConstructorSimpleNames.add(type.substring(type.lastIndexOf('.')+1)); - } - list.add(v); - } - } - - if (detector.appliesToResourceRefs()) { - mResourceFieldDetectors.add(v); - } else if ((names == null || names.isEmpty()) - && (nodeTypes == null || nodeTypes.isEmpty()) - && (types == null || types.isEmpty())) { - mFullTreeDetectors.add(v); - } - } - } - - void visitFile(@NonNull JavaContext context) { - Node compilationUnit = null; - try { - compilationUnit = mParser.parseJava(context); - if (compilationUnit == null) { - // No need to log this; the parser should be reporting - // a full warning (such as IssueRegistry#PARSER_ERROR) - // with details, location, etc. - return; - } - context.setCompilationUnit(compilationUnit); - - for (VisitingDetector v : mAllDetectors) { - v.setContext(context); - v.getDetector().beforeCheckFile(context); - } - - if (!mSuperClassDetectors.isEmpty()) { - SuperclassVisitor visitor = new SuperclassVisitor(context); - compilationUnit.accept(visitor); - } - - for (VisitingDetector v : mFullTreeDetectors) { - AstVisitor visitor = v.getVisitor(); - compilationUnit.accept(visitor); - } - - if (!mMethodDetectors.isEmpty() || !mResourceFieldDetectors.isEmpty() || - !mConstructorDetectors.isEmpty()) { - AstVisitor visitor = new DelegatingJavaVisitor(context); - compilationUnit.accept(visitor); - } else if (!mNodeTypeDetectors.isEmpty()) { - AstVisitor visitor = new DispatchVisitor(); - compilationUnit.accept(visitor); - } - - for (VisitingDetector v : mAllDetectors) { - v.getDetector().afterCheckFile(context); - } - } catch (RuntimeException e) { - if (sExceptionCount++ > MAX_REPORTED_CRASHES) { - // No need to keep spamming the user that a lot of the files - // are tripping up ECJ, they get the picture. - return; - } - - if (e.getClass().getSimpleName().equals("IndexNotReadyException")) { - // Attempting to access PSI during startup before indices are ready; ignore these. - // See http://b.android.com/176644 for an example. - return; - } else if (ExceptionUtilsKt.isProcessCanceledException(e)) { - // Cancelling inspections in the IDE - context.getDriver().cancel(); - return; - } - - // Work around ECJ bugs; see https://code.google.com/p/android/issues/detail?id=172268 - // Don't allow lint bugs to take down the whole build. TRY to log this as a - // lint error instead! - StringBuilder sb = new StringBuilder(100); - sb.append("Unexpected failure during lint analysis of "); - sb.append(context.file.getName()); - sb.append(" (this is a bug in lint or one of the libraries it depends on)\n"); - - sb.append(e.getClass().getSimpleName()); - sb.append(':'); - StackTraceElement[] stackTrace = e.getStackTrace(); - int count = 0; - for (StackTraceElement frame : stackTrace) { - if (count > 0) { - sb.append("<-"); - } - - String className = frame.getClassName(); - sb.append(className.substring(className.lastIndexOf('.') + 1)); - sb.append('.').append(frame.getMethodName()); - sb.append('('); - sb.append(frame.getFileName()).append(':').append(frame.getLineNumber()); - sb.append(')'); - count++; - // Only print the top 3-4 frames such that we can identify the bug - if (count == 4) { - break; - } - } - Throwable throwable = null; // NOT e: this makes for very noisy logs - //noinspection ConstantConditions - context.log(throwable, sb.toString()); - } finally { - if (compilationUnit != null) { - mParser.dispose(context, compilationUnit); - } - } - } - - /** - * For testing only: returns the number of exceptions thrown during Java AST analysis - * - * @return the number of internal errors found - */ - @VisibleForTesting - public static int getCrashCount() { - return sExceptionCount; - } - - /** - * For testing only: clears the crash counter - */ - @VisibleForTesting - public static void clearCrashCount() { - sExceptionCount = 0; - } - - public void prepare(@NonNull List contexts) { - mParser.prepareJavaParse(contexts); - } - - public void dispose() { - mParser.dispose(); - } - - @Nullable - private static Set getInterfaceNames( - @Nullable Set addTo, - @NonNull ResolvedClass cls) { - Iterable interfaces = cls.getInterfaces(); - for (ResolvedClass resolvedInterface : interfaces) { - String name = resolvedInterface.getName(); - if (addTo == null) { - addTo = Sets.newHashSet(); - } else if (addTo.contains(name)) { - // Superclasses can explicitly implement the same interface, - // so keep track of visited interfaces as we traverse up the - // super class chain to avoid checking the same interface - // more than once. - continue; - } - addTo.add(name); - getInterfaceNames(addTo, resolvedInterface); - } - - return addTo; - } - - private static class VisitingDetector { - private AstVisitor mVisitor; // construct lazily, and clear out on context switch! - private JavaContext mContext; - public final Detector mDetector; - public final JavaScanner mJavaScanner; - - public VisitingDetector(@NonNull Detector detector, @NonNull JavaScanner javaScanner) { - mDetector = detector; - mJavaScanner = javaScanner; - } - - @NonNull - public Detector getDetector() { - return mDetector; - } - - @NonNull - public JavaScanner getJavaScanner() { - return mJavaScanner; - } - - public void setContext(@NonNull JavaContext context) { - mContext = context; - - // The visitors are one-per-context, so clear them out here and construct - // lazily only if needed - mVisitor = null; - } - - @NonNull - AstVisitor getVisitor() { - if (mVisitor == null) { - mVisitor = mDetector.createJavaVisitor(mContext); - if (mVisitor == null) { - mVisitor = new ForwardingAstVisitor() { - }; - } - } - return mVisitor; - } - } - - private class SuperclassVisitor extends ForwardingAstVisitor { - private JavaContext mContext; - - public SuperclassVisitor(@NonNull JavaContext context) { - mContext = context; - } - - @Override - public boolean visitClassDeclaration(ClassDeclaration node) { - ResolvedNode resolved = mContext.resolve(node); - if (!(resolved instanceof ResolvedClass)) { - return true; - } - - ResolvedClass resolvedClass = (ResolvedClass) resolved; - ResolvedClass cls = resolvedClass; - int depth = 0; - while (cls != null) { - List list = mSuperClassDetectors.get(cls.getName()); - if (list != null) { - for (VisitingDetector v : list) { - v.getJavaScanner().checkClass(mContext, node, node, resolvedClass); - } - } - - // Check interfaces too - Set interfaceNames = getInterfaceNames(null, cls); - if (interfaceNames != null) { - for (String name : interfaceNames) { - list = mSuperClassDetectors.get(name); - if (list != null) { - for (VisitingDetector v : list) { - v.getJavaScanner().checkClass(mContext, node, node, - resolvedClass); - } - } - } - } - - cls = cls.getSuperClass(); - depth++; - if (depth == 500) { - // Shouldn't happen in practice; this prevents the IDE from - // hanging if the user has accidentally typed in an incorrect - // super class which creates a cycle. - break; - } - } - - return false; - } - - @Override - public boolean visitConstructorInvocation(ConstructorInvocation node) { - NormalTypeBody anonymous = node.astAnonymousClassBody(); - if (anonymous != null) { - ResolvedNode resolved = mContext.resolve(node.astTypeReference()); - if (!(resolved instanceof ResolvedClass)) { - return true; - } - - ResolvedClass resolvedClass = (ResolvedClass) resolved; - ResolvedClass cls = resolvedClass; - while (cls != null) { - List list = mSuperClassDetectors.get(cls.getName()); - if (list != null) { - for (VisitingDetector v : list) { - v.getJavaScanner().checkClass(mContext, null, anonymous, - resolvedClass); - } - } - - // Check interfaces too - Set interfaceNames = getInterfaceNames(null, cls); - if (interfaceNames != null) { - for (String name : interfaceNames) { - list = mSuperClassDetectors.get(name); - if (list != null) { - for (VisitingDetector v : list) { - v.getJavaScanner().checkClass(mContext, null, anonymous, - resolvedClass); - } - } - } - } - - cls = cls.getSuperClass(); - } - } - - return true; - } - - @Override - public boolean visitImportDeclaration(ImportDeclaration node) { - return true; - } - } - - /** - * Generic dispatcher which visits all nodes (once) and dispatches to - * specific visitors for each node. Each visitor typically only wants to - * look at a small part of a tree, such as a method call or a class - * declaration, so this means we avoid visiting all "uninteresting" nodes in - * the tree repeatedly. - */ - private class DispatchVisitor extends ForwardingAstVisitor { - @Override - public void endVisit(Node node) { - for (VisitingDetector v : mAllDetectors) { - v.getVisitor().endVisit(node); - } - } - - @Override - public boolean visitAlternateConstructorInvocation(AlternateConstructorInvocation node) { - List list = - mNodeTypeDetectors.get(AlternateConstructorInvocation.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitAlternateConstructorInvocation(node); - } - } - return false; - } - - @Override - public boolean visitAnnotation(Annotation node) { - List list = mNodeTypeDetectors.get(Annotation.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitAnnotation(node); - } - } - return false; - } - - @Override - public boolean visitAnnotationDeclaration(AnnotationDeclaration node) { - List list = mNodeTypeDetectors.get(AnnotationDeclaration.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitAnnotationDeclaration(node); - } - } - return false; - } - - @Override - public boolean visitAnnotationElement(AnnotationElement node) { - List list = mNodeTypeDetectors.get(AnnotationElement.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitAnnotationElement(node); - } - } - return false; - } - - @Override - public boolean visitAnnotationMethodDeclaration(AnnotationMethodDeclaration node) { - List list = - mNodeTypeDetectors.get(AnnotationMethodDeclaration.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitAnnotationMethodDeclaration(node); - } - } - return false; - } - - @Override - public boolean visitAnnotationValueArray(AnnotationValueArray node) { - List list = mNodeTypeDetectors.get(AnnotationValueArray.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitAnnotationValueArray(node); - } - } - return false; - } - - @Override - public boolean visitArrayAccess(ArrayAccess node) { - List list = mNodeTypeDetectors.get(ArrayAccess.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitArrayAccess(node); - } - } - return false; - } - - @Override - public boolean visitArrayCreation(ArrayCreation node) { - List list = mNodeTypeDetectors.get(ArrayCreation.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitArrayCreation(node); - } - } - return false; - } - - @Override - public boolean visitArrayDimension(ArrayDimension node) { - List list = mNodeTypeDetectors.get(ArrayDimension.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitArrayDimension(node); - } - } - return false; - } - - @Override - public boolean visitArrayInitializer(ArrayInitializer node) { - List list = mNodeTypeDetectors.get(ArrayInitializer.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitArrayInitializer(node); - } - } - return false; - } - - @Override - public boolean visitAssert(Assert node) { - List list = mNodeTypeDetectors.get(Assert.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitAssert(node); - } - } - return false; - } - - @Override - public boolean visitBinaryExpression(BinaryExpression node) { - List list = mNodeTypeDetectors.get(BinaryExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitBinaryExpression(node); - } - } - return false; - } - - @Override - public boolean visitBlock(Block node) { - List list = mNodeTypeDetectors.get(Block.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitBlock(node); - } - } - return false; - } - - @Override - public boolean visitBooleanLiteral(BooleanLiteral node) { - List list = mNodeTypeDetectors.get(BooleanLiteral.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitBooleanLiteral(node); - } - } - return false; - } - - @Override - public boolean visitBreak(Break node) { - List list = mNodeTypeDetectors.get(Break.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitBreak(node); - } - } - return false; - } - - @Override - public boolean visitCase(Case node) { - List list = mNodeTypeDetectors.get(Case.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitCase(node); - } - } - return false; - } - - @Override - public boolean visitCast(Cast node) { - List list = mNodeTypeDetectors.get(Cast.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitCast(node); - } - } - return false; - } - - @Override - public boolean visitCatch(Catch node) { - List list = mNodeTypeDetectors.get(Catch.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitCatch(node); - } - } - return false; - } - - @Override - public boolean visitCharLiteral(CharLiteral node) { - List list = mNodeTypeDetectors.get(CharLiteral.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitCharLiteral(node); - } - } - return false; - } - - @Override - public boolean visitClassDeclaration(ClassDeclaration node) { - List list = mNodeTypeDetectors.get(ClassDeclaration.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitClassDeclaration(node); - } - } - return false; - } - - @Override - public boolean visitClassLiteral(ClassLiteral node) { - List list = mNodeTypeDetectors.get(ClassLiteral.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitClassLiteral(node); - } - } - return false; - } - - @Override - public boolean visitComment(Comment node) { - List list = mNodeTypeDetectors.get(Comment.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitComment(node); - } - } - return false; - } - - @Override - public boolean visitCompilationUnit(CompilationUnit node) { - List list = mNodeTypeDetectors.get(CompilationUnit.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitCompilationUnit(node); - } - } - return false; - } - - @Override - public boolean visitConstructorDeclaration(ConstructorDeclaration node) { - List list = mNodeTypeDetectors.get(ConstructorDeclaration.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitConstructorDeclaration(node); - } - } - return false; - } - - @Override - public boolean visitConstructorInvocation(ConstructorInvocation node) { - List list = mNodeTypeDetectors.get(ConstructorInvocation.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitConstructorInvocation(node); - } - } - return false; - } - - @Override - public boolean visitContinue(Continue node) { - List list = mNodeTypeDetectors.get(Continue.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitContinue(node); - } - } - return false; - } - - @Override - public boolean visitDefault(Default node) { - List list = mNodeTypeDetectors.get(Default.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitDefault(node); - } - } - return false; - } - - @Override - public boolean visitDoWhile(DoWhile node) { - List list = mNodeTypeDetectors.get(DoWhile.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitDoWhile(node); - } - } - return false; - } - - @Override - public boolean visitEmptyDeclaration(EmptyDeclaration node) { - List list = mNodeTypeDetectors.get(EmptyDeclaration.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitEmptyDeclaration(node); - } - } - return false; - } - - @Override - public boolean visitEmptyStatement(EmptyStatement node) { - List list = mNodeTypeDetectors.get(EmptyStatement.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitEmptyStatement(node); - } - } - return false; - } - - @Override - public boolean visitEnumConstant(EnumConstant node) { - List list = mNodeTypeDetectors.get(EnumConstant.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitEnumConstant(node); - } - } - return false; - } - - @Override - public boolean visitEnumDeclaration(EnumDeclaration node) { - List list = mNodeTypeDetectors.get(EnumDeclaration.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitEnumDeclaration(node); - } - } - return false; - } - - @Override - public boolean visitEnumTypeBody(EnumTypeBody node) { - List list = mNodeTypeDetectors.get(EnumTypeBody.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitEnumTypeBody(node); - } - } - return false; - } - - @Override - public boolean visitExpressionStatement(ExpressionStatement node) { - List list = mNodeTypeDetectors.get(ExpressionStatement.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitExpressionStatement(node); - } - } - return false; - } - - @Override - public boolean visitFloatingPointLiteral(FloatingPointLiteral node) { - List list = mNodeTypeDetectors.get(FloatingPointLiteral.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitFloatingPointLiteral(node); - } - } - return false; - } - - @Override - public boolean visitFor(For node) { - List list = mNodeTypeDetectors.get(For.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitFor(node); - } - } - return false; - } - - @Override - public boolean visitForEach(ForEach node) { - List list = mNodeTypeDetectors.get(ForEach.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitForEach(node); - } - } - return false; - } - - @Override - public boolean visitIdentifier(Identifier node) { - List list = mNodeTypeDetectors.get(Identifier.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitIdentifier(node); - } - } - return false; - } - - @Override - public boolean visitIf(If node) { - List list = mNodeTypeDetectors.get(If.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitIf(node); - } - } - return false; - } - - @Override - public boolean visitImportDeclaration(ImportDeclaration node) { - List list = mNodeTypeDetectors.get(ImportDeclaration.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitImportDeclaration(node); - } - } - return false; - } - - @Override - public boolean visitInlineIfExpression(InlineIfExpression node) { - List list = mNodeTypeDetectors.get(InlineIfExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitInlineIfExpression(node); - } - } - return false; - } - - @Override - public boolean visitInstanceInitializer(InstanceInitializer node) { - List list = mNodeTypeDetectors.get(InstanceInitializer.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitInstanceInitializer(node); - } - } - return false; - } - - @Override - public boolean visitInstanceOf(InstanceOf node) { - List list = mNodeTypeDetectors.get(InstanceOf.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitInstanceOf(node); - } - } - return false; - } - - @Override - public boolean visitIntegralLiteral(IntegralLiteral node) { - List list = mNodeTypeDetectors.get(IntegralLiteral.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitIntegralLiteral(node); - } - } - return false; - } - - @Override - public boolean visitInterfaceDeclaration(InterfaceDeclaration node) { - List list = mNodeTypeDetectors.get(InterfaceDeclaration.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitInterfaceDeclaration(node); - } - } - return false; - } - - @Override - public boolean visitKeywordModifier(KeywordModifier node) { - List list = mNodeTypeDetectors.get(KeywordModifier.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitKeywordModifier(node); - } - } - return false; - } - - @Override - public boolean visitLabelledStatement(LabelledStatement node) { - List list = mNodeTypeDetectors.get(LabelledStatement.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitLabelledStatement(node); - } - } - return false; - } - - @Override - public boolean visitMethodDeclaration(MethodDeclaration node) { - List list = mNodeTypeDetectors.get(MethodDeclaration.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitMethodDeclaration(node); - } - } - return false; - } - - @Override - public boolean visitMethodInvocation(MethodInvocation node) { - List list = mNodeTypeDetectors.get(MethodInvocation.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitMethodInvocation(node); - } - } - return false; - } - - @Override - public boolean visitModifiers(Modifiers node) { - List list = mNodeTypeDetectors.get(Modifiers.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitModifiers(node); - } - } - return false; - } - - @Override - public boolean visitNormalTypeBody(NormalTypeBody node) { - List list = mNodeTypeDetectors.get(NormalTypeBody.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitNormalTypeBody(node); - } - } - return false; - } - - @Override - public boolean visitNullLiteral(NullLiteral node) { - List list = mNodeTypeDetectors.get(NullLiteral.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitNullLiteral(node); - } - } - return false; - } - - @Override - public boolean visitPackageDeclaration(PackageDeclaration node) { - List list = mNodeTypeDetectors.get(PackageDeclaration.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitPackageDeclaration(node); - } - } - return false; - } - - @Override - public boolean visitParseArtefact(Node node) { - List list = mNodeTypeDetectors.get(Node.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitParseArtefact(node); - } - } - return false; - } - - @Override - public boolean visitReturn(Return node) { - List list = mNodeTypeDetectors.get(Return.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitReturn(node); - } - } - return false; - } - - @Override - public boolean visitSelect(Select node) { - List list = mNodeTypeDetectors.get(Select.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitSelect(node); - } - } - return false; - } - - @Override - public boolean visitStaticInitializer(StaticInitializer node) { - List list = mNodeTypeDetectors.get(StaticInitializer.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitStaticInitializer(node); - } - } - return false; - } - - @Override - public boolean visitStringLiteral(StringLiteral node) { - List list = mNodeTypeDetectors.get(StringLiteral.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitStringLiteral(node); - } - } - return false; - } - - @Override - public boolean visitSuper(Super node) { - List list = mNodeTypeDetectors.get(Super.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitSuper(node); - } - } - return false; - } - - @Override - public boolean visitSuperConstructorInvocation(SuperConstructorInvocation node) { - List list = mNodeTypeDetectors.get(SuperConstructorInvocation.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitSuperConstructorInvocation(node); - } - } - return false; - } - - @Override - public boolean visitSwitch(Switch node) { - List list = mNodeTypeDetectors.get(Switch.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitSwitch(node); - } - } - return false; - } - - @Override - public boolean visitSynchronized(Synchronized node) { - List list = mNodeTypeDetectors.get(Synchronized.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitSynchronized(node); - } - } - return false; - } - - @Override - public boolean visitThis(This node) { - List list = mNodeTypeDetectors.get(This.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitThis(node); - } - } - return false; - } - - @Override - public boolean visitThrow(Throw node) { - List list = mNodeTypeDetectors.get(Throw.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitThrow(node); - } - } - return false; - } - - @Override - public boolean visitTry(Try node) { - List list = mNodeTypeDetectors.get(Try.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitTry(node); - } - } - return false; - } - - @Override - public boolean visitTypeReference(TypeReference node) { - List list = mNodeTypeDetectors.get(TypeReference.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitTypeReference(node); - } - } - return false; - } - - @Override - public boolean visitTypeReferencePart(TypeReferencePart node) { - List list = mNodeTypeDetectors.get(TypeReferencePart.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitTypeReferencePart(node); - } - } - return false; - } - - @Override - public boolean visitTypeVariable(TypeVariable node) { - List list = mNodeTypeDetectors.get(TypeVariable.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitTypeVariable(node); - } - } - return false; - } - - @Override - public boolean visitUnaryExpression(UnaryExpression node) { - List list = mNodeTypeDetectors.get(UnaryExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitUnaryExpression(node); - } - } - return false; - } - - @Override - public boolean visitVariableDeclaration(VariableDeclaration node) { - List list = mNodeTypeDetectors.get(VariableDeclaration.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitVariableDeclaration(node); - } - } - return false; - } - - @Override - public boolean visitVariableDefinition(VariableDefinition node) { - List list = mNodeTypeDetectors.get(VariableDefinition.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitVariableDefinition(node); - } - } - return false; - } - - @Override - public boolean visitVariableDefinitionEntry(VariableDefinitionEntry node) { - List list = mNodeTypeDetectors.get(VariableDefinitionEntry.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitVariableDefinitionEntry(node); - } - } - return false; - } - - @Override - public boolean visitVariableReference(VariableReference node) { - List list = mNodeTypeDetectors.get(VariableReference.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitVariableReference(node); - } - } - return false; - } - - @Override - public boolean visitWhile(While node) { - List list = mNodeTypeDetectors.get(While.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitWhile(node); - } - } - return false; - } - } - - /** Performs common AST searches for method calls and R-type-field references. - * Note that this is a specialized form of the {@link DispatchVisitor}. */ - private class DelegatingJavaVisitor extends DispatchVisitor { - private final JavaContext mContext; - private final boolean mVisitResources; - private final boolean mVisitMethods; - private final boolean mVisitConstructors; - - public DelegatingJavaVisitor(JavaContext context) { - mContext = context; - - mVisitMethods = !mMethodDetectors.isEmpty(); - mVisitConstructors = !mConstructorDetectors.isEmpty(); - mVisitResources = !mResourceFieldDetectors.isEmpty(); - } - - @Override - public boolean visitSelect(Select node) { - if (mVisitResources) { - // R.type.name - if (node.astOperand() instanceof Select) { - Select select = (Select) node.astOperand(); - if (select.astOperand() instanceof VariableReference) { - VariableReference reference = (VariableReference) select.astOperand(); - if (reference.astIdentifier().astValue().equals(R_CLASS)) { - String type = select.astIdentifier().astValue(); - String name = node.astIdentifier().astValue(); - - // R -could- be referenced locally and really have been - // imported as "import android.R;" in the import statements, - // but this is not recommended (and in fact there's a specific - // lint rule warning against it) - boolean isFramework = false; - - for (VisitingDetector v : mResourceFieldDetectors) { - JavaScanner detector = v.getJavaScanner(); - //noinspection ConstantConditions - detector.visitResourceReference(mContext, v.getVisitor(), - node, type, name, isFramework); - } - - return super.visitSelect(node); - } - } - } - - // Arbitrary packages -- android.R.type.name, foo.bar.R.type.name - if (node.astIdentifier().astValue().equals(R_CLASS)) { - Node parent = node.getParent(); - if (parent instanceof Select) { - Node grandParent = parent.getParent(); - if (grandParent instanceof Select) { - Select select = (Select) grandParent; - String name = select.astIdentifier().astValue(); - Expression typeOperand = select.astOperand(); - if (typeOperand instanceof Select) { - Select typeSelect = (Select) typeOperand; - String type = typeSelect.astIdentifier().astValue(); - boolean isFramework = node.astOperand().toString().equals( - ANDROID_PKG); - for (VisitingDetector v : mResourceFieldDetectors) { - JavaScanner detector = v.getJavaScanner(); - detector.visitResourceReference(mContext, v.getVisitor(), - node, type, name, isFramework); - } - } - } - } - } - } - - return super.visitSelect(node); - } - - @Override - public boolean visitMethodInvocation(MethodInvocation node) { - if (mVisitMethods) { - String methodName = node.astName().astValue(); - List list = mMethodDetectors.get(methodName); - if (list != null) { - for (VisitingDetector v : list) { - v.getJavaScanner().visitMethod(mContext, v.getVisitor(), node); - } - } - } - - return super.visitMethodInvocation(node); - } - - @Override - public boolean visitConstructorInvocation(ConstructorInvocation node) { - if (mVisitConstructors) { - TypeReference typeReference = node.astTypeReference(); - if (typeReference != null) { - TypeReferencePart last = typeReference.astParts().last(); - if (last != null) { - String name = last.astIdentifier().astValue(); - if (mConstructorSimpleNames.contains(name)) { - ResolvedNode resolved = mContext.resolve(node); - if (resolved instanceof ResolvedMethod) { - ResolvedMethod method = (ResolvedMethod) resolved; - String type = method.getContainingClass().getName(); - List list = mConstructorDetectors.get(type); - if (list != null) { - for (VisitingDetector v : list) { - v.getJavaScanner().visitConstructor(mContext, - v.getVisitor(), node, method); - } - } - - } - } - } - } - } - - return super.visitConstructorInvocation(node); - } - } -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/LintClient.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/client/api/LintClient.java.173 deleted file mode 100644 index 0b3597f97ea..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/LintClient.java.173 +++ /dev/null @@ -1,1255 +0,0 @@ -/* - * Copyright (C) 2011 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.client.api; - -import static com.android.SdkConstants.CLASS_FOLDER; -import static com.android.SdkConstants.DOT_AAR; -import static com.android.SdkConstants.DOT_JAR; -import static com.android.SdkConstants.FD_ASSETS; -import static com.android.SdkConstants.GEN_FOLDER; -import static com.android.SdkConstants.LIBS_FOLDER; -import static com.android.SdkConstants.RES_FOLDER; -import static com.android.SdkConstants.SRC_FOLDER; -import static com.android.tools.klint.detector.api.LintUtils.endsWith; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.builder.model.AndroidArtifact; -import com.android.builder.model.AndroidLibrary; -import com.android.builder.model.Dependencies; -import com.android.builder.model.Variant; -import com.android.ide.common.repository.ResourceVisibilityLookup; -import com.android.ide.common.res2.AbstractResourceRepository; -import com.android.ide.common.res2.ResourceItem; -import com.android.prefs.AndroidLocation; -import com.android.repository.api.ProgressIndicator; -import com.android.repository.api.ProgressIndicatorAdapter; -import com.android.sdklib.BuildToolInfo; -import com.android.sdklib.IAndroidTarget; -import com.android.sdklib.SdkVersionInfo; -import com.android.sdklib.repository.AndroidSdkHandler; -import com.android.tools.klint.detector.api.Context; -import com.android.tools.klint.detector.api.Detector; -import com.android.tools.klint.detector.api.Issue; -import com.android.tools.klint.detector.api.LintUtils; -import com.android.tools.klint.detector.api.Location; -import com.android.tools.klint.detector.api.Project; -import com.android.tools.klint.detector.api.Severity; -import com.android.tools.klint.detector.api.TextFormat; -import com.android.utils.XmlUtils; -import com.google.common.annotations.Beta; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import com.google.common.io.Files; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; - -import java.io.File; -import java.io.IOException; -import java.net.HttpURLConnection; -import java.net.URL; -import java.net.URLClassLoader; -import java.net.URLConnection; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Information about the tool embedding the lint analyzer. IDEs and other tools - * implementing lint support will extend this to integrate logging, displaying errors, - * etc. - *

- * NOTE: This is not a public or final API; if you rely on this be prepared - * to adjust your code for the next tools release. - */ -@Beta -public abstract class LintClient { - private static final String PROP_BIN_DIR = "com.android.tools.lint.bindir"; //$NON-NLS-1$ - - protected LintClient(@NonNull String clientName) { - //noinspection AssignmentToStaticFieldFromInstanceMethod - sClientName = clientName; - } - - protected LintClient() { - //noinspection AssignmentToStaticFieldFromInstanceMethod - sClientName = "unknown"; - } - - /** - * Returns a configuration for use by the given project. The configuration - * provides information about which issues are enabled, any customizations - * to the severity of an issue, etc. - *

- * By default this method returns a {@link DefaultConfiguration}. - * - * @param project the project to obtain a configuration for - * @param driver the current driver, if any - * @return a configuration, never null. - */ - @NonNull - public Configuration getConfiguration(@NonNull Project project, @Nullable LintDriver driver) { - return DefaultConfiguration.create(this, project, null); - } - - /** - * Report the given issue. This method will only be called if the configuration - * provided by {@link #getConfiguration(Project,LintDriver)} has reported the corresponding - * issue as enabled and has not filtered out the issue with its - * {@link Configuration#ignore(Context,Issue,Location,String)} method. - *

- * @param context the context used by the detector when the issue was found - * @param issue the issue that was found - * @param severity the severity of the issue - * @param location the location of the issue - * @param message the associated user message - * @param format the format of the description and location descriptions - */ - public abstract void report( - @NonNull Context context, - @NonNull Issue issue, - @NonNull Severity severity, - @NonNull Location location, - @NonNull String message, - @NonNull TextFormat format); - - /** - * Send an exception or error message (with warning severity) to the log - * - * @param exception the exception, possibly null - * @param format the error message using {@link String#format} syntax, possibly null - * (though in that case the exception should not be null) - * @param args any arguments for the format string - */ - public void log( - @Nullable Throwable exception, - @Nullable String format, - @Nullable Object... args) { - log(Severity.WARNING, exception, format, args); - } - - /** - * Send an exception or error message to the log - * - * @param severity the severity of the warning - * @param exception the exception, possibly null - * @param format the error message using {@link String#format} syntax, possibly null - * (though in that case the exception should not be null) - * @param args any arguments for the format string - */ - public abstract void log( - @NonNull Severity severity, - @Nullable Throwable exception, - @Nullable String format, - @Nullable Object... args); - - /** - * Returns a {@link XmlParser} to use to parse XML - * - * @return a new {@link XmlParser}, or null if this client does not support - * XML analysis - */ - @Nullable - public abstract XmlParser getXmlParser(); - - /** - * Returns a {@link JavaParser} to use to parse Java - * - * @param project the project to parse, if known (this can be used to look up - * the class path for type attribution etc, and it can also be used - * to more efficiently process a set of files, for example to - * perform type attribution for multiple units in a single pass) - * @return a new {@link JavaParser}, or null if this client does not - * support Java analysis - */ - @Nullable - public abstract JavaParser getJavaParser(@Nullable Project project); - - /** - * Returns an optimal detector, if applicable. By default, just returns the - * original detector, but tools can replace detectors using this hook with a version - * that takes advantage of native capabilities of the tool. - * - * @param detectorClass the class of the detector to be replaced - * @return the new detector class, or just the original detector (not null) - */ - @NonNull - public Class replaceDetector( - @NonNull Class detectorClass) { - return detectorClass; - } - - /** - * Reads the given text file and returns the content as a string - * - * @param file the file to read - * @return the string to return, never null (will be empty if there is an - * I/O error) - */ - @NonNull - public abstract String readFile(@NonNull File file); - - /** - * Reads the given binary file and returns the content as a byte array. - * By default this method will read the bytes from the file directly, - * but this can be customized by a client if for example I/O could be - * held in memory and not flushed to disk yet. - * - * @param file the file to read - * @return the bytes in the file, never null - * @throws IOException if the file does not exist, or if the file cannot be - * read for some reason - */ - @NonNull - public byte[] readBytes(@NonNull File file) throws IOException { - return Files.toByteArray(file); - } - - /** - * Returns the list of source folders for Java source files - * - * @param project the project to look up Java source file locations for - * @return a list of source folders to search for .java files - */ - @NonNull - public List getJavaSourceFolders(@NonNull Project project) { - return getClassPath(project).getSourceFolders(); - } - - /** - * Returns the list of output folders for class files - * - * @param project the project to look up class file locations for - * @return a list of output folders to search for .class files - */ - @NonNull - public List getJavaClassFolders(@NonNull Project project) { - return getClassPath(project).getClassFolders(); - - } - - /** - * Returns the list of Java libraries - * - * @param project the project to look up jar dependencies for - * @param includeProvided If true, included provided libraries too (libraries that are not - * packaged with the app, but are provided for compilation purposes and - * are assumed to be present in the running environment) - * @return a list of jar dependencies containing .class files - */ - @NonNull - public List getJavaLibraries(@NonNull Project project, boolean includeProvided) { - return getClassPath(project).getLibraries(includeProvided); - } - - /** - * Returns the list of source folders for test source files - * - * @param project the project to look up test source file locations for - * @return a list of source folders to search for .java files - */ - @NonNull - public List getTestSourceFolders(@NonNull Project project) { - return getClassPath(project).getTestSourceFolders(); - } - - /** - * Returns the resource folders. - * - * @param project the project to look up the resource folder for - * @return a list of files pointing to the resource folders, possibly empty - */ - @NonNull - public List getResourceFolders(@NonNull Project project) { - File res = new File(project.getDir(), RES_FOLDER); - if (res.exists()) { - return Collections.singletonList(res); - } - - return Collections.emptyList(); - } - - /** - * Returns the asset folders. - * - * @param project the project to look up the asset folder for - * @return a list of files pointing to the asset folders, possibly empty - */ - @NonNull - public List getAssetFolders(@NonNull Project project) { - File assets = new File(project.getDir(), FD_ASSETS); - if (assets.exists()) { - return Collections.singletonList(assets); - } - - return Collections.emptyList(); - } - - /** - * Returns the {@link SdkInfo} to use for the given project. - * - * @param project the project to look up an {@link SdkInfo} for - * @return an {@link SdkInfo} for the project - */ - @NonNull - public SdkInfo getSdkInfo(@NonNull Project project) { - // By default no per-platform SDK info - return new DefaultSdkInfo(); - } - - /** - * Returns a suitable location for storing cache files. Note that the - * directory may not exist. - * - * @param create if true, attempt to create the cache dir if it does not - * exist - * @return a suitable location for storing cache files, which may be null if - * the create flag was false, or if for some reason the directory - * could not be created - */ - @Nullable - public File getCacheDir(boolean create) { - String home = System.getProperty("user.home"); - String relative = ".android" + File.separator + "cache"; //$NON-NLS-1$ //$NON-NLS-2$ - File dir = new File(home, relative); - if (create && !dir.exists()) { - if (!dir.mkdirs()) { - return null; - } - } - return dir; - } - - /** - * Returns the File corresponding to the system property or the environment variable - * for {@link #PROP_BIN_DIR}. - * This property is typically set by the SDK/tools/lint[.bat] wrapper. - * It denotes the path of the wrapper on disk. - * - * @return A new File corresponding to {@link LintClient#PROP_BIN_DIR} or null. - */ - @Nullable - private static File getLintBinDir() { - // First check the Java properties (e.g. set using "java -jar ... -Dname=value") - String path = System.getProperty(PROP_BIN_DIR); - if (path == null || path.isEmpty()) { - // If not found, check environment variables. - path = System.getenv(PROP_BIN_DIR); - } - if (path != null && !path.isEmpty()) { - File file = new File(path); - if (file.exists()) { - return file; - } - } - return null; - } - - /** - * Returns the File pointing to the user's SDK install area. This is generally - * the root directory containing the lint tool (but also platforms/ etc). - * - * @return a file pointing to the user's install area - */ - @Nullable - public File getSdkHome() { - File binDir = getLintBinDir(); - if (binDir != null) { - assert binDir.getName().equals("tools"); - - File root = binDir.getParentFile(); - if (root != null && root.isDirectory()) { - return root; - } - } - - String home = System.getenv("ANDROID_HOME"); //$NON-NLS-1$ - if (home != null) { - return new File(home); - } - - return null; - } - - /** - * Locates an SDK resource (relative to the SDK root directory). - *

- * TODO: Consider switching to a {@link URL} return type instead. - * - * @param relativePath A relative path (using {@link File#separator} to - * separate path components) to the given resource - * @return a {@link File} pointing to the resource, or null if it does not - * exist - */ - @Nullable - public File findResource(@NonNull String relativePath) { - File top = getSdkHome(); - if (top == null) { - throw new IllegalArgumentException("Lint must be invoked with the System property " - + PROP_BIN_DIR + " pointing to the ANDROID_SDK tools directory"); - } - - File file = new File(top, relativePath); - if (file.exists()) { - return file; - } else { - return null; - } - } - - private Map mProjectInfo; - - /** - * Returns true if this project is a Gradle-based Android project - * - * @param project the project to check - * @return true if this is a Gradle-based project - */ - public boolean isGradleProject(Project project) { - // This is not an accurate test; specific LintClient implementations (e.g. - // IDEs or a gradle-integration of lint) have more context and can perform a more accurate - // check - if (new File(project.getDir(), SdkConstants.FN_BUILD_GRADLE).exists()) { - return true; - } - - File parent = project.getDir().getParentFile(); - if (parent != null && parent.getName().equals(SdkConstants.FD_SOURCES)) { - File root = parent.getParentFile(); - if (root != null && new File(root, SdkConstants.FN_BUILD_GRADLE).exists()) { - return true; - } - } - - return false; - } - - /** - * Information about class paths (sources, class files and libraries) - * usually associated with a project. - */ - protected static class ClassPathInfo { - private final List mClassFolders; - private final List mSourceFolders; - private final List mLibraries; - private final List mNonProvidedLibraries; - private final List mTestFolders; - - public ClassPathInfo( - @NonNull List sourceFolders, - @NonNull List classFolders, - @NonNull List libraries, - @NonNull List nonProvidedLibraries, - @NonNull List testFolders) { - mSourceFolders = sourceFolders; - mClassFolders = classFolders; - mLibraries = libraries; - mNonProvidedLibraries = nonProvidedLibraries; - mTestFolders = testFolders; - } - - @NonNull - public List getSourceFolders() { - return mSourceFolders; - } - - @NonNull - public List getClassFolders() { - return mClassFolders; - } - - @NonNull - public List getLibraries(boolean includeProvided) { - return includeProvided ? mLibraries : mNonProvidedLibraries; - } - - public List getTestSourceFolders() { - return mTestFolders; - } - } - - /** - * Considers the given project as an Eclipse project and returns class path - * information for the project - the source folder(s), the output folder and - * any libraries. - *

- * Callers will not cache calls to this method, so if it's expensive to compute - * the classpath info, this method should perform its own caching. - * - * @param project the project to look up class path info for - * @return a class path info object, never null - */ - @NonNull - protected ClassPathInfo getClassPath(@NonNull Project project) { - ClassPathInfo info; - if (mProjectInfo == null) { - mProjectInfo = Maps.newHashMap(); - info = null; - } else { - info = mProjectInfo.get(project); - } - - if (info == null) { - List sources = new ArrayList(2); - List classes = new ArrayList(1); - List libraries = new ArrayList(); - // No test folders in Eclipse: - // https://bugs.eclipse.org/bugs/show_bug.cgi?id=224708 - List tests = Collections.emptyList(); - - File projectDir = project.getDir(); - File classpathFile = new File(projectDir, ".classpath"); //$NON-NLS-1$ - if (classpathFile.exists()) { - String classpathXml = readFile(classpathFile); - try { - Document document = XmlUtils.parseDocument(classpathXml, false); - NodeList tags = document.getElementsByTagName("classpathentry"); //$NON-NLS-1$ - for (int i = 0, n = tags.getLength(); i < n; i++) { - Element element = (Element) tags.item(i); - String kind = element.getAttribute("kind"); //$NON-NLS-1$ - List addTo = null; - if (kind.equals("src")) { //$NON-NLS-1$ - addTo = sources; - } else if (kind.equals("output")) { //$NON-NLS-1$ - addTo = classes; - } else if (kind.equals("lib")) { //$NON-NLS-1$ - addTo = libraries; - } - if (addTo != null) { - String path = element.getAttribute("path"); //$NON-NLS-1$ - File folder = new File(projectDir, path); - if (folder.exists()) { - addTo.add(folder); - } - } - } - } catch (Exception e) { - log(null, null); - } - } - - // Add in libraries that aren't specified in the .classpath file - File libs = new File(project.getDir(), LIBS_FOLDER); - if (libs.isDirectory()) { - File[] jars = libs.listFiles(); - if (jars != null) { - for (File jar : jars) { - if (endsWith(jar.getPath(), DOT_JAR) - && !libraries.contains(jar)) { - libraries.add(jar); - } - } - } - } - - if (classes.isEmpty()) { - File folder = new File(projectDir, CLASS_FOLDER); - if (folder.exists()) { - classes.add(folder); - } else { - // Maven checks - folder = new File(projectDir, - "target" + File.separator + "classes"); //$NON-NLS-1$ //$NON-NLS-2$ - if (folder.exists()) { - classes.add(folder); - - // If it's maven, also correct the source path, "src" works but - // it's in a more specific subfolder - if (sources.isEmpty()) { - File src = new File(projectDir, - "src" + File.separator //$NON-NLS-1$ - + "main" + File.separator //$NON-NLS-1$ - + "java"); //$NON-NLS-1$ - if (src.exists()) { - sources.add(src); - } else { - src = new File(projectDir, SRC_FOLDER); - if (src.exists()) { - sources.add(src); - } - } - - File gen = new File(projectDir, - "target" + File.separator //$NON-NLS-1$ - + "generated-sources" + File.separator //$NON-NLS-1$ - + "r"); //$NON-NLS-1$ - if (gen.exists()) { - sources.add(gen); - } - } - } - } - } - - // Fallback, in case there is no Eclipse project metadata here - if (sources.isEmpty()) { - File src = new File(projectDir, SRC_FOLDER); - if (src.exists()) { - sources.add(src); - } - File gen = new File(projectDir, GEN_FOLDER); - if (gen.exists()) { - sources.add(gen); - } - } - - info = new ClassPathInfo(sources, classes, libraries, libraries, tests); - mProjectInfo.put(project, info); - } - - return info; - } - - /** - * A map from directory to existing projects, or null. Used to ensure that - * projects are unique for a directory (in case we process a library project - * before its including project for example) - */ - protected Map mDirToProject; - - /** - * Returns a project for the given directory. This should return the same - * project for the same directory if called repeatedly. - * - * @param dir the directory containing the project - * @param referenceDir See {@link Project#getReferenceDir()}. - * @return a project, never null - */ - @NonNull - public Project getProject(@NonNull File dir, @NonNull File referenceDir) { - if (mDirToProject == null) { - mDirToProject = new HashMap(); - } - - File canonicalDir = dir; - try { - // Attempt to use the canonical handle for the file, in case there - // are symlinks etc present (since when handling library projects, - // we also call getCanonicalFile to compute the result of appending - // relative paths, which can then resolve symlinks and end up with - // a different prefix) - canonicalDir = dir.getCanonicalFile(); - } catch (IOException ioe) { - // pass - } - - Project project = mDirToProject.get(canonicalDir); - if (project != null) { - return project; - } - - project = createProject(dir, referenceDir); - mDirToProject.put(canonicalDir, project); - return project; - } - - /** - * Returns the list of known projects (projects registered via - * {@link #getProject(File, File)} - * - * @return a collection of projects in any order - */ - public Collection getKnownProjects() { - return mDirToProject != null ? mDirToProject.values() : Collections.emptyList(); - } - - /** - * Registers the given project for the given directory. This can - * be used when projects are initialized outside of the client itself. - * - * @param dir the directory of the project, which must be unique - * @param project the project - */ - public void registerProject(@NonNull File dir, @NonNull Project project) { - File canonicalDir = dir; - try { - // Attempt to use the canonical handle for the file, in case there - // are symlinks etc present (since when handling library projects, - // we also call getCanonicalFile to compute the result of appending - // relative paths, which can then resolve symlinks and end up with - // a different prefix) - canonicalDir = dir.getCanonicalFile(); - } catch (IOException ioe) { - // pass - } - - - if (mDirToProject == null) { - mDirToProject = new HashMap(); - } else { - assert !mDirToProject.containsKey(dir) : dir; - } - mDirToProject.put(canonicalDir, project); - } - - protected Set mProjectDirs = Sets.newHashSet(); - - /** - * Create a project for the given directory - * @param dir the root directory of the project - * @param referenceDir See {@link Project#getReferenceDir()}. - * @return a new project - */ - @NonNull - protected Project createProject(@NonNull File dir, @NonNull File referenceDir) { - if (mProjectDirs.contains(dir)) { - throw new CircularDependencyException( - "Circular library dependencies; check your project.properties files carefully"); - } - mProjectDirs.add(dir); - return Project.create(this, dir, referenceDir); - } - - /** - * Returns the name of the given project - * - * @param project the project to look up - * @return the name of the project - */ - @NonNull - public String getProjectName(@NonNull Project project) { - return project.getDir().getName(); - } - - protected IAndroidTarget[] mTargets; - - /** - * Returns all the {@link IAndroidTarget} versions installed in the user's SDK install - * area. - * - * @return all the installed targets - */ - @NonNull - public IAndroidTarget[] getTargets() { - if (mTargets == null) { - AndroidSdkHandler sdkHandler = getSdk(); - if (sdkHandler != null) { - ProgressIndicator logger = getRepositoryLogger(); - Collection targets = sdkHandler.getAndroidTargetManager(logger) - .getTargets(logger); - mTargets = targets.toArray(new IAndroidTarget[targets.size()]); - } else { - mTargets = new IAndroidTarget[0]; - } - } - - return mTargets; - } - - protected AndroidSdkHandler mSdk; - - /** - * Returns the SDK installation (used to look up platforms etc) - * - * @return the SDK if known - */ - @Nullable - public AndroidSdkHandler getSdk() { - if (mSdk == null) { - File sdkHome = getSdkHome(); - if (sdkHome != null) { - mSdk = AndroidSdkHandler.getInstance(sdkHome); - } - } - - return mSdk; - } - - /** - * Returns the compile target to use for the given project - * - * @param project the project in question - * - * @return the compile target to use to build the given project - */ - @Nullable - public IAndroidTarget getCompileTarget(@NonNull Project project) { - int buildSdk = project.getBuildSdk(); - IAndroidTarget[] targets = getTargets(); - for (int i = targets.length - 1; i >= 0; i--) { - IAndroidTarget target = targets[i]; - if (target.isPlatform() && target.getVersion().getApiLevel() == buildSdk) { - return target; - } - } - - return null; - } - - /** - * Returns the highest known API level. - * - * @return the highest known API level - */ - public int getHighestKnownApiLevel() { - int max = SdkVersionInfo.HIGHEST_KNOWN_STABLE_API; - - for (IAndroidTarget target : getTargets()) { - if (target.isPlatform()) { - int api = target.getVersion().getApiLevel(); - if (api > max && !target.getVersion().isPreview()) { - max = api; - } - } - } - - return max; - } - - /** - * Returns the specific version of the build tools being used for the given project, if known - * - * @param project the project in question - * - * @return the build tools version in use by the project, or null if not known - */ - @Nullable - public BuildToolInfo getBuildTools(@NonNull Project project) { - //TODO - //AndroidSdkHandler sdk = getSdk(); - //// Build systems like Eclipse and ant just use the latest available - //// build tools, regardless of project metadata. In Gradle, this - //// method is overridden to use the actual build tools specified in the - //// project. - //if (sdk != null) { - // IAndroidTarget compileTarget = getCompileTarget(project); - // if (compileTarget != null) { - // return compileTarget.getBuildToolInfo(); - // } - // return sdk.getLatestBuildTool(getRepositoryLogger(), false); - //} - - return null; - } - - /** - * Returns the super class for the given class name, which should be in VM - * format (e.g. java/lang/Integer, not java.lang.Integer, and using $ rather - * than . for inner classes). If the super class is not known, returns null. - *

- * This is typically not necessary, since lint analyzes all the available - * classes. However, if this lint client is invoking lint in an incremental - * context (for example, an IDE offering incremental analysis of a single - * source file), then lint may not see all the classes, and the client can - * provide its own super class lookup. - * - * @param project the project containing the class - * @param name the fully qualified class name - * @return the corresponding super class name (in VM format), or null if not - * known - */ - @Nullable - public String getSuperClass(@NonNull Project project, @NonNull String name) { - assert name.indexOf('.') == -1 : "Use VM signatures, e.g. java/lang/Integer"; - - if ("java/lang/Object".equals(name)) { //$NON-NLS-1$ - return null; - } - - String superClass = project.getSuperClassMap().get(name); - if (superClass != null) { - return superClass; - } - - for (Project library : project.getAllLibraries()) { - superClass = library.getSuperClassMap().get(name); - if (superClass != null) { - return superClass; - } - } - - return null; - } - - /** - * Creates a super class map for the given project. The map maps from - * internal class name (e.g. java/lang/Integer, not java.lang.Integer) to its - * corresponding super class name. The root class, java/lang/Object, is not in the map. - * - * @param project the project to initialize the super class with; this will include - * local classes as well as any local .jar libraries; not transitive - * dependencies - * @return a map from class to its corresponding super class; never null - */ - @NonNull - public Map createSuperClassMap(@NonNull Project project) { - List libraries = project.getJavaLibraries(true); - List classFolders = project.getJavaClassFolders(); - List classEntries = ClassEntry.fromClassPath(this, classFolders, true); - if (libraries.isEmpty()) { - return ClassEntry.createSuperClassMap(this, classEntries); - } - List libraryEntries = ClassEntry.fromClassPath(this, libraries, true); - return ClassEntry.createSuperClassMap(this, libraryEntries, classEntries); - } - - /** - * Checks whether the given name is a subclass of the given super class. If - * the method does not know, it should return null, and otherwise return - * {@link Boolean#TRUE} or {@link Boolean#FALSE}. - *

- * Note that the class names are in internal VM format (java/lang/Integer, - * not java.lang.Integer, and using $ rather than . for inner classes). - * - * @param project the project context to look up the class in - * @param name the name of the class to be checked - * @param superClassName the name of the super class to compare to - * @return true if the class of the given name extends the given super class - */ - @SuppressWarnings("NonBooleanMethodNameMayNotStartWithQuestion") - @Nullable - public Boolean isSubclassOf( - @NonNull Project project, - @NonNull String name, - @NonNull String superClassName) { - return null; - } - - /** - * Finds any custom lint rule jars that should be included for analysis, - * regardless of project. - *

- * The default implementation locates custom lint jars in ~/.android/lint/ and - * in $ANDROID_LINT_JARS - * - * @return a list of rule jars (possibly empty). - */ - @SuppressWarnings("MethodMayBeStatic") // Intentionally instance method so it can be overridden - @NonNull - public List findGlobalRuleJars() { - // Look for additional detectors registered by the user, via - // (1) an environment variable (useful for build servers etc), and - // (2) via jar files in the .android/lint directory - List files = null; - try { - String androidHome = AndroidLocation.getFolder(); - File lint = new File(androidHome + File.separator + "lint"); //$NON-NLS-1$ - if (lint.exists()) { - File[] list = lint.listFiles(); - if (list != null) { - for (File jarFile : list) { - if (endsWith(jarFile.getName(), DOT_JAR)) { - if (files == null) { - files = new ArrayList(); - } - files.add(jarFile); - } - } - } - } - } catch (AndroidLocation.AndroidLocationException e) { - // Ignore -- no android dir, so no rules to load. - } - - String lintClassPath = System.getenv("ANDROID_LINT_JARS"); //$NON-NLS-1$ - if (lintClassPath != null && !lintClassPath.isEmpty()) { - String[] paths = lintClassPath.split(File.pathSeparator); - for (String path : paths) { - File jarFile = new File(path); - if (jarFile.exists()) { - if (files == null) { - files = new ArrayList(); - } else if (files.contains(jarFile)) { - continue; - } - files.add(jarFile); - } - } - } - - return files != null ? files : Collections.emptyList(); - } - - /** - * Finds any custom lint rule jars that should be included for analysis - * in the given project - * - * @param project the project to look up rule jars from - * @return a list of rule jars (possibly empty). - */ - @SuppressWarnings("MethodMayBeStatic") // Intentionally instance method so it can be overridden - @NonNull - public List findRuleJars(@NonNull Project project) { - if (project.isGradleProject()) { - if (project.isLibrary()) { - AndroidLibrary model = project.getGradleLibraryModel(); - if (model != null) { - File lintJar = model.getLintJar(); - if (lintJar.exists()) { - return Collections.singletonList(lintJar); - } - } - } else if (project.getSubset() != null) { - // Probably just analyzing a single file: we still want to look for custom - // rules applicable to the file - List rules = null; - final Variant variant = project.getCurrentVariant(); - if (variant != null) { - Collection libraries = variant.getMainArtifact() - .getDependencies().getLibraries(); - for (AndroidLibrary library : libraries) { - File lintJar = library.getLintJar(); - if (lintJar.exists()) { - if (rules == null) { - rules = Lists.newArrayListWithExpectedSize(4); - } - rules.add(lintJar); - } - } - if (rules != null) { - return rules; - } - } - } else if (project.getDir().getPath().endsWith(DOT_AAR)) { - File lintJar = new File(project.getDir(), "lint.jar"); //$NON-NLS-1$ - if (lintJar.exists()) { - return Collections.singletonList(lintJar); - } - } - } - - return Collections.emptyList(); - } - - /** - * Opens a URL connection. - * - * Clients such as IDEs can override this to for example consider the user's IDE proxy - * settings. - * - * @param url the URL to read - * @return a {@link URLConnection} or null - * @throws IOException if any kind of IO exception occurs - */ - @Nullable - public URLConnection openConnection(@NonNull URL url) throws IOException { - return url.openConnection(); - } - - /** Closes a connection previously returned by {@link #openConnection(URL)} */ - public void closeConnection(@NonNull URLConnection connection) throws IOException { - if (connection instanceof HttpURLConnection) { - ((HttpURLConnection)connection).disconnect(); - } - } - - /** - * Returns true if the given directory is a lint project directory. - * By default, a project directory is the directory containing a manifest file, - * but in Gradle projects for example it's the root gradle directory. - * - * @param dir the directory to check - * @return true if the directory represents a lint project - */ - @SuppressWarnings("MethodMayBeStatic") // Intentionally instance method so it can be overridden - public boolean isProjectDirectory(@NonNull File dir) { - return LintUtils.isManifestFolder(dir) || Project.isAospFrameworksRelatedProject(dir); - } - - /** - * Returns whether lint should look for suppress comments. Tools that already do - * this on their own can return false here to avoid doing unnecessary work. - */ - public boolean checkForSuppressComments() { - return true; - } - - /** - * Adds in any custom lint rules and returns the result as a new issue registry, - * or the same one if no custom rules were found - * - * @param registry the main registry to add rules to - * @return a new registry containing the passed in rules plus any custom rules, - * or the original registry if no custom rules were found - */ - public IssueRegistry addCustomLintRules(@NonNull IssueRegistry registry) { - List jarFiles = findGlobalRuleJars(); - - if (!jarFiles.isEmpty()) { - List registries = Lists.newArrayListWithExpectedSize(jarFiles.size()); - registries.add(registry); - for (File jarFile : jarFiles) { - try { - registries.add(JarFileIssueRegistry.get(this, jarFile)); - } catch (Throwable e) { - log(e, "Could not load custom rule jar file %1$s", jarFile); - } - } - if (registries.size() > 1) { // the first item is the passed in registry itself - return new CompositeIssueRegistry(registries); - } - } - - return registry; - } - - /** - * Creates a {@link ClassLoader} which can load in a set of Jar files. - * - * @param urls the URLs - * @param parent the parent class loader - * @return a new class loader - */ - public ClassLoader createUrlClassLoader(@NonNull URL[] urls, @NonNull ClassLoader parent) { - return new URLClassLoader(urls, parent); - } - - /** - * Returns true if this client supports project resource repository lookup via - * {@link #getProjectResources(Project,boolean)} - * - * @return true if the client can provide project resources - */ - public boolean supportsProjectResources() { - return false; - } - - /** - * Returns the project resources, if available - * - * @param includeDependencies if true, include merged view of all dependencies - * @return the project resources, or null if not available - */ - @Nullable - public AbstractResourceRepository getProjectResources(Project project, - boolean includeDependencies) { - return null; - } - - /** - * For a lint client which supports resource items (via {@link #supportsProjectResources()}) - * return a handle for a resource item - * - * @param item the resource item to look up a location handle for - * @return a corresponding handle - */ - @NonNull - public Location.Handle createResourceItemHandle(@NonNull ResourceItem item) { - return new Location.ResourceItemHandle(item); - } - - private ResourceVisibilityLookup.Provider mResourceVisibility; - - /** - * Returns a shared {@link ResourceVisibilityLookup.Provider} - * - * @return a shared provider for looking up resource visibility - */ - @NonNull - public ResourceVisibilityLookup.Provider getResourceVisibilityProvider() { - if (mResourceVisibility == null) { - mResourceVisibility = new ResourceVisibilityLookup.Provider(); - } - return mResourceVisibility; - } - - /** - * The client name returned by {@link #getClientName()} when running in - * Android Studio/IntelliJ IDEA - */ - public static final String CLIENT_STUDIO = "studio"; - - /** - * The client name returned by {@link #getClientName()} when running in - * Gradle - */ - public static final String CLIENT_GRADLE = "gradle"; - - /** - * The client name returned by {@link #getClientName()} when running in - * the CLI (command line interface) version of lint, {@code lint} - */ - public static final String CLIENT_CLI = "cli"; - - /** - * The client name returned by {@link #getClientName()} when running in - * some unknown client - */ - public static final String CLIENT_UNKNOWN = "unknown"; - - /** The client name. */ - @NonNull - private static String sClientName = CLIENT_UNKNOWN; - - /** - * Returns the name of the embedding client. It could be not just - * {@link #CLIENT_STUDIO}, {@link #CLIENT_GRADLE}, {@link #CLIENT_CLI} - * etc but other values too as lint is integrated in other embedding contexts. - * - * @return the name of the embedding client - */ - @NonNull - public static String getClientName() { - return sClientName; - } - - /** - * Returns true if the embedding client currently running lint is Android Studio - * (or IntelliJ IDEA) - * - * @return true if running in Android Studio / IntelliJ IDEA - */ - public static boolean isStudio() { - return CLIENT_STUDIO.equals(sClientName); - } - - /** - * Returns true if the embedding client currently running lint is Gradle - * - * @return true if running in Gradle - */ - public static boolean isGradle() { - return CLIENT_GRADLE.equals(sClientName); - } - - @NonNull - public ProgressIndicator getRepositoryLogger() { - return new LintClient.RepoLogger(); - } - - private static final class RepoLogger extends ProgressIndicatorAdapter { - // Intentionally not logging these: the SDK manager is - // logging events such as package.xml parsing - // Parsing /path/to/sdk//build-tools/19.1.0/package.xml - // Parsing /path/to/sdk//build-tools/20.0.0/package.xml - // Parsing /path/to/sdk//build-tools/21.0.0/package.xml - // which we don't want to spam on the console. - // It's also warning about packages that it's encountering - // multiple times etc; that's not something we should include - // in lint command line output. - - @Override - public void logError(@NonNull String s, @Nullable Throwable e) { - } - - @Override - public void logInfo(@NonNull String s) { - } - - @Override - public void logWarning(@NonNull String s, @Nullable Throwable e) { - } - } -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/LintDriver.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/client/api/LintDriver.java.173 deleted file mode 100644 index aafa8abf106..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/LintDriver.java.173 +++ /dev/null @@ -1,2906 +0,0 @@ -/* - * Copyright (C) 2011 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.client.api; - -import static com.android.SdkConstants.ATTR_IGNORE; -import static com.android.SdkConstants.CLASS_CONSTRUCTOR; -import static com.android.SdkConstants.CONSTRUCTOR_NAME; -import static com.android.SdkConstants.DOT_CLASS; -import static com.android.SdkConstants.DOT_JAR; -import static com.android.SdkConstants.DOT_JAVA; -import static com.android.SdkConstants.FD_GRADLE_WRAPPER; -import static com.android.SdkConstants.FN_GRADLE_WRAPPER_PROPERTIES; -import static com.android.SdkConstants.FN_LOCAL_PROPERTIES; -import static com.android.SdkConstants.FQCN_SUPPRESS_LINT; -import static com.android.SdkConstants.RES_FOLDER; -import static com.android.SdkConstants.SUPPRESS_ALL; -import static com.android.SdkConstants.SUPPRESS_LINT; -import static com.android.SdkConstants.TOOLS_URI; -import static com.android.ide.common.resources.configuration.FolderConfiguration.QUALIFIER_SPLITTER; -import static com.android.tools.klint.detector.api.LintUtils.isAnonymousClass; -import static java.io.File.separator; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.ide.common.repository.ResourceVisibilityLookup; -import com.android.ide.common.res2.AbstractResourceRepository; -import com.android.ide.common.res2.ResourceItem; -import com.android.resources.ResourceFolderType; -import com.android.sdklib.BuildToolInfo; -import com.android.sdklib.IAndroidTarget; -import com.android.sdklib.repository.AndroidSdkHandler; -import com.android.tools.klint.client.api.LintListener.EventType; -import com.android.tools.klint.detector.api.ClassContext; -import com.android.tools.klint.detector.api.Context; -import com.android.tools.klint.detector.api.Detector; -import com.android.tools.klint.detector.api.Issue; -import com.android.tools.klint.detector.api.JavaContext; -import com.android.tools.klint.detector.api.LintUtils; -import com.android.tools.klint.detector.api.Location; -import com.android.tools.klint.detector.api.Project; -import com.android.tools.klint.detector.api.ResourceContext; -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.TextFormat; -import com.android.tools.klint.detector.api.XmlContext; -import com.google.common.annotations.Beta; -import com.google.common.base.Joiner; -import com.google.common.base.Objects; -import com.google.common.base.Splitter; -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Multimap; -import com.google.common.collect.Sets; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.psi.PsiAnnotation; -import com.intellij.psi.PsiAnnotationMemberValue; -import com.intellij.psi.PsiAnnotationParameterList; -import com.intellij.psi.PsiArrayInitializerExpression; -import com.intellij.psi.PsiArrayInitializerMemberValue; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiExpression; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiLiteral; -import com.intellij.psi.PsiModifierList; -import com.intellij.psi.PsiModifierListOwner; -import com.intellij.psi.PsiNameValuePair; - -import org.jetbrains.uast.*; -import org.jetbrains.org.objectweb.asm.ClassReader; -import org.jetbrains.org.objectweb.asm.Opcodes; -import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode; -import org.jetbrains.org.objectweb.asm.tree.AnnotationNode; -import org.jetbrains.org.objectweb.asm.tree.ClassNode; -import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode; -import org.jetbrains.org.objectweb.asm.tree.FieldNode; -import org.jetbrains.org.objectweb.asm.tree.InsnList; -import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode; -import org.jetbrains.org.objectweb.asm.tree.MethodNode; -import org.jetbrains.uast.util.UastExpressionUtils; -import org.w3c.dom.Attr; -import org.w3c.dom.Element; - -import java.io.File; -import java.io.IOException; -import java.net.URL; -import java.net.URLConnection; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Deque; -import java.util.EnumMap; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.HashSet; -import java.util.IdentityHashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import lombok.ast.Annotation; -import lombok.ast.AnnotationElement; -import lombok.ast.AnnotationMethodDeclaration; -import lombok.ast.AnnotationValue; -import lombok.ast.ArrayInitializer; -import lombok.ast.ConstructorDeclaration; -import lombok.ast.Expression; -import lombok.ast.MethodDeclaration; -import lombok.ast.Modifiers; -import lombok.ast.Node; -import lombok.ast.StrictListAccessor; -import lombok.ast.StringLiteral; -import lombok.ast.TypeDeclaration; -import lombok.ast.TypeReference; -import lombok.ast.VariableDefinition; - -/** - * Analyzes Android projects and files - *

- * NOTE: This is not a public or final API; if you rely on this be prepared - * to adjust your code for the next tools release. - */ -@Beta -public class LintDriver { - /** - * Max number of passes to run through the lint runner if requested by - * {@link #requestRepeat} - */ - private static final int MAX_PHASES = 3; - private static final String SUPPRESS_LINT_VMSIG = '/' + SUPPRESS_LINT + ';'; - /** Prefix used by the comment suppress mechanism in Studio/IntelliJ */ - private static final String STUDIO_ID_PREFIX = "AndroidLint"; - - private final LintClient mClient; - private LintRequest mRequest; - private IssueRegistry mRegistry; - private volatile boolean mCanceled; - private EnumSet mScope; - private List mApplicableDetectors; - private Map> mScopeDetectors; - private List mListeners; - private int mPhase; - private List mRepeatingDetectors; - private EnumSet mRepeatScope; - private Project[] mCurrentProjects; - private Project mCurrentProject; - private boolean mAbbreviating = true; - private boolean mParserErrors; - private Map mProperties; - /** Whether we need to look for legacy (old Lombok-based Java API) detectors */ - private boolean mRunCompatChecks = true; - - /** - * Creates a new {@link LintDriver} - * - * @param registry The registry containing issues to be checked - * @param client the tool wrapping the analyzer, such as an IDE or a CLI - */ - public LintDriver(@NonNull IssueRegistry registry, @NonNull LintClient client) { - mRegistry = registry; - mClient = new LintClientWrapper(client); - } - - /** Cancels the current lint run as soon as possible */ - public void cancel() { - mCanceled = true; - } - - /** - * Returns the scope for the lint job - * - * @return the scope, never null - */ - @NonNull - public EnumSet getScope() { - return mScope; - } - - /** - * Sets the scope for the lint job - * - * @param scope the scope to use - */ - public void setScope(@NonNull EnumSet scope) { - mScope = scope; - } - - /** - * Returns the lint client requesting the lint check. This may not be the same - * instance as the one passed in to this driver; lint uses a wrapper which performs - * additional validation to ensure that for example badly behaved detectors which report - * issues that have been disabled will get muted without the real lint client getting - * notified. Thus, this {@link LintClient} is suitable for use by detectors to look - * up a client to for example get location handles from, but tool handling code should - * never try to cast this client back to their original lint client. For the original - * lint client, use {@link LintRequest} instead. - * - * @return the client, never null - */ - @NonNull - public LintClient getClient() { - return mClient; - } - - /** - * Returns the current request, which points to the original files to be checked, - * the original scope, the original {@link LintClient}, as well as the release mode. - * - * @return the request - */ - @NonNull - public LintRequest getRequest() { - return mRequest; - } - - /** - * Records a property for later retrieval by {@link #getProperty(Object)} - * - * @param key the key to associate the value with - * @param value the value, or null to remove a previous binding - */ - public void putProperty(@NonNull Object key, @Nullable Object value) { - if (mProperties == null) { - mProperties = Maps.newHashMap(); - } - if (value == null) { - mProperties.remove(key); - } else { - mProperties.put(key, value); - } - } - - /** - * Returns the property previously stored with the given key, or null - * - * @param key the key - * @return the value or null if not found - */ - @Nullable - public Object getProperty(@NonNull Object key) { - if (mProperties != null) { - return mProperties.get(key); - } - - return null; - } - - /** - * Returns the current phase number. The first pass is numbered 1. Only one pass - * will be performed, unless a {@link Detector} calls {@link #requestRepeat}. - * - * @return the current phase, usually 1 - */ - public int getPhase() { - return mPhase; - } - - /** - * Returns the current {@link IssueRegistry}. - * - * @return the current {@link IssueRegistry} - */ - @NonNull - public IssueRegistry getRegistry() { - return mRegistry; - } - - /** - * Returns the project containing a given file, or null if not found. This searches - * only among the currently checked project and its library projects, not among all - * possible projects being scanned sequentially. - * - * @param file the file to be checked - * @return the corresponding project, or null if not found - */ - @Nullable - public Project findProjectFor(@NonNull File file) { - if (mCurrentProjects != null) { - if (mCurrentProjects.length == 1) { - return mCurrentProjects[0]; - } - String path = file.getPath(); - for (Project project : mCurrentProjects) { - if (path.startsWith(project.getDir().getPath())) { - return project; - } - } - } - - return null; - } - - /** - * Sets whether lint should abbreviate output when appropriate. - * - * @param abbreviating true to abbreviate output, false to include everything - */ - public void setAbbreviating(boolean abbreviating) { - mAbbreviating = abbreviating; - } - - /** - * Returns whether lint should abbreviate output when appropriate. - * - * @return true if lint should abbreviate output, false when including everything - */ - public boolean isAbbreviating() { - return mAbbreviating; - } - - /** - * Returns whether lint has encountered any files with fatal parser errors - * (e.g. broken source code, or even broken parsers) - *

- * This is useful for checks that need to make sure they've seen all data in - * order to be conclusive (such as an unused resource check). - * - * @return true if any files were not properly processed because they - * contained parser errors - */ - public boolean hasParserErrors() { - return mParserErrors; - } - - /** - * Sets whether lint has encountered files with fatal parser errors. - * - * @see #hasParserErrors() - * @param hasErrors whether parser errors have been encountered - */ - public void setHasParserErrors(boolean hasErrors) { - mParserErrors = hasErrors; - } - - /** - * Returns the projects being analyzed - * - * @return the projects being analyzed - */ - @NonNull - public List getProjects() { - if (mCurrentProjects != null) { - return Arrays.asList(mCurrentProjects); - } - return Collections.emptyList(); - } - - /** - * Analyze the given file (which can point to an Android project). Issues found - * are reported to the associated {@link LintClient}. - * - * @param files the files and directories to be analyzed - * @param scope the scope of the analysis; detectors with a wider scope will - * not be run. If null, the scope will be inferred from the files. - * @deprecated use {@link #analyze(LintRequest) instead} - */ - @Deprecated - public void analyze(@NonNull List files, @Nullable EnumSet scope) { - analyze(new LintRequest(mClient, files).setScope(scope)); - } - - /** - * Analyze the given files (which can point to Android projects or directories - * containing Android projects). Issues found are reported to the associated - * {@link LintClient}. - *

- * Note that the {@link LintDriver} is not multi thread safe or re-entrant; - * if you want to run potentially overlapping lint jobs, create a separate driver - * for each job. - * - * @param request the files and directories to be analyzed - */ - public void analyze(@NonNull LintRequest request) { - try { - mRequest = request; - analyze(); - } finally { - mRequest = null; - } - } - - /** Runs the driver to analyze the requested files */ - private void analyze() { - mCanceled = false; - mScope = mRequest.getScope(); - assert mScope == null || !mScope.contains(Scope.ALL_RESOURCE_FILES) || - mScope.contains(Scope.RESOURCE_FILE); - - Collection projects; - try { - projects = mRequest.getProjects(); - if (projects == null) { - projects = computeProjects(mRequest.getFiles()); - } - } catch (CircularDependencyException e) { - mCurrentProject = e.getProject(); - if (mCurrentProject != null) { - Location location = e.getLocation(); - File file = location != null ? location.getFile() : mCurrentProject.getDir(); - Context context = new Context(this, mCurrentProject, null, file); - context.report(IssueRegistry.LINT_ERROR, e.getLocation(), e.getMessage()); - mCurrentProject = null; - } - return; - } - if (projects.isEmpty()) { - mClient.log(null, "No projects found for %1$s", mRequest.getFiles().toString()); - return; - } - if (mCanceled) { - return; - } - - if (mScope == null) { - mScope = Scope.infer(projects); - } - - fireEvent(EventType.STARTING, null); - - for (Project project : projects) { - mPhase = 1; - - Project main = mRequest.getMainProject(project); - - // The set of available detectors varies between projects - computeDetectors(project); - - if (mApplicableDetectors.isEmpty()) { - // No detectors enabled in this project: skip it - continue; - } - - checkProject(project, main); - if (mCanceled) { - break; - } - - runExtraPhases(project, main); - } - - fireEvent(mCanceled ? EventType.CANCELED : EventType.COMPLETED, null); - } - - @Nullable - private Set myCustomIssues; - - /** - * Returns true if the given issue is an issue that was loaded as a custom rule - * (e.g. a 3rd-party library provided the detector, it's not built in) - * - * @param issue the issue to be looked up - * @return true if this is a custom (non-builtin) check - */ - public boolean isCustomIssue(@NonNull Issue issue) { - return myCustomIssues != null && myCustomIssues.contains(issue); - } - - private void registerCustomDetectors(Collection projects) { - // Look at the various projects, and if any of them provide a custom - // lint jar, "add" them (this will replace the issue registry with - // a CompositeIssueRegistry containing the original issue registry - // plus JarFileIssueRegistry instances for each lint jar - Set jarFiles = Sets.newHashSet(); - for (Project project : projects) { - jarFiles.addAll(mClient.findRuleJars(project)); - for (Project library : project.getAllLibraries()) { - jarFiles.addAll(mClient.findRuleJars(library)); - } - } - - jarFiles.addAll(mClient.findGlobalRuleJars()); - - if (!jarFiles.isEmpty()) { - List registries = Lists.newArrayListWithExpectedSize(jarFiles.size()); - registries.add(mRegistry); - for (File jarFile : jarFiles) { - try { - JarFileIssueRegistry registry = JarFileIssueRegistry.get(mClient, jarFile); - if (registry.hasLegacyDetectors()) { - mRunCompatChecks = true; - } - if (myCustomIssues == null) { - myCustomIssues = Sets.newHashSet(); - } - myCustomIssues.addAll(registry.getIssues()); - registries.add(registry); - } catch (Throwable e) { - mClient.log(e, "Could not load custom rule jar file %1$s", jarFile); - } - } - if (registries.size() > 1) { // the first item is mRegistry itself - mRegistry = new CompositeIssueRegistry(registries); - } - } - } - - private void runExtraPhases(@NonNull Project project, @NonNull Project main) { - // Did any detectors request another phase? - if (mRepeatingDetectors != null) { - // Yes. Iterate up to MAX_PHASES times. - - // During the extra phases, we might be narrowing the scope, and setting it in the - // scope field such that detectors asking about the available scope will get the - // correct result. However, we need to restore it to the original scope when this - // is done in case there are other projects that will be checked after this, since - // the repeated phases is done *per project*, not after all projects have been - // processed. - EnumSet oldScope = mScope; - - do { - mPhase++; - fireEvent(EventType.NEW_PHASE, - new Context(this, project, null, project.getDir())); - - // Narrow the scope down to the set of scopes requested by - // the rules. - if (mRepeatScope == null) { - mRepeatScope = Scope.ALL; - } - mScope = Scope.intersect(mScope, mRepeatScope); - if (mScope.isEmpty()) { - break; - } - - // Compute the detectors to use for this pass. - // Unlike the normal computeDetectors(project) call, - // this is going to use the existing instances, and include - // those that apply for the configuration. - computeRepeatingDetectors(mRepeatingDetectors, project); - - if (mApplicableDetectors.isEmpty()) { - // No detectors enabled in this project: skip it - continue; - } - - checkProject(project, main); - if (mCanceled) { - break; - } - } while (mPhase < MAX_PHASES && mRepeatingDetectors != null); - - mScope = oldScope; - } - } - - private void computeRepeatingDetectors(List detectors, Project project) { - // Ensure that the current visitor is recomputed - mCurrentFolderType = null; - mCurrentVisitor = null; - mCurrentXmlDetectors = null; - mCurrentBinaryDetectors = null; - - // Create map from detector class to issue such that we can - // compute applicable issues for each detector in the list of detectors - // to be repeated - List issues = mRegistry.getIssues(); - Multimap, Issue> issueMap = - ArrayListMultimap.create(issues.size(), 3); - for (Issue issue : issues) { - issueMap.put(issue.getImplementation().getDetectorClass(), issue); - } - - Map, EnumSet> detectorToScope = - new HashMap, EnumSet>(); - Map> scopeToDetectors = - new EnumMap>(Scope.class); - - List detectorList = new ArrayList(); - // Compute the list of detectors (narrowed down from mRepeatingDetectors), - // and simultaneously build up the detectorToScope map which tracks - // the scopes each detector is affected by (this is used to populate - // the mScopeDetectors map which is used during iteration). - Configuration configuration = project.getConfiguration(this); - for (Detector detector : detectors) { - Class detectorClass = detector.getClass(); - Collection detectorIssues = issueMap.get(detectorClass); - if (detectorIssues != null) { - boolean add = false; - for (Issue issue : detectorIssues) { - // The reason we have to check whether the detector is enabled - // is that this is a per-project property, so when running lint in multiple - // projects, a detector enabled only in a different project could have - // requested another phase, and we end up in this project checking whether - // the detector is enabled here. - if (!configuration.isEnabled(issue)) { - continue; - } - - add = true; // Include detector if any of its issues are enabled - - EnumSet s = detectorToScope.get(detectorClass); - EnumSet issueScope = issue.getImplementation().getScope(); - if (s == null) { - detectorToScope.put(detectorClass, issueScope); - } else if (!s.containsAll(issueScope)) { - EnumSet union = EnumSet.copyOf(s); - union.addAll(issueScope); - detectorToScope.put(detectorClass, union); - } - } - - if (add) { - detectorList.add(detector); - EnumSet union = detectorToScope.get(detector.getClass()); - for (Scope s : union) { - List list = scopeToDetectors.get(s); - if (list == null) { - list = new ArrayList(); - scopeToDetectors.put(s, list); - } - list.add(detector); - } - } - } - } - - mApplicableDetectors = detectorList; - mScopeDetectors = scopeToDetectors; - mRepeatingDetectors = null; - mRepeatScope = null; - - validateScopeList(); - } - - private void computeDetectors(@NonNull Project project) { - // Ensure that the current visitor is recomputed - mCurrentFolderType = null; - mCurrentVisitor = null; - - Configuration configuration = project.getConfiguration(this); - mScopeDetectors = new EnumMap>(Scope.class); - mApplicableDetectors = mRegistry.createDetectors(mClient, configuration, - mScope, mScopeDetectors); - - validateScopeList(); - } - - /** Development diagnostics only, run with assertions on */ - @SuppressWarnings("all") // Turn off warnings for the intentional assertion side effect below - private void validateScopeList() { - boolean assertionsEnabled = false; - assert assertionsEnabled = true; // Intentional side-effect - if (assertionsEnabled) { - List resourceFileDetectors = mScopeDetectors.get(Scope.RESOURCE_FILE); - if (resourceFileDetectors != null) { - for (Detector detector : resourceFileDetectors) { - // This is wrong; it should allow XmlScanner instead of ResourceXmlScanner! - assert detector instanceof ResourceXmlDetector : detector; - } - } - - List manifestDetectors = mScopeDetectors.get(Scope.MANIFEST); - if (manifestDetectors != null) { - for (Detector detector : manifestDetectors) { - assert detector instanceof Detector.XmlScanner : detector; - } - } - List javaCodeDetectors = mScopeDetectors.get(Scope.ALL_JAVA_FILES); - if (javaCodeDetectors != null) { - for (Detector detector : javaCodeDetectors) { - assert detector instanceof Detector.JavaScanner || - // TODO: Migrate all - detector instanceof Detector.UastScanner || - detector instanceof Detector.JavaPsiScanner : detector; - } - } - List javaFileDetectors = mScopeDetectors.get(Scope.JAVA_FILE); - if (javaFileDetectors != null) { - for (Detector detector : javaFileDetectors) { - assert detector instanceof Detector.JavaScanner || - // TODO: Migrate all - detector instanceof Detector.UastScanner || - detector instanceof Detector.JavaPsiScanner : detector; - } - } - - List classDetectors = mScopeDetectors.get(Scope.CLASS_FILE); - if (classDetectors != null) { - for (Detector detector : classDetectors) { - assert detector instanceof Detector.ClassScanner : detector; - } - } - - List classCodeDetectors = mScopeDetectors.get(Scope.ALL_CLASS_FILES); - if (classCodeDetectors != null) { - for (Detector detector : classCodeDetectors) { - assert detector instanceof Detector.ClassScanner : detector; - } - } - - List gradleDetectors = mScopeDetectors.get(Scope.GRADLE_FILE); - if (gradleDetectors != null) { - for (Detector detector : gradleDetectors) { - assert detector instanceof Detector.GradleScanner : detector; - } - } - - List otherDetectors = mScopeDetectors.get(Scope.OTHER); - if (otherDetectors != null) { - for (Detector detector : otherDetectors) { - assert detector instanceof Detector.OtherFileScanner : detector; - } - } - - List dirDetectors = mScopeDetectors.get(Scope.RESOURCE_FOLDER); - if (dirDetectors != null) { - for (Detector detector : dirDetectors) { - assert detector instanceof Detector.ResourceFolderScanner : detector; - } - } - - List binaryDetectors = mScopeDetectors.get(Scope.BINARY_RESOURCE_FILE); - if (binaryDetectors != null) { - for (Detector detector : binaryDetectors) { - assert detector instanceof Detector.BinaryResourceScanner : detector; - } - } - } - } - - private void registerProjectFile( - @NonNull Map fileToProject, - @NonNull File file, - @NonNull File projectDir, - @NonNull File rootDir) { - fileToProject.put(file, mClient.getProject(projectDir, rootDir)); - } - - private Collection computeProjects(@NonNull List files) { - // Compute list of projects - Map fileToProject = new LinkedHashMap(); - - File sharedRoot = null; - - // Ensure that we have absolute paths such that if you lint - // "foo bar" in "baz" we can show baz/ as the root - List absolute = new ArrayList(files.size()); - for (File file : files) { - absolute.add(file.getAbsoluteFile()); - } - // Always use absoluteFiles so that we can check the file's getParentFile() - // which is null if the file is not absolute. - files = absolute; - - if (files.size() > 1) { - sharedRoot = LintUtils.getCommonParent(files); - if (sharedRoot != null && sharedRoot.getParentFile() == null) { // "/" ? - sharedRoot = null; - } - } - - for (File file : files) { - if (file.isDirectory()) { - File rootDir = sharedRoot; - if (rootDir == null) { - rootDir = file; - if (files.size() > 1) { - rootDir = file.getParentFile(); - if (rootDir == null) { - rootDir = file; - } - } - } - - // Figure out what to do with a directory. Note that the meaning of the - // directory can be ambiguous: - // If you pass a directory which is unknown, we don't know if we should - // search upwards (in case you're pointing at a deep java package folder - // within the project), or if you're pointing at some top level directory - // containing lots of projects you want to scan. We attempt to do the - // right thing, which is to see if you're pointing right at a project or - // right within it (say at the src/ or res/) folder, and if not, you're - // hopefully pointing at a project tree that you want to scan recursively. - if (mClient.isProjectDirectory(file)) { - registerProjectFile(fileToProject, file, file, rootDir); - continue; - } else { - File parent = file.getParentFile(); - if (parent != null) { - if (mClient.isProjectDirectory(parent)) { - registerProjectFile(fileToProject, file, parent, parent); - continue; - } else { - parent = parent.getParentFile(); - if (parent != null && mClient.isProjectDirectory(parent)) { - registerProjectFile(fileToProject, file, parent, parent); - continue; - } - } - } - - // Search downwards for nested projects - addProjects(file, fileToProject, rootDir); - } - } else { - // Pointed at a file: Search upwards for the containing project - File parent = file.getParentFile(); - while (parent != null) { - if (mClient.isProjectDirectory(parent)) { - registerProjectFile(fileToProject, file, parent, parent); - break; - } - parent = parent.getParentFile(); - } - } - - if (mCanceled) { - return Collections.emptySet(); - } - } - - for (Map.Entry entry : fileToProject.entrySet()) { - File file = entry.getKey(); - Project project = entry.getValue(); - if (!file.equals(project.getDir())) { - if (file.isDirectory()) { - try { - File dir = file.getCanonicalFile(); - if (dir.equals(project.getDir())) { - continue; - } - } catch (IOException ioe) { - // pass - } - } - - project.addFile(file); - } - } - - // Partition the projects up such that we only return projects that aren't - // included by other projects (e.g. because they are library projects) - - Collection allProjects = fileToProject.values(); - Set roots = new HashSet(allProjects); - for (Project project : allProjects) { - roots.removeAll(project.getAllLibraries()); - } - - // Report issues for all projects that are explicitly referenced. We need to - // do this here, since the project initialization will mark all library - // projects as no-report projects by default. - for (Project project : allProjects) { - // Report issues for all projects explicitly listed or found via a directory - // traversal -- including library projects. - project.setReportIssues(true); - } - - if (LintUtils.assertionsEnabled()) { - // Make sure that all the project directories are unique. This ensures - // that we didn't accidentally end up with different project instances - // for a library project discovered as a directory as well as one - // initialized from the library project dependency list - IdentityHashMap projects = - new IdentityHashMap(); - for (Project project : roots) { - projects.put(project, project); - for (Project library : project.getAllLibraries()) { - projects.put(library, library); - } - } - Set dirs = new HashSet(); - for (Project project : projects.keySet()) { - assert !dirs.contains(project.getDir()); - dirs.add(project.getDir()); - } - } - - return roots; - } - - private void addProjects( - @NonNull File dir, - @NonNull Map fileToProject, - @NonNull File rootDir) { - if (mCanceled) { - return; - } - - if (mClient.isProjectDirectory(dir)) { - registerProjectFile(fileToProject, dir, dir, rootDir); - } else { - File[] files = dir.listFiles(); - if (files != null) { - for (File file : files) { - if (file.isDirectory()) { - addProjects(file, fileToProject, rootDir); - } - } - } - } - } - - private void checkProject(@NonNull Project project, @NonNull Project main) { - File projectDir = project.getDir(); - - Context projectContext = new Context(this, project, null, projectDir); - fireEvent(EventType.SCANNING_PROJECT, projectContext); - - List allLibraries = project.getAllLibraries(); - Set allProjects = new HashSet(allLibraries.size() + 1); - allProjects.add(project); - allProjects.addAll(allLibraries); - mCurrentProjects = allProjects.toArray(new Project[allProjects.size()]); - - mCurrentProject = project; - - for (Detector check : mApplicableDetectors) { - check.beforeCheckProject(projectContext); - if (mCanceled) { - return; - } - } - - assert mCurrentProject == project; - runFileDetectors(project, main); - - if (!Scope.checkSingleFile(mScope)) { - List libraries = project.getAllLibraries(); - for (Project library : libraries) { - Context libraryContext = new Context(this, library, project, projectDir); - fireEvent(EventType.SCANNING_LIBRARY_PROJECT, libraryContext); - mCurrentProject = library; - - for (Detector check : mApplicableDetectors) { - check.beforeCheckLibraryProject(libraryContext); - if (mCanceled) { - return; - } - } - assert mCurrentProject == library; - - runFileDetectors(library, main); - if (mCanceled) { - return; - } - - assert mCurrentProject == library; - - for (Detector check : mApplicableDetectors) { - check.afterCheckLibraryProject(libraryContext); - if (mCanceled) { - return; - } - } - } - } - - mCurrentProject = project; - - for (Detector check : mApplicableDetectors) { - check.afterCheckProject(projectContext); - if (mCanceled) { - return; - } - } - - if (mCanceled) { - mClient.report( - projectContext, - // Must provide an issue since API guarantees that the issue parameter - IssueRegistry.CANCELLED, - Severity.INFORMATIONAL, - Location.create(project.getDir()), - "Lint canceled by user", TextFormat.RAW); - } - - mCurrentProjects = null; - } - - private void runFileDetectors(@NonNull Project project, @Nullable Project main) { - // Look up manifest information (but not for library projects) - if (project.isAndroidProject()) { - for (File manifestFile : project.getManifestFiles()) { - XmlParser parser = mClient.getXmlParser(); - if (parser != null) { - XmlContext context = new XmlContext(this, project, main, manifestFile, null, - parser); - context.document = parser.parseXml(context); - if (context.document != null) { - try { - project.readManifest(context.document); - - if ((!project.isLibrary() || (main != null - && main.isMergingManifests())) - && mScope.contains(Scope.MANIFEST)) { - List detectors = mScopeDetectors.get(Scope.MANIFEST); - if (detectors != null) { - ResourceVisitor v = new ResourceVisitor(parser, detectors, - null); - fireEvent(EventType.SCANNING_FILE, context); - v.visitFile(context, manifestFile); - } - } - } finally { - if (context.document != null) { // else: freed by XmlVisitor above - parser.dispose(context, context.document); - } - } - } - } - } - - // Process both Scope.RESOURCE_FILE and Scope.ALL_RESOURCE_FILES detectors together - // in a single pass through the resource directories. - if (mScope.contains(Scope.ALL_RESOURCE_FILES) - || mScope.contains(Scope.RESOURCE_FILE) - || mScope.contains(Scope.RESOURCE_FOLDER) - || mScope.contains(Scope.BINARY_RESOURCE_FILE)) { - List dirChecks = mScopeDetectors.get(Scope.RESOURCE_FOLDER); - List binaryChecks = mScopeDetectors.get(Scope.BINARY_RESOURCE_FILE); - List checks = union(mScopeDetectors.get(Scope.RESOURCE_FILE), - mScopeDetectors.get(Scope.ALL_RESOURCE_FILES)); - boolean haveXmlChecks = checks != null && !checks.isEmpty(); - List xmlDetectors; - if (haveXmlChecks) { - xmlDetectors = new ArrayList(checks.size()); - for (Detector detector : checks) { - if (detector instanceof ResourceXmlDetector) { - xmlDetectors.add((ResourceXmlDetector) detector); - } - } - haveXmlChecks = !xmlDetectors.isEmpty(); - } else { - xmlDetectors = Collections.emptyList(); - } - if (haveXmlChecks - || dirChecks != null && !dirChecks.isEmpty() - || binaryChecks != null && !binaryChecks.isEmpty()) { - List files = project.getSubset(); - if (files != null) { - checkIndividualResources(project, main, xmlDetectors, dirChecks, - binaryChecks, files); - } else { - List resourceFolders = project.getResourceFolders(); - if (!resourceFolders.isEmpty()) { - for (File res : resourceFolders) { - checkResFolder(project, main, res, xmlDetectors, dirChecks, - binaryChecks); - } - } - } - } - } - - if (mCanceled) { - return; - } - } - - if (mScope.contains(Scope.JAVA_FILE) || mScope.contains(Scope.ALL_JAVA_FILES)) { - List checks = union(mScopeDetectors.get(Scope.JAVA_FILE), - mScopeDetectors.get(Scope.ALL_JAVA_FILES)); - if (checks != null && !checks.isEmpty()) { - List files = project.getSubset(); - if (files != null) { - checkIndividualJavaFiles(project, main, checks, files); - } else { - List sourceFolders = project.getJavaSourceFolders(); - if (mScope.contains(Scope.TEST_SOURCES)) { - List testFolders = project.getTestSourceFolders(); - if (!testFolders.isEmpty()) { - List combined = Lists.newArrayListWithExpectedSize( - sourceFolders.size() + testFolders.size()); - combined.addAll(sourceFolders); - combined.addAll(testFolders); - sourceFolders = combined; - } - } - - checkJava(project, main, sourceFolders, checks); - - } - } - } - - if (mCanceled) { - return; - } - - if (mScope.contains(Scope.CLASS_FILE) - || mScope.contains(Scope.ALL_CLASS_FILES) - || mScope.contains(Scope.JAVA_LIBRARIES)) { - checkClasses(project, main); - } - - if (mCanceled) { - return; - } - - if (mScope.contains(Scope.GRADLE_FILE)) { - checkBuildScripts(project, main); - } - - if (mCanceled) { - return; - } - - if (mScope.contains(Scope.OTHER)) { - List checks = mScopeDetectors.get(Scope.OTHER); - if (checks != null) { - OtherFileVisitor visitor = new OtherFileVisitor(checks); - visitor.scan(this, project, main); - } - } - - if (mCanceled) { - return; - } - - if (project == main && mScope.contains(Scope.PROGUARD_FILE) && - project.isAndroidProject()) { - checkProGuard(project, main); - } - - if (project == main && mScope.contains(Scope.PROPERTY_FILE)) { - checkProperties(project, main); - } - } - - private void checkBuildScripts(Project project, Project main) { - List detectors = mScopeDetectors.get(Scope.GRADLE_FILE); - if (detectors != null) { - List files = project.getSubset(); - if (files == null) { - files = project.getGradleBuildScripts(); - } - for (File file : files) { - Context context = new Context(this, project, main, file); - fireEvent(EventType.SCANNING_FILE, context); - for (Detector detector : detectors) { - if (detector.appliesTo(context, file)) { - detector.beforeCheckFile(context); - detector.visitBuildScript(context, Maps.newHashMap()); - detector.afterCheckFile(context); - } - } - } - } - } - - private void checkProGuard(Project project, Project main) { - List detectors = mScopeDetectors.get(Scope.PROGUARD_FILE); - if (detectors != null) { - List files = project.getProguardFiles(); - for (File file : files) { - Context context = new Context(this, project, main, file); - fireEvent(EventType.SCANNING_FILE, context); - for (Detector detector : detectors) { - if (detector.appliesTo(context, file)) { - detector.beforeCheckFile(context); - detector.run(context); - detector.afterCheckFile(context); - } - } - } - } - } - - private void checkProperties(Project project, Project main) { - List detectors = mScopeDetectors.get(Scope.PROPERTY_FILE); - if (detectors != null) { - checkPropertyFile(project, main, detectors, FN_LOCAL_PROPERTIES); - checkPropertyFile(project, main, detectors, FD_GRADLE_WRAPPER + separator + - FN_GRADLE_WRAPPER_PROPERTIES); - } - } - - private void checkPropertyFile(Project project, Project main, List detectors, - String relativePath) { - File file = new File(project.getDir(), relativePath); - if (file.exists()) { - Context context = new Context(this, project, main, file); - fireEvent(EventType.SCANNING_FILE, context); - for (Detector detector : detectors) { - if (detector.appliesTo(context, file)) { - detector.beforeCheckFile(context); - detector.run(context); - detector.afterCheckFile(context); - } - } - } - } - - /** True if execution has been canceled */ - boolean isCanceled() { - return mCanceled; - } - - /** - * Returns the super class for the given class name, - * which should be in VM format (e.g. java/lang/Integer, not java.lang.Integer). - * If the super class is not known, returns null. This can happen if - * the given class is not a known class according to the project or its - * libraries, for example because it refers to one of the core libraries which - * are not analyzed by lint. - * - * @param name the fully qualified class name - * @return the corresponding super class name (in VM format), or null if not known - */ - @Nullable - public String getSuperClass(@NonNull String name) { - return mClient.getSuperClass(mCurrentProject, name); - } - - /** - * Returns true if the given class is a subclass of the given super class. - * - * @param classNode the class to check whether it is a subclass of the given - * super class name - * @param superClassName the fully qualified super class name (in VM format, - * e.g. java/lang/Integer, not java.lang.Integer. - * @return true if the given class is a subclass of the given super class - */ - public boolean isSubclassOf(@NonNull ClassNode classNode, @NonNull String superClassName) { - if (superClassName.equals(classNode.superName)) { - return true; - } - - if (mCurrentProject != null) { - Boolean isSub = mClient.isSubclassOf(mCurrentProject, classNode.name, superClassName); - if (isSub != null) { - return isSub; - } - } - - String className = classNode.name; - while (className != null) { - if (className.equals(superClassName)) { - return true; - } - className = getSuperClass(className); - } - - return false; - } - @Nullable - private static List union( - @Nullable List list1, - @Nullable List list2) { - if (list1 == null) { - return list2; - } else if (list2 == null) { - return list1; - } else { - // Use set to pick out unique detectors, since it's possible for there to be overlap, - // e.g. the DuplicateIdDetector registers both a cross-resource issue and a - // single-file issue, so it shows up on both scope lists: - Set set = new HashSet(list1.size() + list2.size()); - set.addAll(list1); - set.addAll(list2); - - return new ArrayList(set); - } - } - - /** Check the classes in this project (and if applicable, in any library projects */ - private void checkClasses(Project project, Project main) { - List files = project.getSubset(); - if (files != null) { - checkIndividualClassFiles(project, main, files); - return; - } - - // We need to read in all the classes up front such that we can initialize - // the parent chains (such that for example for a virtual dispatch, we can - // also check the super classes). - - List libraries = project.getJavaLibraries(false); - List libraryEntries = ClassEntry.fromClassPath(mClient, libraries, true); - - List classFolders = project.getJavaClassFolders(); - List classEntries; - if (classFolders.isEmpty()) { - String message = String.format("No `.class` files were found in project \"%1$s\", " - + "so none of the classfile based checks could be run. " - + "Does the project need to be built first?", project.getName()); - Location location = Location.create(project.getDir()); - mClient.report(new Context(this, project, main, project.getDir()), - IssueRegistry.LINT_ERROR, - project.getConfiguration(this).getSeverity(IssueRegistry.LINT_ERROR), - location, message, TextFormat.RAW); - classEntries = Collections.emptyList(); - } else { - classEntries = ClassEntry.fromClassPath(mClient, classFolders, true); - } - - // Actually run the detectors. Libraries should be called before the - // main classes. - runClassDetectors(Scope.JAVA_LIBRARIES, libraryEntries, project, main); - - if (mCanceled) { - return; - } - - runClassDetectors(Scope.CLASS_FILE, classEntries, project, main); - runClassDetectors(Scope.ALL_CLASS_FILES, classEntries, project, main); - } - - private void checkIndividualClassFiles( - @NonNull Project project, - @Nullable Project main, - @NonNull List files) { - List classFiles = Lists.newArrayListWithExpectedSize(files.size()); - List classFolders = project.getJavaClassFolders(); - if (!classFolders.isEmpty()) { - for (File file : files) { - String path = file.getPath(); - if (file.isFile() && path.endsWith(DOT_CLASS)) { - classFiles.add(file); - } - } - } - - List entries = ClassEntry.fromClassFiles(mClient, classFiles, classFolders, - true); - if (!entries.isEmpty()) { - Collections.sort(entries); - runClassDetectors(Scope.CLASS_FILE, entries, project, main); - } - } - - /** - * Stack of {@link ClassNode} nodes for outer classes of the currently - * processed class, including that class itself. Populated by - * {@link #runClassDetectors(Scope, List, Project, Project)} and used by - * {@link #getOuterClassNode(ClassNode)} - */ - private Deque mOuterClasses; - - private void runClassDetectors(Scope scope, List entries, - Project project, Project main) { - if (mScope.contains(scope)) { - List classDetectors = mScopeDetectors.get(scope); - if (classDetectors != null && !classDetectors.isEmpty() && !entries.isEmpty()) { - AsmVisitor visitor = new AsmVisitor(mClient, classDetectors); - - String sourceContents = null; - String sourceName = ""; - mOuterClasses = new ArrayDeque(); - ClassEntry prev = null; - for (ClassEntry entry : entries) { - if (prev != null && prev.compareTo(entry) == 0) { - // Duplicate entries for some reason: ignore - continue; - } - prev = entry; - - ClassReader reader; - ClassNode classNode; - try { - reader = new ClassReader(entry.bytes); - classNode = new ClassNode(); - reader.accept(classNode, 0 /* flags */); - } catch (Throwable t) { - mClient.log(null, "Error processing %1$s: broken class file?", - entry.path()); - continue; - } - - ClassNode peek; - while ((peek = mOuterClasses.peek()) != null) { - if (classNode.name.startsWith(peek.name)) { - break; - } else { - mOuterClasses.pop(); - } - } - mOuterClasses.push(classNode); - - if (isSuppressed(null, classNode)) { - // Class was annotated with suppress all -- no need to look any further - continue; - } - - if (sourceContents != null) { - // Attempt to reuse the source buffer if initialized - // This means making sure that the source files - // foo/bar/MyClass and foo/bar/MyClass$Bar - // and foo/bar/MyClass$3 and foo/bar/MyClass$3$1 have the same prefix. - String newName = classNode.name; - int newRootLength = newName.indexOf('$'); - if (newRootLength == -1) { - newRootLength = newName.length(); - } - int oldRootLength = sourceName.indexOf('$'); - if (oldRootLength == -1) { - oldRootLength = sourceName.length(); - } - if (newRootLength != oldRootLength || - !sourceName.regionMatches(0, newName, 0, newRootLength)) { - sourceContents = null; - } - } - - ClassContext context = new ClassContext(this, project, main, - entry.file, entry.jarFile, entry.binDir, entry.bytes, - classNode, scope == Scope.JAVA_LIBRARIES /*fromLibrary*/, - sourceContents); - - try { - visitor.runClassDetectors(context); - } catch (Exception e) { - mClient.log(e, null); - } - - if (mCanceled) { - return; - } - - sourceContents = context.getSourceContents(false/*read*/); - sourceName = classNode.name; - } - - mOuterClasses = null; - } - } - } - - /** Returns the outer class node of the given class node - * @param classNode the inner class node - * @return the outer class node */ - public ClassNode getOuterClassNode(@NonNull ClassNode classNode) { - String outerName = classNode.outerClass; - - Iterator iterator = mOuterClasses.iterator(); - while (iterator.hasNext()) { - ClassNode node = iterator.next(); - if (outerName != null) { - if (node.name.equals(outerName)) { - return node; - } - } else if (node == classNode) { - return iterator.hasNext() ? iterator.next() : null; - } - } - - return null; - } - - /** - * Returns the {@link ClassNode} corresponding to the given type, if possible, or null - * - * @param type the fully qualified type, using JVM signatures (/ and $, not . as path - * separators) - * @param flags the ASM flags to pass to the {@link ClassReader}, normally 0 but can - * for example be {@link ClassReader#SKIP_CODE} and/oor - * {@link ClassReader#SKIP_DEBUG} - * @return the class node for the type, or null - */ - @Nullable - public ClassNode findClass(@NonNull ClassContext context, @NonNull String type, int flags) { - String relative = type.replace('/', File.separatorChar) + DOT_CLASS; - File classFile = findClassFile(context.getProject(), relative); - if (classFile != null) { - if (classFile.getPath().endsWith(DOT_JAR)) { - // TODO: Handle .jar files - return null; - } - - try { - byte[] bytes = mClient.readBytes(classFile); - ClassReader reader = new ClassReader(bytes); - ClassNode classNode = new ClassNode(); - reader.accept(classNode, flags); - - return classNode; - } catch (Throwable t) { - mClient.log(null, "Error processing %1$s: broken class file?", - classFile.getPath()); - } - } - - return null; - } - - @Nullable - private File findClassFile(@NonNull Project project, String relativePath) { - for (File root : mClient.getJavaClassFolders(project)) { - File path = new File(root, relativePath); - if (path.exists()) { - return path; - } - } - // Search in the libraries - for (File root : mClient.getJavaLibraries(project, true)) { - // TODO: Handle .jar files! - //if (root.getPath().endsWith(DOT_JAR)) { - //} - - File path = new File(root, relativePath); - if (path.exists()) { - return path; - } - } - - // Search dependent projects - for (Project library : project.getDirectLibraries()) { - File path = findClassFile(library, relativePath); - if (path != null) { - return path; - } - } - - return null; - } - - private void checkJava( - @NonNull Project project, - @Nullable Project main, - @NonNull List sourceFolders, - @NonNull List checks) { - JavaParser javaParser = mClient.getJavaParser(project); - if (javaParser == null) { - mClient.log(null, "No java parser provided to lint: not running Java checks"); - return; - } - - assert !checks.isEmpty(); - - // Gather all Java source files in a single pass; more efficient. - List sources = new ArrayList(100); - for (File folder : sourceFolders) { - gatherJavaFiles(folder, sources); - } - if (!sources.isEmpty()) { - List contexts = Lists.newArrayListWithExpectedSize(sources.size()); - for (File file : sources) { - JavaContext context = new JavaContext(this, project, main, file, javaParser); - contexts.add(context); - } - visitJavaFiles(checks, javaParser, contexts); - } - } - - private void visitJavaFiles(@NonNull List checks, JavaParser javaParser, - List contexts) { - // Temporary: we still have some builtin checks that aren't migrated to - // PSI. Until that's complete, remove them from the list here - //List scanners = checks; - List scanners = Lists.newArrayListWithCapacity(0); - List uastScanners = Lists.newArrayListWithCapacity(checks.size()); - for (Detector detector : checks) { - if (detector instanceof Detector.JavaPsiScanner) { - scanners.add(detector); - } else if (detector instanceof Detector.UastScanner) { - uastScanners.add(detector); - } - } - - if (!scanners.isEmpty()) { - JavaPsiVisitor visitor = new JavaPsiVisitor(javaParser, scanners); - visitor.prepare(contexts); - for (JavaContext context : contexts) { - fireEvent(EventType.SCANNING_FILE, context); - visitor.visitFile(context); - if (mCanceled) { - return; - } - } - - visitor.dispose(); - } - - if (!uastScanners.isEmpty()) { - final UElementVisitor uElementVisitor = new UElementVisitor(javaParser, uastScanners); - uElementVisitor.prepare(contexts); - for (final JavaContext context : contexts) { - fireEvent(EventType.SCANNING_FILE, context); - ApplicationManager.getApplication().runReadAction(new Runnable() { - @Override - public void run() { - uElementVisitor.visitFile(context); - } - }); - if (mCanceled) { - return; - } - } - - uElementVisitor.dispose(); - } - - // Only if the user is using some custom lint rules that haven't been updated - // yet - //noinspection ConstantConditions - if (mRunCompatChecks) { - // Filter the checks to only those that implement JavaScanner - List filtered = Lists.newArrayListWithCapacity(checks.size()); - for (Detector detector : checks) { - if (detector instanceof Detector.JavaScanner) { - filtered.add(detector); - } - } - - if (!filtered.isEmpty()) { - List detectorNames = Lists.newArrayListWithCapacity(filtered.size()); - for (Detector detector : filtered) { - detectorNames.add(detector.getClass().getName()); - } - Collections.sort(detectorNames); - - /* Let's not complain quite yet - String message = String.format("Lint found one or more custom checks using its " - + "older Java API; these checks are still run in compatibility mode, " - + "but this causes duplicated parsing, and in the next version lint " - + "will no longer include this legacy mode. Make sure the following " - + "lint detectors are upgraded to the new API: %1$s", - Joiner.on(", ").join(detectorNames)); - JavaContext first = contexts.get(0); - Project project = first.getProject(); - Location location = Location.create(project.getDir()); - mClient.report(first, - IssueRegistry.LINT_ERROR, - project.getConfiguration(this).getSeverity(IssueRegistry.LINT_ERROR), - location, message, TextFormat.RAW); - */ - - - JavaVisitor oldVisitor = new JavaVisitor(javaParser, filtered); - - oldVisitor.prepare(contexts); - for (JavaContext context : contexts) { - fireEvent(EventType.SCANNING_FILE, context); - oldVisitor.visitFile(context); - if (mCanceled) { - return; - } - } - oldVisitor.dispose(); - } - } - } - - private void checkIndividualJavaFiles( - @NonNull Project project, - @Nullable Project main, - @NonNull List checks, - @NonNull List files) { - - JavaParser javaParser = mClient.getJavaParser(project); - if (javaParser == null) { - mClient.log(null, "No java parser provided to lint: not running Java checks"); - return; - } - - List contexts = Lists.newArrayListWithExpectedSize(files.size()); - for (File file : files) { - if (file.isFile() && file.getPath().endsWith(".kt")) { - contexts.add(new JavaContext(this, project, main, file, javaParser)); - } - } - - if (contexts.isEmpty()) { - return; - } - - visitJavaFiles(checks, javaParser, contexts); - } - - private static void gatherJavaFiles(@NonNull File dir, @NonNull List result) { - File[] files = dir.listFiles(); - if (files != null) { - for (File file : files) { - if (file.isFile() && file.getName().endsWith(".java")) { //$NON-NLS-1$ - result.add(file); - } else if (file.isDirectory()) { - gatherJavaFiles(file, result); - } - } - } - } - - private ResourceFolderType mCurrentFolderType; - private List mCurrentXmlDetectors; - private List mCurrentBinaryDetectors; - private ResourceVisitor mCurrentVisitor; - - @Nullable - private ResourceVisitor getVisitor( - @NonNull ResourceFolderType type, - @NonNull List checks, - @Nullable List binaryChecks) { - if (type != mCurrentFolderType) { - mCurrentFolderType = type; - - // Determine which XML resource detectors apply to the given folder type - List applicableXmlChecks = - new ArrayList(checks.size()); - for (ResourceXmlDetector check : checks) { - if (check.appliesTo(type)) { - applicableXmlChecks.add(check); - } - } - List applicableBinaryChecks = null; - if (binaryChecks != null) { - applicableBinaryChecks = new ArrayList(binaryChecks.size()); - for (Detector check : binaryChecks) { - if (check.appliesTo(type)) { - applicableBinaryChecks.add(check); - } - } - } - - // If the list of detectors hasn't changed, then just use the current visitor! - if (mCurrentXmlDetectors != null && mCurrentXmlDetectors.equals(applicableXmlChecks) - && Objects.equal(mCurrentBinaryDetectors, applicableBinaryChecks)) { - return mCurrentVisitor; - } - - mCurrentXmlDetectors = applicableXmlChecks; - mCurrentBinaryDetectors = applicableBinaryChecks; - - if (applicableXmlChecks.isEmpty() - && (applicableBinaryChecks == null || applicableBinaryChecks.isEmpty())) { - mCurrentVisitor = null; - return null; - } - - XmlParser parser = mClient.getXmlParser(); - if (parser != null) { - mCurrentVisitor = new ResourceVisitor(parser, applicableXmlChecks, - applicableBinaryChecks); - } else { - mCurrentVisitor = null; - } - } - - return mCurrentVisitor; - } - - private void checkResFolder( - @NonNull Project project, - @Nullable Project main, - @NonNull File res, - @NonNull List xmlChecks, - @Nullable List dirChecks, - @Nullable List binaryChecks) { - File[] resourceDirs = res.listFiles(); - if (resourceDirs == null) { - return; - } - - // Sort alphabetically such that we can process related folder types at the - // same time, and to have a defined behavior such that detectors can rely on - // predictable ordering, e.g. layouts are seen before menus are seen before - // values, etc (l < m < v). - - Arrays.sort(resourceDirs); - for (File dir : resourceDirs) { - ResourceFolderType type = ResourceFolderType.getFolderType(dir.getName()); - if (type != null) { - checkResourceFolder(project, main, dir, type, xmlChecks, dirChecks, binaryChecks); - } - - if (mCanceled) { - return; - } - } - } - - private void checkResourceFolder( - @NonNull Project project, - @Nullable Project main, - @NonNull File dir, - @NonNull ResourceFolderType type, - @NonNull List xmlChecks, - @Nullable List dirChecks, - @Nullable List binaryChecks) { - - // Process the resource folder - - if (dirChecks != null && !dirChecks.isEmpty()) { - ResourceContext context = new ResourceContext(this, project, main, dir, type); - String folderName = dir.getName(); - fireEvent(EventType.SCANNING_FILE, context); - for (Detector check : dirChecks) { - if (check.appliesTo(type)) { - check.beforeCheckFile(context); - check.checkFolder(context, folderName); - check.afterCheckFile(context); - } - } - if (binaryChecks == null && xmlChecks.isEmpty()) { - return; - } - } - - File[] files = dir.listFiles(); - if (files == null || files.length <= 0) { - return; - } - - ResourceVisitor visitor = getVisitor(type, xmlChecks, binaryChecks); - if (visitor != null) { // if not, there are no applicable rules in this folder - // Process files in alphabetical order, to ensure stable output - // (for example for the duplicate resource detector) - Arrays.sort(files); - for (File file : files) { - if (LintUtils.isXmlFile(file)) { - XmlContext context = new XmlContext(this, project, main, file, type, - visitor.getParser()); - fireEvent(EventType.SCANNING_FILE, context); - visitor.visitFile(context, file); - } else if (binaryChecks != null && (LintUtils.isBitmapFile(file) || - type == ResourceFolderType.RAW)) { - ResourceContext context = new ResourceContext(this, project, main, file, type); - fireEvent(EventType.SCANNING_FILE, context); - visitor.visitBinaryResource(context); - } - if (mCanceled) { - return; - } - } - } - } - - /** Checks individual resources */ - private void checkIndividualResources( - @NonNull Project project, - @Nullable Project main, - @NonNull List xmlDetectors, - @Nullable List dirChecks, - @Nullable List binaryChecks, - @NonNull List files) { - for (File file : files) { - if (file.isDirectory()) { - // Is it a resource folder? - ResourceFolderType type = ResourceFolderType.getFolderType(file.getName()); - if (type != null && new File(file.getParentFile(), RES_FOLDER).exists()) { - // Yes. - checkResourceFolder(project, main, file, type, xmlDetectors, dirChecks, - binaryChecks); - } else if (file.getName().equals(RES_FOLDER)) { // Is it the res folder? - // Yes - checkResFolder(project, main, file, xmlDetectors, dirChecks, binaryChecks); - } else { - mClient.log(null, "Unexpected folder %1$s; should be project, " + - "\"res\" folder or resource folder", file.getPath()); - } - } else if (file.isFile() && LintUtils.isXmlFile(file)) { - // Yes, find out its resource type - String folderName = file.getParentFile().getName(); - ResourceFolderType type = ResourceFolderType.getFolderType(folderName); - if (type != null) { - ResourceVisitor visitor = getVisitor(type, xmlDetectors, binaryChecks); - if (visitor != null) { - XmlContext context = new XmlContext(this, project, main, file, type, - visitor.getParser()); - fireEvent(EventType.SCANNING_FILE, context); - visitor.visitFile(context, file); - } - } - } else if (binaryChecks != null && file.isFile() && LintUtils.isBitmapFile(file)) { - // Yes, find out its resource type - String folderName = file.getParentFile().getName(); - ResourceFolderType type = ResourceFolderType.getFolderType(folderName); - if (type != null) { - ResourceVisitor visitor = getVisitor(type, xmlDetectors, binaryChecks); - if (visitor != null) { - ResourceContext context = new ResourceContext(this, project, main, file, - type); - fireEvent(EventType.SCANNING_FILE, context); - visitor.visitBinaryResource(context); - if (mCanceled) { - return; - } - } - } - } - } - } - - /** - * Adds a listener to be notified of lint progress - * - * @param listener the listener to be added - */ - public void addLintListener(@NonNull LintListener listener) { - if (mListeners == null) { - mListeners = new ArrayList(1); - } - mListeners.add(listener); - } - - /** - * Removes a listener such that it is no longer notified of progress - * - * @param listener the listener to be removed - */ - public void removeLintListener(@NonNull LintListener listener) { - mListeners.remove(listener); - if (mListeners.isEmpty()) { - mListeners = null; - } - } - - /** Notifies listeners, if any, that the given event has occurred */ - private void fireEvent(@NonNull LintListener.EventType type, @Nullable Context context) { - if (mListeners != null) { - for (LintListener listener : mListeners) { - listener.update(this, type, context); - } - } - } - - /** - * Wrapper around the lint client. This sits in the middle between a - * detector calling for example {@link LintClient#report} and - * the actual embedding tool, and performs filtering etc such that detectors - * and lint clients don't have to make sure they check for ignored issues or - * filtered out warnings. - */ - private class LintClientWrapper extends LintClient { - @NonNull - private final LintClient mDelegate; - - public LintClientWrapper(@NonNull LintClient delegate) { - super(getClientName()); - mDelegate = delegate; - } - - @Override - public void report( - @NonNull Context context, - @NonNull Issue issue, - @NonNull Severity severity, - @NonNull Location location, - @NonNull String message, - @NonNull TextFormat format) { - //noinspection ConstantConditions - if (location == null) { - // Misbehaving third-party lint detectors - assert false : issue; - return; - } - - assert mCurrentProject != null; - if (!mCurrentProject.getReportIssues()) { - return; - } - - Configuration configuration = context.getConfiguration(); - if (!configuration.isEnabled(issue)) { - if (issue != IssueRegistry.PARSER_ERROR && issue != IssueRegistry.LINT_ERROR) { - mDelegate.log(null, "Incorrect detector reported disabled issue %1$s", - issue.toString()); - } - return; - } - - if (configuration.isIgnored(context, issue, location, message)) { - return; - } - - if (severity == Severity.IGNORE) { - return; - } - - mDelegate.report(context, issue, severity, location, message, format); - } - - // Everything else just delegates to the embedding lint client - - @Override - @NonNull - public Configuration getConfiguration(@NonNull Project project, - @Nullable LintDriver driver) { - return mDelegate.getConfiguration(project, driver); - } - - @Override - public void log(@NonNull Severity severity, @Nullable Throwable exception, - @Nullable String format, @Nullable Object... args) { - mDelegate.log(exception, format, args); - } - - @Override - @NonNull - public String readFile(@NonNull File file) { - return mDelegate.readFile(file); - } - - @Override - @NonNull - public byte[] readBytes(@NonNull File file) throws IOException { - return mDelegate.readBytes(file); - } - - @Override - @NonNull - public List getJavaSourceFolders(@NonNull Project project) { - return mDelegate.getJavaSourceFolders(project); - } - - @Override - @NonNull - public List getJavaClassFolders(@NonNull Project project) { - return mDelegate.getJavaClassFolders(project); - } - - @NonNull - @Override - public List getJavaLibraries(@NonNull Project project, boolean includeProvided) { - return mDelegate.getJavaLibraries(project, includeProvided); - } - - @NonNull - @Override - public List getTestSourceFolders(@NonNull Project project) { - return mDelegate.getTestSourceFolders(project); - } - - @Override - public Collection getKnownProjects() { - return mDelegate.getKnownProjects(); - } - - @Nullable - @Override - public BuildToolInfo getBuildTools(@NonNull Project project) { - return mDelegate.getBuildTools(project); - } - - @NonNull - @Override - public Map createSuperClassMap(@NonNull Project project) { - return mDelegate.createSuperClassMap(project); - } - - @NonNull - @Override - public ResourceVisibilityLookup.Provider getResourceVisibilityProvider() { - return mDelegate.getResourceVisibilityProvider(); - } - - @Override - @NonNull - public List getResourceFolders(@NonNull Project project) { - return mDelegate.getResourceFolders(project); - } - - @Override - @Nullable - public XmlParser getXmlParser() { - return mDelegate.getXmlParser(); - } - - @Override - @NonNull - public Class replaceDetector( - @NonNull Class detectorClass) { - return mDelegate.replaceDetector(detectorClass); - } - - @Override - @NonNull - public SdkInfo getSdkInfo(@NonNull Project project) { - return mDelegate.getSdkInfo(project); - } - - @Override - @NonNull - public Project getProject(@NonNull File dir, @NonNull File referenceDir) { - return mDelegate.getProject(dir, referenceDir); - } - - @Nullable - @Override - public JavaParser getJavaParser(@Nullable Project project) { - return mDelegate.getJavaParser(project); - } - - @Override - public File findResource(@NonNull String relativePath) { - return mDelegate.findResource(relativePath); - } - - @Override - @Nullable - public File getCacheDir(boolean create) { - return mDelegate.getCacheDir(create); - } - - @Override - @NonNull - protected ClassPathInfo getClassPath(@NonNull Project project) { - return mDelegate.getClassPath(project); - } - - @Override - public void log(@Nullable Throwable exception, @Nullable String format, - @Nullable Object... args) { - mDelegate.log(exception, format, args); - } - - @Override - @Nullable - public File getSdkHome() { - return mDelegate.getSdkHome(); - } - - @Override - @NonNull - public IAndroidTarget[] getTargets() { - return mDelegate.getTargets(); - } - - @Nullable - @Override - public AndroidSdkHandler getSdk() { - return mDelegate.getSdk(); - } - - @Nullable - @Override - public IAndroidTarget getCompileTarget(@NonNull Project project) { - return mDelegate.getCompileTarget(project); - } - - @Override - public int getHighestKnownApiLevel() { - return mDelegate.getHighestKnownApiLevel(); - } - - @Override - @Nullable - public String getSuperClass(@NonNull Project project, @NonNull String name) { - return mDelegate.getSuperClass(project, name); - } - - @Override - @Nullable - public Boolean isSubclassOf(@NonNull Project project, @NonNull String name, - @NonNull String superClassName) { - return mDelegate.isSubclassOf(project, name, superClassName); - } - - @Override - @NonNull - public String getProjectName(@NonNull Project project) { - return mDelegate.getProjectName(project); - } - - @Override - public boolean isGradleProject(Project project) { - return mDelegate.isGradleProject(project); - } - - @NonNull - @Override - protected Project createProject(@NonNull File dir, @NonNull File referenceDir) { - return mDelegate.createProject(dir, referenceDir); - } - - @NonNull - @Override - public List findGlobalRuleJars() { - return mDelegate.findGlobalRuleJars(); - } - - @NonNull - @Override - public List findRuleJars(@NonNull Project project) { - return mDelegate.findRuleJars(project); - } - - @Override - public boolean isProjectDirectory(@NonNull File dir) { - return mDelegate.isProjectDirectory(dir); - } - - @Override - public void registerProject(@NonNull File dir, @NonNull Project project) { - log(Severity.WARNING, null, "Too late to register projects"); - mDelegate.registerProject(dir, project); - } - - @Override - public IssueRegistry addCustomLintRules(@NonNull IssueRegistry registry) { - return mDelegate.addCustomLintRules(registry); - } - - @NonNull - @Override - public List getAssetFolders(@NonNull Project project) { - return mDelegate.getAssetFolders(project); - } - - @Override - public ClassLoader createUrlClassLoader(@NonNull URL[] urls, @NonNull ClassLoader parent) { - return mDelegate.createUrlClassLoader(urls, parent); - } - - @Override - public boolean checkForSuppressComments() { - return mDelegate.checkForSuppressComments(); - } - - @Override - public boolean supportsProjectResources() { - return mDelegate.supportsProjectResources(); - } - - @Nullable - @Override - public AbstractResourceRepository getProjectResources(Project project, - boolean includeDependencies) { - return mDelegate.getProjectResources(project, includeDependencies); - } - - @NonNull - @Override - public Location.Handle createResourceItemHandle(@NonNull ResourceItem item) { - return mDelegate.createResourceItemHandle(item); - } - - @Nullable - @Override - public URLConnection openConnection(@NonNull URL url) throws IOException { - return mDelegate.openConnection(url); - } - - @Override - public void closeConnection(@NonNull URLConnection connection) throws IOException { - mDelegate.closeConnection(connection); - } - } - - /** - * Requests another pass through the data for the given detector. This is - * typically done when a detector needs to do more expensive computation, - * but it only wants to do this once it knows that an error is - * present, or once it knows more specifically what to check for. - * - * @param detector the detector that should be included in the next pass. - * Note that the lint runner may refuse to run more than a couple - * of runs. - * @param scope the scope to be revisited. This must be a subset of the - * current scope ({@link #getScope()}, and it is just a performance hint; - * in particular, the detector should be prepared to be called on other - * scopes as well (since they may have been requested by other detectors). - * You can pall null to indicate "all". - */ - public void requestRepeat(@NonNull Detector detector, @Nullable EnumSet scope) { - if (mRepeatingDetectors == null) { - mRepeatingDetectors = new ArrayList(); - } - mRepeatingDetectors.add(detector); - - if (scope != null) { - if (mRepeatScope == null) { - mRepeatScope = scope; - } else { - mRepeatScope = EnumSet.copyOf(mRepeatScope); - mRepeatScope.addAll(scope); - } - } else { - mRepeatScope = Scope.ALL; - } - } - - // Unfortunately, ASMs nodes do not extend a common DOM node type with parent - // pointers, so we have to have multiple methods which pass in each type - // of node (class, method, field) to be checked. - - /** - * Returns whether the given issue is suppressed in the given method. - * - * @param issue the issue to be checked, or null to just check for "all" - * @param classNode the class containing the issue - * @param method the method containing the issue - * @param instruction the instruction within the method, if any - * @return true if there is a suppress annotation covering the specific - * issue on this method - */ - public boolean isSuppressed( - @Nullable Issue issue, - @NonNull ClassNode classNode, - @NonNull MethodNode method, - @Nullable AbstractInsnNode instruction) { - if (method.invisibleAnnotations != null) { - @SuppressWarnings("unchecked") - List annotations = method.invisibleAnnotations; - return isSuppressed(issue, annotations); - } - - // Initializations of fields end up placed in generated methods ( - // for members and for static fields). - if (instruction != null && method.name.charAt(0) == '<') { - AbstractInsnNode next = LintUtils.getNextInstruction(instruction); - if (next != null && next.getType() == AbstractInsnNode.FIELD_INSN) { - FieldInsnNode fieldRef = (FieldInsnNode) next; - FieldNode field = findField(classNode, fieldRef.owner, fieldRef.name); - if (field != null && isSuppressed(issue, field)) { - return true; - } - } else if (classNode.outerClass != null && classNode.outerMethod == null - && isAnonymousClass(classNode)) { - if (isSuppressed(issue, classNode)) { - return true; - } - } - } - - return false; - } - - @Nullable - private static MethodInsnNode findConstructorInvocation( - @NonNull MethodNode method, - @NonNull String className) { - InsnList nodes = method.instructions; - for (int i = 0, n = nodes.size(); i < n; i++) { - AbstractInsnNode instruction = nodes.get(i); - if (instruction.getOpcode() == Opcodes.INVOKESPECIAL) { - MethodInsnNode call = (MethodInsnNode) instruction; - if (className.equals(call.owner)) { - return call; - } - } - } - - return null; - } - - @Nullable - private FieldNode findField( - @NonNull ClassNode classNode, - @NonNull String owner, - @NonNull String name) { - ClassNode current = classNode; - while (current != null) { - if (owner.equals(current.name)) { - @SuppressWarnings("rawtypes") // ASM API - List fieldList = current.fields; - for (Object f : fieldList) { - FieldNode field = (FieldNode) f; - if (field.name.equals(name)) { - return field; - } - } - return null; - } - current = getOuterClassNode(current); - } - return null; - } - - @Nullable - private MethodNode findMethod( - @NonNull ClassNode classNode, - @NonNull String name, - boolean includeInherited) { - ClassNode current = classNode; - while (current != null) { - @SuppressWarnings("rawtypes") // ASM API - List methodList = current.methods; - for (Object f : methodList) { - MethodNode method = (MethodNode) f; - if (method.name.equals(name)) { - return method; - } - } - - if (includeInherited) { - current = getOuterClassNode(current); - } else { - break; - } - } - return null; - } - - /** - * Returns whether the given issue is suppressed for the given field. - * - * @param issue the issue to be checked, or null to just check for "all" - * @param field the field potentially annotated with a suppress annotation - * @return true if there is a suppress annotation covering the specific - * issue on this field - */ - @SuppressWarnings("MethodMayBeStatic") // API; reserve need to require driver state later - public boolean isSuppressed(@Nullable Issue issue, @NonNull FieldNode field) { - if (field.invisibleAnnotations != null) { - @SuppressWarnings("unchecked") - List annotations = field.invisibleAnnotations; - return isSuppressed(issue, annotations); - } - - return false; - } - - /** - * Returns whether the given issue is suppressed in the given class. - * - * @param issue the issue to be checked, or null to just check for "all" - * @param classNode the class containing the issue - * @return true if there is a suppress annotation covering the specific - * issue in this class - */ - public boolean isSuppressed(@Nullable Issue issue, @NonNull ClassNode classNode) { - if (classNode.invisibleAnnotations != null) { - @SuppressWarnings("unchecked") - List annotations = classNode.invisibleAnnotations; - return isSuppressed(issue, annotations); - } - - if (classNode.outerClass != null && classNode.outerMethod == null - && isAnonymousClass(classNode)) { - ClassNode outer = getOuterClassNode(classNode); - if (outer != null) { - MethodNode m = findMethod(outer, CONSTRUCTOR_NAME, false); - if (m != null) { - MethodInsnNode call = findConstructorInvocation(m, classNode.name); - if (call != null) { - if (isSuppressed(issue, outer, m, call)) { - return true; - } - } - } - m = findMethod(outer, CLASS_CONSTRUCTOR, false); - if (m != null) { - MethodInsnNode call = findConstructorInvocation(m, classNode.name); - if (call != null) { - if (isSuppressed(issue, outer, m, call)) { - return true; - } - } - } - } - } - - return false; - } - - private static boolean isSuppressed(@Nullable Issue issue, List annotations) { - for (AnnotationNode annotation : annotations) { - String desc = annotation.desc; - - // We could obey @SuppressWarnings("all") too, but no need to look for it - // because that annotation only has source retention. - - if (desc.endsWith(SUPPRESS_LINT_VMSIG)) { - if (annotation.values != null) { - for (int i = 0, n = annotation.values.size(); i < n; i += 2) { - String key = (String) annotation.values.get(i); - if (key.equals("value")) { //$NON-NLS-1$ - Object value = annotation.values.get(i + 1); - if (value instanceof String) { - String id = (String) value; - if (matches(issue, id)) { - return true; - } - } else if (value instanceof List) { - @SuppressWarnings("rawtypes") - List list = (List) value; - for (Object v : list) { - if (v instanceof String) { - String id = (String) v; - if (matches(issue, id)) { - return true; - } - } - } - } - } - } - } - } - } - - return false; - } - - private static boolean matches(@Nullable Issue issue, @NonNull String id) { - if (id.equalsIgnoreCase(SUPPRESS_ALL)) { - return true; - } - - if (issue != null) { - String issueId = issue.getId(); - if (id.equalsIgnoreCase(issueId)) { - return true; - } - if (id.startsWith(STUDIO_ID_PREFIX) - && id.regionMatches(true, STUDIO_ID_PREFIX.length(), issueId, 0, issueId.length()) - && id.substring(STUDIO_ID_PREFIX.length()).equalsIgnoreCase(issueId)) { - return true; - } - } - - return false; - } - - /** - * Returns true if the given issue is suppressed by the given suppress string; this - * is typically the same as the issue id, but is allowed to not match case sensitively, - * and is allowed to be a comma separated list, and can be the string "all" - * - * @param issue the issue id to match - * @param string the suppress string -- typically the id, or "all", or a comma separated list - * of ids - * @return true if the issue is suppressed by the given string - */ - private static boolean isSuppressed(@NonNull Issue issue, @NonNull String string) { - if (string.isEmpty()) { - return false; - } - - if (string.indexOf(',') == -1) { - if (matches(issue, string)) { - return true; - } - } else { - for (String id : Splitter.on(',').trimResults().split(string)) { - if (matches(issue, id)) { - return true; - } - } - } - - return false; - } - - /** - * Returns whether the given issue is suppressed in the given parse tree node. - * - * @param context the context for the source being scanned - * @param issue the issue to be checked, or null to just check for "all" - * @param scope the AST node containing the issue - * @return true if there is a suppress annotation covering the specific - * issue in this class - */ - public boolean isSuppressed(@Nullable JavaContext context, @NonNull Issue issue, - @Nullable Node scope) { - boolean checkComments = mClient.checkForSuppressComments() && - context != null && context.containsCommentSuppress(); - while (scope != null) { - Class type = scope.getClass(); - // The Lombok AST uses a flat hierarchy of node type implementation classes - // so no need to do instanceof stuff here. - if (type == VariableDefinition.class) { - // Variable - VariableDefinition declaration = (VariableDefinition) scope; - if (isSuppressed(issue, declaration.astModifiers())) { - return true; - } - } else if (type == MethodDeclaration.class) { - // Method - // Look for annotations on the method - MethodDeclaration declaration = (MethodDeclaration) scope; - if (isSuppressed(issue, declaration.astModifiers())) { - return true; - } - } else if (type == ConstructorDeclaration.class) { - // Constructor - // Look for annotations on the method - ConstructorDeclaration declaration = (ConstructorDeclaration) scope; - if (isSuppressed(issue, declaration.astModifiers())) { - return true; - } - } else if (TypeDeclaration.class.isAssignableFrom(type)) { - // Class, annotation, enum, interface - TypeDeclaration declaration = (TypeDeclaration) scope; - if (isSuppressed(issue, declaration.astModifiers())) { - return true; - } - } else if (type == AnnotationMethodDeclaration.class) { - // Look for annotations on the method - AnnotationMethodDeclaration declaration = (AnnotationMethodDeclaration) scope; - if (isSuppressed(issue, declaration.astModifiers())) { - return true; - } - } - - if (checkComments && context.isSuppressedWithComment(scope, issue)) { - return true; - } - - scope = scope.getParent(); - } - - return false; - } - - public boolean isSuppressed(@Nullable JavaContext context, @NonNull Issue issue, - @Nullable UElement scope) { - boolean checkComments = mClient.checkForSuppressComments() && - context != null && context.containsCommentSuppress(); - while (scope != null) { - if (scope instanceof UAnnotated) { - if (isSuppressed(issue, (UAnnotated) scope)) { - return true; - } - } - - if (checkComments && context.isSuppressedWithComment(scope, issue)) { - return true; - } - - scope = scope.getUastParent(); - if (scope instanceof UFile) { - return false; - } - } - - return false; - } - - public boolean isSuppressed(@Nullable JavaContext context, @NonNull Issue issue, - @Nullable PsiElement scope) { - boolean checkComments = mClient.checkForSuppressComments() && - context != null && context.containsCommentSuppress(); - while (scope != null) { - if (scope instanceof PsiModifierListOwner) { - PsiModifierListOwner owner = (PsiModifierListOwner) scope; - if (isSuppressed(issue, owner.getModifierList())) { - return true; - } - } - - if (checkComments && context.isSuppressedWithComment(scope, issue)) { - return true; - } - - scope = scope.getParent(); - if (scope instanceof PsiFile) { - return false; - } - } - - return false; - } - - /** - * Returns true if the given AST modifier has a suppress annotation for the - * given issue (which can be null to check for the "all" annotation) - * - * @param issue the issue to be checked - * @param modifiers the modifier to check - * @return true if the issue or all issues should be suppressed for this - * modifier - */ - private static boolean isSuppressed(@Nullable Issue issue, @Nullable Modifiers modifiers) { - if (modifiers == null) { - return false; - } - StrictListAccessor annotations = modifiers.astAnnotations(); - if (annotations == null) { - return false; - } - - for (Annotation annotation : annotations) { - TypeReference t = annotation.astAnnotationTypeReference(); - String typeName = t.getTypeName(); - if (typeName.endsWith(SUPPRESS_LINT) - || typeName.endsWith("SuppressWarnings")) { //$NON-NLS-1$ - StrictListAccessor values = - annotation.astElements(); - if (values != null) { - for (AnnotationElement element : values) { - AnnotationValue valueNode = element.astValue(); - if (valueNode == null) { - continue; - } - if (valueNode instanceof StringLiteral) { - StringLiteral literal = (StringLiteral) valueNode; - String value = literal.astValue(); - if (matches(issue, value)) { - return true; - } - } else if (valueNode instanceof ArrayInitializer) { - ArrayInitializer array = (ArrayInitializer) valueNode; - StrictListAccessor expressions = - array.astExpressions(); - if (expressions == null) { - continue; - } - for (Expression arrayElement : expressions) { - if (arrayElement instanceof StringLiteral) { - String value = ((StringLiteral) arrayElement).astValue(); - if (matches(issue, value)) { - return true; - } - } - } - } - } - } - } - } - - return false; - } - - public static final String SUPPRESS_WARNINGS_FQCN = "java.lang.SuppressWarnings"; - - - /** - * Returns true if the given AST modifier has a suppress annotation for the - * given issue (which can be null to check for the "all" annotation) - * - * @param issue the issue to be checked - * @param modifierList the modifier to check - * @return true if the issue or all issues should be suppressed for this - * modifier - */ - public static boolean isSuppressed(@NonNull Issue issue, - @Nullable PsiModifierList modifierList) { - if (modifierList == null) { - return false; - } - - for (PsiAnnotation annotation : modifierList.getAnnotations()) { - String fqcn = annotation.getQualifiedName(); - if (fqcn != null && (fqcn.equals(FQCN_SUPPRESS_LINT) - || fqcn.equals(SUPPRESS_WARNINGS_FQCN) - || fqcn.equals(SUPPRESS_LINT))) { // when missing imports - PsiAnnotationParameterList parameterList = annotation.getParameterList(); - for (PsiNameValuePair pair : parameterList.getAttributes()) { - if (isSuppressed(issue, pair.getValue())) { - return true; - } - } - } - } - - return false; - } - - /** - * Returns true if the annotation member value, assumed to be specified on a a SuppressWarnings - * or SuppressLint annotation, specifies the given id (or "all"). - * - * @param issue the issue to be checked - * @param value the member value to check - * @return true if the issue or all issues should be suppressed for this modifier - */ - public static boolean isSuppressed(@NonNull Issue issue, - @Nullable PsiAnnotationMemberValue value) { - if (value instanceof PsiLiteral) { - PsiLiteral literal = (PsiLiteral)value; - Object literalValue = literal.getValue(); - if (literalValue instanceof String) { - if (isSuppressed(issue, (String) literalValue)) { - return true; - } - } - } else if (value instanceof PsiArrayInitializerMemberValue) { - PsiArrayInitializerMemberValue mv = (PsiArrayInitializerMemberValue)value; - for (PsiAnnotationMemberValue mmv : mv.getInitializers()) { - if (isSuppressed(issue, mmv)) { - return true; - } - } - } else if (value instanceof PsiArrayInitializerExpression) { - PsiArrayInitializerExpression expression = (PsiArrayInitializerExpression) value; - PsiExpression[] initializers = expression.getInitializers(); - for (PsiExpression e : initializers) { - if (isSuppressed(issue, e)) { - return true; - } - } - } - - return false; - } - - /** - * Returns whether the given issue is suppressed in the given XML DOM node. - * - * @param issue the issue to be checked, or null to just check for "all" - * @param node the DOM node containing the issue - * @return true if there is a suppress annotation covering the specific - * issue in this class - */ - public boolean isSuppressed(@Nullable XmlContext context, @NonNull Issue issue, - @Nullable org.w3c.dom.Node node) { - if (node instanceof Attr) { - node = ((Attr) node).getOwnerElement(); - } - boolean checkComments = mClient.checkForSuppressComments() - && context != null && context.containsCommentSuppress(); - while (node != null) { - if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) { - Element element = (Element) node; - if (element.hasAttributeNS(TOOLS_URI, ATTR_IGNORE)) { - String ignore = element.getAttributeNS(TOOLS_URI, ATTR_IGNORE); - if (isSuppressed(issue, ignore)) { - return true; - } - } else if (checkComments && context.isSuppressedWithComment(node, issue)) { - return true; - } - } - - node = node.getParentNode(); - } - - return false; - } - - /** - * Returns true if the given AST modifier has a suppress annotation for the - * given issue (which can be null to check for the "all" annotation) - * - * @param issue the issue to be checked - * @param element the element to check - * @return true if the issue or all issues should be suppressed for this - * element - */ - public static boolean isSuppressed(@NonNull Issue issue, - @Nullable UAnnotated element) { - if (element == null) { - return false; - } - - for (UAnnotation annotation : element.getAnnotations()) { - String fqcn = annotation.getQualifiedName(); - if (fqcn != null && (fqcn.equals(FQCN_SUPPRESS_LINT) - || fqcn.equals(SUPPRESS_WARNINGS_FQCN) - || fqcn.equals(SUPPRESS_LINT))) { // when missing imports - UExpression valueAttributeExpression = annotation.findAttributeValue("value"); - if (valueAttributeExpression != null) { - if (UastExpressionUtils.isArrayInitializer(valueAttributeExpression)) { - UCallExpression arrayInitializer = (UCallExpression) valueAttributeExpression; - for (UExpression issueIdExpression : arrayInitializer.getValueArguments()) { - Object value = issueIdExpression.evaluate(); - if (value instanceof String && isSuppressed(issue, (String) value)) { - return true; - } - } - } - else { - Object value = valueAttributeExpression.evaluate(); - if (value instanceof String && isSuppressed(issue, (String) value)) { - return true; - } - } - } - } - } - - return false; - } - - private File mCachedFolder = null; - private int mCachedFolderVersion = -1; - /** Pattern for version qualifiers */ - private static final Pattern VERSION_PATTERN = Pattern.compile("^v(\\d+)$"); //$NON-NLS-1$ - - /** - * Returns the folder version of the given file. For example, for the file values-v14/foo.xml, - * it returns 14. - * - * @param resourceFile the file to be checked - * @return the folder version, or -1 if no specific version was specified - */ - public int getResourceFolderVersion(@NonNull File resourceFile) { - File parent = resourceFile.getParentFile(); - if (parent == null) { - return -1; - } - if (parent.equals(mCachedFolder)) { - return mCachedFolderVersion; - } - - mCachedFolder = parent; - mCachedFolderVersion = -1; - - for (String qualifier : QUALIFIER_SPLITTER.split(parent.getName())) { - Matcher matcher = VERSION_PATTERN.matcher(qualifier); - if (matcher.matches()) { - String group = matcher.group(1); - assert group != null; - mCachedFolderVersion = Integer.parseInt(group); - break; - } - } - - return mCachedFolderVersion; - } - -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/LintListener.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/client/api/LintListener.java.173 deleted file mode 100644 index 7ef4ba0a305..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/LintListener.java.173 +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2011 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.client.api; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.tools.klint.detector.api.Context; -import com.google.common.annotations.Beta; - -/** - * Interface implemented by listeners to be notified of lint events - *

- * NOTE: This is not a public or final API; if you rely on this be prepared - * to adjust your code for the next tools release. - */ -@Beta -public interface LintListener { - /** The various types of events provided to lint listeners */ - enum EventType { - /** A lint check is about to begin */ - STARTING, - - /** Lint is about to check the given project, see {@link Context#getProject()} */ - SCANNING_PROJECT, - - /** Lint is about to check the given library project, see {@link Context#getProject()} */ - SCANNING_LIBRARY_PROJECT, - - /** Lint is about to check the given file, see {@link Context#file} */ - SCANNING_FILE, - - /** A new pass was initiated */ - NEW_PHASE, - - /** The lint check was canceled */ - CANCELED, - - /** The lint check is done */ - COMPLETED, - } - - /** - * Notifies listeners that the event of the given type has occurred. - * Additional information, such as the file being scanned, or the project - * being scanned, is available in the {@link Context} object (except for the - * {@link EventType#STARTING}, {@link EventType#CANCELED} or - * {@link EventType#COMPLETED} events which are fired outside of project - * contexts.) - * - * @param driver the driver running through the checks - * @param type the type of event that occurred - * @param context the context providing additional information - */ - void update(@NonNull LintDriver driver, @NonNull EventType type, - @Nullable Context context); -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/LintRequest.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/client/api/LintRequest.java.173 deleted file mode 100644 index f812591dabe..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/LintRequest.java.173 +++ /dev/null @@ -1,180 +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 com.android.tools.klint.client.api; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.tools.klint.detector.api.Project; -import com.android.tools.klint.detector.api.Scope; -import com.google.common.annotations.Beta; - -import java.io.File; -import java.util.Collection; -import java.util.EnumSet; -import java.util.List; - -/** - * Information about a request to run lint - *

- * NOTE: This is not a public or final API; if you rely on this be prepared - * to adjust your code for the next tools release. - */ -@Beta -public class LintRequest { - @NonNull - protected final LintClient mClient; - - @NonNull - protected final List mFiles; - - @Nullable - protected EnumSet mScope; - - @Nullable - protected Boolean mReleaseMode; - - @Nullable - protected Collection mProjects; - - /** - * Creates a new {@linkplain LintRequest}, to be passed to a {@link LintDriver} - * - * @param client the tool wrapping the analyzer, such as an IDE or a CLI - * @param files the set of files to check with lint. This can reference Android projects, - * or directories containing Android projects, or individual XML or Java files - * (typically for incremental IDE analysis). - */ - public LintRequest(@NonNull LintClient client, @NonNull List files) { - mClient = client; - mFiles = files; - } - - /** - * Returns the lint client requesting the lint check - * - * @return the client, never null - */ - @NonNull - public LintClient getClient() { - return mClient; - } - - /** - * Returns the set of files to check with lint. This can reference Android projects, - * or directories containing Android projects, or individual XML or Java files - * (typically for incremental IDE analysis). - * - * @return the set of files to check, should not be empty - */ - @NonNull - public List getFiles() { - return mFiles; - } - - /** - * Sets the scope to use; lint checks which require a wider scope set - * will be ignored - * - * @return the scope to use, or null to use the default - */ - @Nullable - public EnumSet getScope() { - return mScope; - } - - /** - * Sets the scope to use; lint checks which require a wider scope set - * will be ignored - * - * @param scope the scope - * @return this, for constructor chaining - */ - @NonNull - public LintRequest setScope(@Nullable EnumSet scope) { - mScope = scope; - return this; - } - - /** - * Returns {@code true} if lint is invoked as part of a release mode build, - * {@code false} if it is part of a debug mode build, and {@code null} if - * the release mode is not known - * - * @return true if this lint is running in release mode, null if not known - */ - @Nullable - public Boolean isReleaseMode() { - return mReleaseMode; - } - - /** - * Sets the release mode. Use {@code true} if lint is invoked as part of a - * release mode build, {@code false} if it is part of a debug mode build, - * and {@code null} if the release mode is not known - * - * @param releaseMode true if this lint is running in release mode, null if not known - * @return this, for constructor chaining - */ - @NonNull - public LintRequest setReleaseMode(@Nullable Boolean releaseMode) { - mReleaseMode = releaseMode; - return this; - } - - /** - * Gets the projects for the lint requests. This is optional; if not provided lint will search - * the {@link #getFiles()} directories and look for projects via {@link - * LintClient#isProjectDirectory(java.io.File)}. However, this method allows a lint client to - * set up all the projects ahead of time, and associate those projects with native resources - * (in an IDE for example, each lint project can be associated with the corresponding IDE - * project). - * - * @return a collection of projects, or null - */ - @Nullable - public Collection getProjects() { - return mProjects; - } - - /** - * Sets the projects for the lint requests. This is optional; if not provided lint will search - * the {@link #getFiles()} directories and look for projects via {@link - * LintClient#isProjectDirectory(java.io.File)}. However, this method allows a lint client to - * set up all the projects ahead of time, and associate those projects with native resources - * (in an IDE for example, each lint project can be associated with the corresponding IDE - * project). - * - * @param projects a collection of projects, or null - */ - public void setProjects(@Nullable Collection projects) { - mProjects = projects; - } - - /** - * Returns the project to be used as the main project during analysis. This is - * usually the project itself, but when you are for example analyzing a library project, - * it can be the app project using the library. - * - * @param project the project to look up the main project for - * @return the main project - */ - @SuppressWarnings("MethodMayBeStatic") - @NonNull - public Project getMainProject(@NonNull Project project) { - return project; - } -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/OtherFileVisitor.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/client/api/OtherFileVisitor.java.173 deleted file mode 100644 index f6a42f24698..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/OtherFileVisitor.java.173 +++ /dev/null @@ -1,207 +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 com.android.tools.klint.client.api; - -import static com.android.SdkConstants.ANDROID_MANIFEST_XML; -import static com.android.SdkConstants.DOT_CLASS; -import static com.android.SdkConstants.DOT_JAVA; -import static com.android.SdkConstants.DOT_XML; -import static com.android.SdkConstants.FD_ASSETS; -import static com.android.tools.klint.detector.api.Detector.OtherFileScanner; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.tools.klint.detector.api.Context; -import com.android.tools.klint.detector.api.Detector; -import com.android.tools.klint.detector.api.Project; -import com.android.tools.klint.detector.api.Scope; -import com.android.utils.SdkUtils; -import com.google.common.collect.Lists; - -import java.io.File; -import java.util.ArrayList; -import java.util.EnumMap; -import java.util.EnumSet; -import java.util.List; -import java.util.Map; - -/** - * Visitor for "other" files: files that aren't java sources, - * XML sources, etc -- or which should have custom handling in some - * other way. - */ -class OtherFileVisitor { - @NonNull - private final List mDetectors; - - @NonNull - private Map> mFiles = new EnumMap>(Scope.class); - - OtherFileVisitor(@NonNull List detectors) { - mDetectors = detectors; - } - - /** Analyze other files in the given project */ - void scan( - @NonNull LintDriver driver, - @NonNull Project project, - @Nullable Project main) { - // Collect all project files - File projectFolder = project.getDir(); - - EnumSet scopes = EnumSet.noneOf(Scope.class); - for (Detector detector : mDetectors) { - OtherFileScanner fileScanner = (OtherFileScanner) detector; - EnumSet applicable = fileScanner.getApplicableFiles(); - if (applicable.contains(Scope.OTHER)) { - scopes = Scope.ALL; - break; - } - scopes.addAll(applicable); - } - - List subset = project.getSubset(); - - if (scopes.contains(Scope.RESOURCE_FILE)) { - if (subset != null && !subset.isEmpty()) { - List files = new ArrayList(subset.size()); - for (File file : subset) { - if (SdkUtils.endsWith(file.getPath(), DOT_XML) && - !file.getName().equals(ANDROID_MANIFEST_XML)) { - files.add(file); - } - } - if (!files.isEmpty()) { - mFiles.put(Scope.RESOURCE_FILE, files); - } - } else { - List files = Lists.newArrayListWithExpectedSize(100); - for (File res : project.getResourceFolders()) { - collectFiles(files, res); - } - File assets = new File(projectFolder, FD_ASSETS); - if (assets.exists()) { - collectFiles(files, assets); - } - if (!files.isEmpty()) { - mFiles.put(Scope.RESOURCE_FILE, files); - } - } - } - - if (scopes.contains(Scope.JAVA_FILE)) { - if (subset != null && !subset.isEmpty()) { - List files = new ArrayList(subset.size()); - for (File file : subset) { - if (file.getPath().endsWith(".kt")) { - files.add(file); - } - } - if (!files.isEmpty()) { - mFiles.put(Scope.JAVA_FILE, files); - } - } else { - List files = Lists.newArrayListWithExpectedSize(100); - for (File srcFolder : project.getJavaSourceFolders()) { - collectFiles(files, srcFolder); - } - if (!files.isEmpty()) { - mFiles.put(Scope.JAVA_FILE, files); - } - } - } - - if (scopes.contains(Scope.CLASS_FILE)) { - if (subset != null && !subset.isEmpty()) { - List files = new ArrayList(subset.size()); - for (File file : subset) { - if (file.getPath().endsWith(DOT_CLASS)) { - files.add(file); - } - } - if (!files.isEmpty()) { - mFiles.put(Scope.CLASS_FILE, files); - } - } else { - List files = Lists.newArrayListWithExpectedSize(100); - for (File classFolder : project.getJavaClassFolders()) { - collectFiles(files, classFolder); - } - if (!files.isEmpty()) { - mFiles.put(Scope.CLASS_FILE, files); - } - } - } - - if (scopes.contains(Scope.MANIFEST)) { - if (subset != null && !subset.isEmpty()) { - List files = new ArrayList(subset.size()); - for (File file : subset) { - if (file.getName().equals(ANDROID_MANIFEST_XML)) { - files.add(file); - } - } - if (!files.isEmpty()) { - mFiles.put(Scope.MANIFEST, files); - } - } else { - List manifestFiles = project.getManifestFiles(); - if (manifestFiles != null) { - mFiles.put(Scope.MANIFEST, manifestFiles); - } - } - } - - for (Map.Entry> entry : mFiles.entrySet()) { - Scope scope = entry.getKey(); - List files = entry.getValue(); - List applicable = new ArrayList(mDetectors.size()); - for (Detector detector : mDetectors) { - OtherFileScanner fileScanner = (OtherFileScanner) detector; - EnumSet appliesTo = fileScanner.getApplicableFiles(); - if (appliesTo.contains(Scope.OTHER) || appliesTo.contains(scope)) { - applicable.add(detector); - } - } - if (!applicable.isEmpty()) { - for (File file : files) { - Context context = new Context(driver, project, main, file); - for (Detector detector : applicable) { - detector.beforeCheckFile(context); - detector.run(context); - detector.afterCheckFile(context); - } - if (driver.isCanceled()) { - return; - } - } - } - } - } - - private static void collectFiles(List files, File file) { - if (file.isDirectory()) { - File[] children = file.listFiles(); - if (children != null) { - for (File child : children) { - collectFiles(files, child); - } - } - } else { - files.add(file); - } - } -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/ResourceVisitor.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/client/api/ResourceVisitor.java.173 deleted file mode 100644 index 5ea1008cfb2..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/ResourceVisitor.java.173 +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright (C) 2011 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.client.api; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.tools.klint.detector.api.Detector; -import com.android.tools.klint.detector.api.Detector.XmlScanner; -import com.android.tools.klint.detector.api.LintUtils; -import com.android.tools.klint.detector.api.ResourceContext; -import com.android.tools.klint.detector.api.XmlContext; -import com.google.common.annotations.Beta; - -import org.w3c.dom.Attr; -import org.w3c.dom.Element; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import java.io.File; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.RandomAccess; - -/** - * Specialized visitor for running detectors on resources: typically XML documents, - * but also binary resources. - *

- * It operates in two phases: - *

    - *
  1. First, it computes a set of maps where it generates a map from each - * significant element name, and each significant attribute name, to a list - * of detectors to consult for that element or attribute name. - * The set of element names or attribute names (or both) that a detector - * is interested in is provided by the detectors themselves. - *
  2. Second, it iterates over the document a single time. For each element and - * attribute it looks up the list of interested detectors, and runs them. - *
- * It also notifies all the detectors before and after the document is processed - * such that they can do pre- and post-processing. - *

- * NOTE: This is not a public or final API; if you rely on this be prepared - * to adjust your code for the next tools release. - */ -@Beta -class ResourceVisitor { - private final Map> mElementToCheck = - new HashMap>(); - private final Map> mAttributeToCheck = - new HashMap>(); - private final List mDocumentDetectors = - new ArrayList(); - private final List mAllElementDetectors = - new ArrayList(); - private final List mAllAttributeDetectors = - new ArrayList(); - private final List mAllDetectors; - private final List mBinaryDetectors; - private final XmlParser mParser; - - // Really want this: - // & Detector.XmlScanner> XmlVisitor(IDomParser parser, - // T xmlDetectors) { - // but it makes client code tricky and ugly. - ResourceVisitor( - @NonNull XmlParser parser, - @NonNull List xmlDetectors, - @Nullable List binaryDetectors) { - mParser = parser; - mAllDetectors = xmlDetectors; - mBinaryDetectors = binaryDetectors; - - // TODO: Check appliesTo() for files, and find a quick way to enable/disable - // rules when running through a full project! - for (Detector detector : xmlDetectors) { - Detector.XmlScanner xmlDetector = (XmlScanner) detector; - Collection attributes = xmlDetector.getApplicableAttributes(); - if (attributes == XmlScanner.ALL) { - mAllAttributeDetectors.add(xmlDetector); - } else if (attributes != null) { - for (String attribute : attributes) { - List list = mAttributeToCheck.get(attribute); - if (list == null) { - list = new ArrayList(); - mAttributeToCheck.put(attribute, list); - } - list.add(xmlDetector); - } - } - Collection elements = xmlDetector.getApplicableElements(); - if (elements == XmlScanner.ALL) { - mAllElementDetectors.add(xmlDetector); - } else if (elements != null) { - for (String element : elements) { - List list = mElementToCheck.get(element); - if (list == null) { - list = new ArrayList(); - mElementToCheck.put(element, list); - } - list.add(xmlDetector); - } - } - - if ((attributes == null || (attributes.isEmpty() - && attributes != XmlScanner.ALL)) - && (elements == null || (elements.isEmpty() - && elements != XmlScanner.ALL))) { - mDocumentDetectors.add(xmlDetector); - } - } - } - - void visitFile(@NonNull XmlContext context, @NonNull File file) { - assert LintUtils.isXmlFile(file); - - try { - if (context.document == null) { - context.document = mParser.parseXml(context); - if (context.document == null) { - // No need to log this; the parser should be reporting - // a full warning (such as IssueRegistry#PARSER_ERROR) - // with details, location, etc. - return; - } - if (context.document.getDocumentElement() == null) { - // Ignore empty documents - return; - } - } - - for (Detector check : mAllDetectors) { - check.beforeCheckFile(context); - } - - for (Detector.XmlScanner check : mDocumentDetectors) { - check.visitDocument(context, context.document); - } - - if (!mElementToCheck.isEmpty() || !mAttributeToCheck.isEmpty() - || !mAllAttributeDetectors.isEmpty() || !mAllElementDetectors.isEmpty()) { - visitElement(context, context.document.getDocumentElement()); - } - - for (Detector check : mAllDetectors) { - check.afterCheckFile(context); - } - } finally { - if (context.document != null) { - mParser.dispose(context, context.document); - context.document = null; - } - } - } - - private void visitElement(@NonNull XmlContext context, @NonNull Element element) { - List elementChecks = mElementToCheck.get(element.getTagName()); - if (elementChecks != null) { - assert elementChecks instanceof RandomAccess; - for (XmlScanner check : elementChecks) { - check.visitElement(context, element); - } - } - if (!mAllElementDetectors.isEmpty()) { - for (XmlScanner check : mAllElementDetectors) { - check.visitElement(context, element); - } - } - - if (!mAttributeToCheck.isEmpty() || !mAllAttributeDetectors.isEmpty()) { - NamedNodeMap attributes = element.getAttributes(); - for (int i = 0, n = attributes.getLength(); i < n; i++) { - Attr attribute = (Attr) attributes.item(i); - String name = attribute.getLocalName(); - if (name == null) { - name = attribute.getName(); - } - List list = mAttributeToCheck.get(name); - if (list != null) { - for (XmlScanner check : list) { - check.visitAttribute(context, attribute); - } - } - if (!mAllAttributeDetectors.isEmpty()) { - for (XmlScanner check : mAllAttributeDetectors) { - check.visitAttribute(context, attribute); - } - } - } - } - - // Visit children - NodeList childNodes = element.getChildNodes(); - for (int i = 0, n = childNodes.getLength(); i < n; i++) { - Node child = childNodes.item(i); - if (child.getNodeType() == Node.ELEMENT_NODE) { - visitElement(context, (Element) child); - } - } - - // Post hooks - if (elementChecks != null) { - for (XmlScanner check : elementChecks) { - check.visitElementAfter(context, element); - } - } - if (!mAllElementDetectors.isEmpty()) { - for (XmlScanner check : mAllElementDetectors) { - check.visitElementAfter(context, element); - } - } - } - - @NonNull - public XmlParser getParser() { - return mParser; - } - - public void visitBinaryResource(@NonNull ResourceContext context) { - if (mBinaryDetectors == null) { - return; - } - for (Detector check : mBinaryDetectors) { - check.beforeCheckFile(context); - check.checkBinaryResource(context); - check.afterCheckFile(context); - } - } -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/SdkInfo.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/client/api/SdkInfo.java.173 deleted file mode 100644 index e109d00ca6c..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/SdkInfo.java.173 +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2011 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.client.api; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.google.common.annotations.Beta; - -/** - * Information about SDKs - *

- * NOTE: This is not a public or final API; if you rely on this be prepared - * to adjust your code for the next tools release. - */ -@Beta -public abstract class SdkInfo { - /** - * Returns true if the given child view is the same class or a sub class of - * the given parent view class - * - * @param parentViewFqcn the fully qualified class name of the parent view - * @param childViewFqcn the fully qualified class name of the child view - * @return true if the child view is a sub view of (or the same class as) - * the parent view - */ - public boolean isSubViewOf(@NonNull String parentViewFqcn, @NonNull String childViewFqcn) { - while (!childViewFqcn.equals("android.view.View")) { //$NON-NLS-1$ - if (parentViewFqcn.equals(childViewFqcn)) { - return true; - } - String parent = getParentViewClass(childViewFqcn); - if (parent == null) { - // Unknown view - err on the side of caution - return true; - } - childViewFqcn = parent; - } - - return false; - } - - - /** - * Returns the fully qualified name of the parent view, or null if the view - * is the root android.view.View class. - * - * @param fqcn the fully qualified class name of the view - * @return the fully qualified class name of the parent view, or null - */ - @Nullable - public abstract String getParentViewClass(@NonNull String fqcn); - - /** - * Returns the class name of the parent view, or null if the view is the - * root android.view.View class. This is the same as the - * {@link #getParentViewClass(String)} but without the package. - * - * @param name the view class name to look up the parent for (not including - * package) - * @return the view name of the parent - */ - @Nullable - public abstract String getParentViewName(@NonNull String name); - - /** - * Returns true if the given widget name is a layout - * - * @param tag the XML tag for the view - * @return true if the given tag corresponds to a layout - */ - public boolean isLayout(@NonNull String tag) { - return tag.endsWith("Layout"); //$NON-NLS-1$ - } - - // TODO: Add access to resource resolution here. -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/UElementVisitor.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/client/api/UElementVisitor.java.173 deleted file mode 100644 index f518bae9df7..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/UElementVisitor.java.173 +++ /dev/null @@ -1,1088 +0,0 @@ -/* - * Copyright (C) 2016 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.client.api; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.annotations.VisibleForTesting; -import com.android.tools.klint.detector.api.Detector; -import com.android.tools.klint.detector.api.Detector.JavaPsiScanner; -import com.android.tools.klint.detector.api.Detector.UastScanner; -import com.android.tools.klint.detector.api.Detector.XmlScanner; -import com.android.tools.klint.detector.api.JavaContext; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import com.intellij.openapi.progress.ProcessCanceledException; -import com.intellij.openapi.progress.ProgressManager; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vfs.StandardFileSystems; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.*; -import org.jetbrains.uast.*; -import org.jetbrains.uast.util.UastExpressionUtils; -import org.jetbrains.uast.visitor.AbstractUastVisitor; -import org.jetbrains.uast.visitor.UastVisitor; - -import java.util.*; - -import static com.android.SdkConstants.ANDROID_PKG; - -/** - * Specialized visitor for running detectors on a Java AST. - * It operates in three phases: - *

    - *
  1. First, it computes a set of maps where it generates a map from each - * significant AST attribute (such as method call names) to a list - * of detectors to consult whenever that attribute is encountered. - * Examples of "attributes" are method names, Android resource identifiers, - * and general AST node types such as "cast" nodes etc. These are - * defined on the {@link JavaPsiScanner} interface. - *
  2. Second, it iterates over the document a single time, delegating to - * the detectors found at each relevant AST attribute. - *
  3. Finally, it calls the remaining visitors (those that need to process a - * whole document on their own). - *
- * It also notifies all the detectors before and after the document is processed - * such that they can do pre- and post-processing. - */ -public class UElementVisitor { - /** Default size of lists holding detectors of the same type for a given node type */ - private static final int SAME_TYPE_COUNT = 8; - - private final Map> mMethodDetectors = - Maps.newHashMapWithExpectedSize(80); - private final Map> mConstructorDetectors = - Maps.newHashMapWithExpectedSize(12); - private final Map> mReferenceDetectors = - Maps.newHashMapWithExpectedSize(10); - private Set mConstructorSimpleNames; - private final List mResourceFieldDetectors = - new ArrayList(); - private final List mAllDetectors; - private final List mFullTreeDetectors; - private final Map, List> mNodePsiTypeDetectors = - new HashMap, List>(16); - private final JavaParser mParser; - private final Map> mSuperClassDetectors = - new HashMap>(); - - /** - * Number of fatal exceptions (internal errors, usually from ECJ) we've - * encountered; we don't log each and every one to avoid massive log spam - * in code which triggers this condition - */ - private static int sExceptionCount; - /** Max number of logs to include */ - private static final int MAX_REPORTED_CRASHES = 20; - - UElementVisitor(@NonNull JavaParser parser, @NonNull List detectors) { - mParser = parser; - mAllDetectors = new ArrayList(detectors.size()); - mFullTreeDetectors = new ArrayList(detectors.size()); - - for (Detector detector : detectors) { - UastScanner uastScanner = (UastScanner) detector; - VisitingDetector v = new VisitingDetector(detector, uastScanner); - mAllDetectors.add(v); - - List names = detector.getApplicableMethodNames(); - if (names != null) { - // not supported in Java visitors; adding a method invocation node is trivial - // for that case. - assert names != XmlScanner.ALL; - - for (String name : names) { - List list = mMethodDetectors.get(name); - if (list == null) { - list = new ArrayList(SAME_TYPE_COUNT); - mMethodDetectors.put(name, list); - } - list.add(v); - } - } - - List applicableSuperClasses = detector.applicableSuperClasses(); - if (applicableSuperClasses != null) { - for (String fqn : applicableSuperClasses) { - List list = mSuperClassDetectors.get(fqn); - if (list == null) { - list = new ArrayList(SAME_TYPE_COUNT); - mSuperClassDetectors.put(fqn, list); - } - list.add(v); - } - continue; - } - - List> nodePsiTypes = detector.getApplicableUastTypes(); - if (nodePsiTypes != null) { - for (Class type : nodePsiTypes) { - List list = mNodePsiTypeDetectors.get(type); - if (list == null) { - list = new ArrayList(SAME_TYPE_COUNT); - mNodePsiTypeDetectors.put(type, list); - } - list.add(v); - } - } - - List types = detector.getApplicableConstructorTypes(); - if (types != null) { - // not supported in Java visitors; adding a method invocation node is trivial - // for that case. - assert types != XmlScanner.ALL; - if (mConstructorSimpleNames == null) { - mConstructorSimpleNames = Sets.newHashSet(); - } - for (String type : types) { - List list = mConstructorDetectors.get(type); - if (list == null) { - list = new ArrayList(SAME_TYPE_COUNT); - mConstructorDetectors.put(type, list); - mConstructorSimpleNames.add(type.substring(type.lastIndexOf('.')+1)); - } - list.add(v); - } - } - - List referenceNames = detector.getApplicableReferenceNames(); - if (referenceNames != null) { - // not supported in Java visitors; adding a method invocation node is trivial - // for that case. - assert referenceNames != XmlScanner.ALL; - - for (String name : referenceNames) { - List list = mReferenceDetectors.get(name); - if (list == null) { - list = new ArrayList(SAME_TYPE_COUNT); - mReferenceDetectors.put(name, list); - } - list.add(v); - } - } - - if (detector.appliesToResourceRefs()) { - mResourceFieldDetectors.add(v); - } else if ((referenceNames == null || referenceNames.isEmpty()) - && (nodePsiTypes == null || nodePsiTypes.isEmpty()) - && (types == null || types.isEmpty())) { - mFullTreeDetectors.add(v); - } - } - } - - void visitFile(@NonNull final JavaContext context) { - try { - Project ideaProject = context.getParser().getIdeaProject(); - if (ideaProject == null) { - return; - } - - VirtualFile virtualFile = StandardFileSystems.local() - .findFileByPath(context.file.getAbsolutePath()); - if (virtualFile == null) { - return; - } - - PsiFile psiFile = PsiManager.getInstance(ideaProject).findFile(virtualFile); - if (psiFile == null) { - return; - } - - UElement uElement = context.getUastContext().convertElementWithParent(psiFile, UFile.class); - if (!(uElement instanceof UFile)) { - // No need to log this; the parser should be reporting - // a full warning (such as IssueRegistry#PARSER_ERROR) - // with details, location, etc. - return; - } - - final UFile uFile = (UFile) uElement; - - try { - context.setUFile(uFile); - - mParser.runReadAction(new Runnable() { - @Override - public void run() { - for (VisitingDetector v : mAllDetectors) { - v.setContext(context); - v.getDetector().beforeCheckFile(context); - } - } - }); - - if (!mSuperClassDetectors.isEmpty()) { - mParser.runReadAction(new Runnable() { - @Override - public void run() { - SuperclassPsiVisitor visitor = new SuperclassPsiVisitor(context); - uFile.accept(visitor); - } - }); - } - - for (final VisitingDetector v : mFullTreeDetectors) { - mParser.runReadAction(new Runnable() { - @Override - public void run() { - UastVisitor visitor = v.getVisitor(); - ProgressManager.checkCanceled(); - uFile.accept(visitor); - } - }); - } - - if (!mMethodDetectors.isEmpty() - || !mResourceFieldDetectors.isEmpty() - || !mConstructorDetectors.isEmpty() - || !mReferenceDetectors.isEmpty()) { - mParser.runReadAction(new Runnable() { - @Override - public void run() { - // TODO: Do we need to break this one up into finer grain - // locking units - UastVisitor visitor = new DelegatingPsiVisitor(context); - uFile.accept(visitor); - } - }); - } else { - if (!mNodePsiTypeDetectors.isEmpty()) { - mParser.runReadAction(new Runnable() { - @Override - public void run() { - // TODO: Do we need to break this one up into finer grain - // locking units - UastVisitor visitor = new DispatchPsiVisitor(); - uFile.accept(visitor); - } - }); - } - } - - mParser.runReadAction(new Runnable() { - @Override - public void run() { - for (VisitingDetector v : mAllDetectors) { - ProgressManager.checkCanceled(); - v.getDetector().afterCheckFile(context); - } - } - }); - } finally { - mParser.dispose(context, uFile); - context.setUFile(null); - } - } catch (ProcessCanceledException ignore) { - // Cancelling inspections in the IDE - } catch (RuntimeException e) { - if (sExceptionCount++ > MAX_REPORTED_CRASHES) { - // No need to keep spamming the user that a lot of the files - // are tripping up ECJ, they get the picture. - return; - } - - if (e.getClass().getSimpleName().equals("IndexNotReadyException")) { - // Attempting to access PSI during startup before indices are ready; ignore these. - // See http://b.android.com/176644 for an example. - return; - } - - // Work around ECJ bugs; see https://code.google.com/p/android/issues/detail?id=172268 - // Don't allow lint bugs to take down the whole build. TRY to log this as a - // lint error instead! - StringBuilder sb = new StringBuilder(100); - sb.append("Unexpected failure during lint analysis of "); - sb.append(context.file.getName()); - sb.append(" (this is a bug in lint or one of the libraries it depends on)\n"); - - sb.append(e.getClass().getSimpleName()); - sb.append(':'); - StackTraceElement[] stackTrace = e.getStackTrace(); - int count = 0; - for (StackTraceElement frame : stackTrace) { - if (count > 0) { - sb.append("<-"); - } - - String className = frame.getClassName(); - sb.append(className.substring(className.lastIndexOf('.') + 1)); - sb.append('.').append(frame.getMethodName()); - sb.append('('); - sb.append(frame.getFileName()).append(':').append(frame.getLineNumber()); - sb.append(')'); - count++; - // Only print the top 3-4 frames such that we can identify the bug - if (count == 4) { - break; - } - } - Throwable throwable = null; // NOT e: this makes for very noisy logs - //noinspection ConstantConditions - context.log(throwable, sb.toString()); - } - } - - /** - * For testing only: returns the number of exceptions thrown during Java AST analysis - * - * @return the number of internal errors found - */ - @VisibleForTesting - public static int getCrashCount() { - return sExceptionCount; - } - - /** - * For testing only: clears the crash counter - */ - @VisibleForTesting - public static void clearCrashCount() { - sExceptionCount = 0; - } - - public void prepare(@NonNull List contexts) { - mParser.prepareJavaParse(contexts); - } - - public void dispose() { - mParser.dispose(); - } - - @Nullable - private static Set getInterfaceNames( - @Nullable Set addTo, - @NonNull PsiClass cls) { - for (PsiClass resolvedInterface : cls.getInterfaces()) { - String name = resolvedInterface.getQualifiedName(); - if (addTo == null) { - addTo = Sets.newHashSet(); - } else if (addTo.contains(name)) { - // Superclasses can explicitly implement the same interface, - // so keep track of visited interfaces as we traverse up the - // super class chain to avoid checking the same interface - // more than once. - continue; - } - addTo.add(name); - getInterfaceNames(addTo, resolvedInterface); - } - - return addTo; - } - - private static class VisitingDetector { - private UastVisitor mVisitor; - private JavaContext mContext; - public final Detector mDetector; - public final UastScanner mUastScanner; - - public VisitingDetector(@NonNull Detector detector, @NonNull UastScanner uastScanner) { - mDetector = detector; - mUastScanner = uastScanner; - } - - @NonNull - public Detector getDetector() { - return mDetector; - } - - @Nullable - public UastScanner getUastScanner() { - return mUastScanner; - } - - public void setContext(@NonNull JavaContext context) { - mContext = context; - - // The visitors are one-per-context, so clear them out here and construct - // lazily only if needed - mVisitor = null; - } - - @NonNull - UastVisitor getVisitor() { - if (mVisitor == null) { - mVisitor = mDetector.createUastVisitor(mContext); - if (mVisitor == null) { - mVisitor = new AbstractUastVisitor() {}; - } - } - return mVisitor; - } - } - - private class SuperclassPsiVisitor extends AbstractUastVisitor { - private JavaContext mContext; - - public SuperclassPsiVisitor(@NonNull JavaContext context) { - mContext = context; - } - - @Override - public boolean visitClass(UClass node) { - boolean result = super.visitClass(node); - checkClass(node); - return result; - } - - private void checkClass(@NonNull UClass node) { - ProgressManager.checkCanceled(); - - if (node instanceof PsiTypeParameter) { - // Not included: explained in javadoc for JavaPsiScanner#checkClass - return; - } - - UClass cls = node; - int depth = 0; - while (cls != null) { - List list = mSuperClassDetectors.get(cls.getQualifiedName()); - if (list != null) { - for (VisitingDetector v : list) { - UastScanner uastScanner = v.getUastScanner(); - if (uastScanner != null) { - uastScanner.checkClass(mContext, node); - } - } - } - - // Check interfaces too - Set interfaceNames = getInterfaceNames(null, cls); - if (interfaceNames != null) { - for (String name : interfaceNames) { - list = mSuperClassDetectors.get(name); - if (list != null) { - for (VisitingDetector v : list) { - UastScanner javaPsiScanner = v.getUastScanner(); - if (javaPsiScanner != null) { - javaPsiScanner.checkClass(mContext, node); - } - } - } - } - } - - cls = cls.getSuperClass(); - depth++; - if (depth == 500) { - // Shouldn't happen in practice; this prevents the IDE from - // hanging if the user has accidentally typed in an incorrect - // super class which creates a cycle. - break; - } - } - } - } - - private class DispatchPsiVisitor extends AbstractUastVisitor { - - @Override - public boolean visitAnnotation(UAnnotation node) { - List list = mNodePsiTypeDetectors.get(UAnnotation.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitAnnotation(node); - } - } - return super.visitAnnotation(node); - } - - @Override - public boolean visitCatchClause(UCatchClause node) { - List list = mNodePsiTypeDetectors.get(UCatchClause.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitCatchClause(node); - } - } - return super.visitCatchClause(node); - } - - @Override - public boolean visitMethod(UMethod node) { - List list = mNodePsiTypeDetectors.get(UMethod.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitMethod(node); - } - } - return super.visitMethod(node); - } - - @Override - public boolean visitVariable(UVariable node) { - List list = mNodePsiTypeDetectors.get(UVariable.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitVariable(node); - } - } - return super.visitVariable(node); - } - - @Override - public boolean visitFile(UFile node) { - List list = mNodePsiTypeDetectors.get(UFile.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitFile(node); - } - } - return super.visitFile(node); - } - - @Override - public boolean visitImportStatement(UImportStatement node) { - List list = mNodePsiTypeDetectors.get(UImportStatement.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitImportStatement(node); - } - } - return super.visitImportStatement(node); - } - - @Override - public boolean visitElement(UElement node) { - List list = mNodePsiTypeDetectors.get(UElement.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitElement(node); - } - } - return super.visitElement(node); - } - - @Override - public boolean visitClass(UClass node) { - List list = mNodePsiTypeDetectors.get(UClass.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitClass(node); - } - } - return super.visitClass(node); - } - - @Override - public boolean visitInitializer(UClassInitializer node) { - List list = mNodePsiTypeDetectors.get(UClassInitializer.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitInitializer(node); - } - } - return super.visitInitializer(node); - } - - @Override - public boolean visitLabeledExpression(ULabeledExpression node) { - List list = mNodePsiTypeDetectors.get(ULabeledExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitLabeledExpression(node); - } - } - return super.visitLabeledExpression(node); - } - - @Override - public boolean visitBlockExpression(UBlockExpression node) { - List list = mNodePsiTypeDetectors.get(UBlockExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitBlockExpression(node); - } - } - return super.visitBlockExpression(node); - } - - @Override - public boolean visitCallExpression(UCallExpression node) { - List list = mNodePsiTypeDetectors.get(UCallExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitCallExpression(node); - } - } - return super.visitCallExpression(node); - } - - @Override - public boolean visitBinaryExpression(UBinaryExpression node) { - List list = mNodePsiTypeDetectors.get(UBinaryExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitBinaryExpression(node); - } - } - return super.visitBinaryExpression(node); - } - - @Override - public boolean visitBinaryExpressionWithType(UBinaryExpressionWithType node) { - List list = mNodePsiTypeDetectors.get(UBinaryExpressionWithType.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitBinaryExpressionWithType(node); - } - } - return super.visitBinaryExpressionWithType(node); - } - - @Override - public boolean visitParenthesizedExpression(UParenthesizedExpression node) { - List list = mNodePsiTypeDetectors.get(UParenthesizedExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitParenthesizedExpression(node); - } - } - return super.visitParenthesizedExpression(node); - } - - @Override - public boolean visitUnaryExpression(UUnaryExpression node) { - List list = mNodePsiTypeDetectors.get(UUnaryExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitUnaryExpression(node); - } - } - return super.visitUnaryExpression(node); - } - - @Override - public boolean visitPrefixExpression(UPrefixExpression node) { - List list = mNodePsiTypeDetectors.get(UPrefixExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitPrefixExpression(node); - } - } - return super.visitPrefixExpression(node); - } - - @Override - public boolean visitPostfixExpression(UPostfixExpression node) { - List list = mNodePsiTypeDetectors.get(UPostfixExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitPostfixExpression(node); - } - } - return super.visitPostfixExpression(node); - } - - @Override - public boolean visitIfExpression(UIfExpression node) { - List list = mNodePsiTypeDetectors.get(UIfExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitIfExpression(node); - } - } - return super.visitIfExpression(node); - } - - @Override - public boolean visitSwitchExpression(USwitchExpression node) { - List list = mNodePsiTypeDetectors.get(USwitchExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitSwitchExpression(node); - } - } - return super.visitSwitchExpression(node); - } - - @Override - public boolean visitSwitchClauseExpression(USwitchClauseExpression node) { - List list = mNodePsiTypeDetectors.get(USwitchClauseExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitSwitchClauseExpression(node); - } - } - return super.visitSwitchClauseExpression(node); - } - - @Override - public boolean visitWhileExpression(UWhileExpression node) { - List list = mNodePsiTypeDetectors.get(UWhileExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitWhileExpression(node); - } - } - return super.visitWhileExpression(node); - } - - @Override - public boolean visitDoWhileExpression(UDoWhileExpression node) { - List list = mNodePsiTypeDetectors.get(UDoWhileExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitDoWhileExpression(node); - } - } - return super.visitDoWhileExpression(node); - } - - @Override - public boolean visitForExpression(UForExpression node) { - List list = mNodePsiTypeDetectors.get(UForExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitForExpression(node); - } - } - return super.visitForExpression(node); - } - - @Override - public boolean visitForEachExpression(UForEachExpression node) { - List list = mNodePsiTypeDetectors.get(UForEachExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitForEachExpression(node); - } - } - return super.visitForEachExpression(node); - } - - @Override - public boolean visitTryExpression(UTryExpression node) { - List list = mNodePsiTypeDetectors.get(UTryExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitTryExpression(node); - } - } - return super.visitTryExpression(node); - } - - @Override - public boolean visitLiteralExpression(ULiteralExpression node) { - List list = mNodePsiTypeDetectors.get(ULiteralExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitLiteralExpression(node); - } - } - return super.visitLiteralExpression(node); - } - - @Override - public boolean visitThisExpression(UThisExpression node) { - List list = mNodePsiTypeDetectors.get(UThisExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitThisExpression(node); - } - } - return super.visitThisExpression(node); - } - - @Override - public boolean visitSuperExpression(USuperExpression node) { - List list = mNodePsiTypeDetectors.get(USuperExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitSuperExpression(node); - } - } - return super.visitSuperExpression(node); - } - - @Override - public boolean visitReturnExpression(UReturnExpression node) { - List list = mNodePsiTypeDetectors.get(UReturnExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitReturnExpression(node); - } - } - return super.visitReturnExpression(node); - } - - @Override - public boolean visitBreakExpression(UBreakExpression node) { - List list = mNodePsiTypeDetectors.get(UBreakExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitBreakExpression(node); - } - } - return super.visitBreakExpression(node); - } - - @Override - public boolean visitContinueExpression(UContinueExpression node) { - List list = mNodePsiTypeDetectors.get(UContinueExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitContinueExpression(node); - } - } - return super.visitContinueExpression(node); - } - - @Override - public boolean visitThrowExpression(UThrowExpression node) { - List list = mNodePsiTypeDetectors.get(UThrowExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitThrowExpression(node); - } - } - return super.visitThrowExpression(node); - } - - @Override - public boolean visitArrayAccessExpression(UArrayAccessExpression node) { - List list = mNodePsiTypeDetectors.get(UArrayAccessExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitArrayAccessExpression(node); - } - } - return super.visitArrayAccessExpression(node); - } - - @Override - public boolean visitCallableReferenceExpression(UCallableReferenceExpression node) { - List list = mNodePsiTypeDetectors.get(UCallableReferenceExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitCallableReferenceExpression(node); - } - } - return super.visitCallableReferenceExpression(node); - } - - @Override - public boolean visitClassLiteralExpression(UClassLiteralExpression node) { - List list = mNodePsiTypeDetectors.get(UClassLiteralExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitClassLiteralExpression(node); - } - } - return super.visitClassLiteralExpression(node); - } - - @Override - public boolean visitLambdaExpression(ULambdaExpression node) { - List list = mNodePsiTypeDetectors.get(ULambdaExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitLambdaExpression(node); - } - } - return super.visitLambdaExpression(node); - } - - @Override - public boolean visitObjectLiteralExpression(UObjectLiteralExpression node) { - List list = mNodePsiTypeDetectors.get(UObjectLiteralExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitObjectLiteralExpression(node); - } - } - return super.visitObjectLiteralExpression(node); - } - - @Override - public boolean visitExpressionList(UExpressionList node) { - List list = mNodePsiTypeDetectors.get(UExpressionList.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitExpressionList(node); - } - } - return super.visitExpressionList(node); - } - - @Override - public boolean visitTypeReferenceExpression(UTypeReferenceExpression node) { - List list = mNodePsiTypeDetectors.get(UTypeReferenceExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitTypeReferenceExpression(node); - } - } - return super.visitTypeReferenceExpression(node); - } - - @Override - public boolean visitSimpleNameReferenceExpression(USimpleNameReferenceExpression node) { - List list = mNodePsiTypeDetectors.get(USimpleNameReferenceExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitSimpleNameReferenceExpression(node); - } - } - return super.visitSimpleNameReferenceExpression(node); - } - - @Override - public boolean visitQualifiedReferenceExpression(UQualifiedReferenceExpression node) { - List list = mNodePsiTypeDetectors.get(UQualifiedReferenceExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitQualifiedReferenceExpression(node); - } - } - return super.visitQualifiedReferenceExpression(node); - } - - @Override - public boolean visitDeclarationsExpression(UDeclarationsExpression node) { - List list = mNodePsiTypeDetectors.get(UDeclarationsExpression.class); - if (list != null) { - for (VisitingDetector v : list) { - v.getVisitor().visitDeclarationsExpression(node); - } - } - return super.visitDeclarationsExpression(node); - } - } - - /** Performs common AST searches for method calls and R-type-field references. - * Note that this is a specialized form of the {@link DispatchPsiVisitor}. */ - private class DelegatingPsiVisitor extends DispatchPsiVisitor { - private final JavaContext mContext; - private final boolean mVisitResources; - private final boolean mVisitMethods; - private final boolean mVisitConstructors; - private final boolean mVisitReferences; - - DelegatingPsiVisitor(JavaContext context) { - mContext = context; - - mVisitMethods = !mMethodDetectors.isEmpty(); - mVisitConstructors = !mConstructorDetectors.isEmpty(); - mVisitResources = !mResourceFieldDetectors.isEmpty(); - mVisitReferences = !mReferenceDetectors.isEmpty(); - } - - @Override - public boolean visitSimpleNameReferenceExpression(USimpleNameReferenceExpression node) { - if (mVisitReferences || mVisitResources) { - ProgressManager.checkCanceled(); - } - - if (mVisitReferences) { - List list = mReferenceDetectors.get(node.getIdentifier()); - if (list != null) { - PsiElement referenced = node.resolve(); - if (referenced != null) { - for (VisitingDetector v : list) { - UastScanner uastScanner = v.getUastScanner(); - if (uastScanner != null) { - uastScanner.visitReference(mContext, v.getVisitor(), - node, referenced); - } - } - } - } - } - - if (mVisitResources) { - AndroidReference androidReference = UastLintUtils.toAndroidReferenceViaResolve(node); - if (androidReference != null) { - for (VisitingDetector v : mResourceFieldDetectors) { - UastScanner uastScanner = v.getUastScanner(); - if (uastScanner != null) { - uastScanner.visitResourceReference(mContext, v.getVisitor(), - androidReference.node, - androidReference.getType(), - androidReference.getName(), - androidReference.getPackage().equals(ANDROID_PKG)); - } - } - } - } - - return super.visitSimpleNameReferenceExpression(node); - } - - @Override - public boolean visitCallExpression(UCallExpression node) { - boolean result = super.visitCallExpression(node); - - ProgressManager.checkCanceled(); - - if (UastExpressionUtils.isMethodCall(node)) { - visitMethodCallExpression(node); - } else if (UastExpressionUtils.isConstructorCall(node)) { - visitNewExpression(node); - } - - return result; - } - - private void visitMethodCallExpression(UCallExpression node) { - if (mVisitMethods) { - String methodName = node.getMethodName(); - if (methodName != null) { - List list = mMethodDetectors.get(methodName); - if (list != null) { - PsiMethod function = node.resolve(); - if (function != null) { - for (VisitingDetector v : list) { - UastScanner scanner = v.getUastScanner(); - if (scanner != null) { - scanner.visitMethod(mContext, v.getVisitor(), node, - mContext.getUastContext().getMethod(function)); - } - } - } - } - } - } - } - - private void visitNewExpression(UCallExpression node) { - if (mVisitConstructors) { - PsiMethod resolvedConstructor = node.resolve(); - if (resolvedConstructor == null) { - return; - } - - PsiClass resolvedClass = resolvedConstructor.getContainingClass(); - if (resolvedClass != null) { - List list = mConstructorDetectors.get( - resolvedClass.getQualifiedName()); - if (list != null) { - for (VisitingDetector v : list) { - UastScanner javaPsiScanner = v.getUastScanner(); - if (javaPsiScanner != null) { - javaPsiScanner.visitConstructor(mContext, - v.getVisitor(), node, - mContext.getUastContext().getMethod(resolvedConstructor)); - } - } - } - } - } - } - } -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/UastLintUtils.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/client/api/UastLintUtils.java.173 deleted file mode 100644 index 84922d24063..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/UastLintUtils.java.173 +++ /dev/null @@ -1,338 +0,0 @@ -/* - * Copyright (C) 2016 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.client.api; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.resources.ResourceType; -import com.android.tools.klint.detector.api.ConstantEvaluator; -import com.android.tools.klint.detector.api.JavaContext; -import com.google.common.base.Joiner; -import com.intellij.psi.*; - -import org.jetbrains.uast.*; -import org.jetbrains.uast.UReferenceExpression; -import org.jetbrains.uast.java.JavaAbstractUExpression; -import org.jetbrains.uast.java.JavaUDeclarationsExpression; - -import java.util.Collections; -import java.util.List; - -public class UastLintUtils { - @Nullable - public static String getQualifiedName(PsiElement element) { - if (element instanceof PsiClass) { - return ((PsiClass) element).getQualifiedName(); - } else if (element instanceof PsiMethod) { - PsiClass containingClass = ((PsiMethod) element).getContainingClass(); - if (containingClass == null) { - return null; - } - String containingClassFqName = getQualifiedName(containingClass); - if (containingClassFqName == null) { - return null; - } - return containingClassFqName + "." + ((PsiMethod) element).getName(); - } else if (element instanceof PsiField) { - PsiClass containingClass = ((PsiField) element).getContainingClass(); - if (containingClass == null) { - return null; - } - String containingClassFqName = getQualifiedName(containingClass); - if (containingClassFqName == null) { - return null; - } - return containingClassFqName + "." + ((PsiField) element).getName(); - } else { - return null; - } - } - - @Nullable - public static PsiElement resolve(ExternalReferenceExpression expression, UElement context) { - UDeclaration declaration = UastUtils.getParentOfType(context, UDeclaration.class); - if (declaration == null) { - return null; - } - - return expression.resolve(declaration.getPsi()); - } - - @NonNull - public static String getClassName(PsiClassType type) { - PsiClass psiClass = type.resolve(); - if (psiClass == null) { - return type.getClassName(); - } else { - return getClassName(psiClass); - } - } - - @NonNull - public static String getClassName(PsiClass psiClass) { - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append(psiClass.getName()); - psiClass = psiClass.getContainingClass(); - while (psiClass != null) { - stringBuilder.insert(0, psiClass.getName() + "."); - psiClass = psiClass.getContainingClass(); - } - return stringBuilder.toString(); - } - - @Nullable - public static UExpression findLastAssignment( - @NonNull PsiVariable variable, - @NonNull UElement call, - @NonNull JavaContext context) { - UElement lastAssignment = null; - - if (variable instanceof UVariable) { - variable = ((UVariable) variable).getPsi(); - } - - if (!variable.hasModifierProperty(PsiModifier.FINAL) && - (variable instanceof PsiLocalVariable || variable instanceof PsiParameter)) { - UMethod containingFunction = UastUtils.getContainingUMethod(call); - if (containingFunction != null) { - ConstantEvaluator.LastAssignmentFinder finder = - new ConstantEvaluator.LastAssignmentFinder(variable, call, context, null, -1); - containingFunction.accept(finder); - lastAssignment = finder.getLastAssignment(); - } - } else { - lastAssignment = context.getUastContext().getInitializerBody(variable); - } - - if (lastAssignment instanceof UExpression) { - return (UExpression) lastAssignment; - } - - return null; - } - - @Nullable - public static String getReferenceName(UReferenceExpression expression) { - if (expression instanceof USimpleNameReferenceExpression) { - return ((USimpleNameReferenceExpression) expression).getIdentifier(); - } else if (expression instanceof UQualifiedReferenceExpression) { - UExpression selector = ((UQualifiedReferenceExpression) expression).getSelector(); - if (selector instanceof USimpleNameReferenceExpression) { - return ((USimpleNameReferenceExpression) selector).getIdentifier(); - } - } - - return null; - } - - @Nullable - public static Object findLastValue( - @NonNull PsiVariable variable, - @NonNull UElement call, - @NonNull JavaContext context, - @NonNull ConstantEvaluator evaluator) { - Object value = null; - - if (!variable.hasModifierProperty(PsiModifier.FINAL) && - (variable instanceof PsiLocalVariable || variable instanceof PsiParameter)) { - UMethod containingFunction = UastUtils.getContainingUMethod(call); - if (containingFunction != null) { - ConstantEvaluator.LastAssignmentFinder - finder = new ConstantEvaluator.LastAssignmentFinder( - variable, call, context, evaluator, 1); - containingFunction.getUastBody().accept(finder); - value = finder.getCurrentValue(); - } - } else { - UExpression initializer = context.getUastContext().getInitializerBody(variable); - if (initializer != null) { - value = initializer.evaluate(); - } - } - - return value; - } - - @Nullable - private static AndroidReference toAndroidReference(UQualifiedReferenceExpression expression) { - List path = UastUtils.asQualifiedPath(expression); - - String packageNameFromResolved = null; - - PsiClass containingClass = UastUtils.getContainingClass(expression.resolve()); - if (containingClass != null) { - String containingClassFqName = containingClass.getQualifiedName(); - - if (containingClassFqName != null) { - int i = containingClassFqName.lastIndexOf(".R."); - if (i >= 0) { - packageNameFromResolved = containingClassFqName.substring(0, i); - } - } - } - - if (path == null) { - return null; - } - - int size = path.size(); - if (size < 3) { - return null; - } - - String r = path.get(size - 3); - if (!r.equals(SdkConstants.R_CLASS)) { - return null; - } - - String packageName = packageNameFromResolved != null - ? packageNameFromResolved - : Joiner.on('.').join(path.subList(0, size - 3)); - - String type = path.get(size - 2); - String name = path.get(size - 1); - - ResourceType resourceType = null; - for (ResourceType value : ResourceType.values()) { - if (value.getName().equals(type)) { - resourceType = value; - break; - } - } - - if (resourceType == null) { - return null; - } - - return new AndroidReference(expression, packageName, resourceType, name); - } - - - @Nullable - public static AndroidReference toAndroidReferenceViaResolve(UElement element) { - if (element instanceof UQualifiedReferenceExpression - && element instanceof JavaAbstractUExpression) { - AndroidReference ref = toAndroidReference((UQualifiedReferenceExpression) element); - if (ref != null) { - return ref; - } - } - - PsiElement declaration; - if (element instanceof UVariable) { - declaration = ((UVariable) element).getPsi(); - } else if (element instanceof UResolvable) { - declaration = ((UResolvable) element).resolve(); - } else { - return null; - } - - if (declaration == null && element instanceof USimpleNameReferenceExpression - && element instanceof JavaAbstractUExpression) { - // R class can't be resolved in tests so we need to use heuristics to calc the reference - UExpression maybeQualified = UastUtils.getQualifiedParentOrThis((UExpression) element); - if (maybeQualified instanceof UQualifiedReferenceExpression) { - AndroidReference ref = toAndroidReference( - (UQualifiedReferenceExpression) maybeQualified); - if (ref != null) { - return ref; - } - } - } - - if (!(declaration instanceof PsiVariable)) { - return null; - } - - PsiVariable variable = (PsiVariable) declaration; - if (!(variable instanceof PsiField) - || variable.getType() != PsiType.INT - || !variable.hasModifierProperty(PsiModifier.STATIC) - || !variable.hasModifierProperty(PsiModifier.FINAL)) { - return null; - } - - PsiClass resTypeClass = ((PsiField) variable).getContainingClass(); - if (resTypeClass == null || !resTypeClass.hasModifierProperty(PsiModifier.STATIC)) { - return null; - } - - PsiClass rClass = resTypeClass.getContainingClass(); - if (rClass == null || rClass.getContainingClass() != null || !"R".equals(rClass.getName())) { - return null; - } - - String packageName = ((PsiJavaFile) rClass.getContainingFile()).getPackageName(); - if (packageName.isEmpty()) { - return null; - } - - String resourceTypeName = resTypeClass.getName(); - ResourceType resourceType = null; - for (ResourceType value : ResourceType.values()) { - if (value.getName().equals(resourceTypeName)) { - resourceType = value; - break; - } - } - - if (resourceType == null) { - return null; - } - - String resourceName = variable.getName(); - - UExpression node; - if (element instanceof UExpression) { - node = (UExpression) element; - } else if (element instanceof UVariable) { - node = new JavaUDeclarationsExpression( - null, Collections.singletonList(((UVariable) element))); - } else { - throw new IllegalArgumentException("element must be an expression or an UVariable"); - } - - return new AndroidReference(node, packageName, resourceType, resourceName); - } - - public static boolean areIdentifiersEqual(UExpression first, UExpression second) { - String firstIdentifier = getIdentifier(first); - String secondIdentifier = getIdentifier(second); - return firstIdentifier != null && secondIdentifier != null - && firstIdentifier.equals(secondIdentifier); - } - - @Nullable - public static String getIdentifier(UExpression expression) { - if (expression instanceof ULiteralExpression) { - expression.asRenderString(); - } else if (expression instanceof USimpleNameReferenceExpression) { - return ((USimpleNameReferenceExpression) expression).getIdentifier(); - } else if (expression instanceof UQualifiedReferenceExpression) { - UQualifiedReferenceExpression qualified = (UQualifiedReferenceExpression) expression; - String receiverIdentifier = getIdentifier(qualified.getReceiver()); - String selectorIdentifier = getIdentifier(qualified.getSelector()); - if (receiverIdentifier == null || selectorIdentifier == null) { - return null; - } - return receiverIdentifier + "." + selectorIdentifier; - } - - return null; - } -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/XmlParser.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/client/api/XmlParser.java.173 deleted file mode 100644 index 4a50c67d571..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/client/api/XmlParser.java.173 +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (C) 2011 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.client.api; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.tools.klint.detector.api.Context; -import com.android.tools.klint.detector.api.Location; -import com.android.tools.klint.detector.api.XmlContext; -import com.google.common.annotations.Beta; - -import org.w3c.dom.Attr; -import org.w3c.dom.Document; -import org.w3c.dom.Node; - -/** - * A wrapper for an XML parser. This allows tools integrating lint to map directly - * to builtin services, such as already-parsed data structures in XML editors. - *

- * NOTE: This is not a public or final API; if you rely on this be prepared - * to adjust your code for the next tools release. - */ -@Beta -public abstract class XmlParser { - /** - * Parse the file pointed to by the given context and return as a Document - * - * @param context the context pointing to the file to be parsed, typically - * via {@link Context#getContents()} but the file handle ( - * {@link Context#file} can also be used to map to an existing - * editor buffer in the surrounding tool, etc) - * @return the parsed DOM document, or null if parsing fails - */ - @Nullable - public abstract Document parseXml(@NonNull XmlContext context); - - /** - * Returns a {@link Location} for the given DOM node - * - * @param context information about the file being parsed - * @param node the node to create a location for - * @return a location for the given node - */ - @NonNull - public abstract Location getLocation(@NonNull XmlContext context, @NonNull Node node); - - /** - * Returns a {@link Location} for the given DOM node. Like - * {@link #getLocation(XmlContext, Node)}, but allows a position range that - * is a subset of the node range. - * - * @param context information about the file being parsed - * @param node the node to create a location for - * @param start the starting position within the node, inclusive - * @param end the ending position within the node, exclusive - * @return a location for the given node - */ - @NonNull - public abstract Location getLocation(@NonNull XmlContext context, @NonNull Node node, - int start, int end); - - /** - * Returns a {@link Location} for the given DOM node - * - * @param context information about the file being parsed - * @param node the node to create a location for - * @return a location for the given node - */ - @NonNull - public abstract Location getNameLocation(@NonNull XmlContext context, @NonNull Node node); - - /** - * Returns a {@link Location} for the given DOM node - * - * @param context information about the file being parsed - * @param node the node to create a location for - * @return a location for the given node - */ - @NonNull - public abstract Location getValueLocation(@NonNull XmlContext context, @NonNull Attr node); - - /** - * Creates a light-weight handle to a location for the given node. It can be - * turned into a full fledged location by - * {@link com.android.tools.lint.detector.api.Location.Handle#resolve()}. - * - * @param context the context providing the node - * @param node the node (element or attribute) to create a location handle - * for - * @return a location handle - */ - @NonNull - public abstract Location.Handle createLocationHandle(@NonNull XmlContext context, - @NonNull Node node); - - /** - * Dispose any data structures held for the given context. - * @param context information about the file previously parsed - * @param document the document that was parsed and is now being disposed - */ - public void dispose(@NonNull XmlContext context, @NonNull Document document) { - } - - /** - * Returns the start offset of the given node, or -1 if not known - * - * @param context the context providing the node - * @param node the node (element or attribute) to create a location handle - * for - * @return the start offset, or -1 if not known - */ - public abstract int getNodeStartOffset(@NonNull XmlContext context, @NonNull Node node); - - /** - * Returns the end offset of the given node, or -1 if not known - * - * @param context the context providing the node - * @param node the node (element or attribute) to create a location handle - * for - * @return the end offset, or -1 if not known - */ - public abstract int getNodeEndOffset(@NonNull XmlContext context, @NonNull Node node); -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/Category.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/Category.java.173 deleted file mode 100644 index 8bcb56a39ff..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/Category.java.173 +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (C) 2011 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.detector.api; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.google.common.annotations.Beta; - -/** - * A category is a container for related issues. - *

- * NOTE: This is not a public or final API; if you rely on this be prepared - * to adjust your code for the next tools release. - */ -@Beta -public final class Category implements Comparable { - private final String mName; - private final int mPriority; - private final Category mParent; - - /** - * Creates a new {@link Category}. - * - * @param parent the name of a parent category, or null - * @param name the name of the category - * @param priority a sorting priority, with higher being more important - */ - private Category( - @Nullable Category parent, - @NonNull String name, - int priority) { - mParent = parent; - mName = name; - mPriority = priority; - } - - /** - * Creates a new top level {@link Category} with the given sorting priority. - * - * @param name the name of the category - * @param priority a sorting priority, with higher being more important - * @return a new category - */ - @NonNull - public static Category create(@NonNull String name, int priority) { - return new Category(null, name, priority); - } - - /** - * Creates a new top level {@link Category} with the given sorting priority. - * - * @param parent the name of a parent category, or null - * @param name the name of the category - * @param priority a sorting priority, with higher being more important - * @return a new category - */ - @NonNull - public static Category create(@Nullable Category parent, @NonNull String name, int priority) { - return new Category(parent, name, priority); - } - - /** - * Returns the parent category, or null if this is a top level category - * - * @return the parent category, or null if this is a top level category - */ - public Category getParent() { - return mParent; - } - - /** - * Returns the name of this category - * - * @return the name of this category - */ - public String getName() { - return mName; - } - - /** - * Returns a full name for this category. For a top level category, this is just - * the {@link #getName()} value, but for nested categories it will include the parent - * names as well. - * - * @return a full name for this category - */ - public String getFullName() { - if (mParent != null) { - return mParent.getFullName() + ':' + mName; - } else { - return mName; - } - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - Category category = (Category) o; - - //noinspection SimplifiableIfStatement - if (!mName.equals(category.mName)) { - return false; - } - return mParent != null ? mParent.equals(category.mParent) : category.mParent == null; - - } - - @Override - public String toString() { - return getFullName(); - } - - @Override - public int hashCode() { - return mName.hashCode(); - } - - @Override - public int compareTo(@NonNull Category other) { - if (other.mPriority == mPriority) { - if (mParent == other) { - return 1; - } else if (other.mParent == this) { - return -1; - } - } - - int delta = other.mPriority - mPriority; - if (delta != 0) { - return delta; - } - - return mName.compareTo(other.mName); - } - - /** Issues related to running lint itself */ - public static final Category LINT = create("Lint", 110); - - /** Issues related to correctness */ - public static final Category CORRECTNESS = create("Correctness", 100); - - /** Issues related to security */ - public static final Category SECURITY = create("Security", 90); - - /** Issues related to performance */ - public static final Category PERFORMANCE = create("Performance", 80); - - /** Issues related to usability */ - public static final Category USABILITY = create("Usability", 70); - - /** Issues related to accessibility */ - public static final Category A11Y = create("Accessibility", 60); - - /** Issues related to internationalization */ - public static final Category I18N = create("Internationalization", 50); - - // Sub categories - - /** Issues related to icons */ - public static final Category ICONS = create(USABILITY, "Icons", 73); - - /** Issues related to typography */ - public static final Category TYPOGRAPHY = create(USABILITY, "Typography", 76); - - /** Issues related to messages/strings */ - public static final Category MESSAGES = create(CORRECTNESS, "Messages", 95); - - /** Issues related to right to left and bidirectional text support */ - public static final Category RTL = create(I18N, "Bidirectional Text", 40); -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/ClassContext.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/ClassContext.java.173 deleted file mode 100644 index 07759bd97dd..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/ClassContext.java.173 +++ /dev/null @@ -1,725 +0,0 @@ -/* - * Copyright (C) 2011 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.detector.api; - -import static com.android.SdkConstants.CONSTRUCTOR_NAME; -import static com.android.SdkConstants.DOT_CLASS; -import static com.android.SdkConstants.DOT_JAVA; -import static com.android.tools.klint.detector.api.Location.SearchDirection.BACKWARD; -import static com.android.tools.klint.detector.api.Location.SearchDirection.EOL_BACKWARD; -import static com.android.tools.klint.detector.api.Location.SearchDirection.FORWARD; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.tools.klint.client.api.LintDriver; -import com.android.tools.klint.detector.api.Location.SearchDirection; -import com.android.tools.klint.detector.api.Location.SearchHints; -import com.google.common.annotations.Beta; -import com.google.common.base.Splitter; - -import org.jetbrains.org.objectweb.asm.Type; -import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode; -import org.jetbrains.org.objectweb.asm.tree.ClassNode; -import org.jetbrains.org.objectweb.asm.tree.FieldNode; -import org.jetbrains.org.objectweb.asm.tree.LineNumberNode; -import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode; -import org.jetbrains.org.objectweb.asm.tree.MethodNode; - -import java.io.File; -import java.util.List; - -/** - * A {@link Context} used when checking .class files. - *

- * NOTE: This is not a public or final API; if you rely on this be prepared - * to adjust your code for the next tools release. - */ -@Beta -public class ClassContext extends Context { - private final File mBinDir; - /** The class file DOM root node */ - private final ClassNode mClassNode; - /** The class file byte data */ - private final byte[] mBytes; - /** The source file, if known/found */ - private File mSourceFile; - /** The contents of the source file, if source file is known/found */ - private String mSourceContents; - /** Whether we've searched for the source file (used to avoid repeated failed searches) */ - private boolean mSearchedForSource; - /** If the file is a relative path within a jar file, this is the jar file, otherwise null */ - private final File mJarFile; - /** Whether this class is part of a library (rather than corresponding to one of the - * source files in this project */ - private final boolean mFromLibrary; - - /** - * Construct a new {@link ClassContext} - * - * @param driver the driver running through the checks - * @param project the project containing the file being checked - * @param main the main project if this project is a library project, or - * null if this is not a library project. The main project is the - * root project of all library projects, not necessarily the - * directly including project. - * @param file the file being checked - * @param jarFile If the file is a relative path within a jar file, this is - * the jar file, otherwise null - * @param binDir the root binary directory containing this .class file. - * @param bytes the bytecode raw data - * @param classNode the bytecode object model - * @param fromLibrary whether this class is from a library rather than part - * of this project - * @param sourceContents initial contents of the Java source, if known, or - * null - */ - public ClassContext( - @NonNull LintDriver driver, - @NonNull Project project, - @Nullable Project main, - @NonNull File file, - @Nullable File jarFile, - @NonNull File binDir, - @NonNull byte[] bytes, - @NonNull ClassNode classNode, - boolean fromLibrary, - @Nullable String sourceContents) { - super(driver, project, main, file); - mJarFile = jarFile; - mBinDir = binDir; - mBytes = bytes; - mClassNode = classNode; - mFromLibrary = fromLibrary; - mSourceContents = sourceContents; - } - - /** - * Returns the raw bytecode data for this class file - * - * @return the byte array containing the bytecode data - */ - @NonNull - public byte[] getBytecode() { - return mBytes; - } - - /** - * Returns the bytecode object model - * - * @return the bytecode object model, never null - */ - @NonNull - public ClassNode getClassNode() { - return mClassNode; - } - - /** - * Returns the jar file, if any. If this is null, the .class file is a real file - * on disk, otherwise it represents a relative path within the jar file. - * - * @return the jar file, or null - */ - @Nullable - public File getJarFile() { - return mJarFile; - } - - /** - * Returns whether this class is part of a library (not this project). - * - * @return true if this class is part of a library - */ - public boolean isFromClassLibrary() { - return mFromLibrary; - } - - /** - * Returns the source file for this class file, if possible. - * - * @return the source file, or null - */ - @Nullable - public File getSourceFile() { - if (mSourceFile == null && !mSearchedForSource) { - mSearchedForSource = true; - - String source = mClassNode.sourceFile; - if (source == null) { - source = file.getName(); - if (source.endsWith(DOT_CLASS)) { - source = source.substring(0, source.length() - DOT_CLASS.length()) + ".kt"; - } - int index = source.indexOf('$'); - if (index != -1) { - source = source.substring(0, index) + ".kt"; - } - } - if (source != null) { - if (mJarFile != null) { - String relative = file.getParent() + File.separator + source; - List sources = getProject().getJavaSourceFolders(); - for (File dir : sources) { - File sourceFile = new File(dir, relative); - if (sourceFile.exists()) { - mSourceFile = sourceFile; - break; - } - } - } else { - // Determine package - String topPath = mBinDir.getPath(); - String parentPath = file.getParentFile().getPath(); - if (parentPath.startsWith(topPath)) { - int start = topPath.length() + 1; - String relative = start > parentPath.length() ? // default package? - "" : parentPath.substring(start); - List sources = getProject().getJavaSourceFolders(); - for (File dir : sources) { - File sourceFile = new File(dir, relative + File.separator + source); - if (sourceFile.exists()) { - mSourceFile = sourceFile; - break; - } - } - } - } - } - } - - return mSourceFile; - } - - /** - * Returns the contents of the source file for this class file, if found. - * - * @return the source contents, or "" - */ - @NonNull - public String getSourceContents() { - if (mSourceContents == null) { - File sourceFile = getSourceFile(); - if (sourceFile != null) { - mSourceContents = getClient().readFile(mSourceFile); - } - - if (mSourceContents == null) { - mSourceContents = ""; - } - } - - return mSourceContents; - } - - /** - * Returns the contents of the source file for this class file, if found. If - * {@code read} is false, do not read the source contents if it has not - * already been read. (This is primarily intended for the lint - * infrastructure; most client code would call {@link #getSourceContents()} - * .) - * - * @param read whether to read the source contents if it has not already - * been initialized - * @return the source contents, which will never be null if {@code read} is - * true, or null if {@code read} is false and the source contents - * hasn't already been read. - */ - @Nullable - public String getSourceContents(boolean read) { - if (read) { - return getSourceContents(); - } else { - return mSourceContents; - } - } - - /** - * Returns a location for the given source line number in this class file's - * source file, if available. - * - * @param line the line number (1-based, which is what ASM uses) - * @param patternStart optional pattern to search for in the source for - * range start - * @param patternEnd optional pattern to search for in the source for range - * end - * @param hints additional hints about the pattern search (provided - * {@code patternStart} is non null) - * @return a location, never null - */ - @NonNull - public Location getLocationForLine(int line, @Nullable String patternStart, - @Nullable String patternEnd, @Nullable SearchHints hints) { - File sourceFile = getSourceFile(); - if (sourceFile != null) { - // ASM line numbers are 1-based, and lint line numbers are 0-based - if (line != -1) { - return Location.create(sourceFile, getSourceContents(), line - 1, - patternStart, patternEnd, hints); - } else { - return Location.create(sourceFile); - } - } - - return Location.create(file); - } - - /** - * Reports an issue. - *

- * Detectors should only call this method if an error applies to the whole class - * scope and there is no specific method or field that applies to the error. - * If so, use - * {@link #report(Issue, MethodNode, AbstractInsnNode, Location, String)} or - * {@link #report(Issue, FieldNode, Location, String)}, such that - * suppress annotations are checked. - * - * @param issue the issue to report - * @param location the location of the issue, or null if not known - * @param message the message for this warning - */ - @Override - public void report( - @NonNull Issue issue, - @NonNull Location location, - @NonNull String message) { - if (mDriver.isSuppressed(issue, mClassNode)) { - return; - } - ClassNode curr = mClassNode; - while (curr != null) { - ClassNode prev = curr; - curr = mDriver.getOuterClassNode(curr); - if (curr != null) { - if (prev.outerMethod != null) { - @SuppressWarnings("rawtypes") // ASM API - List methods = curr.methods; - for (Object m : methods) { - MethodNode method = (MethodNode) m; - if (method.name.equals(prev.outerMethod) - && method.desc.equals(prev.outerMethodDesc)) { - // Found the outer method for this anonymous class; continue - // reporting on it (which will also work its way up the parent - // class hierarchy) - if (method != null && mDriver.isSuppressed(issue, mClassNode, method, - null)) { - return; - } - break; - } - } - } - if (mDriver.isSuppressed(issue, curr)) { - return; - } - } - } - - super.report(issue, location, message); - } - - // Unfortunately, ASMs nodes do not extend a common DOM node type with parent - // pointers, so we have to have multiple methods which pass in each type - // of node (class, method, field) to be checked. - - /** - * Reports an issue applicable to a given method node. - * - * @param issue the issue to report - * @param method the method scope the error applies to. The lint - * infrastructure will check whether there are suppress - * annotations on this method (or its enclosing class) and if so - * suppress the warning without involving the client. - * @param instruction the instruction within the method the error applies - * to. You cannot place annotations on individual method - * instructions (for example, annotations on local variables are - * allowed, but are not kept in the .class file). However, this - * instruction is needed to handle suppressing errors on field - * initializations; in that case, the errors may be reported in - * the {@code } method, but the annotation is found not - * on that method but for the {@link FieldNode}'s. - * @param location the location of the issue, or null if not known - * @param message the message for this warning - */ - public void report( - @NonNull Issue issue, - @Nullable MethodNode method, - @Nullable AbstractInsnNode instruction, - @NonNull Location location, - @NonNull String message) { - if (method != null && mDriver.isSuppressed(issue, mClassNode, method, instruction)) { - return; - } - report(issue, location, message); // also checks the class node - } - - /** - * Reports an issue applicable to a given method node. - * - * @param issue the issue to report - * @param field the scope the error applies to. The lint infrastructure - * will check whether there are suppress annotations on this field (or its enclosing - * class) and if so suppress the warning without involving the client. - * @param location the location of the issue, or null if not known - * @param message the message for this warning - */ - public void report( - @NonNull Issue issue, - @Nullable FieldNode field, - @NonNull Location location, - @NonNull String message) { - if (field != null && mDriver.isSuppressed(issue, field)) { - return; - } - report(issue, location, message); // also checks the class node - } - - /** - * Report an error. - * Like {@link #report(Issue, MethodNode, AbstractInsnNode, Location, String)} but with - * a now-unused data parameter at the end. - * - * @deprecated Use {@link #report(Issue, FieldNode, Location, String)} instead; - * this method is here for custom rule compatibility - */ - @SuppressWarnings("UnusedDeclaration") // Potentially used by external existing custom rules - @Deprecated - public void report( - @NonNull Issue issue, - @Nullable MethodNode method, - @Nullable AbstractInsnNode instruction, - @NonNull Location location, - @NonNull String message, - @SuppressWarnings("UnusedParameters") @Nullable Object data) { - report(issue, method, instruction, location, message); - } - - /** - * Report an error. - * Like {@link #report(Issue, FieldNode, Location, String)} but with - * a now-unused data parameter at the end. - * - * @deprecated Use {@link #report(Issue, FieldNode, Location, String)} instead; - * this method is here for custom rule compatibility - */ - @SuppressWarnings("UnusedDeclaration") // Potentially used by external existing custom rules - @Deprecated - public void report( - @NonNull Issue issue, - @Nullable FieldNode field, - @NonNull Location location, - @NonNull String message, - @SuppressWarnings("UnusedParameters") @Nullable Object data) { - report(issue, field, location, message); - } - - /** - * Finds the line number closest to the given node - * - * @param node the instruction node to get a line number for - * @return the closest line number, or -1 if not known - */ - public static int findLineNumber(@NonNull AbstractInsnNode node) { - AbstractInsnNode curr = node; - - // First search backwards - while (curr != null) { - if (curr.getType() == AbstractInsnNode.LINE) { - return ((LineNumberNode) curr).line; - } - curr = curr.getPrevious(); - } - - // Then search forwards - curr = node; - while (curr != null) { - if (curr.getType() == AbstractInsnNode.LINE) { - return ((LineNumberNode) curr).line; - } - curr = curr.getNext(); - } - - return -1; - } - - /** - * Finds the line number closest to the given method declaration - * - * @param node the method node to get a line number for - * @return the closest line number, or -1 if not known - */ - public static int findLineNumber(@NonNull MethodNode node) { - if (node.instructions != null && node.instructions.size() > 0) { - return findLineNumber(node.instructions.get(0)); - } - - return -1; - } - - /** - * Finds the line number closest to the given class declaration - * - * @param node the method node to get a line number for - * @return the closest line number, or -1 if not known - */ - public static int findLineNumber(@NonNull ClassNode node) { - if (node.methods != null && !node.methods.isEmpty()) { - MethodNode firstMethod = getFirstRealMethod(node); - if (firstMethod != null) { - return findLineNumber(firstMethod); - } - } - - return -1; - } - - /** - * Returns a location for the given {@link ClassNode}, where class node is - * either the top level class, or an inner class, in the current context. - * - * @param classNode the class in the current context - * @return a location pointing to the class declaration, or as close to it - * as possible - */ - @NonNull - public Location getLocation(@NonNull ClassNode classNode) { - // Attempt to find a proper location for this class. This is tricky - // since classes do not have line number entries in the class file; we need - // to find a method, look up the corresponding line number then search - // around it for a suitable tag, such as the class name. - String pattern; - if (isAnonymousClass(classNode.name)) { - pattern = classNode.superName; - } else { - pattern = classNode.name; - } - int index = pattern.lastIndexOf('$'); - if (index != -1) { - pattern = pattern.substring(index + 1); - } - index = pattern.lastIndexOf('/'); - if (index != -1) { - pattern = pattern.substring(index + 1); - } - - return getLocationForLine(findLineNumber(classNode), pattern, null, - SearchHints.create(BACKWARD).matchJavaSymbol()); - } - - @Nullable - private static MethodNode getFirstRealMethod(@NonNull ClassNode classNode) { - // Return the first method in the class for line number purposes. Skip , - // since it's typically not located near the real source of the method. - if (classNode.methods != null) { - @SuppressWarnings("rawtypes") // ASM API - List methods = classNode.methods; - for (Object m : methods) { - MethodNode method = (MethodNode) m; - if (method.name.charAt(0) != '<') { - return method; - } - } - - if (!classNode.methods.isEmpty()) { - return (MethodNode) classNode.methods.get(0); - } - } - - return null; - } - - /** - * Returns a location for the given {@link MethodNode}. - * - * @param methodNode the class in the current context - * @param classNode the class containing the method - * @return a location pointing to the class declaration, or as close to it - * as possible - */ - @NonNull - public Location getLocation(@NonNull MethodNode methodNode, - @NonNull ClassNode classNode) { - // Attempt to find a proper location for this class. This is tricky - // since classes do not have line number entries in the class file; we need - // to find a method, look up the corresponding line number then search - // around it for a suitable tag, such as the class name. - String pattern; - SearchDirection searchMode; - if (methodNode.name.equals(CONSTRUCTOR_NAME)) { - searchMode = EOL_BACKWARD; - if (isAnonymousClass(classNode.name)) { - pattern = classNode.superName.substring(classNode.superName.lastIndexOf('/') + 1); - } else { - pattern = classNode.name.substring(classNode.name.lastIndexOf('$') + 1); - } - } else { - searchMode = BACKWARD; - pattern = methodNode.name; - } - - return getLocationForLine(findLineNumber(methodNode), pattern, null, - SearchHints.create(searchMode).matchJavaSymbol()); - } - - /** - * Returns a location for the given {@link AbstractInsnNode}. - * - * @param instruction the instruction to look up the location for - * @return a location pointing to the instruction, or as close to it - * as possible - */ - @NonNull - public Location getLocation(@NonNull AbstractInsnNode instruction) { - SearchHints hints = SearchHints.create(FORWARD).matchJavaSymbol(); - String pattern = null; - if (instruction instanceof MethodInsnNode) { - MethodInsnNode call = (MethodInsnNode) instruction; - if (call.name.equals(CONSTRUCTOR_NAME)) { - pattern = call.owner; - hints = hints.matchConstructor(); - } else { - pattern = call.name; - } - int index = pattern.lastIndexOf('$'); - if (index != -1) { - pattern = pattern.substring(index + 1); - } - index = pattern.lastIndexOf('/'); - if (index != -1) { - pattern = pattern.substring(index + 1); - } - } - - int line = findLineNumber(instruction); - return getLocationForLine(line, pattern, null, hints); - } - - private static boolean isAnonymousClass(@NonNull String fqcn) { - int lastIndex = fqcn.lastIndexOf('$'); - if (lastIndex != -1 && lastIndex < fqcn.length() - 1) { - if (Character.isDigit(fqcn.charAt(lastIndex + 1))) { - return true; - } - } - return false; - } - - /** - * Converts from a VM owner name (such as foo/bar/Foo$Baz) to a - * fully qualified class name (such as foo.bar.Foo.Baz). - * - * @param owner the owner name to convert - * @return the corresponding fully qualified class name - */ - @NonNull - public static String getFqcn(@NonNull String owner) { - return owner.replace('/', '.').replace('$','.'); - } - - /** - * Computes a user-readable type signature from the given class owner, name - * and description. For example, for owner="foo/bar/Foo$Baz", name="foo", - * description="(I)V", it returns "void foo.bar.Foo.Bar#foo(int)". - * - * @param owner the class name - * @param name the method name - * @param desc the method description - * @return a user-readable string - */ - public static String createSignature(String owner, String name, String desc) { - StringBuilder sb = new StringBuilder(100); - - if (desc != null) { - Type returnType = Type.getReturnType(desc); - sb.append(getTypeString(returnType)); - sb.append(' '); - } - - if (owner != null) { - sb.append(getFqcn(owner)); - } - if (name != null) { - sb.append('#'); - sb.append(name); - if (desc != null) { - Type[] argumentTypes = Type.getArgumentTypes(desc); - if (argumentTypes != null && argumentTypes.length > 0) { - sb.append('('); - boolean first = true; - for (Type type : argumentTypes) { - if (first) { - first = false; - } else { - sb.append(", "); - } - sb.append(getTypeString(type)); - } - sb.append(')'); - } - } - } - - return sb.toString(); - } - - private static String getTypeString(Type type) { - String s = type.getClassName(); - if (s.startsWith("java.lang.")) { //$NON-NLS-1$ - s = s.substring("java.lang.".length()); //$NON-NLS-1$ - } - - return s; - } - - /** - * Computes the internal class name of the given fully qualified class name. - * For example, it converts foo.bar.Foo.Bar into foo/bar/Foo$Bar - * - * @param fqcn the fully qualified class name - * @return the internal class name - */ - @NonNull - public static String getInternalName(@NonNull String fqcn) { - if (fqcn.indexOf('.') == -1) { - return fqcn; - } - - int index = fqcn.indexOf('<'); - if(index != -1) { - fqcn = fqcn.substring(0, index); - } - - // If class name contains $, it's not an ambiguous inner class name. - if (fqcn.indexOf('$') != -1) { - return fqcn.replace('.', '/'); - } - // Let's assume that components that start with Caps are class names. - StringBuilder sb = new StringBuilder(fqcn.length()); - String prev = null; - for (String part : Splitter.on('.').split(fqcn)) { - if (prev != null && !prev.isEmpty()) { - if (Character.isUpperCase(prev.charAt(0))) { - sb.append('$'); - } else { - sb.append('/'); - } - } - sb.append(part); - prev = part; - } - - return sb.toString(); - } -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/ConstantEvaluator.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/ConstantEvaluator.java.173 deleted file mode 100644 index b6d86506dcb..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/ConstantEvaluator.java.173 +++ /dev/null @@ -1,1924 +0,0 @@ -/* - * Copyright (C) 2015 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.detector.api; - -import static com.android.tools.klint.client.api.JavaParser.TYPE_BOOLEAN; -import static com.android.tools.klint.client.api.JavaParser.TYPE_BYTE; -import static com.android.tools.klint.client.api.JavaParser.TYPE_CHAR; -import static com.android.tools.klint.client.api.JavaParser.TYPE_DOUBLE; -import static com.android.tools.klint.client.api.JavaParser.TYPE_FLOAT; -import static com.android.tools.klint.client.api.JavaParser.TYPE_INT; -import static com.android.tools.klint.client.api.JavaParser.TYPE_LONG; -import static com.android.tools.klint.client.api.JavaParser.TYPE_OBJECT; -import static com.android.tools.klint.client.api.JavaParser.TYPE_SHORT; -import static com.android.tools.klint.client.api.JavaParser.TYPE_STRING; -import static com.android.tools.klint.detector.api.JavaContext.getParentOfType; -import static org.jetbrains.uast.UastBinaryExpressionWithTypeKind.TYPE_CAST; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.tools.klint.client.api.JavaParser.ResolvedField; -import com.android.tools.klint.client.api.JavaParser.ResolvedNode; -import com.android.tools.klint.client.api.UastLintUtils; -import com.google.common.collect.Lists; -import com.intellij.psi.JavaTokenType; -import com.intellij.psi.PsiArrayInitializerExpression; -import com.intellij.psi.PsiArrayType; -import com.intellij.psi.PsiAssignmentExpression; -import com.intellij.psi.PsiBinaryExpression; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiClassType; -import com.intellij.psi.PsiConditionalExpression; -import com.intellij.psi.PsiDeclarationStatement; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiExpression; -import com.intellij.psi.PsiExpressionStatement; -import com.intellij.psi.PsiField; -import com.intellij.psi.PsiLiteral; -import com.intellij.psi.PsiLocalVariable; -import com.intellij.psi.PsiNewExpression; -import com.intellij.psi.PsiParenthesizedExpression; -import com.intellij.psi.PsiPrefixExpression; -import com.intellij.psi.PsiPrimitiveType; -import com.intellij.psi.PsiReference; -import com.intellij.psi.PsiReferenceExpression; -import com.intellij.psi.PsiStatement; -import com.intellij.psi.PsiType; -import com.intellij.psi.PsiTypeCastExpression; -import com.intellij.psi.PsiTypeElement; -import com.intellij.psi.PsiVariable; -import com.intellij.psi.tree.IElementType; -import com.intellij.psi.util.PsiTreeUtil; - -import org.jetbrains.uast.*; -import org.jetbrains.uast.UReferenceExpression; -import org.jetbrains.uast.util.UastExpressionUtils; -import org.jetbrains.uast.visitor.AbstractUastVisitor; - -import java.lang.reflect.Array; -import java.util.ArrayList; -import java.util.List; -import java.util.ListIterator; - -import lombok.ast.ArrayCreation; -import lombok.ast.ArrayInitializer; -import lombok.ast.BinaryExpression; -import lombok.ast.BinaryOperator; -import lombok.ast.BooleanLiteral; -import lombok.ast.Cast; -import lombok.ast.CharLiteral; -import lombok.ast.Expression; -import lombok.ast.ExpressionStatement; -import lombok.ast.FloatingPointLiteral; -import lombok.ast.InlineIfExpression; -import lombok.ast.IntegralLiteral; -import lombok.ast.Node; -import lombok.ast.NullLiteral; -import lombok.ast.Select; -import lombok.ast.Statement; -import lombok.ast.StrictListAccessor; -import lombok.ast.StringLiteral; -import lombok.ast.TypeReference; -import lombok.ast.UnaryExpression; -import lombok.ast.UnaryOperator; -import lombok.ast.VariableDeclaration; -import lombok.ast.VariableDefinition; -import lombok.ast.VariableDefinitionEntry; -import lombok.ast.VariableReference; - -/** Evaluates constant expressions */ -public class ConstantEvaluator { - private final JavaContext mContext; - private boolean mAllowUnknown; - - /** - * Creates a new constant evaluator - * - * @param context the context to use to resolve field references, if any - */ - public ConstantEvaluator(@Nullable JavaContext context) { - mContext = context; - } - - /** - * Whether we allow computing values where some terms are unknown. For example, the expression - * {@code "foo" + x + "bar"} would return {@code null} without and {@code "foobar"} with. - * - * @return this for constructor chaining - */ - public ConstantEvaluator allowUnknowns() { - mAllowUnknown = true; - return this; - } - - /** - * Evaluates the given node and returns the constant value it resolves to, if any - * - * @param node the node to compute the constant value for - * @return the corresponding constant value - a String, an Integer, a Float, and so on - * @deprecated Use {@link #evaluate(PsiElement)} instead - */ - @Deprecated - @Nullable - public Object evaluate(@NonNull Node node) { - if (node instanceof NullLiteral) { - return null; - } else if (node instanceof BooleanLiteral) { - return ((BooleanLiteral)node).astValue(); - } else if (node instanceof StringLiteral) { - StringLiteral string = (StringLiteral) node; - return string.astValue(); - } else if (node instanceof CharLiteral) { - return ((CharLiteral)node).astValue(); - } else if (node instanceof IntegralLiteral) { - IntegralLiteral literal = (IntegralLiteral) node; - // Don't combine to ?: since that will promote astIntValue to a long - if (literal.astMarkedAsLong()) { - return literal.astLongValue(); - } else { - return literal.astIntValue(); - } - } else if (node instanceof FloatingPointLiteral) { - FloatingPointLiteral literal = (FloatingPointLiteral) node; - // Don't combine to ?: since that will promote astFloatValue to a double - if (literal.astMarkedAsFloat()) { - return literal.astFloatValue(); - } else { - return literal.astDoubleValue(); - } - } else if (node instanceof UnaryExpression) { - UnaryOperator operator = ((UnaryExpression) node).astOperator(); - Object operand = evaluate(((UnaryExpression) node).astOperand()); - if (operand == null) { - return null; - } - switch (operator) { - case LOGICAL_NOT: - if (operand instanceof Boolean) { - return !(Boolean) operand; - } - break; - case UNARY_PLUS: - return operand; - case BINARY_NOT: - if (operand instanceof Integer) { - return ~(Integer) operand; - } else if (operand instanceof Long) { - return ~(Long) operand; - } else if (operand instanceof Short) { - return ~(Short) operand; - } else if (operand instanceof Character) { - return ~(Character) operand; - } else if (operand instanceof Byte) { - return ~(Byte) operand; - } - break; - case UNARY_MINUS: - if (operand instanceof Integer) { - return -(Integer) operand; - } else if (operand instanceof Long) { - return -(Long) operand; - } else if (operand instanceof Double) { - return -(Double) operand; - } else if (operand instanceof Float) { - return -(Float) operand; - } else if (operand instanceof Short) { - return -(Short) operand; - } else if (operand instanceof Character) { - return -(Character) operand; - } else if (operand instanceof Byte) { - return -(Byte) operand; - } - break; - } - } else if (node instanceof InlineIfExpression) { - InlineIfExpression expression = (InlineIfExpression) node; - Object known = evaluate(expression.astCondition()); - if (known == Boolean.TRUE && expression.astIfTrue() != null) { - return evaluate(expression.astIfTrue()); - } else if (known == Boolean.FALSE && expression.astIfFalse() != null) { - return evaluate(expression.astIfFalse()); - } - } else if (node instanceof BinaryExpression) { - BinaryOperator operator = ((BinaryExpression) node).astOperator(); - Object operandLeft = evaluate(((BinaryExpression) node).astLeft()); - Object operandRight = evaluate(((BinaryExpression) node).astRight()); - if (operandLeft == null || operandRight == null) { - if (mAllowUnknown) { - if (operandLeft == null) { - return operandRight; - } else { - return operandLeft; - } - } - return null; - } - if (operandLeft instanceof String && operandRight instanceof String) { - if (operator == BinaryOperator.PLUS) { - return operandLeft.toString() + operandRight.toString(); - } - return null; - } else if (operandLeft instanceof Boolean && operandRight instanceof Boolean) { - boolean left = (Boolean) operandLeft; - boolean right = (Boolean) operandRight; - switch (operator) { - case LOGICAL_OR: - return left || right; - case LOGICAL_AND: - return left && right; - case BITWISE_OR: - return left | right; - case BITWISE_XOR: - return left ^ right; - case BITWISE_AND: - return left & right; - case EQUALS: - return left == right; - case NOT_EQUALS: - return left != right; - } - } else if (operandLeft instanceof Number && operandRight instanceof Number) { - Number left = (Number) operandLeft; - Number right = (Number) operandRight; - boolean isInteger = - !(left instanceof Float || left instanceof Double - || right instanceof Float || right instanceof Double); - boolean isWide = - isInteger ? (left instanceof Long || right instanceof Long) - : (left instanceof Double || right instanceof Double); - - switch (operator) { - case BITWISE_OR: - if (isWide) { - return left.longValue() | right.longValue(); - } else { - return left.intValue() | right.intValue(); - } - case BITWISE_XOR: - if (isWide) { - return left.longValue() ^ right.longValue(); - } else { - return left.intValue() ^ right.intValue(); - } - case BITWISE_AND: - if (isWide) { - return left.longValue() & right.longValue(); - } else { - return left.intValue() & right.intValue(); - } - case EQUALS: - if (isInteger) { - return left.longValue() == right.longValue(); - } else { - return left.doubleValue() == right.doubleValue(); - } - case NOT_EQUALS: - if (isInteger) { - return left.longValue() != right.longValue(); - } else { - return left.doubleValue() != right.doubleValue(); - } - case GREATER: - if (isInteger) { - return left.longValue() > right.longValue(); - } else { - return left.doubleValue() > right.doubleValue(); - } - case GREATER_OR_EQUAL: - if (isInteger) { - return left.longValue() >= right.longValue(); - } else { - return left.doubleValue() >= right.doubleValue(); - } - case LESS: - if (isInteger) { - return left.longValue() < right.longValue(); - } else { - return left.doubleValue() < right.doubleValue(); - } - case LESS_OR_EQUAL: - if (isInteger) { - return left.longValue() <= right.longValue(); - } else { - return left.doubleValue() <= right.doubleValue(); - } - case SHIFT_LEFT: - if (isWide) { - return left.longValue() << right.intValue(); - } else { - return left.intValue() << right.intValue(); - } - case SHIFT_RIGHT: - if (isWide) { - return left.longValue() >> right.intValue(); - } else { - return left.intValue() >> right.intValue(); - } - case BITWISE_SHIFT_RIGHT: - if (isWide) { - return left.longValue() >>> right.intValue(); - } else { - return left.intValue() >>> right.intValue(); - } - case PLUS: - if (isInteger) { - if (isWide) { - return left.longValue() + right.longValue(); - } else { - return left.intValue() + right.intValue(); - } - } else { - if (isWide) { - return left.doubleValue() + right.doubleValue(); - } else { - return left.floatValue() + right.floatValue(); - } - } - case MINUS: - if (isInteger) { - if (isWide) { - return left.longValue() - right.longValue(); - } else { - return left.intValue() - right.intValue(); - } - } else { - if (isWide) { - return left.doubleValue() - right.doubleValue(); - } else { - return left.floatValue() - right.floatValue(); - } - } - case MULTIPLY: - if (isInteger) { - if (isWide) { - return left.longValue() * right.longValue(); - } else { - return left.intValue() * right.intValue(); - } - } else { - if (isWide) { - return left.doubleValue() * right.doubleValue(); - } else { - return left.floatValue() * right.floatValue(); - } - } - case DIVIDE: - if (isInteger) { - if (isWide) { - return left.longValue() / right.longValue(); - } else { - return left.intValue() / right.intValue(); - } - } else { - if (isWide) { - return left.doubleValue() / right.doubleValue(); - } else { - return left.floatValue() / right.floatValue(); - } - } - case REMAINDER: - if (isInteger) { - if (isWide) { - return left.longValue() % right.longValue(); - } else { - return left.intValue() % right.intValue(); - } - } else { - if (isWide) { - return left.doubleValue() % right.doubleValue(); - } else { - return left.floatValue() % right.floatValue(); - } - } - default: - return null; - } - } - } else if (node instanceof Cast) { - Cast cast = (Cast)node; - Object operandValue = evaluate(cast.astOperand()); - if (operandValue instanceof Number) { - Number number = (Number)operandValue; - String typeName = cast.astTypeReference().getTypeName(); - if (typeName.equals("float")) { - return number.floatValue(); - } else if (typeName.equals("double")) { - return number.doubleValue(); - } else if (typeName.equals("int")) { - return number.intValue(); - } else if (typeName.equals("long")) { - return number.longValue(); - } else if (typeName.equals("short")) { - return number.shortValue(); - } else if (typeName.equals("byte")) { - return number.byteValue(); - } - } - return operandValue; - } else if (mContext != null && (node instanceof VariableReference || - node instanceof Select)) { - ResolvedNode resolved = mContext.resolve(node); - if (resolved instanceof ResolvedField) { - ResolvedField field = (ResolvedField) resolved; - Object value = field.getValue(); - if (value != null) { - return value; - } - Node astNode = field.findAstNode(); - if (astNode instanceof VariableDeclaration) { - VariableDeclaration declaration = (VariableDeclaration) astNode; - VariableDefinition definition = declaration.astDefinition(); - if (definition != null && definition.astModifiers().isFinal()) { - StrictListAccessor variables = - definition.astVariables(); - if (variables.size() == 1) { - VariableDefinitionEntry first = variables.first(); - if (first.astInitializer() != null) { - return evaluate(first.astInitializer()); - } - } - } - } - return null; - } else if (node instanceof VariableReference) { - Statement statement = getParentOfType(node, Statement.class, false); - if (statement != null) { - ListIterator iterator = statement.getParent().getChildren().listIterator(); - while (iterator.hasNext()) { - if (iterator.next() == statement) { - if (iterator.hasPrevious()) { // should always be true - iterator.previous(); - } - break; - } - } - - String targetName = ((VariableReference)node).astIdentifier().astValue(); - while (iterator.hasPrevious()) { - Node previous = iterator.previous(); - if (previous instanceof VariableDeclaration) { - VariableDeclaration declaration = (VariableDeclaration) previous; - VariableDefinition definition = declaration.astDefinition(); - for (VariableDefinitionEntry entry : definition - .astVariables()) { - if (entry.astInitializer() != null - && entry.astName().astValue().equals(targetName)) { - return evaluate(entry.astInitializer()); - } - } - } else if (previous instanceof ExpressionStatement) { - ExpressionStatement expressionStatement = (ExpressionStatement) previous; - Expression expression = expressionStatement.astExpression(); - if (expression instanceof BinaryExpression && - ((BinaryExpression) expression).astOperator() - == BinaryOperator.ASSIGN) { - BinaryExpression binaryExpression = (BinaryExpression) expression; - if (targetName.equals(binaryExpression.astLeft().toString())) { - return evaluate(binaryExpression.astRight()); - } - } - } - } - } - } - } else if (node instanceof ArrayCreation) { - ArrayCreation creation = (ArrayCreation) node; - ArrayInitializer initializer = creation.astInitializer(); - if (initializer != null) { - TypeReference typeReference = creation.astComponentTypeReference(); - StrictListAccessor expressions = initializer - .astExpressions(); - List values = Lists.newArrayListWithExpectedSize(expressions.size()); - Class commonType = null; - for (Expression expression : expressions) { - Object value = evaluate(expression); - if (value != null) { - values.add(value); - if (commonType == null) { - commonType = value.getClass(); - } else { - while (!commonType.isAssignableFrom(value.getClass())) { - commonType = commonType.getSuperclass(); - } - } - } else if (!mAllowUnknown) { - // Inconclusive - return null; - } - } - if (!values.isEmpty()) { - Object o = Array.newInstance(commonType, values.size()); - return values.toArray((Object[]) o); - } else if (mContext != null) { - ResolvedNode type = mContext.resolve(typeReference); - System.out.println(type); - // TODO: return new array of this type - } - } else { - // something like "new byte[3]" but with no initializer. - String type = creation.astComponentTypeReference().toString(); - // TODO: Look up the size and only if small, use it. E.g. if it was byte[3] - // we could return a byte[3] array, but if it's say byte[1024*1024] we don't - // want to do that. - int size = 0; - if (TYPE_BYTE.equals(type)) { - return new byte[size]; - } - if (TYPE_BOOLEAN.equals(type)) { - return new boolean[size]; - } - if (TYPE_INT.equals(type)) { - return new int[size]; - } - if (TYPE_LONG.equals(type)) { - return new long[size]; - } - if (TYPE_CHAR.equals(type)) { - return new char[size]; - } - if (TYPE_FLOAT.equals(type)) { - return new float[size]; - } - if (TYPE_DOUBLE.equals(type)) { - return new double[size]; - } - if (TYPE_STRING.equals(type)) { - //noinspection SSBasedInspection - return new String[size]; - } - if (TYPE_SHORT.equals(type)) { - return new short[size]; - } - if (TYPE_OBJECT.equals(type)) { - //noinspection SSBasedInspection - return new Object[size]; - } - } - } - - // TODO: Check for MethodInvocation and perform some common operations - - // Math.* methods, String utility methods like notNullize, etc - - return null; - } - - /** - * Evaluates the given node and returns the constant value it resolves to, if any - * - * @param node the node to compute the constant value for - * @return the corresponding constant value - a String, an Integer, a Float, and so on - */ - @Nullable - public Object evaluate(@Nullable UElement node) { - if (node == null) { - return null; - } - - if (node instanceof ULiteralExpression) { - return ((ULiteralExpression) node).getValue(); - } else if (node instanceof UPrefixExpression) { - UastPrefixOperator operator = ((UPrefixExpression) node).getOperator(); - Object operand = evaluate(((UPrefixExpression) node).getOperand()); - if (operand == null) { - return null; - } - if (operator == UastPrefixOperator.LOGICAL_NOT) { - if (operand instanceof Boolean) { - return !(Boolean) operand; - } - } else if (operator == UastPrefixOperator.UNARY_PLUS) { - return operand; - } else if (operator == UastPrefixOperator.BITWISE_NOT) { - if (operand instanceof Integer) { - return ~(Integer) operand; - } else if (operand instanceof Long) { - return ~(Long) operand; - } else if (operand instanceof Short) { - return ~(Short) operand; - } else if (operand instanceof Character) { - return ~(Character) operand; - } else if (operand instanceof Byte) { - return ~(Byte) operand; - } - } else if (operator == UastPrefixOperator.UNARY_MINUS) { - if (operand instanceof Integer) { - return -(Integer) operand; - } else if (operand instanceof Long) { - return -(Long) operand; - } else if (operand instanceof Double) { - return -(Double) operand; - } else if (operand instanceof Float) { - return -(Float) operand; - } else if (operand instanceof Short) { - return -(Short) operand; - } else if (operand instanceof Character) { - return -(Character) operand; - } else if (operand instanceof Byte) { - return -(Byte) operand; - } - } - } else if (node instanceof UIfExpression - && ((UIfExpression) node).getExpressionType() != null) { - UIfExpression expression = (UIfExpression) node; - Object known = evaluate(expression.getCondition()); - if (known == Boolean.TRUE && expression.getThenExpression() != null) { - return evaluate(expression.getThenExpression()); - } else if (known == Boolean.FALSE && expression.getElseExpression() != null) { - return evaluate(expression.getElseExpression()); - } - } else if (node instanceof UParenthesizedExpression) { - UParenthesizedExpression parenthesizedExpression = (UParenthesizedExpression) node; - UExpression expression = parenthesizedExpression.getExpression(); - return evaluate(expression); - } else if (node instanceof UBinaryExpression) { - UastBinaryOperator operator = ((UBinaryExpression) node).getOperator(); - Object operandLeft = evaluate(((UBinaryExpression) node).getLeftOperand()); - Object operandRight = evaluate(((UBinaryExpression) node).getRightOperand()); - if (operandLeft == null || operandRight == null) { - if (mAllowUnknown) { - if (operandLeft == null) { - return operandRight; - } else { - return operandLeft; - } - } - return null; - } - if (operandLeft instanceof String && operandRight instanceof String) { - if (operator == UastBinaryOperator.PLUS) { - return operandLeft.toString() + operandRight.toString(); - } - return null; - } else if (operandLeft instanceof Boolean && operandRight instanceof Boolean) { - boolean left = (Boolean) operandLeft; - boolean right = (Boolean) operandRight; - if (operator == UastBinaryOperator.LOGICAL_OR) { - return left || right; - } else if (operator == UastBinaryOperator.LOGICAL_AND) { - return left && right; - } else if (operator == UastBinaryOperator.BITWISE_OR) { - return left | right; - } else if (operator == UastBinaryOperator.BITWISE_XOR) { - return left ^ right; - } else if (operator == UastBinaryOperator.BITWISE_AND) { - return left & right; - } else if (operator == UastBinaryOperator.IDENTITY_EQUALS - || operator == UastBinaryOperator.EQUALS) { - return left == right; - } else if (operator == UastBinaryOperator.IDENTITY_NOT_EQUALS - || operator == UastBinaryOperator.NOT_EQUALS) { - return left != right; - } - } else if (operandLeft instanceof Number && operandRight instanceof Number) { - Number left = (Number) operandLeft; - Number right = (Number) operandRight; - boolean isInteger = - !(left instanceof Float || left instanceof Double - || right instanceof Float || right instanceof Double); - boolean isWide = - isInteger ? (left instanceof Long || right instanceof Long) - : (left instanceof Double || right instanceof Double); - - if (operator == UastBinaryOperator.BITWISE_OR) { - if (isWide) { - return left.longValue() | right.longValue(); - } else { - return left.intValue() | right.intValue(); - } - } else if (operator == UastBinaryOperator.BITWISE_XOR) { - if (isWide) { - return left.longValue() ^ right.longValue(); - } else { - return left.intValue() ^ right.intValue(); - } - } else if (operator == UastBinaryOperator.BITWISE_AND) { - if (isWide) { - return left.longValue() & right.longValue(); - } else { - return left.intValue() & right.intValue(); - } - } else if (operator == UastBinaryOperator.EQUALS - || operator == UastBinaryOperator.IDENTITY_EQUALS) { - if (isInteger) { - return left.longValue() == right.longValue(); - } else { - return left.doubleValue() == right.doubleValue(); - } - } else if (operator == UastBinaryOperator.NOT_EQUALS - || operator == UastBinaryOperator.IDENTITY_NOT_EQUALS) { - if (isInteger) { - return left.longValue() != right.longValue(); - } else { - return left.doubleValue() != right.doubleValue(); - } - } else if (operator == UastBinaryOperator.GREATER) { - if (isInteger) { - return left.longValue() > right.longValue(); - } else { - return left.doubleValue() > right.doubleValue(); - } - } else if (operator == UastBinaryOperator.GREATER_OR_EQUALS) { - if (isInteger) { - return left.longValue() >= right.longValue(); - } else { - return left.doubleValue() >= right.doubleValue(); - } - } else if (operator == UastBinaryOperator.LESS) { - if (isInteger) { - return left.longValue() < right.longValue(); - } else { - return left.doubleValue() < right.doubleValue(); - } - } else if (operator == UastBinaryOperator.LESS_OR_EQUALS) { - if (isInteger) { - return left.longValue() <= right.longValue(); - } else { - return left.doubleValue() <= right.doubleValue(); - } - } else if (operator == UastBinaryOperator.SHIFT_LEFT) { - if (isWide) { - return left.longValue() << right.intValue(); - } else { - return left.intValue() << right.intValue(); - } - } else if (operator == UastBinaryOperator.SHIFT_RIGHT) { - if (isWide) { - return left.longValue() >> right.intValue(); - } else { - return left.intValue() >> right.intValue(); - } - } else if (operator == UastBinaryOperator.UNSIGNED_SHIFT_RIGHT) { - if (isWide) { - return left.longValue() >>> right.intValue(); - } else { - return left.intValue() >>> right.intValue(); - } - } else if (operator == UastBinaryOperator.PLUS) { - if (isInteger) { - if (isWide) { - return left.longValue() + right.longValue(); - } else { - return left.intValue() + right.intValue(); - } - } else { - if (isWide) { - return left.doubleValue() + right.doubleValue(); - } else { - return left.floatValue() + right.floatValue(); - } - } - } else if (operator == UastBinaryOperator.MINUS) { - if (isInteger) { - if (isWide) { - return left.longValue() - right.longValue(); - } else { - return left.intValue() - right.intValue(); - } - } else { - if (isWide) { - return left.doubleValue() - right.doubleValue(); - } else { - return left.floatValue() - right.floatValue(); - } - } - } else if (operator == UastBinaryOperator.MULTIPLY) { - if (isInteger) { - if (isWide) { - return left.longValue() * right.longValue(); - } else { - return left.intValue() * right.intValue(); - } - } else { - if (isWide) { - return left.doubleValue() * right.doubleValue(); - } else { - return left.floatValue() * right.floatValue(); - } - } - } else if (operator == UastBinaryOperator.DIV) { - if (isInteger) { - if (isWide) { - return left.longValue() / right.longValue(); - } else { - return left.intValue() / right.intValue(); - } - } else { - if (isWide) { - return left.doubleValue() / right.doubleValue(); - } else { - return left.floatValue() / right.floatValue(); - } - } - } else if (operator == UastBinaryOperator.MOD) { - if (isInteger) { - if (isWide) { - return left.longValue() % right.longValue(); - } else { - return left.intValue() % right.intValue(); - } - } else { - if (isWide) { - return left.doubleValue() % right.doubleValue(); - } else { - return left.floatValue() % right.floatValue(); - } - } - } else { - return null; - } - } - } else if (node instanceof UBinaryExpressionWithType && - ((UBinaryExpressionWithType) node).getOperationKind() == TYPE_CAST) { - UBinaryExpressionWithType cast = (UBinaryExpressionWithType) node; - Object operandValue = evaluate(cast.getOperand()); - if (operandValue instanceof Number) { - Number number = (Number) operandValue; - PsiType type = cast.getType(); - if (PsiType.FLOAT.equals(type)) { - return number.floatValue(); - } else if (PsiType.DOUBLE.equals(type)) { - return number.doubleValue(); - } else if (PsiType.INT.equals(type)) { - return number.intValue(); - } else if (PsiType.LONG.equals(type)) { - return number.longValue(); - } else if (PsiType.SHORT.equals(type)) { - return number.shortValue(); - } else if (PsiType.BYTE.equals(type)) { - return number.byteValue(); - } - } - return operandValue; - } else if (mContext != null && node instanceof UReferenceExpression) { - PsiElement resolved = ((UReferenceExpression) node).resolve(); - if (resolved instanceof PsiVariable) { - PsiVariable variable = (PsiVariable) resolved; - Object value = UastLintUtils.findLastValue(variable, node, mContext, this); - - if (value != null) { - return value; - } - if (variable.getInitializer() != null) { - return evaluate(variable.getInitializer()); - } - return null; - } - } else if (UastExpressionUtils.isNewArrayWithDimensions((UExpression) node)) { - UCallExpression call = (UCallExpression) node; - PsiType arrayType = call.getExpressionType(); - if (arrayType instanceof PsiArrayType) { - PsiType componentType = ((PsiArrayType) arrayType).getComponentType(); - // Single-dimension array - if (!(componentType instanceof PsiArrayType) - && call.getValueArgumentCount() == 1) { - Object lengthObj = evaluate(call.getValueArguments().get(0)); - if (lengthObj instanceof Number) { - int length = ((Number) lengthObj).intValue(); - if (length > 30) { - length = 30; - } - if (componentType == PsiType.BOOLEAN) { - return new boolean[length]; - } else if (isObjectType(componentType)) { - return new Object[length]; - } else if (componentType == PsiType.CHAR) { - return new char[length]; - } else if (componentType == PsiType.BYTE) { - return new byte[length]; - } else if (componentType == PsiType.DOUBLE) { - return new double[length]; - } else if (componentType == PsiType.FLOAT) { - return new float[length]; - } else if (componentType == PsiType.INT) { - return new int[length]; - } else if (componentType == PsiType.SHORT) { - return new short[length]; - } else if (componentType == PsiType.LONG) { - return new long[length]; - } else if (isStringType(componentType)) { - return new String[length]; - } - } - } - } - } else if (UastExpressionUtils.isNewArrayWithInitializer(node)) { - UCallExpression call = (UCallExpression) node; - PsiType arrayType = call.getExpressionType(); - if (arrayType instanceof PsiArrayType) { - PsiType componentType = ((PsiArrayType) arrayType).getComponentType(); - // Single-dimension array - if (!(componentType instanceof PsiArrayType)) { - int length = call.getValueArgumentCount(); - List evaluatedArgs = new ArrayList(length); - for (UExpression arg : call.getValueArguments()) { - Object evaluatedArg = evaluate(arg); - if (!mAllowUnknown && evaluatedArg == null) { - // Inconclusive - return null; - } - evaluatedArgs.add(evaluatedArg); - } - - if (componentType == PsiType.BOOLEAN) { - boolean[] arr = new boolean[length]; - for (int i = 0; i < length; ++i) { - Object o = evaluatedArgs.get(i); - if (o instanceof Boolean) { - arr[i] = (Boolean) o; - } - } - return arr; - } else if (isObjectType(componentType)) { - Object[] arr = new Object[length]; - for (int i = 0; i < length; ++i) { - arr[i] = evaluatedArgs.get(i); - } - return arr; - } else if (componentType.equals(PsiType.CHAR)) { - char[] arr = new char[length]; - for (int i = 0; i < length; ++i) { - Object o = evaluatedArgs.get(i); - if (o instanceof Character) { - arr[i] = (Character) o; - } - } - return arr; - } else if (componentType.equals(PsiType.BYTE)) { - byte[] arr = new byte[length]; - for (int i = 0; i < length; ++i) { - Object o = evaluatedArgs.get(i); - if (o instanceof Byte) { - arr[i] = (Byte) o; - } - } - return arr; - } else if (componentType.equals(PsiType.DOUBLE)) { - double[] arr = new double[length]; - for (int i = 0; i < length; ++i) { - Object o = evaluatedArgs.get(i); - if (o instanceof Double) { - arr[i] = (Double) o; - } - } - return arr; - } else if (componentType.equals(PsiType.FLOAT)) { - float[] arr = new float[length]; - for (int i = 0; i < length; ++i) { - Object o = evaluatedArgs.get(i); - if (o instanceof Float) { - arr[i] = (Float) o; - } - } - return arr; - } else if (componentType.equals(PsiType.INT)) { - int[] arr = new int[length]; - for (int i = 0; i < length; ++i) { - Object o = evaluatedArgs.get(i); - if (o instanceof Integer) { - arr[i] = (Integer) o; - } - } - return arr; - } else if (componentType.equals(PsiType.SHORT)) { - short[] arr = new short[length]; - for (int i = 0; i < length; ++i) { - Object o = evaluatedArgs.get(i); - if (o instanceof Short) { - arr[i] = (Short) o; - } - } - return arr; - } else if (componentType.equals(PsiType.LONG)) { - long[] arr = new long[length]; - for (int i = 0; i < length; ++i) { - Object o = evaluatedArgs.get(i); - if (o instanceof Long) { - arr[i] = (Long) o; - } - } - return arr; - } else if (isStringType(componentType)) { - String[] arr = new String[length]; - for (int i = 0; i < length; ++i) { - Object o = evaluatedArgs.get(i); - if (o instanceof String) { - arr[i] = (String) o; - } - } - return arr; - } - } - } - } - - if (node instanceof UExpression) { - Object evaluated = ((UExpression) node).evaluate(); - if (evaluated != null) { - return evaluated; - } - } - - // TODO: Check for MethodInvocation and perform some common operations - - // Math.* methods, String utility methods like notNullize, etc - - return null; - } - - private static boolean isStringType(PsiType type) { - if (!(type instanceof PsiClassType)) { - return false; - } - - PsiClass resolvedClass = ((PsiClassType) type).resolve(); - return resolvedClass != null && TYPE_STRING.equals(resolvedClass.getQualifiedName()); - } - - private static boolean isObjectType(PsiType type) { - if (!(type instanceof PsiClassType)) { - return false; - } - - PsiClass resolvedClass = ((PsiClassType) type).resolve(); - return resolvedClass != null && TYPE_OBJECT.equals(resolvedClass.getQualifiedName()); - } - - public static class LastAssignmentFinder extends AbstractUastVisitor { - private final PsiVariable mVariable; - private final UElement mEndAt; - - private final ConstantEvaluator mConstantEvaluator; - - private boolean mDone = false; - private int mCurrentLevel = 0; - private int mVariableLevel = -1; - private Object mCurrentValue; - private UElement mLastAssignment; - - public LastAssignmentFinder( - @NonNull PsiVariable variable, - @NonNull UElement endAt, - @NonNull JavaContext context, - @Nullable ConstantEvaluator constantEvaluator, - int variableLevel) { - mVariable = variable; - mEndAt = endAt; - UExpression initializer = context.getUastContext().getInitializerBody(variable); - mLastAssignment = initializer; - mConstantEvaluator = constantEvaluator; - if (initializer != null && constantEvaluator != null) { - mCurrentValue = constantEvaluator.evaluate(initializer); - } - this.mVariableLevel = variableLevel; - } - - @Nullable - public Object getCurrentValue() { - return mCurrentValue; - } - - @Nullable - public UElement getLastAssignment() { - return mLastAssignment; - } - - @Override - public boolean visitElement(UElement node) { - if (elementHasLevel(node)) { - mCurrentLevel++; - } - if (node.equals(mEndAt)) { - mDone = true; - } - return mDone || super.visitElement(node); - } - - @Override - public boolean visitVariable(UVariable node) { - if (mVariableLevel < 0 && node.getPsi().isEquivalentTo(mVariable)) { - mVariableLevel = mCurrentLevel; - } - - return super.visitVariable(node); - } - - @Override - public void afterVisitBinaryExpression(UBinaryExpression node) { - if (!mDone - && node.getOperator() instanceof UastBinaryOperator.AssignOperator - && mVariableLevel >= 0) { - UExpression leftOperand = node.getLeftOperand(); - UastBinaryOperator operator = node.getOperator(); - - if (!(operator instanceof UastBinaryOperator.AssignOperator) - || !(leftOperand instanceof UResolvable)) { - return; - } - - PsiElement resolved = ((UResolvable) leftOperand).resolve(); - if (!mVariable.equals(resolved)) { - return; - } - - // Last assignment is unknown if we see an assignment inside - // some conditional or loop statement. - if (mCurrentLevel > mVariableLevel + 1) { - mLastAssignment = null; - mCurrentValue = null; - return; - } - - UExpression rightOperand = node.getRightOperand(); - ConstantEvaluator constantEvaluator = mConstantEvaluator; - - mCurrentValue = (constantEvaluator != null) - ? constantEvaluator.evaluate(rightOperand) - : null; - mLastAssignment = rightOperand; - } - - super.afterVisitBinaryExpression(node); - } - - @Override - public void afterVisitElement(UElement node) { - if (elementHasLevel(node)) { - mCurrentLevel--; - } - super.afterVisitElement(node); - } - - private static boolean elementHasLevel(UElement node) { - return !(node instanceof UBlockExpression - || node instanceof UDeclarationsExpression); - } - } - - /** - * Evaluates the given node and returns the constant value it resolves to, if any - * - * @param node the node to compute the constant value for - * @return the corresponding constant value - a String, an Integer, a Float, and so on - */ - @Nullable - public Object evaluate(@Nullable PsiElement node) { - if (node == null) { - return null; - } - if (node instanceof PsiLiteral) { - return ((PsiLiteral)node).getValue(); - } else if (node instanceof PsiPrefixExpression) { - IElementType operator = ((PsiPrefixExpression) node).getOperationTokenType(); - Object operand = evaluate(((PsiPrefixExpression) node).getOperand()); - if (operand == null) { - return null; - } - if (operator == JavaTokenType.EXCL) { - if (operand instanceof Boolean) { - return !(Boolean) operand; - } - } else if (operator == JavaTokenType.PLUS) { - return operand; - } else if (operator == JavaTokenType.TILDE) { - if (operand instanceof Integer) { - return ~(Integer) operand; - } else if (operand instanceof Long) { - return ~(Long) operand; - } else if (operand instanceof Short) { - return ~(Short) operand; - } else if (operand instanceof Character) { - return ~(Character) operand; - } else if (operand instanceof Byte) { - return ~(Byte) operand; - } - } else if (operator == JavaTokenType.MINUS) { - if (operand instanceof Integer) { - return -(Integer) operand; - } else if (operand instanceof Long) { - return -(Long) operand; - } else if (operand instanceof Double) { - return -(Double) operand; - } else if (operand instanceof Float) { - return -(Float) operand; - } else if (operand instanceof Short) { - return -(Short) operand; - } else if (operand instanceof Character) { - return -(Character) operand; - } else if (operand instanceof Byte) { - return -(Byte) operand; - } - } - } else if (node instanceof PsiConditionalExpression) { - PsiConditionalExpression expression = (PsiConditionalExpression) node; - Object known = evaluate(expression.getCondition()); - if (known == Boolean.TRUE && expression.getThenExpression() != null) { - return evaluate(expression.getThenExpression()); - } else if (known == Boolean.FALSE && expression.getElseExpression() != null) { - return evaluate(expression.getElseExpression()); - } - } else if (node instanceof PsiParenthesizedExpression) { - PsiParenthesizedExpression parenthesizedExpression = (PsiParenthesizedExpression) node; - PsiExpression expression = parenthesizedExpression.getExpression(); - if (expression != null) { - return evaluate(expression); - } - } else if (node instanceof PsiBinaryExpression) { - IElementType operator = ((PsiBinaryExpression) node).getOperationTokenType(); - Object operandLeft = evaluate(((PsiBinaryExpression) node).getLOperand()); - Object operandRight = evaluate(((PsiBinaryExpression) node).getROperand()); - if (operandLeft == null || operandRight == null) { - if (mAllowUnknown) { - if (operandLeft == null) { - return operandRight; - } else { - return operandLeft; - } - } - return null; - } - if (operandLeft instanceof String && operandRight instanceof String) { - if (operator == JavaTokenType.PLUS) { - return operandLeft.toString() + operandRight.toString(); - } - return null; - } else if (operandLeft instanceof Boolean && operandRight instanceof Boolean) { - boolean left = (Boolean) operandLeft; - boolean right = (Boolean) operandRight; - if (operator == JavaTokenType.OROR) { - return left || right; - } else if (operator == JavaTokenType.ANDAND) { - return left && right; - } else if (operator == JavaTokenType.OR) { - return left | right; - } else if (operator == JavaTokenType.XOR) { - return left ^ right; - } else if (operator == JavaTokenType.AND) { - return left & right; - } else if (operator == JavaTokenType.EQEQ) { - return left == right; - } else if (operator == JavaTokenType.NE) { - return left != right; - } - } else if (operandLeft instanceof Number && operandRight instanceof Number) { - Number left = (Number) operandLeft; - Number right = (Number) operandRight; - boolean isInteger = - !(left instanceof Float || left instanceof Double - || right instanceof Float || right instanceof Double); - boolean isWide = - isInteger ? (left instanceof Long || right instanceof Long) - : (left instanceof Double || right instanceof Double); - - if (operator == JavaTokenType.OR) { - if (isWide) { - return left.longValue() | right.longValue(); - } else { - return left.intValue() | right.intValue(); - } - } else if (operator == JavaTokenType.XOR) { - if (isWide) { - return left.longValue() ^ right.longValue(); - } else { - return left.intValue() ^ right.intValue(); - } - } else if (operator == JavaTokenType.AND) { - if (isWide) { - return left.longValue() & right.longValue(); - } else { - return left.intValue() & right.intValue(); - } - } else if (operator == JavaTokenType.EQEQ) { - if (isInteger) { - return left.longValue() == right.longValue(); - } else { - return left.doubleValue() == right.doubleValue(); - } - } else if (operator == JavaTokenType.NE) { - if (isInteger) { - return left.longValue() != right.longValue(); - } else { - return left.doubleValue() != right.doubleValue(); - } - } else if (operator == JavaTokenType.GT) { - if (isInteger) { - return left.longValue() > right.longValue(); - } else { - return left.doubleValue() > right.doubleValue(); - } - } else if (operator == JavaTokenType.GE) { - if (isInteger) { - return left.longValue() >= right.longValue(); - } else { - return left.doubleValue() >= right.doubleValue(); - } - } else if (operator == JavaTokenType.LT) { - if (isInteger) { - return left.longValue() < right.longValue(); - } else { - return left.doubleValue() < right.doubleValue(); - } - } else if (operator == JavaTokenType.LE) { - if (isInteger) { - return left.longValue() <= right.longValue(); - } else { - return left.doubleValue() <= right.doubleValue(); - } - } else if (operator == JavaTokenType.LTLT) { - if (isWide) { - return left.longValue() << right.intValue(); - } else { - return left.intValue() << right.intValue(); - } - } else if (operator == JavaTokenType.GTGT) { - if (isWide) { - return left.longValue() >> right.intValue(); - } else { - return left.intValue() >> right.intValue(); - } - } else if (operator == JavaTokenType.GTGTGT) { - if (isWide) { - return left.longValue() >>> right.intValue(); - } else { - return left.intValue() >>> right.intValue(); - } - } else if (operator == JavaTokenType.PLUS) { - if (isInteger) { - if (isWide) { - return left.longValue() + right.longValue(); - } else { - return left.intValue() + right.intValue(); - } - } else { - if (isWide) { - return left.doubleValue() + right.doubleValue(); - } else { - return left.floatValue() + right.floatValue(); - } - } - } else if (operator == JavaTokenType.MINUS) { - if (isInteger) { - if (isWide) { - return left.longValue() - right.longValue(); - } else { - return left.intValue() - right.intValue(); - } - } else { - if (isWide) { - return left.doubleValue() - right.doubleValue(); - } else { - return left.floatValue() - right.floatValue(); - } - } - } else if (operator == JavaTokenType.ASTERISK) { - if (isInteger) { - if (isWide) { - return left.longValue() * right.longValue(); - } else { - return left.intValue() * right.intValue(); - } - } else { - if (isWide) { - return left.doubleValue() * right.doubleValue(); - } else { - return left.floatValue() * right.floatValue(); - } - } - } else if (operator == JavaTokenType.DIV) { - if (isInteger) { - if (isWide) { - return left.longValue() / right.longValue(); - } else { - return left.intValue() / right.intValue(); - } - } else { - if (isWide) { - return left.doubleValue() / right.doubleValue(); - } else { - return left.floatValue() / right.floatValue(); - } - } - } else if (operator == JavaTokenType.PERC) { - if (isInteger) { - if (isWide) { - return left.longValue() % right.longValue(); - } else { - return left.intValue() % right.intValue(); - } - } else { - if (isWide) { - return left.doubleValue() % right.doubleValue(); - } else { - return left.floatValue() % right.floatValue(); - } - } - } else { - return null; - } - } - } else if (node instanceof PsiTypeCastExpression) { - PsiTypeCastExpression cast = (PsiTypeCastExpression) node; - Object operandValue = evaluate(cast.getOperand()); - if (operandValue instanceof Number) { - Number number = (Number) operandValue; - PsiTypeElement typeElement = cast.getCastType(); - if (typeElement != null) { - PsiType type = typeElement.getType(); - if (PsiType.FLOAT.equals(type)) { - return number.floatValue(); - } else if (PsiType.DOUBLE.equals(type)) { - return number.doubleValue(); - } else if (PsiType.INT.equals(type)) { - return number.intValue(); - } else if (PsiType.LONG.equals(type)) { - return number.longValue(); - } else if (PsiType.SHORT.equals(type)) { - return number.shortValue(); - } else if (PsiType.BYTE.equals(type)) { - return number.byteValue(); - } - } - } - return operandValue; - } else if (node instanceof PsiReference) { - PsiElement resolved = ((PsiReference) node).resolve(); - if (resolved instanceof PsiField) { - PsiField field = (PsiField) resolved; - Object value = field.computeConstantValue(); - if (value != null) { - return value; - } - if (field.getInitializer() != null) { - return evaluate(field.getInitializer()); - } - return null; - } else if (resolved instanceof PsiLocalVariable) { - PsiLocalVariable variable = (PsiLocalVariable) resolved; - PsiStatement statement = PsiTreeUtil.getParentOfType(node, PsiStatement.class, - false); - if (statement != null) { - PsiStatement prev = PsiTreeUtil.getPrevSiblingOfType(statement, - PsiStatement.class); - String targetName = variable.getName(); - if (targetName == null) { - return null; - } - while (prev != null) { - if (prev instanceof PsiDeclarationStatement) { - for (PsiElement element : ((PsiDeclarationStatement) prev) - .getDeclaredElements()) { - if (variable.equals(element)) { - return evaluate(variable.getInitializer()); - } - } - } else if (prev instanceof PsiExpressionStatement) { - PsiExpression expression = ((PsiExpressionStatement) prev) - .getExpression(); - if (expression instanceof PsiAssignmentExpression) { - PsiAssignmentExpression assign - = (PsiAssignmentExpression) expression; - PsiExpression lhs = assign.getLExpression(); - if (lhs instanceof PsiReferenceExpression) { - PsiReferenceExpression reference = (PsiReferenceExpression) lhs; - if (targetName.equals(reference.getReferenceName()) && - reference.getQualifier() == null) { - return evaluate(assign.getRExpression()); - } - } - } - } - prev = PsiTreeUtil.getPrevSiblingOfType(prev, - PsiStatement.class); - } - } - } - } else if (node instanceof PsiNewExpression) { - PsiNewExpression creation = (PsiNewExpression) node; - PsiArrayInitializerExpression initializer = creation.getArrayInitializer(); - PsiType type = creation.getType(); - if (type instanceof PsiArrayType) { - if (initializer != null) { - PsiExpression[] initializers = initializer.getInitializers(); - Class commonType = null; - List values = Lists.newArrayListWithExpectedSize(initializers.length); - int count = 0; - for (PsiExpression expression : initializers) { - Object value = evaluate(expression); - if (value != null) { - values.add(value); - if (commonType == null) { - commonType = value.getClass(); - } else { - while (!commonType.isAssignableFrom(value.getClass())) { - commonType = commonType.getSuperclass(); - } - } - } else if (!mAllowUnknown) { - // Inconclusive - return null; - } - count++; - if (count == 20) { // avoid large initializers - break; - } - } - type = type.getDeepComponentType(); - if (type == PsiType.INT) { - if (!values.isEmpty()) { - int[] array = new int[values.size()]; - for (int i = 0; i < values.size(); i++) { - Object o = values.get(i); - if (o instanceof Integer) { - array[i] = (Integer) o; - } - } - return array; - } - return new int[0]; - } else if (type == PsiType.BOOLEAN) { - if (!values.isEmpty()) { - boolean[] array = new boolean[values.size()]; - for (int i = 0; i < values.size(); i++) { - Object o = values.get(i); - if (o instanceof Boolean) { - array[i] = (Boolean) o; - } - } - return array; - } - return new boolean[0]; - } else if (type == PsiType.DOUBLE) { - if (!values.isEmpty()) { - double[] array = new double[values.size()]; - for (int i = 0; i < values.size(); i++) { - Object o = values.get(i); - if (o instanceof Double) { - array[i] = (Double) o; - } - } - return array; - } - return new double[0]; - } else if (type == PsiType.LONG) { - if (!values.isEmpty()) { - long[] array = new long[values.size()]; - for (int i = 0; i < values.size(); i++) { - Object o = values.get(i); - if (o instanceof Long) { - array[i] = (Long) o; - } - } - return array; - } - return new long[0]; - } else if (type == PsiType.FLOAT) { - if (!values.isEmpty()) { - float[] array = new float[values.size()]; - for (int i = 0; i < values.size(); i++) { - Object o = values.get(i); - if (o instanceof Float) { - array[i] = (Float) o; - } - } - return array; - } - return new float[0]; - } else if (type == PsiType.CHAR) { - if (!values.isEmpty()) { - char[] array = new char[values.size()]; - for (int i = 0; i < values.size(); i++) { - Object o = values.get(i); - if (o instanceof Character) { - array[i] = (Character) o; - } - } - return array; - } - return new char[0]; - } else if (type == PsiType.BYTE) { - if (!values.isEmpty()) { - byte[] array = new byte[values.size()]; - for (int i = 0; i < values.size(); i++) { - Object o = values.get(i); - if (o instanceof Byte) { - array[i] = (Byte) o; - } - } - return array; - } - return new byte[0]; - } else if (type == PsiType.SHORT) { - if (!values.isEmpty()) { - short[] array = new short[values.size()]; - for (int i = 0; i < values.size(); i++) { - Object o = values.get(i); - if (o instanceof Short) { - array[i] = (Short) o; - } - } - return array; - } - return new short[0]; - } else { - if (!values.isEmpty()) { - Object o = Array.newInstance(commonType, values.size()); - return values.toArray((Object[]) o); - } - return null; - } - } else { - // something like "new byte[3]" but with no initializer. - // Look up the size and only if small, use it. E.g. if it was byte[3] - // we return a byte[3] array, but if it's say byte[1024*1024] we don't - // want to do that. - PsiExpression[] arrayDimensions = creation.getArrayDimensions(); - int size = 0; - if (arrayDimensions.length == 1) { - Object fixedSize = evaluate(arrayDimensions[0]); - if (fixedSize instanceof Number) { - size = ((Number)fixedSize).intValue(); - if (size > 30) { - size = 30; - } - } - } - type = type.getDeepComponentType(); - if (type instanceof PsiPrimitiveType) { - if (PsiType.BYTE.equals(type)) { - return new byte[size]; - } - if (PsiType.BOOLEAN.equals(type)) { - return new boolean[size]; - } - if (PsiType.INT.equals(type)) { - return new int[size]; - } - if (PsiType.LONG.equals(type)) { - return new long[size]; - } - if (PsiType.CHAR.equals(type)) { - return new char[size]; - } - if (PsiType.FLOAT.equals(type)) { - return new float[size]; - } - if (PsiType.DOUBLE.equals(type)) { - return new double[size]; - } - if (PsiType.SHORT.equals(type)) { - return new short[size]; - } - } else if (type instanceof PsiClassType) { - String className = type.getCanonicalText(); - if (TYPE_STRING.equals(className)) { - //noinspection SSBasedInspection - return new String[size]; - } - if (TYPE_OBJECT.equals(className)) { - //noinspection SSBasedInspection - return new Object[size]; - } - } - } - } - } - - // TODO: Check for MethodInvocation and perform some common operations - - // Math.* methods, String utility methods like notNullize, etc - - return null; - } - - /** - * Returns true if the node is pointing to a an array literal - */ - public static boolean isArrayLiteral(@Nullable UElement node, @NonNull JavaContext context) { - if (node instanceof UReferenceExpression) { - PsiElement resolved = ((UReferenceExpression) node).resolve(); - if (resolved instanceof PsiVariable) { - PsiVariable variable = (PsiVariable) resolved; - UExpression lastAssignment = - UastLintUtils.findLastAssignment(variable, node, context); - - if (lastAssignment != null) { - return isArrayLiteral(lastAssignment, context); - } - } - } else if (UastExpressionUtils.isNewArrayWithDimensions(node)) { - return true; - } else if (UastExpressionUtils.isNewArrayWithInitializer(node)) { - return true; - } else if (node instanceof UParenthesizedExpression) { - UParenthesizedExpression parenthesizedExpression = (UParenthesizedExpression) node; - UExpression expression = parenthesizedExpression.getExpression(); - return isArrayLiteral(expression, context); - } else if (UastExpressionUtils.isTypeCast(node)) { - UBinaryExpressionWithType castExpression = (UBinaryExpressionWithType) node; - assert castExpression != null; - UExpression operand = castExpression.getOperand(); - return isArrayLiteral(operand, context); - } - - return false; - } - - /** - * Returns true if the node is pointing to a an array literal - */ - public static boolean isArrayLiteral(@Nullable PsiElement node) { - if (node instanceof PsiReference) { - PsiElement resolved = ((PsiReference) node).resolve(); - if (resolved instanceof PsiField) { - PsiField field = (PsiField) resolved; - if (field.getInitializer() != null) { - return isArrayLiteral(field.getInitializer()); - } - } else if (resolved instanceof PsiLocalVariable) { - PsiLocalVariable variable = (PsiLocalVariable) resolved; - PsiStatement statement = PsiTreeUtil.getParentOfType(node, PsiStatement.class, - false); - if (statement != null) { - PsiStatement prev = PsiTreeUtil.getPrevSiblingOfType(statement, - PsiStatement.class); - String targetName = variable.getName(); - if (targetName == null) { - return false; - } - while (prev != null) { - if (prev instanceof PsiDeclarationStatement) { - for (PsiElement element : ((PsiDeclarationStatement) prev) - .getDeclaredElements()) { - if (variable.equals(element)) { - return isArrayLiteral(variable.getInitializer()); - } - } - } else if (prev instanceof PsiExpressionStatement) { - PsiExpression expression = ((PsiExpressionStatement) prev) - .getExpression(); - if (expression instanceof PsiAssignmentExpression) { - PsiAssignmentExpression assign - = (PsiAssignmentExpression) expression; - PsiExpression lhs = assign.getLExpression(); - if (lhs instanceof PsiReferenceExpression) { - PsiReferenceExpression reference = (PsiReferenceExpression) lhs; - if (targetName.equals(reference.getReferenceName()) && - reference.getQualifier() == null) { - return isArrayLiteral(assign.getRExpression()); - } - } - } - } - prev = PsiTreeUtil.getPrevSiblingOfType(prev, - PsiStatement.class); - } - } - } - } else if (node instanceof PsiNewExpression) { - PsiNewExpression creation = (PsiNewExpression) node; - if (creation.getArrayInitializer() != null) { - return true; - } - PsiType type = creation.getType(); - if (type instanceof PsiArrayType) { - return true; - } - } else if (node instanceof PsiParenthesizedExpression) { - PsiParenthesizedExpression parenthesizedExpression = (PsiParenthesizedExpression) node; - PsiExpression expression = parenthesizedExpression.getExpression(); - if (expression != null) { - return isArrayLiteral(expression); - } - } else if (node instanceof PsiTypeCastExpression) { - PsiTypeCastExpression castExpression = (PsiTypeCastExpression) node; - PsiExpression operand = castExpression.getOperand(); - if (operand != null) { - return isArrayLiteral(operand); - } - } - - return false; - } - - /** - * Evaluates the given node and returns the constant value it resolves to, if any. Convenience - * wrapper which creates a new {@linkplain ConstantEvaluator}, evaluates the node and returns - * the result. - * - * @param context the context to use to resolve field references, if any - * @param node the node to compute the constant value for - * @return the corresponding constant value - a String, an Integer, a Float, and so on - * @deprecated Use {@link #evaluate(JavaContext, PsiElement)} instead - */ - @Deprecated - @Nullable - public static Object evaluate(@NonNull JavaContext context, @NonNull Node node) { - return new ConstantEvaluator(context).evaluate(node); - } - - /** - * Evaluates the given node and returns the constant string it resolves to, if any. Convenience - * wrapper which creates a new {@linkplain ConstantEvaluator}, evaluates the node and returns - * the result if the result is a string. - * - * @param context the context to use to resolve field references, if any - * @param node the node to compute the constant value for - * @param allowUnknown whether we should construct the string even if some parts of it are - * unknown - * @return the corresponding string, if any - * @deprecated Use {@link #evaluateString(JavaContext, PsiElement, boolean)} instead - */ - @Deprecated - @Nullable - public static String evaluateString(@NonNull JavaContext context, @NonNull Node node, - boolean allowUnknown) { - ConstantEvaluator evaluator = new ConstantEvaluator(context); - if (allowUnknown) { - evaluator.allowUnknowns(); - } - Object value = evaluator.evaluate(node); - return value instanceof String ? (String) value : null; - } - - /** - * Evaluates the given node and returns the constant value it resolves to, if any. Convenience - * wrapper which creates a new {@linkplain ConstantEvaluator}, evaluates the node and returns - * the result. - * - * @param context the context to use to resolve field references, if any - * @param node the node to compute the constant value for - * @return the corresponding constant value - a String, an Integer, a Float, and so on - */ - @Nullable - public static Object evaluate(@Nullable JavaContext context, @NonNull PsiElement node) { - return new ConstantEvaluator(context).evaluate(node); - } - - /** - * Evaluates the given node and returns the constant value it resolves to, if any. Convenience - * wrapper which creates a new {@linkplain ConstantEvaluator}, evaluates the node and returns - * the result. - * - * @param context the context to use to resolve field references, if any - * @param node the node to compute the constant value for - * @return the corresponding constant value - a String, an Integer, a Float, and so on - */ - @Nullable - public static Object evaluate(@Nullable JavaContext context, @NonNull UElement node) { - return new ConstantEvaluator(context).evaluate(node); - } - - /** - * Evaluates the given node and returns the constant string it resolves to, if any. Convenience - * wrapper which creates a new {@linkplain ConstantEvaluator}, evaluates the node and returns - * the result if the result is a string. - * - * @param context the context to use to resolve field references, if any - * @param node the node to compute the constant value for - * @param allowUnknown whether we should construct the string even if some parts of it are - * unknown - * @return the corresponding string, if any - */ - @Nullable - public static String evaluateString(@Nullable JavaContext context, @NonNull PsiElement node, - boolean allowUnknown) { - ConstantEvaluator evaluator = new ConstantEvaluator(context); - if (allowUnknown) { - evaluator.allowUnknowns(); - } - Object value = evaluator.evaluate(node); - return value instanceof String ? (String) value : null; - } - - /** - * Evaluates the given node and returns the constant string it resolves to, if any. Convenience - * wrapper which creates a new {@linkplain ConstantEvaluator}, evaluates the node and returns - * the result if the result is a string. - * - * @param context the context to use to resolve field references, if any - * @param node the node to compute the constant value for - * @param allowUnknown whether we should construct the string even if some parts of it are - * unknown - * @return the corresponding string, if any - */ - @Nullable - public static String evaluateString(@Nullable JavaContext context, @NonNull UElement node, - boolean allowUnknown) { - ConstantEvaluator evaluator = new ConstantEvaluator(context); - if (allowUnknown) { - evaluator.allowUnknowns(); - } - Object value = evaluator.evaluate(node); - return value instanceof String ? (String) value : null; - } -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/Context.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/Context.java.173 deleted file mode 100644 index 9d87faef96f..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/Context.java.173 +++ /dev/null @@ -1,451 +0,0 @@ -/* - * Copyright (C) 2011 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.detector.api; - -import static com.android.SdkConstants.DOT_GRADLE; -import static com.android.SdkConstants.DOT_JAVA; -import static com.android.SdkConstants.DOT_XML; -import static com.android.SdkConstants.SUPPRESS_ALL; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.tools.klint.client.api.Configuration; -import com.android.tools.klint.client.api.LintClient; -import com.android.tools.klint.client.api.LintDriver; -import com.android.tools.klint.client.api.SdkInfo; -import com.google.common.annotations.Beta; - -import java.io.File; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.Map; - -/** - * Context passed to the detectors during an analysis run. It provides - * information about the file being analyzed, it allows shared properties (so - * the detectors can share results), etc. - *

- * NOTE: This is not a public or final API; if you rely on this be prepared - * to adjust your code for the next tools release. - */ -@Beta -public class Context { - /** - * The file being checked. Note that this may not always be to a concrete - * file. For example, in the {@link Detector#beforeCheckProject(Context)} - * method, the context file is the directory of the project. - */ - public final File file; - - /** The driver running through the checks */ - protected final LintDriver mDriver; - - /** The project containing the file being checked */ - @NonNull - private final Project mProject; - - /** - * The "main" project. For normal projects, this is the same as {@link #mProject}, - * but for library projects, it's the root project that includes (possibly indirectly) - * the various library projects and their library projects. - *

- * Note that this is a property on the {@link Context}, not the - * {@link Project}, since a library project can be included from multiple - * different top level projects, so there isn't one main project, - * just one per main project being analyzed with its library projects. - */ - private final Project mMainProject; - - /** The current configuration controlling which checks are enabled etc */ - private final Configuration mConfiguration; - - /** The contents of the file */ - private String mContents; - - /** Map of properties to share results between detectors */ - private Map mProperties; - - /** Whether this file contains any suppress markers (null means not yet determined) */ - private Boolean mContainsCommentSuppress; - - /** - * Construct a new {@link Context} - * - * @param driver the driver running through the checks - * @param project the project containing the file being checked - * @param main the main project if this project is a library project, or - * null if this is not a library project. The main project is - * the root project of all library projects, not necessarily the - * directly including project. - * @param file the file being checked - */ - public Context( - @NonNull LintDriver driver, - @NonNull Project project, - @Nullable Project main, - @NonNull File file) { - this.file = file; - - mDriver = driver; - mProject = project; - mMainProject = main; - mConfiguration = project.getConfiguration(driver); - } - - /** - * Returns the scope for the lint job - * - * @return the scope, never null - */ - @NonNull - public EnumSet getScope() { - return mDriver.getScope(); - } - - /** - * Returns the configuration for this project. - * - * @return the configuration, never null - */ - @NonNull - public Configuration getConfiguration() { - return mConfiguration; - } - - /** - * Returns the project containing the file being checked - * - * @return the project, never null - */ - @NonNull - public Project getProject() { - return mProject; - } - - /** - * Returns the main project if this project is a library project, or self - * if this is not a library project. The main project is the root project - * of all library projects, not necessarily the directly including project. - * - * @return the main project, never null - */ - @NonNull - public Project getMainProject() { - return mMainProject != null ? mMainProject : mProject; - } - - /** - * Returns the lint client requesting the lint check - * - * @return the client, never null - */ - @NonNull - public LintClient getClient() { - return mDriver.getClient(); - } - - /** - * Returns the driver running through the lint checks - * - * @return the driver - */ - @NonNull - public LintDriver getDriver() { - return mDriver; - } - - /** - * Returns the contents of the file. This may not be the contents of the - * file on disk, since it delegates to the {@link LintClient}, which in turn - * may decide to return the current edited contents of the file open in an - * editor. - * - * @return the contents of the given file, or null if an error occurs. - */ - @Nullable - public String getContents() { - if (mContents == null) { - mContents = mDriver.getClient().readFile(file); - } - - return mContents; - } - - /** - * Returns the value of the given named property, or null. - * - * @param name the name of the property - * @return the corresponding value, or null - */ - @SuppressWarnings("UnusedDeclaration") // Used in ADT - @Nullable - public Object getProperty(String name) { - if (mProperties == null) { - return null; - } - - return mProperties.get(name); - } - - /** - * Sets the value of the given named property. - * - * @param name the name of the property - * @param value the corresponding value - */ - @SuppressWarnings("UnusedDeclaration") // Used in ADT - public void setProperty(@NonNull String name, @Nullable Object value) { - if (value == null) { - if (mProperties != null) { - mProperties.remove(name); - } - } else { - if (mProperties == null) { - mProperties = new HashMap(); - } - mProperties.put(name, value); - } - } - - /** - * Gets the SDK info for the current project. - * - * @return the SDK info for the current project, never null - */ - @NonNull - public SdkInfo getSdkInfo() { - return mProject.getSdkInfo(); - } - - // ---- Convenience wrappers ---- (makes the detector code a bit leaner) - - /** - * Returns false if the given issue has been disabled. Convenience wrapper - * around {@link Configuration#getSeverity(Issue)}. - * - * @param issue the issue to check - * @return false if the issue has been disabled - */ - public boolean isEnabled(@NonNull Issue issue) { - return mConfiguration.isEnabled(issue); - } - - /** - * Reports an issue. Convenience wrapper around {@link LintClient#report} - * - * @param issue the issue to report - * @param location the location of the issue - * @param message the message for this warning - */ - public void report( - @NonNull Issue issue, - @NonNull Location location, - @NonNull String message) { - //noinspection ConstantConditions - if (location == null) { - // Misbehaving third-party lint detectors - assert false : issue; - return; - } - - if (location == Location.NONE) { - // Detector reported error for issue in a non-applicable location etc - return; - } - - Configuration configuration = mConfiguration; - - // If this error was computed for a context where the context corresponds to - // a project instead of a file, the actual error may be in a different project (e.g. - // a library project), so adjust the configuration as necessary. - Project project = mDriver.findProjectFor(location.getFile()); - if (project != null) { - configuration = project.getConfiguration(mDriver); - } - - // If an error occurs in a library project, but you've disabled that check in the - // main project, disable it in the library project too. (In some cases you don't - // control the lint.xml of a library project, and besides, if you're not interested in - // a check for your main project you probably don't care about it in the library either.) - if (configuration != mConfiguration - && mConfiguration.getSeverity(issue) == Severity.IGNORE) { - return; - } - - Severity severity = configuration.getSeverity(issue); - if (severity == Severity.IGNORE) { - return; - } - - mDriver.getClient().report(this, issue, severity, location, message, TextFormat.RAW); - } - - /** - * Report an error. - * Like {@link #report(Issue, Location, String)} but with - * a now-unused data parameter at the end - * - * @deprecated Use {@link #report(Issue, Location, String)} instead; - * this method is here for custom rule compatibility - */ - @SuppressWarnings("UnusedDeclaration") // Potentially used by external existing custom rules - @Deprecated - public void report( - @NonNull Issue issue, - @NonNull Location location, - @NonNull String message, - @SuppressWarnings("UnusedParameters") @Nullable Object data) { - report(issue, location, message); - } - - /** - * Send an exception to the log. Convenience wrapper around {@link LintClient#log}. - * - * @param exception the exception, possibly null - * @param format the error message using {@link String#format} syntax, possibly null - * @param args any arguments for the format string - */ - public void log( - @Nullable Throwable exception, - @Nullable String format, - @Nullable Object... args) { - mDriver.getClient().log(exception, format, args); - } - - /** - * Returns the current phase number. The first pass is numbered 1. Only one pass - * will be performed, unless a {@link Detector} calls {@link #requestRepeat}. - * - * @return the current phase, usually 1 - */ - public int getPhase() { - return mDriver.getPhase(); - } - - /** - * Requests another pass through the data for the given detector. This is - * typically done when a detector needs to do more expensive computation, - * but it only wants to do this once it knows that an error is - * present, or once it knows more specifically what to check for. - * - * @param detector the detector that should be included in the next pass. - * Note that the lint runner may refuse to run more than a couple - * of runs. - * @param scope the scope to be revisited. This must be a subset of the - * current scope ({@link #getScope()}, and it is just a performance hint; - * in particular, the detector should be prepared to be called on other - * scopes as well (since they may have been requested by other detectors). - * You can pall null to indicate "all". - */ - public void requestRepeat(@NonNull Detector detector, @Nullable EnumSet scope) { - mDriver.requestRepeat(detector, scope); - } - - /** Returns the comment marker used in Studio to suppress statements for language, if any */ - @Nullable - protected String getSuppressCommentPrefix() { - // Java and XML files are handled in sub classes (XmlContext, JavaContext) - - String path = file.getPath(); - if (path.endsWith(DOT_JAVA) || path.endsWith(".kt") || path.endsWith(DOT_GRADLE)) { - return JavaContext.SUPPRESS_COMMENT_PREFIX; - } else if (path.endsWith(DOT_XML)) { - return XmlContext.SUPPRESS_COMMENT_PREFIX; - } else if (path.endsWith(".cfg") || path.endsWith(".pro")) { - return "#suppress "; - } - - return null; - } - - /** Returns whether this file contains any suppress comment markers */ - public boolean containsCommentSuppress() { - if (mContainsCommentSuppress == null) { - mContainsCommentSuppress = false; - String prefix = getSuppressCommentPrefix(); - if (prefix != null) { - String contents = getContents(); - if (contents != null) { - mContainsCommentSuppress = contents.contains(prefix); - } - } - } - - return mContainsCommentSuppress; - } - - /** - * Returns true if the given issue is suppressed at the given character offset - * in the file's contents - */ - public boolean isSuppressedWithComment(int startOffset, @NonNull Issue issue) { - String prefix = getSuppressCommentPrefix(); - if (prefix == null) { - return false; - } - - if (startOffset <= 0) { - return false; - } - - // Check whether there is a comment marker - String contents = getContents(); - assert contents != null; // otherwise we wouldn't be here - if (startOffset >= contents.length()) { - return false; - } - - // Scan backwards to the previous line and see if it contains the marker - int lineStart = contents.lastIndexOf('\n', startOffset) + 1; - if (lineStart <= 1) { - return false; - } - int index = findPrefixOnPreviousLine(contents, lineStart, prefix); - if (index != -1 &&index+prefix.length() < lineStart) { - String line = contents.substring(index + prefix.length(), lineStart); - return line.contains(issue.getId()) - || line.contains(SUPPRESS_ALL) && line.trim().startsWith(SUPPRESS_ALL); - } - - return false; - } - - private static int findPrefixOnPreviousLine(String contents, int lineStart, String prefix) { - // Search backwards on the previous line until you find the prefix start (also look - // back on previous lines if the previous line(s) contain just whitespace - char first = prefix.charAt(0); - int offset = lineStart - 2; // 0: first char on this line, -1: \n on previous line, -2 last - boolean seenNonWhitespace = false; - for (; offset >= 0; offset--) { - char c = contents.charAt(offset); - if (seenNonWhitespace && c == '\n') { - return -1; - } - - if (!seenNonWhitespace && !Character.isWhitespace(c)) { - seenNonWhitespace = true; - } - - if (c == first && contents.regionMatches(false, offset, prefix, 0, - prefix.length())) { - return offset; - } - } - - return -1; - } -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/DefaultPosition.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/DefaultPosition.java.173 deleted file mode 100644 index fd370cc4d22..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/DefaultPosition.java.173 +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2011 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.detector.api; - -import com.google.common.annotations.Beta; - -/** - * A simple offset-based position * - *

- * NOTE: This is not a public or final API; if you rely on this be prepared - * to adjust your code for the next tools release. - */ -@Beta -public class DefaultPosition extends Position { - /** The line number (0-based where the first line is line 0) */ - private final int mLine; - - /** - * The column number (where the first character on the line is 0), or -1 if - * unknown - */ - private final int mColumn; - - /** The character offset */ - private final int mOffset; - - /** - * Creates a new {@link DefaultPosition} - * - * @param line the 0-based line number, or -1 if unknown - * @param column the 0-based column number, or -1 if unknown - * @param offset the offset, or -1 if unknown - */ - public DefaultPosition(int line, int column, int offset) { - mLine = line; - mColumn = column; - mOffset = offset; - } - - @Override - public int getLine() { - return mLine; - } - - @Override - public int getOffset() { - return mOffset; - } - - @Override - public int getColumn() { - return mColumn; - } -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/Detector.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/Detector.java.173 deleted file mode 100644 index fc60ac8b3fb..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/Detector.java.173 +++ /dev/null @@ -1,1515 +0,0 @@ -/* - * Copyright (C) 2011 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.detector.api; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.resources.ResourceFolderType; -import com.android.resources.ResourceType; -import com.android.tools.klint.client.api.JavaParser.ResolvedClass; -import com.android.tools.klint.client.api.JavaParser.ResolvedMethod; -import com.android.tools.klint.client.api.LintDriver; -import com.android.tools.klint.client.api.UElementVisitor; -import com.google.common.annotations.Beta; -import com.intellij.psi.JavaElementVisitor; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiJavaCodeReferenceElement; -import com.intellij.psi.PsiMethod; -import com.intellij.psi.PsiMethodCallExpression; -import com.intellij.psi.PsiNewExpression; - -import com.intellij.psi.PsiTypeParameter; - -import org.jetbrains.uast.UCallExpression; -import org.jetbrains.uast.UClass; -import org.jetbrains.uast.UElement; -import org.jetbrains.uast.UMethod; -import org.jetbrains.uast.UReferenceExpression; -import org.jetbrains.uast.visitor.UastVisitor; -import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode; -import org.jetbrains.org.objectweb.asm.tree.ClassNode; -import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode; -import org.jetbrains.org.objectweb.asm.tree.MethodNode; -import org.w3c.dom.Attr; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import java.io.File; -import java.util.ArrayList; -import java.util.Collection; -import java.util.EnumSet; -import java.util.List; -import java.util.Map; - -import lombok.ast.AstVisitor; -import lombok.ast.ClassDeclaration; -import lombok.ast.ConstructorInvocation; -import lombok.ast.MethodInvocation; -import lombok.ast.Node; - -/** - * A detector is able to find a particular problem (or a set of related problems). - * Each problem type is uniquely identified as an {@link Issue}. - *

- * Detectors will be called in a predefined order: - *

    - *
  1. Manifest file - *
  2. Resource files, in alphabetical order by resource type - * (therefore, "layout" is checked before "values", "values-de" is checked before - * "values-en" but after "values", and so on. - *
  3. Java sources - *
  4. Java classes - *
  5. Gradle files - *
  6. Generic files - *
  7. Proguard files - *
  8. Property files - *
- * If a detector needs information when processing a file type that comes from a type of - * file later in the order above, they can request a second phase; see - * {@link LintDriver#requestRepeat}. - * NOTE: This is not a public or final API; if you rely on this be prepared - * to adjust your code for the next tools release. - */ -@Beta -public abstract class Detector { - /** - * Specialized interface for detectors that scan Java source file parse trees - * @deprecated Use {@link JavaPsiScanner} instead - */ - @Deprecated @SuppressWarnings("unused") // Still here for third-party rules - public interface JavaScanner { - /** - * Create a parse tree visitor to process the parse tree. All - * {@link JavaScanner} detectors must provide a visitor, unless they - * either return true from {@link #appliesToResourceRefs()} or return - * non null from {@link #getApplicableMethodNames()}. - *

- * If you return specific AST node types from - * {@link #getApplicableNodeTypes()}, then the visitor will only - * be called for the specific requested node types. This is more - * efficient, since it allows many detectors that apply to only a small - * part of the AST (such as method call nodes) to share iteration of the - * majority of the parse tree. - *

- * If you return null from {@link #getApplicableNodeTypes()}, then your - * visitor will be called from the top and all node types visited. - *

- * Note that a new visitor is created for each separate compilation - * unit, so you can store per file state in the visitor. - * - * @param context the {@link Context} for the file being analyzed - * @return a visitor, or null. - */ - @Nullable - AstVisitor createJavaVisitor(@NonNull JavaContext context); - - /** - * Return the types of AST nodes that the visitor returned from - * {@link #createJavaVisitor(JavaContext)} should visit. See the - * documentation for {@link #createJavaVisitor(JavaContext)} for details - * on how the shared visitor is used. - *

- * If you return null from this method, then the visitor will process - * the full tree instead. - *

- * Note that for the shared visitor, the return codes from the visit - * methods are ignored: returning true will not prune iteration - * of the subtree, since there may be other node types interested in the - * children. If you need to ensure that your visitor only processes a - * part of the tree, use a full visitor instead. See the - * OverdrawDetector implementation for an example of this. - * - * @return the list of applicable node types (AST node classes), or null - */ - @Nullable - List> getApplicableNodeTypes(); - - /** - * Return the list of method names this detector is interested in, or - * null. If this method returns non-null, then any AST nodes that match - * a method call in the list will be passed to the - * {@link #visitMethod(JavaContext, AstVisitor, MethodInvocation)} - * method for processing. The visitor created by - * {@link #createJavaVisitor(JavaContext)} is also passed to that - * method, although it can be null. - *

- * This makes it easy to write detectors that focus on some fixed calls. - * For example, the StringFormatDetector uses this mechanism to look for - * "format" calls, and when found it looks around (using the AST's - * {@link Node#getParent()} method) to see if it's called on - * a String class instance, and if so do its normal processing. Note - * that since it doesn't need to do any other AST processing, that - * detector does not actually supply a visitor. - * - * @return a set of applicable method names, or null. - */ - @Nullable - List getApplicableMethodNames(); - - /** - * Method invoked for any method calls found that matches any names - * returned by {@link #getApplicableMethodNames()}. This also passes - * back the visitor that was created by - * {@link #createJavaVisitor(JavaContext)}, but a visitor is not - * required. It is intended for detectors that need to do additional AST - * processing, but also want the convenience of not having to look for - * method names on their own. - * - * @param context the context of the lint request - * @param visitor the visitor created from - * {@link #createJavaVisitor(JavaContext)}, or null - * @param node the {@link MethodInvocation} node for the invoked method - */ - void visitMethod( - @NonNull JavaContext context, - @Nullable AstVisitor visitor, - @NonNull MethodInvocation node); - - /** - * Return the list of constructor types this detector is interested in, or - * null. If this method returns non-null, then any AST nodes that match - * a constructor call in the list will be passed to the - * {@link #visitConstructor(JavaContext, AstVisitor, ConstructorInvocation, ResolvedMethod)} - * method for processing. The visitor created by - * {@link #createJavaVisitor(JavaContext)} is also passed to that - * method, although it can be null. - *

- * This makes it easy to write detectors that focus on some fixed constructors. - * - * @return a set of applicable fully qualified types, or null. - */ - @Nullable - List getApplicableConstructorTypes(); - - /** - * Method invoked for any constructor calls found that matches any names - * returned by {@link #getApplicableConstructorTypes()}. This also passes - * back the visitor that was created by - * {@link #createJavaVisitor(JavaContext)}, but a visitor is not - * required. It is intended for detectors that need to do additional AST - * processing, but also want the convenience of not having to look for - * method names on their own. - * - * @param context the context of the lint request - * @param visitor the visitor created from - * {@link #createJavaVisitor(JavaContext)}, or null - * @param node the {@link ConstructorInvocation} node for the invoked method - * @param constructor the resolved constructor method with type information - */ - void visitConstructor( - @NonNull JavaContext context, - @Nullable AstVisitor visitor, - @NonNull ConstructorInvocation node, - @NonNull ResolvedMethod constructor); - - /** - * Returns whether this detector cares about Android resource references - * (such as {@code R.layout.main} or {@code R.string.app_name}). If it - * does, then the visitor will look for these patterns, and if found, it - * will invoke {@link #visitResourceReference} passing the resource type - * and resource name. It also passes the visitor, if any, that was - * created by {@link #createJavaVisitor(JavaContext)}, such that a - * detector can do more than just look for resources. - * - * @return true if this detector wants to be notified of R resource - * identifiers found in the code. - */ - boolean appliesToResourceRefs(); - - /** - * Called for any resource references (such as {@code R.layout.main} - * found in Java code, provided this detector returned {@code true} from - * {@link #appliesToResourceRefs()}. - * - * @param context the lint scanning context - * @param visitor the visitor created from - * {@link #createJavaVisitor(JavaContext)}, or null - * @param node the variable reference for the resource - * @param type the resource type, such as "layout" or "string" - * @param name the resource name, such as "main" from - * {@code R.layout.main} - * @param isFramework whether the resource is a framework resource - * (android.R) or a local project resource (R) - */ - void visitResourceReference( - @NonNull JavaContext context, - @Nullable AstVisitor visitor, - @NonNull Node node, - @NonNull String type, - @NonNull String name, - boolean isFramework); - - /** - * Returns a list of fully qualified names for super classes that this - * detector cares about. If not null, this detector will *only* be called - * if the current class is a subclass of one of the specified superclasses. - * - * @return a list of fully qualified names - */ - @Nullable - List applicableSuperClasses(); - - /** - * Called for each class that extends one of the super classes specified with - * {@link #applicableSuperClasses()} - * - * @param context the lint scanning context - * @param declaration the class declaration node, or null for anonymous classes - * @param node the class declaration node or the anonymous class construction node - * @param resolvedClass the resolved class - */ - // TODO: Change signature to pass in the NormalTypeBody instead of the plain Node? - void checkClass(@NonNull JavaContext context, @Nullable ClassDeclaration declaration, - @NonNull Node node, @NonNull ResolvedClass resolvedClass); - } - - /** - Interface to be implemented by lint detectors that want to analyze - Java source files. -

- The Lint Java API sits on top of IntelliJ IDEA's "PSI" API, an API - which exposes the underlying abstract syntax tree as well as providing - core services like resolving symbols. -

- This new API replaces the older Lombok AST API that was used for Java - source checks. Migrating a check from the Lombok APIs to the new PSI - based APIs is relatively straightforward. -

- First, replace "implements JavaScanner" with "implements - JavaPsiScanner" in your detector signature, and then locate all the - JavaScanner methods your detector was overriding and replace them with - the new corresponding signatures. -

- For example, replace -

-     {@code List> getApplicableNodeTypes();}
-     
- with -
-     {@code List> getApplicablePsiTypes();}
-     
- and replace -
-     void visitMethod(
-     @NonNull JavaContext context,
-     @Nullable AstVisitor visitor,
-     @NonNull MethodInvocation node);
-     
- with -
-     void visitMethod(
-     @NonNull JavaContext context,
-     @Nullable JavaElementVisitor visitor,
-     @NonNull PsiMethodCallExpression call,
-     @NonNull PsiMethod method);
-     
- and so on. -

- Finally, replace the various Lombok iteration code with PSI based - code. Both Lombok and PSI used class names that closely resemble the - Java language specification, so guessing the corresponding names is - straightforward; here are some examples: -

-     ClassDeclaration ⇒ PsiClass
-     MethodDeclaration ⇒ PsiMethod
-     MethodInvocation ⇒ PsiMethodCallExpression
-     ConstructorInvocation ⇒ PsiNewExpression
-     If ⇒ PsiIfStatement
-     For ⇒ PsiForStatement
-     Continue ⇒ PsiContinueStatement
-     StringLiteral ⇒ PsiLiteral
-     IntegralLiteral ⇒ PsiLiteral
-     ... etc
-     
- Lombok AST had no support for symbol and type resolution, so lint - added its own separate API to support (the "ResolvedNode" - hierarchy). This is no longer needed since PSI supports it directly - (for example, on a PsiMethodCallExpression you just call - "resolveMethod" to get the PsiMethod the method calls, and on a - PsiExpression you just call getType() to get the corresponding -

- The old ResolvedNode interface was written for lint so it made certain - kinds of common checks very easy. To help make porting lint rules from - the old API easier, and to make writing future lint checks easier - too), there is a new helper class, "JavaEvaluator" (which you can - obtain from JavaContext). This lets you for example quickly check - whether a given method is a member of a subclass of a given class, or - whether a method has a certain set of parameters, etc. It also makes - it easy to check whether a given method is private, abstract or - static, and so on. (And most of its parameters are nullable which - makes it simpler to use; you don't have to null check resolve results - before calling into it.) -

- Some further porting tips: -

    -
  • Make sure you don't call toString() on nodes to get their - contents. In Lombok, toString returned the underlying source - text. In PSI, call getText() instead, since toString() is meant for - debugging and includes node types etc. - -
  • ResolvedClass#getName() used to return *qualified* name. In PSI, - PsiClass#getName() returns just the simple name, so call - #getQualifiedName() instead if that's what your code needs! Node - also that PsiClassType#getClassName() returns the simple name; if - you want the fully qualified name, call PsiType#getCanonicalText(). - -
  • Lombok didn't distinguish between a local variable declaration, a - parameter and a field declaration. These are all different in PSI, - so when writing visitors, make sure you replace a single - visitVariableDeclaration with visitField, visitLocalVariable and - visitParameter methods as applicable. - -
  • Note that when lint runs in the IDE, there may be extra PSI nodes in - the hierarchy representing whitespace as well as parentheses. Watch - out for this when calling getParent, getPrevSibling or - getNextSibling - don't just go one level up and check instanceof - {@code }; instead, use LintUtils.skipParentheses (or the - corresponding methods to skip whitespace left and right.) Note that - when you write lint unit tests, the infrastructure will run your - tests twice, one with a normal AST and once where it has inserted - whitespace and parentheses everywhere, and it asserts that you come - up with the same analysis results. (This caught 16 failing tests - across 7 different detectors.) - -
  • Annotation handling is a bit different. In ResolvedAnnotations I had - (for convenience) inlined things like annotations on the class; you - now have to resolve the annotation name reference to the - corresponding annotation class and look there. -
- - Some additional conversion examples: replace -
-     @Override
-     public void visitMethod(@NonNull JavaContext context, @Nullable AstVisitor visitor,
-     @NonNull MethodInvocation node) {
-         ResolvedNode resolved = context.resolve(node);
-         if (resolved instanceof ResolvedMethod) {
-             ResolvedMethod method = (ResolvedMethod) resolved;
-             if (method.getContainingClass().matches("android.os.Parcel")) {
-                 ...
-     
- with -
-     @Override
-     public void visitMethod(@NonNull JavaContext context, @Nullable AstVisitor visitor,
-             @NonNull PsiCall node) {
-         if (method != null && method.getContainingClass() != null &&
-             "android.os.Parcel".equals(method.getContainingClass().getQualifiedName())) {
-             ....
-     
- - Similarly: -
-     if (method.getArgumentCount() != 2
-             || !method.getArgumentType(0).matchesName(TYPE_OBJECT)
-             || !method.getArgumentType(1).matchesName(TYPE_STRING)) {
-         return;
-     }
-     
- can now be written as -
-     JavaEvaluator resolver = context.getEvaluator();
-     if (!resolver.methodMatches(method, WEB_VIEW, true, TYPE_OBJECT, TYPE_STRING)) {
-         return;
-     }
-     
- Finally, note that many deprecated methods in lint itself point to the replacement - methods, see for example {@link JavaContext#findSurroundingMethod(Node)}. - */ - public interface JavaPsiScanner { - /** - * Create a parse tree visitor to process the parse tree. All - * {@link JavaScanner} detectors must provide a visitor, unless they - * either return true from {@link #appliesToResourceRefs()} or return - * non null from {@link #getApplicableMethodNames()}. - *

- * If you return specific AST node types from - * {@link #getApplicablePsiTypes()}, then the visitor will only - * be called for the specific requested node types. This is more - * efficient, since it allows many detectors that apply to only a small - * part of the AST (such as method call nodes) to share iteration of the - * majority of the parse tree. - *

- * If you return null from {@link #getApplicablePsiTypes()}, then your - * visitor will be called from the top and all node types visited. - *

- * Note that a new visitor is created for each separate compilation - * unit, so you can store per file state in the visitor. - *

- * - * NOTE: Your visitor should NOT extend JavaRecursiveElementVisitor. - * Your visitor should only visit the current node type; the infrastructure - * will do the recursion. (Lint's unit test infrastructure will check and - * enforce this restriction.) - * - * - * @param context the {@link Context} for the file being analyzed - * @return a visitor, or null. - */ - @Nullable - JavaElementVisitor createPsiVisitor(@NonNull JavaContext context); - - /** - * Return the types of AST nodes that the visitor returned from - * {@link #createJavaVisitor(JavaContext)} should visit. See the - * documentation for {@link #createJavaVisitor(JavaContext)} for details - * on how the shared visitor is used. - *

- * If you return null from this method, then the visitor will process - * the full tree instead. - *

- * Note that for the shared visitor, the return codes from the visit - * methods are ignored: returning true will not prune iteration - * of the subtree, since there may be other node types interested in the - * children. If you need to ensure that your visitor only processes a - * part of the tree, use a full visitor instead. See the - * OverdrawDetector implementation for an example of this. - * - * @return the list of applicable node types (AST node classes), or null - */ - @Nullable - List> getApplicablePsiTypes(); - - /** - * Return the list of method names this detector is interested in, or - * null. If this method returns non-null, then any AST nodes that match - * a method call in the list will be passed to the - * {@link #visitMethod(JavaContext, JavaElementVisitor, PsiMethodCallExpression, PsiMethod)} - * method for processing. The visitor created by - * {@link #createPsiVisitor(JavaContext)} is also passed to that - * method, although it can be null. - *

- * This makes it easy to write detectors that focus on some fixed calls. - * For example, the StringFormatDetector uses this mechanism to look for - * "format" calls, and when found it looks around (using the AST's - * {@link PsiElement#getParent()} method) to see if it's called on - * a String class instance, and if so do its normal processing. Note - * that since it doesn't need to do any other AST processing, that - * detector does not actually supply a visitor. - * - * @return a set of applicable method names, or null. - */ - @Nullable - List getApplicableMethodNames(); - - /** - * Method invoked for any method calls found that matches any names - * returned by {@link #getApplicableMethodNames()}. This also passes - * back the visitor that was created by - * {@link #createJavaVisitor(JavaContext)}, but a visitor is not - * required. It is intended for detectors that need to do additional AST - * processing, but also want the convenience of not having to look for - * method names on their own. - * - * @param context the context of the lint request - * @param visitor the visitor created from - * {@link #createPsiVisitor(JavaContext)}, or null - * @param call the {@link PsiMethodCallExpression} node for the invoked method - * @param method the {@link PsiMethod} being called - */ - void visitMethod( - @NonNull JavaContext context, - @Nullable JavaElementVisitor visitor, - @NonNull PsiMethodCallExpression call, - @NonNull PsiMethod method); - - /** - * Return the list of constructor types this detector is interested in, or - * null. If this method returns non-null, then any AST nodes that match - * a constructor call in the list will be passed to the - * {@link #visitConstructor(JavaContext, JavaElementVisitor, PsiNewExpression, PsiMethod)} - * method for processing. The visitor created by - * {@link #createJavaVisitor(JavaContext)} is also passed to that - * method, although it can be null. - *

- * This makes it easy to write detectors that focus on some fixed constructors. - * - * @return a set of applicable fully qualified types, or null. - */ - @Nullable - List getApplicableConstructorTypes(); - - /** - * Method invoked for any constructor calls found that matches any names - * returned by {@link #getApplicableConstructorTypes()}. This also passes - * back the visitor that was created by - * {@link #createPsiVisitor(JavaContext)}, but a visitor is not - * required. It is intended for detectors that need to do additional AST - * processing, but also want the convenience of not having to look for - * method names on their own. - * - * @param context the context of the lint request - * @param visitor the visitor created from - * {@link #createPsiVisitor(JavaContext)}, or null - * @param node the {@link PsiNewExpression} node for the invoked method - * @param constructor the called constructor method - */ - void visitConstructor( - @NonNull JavaContext context, - @Nullable JavaElementVisitor visitor, - @NonNull PsiNewExpression node, - @NonNull PsiMethod constructor); - - /** - * Return the list of reference names types this detector is interested in, or null. If this - * method returns non-null, then any AST elements that match a reference in the list will be - * passed to the {@link #visitReference(JavaContext, JavaElementVisitor, - * PsiJavaCodeReferenceElement, PsiElement)} method for processing. The visitor created by - * {@link #createJavaVisitor(JavaContext)} is also passed to that method, although it can be - * null.

This makes it easy to write detectors that focus on some fixed references. - * - * @return a set of applicable reference names, or null. - */ - @Nullable - List getApplicableReferenceNames(); - - /** - * Method invoked for any references found that matches any names returned by {@link - * #getApplicableReferenceNames()}. This also passes back the visitor that was created by - * {@link #createPsiVisitor(JavaContext)}, but a visitor is not required. It is intended for - * detectors that need to do additional AST processing, but also want the convenience of not - * having to look for method names on their own. - * - * @param context the context of the lint request - * @param visitor the visitor created from {@link #createPsiVisitor(JavaContext)}, or - * null - * @param reference the {@link PsiJavaCodeReferenceElement} element - * @param referenced the referenced element - */ - void visitReference( - @NonNull JavaContext context, - @Nullable JavaElementVisitor visitor, - @NonNull PsiJavaCodeReferenceElement reference, - @NonNull PsiElement referenced); - - /** - * Returns whether this detector cares about Android resource references - * (such as {@code R.layout.main} or {@code R.string.app_name}). If it - * does, then the visitor will look for these patterns, and if found, it - * will invoke {@link #visitResourceReference} passing the resource type - * and resource name. It also passes the visitor, if any, that was - * created by {@link #createJavaVisitor(JavaContext)}, such that a - * detector can do more than just look for resources. - * - * @return true if this detector wants to be notified of R resource - * identifiers found in the code. - */ - boolean appliesToResourceRefs(); - - /** - * Called for any resource references (such as {@code R.layout.main} - * found in Java code, provided this detector returned {@code true} from - * {@link #appliesToResourceRefs()}. - * - * @param context the lint scanning context - * @param visitor the visitor created from - * {@link #createPsiVisitor(JavaContext)}, or null - * @param node the variable reference for the resource - * @param type the resource type, such as "layout" or "string" - * @param name the resource name, such as "main" from - * {@code R.layout.main} - * @param isFramework whether the resource is a framework resource - * (android.R) or a local project resource (R) - */ - void visitResourceReference( - @NonNull JavaContext context, - @Nullable JavaElementVisitor visitor, - @NonNull PsiElement node, - @NonNull ResourceType type, - @NonNull String name, - boolean isFramework); - - /** - * Returns a list of fully qualified names for super classes that this - * detector cares about. If not null, this detector will only be called - * if the current class is a subclass of one of the specified superclasses. - * - * @return a list of fully qualified names - */ - @Nullable - List applicableSuperClasses(); - - /** - * Called for each class that extends one of the super classes specified with - * {@link #applicableSuperClasses()}. - *

- * Note: This method will not be called for {@link PsiTypeParameter} classes. These - * aren't really classes in the sense most lint detectors think of them, so these - * are excluded to avoid having lint checks that don't defensively code for these - * accidentally report errors on type parameters. If you really need to check these, - * use {@link #getApplicablePsiTypes} with {@code PsiTypeParameter.class} instead. - * - * @param context the lint scanning context - * @param declaration the class declaration node, or null for anonymous classes - */ - void checkClass(@NonNull JavaContext context, @NonNull PsiClass declaration); - } - - public interface UastScanner { - /** - * Create a parse tree visitor to process the parse tree. All - * {@link JavaScanner} detectors must provide a visitor, unless they - * either return true from {@link #appliesToResourceRefs()} or return - * non null from {@link #getApplicableMethodNames()}. - *

- * If you return specific AST node types from - * {@link #getApplicablePsiTypes()}, then the visitor will only - * be called for the specific requested node types. This is more - * efficient, since it allows many detectors that apply to only a small - * part of the AST (such as method call nodes) to share iteration of the - * majority of the parse tree. - *

- * If you return null from {@link #getApplicablePsiTypes()}, then your - * visitor will be called from the top and all node types visited. - *

- * Note that a new visitor is created for each separate compilation - * unit, so you can store per file state in the visitor. - *

- * - * NOTE: Your visitor should NOT extend JavaRecursiveElementVisitor. - * Your visitor should only visit the current node type; the infrastructure - * will do the recursion. (Lint's unit test infrastructure will check and - * enforce this restriction.) - * - * - * @param context the {@link Context} for the file being analyzed - * @return a visitor, or null. - */ - @Nullable - UastVisitor createUastVisitor(@NonNull JavaContext context); - - /** - * Return the types of AST nodes that the visitor returned from - * {@link #createJavaVisitor(JavaContext)} should visit. See the - * documentation for {@link #createJavaVisitor(JavaContext)} for details - * on how the shared visitor is used. - *

- * If you return null from this method, then the visitor will process - * the full tree instead. - *

- * Note that for the shared visitor, the return codes from the visit - * methods are ignored: returning true will not prune iteration - * of the subtree, since there may be other node types interested in the - * children. If you need to ensure that your visitor only processes a - * part of the tree, use a full visitor instead. See the - * OverdrawDetector implementation for an example of this. - * - * @return the list of applicable node types (AST node classes), or null - */ - @Nullable - List> getApplicableUastTypes(); - - @Nullable - List> getApplicablePsiTypes(); - - /** - * Return the list of method names this detector is interested in, or - * null. If this method returns non-null, then any AST nodes that match - * a method call in the list will be passed to the - * {@link #visitMethod(JavaContext, JavaElementVisitor, PsiMethodCallExpression, PsiMethod)} - * method for processing. The visitor created by - * {@link #createPsiVisitor(JavaContext)} is also passed to that - * method, although it can be null. - *

- * This makes it easy to write detectors that focus on some fixed calls. - * For example, the StringFormatDetector uses this mechanism to look for - * "format" calls, and when found it looks around (using the AST's - * {@link PsiElement#getParent()} method) to see if it's called on - * a String class instance, and if so do its normal processing. Note - * that since it doesn't need to do any other AST processing, that - * detector does not actually supply a visitor. - * - * @return a set of applicable method names, or null. - */ - @Nullable - List getApplicableMethodNames(); - - /** - * Method invoked for any method calls found that matches any names - * returned by {@link #getApplicableMethodNames()}. This also passes - * back the visitor that was created by - * {@link #createJavaVisitor(JavaContext)}, but a visitor is not - * required. It is intended for detectors that need to do additional AST - * processing, but also want the convenience of not having to look for - * method names on their own. - * - * @param context the context of the lint request - * @param visitor the visitor created from - * {@link #createPsiVisitor(JavaContext)}, or null - * @param node the {@link PsiMethodCallExpression} node for the invoked method - * @param method the {@link PsiMethod} being called - */ - void visitMethod( - @NonNull JavaContext context, - @Nullable UastVisitor visitor, - @NonNull UCallExpression node, - @NonNull UMethod method); - - /** - * Return the list of constructor types this detector is interested in, or - * null. If this method returns non-null, then any AST nodes that match - * a constructor call in the list will be passed to the - * {@link #visitConstructor(JavaContext, JavaElementVisitor, PsiNewExpression, PsiMethod)} - * method for processing. The visitor created by - * {@link #createJavaVisitor(JavaContext)} is also passed to that - * method, although it can be null. - *

- * This makes it easy to write detectors that focus on some fixed constructors. - * - * @return a set of applicable fully qualified types, or null. - */ - @Nullable - List getApplicableConstructorTypes(); - - /** - * Method invoked for any constructor calls found that matches any names - * returned by {@link #getApplicableConstructorTypes()}. This also passes - * back the visitor that was created by - * {@link #createPsiVisitor(JavaContext)}, but a visitor is not - * required. It is intended for detectors that need to do additional AST - * processing, but also want the convenience of not having to look for - * method names on their own. - * - * @param context the context of the lint request - * @param visitor the visitor created from - * {@link #createPsiVisitor(JavaContext)}, or null - * @param node the {@link PsiNewExpression} node for the invoked method - * @param constructor the called constructor method - */ - void visitConstructor( - @NonNull JavaContext context, - @Nullable UastVisitor visitor, - @NonNull UCallExpression node, - @NonNull UMethod constructor); - - /** - * Return the list of reference names types this detector is interested in, or null. If this - * method returns non-null, then any AST elements that match a reference in the list will be - * passed to the {@link #visitReference(JavaContext, JavaElementVisitor, - * PsiJavaCodeReferenceElement, PsiElement)} method for processing. The visitor created by - * {@link #createJavaVisitor(JavaContext)} is also passed to that method, although it can be - * null.

This makes it easy to write detectors that focus on some fixed references. - * - * @return a set of applicable reference names, or null. - */ - @Nullable - List getApplicableReferenceNames(); - - /** - * Method invoked for any references found that matches any names returned by {@link - * #getApplicableReferenceNames()}. This also passes back the visitor that was created by - * {@link #createPsiVisitor(JavaContext)}, but a visitor is not required. It is intended for - * detectors that need to do additional AST processing, but also want the convenience of not - * having to look for method names on their own. - * - * @param context the context of the lint request - * @param visitor the visitor created from {@link #createPsiVisitor(JavaContext)}, or - * null - * @param reference the {@link PsiJavaCodeReferenceElement} element - * @param referenced the referenced element - */ - void visitReference( - @NonNull JavaContext context, - @Nullable UastVisitor visitor, - @NonNull UReferenceExpression reference, - @NonNull PsiElement referenced); - - /** - * Returns whether this detector cares about Android resource references - * (such as {@code R.layout.main} or {@code R.string.app_name}). If it - * does, then the visitor will look for these patterns, and if found, it - * will invoke {@link #visitResourceReference} passing the resource type - * and resource name. It also passes the visitor, if any, that was - * created by {@link #createJavaVisitor(JavaContext)}, such that a - * detector can do more than just look for resources. - * - * @return true if this detector wants to be notified of R resource - * identifiers found in the code. - */ - boolean appliesToResourceRefs(); - - /** - * Called for any resource references (such as {@code R.layout.main} - * found in Java code, provided this detector returned {@code true} from - * {@link #appliesToResourceRefs()}. - * - * @param context the lint scanning context - * @param visitor the visitor created from - * {@link #createPsiVisitor(JavaContext)}, or null - * @param node the variable reference for the resource - * @param type the resource type, such as "layout" or "string" - * @param name the resource name, such as "main" from - * {@code R.layout.main} - * @param isFramework whether the resource is a framework resource - * (android.R) or a local project resource (R) - */ - void visitResourceReference( - @NonNull JavaContext context, - @Nullable UastVisitor visitor, - @NonNull UElement node, - @NonNull ResourceType type, - @NonNull String name, - boolean isFramework); - - /** - * Returns a list of fully qualified names for super classes that this - * detector cares about. If not null, this detector will only be called - * if the current class is a subclass of one of the specified superclasses. - * - * @return a list of fully qualified names - */ - @Nullable - List applicableSuperClasses(); - - /** - * Called for each class that extends one of the super classes specified with - * {@link #applicableSuperClasses()}. - *

- * Note: This method will not be called for {@link PsiTypeParameter} classes. These - * aren't really classes in the sense most lint detectors think of them, so these - * are excluded to avoid having lint checks that don't defensively code for these - * accidentally report errors on type parameters. If you really need to check these, - * use {@link #getApplicablePsiTypes} with {@code PsiTypeParameter.class} instead. - * - * @param context the lint scanning context - * @param declaration the class declaration node, or null for anonymous classes - */ - void checkClass(@NonNull JavaContext context, @NonNull UClass declaration); - } - - /** Specialized interface for detectors that scan Java class files */ - public interface ClassScanner { - /** - * Checks the given class' bytecode for issues. - * - * @param context the context of the lint check, pointing to for example - * the file - * @param classNode the root class node - */ - void checkClass(@NonNull ClassContext context, @NonNull ClassNode classNode); - - /** - * Returns the list of node types (corresponding to the constants in the - * {@link AbstractInsnNode} class) that this scanner applies to. The - * {@link #checkInstruction(ClassContext, ClassNode, MethodNode, AbstractInsnNode)} - * method will be called for each match. - * - * @return an array containing all the node types this detector should be - * called for, or null if none. - */ - @Nullable - int[] getApplicableAsmNodeTypes(); - - /** - * Process a given instruction node, and register lint issues if - * applicable. - * - * @param context the context of the lint check, pointing to for example - * the file - * @param classNode the root class node - * @param method the method node containing the call - * @param instruction the actual instruction - */ - void checkInstruction(@NonNull ClassContext context, @NonNull ClassNode classNode, - @NonNull MethodNode method, @NonNull AbstractInsnNode instruction); - - /** - * Return the list of method call names (in VM format, e.g. {@code ""} for - * constructors, etc) for method calls this detector is interested in, - * or null. T his will be used to dispatch calls to - * {@link #checkCall(ClassContext, ClassNode, MethodNode, MethodInsnNode)} - * for only the method calls in owners that the detector is interested - * in. - *

- * NOTE: If you return non null from this method, then only - * {@link #checkCall(ClassContext, ClassNode, MethodNode, MethodInsnNode)} - * will be called if a suitable method is found; - * {@link #checkClass(ClassContext, ClassNode)} will not be called under - * any circumstances. - *

- * This makes it easy to write detectors that focus on some fixed calls, - * and allows lint to make a single pass over the bytecode over a class, - * and efficiently dispatch method calls to any detectors that are - * interested in it. Without this, each new lint check interested in a - * single method, would be doing a complete pass through all the - * bytecode instructions of the class via the - * {@link #checkClass(ClassContext, ClassNode)} method, which would make - * each newly added lint check make lint slower. Now a single dispatch - * map is used instead, and for each encountered call in the single - * dispatch, it looks up in the map which if any detectors are - * interested in the given call name, and dispatches to each one in - * turn. - * - * @return a list of applicable method names, or null. - */ - @Nullable - List getApplicableCallNames(); - - /** - * Just like {@link Detector#getApplicableCallNames()}, but for the owner - * field instead. The - * {@link #checkCall(ClassContext, ClassNode, MethodNode, MethodInsnNode)} - * method will be called for all {@link MethodInsnNode} instances where the - * owner field matches any of the members returned in this node. - *

- * Note that if your detector provides both a name and an owner, the - * method will be called for any nodes matching either the name or - * the owner, not only where they match both. Note also that it will - * be called twice - once for the name match, and (at least once) for the owner - * match. - * - * @return a list of applicable owner names, or null. - */ - @Nullable - List getApplicableCallOwners(); - - /** - * Process a given method call node, and register lint issues if - * applicable. This is similar to the - * {@link #checkInstruction(ClassContext, ClassNode, MethodNode, AbstractInsnNode)} - * method, but has the additional advantage that it is only called for known - * method names or method owners, according to - * {@link #getApplicableCallNames()} and {@link #getApplicableCallOwners()}. - * - * @param context the context of the lint check, pointing to for example - * the file - * @param classNode the root class node - * @param method the method node containing the call - * @param call the actual method call node - */ - void checkCall(@NonNull ClassContext context, @NonNull ClassNode classNode, - @NonNull MethodNode method, @NonNull MethodInsnNode call); - } - - /** - * Specialized interface for detectors that scan binary resource files - * (typically bitmaps but also files in res/raw) - */ - public interface BinaryResourceScanner { - /** - * Called for each resource folder - * - * @param context the context for the resource file - */ - void checkBinaryResource(@NonNull ResourceContext context); - - /** - * Returns whether this detector applies to the given folder type. This - * allows the detectors to be pruned from iteration, so for example when we - * are analyzing a string value file we don't need to look up detectors - * related to layout. - * - * @param folderType the folder type to be visited - * @return true if this detector can apply to resources in folders of the - * given type - */ - boolean appliesTo(@NonNull ResourceFolderType folderType); - } - - /** Specialized interface for detectors that scan resource folders (the folder directory - * itself, not the individual files within it */ - public interface ResourceFolderScanner { - /** - * Called for each resource folder - * - * @param context the context for the resource folder - * @param folderName the resource folder name - */ - void checkFolder(@NonNull ResourceContext context, @NonNull String folderName); - - /** - * Returns whether this detector applies to the given folder type. This - * allows the detectors to be pruned from iteration, so for example when we - * are analyzing a string value file we don't need to look up detectors - * related to layout. - * - * @param folderType the folder type to be visited - * @return true if this detector can apply to resources in folders of the - * given type - */ - boolean appliesTo(@NonNull ResourceFolderType folderType); - } - - /** Specialized interface for detectors that scan XML files */ - public interface XmlScanner { - /** - * Visit the given document. The detector is responsible for its own iteration - * through the document. - * @param context information about the document being analyzed - * @param document the document to examine - */ - void visitDocument(@NonNull XmlContext context, @NonNull Document document); - - /** - * Visit the given element. - * @param context information about the document being analyzed - * @param element the element to examine - */ - void visitElement(@NonNull XmlContext context, @NonNull Element element); - - /** - * Visit the given element after its children have been analyzed. - * @param context information about the document being analyzed - * @param element the element to examine - */ - void visitElementAfter(@NonNull XmlContext context, @NonNull Element element); - - /** - * Visit the given attribute. - * @param context information about the document being analyzed - * @param attribute the attribute node to examine - */ - void visitAttribute(@NonNull XmlContext context, @NonNull Attr attribute); - - /** - * Returns the list of elements that this detector wants to analyze. If non - * null, this detector will be called (specifically, the - * {@link #visitElement} method) for each matching element in the document. - *

- * If this method returns null, and {@link #getApplicableAttributes()} also returns - * null, then the {@link #visitDocument} method will be called instead. - * - * @return a collection of elements, or null, or the special - * {@link XmlScanner#ALL} marker to indicate that every single - * element should be analyzed. - */ - @Nullable - Collection getApplicableElements(); - - /** - * Returns the list of attributes that this detector wants to analyze. If non - * null, this detector will be called (specifically, the - * {@link #visitAttribute} method) for each matching attribute in the document. - *

- * If this method returns null, and {@link #getApplicableElements()} also returns - * null, then the {@link #visitDocument} method will be called instead. - * - * @return a collection of attributes, or null, or the special - * {@link XmlScanner#ALL} marker to indicate that every single - * attribute should be analyzed. - */ - @Nullable - Collection getApplicableAttributes(); - - /** - * Special marker collection returned by {@link #getApplicableElements()} or - * {@link #getApplicableAttributes()} to indicate that the check should be - * invoked on all elements or all attributes - */ - @NonNull - List ALL = new ArrayList(0); // NOT Collections.EMPTY! - // We want to distinguish this from just an *empty* list returned by the caller! - } - - /** Specialized interface for detectors that scan Gradle files */ - public interface GradleScanner { - void visitBuildScript(@NonNull Context context, Map sharedData); - } - - /** Specialized interface for detectors that scan other files */ - public interface OtherFileScanner { - /** - * Returns the set of files this scanner wants to consider. If this includes - * {@link Scope#OTHER} then all source files will be checked. Note that the - * set of files will not just include files of the indicated type, but all files - * within the relevant source folder. For example, returning {@link Scope#JAVA_FILE} - * will not just return {@code .java} files, but also other resource files such as - * {@code .html} and other files found within the Java source folders. - *

- * Lint will call the {@link #run(Context)}} method when the file should be checked. - * - * @return set of scopes that define the types of source files the - * detector wants to consider - */ - @NonNull - EnumSet getApplicableFiles(); - } - - /** - * Runs the detector. This method will not be called for certain specialized - * detectors, such as {@link XmlScanner} and {@link JavaScanner}, where - * there are specialized analysis methods instead such as - * {@link XmlScanner#visitElement(XmlContext, Element)}. - * - * @param context the context describing the work to be done - */ - public void run(@NonNull Context context) { - } - - /** - * Returns true if this detector applies to the given file - * - * @param context the context to check - * @param file the file in the context to check - * @return true if this detector applies to the given context and file - */ - @Deprecated // Slated for removal in lint 2.0 - public boolean appliesTo(@NonNull Context context, @NonNull File file) { - return false; - } - - /** - * Analysis is about to begin, perform any setup steps. - * - * @param context the context for the check referencing the project, lint - * client, etc - */ - public void beforeCheckProject(@NonNull Context context) { - } - - /** - * Analysis has just been finished for the whole project, perform any - * cleanup or report issues that require project-wide analysis. - * - * @param context the context for the check referencing the project, lint - * client, etc - */ - public void afterCheckProject(@NonNull Context context) { - } - - /** - * Analysis is about to begin for the given library project, perform any setup steps. - * - * @param context the context for the check referencing the project, lint - * client, etc - */ - public void beforeCheckLibraryProject(@NonNull Context context) { - } - - /** - * Analysis has just been finished for the given library project, perform any - * cleanup or report issues that require library-project-wide analysis. - * - * @param context the context for the check referencing the project, lint - * client, etc - */ - public void afterCheckLibraryProject(@NonNull Context context) { - } - - /** - * Analysis is about to be performed on a specific file, perform any setup - * steps. - *

- * Note: When this method is called at the beginning of checking an XML - * file, the context is guaranteed to be an instance of {@link XmlContext}, - * and similarly for a Java source file, the context will be a - * {@link JavaContext} and so on. - * - * @param context the context for the check referencing the file to be - * checked, the project, etc. - */ - public void beforeCheckFile(@NonNull Context context) { - } - - /** - * Analysis has just been finished for a specific file, perform any cleanup - * or report issues found - *

- * Note: When this method is called at the end of checking an XML - * file, the context is guaranteed to be an instance of {@link XmlContext}, - * and similarly for a Java source file, the context will be a - * {@link JavaContext} and so on. - * - * @param context the context for the check referencing the file to be - * checked, the project, etc. - */ - public void afterCheckFile(@NonNull Context context) { - } - - /** - * Returns the expected speed of this detector - * - * @return the expected speed of this detector - */ - @NonNull - @Deprecated // Slated for removal in Lint 2.0 - public Speed getSpeed() { - return Speed.NORMAL; - } - - /** - * Returns the expected speed of this detector. - * The issue parameter is made available for subclasses which analyze multiple issues - * and which need to distinguish implementation cost by issue. If the detector does - * not analyze multiple issues or does not vary in speed by issue type, just override - * {@link #getSpeed()} instead. - * - * @param issue the issue to look up the analysis speed for - * @return the expected speed of this detector - */ - @NonNull - @Deprecated // Slated for removal in Lint 2.0 - public Speed getSpeed(@SuppressWarnings("UnusedParameters") @NonNull Issue issue) { - // If not overridden, this detector does not distinguish speed by issue type - return getSpeed(); - } - - // ---- Dummy implementations to make implementing XmlScanner easier: ---- - - @SuppressWarnings({"UnusedParameters", "unused", "javadoc"}) - public void visitDocument(@NonNull XmlContext context, @NonNull Document document) { - // This method must be overridden if your detector does - // not return something from getApplicableElements or - // getApplicableAttributes - assert false; - } - - @SuppressWarnings({"UnusedParameters", "unused", "javadoc"}) - public void visitElement(@NonNull XmlContext context, @NonNull Element element) { - // This method must be overridden if your detector returns - // tag names from getApplicableElements - assert false; - } - - @SuppressWarnings({"UnusedParameters", "unused", "javadoc"}) - public void visitElementAfter(@NonNull XmlContext context, @NonNull Element element) { - } - - @SuppressWarnings({"UnusedParameters", "unused", "javadoc"}) - public void visitAttribute(@NonNull XmlContext context, @NonNull Attr attribute) { - // This method must be overridden if your detector returns - // attribute names from getApplicableAttributes - assert false; - } - - @SuppressWarnings("javadoc") - @Nullable - public Collection getApplicableElements() { - return null; - } - - @Nullable - @SuppressWarnings("javadoc") - public Collection getApplicableAttributes() { - return null; - } - - // ---- Dummy implementations to make implementing JavaScanner easier: ---- - - @Deprecated @Nullable @SuppressWarnings({"UnusedParameters", "unused", "javadoc"}) - public AstVisitor createJavaVisitor(@NonNull JavaContext context) { - return null; - } - - @Deprecated @Nullable@SuppressWarnings({"UnusedParameters", "unused", "javadoc"}) - public List> getApplicableNodeTypes() { - return null; - } - - @Deprecated @SuppressWarnings({"UnusedParameters", "unused", "javadoc"}) - public void visitMethod(@NonNull JavaContext context, @Nullable AstVisitor visitor, - @NonNull MethodInvocation node) { - } - - @Deprecated @SuppressWarnings({"UnusedParameters", "unused", "javadoc"}) - public void visitResourceReference(@NonNull JavaContext context, @Nullable AstVisitor visitor, - @NonNull Node node, @NonNull String type, @NonNull String name, - boolean isFramework) { - } - - @Deprecated @SuppressWarnings({"UnusedParameters", "unused", "javadoc"}) - public void checkClass(@NonNull JavaContext context, @Nullable ClassDeclaration declaration, - @NonNull Node node, @NonNull ResolvedClass resolvedClass) { - } - - @Deprecated @SuppressWarnings({"UnusedParameters", "unused", "javadoc"}) - public void visitConstructor( - @NonNull JavaContext context, - @Nullable AstVisitor visitor, - @NonNull ConstructorInvocation node, - @NonNull ResolvedMethod constructor) { - } - - // ---- Dummy implementations to make implementing a ClassScanner easier: ---- - - @SuppressWarnings("javadoc") - public void checkClass(@NonNull ClassContext context, @NonNull ClassNode classNode) { - } - - @SuppressWarnings("javadoc") - @Nullable - public List getApplicableCallNames() { - return null; - } - - @SuppressWarnings("javadoc") - @Nullable - public List getApplicableCallOwners() { - return null; - } - - @SuppressWarnings("javadoc") - public void checkCall(@NonNull ClassContext context, @NonNull ClassNode classNode, - @NonNull MethodNode method, @NonNull MethodInsnNode call) { - } - - @SuppressWarnings("javadoc") - @Nullable - public int[] getApplicableAsmNodeTypes() { - return null; - } - - @SuppressWarnings("javadoc") - public void checkInstruction(@NonNull ClassContext context, @NonNull ClassNode classNode, - @NonNull MethodNode method, @NonNull AbstractInsnNode instruction) { - } - - // ---- Dummy implementations to make implementing an OtherFileScanner easier: ---- - - @SuppressWarnings({"UnusedParameters", "unused"}) - public boolean appliesToFolder(@NonNull Scope scope, @Nullable ResourceFolderType folderType) { - return false; - } - - @NonNull - public EnumSet getApplicableFiles() { - return Scope.OTHER_SCOPE; - } - - // ---- Dummy implementations to make implementing an GradleScanner easier: ---- - - public void visitBuildScript(@NonNull Context context, Map sharedData) { - } - - // ---- Dummy implementations to make implementing a resource folder scanner easier: ---- - - public void checkFolder(@NonNull ResourceContext context, @NonNull String folderName) { - } - - // ---- Dummy implementations to make implementing a binary resource scanner easier: ---- - - public void checkBinaryResource(@NonNull ResourceContext context) { - } - - public boolean appliesTo(@NonNull ResourceFolderType folderType) { - return true; - } - - // ---- Dummy implementation to make implementing UastScanner easier: ---- - - public void checkClass(@NonNull JavaContext context, @NonNull UClass declaration) { - } - - public void visitReference( - @NonNull JavaContext context, - @Nullable UastVisitor visitor, - @NonNull UReferenceExpression reference, - @NonNull PsiElement referenced) { - } - - public void visitConstructor( - @NonNull JavaContext context, - @Nullable UastVisitor visitor, - @NonNull UCallExpression node, - @NonNull UMethod constructor) { - } - - public void visitMethod( - @NonNull JavaContext context, - @Nullable UastVisitor visitor, - @NonNull UCallExpression node, - @NonNull UMethod method) { - } - - @Nullable - public UastVisitor createUastVisitor(@NonNull JavaContext context) { - return null; - } - - @Nullable - public List> getApplicableUastTypes() { - return null; - } - - public void visitResourceReference( - @NonNull JavaContext context, - @Nullable UastVisitor visitor, - @NonNull UElement node, - @NonNull ResourceType type, - @NonNull String name, - boolean isFramework) { - } - - // ---- Dummy implementation to make implementing JavaPsiScanner easier: ---- - - @Nullable - public List getApplicableMethodNames() { - return null; - } - - @Nullable @SuppressWarnings({"UnusedParameters", "unused", "javadoc"}) - public List getApplicableConstructorTypes() { - return null; - } - - @SuppressWarnings({"UnusedParameters", "unused", "javadoc"}) - public boolean appliesToResourceRefs() { - return false; - } - - @Nullable @SuppressWarnings({"UnusedParameters", "unused", "javadoc"}) - public List applicableSuperClasses() { - return null; - } - - @SuppressWarnings({"UnusedParameters", "unused", "javadoc"}) - public void visitMethod(@NonNull JavaContext context, @Nullable JavaElementVisitor visitor, - @NonNull PsiMethodCallExpression call, @NonNull PsiMethod method) { - } - - @SuppressWarnings({"UnusedParameters", "unused", "javadoc"}) - public void visitConstructor( - @NonNull JavaContext context, - @Nullable JavaElementVisitor visitor, - @NonNull PsiNewExpression node, - @NonNull PsiMethod constructor) { - } - - @SuppressWarnings({"UnusedParameters", "unused", "javadoc"}) - public void visitResourceReference(@NonNull JavaContext context, - @Nullable JavaElementVisitor visitor, @NonNull PsiElement node, - @NonNull ResourceType type, @NonNull String name, boolean isFramework) { - } - - @SuppressWarnings({"UnusedParameters", "unused", "javadoc"}) - public void checkClass(@NonNull JavaContext context, @NonNull PsiClass declaration) { - } - - @Nullable @SuppressWarnings({"UnusedParameters", "unused", "javadoc"}) - public JavaElementVisitor createPsiVisitor(@NonNull JavaContext context) { - return null; - } - - @Nullable @SuppressWarnings({"UnusedParameters", "unused", "javadoc"}) - public List> getApplicablePsiTypes() { - return null; - } - - @Nullable @SuppressWarnings({"unused", "javadoc"}) - public List getApplicableReferenceNames() { - return null; - } - - @SuppressWarnings({"UnusedParameters", "unused", "javadoc"}) - public void visitReference( - @NonNull JavaContext context, - @Nullable JavaElementVisitor visitor, - @NonNull PsiJavaCodeReferenceElement reference, - @NonNull PsiElement referenced) { - } -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/Implementation.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/Implementation.java.173 deleted file mode 100644 index eb5358c1737..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/Implementation.java.173 +++ /dev/null @@ -1,189 +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 com.android.tools.klint.detector.api; - -import com.android.annotations.NonNull; -import com.google.common.annotations.Beta; - -import java.util.EnumSet; - -/** - * An {@linkplain Implementation} of an {@link Issue} maps to the {@link Detector} - * class responsible for analyzing the issue, as well as the {@link Scope} required - * by the detector to perform its analysis. - *

- * NOTE: This is not a public or final API; if you rely on this be prepared - * to adjust your code for the next tools release. - */ -@Beta -public class Implementation { - private final Class mClass; - private final EnumSet mScope; - private EnumSet[] mAnalysisScopes; - - @SuppressWarnings("unchecked") - private static final EnumSet[] EMPTY = new EnumSet[0]; - - /** - * Creates a new implementation for analyzing one or more issues - * - * @param detectorClass the class of the detector to find this issue - * @param scope the scope of files required to analyze this issue - */ - @SuppressWarnings("unchecked") - public Implementation( - @NonNull Class detectorClass, - @NonNull EnumSet scope) { - this(detectorClass, scope, EMPTY); - } - - /** - * Creates a new implementation for analyzing one or more issues - * - * @param detectorClass the class of the detector to find this issue - * @param scope the scope of files required to analyze this issue - * @param analysisScopes optional set of extra scopes the detector is capable of working in - */ - public Implementation( - @NonNull Class detectorClass, - @NonNull EnumSet scope, - @NonNull EnumSet... analysisScopes) { - mClass = detectorClass; - mScope = scope; - mAnalysisScopes = analysisScopes; - } - - /** - * Returns the class of the detector to use to find this issue - * - * @return the class of the detector to use to find this issue - */ - @NonNull - public Class getDetectorClass() { - return mClass; - } - - @Override - public String toString() { - return mClass.toString(); - } - - /** - * Returns the scope required to analyze the code to detect this issue. - * This is determined by the detectors which reports the issue. - * - * @return the required scope - */ - @NonNull - public EnumSet getScope() { - return mScope; - } - - /** - * Returns the sets of scopes required to analyze this issue, or null if all - * scopes named by {@link #getScope()} are necessary. Note that only - * one match out of this collection is required, not all, and that - * the scope set returned by {@link #getScope()} does not have to be returned - * by this method, but is always implied to be included. - *

- * The scopes returned by {@link #getScope()} list all the various - * scopes that are affected by this issue, meaning the detector - * should consider it. Frequently, the detector must analyze all these - * scopes in order to properly decide whether an issue is found. For - * example, the unused resource detector needs to consider both the XML - * resource files and the Java source files in order to decide if a resource - * is unused. If it analyzes just the Java files for example, it might - * incorrectly conclude that a resource is unused because it did not - * discover a resource reference in an XML file. - *

- * However, there are other issues where the issue can occur in a variety of - * files, but the detector can consider each in isolation. For example, the - * API checker is affected by both XML files and Java class files (detecting - * both layout constructor references in XML layout files as well as code - * references in .class files). It doesn't have to analyze both; it is - * capable of incrementally analyzing just an XML file, or just a class - * file, without considering the other. - *

- * The required scope list provides a list of scope sets that can be used to - * analyze this issue. For each scope set, all the scopes must be matched by - * the incremental analysis, but any one of the scope sets can be analyzed - * in isolation. - *

- * The required scope list is not required to include the full scope set - * returned by {@link #getScope()}; that set is always assumed to be - * included. - *

- * NOTE: You would normally call {@link #isAdequate(EnumSet)} rather - * than calling this method directly. - * - * @return a list of required scopes, or null. - */ - @NonNull - public EnumSet[] getAnalysisScopes() { - return mAnalysisScopes; - } - - /** - * Returns true if the given scope is adequate for analyzing this issue. - * This looks through the analysis scopes (see - * {@link #getAnalysisScopes()}) and if the scope passed in fully - * covers at least one of them, or if it covers the scope of the issue - * itself (see {@link #getScope()}, which should be a superset of all the - * analysis scopes) returns true. - *

- * The scope set returned by {@link #getScope()} lists all the various - * scopes that are affected by this issue, meaning the detector - * should consider it. Frequently, the detector must analyze all these - * scopes in order to properly decide whether an issue is found. For - * example, the unused resource detector needs to consider both the XML - * resource files and the Java source files in order to decide if a resource - * is unused. If it analyzes just the Java files for example, it might - * incorrectly conclude that a resource is unused because it did not - * discover a resource reference in an XML file. - *

- * However, there are other issues where the issue can occur in a variety of - * files, but the detector can consider each in isolation. For example, the - * API checker is affected by both XML files and Java class files (detecting - * both layout constructor references in XML layout files as well as code - * references in .class files). It doesn't have to analyze both; it is - * capable of incrementally analyzing just an XML file, or just a class - * file, without considering the other. - *

- * An issue can register additional scope sets that can are adequate - * for analyzing the issue, by supplying it to - * {@link #Implementation(Class, java.util.EnumSet, java.util.EnumSet[])}. - * This method returns true if the given scope matches one or more analysis - * scope, or the overall scope. - * - * @param scope the scope available for analysis - * @return true if this issue can be analyzed with the given available scope - */ - public boolean isAdequate(@NonNull EnumSet scope) { - if (scope.containsAll(mScope)) { - return true; - } - - if (mAnalysisScopes != null) { - for (EnumSet analysisScope : mAnalysisScopes) { - if (scope.containsAll(analysisScope)) { - return true; - } - } - } - - return false; - } -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/Issue.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/Issue.java.173 deleted file mode 100644 index 24271325471..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/Issue.java.173 +++ /dev/null @@ -1,307 +0,0 @@ -/* - * Copyright (C) 2011 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.detector.api; - -import static com.android.tools.klint.detector.api.TextFormat.RAW; - -import com.android.annotations.NonNull; -import com.android.tools.klint.client.api.Configuration; -import com.google.common.annotations.Beta; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - - -/** - * An issue is a potential bug in an Android application. An issue is discovered - * by a {@link Detector}, and has an associated {@link Severity}. - *

- * Issues and detectors are separate classes because a detector can discover - * multiple different issues as it's analyzing code, and we want to be able to - * different severities for different issues, the ability to suppress one but - * not other issues from the same detector, and so on. - *

- * NOTE: This is not a public or final API; if you rely on this be prepared - * to adjust your code for the next tools release. - */ -@Beta -public final class Issue implements Comparable { - private final String mId; - private final String mBriefDescription; - private final String mExplanation; - private final Category mCategory; - private final int mPriority; - private final Severity mSeverity; - private Object mMoreInfoUrls; - private boolean mEnabledByDefault = true; - private Implementation mImplementation; - - // Use factory methods - private Issue( - @NonNull String id, - @NonNull String shortDescription, - @NonNull String explanation, - @NonNull Category category, - int priority, - @NonNull Severity severity, - @NonNull Implementation implementation) { - assert !shortDescription.isEmpty(); - assert !explanation.isEmpty(); - - mId = id; - mBriefDescription = shortDescription; - mExplanation = explanation; - mCategory = category; - mPriority = priority; - mSeverity = severity; - mImplementation = implementation; - } - - /** - * Creates a new issue. The description strings can use some simple markup; - * see the {@link TextFormat#RAW} documentation - * for details. - * - * @param id the fixed id of the issue - * @param briefDescription short summary (typically 5-6 words or less), typically - * describing the problem rather than the fix - * (e.g. "Missing minSdkVersion") - * @param explanation a full explanation of the issue, with suggestions for - * how to fix it - * @param category the associated category, if any - * @param priority the priority, a number from 1 to 10 with 10 being most - * important/severe - * @param severity the default severity of the issue - * @param implementation the default implementation for this issue - * @return a new {@link Issue} - */ - @NonNull - public static Issue create( - @NonNull String id, - @NonNull String briefDescription, - @NonNull String explanation, - @NonNull Category category, - int priority, - @NonNull Severity severity, - @NonNull Implementation implementation) { - return new Issue(id, briefDescription, explanation, category, priority, - severity, implementation); - } - - /** - * For compatibility with older custom rules) - * - * @deprecated Use {@link #create(String, String, String, Category, int, Severity, Implementation)} instead - */ - @NonNull - @Deprecated - public static Issue create( - @NonNull String id, - @NonNull String briefDescription, - @SuppressWarnings("UnusedParameters") @NonNull String description, - @NonNull String explanation, - @NonNull Category category, - int priority, - @NonNull Severity severity, - @NonNull Implementation implementation) { - return new Issue(id, briefDescription, explanation, category, priority, - severity, implementation); - } - - /** - * Returns the unique id of this issue. These should not change over time - * since they are used to persist the names of issues suppressed by the user - * etc. It is typically a single camel-cased word. - * - * @return the associated fixed id, never null and always unique - */ - @NonNull - public String getId() { - return mId; - } - - /** - * Briefly (in a couple of words) describes these errors - * - * @return a brief summary of the issue, never null, never empty - */ - @NonNull - public String getBriefDescription(@NonNull TextFormat format) { - return RAW.convertTo(mBriefDescription, format); - } - - /** - * Describes the error found by this rule, e.g. - * "Buttons must define contentDescriptions". Preferably the explanation - * should also contain a description of how the problem should be solved. - * Additional info can be provided via {@link #getMoreInfo()}. - * - * @param format the format to write the format as - * @return an explanation of the issue, never null, never empty - */ - @NonNull - public String getExplanation(@NonNull TextFormat format) { - return RAW.convertTo(mExplanation, format); - } - - /** - * The primary category of the issue - * - * @return the primary category of the issue, never null - */ - @NonNull - public Category getCategory() { - return mCategory; - } - - /** - * Returns a priority, in the range 1-10, with 10 being the most severe and - * 1 the least - * - * @return a priority from 1 to 10 - */ - public int getPriority() { - return mPriority; - } - - /** - * Returns the default severity of the issues found by this detector (some - * tools may allow the user to specify custom severities for detectors). - *

- * Note that even though the normal way for an issue to be disabled is for - * the {@link Configuration} to return {@link Severity#IGNORE}, there is a - * {@link #isEnabledByDefault()} method which can be used to turn off issues - * by default. This is done rather than just having the severity as the only - * attribute on the issue such that an issue can be configured with an - * appropriate severity (such as {@link Severity#ERROR}) even when issues - * are disabled by default for example because they are experimental or not - * yet stable. - * - * @return the severity of the issues found by this detector - */ - @NonNull - public Severity getDefaultSeverity() { - return mSeverity; - } - - /** - * Returns a link (a URL string) to more information, or null - * - * @return a link to more information, or null - */ - @NonNull - public List getMoreInfo() { - if (mMoreInfoUrls == null) { - return Collections.emptyList(); - } else if (mMoreInfoUrls instanceof String) { - return Collections.singletonList((String) mMoreInfoUrls); - } else { - assert mMoreInfoUrls instanceof List; - //noinspection unchecked - return (List) mMoreInfoUrls; - } - } - - /** - * Adds a more info URL string - * - * @param moreInfoUrl url string - * @return this, for constructor chaining - */ - @NonNull - public Issue addMoreInfo(@NonNull String moreInfoUrl) { - // Nearly all issues supply at most a single URL, so don't bother with - // lists wrappers for most of these issues - if (mMoreInfoUrls == null) { - mMoreInfoUrls = moreInfoUrl; - } else if (mMoreInfoUrls instanceof String) { - String existing = (String) mMoreInfoUrls; - List list = new ArrayList(2); - list.add(existing); - list.add(moreInfoUrl); - mMoreInfoUrls = list; - } else { - assert mMoreInfoUrls instanceof List; - //noinspection unchecked - ((List) mMoreInfoUrls).add(moreInfoUrl); - } - return this; - } - - /** - * Returns whether this issue should be enabled by default, unless the user - * has explicitly disabled it. - * - * @return true if this issue should be enabled by default - */ - public boolean isEnabledByDefault() { - return mEnabledByDefault; - } - - /** - * Returns the implementation for the given issue - * - * @return the implementation for this issue - */ - @NonNull - public Implementation getImplementation() { - return mImplementation; - } - - /** - * Sets the implementation for the given issue. This is typically done by - * IDEs that can offer a replacement for a given issue which performs better - * or in some other way works better within the IDE. - * - * @param implementation the new implementation to use - */ - public void setImplementation(@NonNull Implementation implementation) { - mImplementation = implementation; - } - - /** - * Sorts the detectors alphabetically by id. This is intended to make it - * convenient to store settings for detectors in a fixed order. It is not - * intended as the order to be shown to the user; for that, a tool embedding - * lint might consider the priorities, categories, severities etc of the - * various detectors. - * - * @param other the {@link Issue} to compare this issue to - */ - @Override - public int compareTo(@NonNull Issue other) { - return getId().compareTo(other.getId()); - } - - /** - * Sets whether this issue is enabled by default. - * - * @param enabledByDefault whether the issue should be enabled by default - * @return this, for constructor chaining - */ - @NonNull - public Issue setEnabledByDefault(boolean enabledByDefault) { - mEnabledByDefault = enabledByDefault; - return this; - } - - @Override - public String toString() { - return mId; - } -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/JavaContext.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/JavaContext.java.173 deleted file mode 100644 index 4dd1b93a527..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/JavaContext.java.173 +++ /dev/null @@ -1,823 +0,0 @@ -/* - * Copyright (C) 2011 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.detector.api; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.tools.klint.client.api.JavaEvaluator; -import com.android.tools.klint.client.api.JavaParser; -import com.android.tools.klint.client.api.JavaParser.ResolvedClass; -import com.android.tools.klint.client.api.LintDriver; -import com.android.tools.klint.detector.api.Detector.JavaPsiScanner; -import com.intellij.openapi.util.TextRange; -import com.intellij.openapi.vfs.VfsUtilCore; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.*; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.util.containers.ContainerUtil; -import lombok.ast.*; -import lombok.ast.Position; -import org.jetbrains.uast.*; -import org.jetbrains.uast.psi.UElementWithLocation; - -import java.io.File; -import java.util.Iterator; - -import static com.android.SdkConstants.CLASS_CONTEXT; -import static com.android.tools.klint.client.api.JavaParser.ResolvedNode; -import static com.android.tools.klint.client.api.JavaParser.TypeDescriptor; - -/** - * A {@link Context} used when checking Java files. - *

- * NOTE: This is not a public or final API; if you rely on this be prepared - * to adjust your code for the next tools release. - */ -public class JavaContext extends Context { - static final String SUPPRESS_COMMENT_PREFIX = "//noinspection "; //$NON-NLS-1$ - - /** - * The parse tree - * - * @deprecated Use {@link #mJavaFile} instead (see {@link JavaPsiScanner}) - */ - @Deprecated - private Node mCompilationUnit; - - /** The parse tree */ - private PsiJavaFile mJavaFile; - - private UFile mUFile; - - /** The parser which produced the parse tree */ - private final JavaParser mParser; - - /** - * Constructs a {@link JavaContext} for running lint on the given file, with - * the given scope, in the given project reporting errors to the given - * client. - * - * @param driver the driver running through the checks - * @param project the project to run lint on which contains the given file - * @param main the main project if this project is a library project, or - * null if this is not a library project. The main project is - * the root project of all library projects, not necessarily the - * directly including project. - * @param file the file to be analyzed - * @param parser the parser to use - */ - public JavaContext( - @NonNull LintDriver driver, - @NonNull Project project, - @Nullable Project main, - @NonNull File file, - @NonNull JavaParser parser) { - super(driver, project, main, file); - mParser = parser; - } - - @NonNull - public UastContext getUastContext() { - return mParser.getUastContext(); - } - - /** - * Returns a location for the given node - * - * @param node the AST node to get a location for - * @return a location for the given node - */ - @NonNull - public Location getLocation(@NonNull Node node) { - return mParser.getLocation(this, node); - } - - /** - * Returns a location for the given node range (from the starting offset of the first node to - * the ending offset of the second node). - * - * @param from the AST node to get a starting location from - * @param fromDelta Offset delta to apply to the starting offset - * @param to the AST node to get a ending location from - * @param toDelta Offset delta to apply to the ending offset - * @return a location for the given node - */ - @NonNull - public Location getRangeLocation( - @NonNull Node from, - int fromDelta, - @NonNull Node to, - int toDelta) { - return mParser.getRangeLocation(this, from, fromDelta, to, toDelta); - } - - /** - * Returns a location for the given node range (from the starting offset of the first node to - * the ending offset of the second node). - * - * @param from the AST node to get a starting location from - * @param fromDelta Offset delta to apply to the starting offset - * @param to the AST node to get a ending location from - * @param toDelta Offset delta to apply to the ending offset - * @return a location for the given node - */ - @NonNull - public Location getRangeLocation( - @NonNull PsiElement from, - int fromDelta, - @NonNull PsiElement to, - int toDelta) { - return mParser.getRangeLocation(this, from, fromDelta, to, toDelta); - } - - /** - * Returns a {@link Location} for the given node. This attempts to pick a shorter - * location range than the entire node; for a class or method for example, it picks - * the name node (if found). For statement constructs such as a {@code switch} statement - * it will highlight the keyword, etc. - * - * @param node the AST node to create a location for - * @return a location for the given node - */ - @NonNull - public Location getNameLocation(@NonNull Node node) { - return mParser.getNameLocation(this, node); - } - - /** - * Returns a {@link Location} for the given node. This attempts to pick a shorter - * location range than the entire node; for a class or method for example, it picks - * the name node (if found). For statement constructs such as a {@code switch} statement - * it will highlight the keyword, etc. - * - * @param element the AST node to create a location for - * @return a location for the given node - */ - @NonNull - public Location getNameLocation(@NonNull PsiElement element) { - if (element instanceof PsiSwitchStatement) { - // Just use keyword - return mParser.getRangeLocation(this, element, 0, 6); // 6: "switch".length() - } - return mParser.getNameLocation(this, element); - } - - @NonNull - public Location getUastNameLocation(@NonNull UElement element) { - if (element instanceof UDeclaration) { - UElement nameIdentifier = ((UDeclaration) element).getUastAnchor(); - if (nameIdentifier != null) { - return getUastLocation(nameIdentifier); - } - } else if (element instanceof PsiNameIdentifierOwner) { - PsiElement nameIdentifier = ((PsiNameIdentifierOwner) element).getNameIdentifier(); - if (nameIdentifier != null) { - return getLocation(nameIdentifier); - } - } else if (element instanceof UCallExpression) { - UElement methodReference = ((UCallExpression) element).getMethodIdentifier(); - if (methodReference != null) { - return getUastLocation(methodReference); - } - } - - return getUastLocation(element); - } - - @NonNull - public Location getLocation(@NonNull PsiElement node) { - return mParser.getLocation(this, node); - } - - @NonNull - public Location getUastLocation(@Nullable UElement node) { - if (node == null) { - return Location.NONE; - } - - if (node instanceof UElementWithLocation) { - UFile file = UastUtils.getContainingFile(node); - if (file == null) { - return Location.NONE; - } - File ioFile = UastUtils.getIoFile(file); - if (ioFile == null) { - return Location.NONE; - } - UElementWithLocation segment = (UElementWithLocation) node; - return Location.create(ioFile, file.getPsi().getText(), - segment.getStartOffset(), segment.getEndOffset()); - } else { - PsiElement psiElement = node.getPsi(); - if (psiElement != null) { - TextRange range = psiElement.getTextRange(); - UFile containingFile = getUFile(); - if (containingFile == null) { - return Location.NONE; - } - File file = this.file; - if (!containingFile.equals(getUFile())) { - // Reporting an error in a different file. - if (getDriver().getScope().size() == 1) { - // Don't bother with this error if it's in a different file during single-file analysis - return Location.NONE; - } - VirtualFile virtualFile = containingFile.getPsi().getVirtualFile(); - if (virtualFile == null) { - return Location.NONE; - } - file = VfsUtilCore.virtualToIoFile(virtualFile); - } - return Location.create(file, getContents(), range.getStartOffset(), - range.getEndOffset()); - } - } - - return Location.NONE; - } - - @NonNull - public JavaParser getParser() { - return mParser; - } - - @NonNull - public JavaEvaluator getEvaluator() { - return mParser.getEvaluator(); - } - - @Nullable - public Node getCompilationUnit() { - return mCompilationUnit; - } - - /** - * Sets the compilation result. Not intended for client usage; the lint infrastructure - * will set this when a context has been processed - * - * @param compilationUnit the parse tree - */ - public void setCompilationUnit(@Nullable Node compilationUnit) { - mCompilationUnit = compilationUnit; - } - - /** - * Returns the {@link UFile}. - * - * @return the parsed UFile - */ - @Nullable - public UFile getUFile() { - return mUFile; - } - - /** - * Sets the compilation result. Not intended for client usage; the lint infrastructure - * will set this when a context has been processed - * - * @param javaFile the parse tree - */ - public void setJavaFile(@Nullable PsiJavaFile javaFile) { - mJavaFile = javaFile; - } - - public void setUFile(@Nullable UFile file) { - mUFile = file; - } - - @Override - public void report(@NonNull Issue issue, @NonNull Location location, - @NonNull String message) { - if (mDriver.isSuppressed(this, issue, mCompilationUnit)) { - return; - } - super.report(issue, location, message); - } - - /** - * Reports an issue applicable to a given AST node. The AST node is used as the - * scope to check for suppress lint annotations. - * - * @param issue the issue to report - * @param scope the AST node scope the error applies to. The lint infrastructure - * will check whether there are suppress annotations on this node (or its enclosing - * nodes) and if so suppress the warning without involving the client. - * @param location the location of the issue, or null if not known - * @param message the message for this warning - */ - public void report( - @NonNull Issue issue, - @Nullable Node scope, - @NonNull Location location, - @NonNull String message) { - if (scope != null && mDriver.isSuppressed(this, issue, scope)) { - return; - } - super.report(issue, location, message); - } - - public void report( - @NonNull Issue issue, - @Nullable PsiElement scope, - @NonNull Location location, - @NonNull String message) { - if (scope != null && mDriver.isSuppressed(this, issue, scope)) { - return; - } - super.report(issue, location, message); - } - - public void report( - @NonNull Issue issue, - @Nullable UElement scope, - @NonNull Location location, - @NonNull String message) { - if (scope != null && mDriver.isSuppressed(this, issue, scope)) { - return; - } - super.report(issue, location, message); - } - - /** UDeclaration is a PsiElement, so it's impossible to call report(Issue, UElement, ...) - * without an explicit cast. */ - public void reportUast( - @NonNull Issue issue, - @Nullable UElement scope, - @NonNull Location location, - @NonNull String message) { - report(issue, scope, location, message); - } - - /** - * Report an error. - * Like {@link #report(Issue, Node, Location, String)} but with - * a now-unused data parameter at the end. - * - * @deprecated Use {@link #report(Issue, Node, Location, String)} instead; - * this method is here for custom rule compatibility - */ - @SuppressWarnings("UnusedDeclaration") // Potentially used by external existing custom rules - @Deprecated - public void report( - @NonNull Issue issue, - @Nullable Node scope, - @NonNull Location location, - @NonNull String message, - @SuppressWarnings("UnusedParameters") @Nullable Object data) { - report(issue, scope, location, message); - } - - /** - * @deprecated Use {@link PsiTreeUtil#getParentOfType(PsiElement, Class[])} - * with PsiMethod.class instead - */ - @Deprecated - @Nullable - public static Node findSurroundingMethod(Node scope) { - while (scope != null) { - Class type = scope.getClass(); - // The Lombok AST uses a flat hierarchy of node type implementation classes - // so no need to do instanceof stuff here. - if (type == MethodDeclaration.class || type == ConstructorDeclaration.class) { - return scope; - } - - scope = scope.getParent(); - } - - return null; - } - - /** - * @deprecated Use {@link PsiTreeUtil#getParentOfType(PsiElement, Class[])} - * with PsiMethod.class instead - */ - @Deprecated - @Nullable - public static ClassDeclaration findSurroundingClass(@Nullable Node scope) { - while (scope != null) { - Class type = scope.getClass(); - // The Lombok AST uses a flat hierarchy of node type implementation classes - // so no need to do instanceof stuff here. - if (type == ClassDeclaration.class) { - return (ClassDeclaration) scope; - } - - scope = scope.getParent(); - } - - return null; - } - - @Override - @Nullable - protected String getSuppressCommentPrefix() { - return SUPPRESS_COMMENT_PREFIX; - } - - /** - * @deprecated Use {@link #isSuppressedWithComment(PsiElement, Issue)} instead - */ - @Deprecated - public boolean isSuppressedWithComment(@NonNull Node scope, @NonNull Issue issue) { - // Check whether there is a comment marker - String contents = getContents(); - assert contents != null; // otherwise we wouldn't be here - Position position = scope.getPosition(); - if (position == null) { - return false; - } - - int start = position.getStart(); - return isSuppressedWithComment(start, issue); - } - - public boolean isSuppressedWithComment(@NonNull UElement scope, @NonNull Issue issue) { - PsiElement psi = scope.getPsi(); - return psi != null && isSuppressedWithComment(psi, issue); - - } - - public boolean isSuppressedWithComment(@NonNull PsiElement scope, @NonNull Issue issue) { - // Check whether there is a comment marker - String contents = getContents(); - assert contents != null; // otherwise we wouldn't be here - TextRange textRange = scope.getTextRange(); - if (textRange == null) { - return false; - } - int start = textRange.getStartOffset(); - return isSuppressedWithComment(start, issue); - } - - /** - * @deprecated Location handles aren't needed for AST nodes anymore; just use the - * {@link PsiElement} from the AST - */ - @Deprecated - @NonNull - public Location.Handle createLocationHandle(@NonNull Node node) { - return mParser.createLocationHandle(this, node); - } - - /** - * @deprecated Use PsiElement resolve methods (varies by AST node type, e.g. - * {@link PsiMethodCallExpression#resolveMethod()} - */ - @Deprecated - @Nullable - public ResolvedNode resolve(@NonNull Node node) { - return mParser.resolve(this, node); - } - - /** - * @deprecated Use {@link JavaEvaluator#findClass(String)} instead - */ - @Deprecated - @Nullable - public ResolvedClass findClass(@NonNull String fullyQualifiedName) { - return mParser.findClass(this, fullyQualifiedName); - } - - /** - * @deprecated Use {@link PsiExpression#getType()} )} instead - */ - @Deprecated - @Nullable - public TypeDescriptor getType(@NonNull Node node) { - return mParser.getType(this, node); - } - - /** - * @deprecated Use {@link #getMethodName(PsiElement)} instead - */ - @Deprecated - @Nullable - public static String getMethodName(@NonNull Node call) { - if (call instanceof MethodInvocation) { - return ((MethodInvocation)call).astName().astValue(); - } else if (call instanceof ConstructorInvocation) { - return ((ConstructorInvocation)call).astTypeReference().getTypeName(); - } else if (call instanceof EnumConstant) { - return ((EnumConstant)call).astName().astValue(); - } else { - return null; - } - } - - @Nullable - public static String getMethodName(@NonNull PsiElement call) { - if (call instanceof PsiMethodCallExpression) { - return ((PsiMethodCallExpression)call).getMethodExpression().getReferenceName(); - } else if (call instanceof PsiNewExpression) { - PsiJavaCodeReferenceElement classReference = ((PsiNewExpression) call).getClassReference(); - if (classReference != null) { - return classReference.getReferenceName(); - } else { - return null; - } - } else if (call instanceof PsiEnumConstant) { - return ((PsiEnumConstant)call).getName(); - } else { - return null; - } - } - - @Nullable - public static String getMethodName(@NonNull UElement call) { - if (call instanceof UEnumConstant) { - return ((UEnumConstant)call).getName(); - } else if (call instanceof UCallExpression) { - String methodName = ((UCallExpression) call).getMethodName(); - if (methodName != null) { - return methodName; - } else { - return UastUtils.getQualifiedName(((UCallExpression) call).getClassReference()); - } - } else { - return null; - } - } - - /** - * Searches for a name node corresponding to the given node - * @return the name node to use, if applicable - * @deprecated Use {@link #findNameElement(PsiElement)} instead - */ - @Deprecated - @Nullable - public static Node findNameNode(@NonNull Node node) { - if (node instanceof TypeDeclaration) { - // ClassDeclaration, AnnotationDeclaration, EnumDeclaration, InterfaceDeclaration - return ((TypeDeclaration) node).astName(); - } else if (node instanceof MethodDeclaration) { - return ((MethodDeclaration)node).astMethodName(); - } else if (node instanceof ConstructorDeclaration) { - return ((ConstructorDeclaration)node).astTypeName(); - } else if (node instanceof MethodInvocation) { - return ((MethodInvocation)node).astName(); - } else if (node instanceof ConstructorInvocation) { - return ((ConstructorInvocation)node).astTypeReference(); - } else if (node instanceof EnumConstant) { - return ((EnumConstant)node).astName(); - } else if (node instanceof AnnotationElement) { - return ((AnnotationElement)node).astName(); - } else if (node instanceof AnnotationMethodDeclaration) { - return ((AnnotationMethodDeclaration)node).astMethodName(); - } else if (node instanceof VariableReference) { - return ((VariableReference)node).astIdentifier(); - } else if (node instanceof LabelledStatement) { - return ((LabelledStatement)node).astLabel(); - } - - return null; - } - - /** - * Searches for a name node corresponding to the given node - * @return the name node to use, if applicable - */ - @Nullable - public static PsiElement findNameElement(@NonNull PsiElement element) { - if (element instanceof PsiClass) { - if (element instanceof PsiAnonymousClass) { - return ((PsiAnonymousClass)element).getBaseClassReference(); - } - return ((PsiClass) element).getNameIdentifier(); - } else if (element instanceof PsiMethod) { - return ((PsiMethod) element).getNameIdentifier(); - } else if (element instanceof PsiMethodCallExpression) { - return ((PsiMethodCallExpression) element).getMethodExpression(). - getReferenceNameElement(); - } else if (element instanceof PsiNewExpression) { - return ((PsiNewExpression) element).getClassReference(); - } else if (element instanceof PsiField) { - return ((PsiField)element).getNameIdentifier(); - } else if (element instanceof PsiAnnotation) { - return ((PsiAnnotation)element).getNameReferenceElement(); - } else if (element instanceof PsiReferenceExpression) { - return ((PsiReferenceExpression) element).getReferenceNameElement(); - } else if (element instanceof PsiLabeledStatement) { - return ((PsiLabeledStatement)element).getLabelIdentifier(); - } - - return null; - } - - @Deprecated - @NonNull - public static Iterator getParameters(@NonNull Node call) { - if (call instanceof MethodInvocation) { - return ((MethodInvocation) call).astArguments().iterator(); - } else if (call instanceof ConstructorInvocation) { - return ((ConstructorInvocation) call).astArguments().iterator(); - } else if (call instanceof EnumConstant) { - return ((EnumConstant) call).astArguments().iterator(); - } else { - return ContainerUtil.emptyIterator(); - } - } - - @Deprecated - @Nullable - public static Node getParameter(@NonNull Node call, int parameter) { - Iterator iterator = getParameters(call); - - for (int i = 0; i < parameter - 1; i++) { - if (!iterator.hasNext()) { - return null; - } - iterator.next(); - } - return iterator.hasNext() ? iterator.next() : null; - } - - /** - * Returns true if the given method invocation node corresponds to a call on a - * {@code android.content.Context} - * - * @param node the method call node - * @return true iff the method call is on a class extending context - * @deprecated use {@link JavaEvaluator#isMemberInSubClassOf(PsiMember, String, boolean)} instead - */ - @Deprecated - public boolean isContextMethod(@NonNull MethodInvocation node) { - // Method name used in many other contexts where it doesn't have the - // same semantics; only use this one if we can resolve types - // and we're certain this is the Context method - ResolvedNode resolved = resolve(node); - if (resolved instanceof JavaParser.ResolvedMethod) { - JavaParser.ResolvedMethod method = (JavaParser.ResolvedMethod) resolved; - ResolvedClass containingClass = method.getContainingClass(); - if (containingClass.isSubclassOf(CLASS_CONTEXT, false)) { - return true; - } - } - return false; - } - - /** - * Returns the first ancestor node of the given type - * - * @param element the element to search from - * @param clz the target node type - * @param the target node type - * @return the nearest ancestor node in the parent chain, or null if not found - * @deprecated Use {@link PsiTreeUtil#getParentOfType} instead - */ - @Deprecated - @Nullable - public static T getParentOfType( - @Nullable Node element, - @NonNull Class clz) { - return getParentOfType(element, clz, true); - } - - /** - * Returns the first ancestor node of the given type - * - * @param element the element to search from - * @param clz the target node type - * @param strict if true, do not consider the element itself, only its parents - * @param the target node type - * @return the nearest ancestor node in the parent chain, or null if not found - * @deprecated Use {@link PsiTreeUtil#getParentOfType} instead - */ - @Deprecated - @Nullable - public static T getParentOfType( - @Nullable Node element, - @NonNull Class clz, - boolean strict) { - if (element == null) { - return null; - } - - if (strict) { - element = element.getParent(); - } - - while (element != null) { - if (clz.isInstance(element)) { - //noinspection unchecked - return (T) element; - } - element = element.getParent(); - } - - return null; - } - - /** - * Returns the first ancestor node of the given type, stopping at the given type - * - * @param element the element to search from - * @param clz the target node type - * @param strict if true, do not consider the element itself, only its parents - * @param terminators optional node types to terminate the search at - * @param the target node type - * @return the nearest ancestor node in the parent chain, or null if not found - * @deprecated Use {@link PsiTreeUtil#getParentOfType} instead - */ - @Deprecated - @Nullable - public static T getParentOfType(@Nullable Node element, - @NonNull Class clz, - boolean strict, - @NonNull Class... terminators) { - if (element == null) { - return null; - } - if (strict) { - element = element.getParent(); - } - - while (element != null && !clz.isInstance(element)) { - for (Class terminator : terminators) { - if (terminator.isInstance(element)) { - return null; - } - } - element = element.getParent(); - } - - //noinspection unchecked - return (T) element; - } - - /** - * Returns the first sibling of the given node that is of the given class - * - * @param sibling the sibling to search from - * @param clz the type to look for - * @param the type - * @return the first sibling of the given type, or null - * @deprecated Use {@link PsiTreeUtil#getNextSiblingOfType(PsiElement, Class)} instead - */ - @Deprecated - @Nullable - public static T getNextSiblingOfType(@Nullable Node sibling, - @NonNull Class clz) { - if (sibling == null) { - return null; - } - Node parent = sibling.getParent(); - if (parent == null) { - return null; - } - - Iterator iterator = parent.getChildren().iterator(); - while (iterator.hasNext()) { - if (iterator.next() == sibling) { - break; - } - } - - while (iterator.hasNext()) { - Node child = iterator.next(); - if (clz.isInstance(child)) { - //noinspection unchecked - return (T) child; - } - - } - - return null; - } - - - /** - * Returns the given argument of the given call - * - * @param call the call containing arguments - * @param index the index of the target argument - * @return the argument at the given index - * @throws IllegalArgumentException if index is outside the valid range - */ - @Deprecated - @NonNull - public static Node getArgumentNode(@NonNull MethodInvocation call, int index) { - int i = 0; - for (Expression parameter : call.astArguments()) { - if (i == index) { - return parameter; - } - i++; - } - throw new IllegalArgumentException(Integer.toString(index)); - } -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/LayoutDetector.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/LayoutDetector.java.173 deleted file mode 100644 index ce1b8b2b5ab..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/LayoutDetector.java.173 +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2011 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.detector.api; - -import static com.android.SdkConstants.ANDROID_URI; -import static com.android.SdkConstants.ATTR_LAYOUT_HEIGHT; -import static com.android.SdkConstants.ATTR_LAYOUT_WIDTH; -import static com.android.SdkConstants.ATTR_PADDING; -import static com.android.SdkConstants.ATTR_PADDING_BOTTOM; -import static com.android.SdkConstants.ATTR_PADDING_LEFT; -import static com.android.SdkConstants.ATTR_PADDING_RIGHT; -import static com.android.SdkConstants.ATTR_PADDING_TOP; -import static com.android.SdkConstants.VALUE_FILL_PARENT; -import static com.android.SdkConstants.VALUE_MATCH_PARENT; - -import com.android.annotations.NonNull; -import com.android.resources.ResourceFolderType; -import com.google.common.annotations.Beta; - -import org.w3c.dom.Element; - -/** - * Abstract class specifically intended for layout detectors which provides some - * common utility methods shared by layout detectors. - *

- * NOTE: This is not a public or final API; if you rely on this be prepared - * to adjust your code for the next tools release. - */ -@Beta -public abstract class LayoutDetector extends ResourceXmlDetector { - @Override - public boolean appliesTo(@NonNull ResourceFolderType folderType) { - return folderType == ResourceFolderType.LAYOUT; - } - - private static boolean isFillParent(@NonNull Element element, @NonNull String dimension) { - String width = element.getAttributeNS(ANDROID_URI, dimension); - return width.equals(VALUE_MATCH_PARENT) || width.equals(VALUE_FILL_PARENT); - } - - protected static boolean isWidthFillParent(@NonNull Element element) { - return isFillParent(element, ATTR_LAYOUT_WIDTH); - } - - protected static boolean isHeightFillParent(@NonNull Element element) { - return isFillParent(element, ATTR_LAYOUT_HEIGHT); - } - - protected boolean hasPadding(@NonNull Element root) { - return root.hasAttributeNS(ANDROID_URI, ATTR_PADDING) - || root.hasAttributeNS(ANDROID_URI, ATTR_PADDING_LEFT) - || root.hasAttributeNS(ANDROID_URI, ATTR_PADDING_RIGHT) - || root.hasAttributeNS(ANDROID_URI, ATTR_PADDING_TOP) - || root.hasAttributeNS(ANDROID_URI, ATTR_PADDING_BOTTOM); - } -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/LintUtils.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/LintUtils.java.173 deleted file mode 100644 index 811c78f35ad..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/LintUtils.java.173 +++ /dev/null @@ -1,1343 +0,0 @@ -/* - * Copyright (C) 2011 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.detector.api; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.builder.model.AndroidProject; -import com.android.builder.model.ApiVersion; -import com.android.ide.common.rendering.api.ItemResourceValue; -import com.android.ide.common.rendering.api.ResourceValue; -import com.android.ide.common.rendering.api.StyleResourceValue; -import com.android.ide.common.res2.AbstractResourceRepository; -import com.android.ide.common.res2.ResourceItem; -import com.android.ide.common.resources.ResourceUrl; -import com.android.ide.common.resources.configuration.FolderConfiguration; -import com.android.ide.common.resources.configuration.LocaleQualifier; -import com.android.resources.FolderTypeRelationship; -import com.android.resources.ResourceFolderType; -import com.android.resources.ResourceType; -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.IAndroidTarget; -import com.android.sdklib.SdkVersionInfo; -import com.android.tools.klint.client.api.LintClient; -import com.android.utils.PositionXmlParser; -import com.android.utils.SdkUtils; -import com.google.common.annotations.Beta; -import com.google.common.base.Objects; -import com.google.common.base.Splitter; -import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; -import com.intellij.psi.*; -import lombok.ast.ImportDeclaration; -import org.jetbrains.org.objectweb.asm.Opcodes; -import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode; -import org.jetbrains.org.objectweb.asm.tree.ClassNode; -import org.jetbrains.org.objectweb.asm.tree.FieldNode; -import org.jetbrains.uast.UElement; -import org.jetbrains.uast.UParenthesizedExpression; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import java.io.File; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.util.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.regex.PatternSyntaxException; - -import static com.android.SdkConstants.*; -import static com.android.ide.common.resources.configuration.FolderConfiguration.QUALIFIER_SPLITTER; -import static com.android.ide.common.resources.configuration.LocaleQualifier.BCP_47_PREFIX; -import static com.android.tools.klint.client.api.JavaParser.*; - - -/** - * Useful utility methods related to lint. - *

- * NOTE: This is not a public or final API; if you rely on this be prepared - * to adjust your code for the next tools release. - */ -@Beta -public class LintUtils { - // Utility class, do not instantiate - private LintUtils() { - } - - /** - * Format a list of strings, and cut of the list at {@code maxItems} if the - * number of items are greater. - * - * @param strings the list of strings to print out as a comma separated list - * @param maxItems the maximum number of items to print - * @return a comma separated list - */ - @NonNull - public static String formatList(@NonNull List strings, int maxItems) { - StringBuilder sb = new StringBuilder(20 * strings.size()); - - for (int i = 0, n = strings.size(); i < n; i++) { - if (sb.length() > 0) { - sb.append(", "); //$NON-NLS-1$ - } - sb.append(strings.get(i)); - - if (maxItems > 0 && i == maxItems - 1 && n > maxItems) { - sb.append(String.format("... (%1$d more)", n - i - 1)); - break; - } - } - - return sb.toString(); - } - - /** - * Determine if the given type corresponds to a resource that has a unique - * file - * - * @param type the resource type to check - * @return true if the given type corresponds to a file-type resource - */ - public static boolean isFileBasedResourceType(@NonNull ResourceType type) { - List folderTypes = FolderTypeRelationship.getRelatedFolders(type); - for (ResourceFolderType folderType : folderTypes) { - if (folderType != ResourceFolderType.VALUES) { - return type != ResourceType.ID; - } - } - return false; - } - - /** - * Returns true if the given file represents an XML file - * - * @param file the file to be checked - * @return true if the given file is an xml file - */ - public static boolean isXmlFile(@NonNull File file) { - return SdkUtils.endsWithIgnoreCase(file.getPath(), DOT_XML); - } - - /** - * Returns true if the given file represents a bitmap drawable file - * - * @param file the file to be checked - * @return true if the given file is an xml file - */ - public static boolean isBitmapFile(@NonNull File file) { - String path = file.getPath(); - // endsWith(name, DOT_PNG) is also true for endsWith(name, DOT_9PNG) - return endsWith(path, DOT_PNG) - || endsWith(path, DOT_JPG) - || endsWith(path, DOT_GIF) - || endsWith(path, DOT_JPEG) - || endsWith(path, DOT_WEBP); - } - - /** - * Case insensitive ends with - * - * @param string the string to be tested whether it ends with the given - * suffix - * @param suffix the suffix to check - * @return true if {@code string} ends with {@code suffix}, - * case-insensitively. - */ - public static boolean endsWith(@NonNull String string, @NonNull String suffix) { - return string.regionMatches(true /* ignoreCase */, string.length() - suffix.length(), - suffix, 0, suffix.length()); - } - - /** - * Case insensitive starts with - * - * @param string the string to be tested whether it starts with the given prefix - * @param prefix the prefix to check - * @param offset the offset to start checking with - * @return true if {@code string} starts with {@code prefix}, - * case-insensitively. - */ - public static boolean startsWith(@NonNull String string, @NonNull String prefix, int offset) { - return string.regionMatches(true /* ignoreCase */, offset, prefix, 0, prefix.length()); - } - - /** - * Returns the basename of the given filename, unless it's a dot-file such as ".svn". - * - * @param fileName the file name to extract the basename from - * @return the basename (the filename without the file extension) - */ - public static String getBaseName(@NonNull String fileName) { - int extension = fileName.indexOf('.'); - if (extension > 0) { - return fileName.substring(0, extension); - } else { - return fileName; - } - } - - /** - * Returns the children elements of the given node - * - * @param node the parent node - * @return a list of element children, never null - */ - @NonNull - public static List getChildren(@NonNull Node node) { - NodeList childNodes = node.getChildNodes(); - List children = new ArrayList(childNodes.getLength()); - for (int i = 0, n = childNodes.getLength(); i < n; i++) { - Node child = childNodes.item(i); - if (child.getNodeType() == Node.ELEMENT_NODE) { - children.add((Element) child); - } - } - - return children; - } - - /** - * Returns the number of children of the given node - * - * @param node the parent node - * @return the count of element children - */ - public static int getChildCount(@NonNull Node node) { - NodeList childNodes = node.getChildNodes(); - int childCount = 0; - for (int i = 0, n = childNodes.getLength(); i < n; i++) { - Node child = childNodes.item(i); - if (child.getNodeType() == Node.ELEMENT_NODE) { - childCount++; - } - } - - return childCount; - } - - /** - * Returns true if the given element is the root element of its document - * - * @param element the element to test - * @return true if the element is the root element - */ - public static boolean isRootElement(Element element) { - return element == element.getOwnerDocument().getDocumentElement(); - } - - /** - * Returns the corresponding R field name for the given XML resource name - * @param styleName the XML name - * @return the corresponding R field name - */ - public static String getFieldName(@NonNull String styleName) { - for (int i = 0, n = styleName.length(); i < n; i++) { - char c = styleName.charAt(i); - if (c == '.' || c == '-' || c == ':') { - return styleName.replace('.', '_').replace('-', '_').replace(':', '_'); - } - } - - return styleName; - } - - /** - * Returns the given id without an {@code @id/} or {@code @+id} prefix - * - * @param id the id to strip - * @return the stripped id, never null - */ - @NonNull - public static String stripIdPrefix(@Nullable String id) { - if (id == null) { - return ""; - } else if (id.startsWith(NEW_ID_PREFIX)) { - return id.substring(NEW_ID_PREFIX.length()); - } else if (id.startsWith(ID_PREFIX)) { - return id.substring(ID_PREFIX.length()); - } - - return id; - } - - /** - * Returns true if the given two id references match. This is similar to - * String equality, but it also considers "{@code @+id/foo == @id/foo}. - * - * @param id1 the first id to compare - * @param id2 the second id to compare - * @return true if the two id references refer to the same id - */ - public static boolean idReferencesMatch(@Nullable String id1, @Nullable String id2) { - if (id1 == null || id2 == null || id1.isEmpty() || id2.isEmpty()) { - return false; - } - if (id1.startsWith(NEW_ID_PREFIX)) { - if (id2.startsWith(NEW_ID_PREFIX)) { - return id1.equals(id2); - } else { - assert id2.startsWith(ID_PREFIX) : id2; - return ((id1.length() - id2.length()) - == (NEW_ID_PREFIX.length() - ID_PREFIX.length())) - && id1.regionMatches(NEW_ID_PREFIX.length(), id2, - ID_PREFIX.length(), - id2.length() - ID_PREFIX.length()); - } - } else { - assert id1.startsWith(ID_PREFIX) : id1; - if (id2.startsWith(ID_PREFIX)) { - return id1.equals(id2); - } else { - assert id2.startsWith(NEW_ID_PREFIX); - return (id2.length() - id1.length() - == (NEW_ID_PREFIX.length() - ID_PREFIX.length())) - && id2.regionMatches(NEW_ID_PREFIX.length(), id1, - ID_PREFIX.length(), - id1.length() - ID_PREFIX.length()); - } - } - } - - /** - * Computes the edit distance (number of insertions, deletions or substitutions - * to edit one string into the other) between two strings. In particular, - * this will compute the Levenshtein distance. - *

- * See http://en.wikipedia.org/wiki/Levenshtein_distance for details. - * - * @param s the first string to compare - * @param t the second string to compare - * @return the edit distance between the two strings - */ - public static int editDistance(@NonNull String s, @NonNull String t) { - int m = s.length(); - int n = t.length(); - int[][] d = new int[m + 1][n + 1]; - for (int i = 0; i <= m; i++) { - d[i][0] = i; - } - for (int j = 0; j <= n; j++) { - d[0][j] = j; - } - for (int j = 1; j <= n; j++) { - for (int i = 1; i <= m; i++) { - if (s.charAt(i - 1) == t.charAt(j - 1)) { - d[i][j] = d[i - 1][j - 1]; - } else { - int deletion = d[i - 1][j] + 1; - int insertion = d[i][j - 1] + 1; - int substitution = d[i - 1][j - 1] + 1; - d[i][j] = Math.min(deletion, Math.min(insertion, substitution)); - } - } - } - - return d[m][n]; - } - - /** - * Returns true if assertions are enabled - * - * @return true if assertions are enabled - */ - @SuppressWarnings("all") - public static boolean assertionsEnabled() { - boolean assertionsEnabled = false; - assert assertionsEnabled = true; // Intentional side-effect - return assertionsEnabled; - } - - /** - * Returns the layout resource name for the given layout file - * - * @param layoutFile the file pointing to the layout - * @return the layout resource name, not including the {@code @layout} - * prefix - */ - public static String getLayoutName(File layoutFile) { - String name = layoutFile.getName(); - int dotIndex = name.indexOf('.'); - if (dotIndex != -1) { - name = name.substring(0, dotIndex); - } - return name; - } - - /** - * Splits the given path into its individual parts, attempting to be - * tolerant about path separators (: or ;). It can handle possibly ambiguous - * paths, such as {@code c:\foo\bar:\other}, though of course these are to - * be avoided if possible. - * - * @param path the path variable to split, which can use both : and ; as - * path separators. - * @return the individual path components as an Iterable of strings - */ - public static Iterable splitPath(@NonNull String path) { - if (path.indexOf(';') != -1) { - return Splitter.on(';').omitEmptyStrings().trimResults().split(path); - } - - List combined = new ArrayList(); - Iterables.addAll(combined, Splitter.on(':').omitEmptyStrings().trimResults().split(path)); - for (int i = 0, n = combined.size(); i < n; i++) { - String p = combined.get(i); - if (p.length() == 1 && i < n - 1 && Character.isLetter(p.charAt(0)) - // Technically, Windows paths do not have to have a \ after the :, - // which means it would be using the current directory on that drive, - // but that's unlikely to be the case in a path since it would have - // unpredictable results - && !combined.get(i+1).isEmpty() && combined.get(i+1).charAt(0) == '\\') { - combined.set(i, p + ':' + combined.get(i+1)); - combined.remove(i+1); - n--; - continue; - } - } - - return combined; - } - - /** - * Computes the shared parent among a set of files (which may be null). - * - * @param files the set of files to be checked - * @return the closest common ancestor file, or null if none was found - */ - @Nullable - public static File getCommonParent(@NonNull List files) { - int fileCount = files.size(); - if (fileCount == 0) { - return null; - } else if (fileCount == 1) { - return files.get(0); - } else if (fileCount == 2) { - return getCommonParent(files.get(0), files.get(1)); - } else { - File common = files.get(0); - for (int i = 1; i < fileCount; i++) { - common = getCommonParent(common, files.get(i)); - if (common == null) { - return null; - } - } - - return common; - } - } - - /** - * Computes the closest common parent path between two files. - * - * @param file1 the first file to be compared - * @param file2 the second file to be compared - * @return the closest common ancestor file, or null if the two files have - * no common parent - */ - @Nullable - public static File getCommonParent(@NonNull File file1, @NonNull File file2) { - if (file1.equals(file2)) { - return file1; - } else if (file1.getPath().startsWith(file2.getPath())) { - return file2; - } else if (file2.getPath().startsWith(file1.getPath())) { - return file1; - } else { - // Dumb and simple implementation - File first = file1.getParentFile(); - while (first != null) { - File second = file2.getParentFile(); - while (second != null) { - if (first.equals(second)) { - return first; - } - second = second.getParentFile(); - } - - first = first.getParentFile(); - } - } - return null; - } - - private static final String UTF_16 = "UTF_16"; //$NON-NLS-1$ - private static final String UTF_16LE = "UTF_16LE"; //$NON-NLS-1$ - - /** - * Returns the encoded String for the given file. This is usually the - * same as {@code Files.toString(file, Charsets.UTF8}, but if there's a UTF byte order mark - * (for UTF8, UTF_16 or UTF_16LE), use that instead. - * - * @param client the client to use for I/O operations - * @param file the file to read from - * @return the string - * @throws IOException if the file cannot be read properly - */ - @NonNull - public static String getEncodedString( - @NonNull LintClient client, - @NonNull File file) throws IOException { - byte[] bytes = client.readBytes(file); - if (endsWith(file.getName(), DOT_XML)) { - return PositionXmlParser.getXmlString(bytes); - } - - return getEncodedString(bytes); - } - - /** - * Returns the String corresponding to the given data. This is usually the - * same as {@code new String(data)}, but if there's a UTF byte order mark - * (for UTF8, UTF_16 or UTF_16LE), use that instead. - *

- * NOTE: For XML files, there is the additional complication that there - * could be a {@code encoding=} attribute in the prologue. For those files, - * use {@link PositionXmlParser#getXmlString(byte[])} instead. - * - * @param data the byte array to construct the string from - * @return the string - */ - @NonNull - public static String getEncodedString(@Nullable byte[] data) { - if (data == null) { - return ""; - } - - int offset = 0; - String defaultCharset = UTF_8; - String charset = null; - // Look for the byte order mark, to see if we need to remove bytes from - // the input stream (and to determine whether files are big endian or little endian) etc - // for files which do not specify the encoding. - // See http://unicode.org/faq/utf_bom.html#BOM for more. - if (data.length > 4) { - if (data[0] == (byte)0xef && data[1] == (byte)0xbb && data[2] == (byte)0xbf) { - // UTF-8 - defaultCharset = charset = UTF_8; - offset += 3; - } else if (data[0] == (byte)0xfe && data[1] == (byte)0xff) { - // UTF-16, big-endian - defaultCharset = charset = UTF_16; - offset += 2; - } else if (data[0] == (byte)0x0 && data[1] == (byte)0x0 - && data[2] == (byte)0xfe && data[3] == (byte)0xff) { - // UTF-32, big-endian - defaultCharset = charset = "UTF_32"; //$NON-NLS-1$ - offset += 4; - } else if (data[0] == (byte)0xff && data[1] == (byte)0xfe - && data[2] == (byte)0x0 && data[3] == (byte)0x0) { - // UTF-32, little-endian. We must check for this *before* looking for - // UTF_16LE since UTF_32LE has the same prefix! - defaultCharset = charset = "UTF_32LE"; //$NON-NLS-1$ - offset += 4; - } else if (data[0] == (byte)0xff && data[1] == (byte)0xfe) { - // UTF-16, little-endian - defaultCharset = charset = UTF_16LE; - offset += 2; - } - } - int length = data.length - offset; - - // Guess encoding by searching for an encoding= entry in the first line. - boolean seenOddZero = false; - boolean seenEvenZero = false; - for (int lineEnd = offset; lineEnd < data.length; lineEnd++) { - if (data[lineEnd] == 0) { - if ((lineEnd - offset) % 2 == 0) { - seenEvenZero = true; - } else { - seenOddZero = true; - } - } else if (data[lineEnd] == '\n' || data[lineEnd] == '\r') { - break; - } - } - - if (charset == null) { - charset = seenOddZero ? UTF_16LE : seenEvenZero ? UTF_16 : UTF_8; - } - - String text = null; - try { - text = new String(data, offset, length, charset); - } catch (UnsupportedEncodingException e) { - try { - if (!charset.equals(defaultCharset)) { - text = new String(data, offset, length, defaultCharset); - } - } catch (UnsupportedEncodingException u) { - // Just use the default encoding below - } - } - if (text == null) { - text = new String(data, offset, length); - } - return text; - } - - /** - * Returns true if the given class node represents a static inner class. - * - * @param classNode the inner class to be checked - * @return true if the class node represents an inner class that is static - */ - public static boolean isStaticInnerClass(@NonNull ClassNode classNode) { - // Note: We can't just filter out static inner classes like this: - // (classNode.access & Opcodes.ACC_STATIC) != 0 - // because the static flag only appears on methods and fields in the class - // file. Instead, look for the synthetic this pointer. - - @SuppressWarnings("rawtypes") // ASM API - List fieldList = classNode.fields; - for (Object f : fieldList) { - FieldNode field = (FieldNode) f; - if (field.name.startsWith("this$") && (field.access & Opcodes.ACC_SYNTHETIC) != 0) { - return false; - } - } - - return true; - } - - /** - * Returns true if the given class node represents an anonymous inner class - * - * @param classNode the class to be checked - * @return true if the class appears to be an anonymous class - */ - public static boolean isAnonymousClass(@NonNull ClassNode classNode) { - if (classNode.outerClass == null) { - return false; - } - - String name = classNode.name; - int index = name.lastIndexOf('$'); - if (index == -1 || index == name.length() - 1) { - return false; - } - - return Character.isDigit(name.charAt(index + 1)); - } - - /** - * Returns the previous opcode prior to the given node, ignoring label and - * line number nodes - * - * @param node the node to look up the previous opcode for - * @return the previous opcode, or {@link Opcodes#NOP} if no previous node - * was found - */ - public static int getPrevOpcode(@NonNull AbstractInsnNode node) { - AbstractInsnNode prev = getPrevInstruction(node); - if (prev != null) { - return prev.getOpcode(); - } else { - return Opcodes.NOP; - } - } - - /** - * Returns the previous instruction prior to the given node, ignoring label - * and line number nodes. - * - * @param node the node to look up the previous instruction for - * @return the previous instruction, or null if no previous node was found - */ - @Nullable - public static AbstractInsnNode getPrevInstruction(@NonNull AbstractInsnNode node) { - AbstractInsnNode prev = node; - while (true) { - prev = prev.getPrevious(); - if (prev == null) { - return null; - } else { - int type = prev.getType(); - if (type != AbstractInsnNode.LINE && type != AbstractInsnNode.LABEL - && type != AbstractInsnNode.FRAME) { - return prev; - } - } - } - } - - /** - * Returns the next opcode after to the given node, ignoring label and line - * number nodes - * - * @param node the node to look up the next opcode for - * @return the next opcode, or {@link Opcodes#NOP} if no next node was found - */ - public static int getNextOpcode(@NonNull AbstractInsnNode node) { - AbstractInsnNode next = getNextInstruction(node); - if (next != null) { - return next.getOpcode(); - } else { - return Opcodes.NOP; - } - } - - /** - * Returns the next instruction after to the given node, ignoring label and - * line number nodes. - * - * @param node the node to look up the next node for - * @return the next instruction, or null if no next node was found - */ - @Nullable - public static AbstractInsnNode getNextInstruction(@NonNull AbstractInsnNode node) { - AbstractInsnNode next = node; - while (true) { - next = next.getNext(); - if (next == null) { - return null; - } else { - int type = next.getType(); - if (type != AbstractInsnNode.LINE && type != AbstractInsnNode.LABEL - && type != AbstractInsnNode.FRAME) { - return next; - } - } - } - } - - /** - * Returns true if the given directory is a lint manifest file directory. - * - * @param dir the directory to check - * @return true if the directory contains a manifest file - */ - public static boolean isManifestFolder(File dir) { - boolean hasManifest = new File(dir, ANDROID_MANIFEST_XML).exists(); - if (hasManifest) { - // Special case: the bin/ folder can also contain a copy of the - // manifest file, but this is *not* a project directory - if (dir.getName().equals(BIN_FOLDER)) { - // ...unless of course it just *happens* to be a project named bin, in - // which case we peek at its parent to see if this is the case - dir = dir.getParentFile(); - //noinspection ConstantConditions - if (dir != null && isManifestFolder(dir)) { - // Yes, it's a bin/ directory inside a real project: ignore this dir - return false; - } - } - } - - return hasManifest; - } - - /** - * Look up the locale and region from the given parent folder name and - * return it as a combined string, such as "en", "en-rUS", b+eng-US, etc, or null if - * no language is specified. - * - * @param folderName the folder name - * @return the locale+region string or null - */ - @Nullable - public static String getLocaleAndRegion(@NonNull String folderName) { - if (folderName.indexOf('-') == -1) { - return null; - } - - String locale = null; - - for (String qualifier : QUALIFIER_SPLITTER.split(folderName)) { - int qualifierLength = qualifier.length(); - if (qualifierLength == 2) { - char first = qualifier.charAt(0); - char second = qualifier.charAt(1); - if (first >= 'a' && first <= 'z' && second >= 'a' && second <= 'z') { - locale = qualifier; - } - } else if (qualifierLength == 3 && qualifier.charAt(0) == 'r' && locale != null) { - char first = qualifier.charAt(1); - char second = qualifier.charAt(2); - if (first >= 'A' && first <= 'Z' && second >= 'A' && second <= 'Z') { - return locale + '-' + qualifier; - } - break; - } else if (qualifier.startsWith(BCP_47_PREFIX)) { - return qualifier; - } - } - - return locale; - } - - /** - * Returns true if the given class (specified by a fully qualified class - * name) name is imported in the given compilation unit either through a fully qualified - * import or by a wildcard import. - * - * @param compilationUnit the compilation unit - * @param fullyQualifiedName the fully qualified class name - * @return true if the given imported name refers to the given fully - * qualified name - * @deprecated Use PSI element hierarchies instead where type resolution is more directly - * available (call {@link PsiImportStatement#resolve()}) - */ - @Deprecated - public static boolean isImported( - @Nullable lombok.ast.Node compilationUnit, - @NonNull String fullyQualifiedName) { - if (compilationUnit == null) { - return false; - } - int dotIndex = fullyQualifiedName.lastIndexOf('.'); - int dotLength = fullyQualifiedName.length() - dotIndex; - - boolean imported = false; - for (lombok.ast.Node rootNode : compilationUnit.getChildren()) { - if (rootNode instanceof ImportDeclaration) { - ImportDeclaration importDeclaration = (ImportDeclaration) rootNode; - String fqn = importDeclaration.asFullyQualifiedName(); - if (fqn.equals(fullyQualifiedName)) { - return true; - } else if (fullyQualifiedName.regionMatches(dotIndex, fqn, - fqn.length() - dotLength, dotLength)) { - // This import is importing the class name using some other prefix, so there - // fully qualified class name cannot be imported under that name - return false; - } else if (importDeclaration.astStarImport() - && fqn.regionMatches(0, fqn, 0, dotIndex + 1)) { - imported = true; - // but don't break -- keep searching in case there's a non-wildcard - // import of the specific class name, e.g. if we're looking for - // android.content.SharedPreferences.Editor, don't match on the following: - // import android.content.SharedPreferences.*; - // import foo.bar.Editor; - } - } - } - - return imported; - } - - /** - * Looks up the resource values for the given attribute given a style. Note that - * this only looks project-level style values, it does not resume into the framework - * styles. - */ - @Nullable - public static List getStyleAttributes( - @NonNull Project project, @NonNull LintClient client, - @NonNull String styleUrl, @NonNull String namespace, @NonNull String attribute) { - if (!client.supportsProjectResources()) { - return null; - } - - AbstractResourceRepository resources = client.getProjectResources(project, true); - if (resources == null) { - return null; - } - - ResourceUrl style = ResourceUrl.parse(styleUrl); - if (style == null || style.framework) { - return null; - } - - List result = null; - - Queue queue = new ArrayDeque(); - queue.add(new ResourceValue(style.type, style.name, false)); - Set seen = Sets.newHashSet(); - int count = 0; - boolean isFrameworkAttribute = ANDROID_URI.equals(namespace); - while (count < 30 && !queue.isEmpty()) { - ResourceValue front = queue.remove(); - String name = front.getName(); - seen.add(name); - List items = resources.getResourceItem(front.getResourceType(), name); - if (items != null) { - for (ResourceItem item : items) { - ResourceValue rv = item.getResourceValue(false); - if (rv instanceof StyleResourceValue) { - StyleResourceValue srv = (StyleResourceValue) rv; - ItemResourceValue value = srv.getItem(attribute, isFrameworkAttribute); - if (value != null) { - if (result == null) { - result = Lists.newArrayList(); - } - if (!result.contains(value)) { - result.add(value); - } - } - - String parent = srv.getParentStyle(); - if (parent != null && !parent.startsWith(ANDROID_PREFIX)) { - ResourceUrl p = ResourceUrl.parse(parent); - if (p != null && !p.framework && !seen.contains(p.name)) { - seen.add(p.name); - queue.add(new ResourceValue(ResourceType.STYLE, p.name, - false)); - } - } - - int index = name.lastIndexOf('.'); - if (index > 0) { - String parentName = name.substring(0, index); - if (!seen.contains(parentName)) { - seen.add(parentName); - queue.add(new ResourceValue(ResourceType.STYLE, parentName, - false)); - } - } - } - } - } - - count++; - } - - return result; - } - - @Nullable - public static List getInheritedStyles( - @NonNull Project project, @NonNull LintClient client, - @NonNull String styleUrl) { - if (!client.supportsProjectResources()) { - return null; - } - - AbstractResourceRepository resources = client.getProjectResources(project, true); - if (resources == null) { - return null; - } - - ResourceUrl style = ResourceUrl.parse(styleUrl); - if (style == null || style.framework) { - return null; - } - - List result = null; - - Queue queue = new ArrayDeque(); - queue.add(new ResourceValue(style.type, style.name, false)); - Set seen = Sets.newHashSet(); - int count = 0; - while (count < 30 && !queue.isEmpty()) { - ResourceValue front = queue.remove(); - String name = front.getName(); - seen.add(name); - List items = resources.getResourceItem(front.getResourceType(), name); - if (items != null) { - for (ResourceItem item : items) { - ResourceValue rv = item.getResourceValue(false); - if (rv instanceof StyleResourceValue) { - StyleResourceValue srv = (StyleResourceValue) rv; - if (result == null) { - result = Lists.newArrayList(); - } - result.add(srv); - - String parent = srv.getParentStyle(); - if (parent != null && !parent.startsWith(ANDROID_PREFIX)) { - ResourceUrl p = ResourceUrl.parse(parent); - if (p != null && !p.framework && !seen.contains(p.name)) { - seen.add(p.name); - queue.add(new ResourceValue(ResourceType.STYLE, p.name, - false)); - } - } - - int index = name.lastIndexOf('.'); - if (index > 0) { - String parentName = name.substring(0, index); - if (!seen.contains(parentName)) { - seen.add(parentName); - queue.add(new ResourceValue(ResourceType.STYLE, parentName, - false)); - } - } - } - } - } - - count++; - } - - return result; - } - - /** Returns true if the given two paths point to the same logical resource file within - * a source set. This means that it only checks the parent folder name and individual - * file name, not the path outside the parent folder. - * - * @param file1 the first file to compare - * @param file2 the second file to compare - * @return true if the two files have the same parent and file names - */ - public static boolean isSameResourceFile(@Nullable File file1, @Nullable File file2) { - if (file1 != null && file2 != null - && file1.getName().equals(file2.getName())) { - File parent1 = file1.getParentFile(); - File parent2 = file2.getParentFile(); - if (parent1 != null && parent2 != null && - parent1.getName().equals(parent2.getName())) { - return true; - } - } - - return false; - } - - /** - * Whether we should attempt to look up the prefix from the model. Set to false - * if we encounter a model which is too old. - *

- * This is public such that code which for example syncs to a new gradle model - * can reset it. - */ - public static boolean sTryPrefixLookup = true; - - /** Looks up the resource prefix for the given Gradle project, if possible */ - @Nullable - public static String computeResourcePrefix(@Nullable AndroidProject project) { - try { - if (sTryPrefixLookup && project != null) { - return project.getResourcePrefix(); - } - } catch (Exception e) { - // This happens if we're talking to an older model than 0.10 - // Ignore; fall through to normal handling and never try again. - //noinspection AssignmentToStaticFieldFromInstanceMethod - sTryPrefixLookup = false; - } - - return null; - } - - /** Computes a suggested name given a resource prefix and resource name */ - public static String computeResourceName(@NonNull String prefix, @NonNull String name) { - if (prefix.isEmpty()) { - return name; - } else if (name.isEmpty()) { - return prefix; - } else if (prefix.endsWith("_")) { - return prefix + name; - } else { - return prefix + Character.toUpperCase(name.charAt(0)) + name.substring(1); - } - } - - - /** - * Convert an {@link com.android.builder.model.ApiVersion} to a {@link - * com.android.sdklib.AndroidVersion}. The chief problem here is that the {@link - * com.android.builder.model.ApiVersion}, when using a codename, will not encode the - * corresponding API level (it just reflects the string entered by the user in the gradle file) - * so we perform a search here (since lint really wants to know the actual numeric API level) - * - * @param api the api version to convert - * @param targets if known, the installed targets (used to resolve platform codenames, only - * needed to resolve platforms newer than the tools since {@link - * com.android.sdklib.SdkVersionInfo} knows the rest) - * @return the corresponding version - */ - @NonNull - public static AndroidVersion convertVersion( - @NonNull ApiVersion api, - @Nullable IAndroidTarget[] targets) { - String codename = api.getCodename(); - if (codename != null) { - AndroidVersion version = SdkVersionInfo.getVersion(codename, targets); - if (version != null) { - return version; - } - return new AndroidVersion(api.getApiLevel(), codename); - } - return new AndroidVersion(api.getApiLevel(), null); - } - - /** - * Looks for a certain string within a larger string, which should immediately follow - * the given prefix and immediately precede the given suffix. - * - * @param string the full string to search - * @param prefix the optional prefix to follow - * @param suffix the optional suffix to precede - * @return the corresponding substring, if present - */ - @Nullable - public static String findSubstring(@NonNull String string, @Nullable String prefix, - @Nullable String suffix) { - int start = 0; - if (prefix != null) { - start = string.indexOf(prefix); - if (start == -1) { - return null; - } - start += prefix.length(); - } - - if (suffix != null) { - int end = string.indexOf(suffix, start); - if (end == -1) { - return null; - } - return string.substring(start, end); - } - - return string.substring(start); - } - - /** - * Splits up the given message coming from a given string format (where the string - * format follows the very specific convention of having only strings formatted exactly - * with the format %n$s where n is between 1 and 9 inclusive, and each formatting parameter - * appears exactly once, and in increasing order. - * - * @param format the format string responsible for creating the error message - * @param errorMessage an error message formatted with the format string - * @return the specific values inserted into the format - */ - @NonNull - public static List getFormattedParameters( - @NonNull String format, - @NonNull String errorMessage) { - StringBuilder pattern = new StringBuilder(format.length()); - int parameter = 1; - for (int i = 0, n = format.length(); i < n; i++) { - char c = format.charAt(i); - if (c == '%') { - // Only support formats of the form %n$s where n is 1 <= n <=9 - assert i < format.length() - 4 : format; - assert format.charAt(i + 1) == ('0' + parameter) : format; - assert Character.isDigit(format.charAt(i + 1)) : format; - assert format.charAt(i + 2) == '$' : format; - assert format.charAt(i + 3) == 's' : format; - parameter++; - i += 3; - pattern.append("(.*)"); - } else { - pattern.append(c); - } - } - try { - Pattern compile = Pattern.compile(pattern.toString()); - Matcher matcher = compile.matcher(errorMessage); - if (matcher.find()) { - int groupCount = matcher.groupCount(); - List parameters = Lists.newArrayListWithExpectedSize(groupCount); - for (int i = 1; i <= groupCount; i++) { - parameters.add(matcher.group(i)); - } - - return parameters; - } - - } catch (PatternSyntaxException pse) { - // Internal error: string format is not valid. Should be caught by unit tests - // as a failure to return the formatted parameters. - } - return Collections.emptyList(); - } - - /** - * Returns the locale for the given parent folder. - * - * @param parent the name of the parent folder - * @return null if the locale is not known, or a locale qualifier providing the language - * and possibly region - */ - @Nullable - public static LocaleQualifier getLocale(@NonNull String parent) { - if (parent.indexOf('-') != -1) { - FolderConfiguration config = FolderConfiguration.getConfigForFolder(parent); - if (config != null) { - return config.getLocaleQualifier(); - } - } - return null; - } - - /** - * Returns the locale for the given context. - * - * @param context the context to look up the locale for - * @return null if the locale is not known, or a locale qualifier providing the language - * and possibly region - */ - @Nullable - public static LocaleQualifier getLocale(@NonNull XmlContext context) { - Element root = context.document.getDocumentElement(); - if (root != null) { - String locale = root.getAttributeNS(TOOLS_URI, ATTR_LOCALE); - if (locale != null && !locale.isEmpty()) { - return getLocale(locale); - } - } - - return getLocale(context.file.getParentFile().getName()); - } - - /** - * Check whether the given resource file is in an English locale - * @param context the XML context for the resource file - * @param assumeForBase whether the base folder (e.g. no locale specified) should be - * treated as English - */ - public static boolean isEnglishResource(@NonNull XmlContext context, boolean assumeForBase) { - LocaleQualifier locale = LintUtils.getLocale(context); - if (locale == null) { - return assumeForBase; - } else { - return "en".equals(locale.getLanguage()); //$NON-NLS-1$ - } - } - - /** - * Create a {@link Location} for an error in the top level build.gradle file. - * This is necessary when we're doing an analysis based on the Gradle interpreted model, - * not from parsing Gradle files - and the model doesn't provide source positions. - * @param project the project containing the gradle file being analyzed - * @return location for the top level gradle file if it exists, otherwise fall back to - * the project directory. - */ - public static Location guessGradleLocation(@NonNull Project project) { - File dir = project.getDir(); - Location location; - File topLevel = new File(dir, FN_BUILD_GRADLE); - if (topLevel.exists()) { - location = Location.create(topLevel); - } else { - location = Location.create(dir); - } - return location; - } - - /** - * Returns true if the given element is the null literal - * - * @param element the element to check - * @return true if the element is "null" - */ - public static boolean isNullLiteral(@Nullable PsiElement element) { - return element instanceof PsiLiteral && "null".equals(element.getText()); - } - - public static boolean isTrueLiteral(@Nullable PsiElement element) { - return element instanceof PsiLiteral && "true".equals(element.getText()); - } - - public static boolean isFalseLiteral(@Nullable PsiElement element) { - return element instanceof PsiLiteral && "false".equals(element.getText()); - } - - @Nullable - public static PsiElement skipParentheses(@Nullable PsiElement element) { - while (element instanceof PsiParenthesizedExpression) { - element = element.getParent(); - } - - return element; - } - - @Nullable - public static UElement skipParentheses(@Nullable UElement element) { - while (element instanceof UParenthesizedExpression) { - element = element.getUastParent(); - } - - return element; - } - - @Nullable - public static PsiElement nextNonWhitespace(@Nullable PsiElement element) { - if (element != null) { - element = element.getNextSibling(); - while (element instanceof PsiWhiteSpace) { - element = element.getNextSibling(); - } - } - - return element; - } - - @Nullable - public static PsiElement prevNonWhitespace(@Nullable PsiElement element) { - if (element != null) { - element = element.getPrevSibling(); - while (element instanceof PsiWhiteSpace) { - element = element.getPrevSibling(); - } - } - - return element; - } - - public static boolean isString(@NonNull PsiType type) { - if (type instanceof PsiClassType) { - final String shortName = ((PsiClassType)type).getClassName(); - if (!Objects.equal(shortName, CommonClassNames.JAVA_LANG_STRING_SHORT)) { - return false; - } - } - return CommonClassNames.JAVA_LANG_STRING.equals(type.getCanonicalText()); - } - - @Nullable - public static String getAutoBoxedType(@NonNull String primitive) { - if (TYPE_INT.equals(primitive)) { - return TYPE_INTEGER_WRAPPER; - } else if (TYPE_LONG.equals(primitive)) { - return TYPE_LONG_WRAPPER; - } else if (TYPE_CHAR.equals(primitive)) { - return TYPE_CHARACTER_WRAPPER; - } else if (TYPE_FLOAT.equals(primitive)) { - return TYPE_FLOAT_WRAPPER; - } else if (TYPE_DOUBLE.equals(primitive)) { - return TYPE_DOUBLE_WRAPPER; - } else if (TYPE_BOOLEAN.equals(primitive)) { - return TYPE_BOOLEAN_WRAPPER; - } else if (TYPE_SHORT.equals(primitive)) { - return TYPE_SHORT_WRAPPER; - } else if (TYPE_BYTE.equals(primitive)) { - return TYPE_BYTE_WRAPPER; - } - - return null; - } - - @Nullable - public static String getPrimitiveType(@NonNull String autoBoxedType) { - if (TYPE_INTEGER_WRAPPER.equals(autoBoxedType)) { - return TYPE_INT; - } else if (TYPE_LONG_WRAPPER.equals(autoBoxedType)) { - return TYPE_LONG; - } else if (TYPE_CHARACTER_WRAPPER.equals(autoBoxedType)) { - return TYPE_CHAR; - } else if (TYPE_FLOAT_WRAPPER.equals(autoBoxedType)) { - return TYPE_FLOAT; - } else if (TYPE_DOUBLE_WRAPPER.equals(autoBoxedType)) { - return TYPE_DOUBLE; - } else if (TYPE_BOOLEAN_WRAPPER.equals(autoBoxedType)) { - return TYPE_BOOLEAN; - } else if (TYPE_SHORT_WRAPPER.equals(autoBoxedType)) { - return TYPE_SHORT; - } else if (TYPE_BYTE_WRAPPER.equals(autoBoxedType)) { - return TYPE_BYTE; - } - - return null; - } -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/Location.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/Location.java.173 deleted file mode 100644 index bb80f41329f..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/Location.java.173 +++ /dev/null @@ -1,814 +0,0 @@ -/* - * Copyright (C) 2011 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.detector.api; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.ide.common.blame.SourcePosition; -import com.android.ide.common.res2.ResourceFile; -import com.android.ide.common.res2.ResourceItem; -import com.android.tools.klint.client.api.JavaParser; -import com.google.common.annotations.Beta; -import com.intellij.psi.PsiElement; - -import java.io.File; - -/** - * Location information for a warning - *

- * NOTE: This is not a public or final API; if you rely on this be prepared - * to adjust your code for the next tools release. - */ -@Beta -public class Location { - private static final String SUPER_KEYWORD = "super"; //$NON-NLS-1$ - - private final File mFile; - private final Position mStart; - private final Position mEnd; - private String mMessage; - private Location mSecondary; - private Object mClientData; - - /** - * Special marker location which means location not available, or not applicable, or filtered out, etc. - * For example, the infrastructure may return {@link #NONE} if you ask {@link JavaParser#getLocation(JavaContext, PsiElement)} - * for an element which is not in the current file during an incremental lint run in a single file. - */ - public static final Location NONE = new Location(new File("NONE"), null, null); - - /** - * (Private constructor, use one of the factory methods - * {@link Location#create(File)}, - * {@link Location#create(File, Position, Position)}, or - * {@link Location#create(File, String, int, int)}. - *

- * Constructs a new location range for the given file, from start to end. If - * the length of the range is not known, end may be null. - * - * @param file the associated file (but see the documentation for - * {@link #getFile()} for more information on what the file - * represents) - * @param start the starting position, or null - * @param end the ending position, or null - */ - protected Location(@NonNull File file, @Nullable Position start, @Nullable Position end) { - super(); - mFile = file; - mStart = start; - mEnd = end; - } - - /** - * Returns the file containing the warning. Note that the file *itself* may - * not yet contain the error. When editing a file in the IDE for example, - * the tool could generate warnings in the background even before the - * document is saved. However, the file is used as a identifying token for - * the document being edited, and the IDE integration can map this back to - * error locations in the editor source code. - * - * @return the file handle for the location - */ - @NonNull - public File getFile() { - return mFile; - } - - /** - * The start position of the range - * - * @return the start position of the range, or null - */ - @Nullable - public Position getStart() { - return mStart; - } - - /** - * The end position of the range - * - * @return the start position of the range, may be null for an empty range - */ - @Nullable - public Position getEnd() { - return mEnd; - } - - /** - * Returns a secondary location associated with this location (if - * applicable), or null. - * - * @return a secondary location or null - */ - @Nullable - public Location getSecondary() { - return mSecondary; - } - - /** - * Sets a secondary location for this location. - * - * @param secondary a secondary location associated with this location - */ - public void setSecondary(@Nullable Location secondary) { - mSecondary = secondary; - } - - /** - * Sets a custom message for this location. This is typically used for - * secondary locations, to describe the significance of this alternate - * location. For example, for a duplicate id warning, the primary location - * might say "This is a duplicate id", pointing to the second occurrence of - * id declaration, and then the secondary location could point to the - * original declaration with the custom message "Originally defined here". - * - * @param message the message to apply to this location - */ - public void setMessage(@NonNull String message) { - mMessage = message; - } - - /** - * Returns the custom message for this location, if any. This is typically - * used for secondary locations, to describe the significance of this - * alternate location. For example, for a duplicate id warning, the primary - * location might say "This is a duplicate id", pointing to the second - * occurrence of id declaration, and then the secondary location could point - * to the original declaration with the custom message - * "Originally defined here". - * - * @return the custom message for this location, or null - */ - @Nullable - public String getMessage() { - return mMessage; - } - - /** - * Sets the client data associated with this location. This is an optional - * field which can be used by the creator of the {@link Location} to store - * temporary state associated with the location. - * - * @param clientData the data to store with this location - */ - public void setClientData(@Nullable Object clientData) { - mClientData = clientData; - } - - /** - * Returns the client data associated with this location - an optional field - * which can be used by the creator of the {@link Location} to store - * temporary state associated with the location. - * - * @return the data associated with this location - */ - @Nullable - public Object getClientData() { - return mClientData; - } - - @Override - public String toString() { - return "Location [file=" + mFile + ", start=" + mStart + ", end=" + mEnd + ", message=" - + mMessage + ']'; - } - - /** - * Creates a new location for the given file - * - * @param file the file to create a location for - * @return a new location - */ - @NonNull - public static Location create(@NonNull File file) { - return new Location(file, null /*start*/, null /*end*/); - } - - /** - * Creates a new location for the given file and SourcePosition. - * - * @param file the file containing the positions - * @param position the source position - * @return a new location - */ - @NonNull - public static Location create( - @NonNull File file, - @NonNull SourcePosition position) { - if (position.equals(SourcePosition.UNKNOWN)) { - return new Location(file, null /*start*/, null /*end*/); - } - return new Location(file, - new DefaultPosition( - position.getStartLine(), - position.getStartColumn(), - position.getStartOffset()), - new DefaultPosition( - position.getEndLine(), - position.getEndColumn(), - position.getEndOffset())); - } - - /** - * Creates a new location for the given file and starting and ending - * positions. - * - * @param file the file containing the positions - * @param start the starting position - * @param end the ending position - * @return a new location - */ - @NonNull - public static Location create( - @NonNull File file, - @NonNull Position start, - @Nullable Position end) { - return new Location(file, start, end); - } - - /** - * Creates a new location for the given file, with the given contents, for - * the given offset range. - * - * @param file the file containing the location - * @param contents the current contents of the file - * @param startOffset the starting offset - * @param endOffset the ending offset - * @return a new location - */ - @NonNull - public static Location create( - @NonNull File file, - @Nullable String contents, - int startOffset, - int endOffset) { - if (startOffset < 0 || endOffset < startOffset) { - throw new IllegalArgumentException("Invalid offsets"); - } - - if (contents == null) { - return new Location(file, - new DefaultPosition(-1, -1, startOffset), - new DefaultPosition(-1, -1, endOffset)); - } - - int size = contents.length(); - endOffset = Math.min(endOffset, size); - startOffset = Math.min(startOffset, endOffset); - Position start = null; - int line = 0; - int lineOffset = 0; - char prev = 0; - for (int offset = 0; offset <= size; offset++) { - if (offset == startOffset) { - start = new DefaultPosition(line, offset - lineOffset, offset); - } - if (offset == endOffset) { - Position end = new DefaultPosition(line, offset - lineOffset, offset); - return new Location(file, start, end); - } - char c = contents.charAt(offset); - if (c == '\n') { - lineOffset = offset + 1; - if (prev != '\r') { - line++; - } - } else if (c == '\r') { - line++; - lineOffset = offset + 1; - } - prev = c; - } - return create(file); - } - - /** - * Creates a new location for the given file, with the given contents, for - * the given line number. - * - * @param file the file containing the location - * @param contents the current contents of the file - * @param line the line number (0-based) for the position - * @return a new location - */ - @NonNull - public static Location create(@NonNull File file, @NonNull String contents, int line) { - return create(file, contents, line, null, null, null); - } - - /** - * Creates a new location for the given file, with the given contents, for - * the given line number. - * - * @param file the file containing the location - * @param contents the current contents of the file - * @param line the line number (0-based) for the position - * @param patternStart an optional pattern to search for from the line - * match; if found, adjust the column and offsets to begin at the - * pattern start - * @param patternEnd an optional pattern to search for behind the start - * pattern; if found, adjust the end offset to match the end of - * the pattern - * @param hints optional additional information regarding the pattern search - * @return a new location - */ - @NonNull - public static Location create(@NonNull File file, @NonNull String contents, int line, - @Nullable String patternStart, @Nullable String patternEnd, - @Nullable SearchHints hints) { - int currentLine = 0; - int offset = 0; - while (currentLine < line) { - offset = contents.indexOf('\n', offset); - if (offset == -1) { - return create(file); - } - currentLine++; - offset++; - } - - if (line == currentLine) { - if (patternStart != null) { - SearchDirection direction = SearchDirection.NEAREST; - if (hints != null) { - direction = hints.mDirection; - } - - int index; - if (direction == SearchDirection.BACKWARD) { - index = findPreviousMatch(contents, offset, patternStart, hints); - line = adjustLine(contents, line, offset, index); - } else if (direction == SearchDirection.EOL_BACKWARD) { - int lineEnd = contents.indexOf('\n', offset); - if (lineEnd == -1) { - lineEnd = contents.length(); - } - - index = findPreviousMatch(contents, lineEnd, patternStart, hints); - line = adjustLine(contents, line, offset, index); - } else if (direction == SearchDirection.FORWARD) { - index = findNextMatch(contents, offset, patternStart, hints); - line = adjustLine(contents, line, offset, index); - } else { - assert direction == SearchDirection.NEAREST || - direction == SearchDirection.EOL_NEAREST; - - int lineEnd = contents.indexOf('\n', offset); - if (lineEnd == -1) { - lineEnd = contents.length(); - } - offset = lineEnd; - - int before = findPreviousMatch(contents, offset, patternStart, hints); - int after = findNextMatch(contents, offset, patternStart, hints); - - if (before == -1) { - index = after; - line = adjustLine(contents, line, offset, index); - } else if (after == -1) { - index = before; - line = adjustLine(contents, line, offset, index); - } else { - int newLinesBefore = 0; - for (int i = before; i < offset; i++) { - if (contents.charAt(i) == '\n') { - newLinesBefore++; - } - } - int newLinesAfter = 0; - for (int i = offset; i < after; i++) { - if (contents.charAt(i) == '\n') { - newLinesAfter++; - } - } - if (newLinesBefore < newLinesAfter || newLinesBefore == newLinesAfter - && offset - before < after - offset) { - index = before; - line = adjustLine(contents, line, offset, index); - } else { - index = after; - line = adjustLine(contents, line, offset, index); - } - } - } - - if (index != -1) { - int lineStart = contents.lastIndexOf('\n', index); - if (lineStart == -1) { - lineStart = 0; - } else { - lineStart++; // was pointing to the previous line's CR, not line start - } - int column = index - lineStart; - if (patternEnd != null) { - int end = contents.indexOf(patternEnd, offset + patternStart.length()); - if (end != -1) { - return new Location(file, new DefaultPosition(line, column, index), - new DefaultPosition(line, -1, end + patternEnd.length())); - } - } else if (hints != null && (hints.isJavaSymbol() || hints.isWholeWord())) { - if (hints.isConstructor() && contents.startsWith(SUPER_KEYWORD, index)) { - patternStart = SUPER_KEYWORD; - } - return new Location(file, new DefaultPosition(line, column, index), - new DefaultPosition(line, column + patternStart.length(), - index + patternStart.length())); - } - return new Location(file, new DefaultPosition(line, column, index), - new DefaultPosition(line, column, index + patternStart.length())); - } - } - - Position position = new DefaultPosition(line, -1, offset); - return new Location(file, position, position); - } - - return create(file); - } - - private static int findPreviousMatch(@NonNull String contents, int offset, String pattern, - @Nullable SearchHints hints) { - while (true) { - int index = contents.lastIndexOf(pattern, offset); - if (index == -1) { - return -1; - } else { - if (isMatch(contents, index, pattern, hints)) { - return index; - } else { - offset = index - pattern.length(); - } - } - } - } - - private static int findNextMatch(@NonNull String contents, int offset, String pattern, - @Nullable SearchHints hints) { - int constructorIndex = -1; - if (hints != null && hints.isConstructor()) { - // Special condition: See if the call is referenced as "super" instead. - assert hints.isWholeWord(); - int index = contents.indexOf(SUPER_KEYWORD, offset); - if (index != -1 && isMatch(contents, index, SUPER_KEYWORD, hints)) { - constructorIndex = index; - } - } - - while (true) { - int index = contents.indexOf(pattern, offset); - if (index == -1) { - return constructorIndex; - } else { - if (isMatch(contents, index, pattern, hints)) { - if (constructorIndex != -1) { - return Math.min(constructorIndex, index); - } - return index; - } else { - offset = index + pattern.length(); - } - } - } - } - - private static boolean isMatch(@NonNull String contents, int offset, String pattern, - @Nullable SearchHints hints) { - if (!contents.startsWith(pattern, offset)) { - return false; - } - - if (hints != null) { - char prevChar = offset > 0 ? contents.charAt(offset - 1) : 0; - int lastIndex = offset + pattern.length() - 1; - char nextChar = lastIndex < contents.length() - 1 ? contents.charAt(lastIndex + 1) : 0; - - if (hints.isWholeWord() && (Character.isLetter(prevChar) - || Character.isLetter(nextChar))) { - return false; - - } - - if (hints.isJavaSymbol()) { - if (Character.isJavaIdentifierPart(prevChar) - || Character.isJavaIdentifierPart(nextChar)) { - return false; - } - - if (prevChar == '"') { - return false; - } - - // TODO: Additional validation to see if we're in a comment, string, etc. - // This will require lexing from the beginning of the buffer. - } - - if (hints.isConstructor() && SUPER_KEYWORD.equals(pattern)) { - // Only looking for super(), not super.x, so assert that the next - // non-space character is ( - int index = lastIndex + 1; - while (index < contents.length() - 1) { - char c = contents.charAt(index); - if (c == '(') { - break; - } else if (!Character.isWhitespace(c)) { - return false; - } - index++; - } - } - } - - return true; - } - - private static int adjustLine(String doc, int line, int offset, int newOffset) { - if (newOffset == -1) { - return line; - } - - if (newOffset < offset) { - return line - countLines(doc, newOffset, offset); - } else { - return line + countLines(doc, offset, newOffset); - } - } - - private static int countLines(String doc, int start, int end) { - int lines = 0; - for (int offset = start; offset < end; offset++) { - char c = doc.charAt(offset); - if (c == '\n') { - lines++; - } - } - - return lines; - } - - /** - * Reverses the secondary location list initiated by the given location - * - * @param location the first location in the list - * @return the first location in the reversed list - */ - public static Location reverse(@NonNull Location location) { - Location next = location.getSecondary(); - location.setSecondary(null); - while (next != null) { - Location nextNext = next.getSecondary(); - next.setSecondary(location); - location = next; - next = nextNext; - } - - return location; - } - - /** - * A {@link Handle} is a reference to a location. The point of a location - * handle is to be able to create them cheaply, and then resolve them into - * actual locations later (if needed). This makes it possible to for example - * delay looking up line numbers, for locations that are offset based. - */ - public interface Handle { - /** - * Compute a full location for the given handle - * - * @return create a location for this handle - */ - @NonNull - Location resolve(); - - /** - * Sets the client data associated with this location. This is an optional - * field which can be used by the creator of the {@link Location} to store - * temporary state associated with the location. - * - * @param clientData the data to store with this location - */ - void setClientData(@Nullable Object clientData); - - /** - * Returns the client data associated with this location - an optional field - * which can be used by the creator of the {@link Location} to store - * temporary state associated with the location. - * - * @return the data associated with this location - */ - @Nullable - Object getClientData(); - } - - /** A default {@link Handle} implementation for simple file offsets */ - public static class DefaultLocationHandle implements Handle { - private final File mFile; - private final String mContents; - private final int mStartOffset; - private final int mEndOffset; - private Object mClientData; - - /** - * Constructs a new {@link DefaultLocationHandle} - * - * @param context the context pointing to the file and its contents - * @param startOffset the start offset within the file - * @param endOffset the end offset within the file - */ - public DefaultLocationHandle(@NonNull Context context, int startOffset, int endOffset) { - mFile = context.file; - mContents = context.getContents(); - mStartOffset = startOffset; - mEndOffset = endOffset; - } - - @Override - @NonNull - public Location resolve() { - return create(mFile, mContents, mStartOffset, mEndOffset); - } - - @Override - public void setClientData(@Nullable Object clientData) { - mClientData = clientData; - } - - @Override - @Nullable - public Object getClientData() { - return mClientData; - } - } - - public static class ResourceItemHandle implements Handle { - private final ResourceItem mItem; - - public ResourceItemHandle(@NonNull ResourceItem item) { - mItem = item; - } - @NonNull - @Override - public Location resolve() { - // TODO: Look up the exact item location more - // closely - ResourceFile source = mItem.getSource(); - assert source != null : mItem; - return create(source.getFile()); - } - - @Override - public void setClientData(@Nullable Object clientData) { - } - - @Nullable - @Override - public Object getClientData() { - return null; - } - } - - /** - * Whether to look forwards, or backwards, or in both directions, when - * searching for a pattern in the source code to determine the right - * position range for a given symbol. - *

- * When dealing with bytecode for example, there are only line number entries - * within method bodies, so when searching for the method declaration, we should only - * search backwards from the first line entry in the method. - */ - public enum SearchDirection { - /** Only search forwards */ - FORWARD, - - /** Only search backwards */ - BACKWARD, - - /** Search backwards from the current end of line (normally it's the beginning of - * the current line) */ - EOL_BACKWARD, - - /** - * Search both forwards and backwards from the given line, and prefer - * the match that is closest - */ - NEAREST, - - /** - * Search both forwards and backwards from the end of the given line, and prefer - * the match that is closest - */ - EOL_NEAREST, - } - - /** - * Extra information pertaining to finding a symbol in a source buffer, - * used by {@link Location#create(File, String, int, String, String, SearchHints)} - */ - public static class SearchHints { - /** - * the direction to search for the nearest match in (provided - * {@code patternStart} is non null) - */ - @NonNull - private final SearchDirection mDirection; - - /** Whether the matched pattern should be a whole word */ - private boolean mWholeWord; - - /** - * Whether the matched pattern should be a Java symbol (so for example, - * a match inside a comment or string literal should not be used) - */ - private boolean mJavaSymbol; - - /** - * Whether the matched pattern corresponds to a constructor; if so, look for - * some other possible source aliases too, such as "super". - */ - private boolean mConstructor; - - private SearchHints(@NonNull SearchDirection direction) { - super(); - mDirection = direction; - } - - /** - * Constructs a new {@link SearchHints} object - * - * @param direction the direction to search in for the pattern - * @return a new @link SearchHints} object - */ - @NonNull - public static SearchHints create(@NonNull SearchDirection direction) { - return new SearchHints(direction); - } - - /** - * Indicates that pattern matches should apply to whole words only - - * @return this, for constructor chaining - */ - @NonNull - public SearchHints matchWholeWord() { - mWholeWord = true; - - return this; - } - - /** @return true if the pattern match should be for whole words only */ - public boolean isWholeWord() { - return mWholeWord; - } - - /** - * Indicates that pattern matches should apply to Java symbols only - * - * @return this, for constructor chaining - */ - @NonNull - public SearchHints matchJavaSymbol() { - mJavaSymbol = true; - mWholeWord = true; - - return this; - } - - /** @return true if the pattern match should be for Java symbols only */ - public boolean isJavaSymbol() { - return mJavaSymbol; - } - - /** - * Indicates that pattern matches should apply to constructors. If so, look for - * some other possible source aliases too, such as "super". - * - * @return this, for constructor chaining - */ - @NonNull - public SearchHints matchConstructor() { - mConstructor = true; - mWholeWord = true; - mJavaSymbol = true; - - return this; - } - - /** @return true if the pattern match should be for a constructor */ - public boolean isConstructor() { - return mConstructor; - } - } -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/Position.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/Position.java.173 deleted file mode 100644 index 02756d7bbda..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/Position.java.173 +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2011 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.detector.api; - -import com.google.common.annotations.Beta; - -/** - * Information about a position in a file/document. - *

- * NOTE: This is not a public or final API; if you rely on this be prepared - * to adjust your code for the next tools release. - */ -@Beta -public abstract class Position { - /** - * Returns the line number (0-based where the first line is line 0) - * - * @return the 0-based line number - */ - public abstract int getLine(); - - /** - * The character offset - * - * @return the 0-based character offset - */ - public abstract int getOffset(); - - /** - * Returns the column number (where the first character on the line is 0), - * or -1 if unknown - * - * @return the 0-based column number - */ - public abstract int getColumn(); -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/Project.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/Project.java.173 deleted file mode 100644 index ba3221cc5b0..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/Project.java.173 +++ /dev/null @@ -1,1491 +0,0 @@ -/* - * Copyright (C) 2011 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.detector.api; - -import static com.android.SdkConstants.ANDROID_LIBRARY; -import static com.android.SdkConstants.ANDROID_LIBRARY_REFERENCE_FORMAT; -import static com.android.SdkConstants.ANDROID_MANIFEST_XML; -import static com.android.SdkConstants.ANDROID_URI; -import static com.android.SdkConstants.APPCOMPAT_LIB_ARTIFACT; -import static com.android.SdkConstants.ATTR_MIN_SDK_VERSION; -import static com.android.SdkConstants.ATTR_PACKAGE; -import static com.android.SdkConstants.ATTR_TARGET_SDK_VERSION; -import static com.android.SdkConstants.FN_ANDROID_MANIFEST_XML; -import static com.android.SdkConstants.FN_PROJECT_PROGUARD_FILE; -import static com.android.SdkConstants.OLD_PROGUARD_FILE; -import static com.android.SdkConstants.PROGUARD_CONFIG; -import static com.android.SdkConstants.PROJECT_PROPERTIES; -import static com.android.SdkConstants.RES_FOLDER; -import static com.android.SdkConstants.SUPPORT_LIB_ARTIFACT; -import static com.android.SdkConstants.TAG_USES_SDK; -import static com.android.SdkConstants.VALUE_TRUE; -import static com.android.sdklib.SdkVersionInfo.HIGHEST_KNOWN_API; -import static com.android.sdklib.SdkVersionInfo.LOWEST_ACTIVE_API; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.build.FilterData; -import com.android.build.OutputFile; -import com.android.builder.model.AndroidArtifact; -import com.android.builder.model.AndroidArtifactOutput; -import com.android.builder.model.AndroidLibrary; -import com.android.builder.model.AndroidProject; -import com.android.builder.model.ProductFlavor; -import com.android.builder.model.ProductFlavorContainer; -import com.android.builder.model.Variant; -import com.android.ide.common.repository.GradleVersion; -import com.android.ide.common.repository.ResourceVisibilityLookup; -import com.android.resources.Density; -import com.android.resources.ResourceFolderType; -import com.android.sdklib.AndroidVersion; -import com.android.sdklib.BuildToolInfo; -import com.android.sdklib.IAndroidTarget; -import com.android.sdklib.SdkVersionInfo; -import com.android.tools.klint.client.api.CircularDependencyException; -import com.android.tools.klint.client.api.Configuration; -import com.android.tools.klint.client.api.LintClient; -import com.android.tools.klint.client.api.LintDriver; -import com.android.tools.klint.client.api.SdkInfo; -import com.google.common.annotations.Beta; -import com.google.common.base.CharMatcher; -import com.google.common.base.Charsets; -import com.google.common.base.Splitter; -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; -import com.google.common.io.Closeables; -import com.google.common.io.Files; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; - -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * A project contains information about an Android project being scanned for - * Lint errors. - *

- * NOTE: This is not a public or final API; if you rely on this be prepared - * to adjust your code for the next tools release. - */ -@Beta -public class Project { - protected final LintClient mClient; - protected final File mDir; - protected final File mReferenceDir; - protected Configuration mConfiguration; - protected String mPackage; - protected int mBuildSdk = -1; - protected IAndroidTarget mTarget; - - protected AndroidVersion mManifestMinSdk = AndroidVersion.DEFAULT; - protected AndroidVersion mManifestTargetSdk = AndroidVersion.DEFAULT; - - protected boolean mLibrary; - protected String mName; - protected String mProguardPath; - protected boolean mMergeManifests; - - /** The SDK info, if any */ - protected SdkInfo mSdkInfo; - - /** - * If non null, specifies a non-empty list of specific files under this - * project which should be checked. - */ - protected List mFiles; - protected List mProguardFiles; - protected List mGradleFiles; - protected List mManifestFiles; - protected List mJavaSourceFolders; - protected List mJavaClassFolders; - protected List mNonProvidedJavaLibraries; - protected List mJavaLibraries; - protected List mTestSourceFolders; - protected List mResourceFolders; - protected List mAssetFolders; - protected List mDirectLibraries; - protected List mAllLibraries; - protected boolean mReportIssues = true; - protected Boolean mGradleProject; - protected Boolean mSupportLib; - protected Boolean mAppCompat; - protected GradleVersion mGradleVersion; - private Map mSuperClassMap; - private ResourceVisibilityLookup mResourceVisibility; - private BuildToolInfo mBuildTools; - - /** - * Creates a new {@link Project} for the given directory. - * - * @param client the tool running the lint check - * @param dir the root directory of the project - * @param referenceDir See {@link #getReferenceDir()}. - * @return a new {@link Project} - */ - @NonNull - public static Project create( - @NonNull LintClient client, - @NonNull File dir, - @NonNull File referenceDir) { - return new Project(client, dir, referenceDir); - } - - /** - * Returns true if this project is a Gradle-based Android project - * - * @return true if this is a Gradle-based project - */ - public boolean isGradleProject() { - if (mGradleProject == null) { - mGradleProject = mClient.isGradleProject(this); - } - - return mGradleProject; - } - - /** - * Returns true if this project is an Android project. - * - * @return true if this project is an Android project. - */ - @SuppressWarnings("MethodMayBeStatic") - public boolean isAndroidProject() { - return true; - } - - /** - * Returns the project model for this project if it corresponds to - * a Gradle project. This is the case if {@link #isGradleProject()} - * is true and {@link #isLibrary()} is false. - * - * @return the project model, or null - */ - @Nullable - public AndroidProject getGradleProjectModel() { - return null; - } - - /** - * If this is a Gradle project with a valid Gradle model, return the version - * of the model/plugin. - * - * @return the Gradle plugin version, or null if invalid or not a Gradle project - */ - @Nullable - public GradleVersion getGradleModelVersion() { - if (mGradleVersion == null && isGradleProject()) { - AndroidProject gradleProjectModel = getGradleProjectModel(); - if (gradleProjectModel != null) { - mGradleVersion = GradleVersion.tryParse(gradleProjectModel.getModelVersion()); - } - } - - return mGradleVersion; - } - - /** - * Returns the project model for this project if it corresponds to - * a Gradle library. This is the case if both - * {@link #isGradleProject()} and {@link #isLibrary()} return true. - * - * @return the project model, or null - */ - @SuppressWarnings("UnusedDeclaration") - @Nullable - public AndroidLibrary getGradleLibraryModel() { - return null; - } - - /** - * Returns the current selected variant, if any (and if the current project is a Gradle - * project). This can be used by incremental lint rules to warn about problems in the current - * context. Lint rules should however strive to perform cross variant analysis and warn about - * problems in any configuration. - * - * @return the select variant, or null - */ - @Nullable - public Variant getCurrentVariant() { - return null; - } - - /** Creates a new Project. Use one of the factory methods to create. */ - protected Project( - @NonNull LintClient client, - @NonNull File dir, - @NonNull File referenceDir) { - mClient = client; - mDir = dir; - mReferenceDir = referenceDir; - initialize(); - } - - protected void initialize() { - // Default initialization: Use ADT/ant style project.properties file - try { - // Read properties file and initialize library state - Properties properties = new Properties(); - File propFile = new File(mDir, PROJECT_PROPERTIES); - if (propFile.exists()) { - BufferedInputStream is = new BufferedInputStream(new FileInputStream(propFile)); - try { - properties.load(is); - String value = properties.getProperty(ANDROID_LIBRARY); - mLibrary = VALUE_TRUE.equals(value); - String proguardPath = properties.getProperty(PROGUARD_CONFIG); - if (proguardPath != null) { - mProguardPath = proguardPath; - } - mMergeManifests = VALUE_TRUE.equals(properties.getProperty( - "manifestmerger.enabled")); //$NON-NLS-1$ - String target = properties.getProperty("target"); //$NON-NLS-1$ - if (target != null) { - int index = target.lastIndexOf('-'); - if (index == -1) { - index = target.lastIndexOf(':'); - } - if (index != -1) { - String versionString = target.substring(index + 1); - try { - mBuildSdk = Integer.parseInt(versionString); - } catch (NumberFormatException nufe) { - mClient.log(Severity.WARNING, null, - "Unexpected build target format: %1$s", target); - } - } - } - - for (int i = 1; i < 1000; i++) { - String key = String.format(ANDROID_LIBRARY_REFERENCE_FORMAT, i); - String library = properties.getProperty(key); - if (library == null || library.isEmpty()) { - // No holes in the numbering sequence is allowed - break; - } - - File libraryDir = new File(mDir, library).getCanonicalFile(); - - if (mDirectLibraries == null) { - mDirectLibraries = new ArrayList(); - } - - // Adjust the reference dir to be a proper prefix path of the - // library dir - File libraryReferenceDir = mReferenceDir; - if (!libraryDir.getPath().startsWith(mReferenceDir.getPath())) { - // Symlinks etc might have been resolved, so do those to - // the reference dir as well - libraryReferenceDir = libraryReferenceDir.getCanonicalFile(); - if (!libraryDir.getPath().startsWith(mReferenceDir.getPath())) { - File file = libraryReferenceDir; - while (file != null && !file.getPath().isEmpty()) { - if (libraryDir.getPath().startsWith(file.getPath())) { - libraryReferenceDir = file; - break; - } - file = file.getParentFile(); - } - } - } - - try { - Project libraryPrj = mClient.getProject(libraryDir, - libraryReferenceDir); - mDirectLibraries.add(libraryPrj); - // By default, we don't report issues in inferred library projects. - // The driver will set report = true for those library explicitly - // requested. - libraryPrj.setReportIssues(false); - } catch (CircularDependencyException e) { - e.setProject(this); - e.setLocation(Location.create(propFile)); - throw e; - } - } - } finally { - try { - Closeables.close(is, true /* swallowIOException */); - } catch (IOException e) { - // cannot happen - } - } - } - } catch (IOException ioe) { - mClient.log(ioe, "Initializing project state"); - } - - if (mDirectLibraries != null) { - mDirectLibraries = Collections.unmodifiableList(mDirectLibraries); - } else { - mDirectLibraries = Collections.emptyList(); - } - - if (isAospBuildEnvironment()) { - if (isAospFrameworksRelatedProject(mDir)) { - // No manifest file for this project: just init the manifest values here - mManifestMinSdk = mManifestTargetSdk = new AndroidVersion(HIGHEST_KNOWN_API, null); - } else if (mBuildSdk == -1) { - // only set BuildSdk for projects other than frameworks and - // the ones that don't have one set in project.properties. - mBuildSdk = getClient().getHighestKnownApiLevel(); - } - - } - } - - @Override - public String toString() { - return "Project [dir=" + mDir + ']'; - } - - @Override - public int hashCode() { - return mDir.hashCode(); - } - - @Override - public boolean equals(@Nullable Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Project other = (Project) obj; - return mDir.equals(other.mDir); - } - - /** - * Adds the given file to the list of files which should be checked in this - * project. If no files are added, the whole project will be checked. - * - * @param file the file to be checked - */ - public void addFile(@NonNull File file) { - if (mFiles == null) { - mFiles = new ArrayList(); - } - mFiles.add(file); - } - - /** - * The list of files to be checked in this project. If null, the whole - * project should be checked. - * - * @return the subset of files to be checked, or null for the whole project - */ - @Nullable - public List getSubset() { - return mFiles; - } - - /** - * Returns the list of source folders for Java source files - * - * @return a list of source folders to search for .java files - */ - @NonNull - public List getJavaSourceFolders() { - if (mJavaSourceFolders == null) { - if (isAospFrameworksRelatedProject(mDir)) { - return Collections.singletonList(new File(mDir, "java")); //$NON-NLS-1$ - } - if (isAospBuildEnvironment()) { - String top = getAospTop(); - if (mDir.getAbsolutePath().startsWith(top)) { - mJavaSourceFolders = getAospJavaSourcePath(); - return mJavaSourceFolders; - } - } - - mJavaSourceFolders = mClient.getJavaSourceFolders(this); - } - - return mJavaSourceFolders; - } - - /** - * Returns the list of output folders for class files - * @return a list of output folders to search for .class files - */ - @NonNull - public List getJavaClassFolders() { - if (mJavaClassFolders == null) { - if (isAospFrameworksProject(mDir)) { - String top = getAospTop(); - if (top != null) { - File out = new File(top, "out"); //$NON-NLS-1$ - if (out.exists()) { - String relative = - "target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar"; - File jar = new File(out, relative.replace('/', File.separatorChar)); - if (jar.exists()) { - mJavaClassFolders = Collections.singletonList(jar); - return mJavaClassFolders; - } - } - } - } - if (isAospBuildEnvironment()) { - String top = getAospTop(); - if (mDir.getAbsolutePath().startsWith(top)) { - mJavaClassFolders = getAospJavaClassPath(); - return mJavaClassFolders; - } - } - - mJavaClassFolders = mClient.getJavaClassFolders(this); - } - return mJavaClassFolders; - } - - /** - * Returns the list of Java libraries (typically .jar files) that this - * project depends on. Note that this refers to jar libraries, not Android - * library projects which are processed in a separate pass with their own - * source and class folders. - * - * @param includeProvided If true, included provided libraries too (libraries - * that are not packaged with the app, but are provided - * for compilation purposes and are assumed to be present - * in the running environment) - * @return a list of .jar files (or class folders) that this project depends - * on. - */ - @NonNull - public List getJavaLibraries(boolean includeProvided) { - if (includeProvided) { - if (mJavaLibraries == null) { - // AOSP builds already merge libraries and class folders into - // the single classes.jar file, so these have already been processed - // in getJavaClassFolders. - mJavaLibraries = mClient.getJavaLibraries(this, true); - if (isAospBuildEnvironment()) { - // We still need to add the support-annotations library in the case of AOSP - File out = new File(getAospTop(), "out"); - String relative = "target/common/obj/JAVA_LIBRARIES/" - + "android-support-annotations_intermediates/classes"; - File annotationsDir = new File(out, relative.replace('/', File.separatorChar)); - if (annotationsDir.exists()) { - mJavaLibraries.add(annotationsDir); - } - } - } - return mJavaLibraries; - } else { - if (mNonProvidedJavaLibraries == null) { - mNonProvidedJavaLibraries = mClient.getJavaLibraries(this, false); - } - return mNonProvidedJavaLibraries; - } - } - - /** - * Returns the list of source folders for Java test source files - * - * @return a list of source folders to search for .java files - */ - @NonNull - public List getTestSourceFolders() { - if (mTestSourceFolders == null) { - mTestSourceFolders = mClient.getTestSourceFolders(this); - } - - return mTestSourceFolders; - } - - /** - * Returns the resource folders. - * - * @return a list of files pointing to the resource folders, which might be empty if the project - * does not provide any resources. - */ - @NonNull - public List getResourceFolders() { - if (mResourceFolders == null) { - List folders = mClient.getResourceFolders(this); - - if (folders.size() == 1 && isAospFrameworksRelatedProject(mDir)) { - // No manifest file for this project: just init the manifest values here - mManifestMinSdk = mManifestTargetSdk = new AndroidVersion(HIGHEST_KNOWN_API, null); - File folder = new File(folders.get(0), RES_FOLDER); - if (!folder.exists()) { - folders = Collections.emptyList(); - } - } - - mResourceFolders = folders; - } - - return mResourceFolders; - } - - /** - * Returns the asset folders. - * - * @return a list of files pointing to the asset folders, which might be empty if the project - * does not provide any resources. - */ - @NonNull - public List getAssetFolders() { - if (mAssetFolders == null) { - mAssetFolders = mClient.getAssetFolders(this); - } - - return mAssetFolders; - } - - /** - * Returns the relative path of a given file relative to the user specified - * directory (which is often the project directory but sometimes a higher up - * directory when a directory tree is being scanned - * - * @param file the file under this project to check - * @return the path relative to the reference directory (often the project directory) - */ - @NonNull - public String getDisplayPath(@NonNull File file) { - String path = file.getPath(); - String referencePath = mReferenceDir.getPath(); - if (path.startsWith(referencePath)) { - int length = referencePath.length(); - if (path.length() > length && path.charAt(length) == File.separatorChar) { - length++; - } - - return path.substring(length); - } - - return path; - } - - /** - * Returns the relative path of a given file within the current project. - * - * @param file the file under this project to check - * @return the path relative to the project - */ - @NonNull - public String getRelativePath(@NonNull File file) { - String path = file.getPath(); - String referencePath = mDir.getPath(); - if (path.startsWith(referencePath)) { - int length = referencePath.length(); - if (path.length() > length && path.charAt(length) == File.separatorChar) { - length++; - } - - return path.substring(length); - } - - return path; - } - - /** - * Returns the project root directory - * - * @return the dir - */ - @NonNull - public File getDir() { - return mDir; - } - - /** - * Returns the original user supplied directory where the lint search - * started. For example, if you run lint against {@code /tmp/foo}, and it - * finds a project to lint in {@code /tmp/foo/dev/src/project1}, then the - * {@code dir} is {@code /tmp/foo/dev/src/project1} and the - * {@code referenceDir} is {@code /tmp/foo/}. - * - * @return the reference directory, never null - */ - @NonNull - public File getReferenceDir() { - return mReferenceDir; - } - - /** - * Gets the configuration associated with this project - * - * @param driver the current driver, if any - * @return the configuration associated with this project - */ - @NonNull - public Configuration getConfiguration(@Nullable LintDriver driver) { - if (mConfiguration == null) { - mConfiguration = mClient.getConfiguration(this, driver); - } - return mConfiguration; - } - - /** - * Returns the application package specified by the manifest - * - * @return the application package, or null if unknown - */ - @Nullable - public String getPackage() { - return mPackage; - } - - /** - * Returns the minimum API level for the project - * - * @return the minimum API level or {@link AndroidVersion#DEFAULT} if unknown - */ - @NonNull - public AndroidVersion getMinSdkVersion() { - return mManifestMinSdk == null ? AndroidVersion.DEFAULT : mManifestMinSdk; - } - - /** - * Returns the minimum API level requested by the manifest, or -1 if not - * specified. Use {@link #getMinSdkVersion()} to get a full version if you need - * to check if the platform is a preview platform etc. - * - * @return the minimum API level or -1 if unknown - */ - public int getMinSdk() { - AndroidVersion version = getMinSdkVersion(); - return version == AndroidVersion.DEFAULT ? -1 : version.getApiLevel(); - } - - /** - * Returns the target API level for the project - * - * @return the target API level or {@link AndroidVersion#DEFAULT} if unknown - */ - @NonNull - public AndroidVersion getTargetSdkVersion() { - return mManifestTargetSdk == AndroidVersion.DEFAULT - ? getMinSdkVersion() : mManifestTargetSdk; - } - - /** - * Returns the target API level specified by the manifest, or -1 if not - * specified. Use {@link #getTargetSdkVersion()} to get a full version if you need - * to check if the platform is a preview platform etc. - * - * @return the target API level or -1 if unknown - */ - public int getTargetSdk() { - AndroidVersion version = getTargetSdkVersion(); - return version == AndroidVersion.DEFAULT ? -1 : version.getApiLevel(); - } - - /** - * Returns the target API used to build the project, or -1 if not known - * - * @return the build target API or -1 if unknown - */ - public int getBuildSdk() { - return mBuildSdk; - } - - /** - * Returns the specific version of the build tools being used, if known - * - * @return the build tools version in use, or null if not known - */ - @Nullable - public BuildToolInfo getBuildTools() { - if (mBuildTools == null) { - mBuildTools = mClient.getBuildTools(this); - } - - return mBuildTools; - } - - /** - * Returns the target used to build the project, or null if not known - * - * @return the build target, or null - */ - @Nullable - public IAndroidTarget getBuildTarget() { - if (mTarget == null) { - mTarget = mClient.getCompileTarget(this); - } - - return mTarget; - } - - /** - * Initialized the manifest state from the given manifest model - * - * @param document the DOM document for the manifest XML document - */ - public void readManifest(@NonNull Document document) { - Element root = document.getDocumentElement(); - if (root == null) { - return; - } - - mPackage = root.getAttribute(ATTR_PACKAGE); - - // Treat support libraries as non-reportable (in Eclipse where we don't - // have binary libraries, the support libraries have to be source-copied into - // the workspace which then triggers warnings in these libraries that users - // shouldn't have to investigate) - if (mPackage != null && mPackage.startsWith("android.support.")) { - mReportIssues = false; - } - - // Initialize minSdk and targetSdk - mManifestMinSdk = AndroidVersion.DEFAULT; - mManifestTargetSdk = AndroidVersion.DEFAULT; - NodeList usesSdks = root.getElementsByTagName(TAG_USES_SDK); - if (usesSdks.getLength() > 0) { - Element element = (Element) usesSdks.item(0); - - String minSdk = null; - if (element.hasAttributeNS(ANDROID_URI, ATTR_MIN_SDK_VERSION)) { - minSdk = element.getAttributeNS(ANDROID_URI, ATTR_MIN_SDK_VERSION); - } - if (minSdk != null) { - IAndroidTarget[] targets = mClient.getTargets(); - mManifestMinSdk = SdkVersionInfo.getVersion(minSdk, targets); - } - - if (element.hasAttributeNS(ANDROID_URI, ATTR_TARGET_SDK_VERSION)) { - String targetSdk = element.getAttributeNS(ANDROID_URI, ATTR_TARGET_SDK_VERSION); - if (targetSdk != null) { - IAndroidTarget[] targets = mClient.getTargets(); - mManifestTargetSdk = SdkVersionInfo.getVersion(targetSdk, targets); - } - } else { - mManifestTargetSdk = mManifestMinSdk; - } - } else if (isAospBuildEnvironment()) { - extractAospMinSdkVersion(); - mManifestTargetSdk = mManifestMinSdk; - } - } - - /** - * Returns true if this project is an Android library project - * - * @return true if this project is an Android library project - */ - public boolean isLibrary() { - return mLibrary; - } - - /** - * Returns the list of library projects referenced by this project - * - * @return the list of library projects referenced by this project, never - * null - */ - @NonNull - public List getDirectLibraries() { - return mDirectLibraries != null ? mDirectLibraries : Collections.emptyList(); - } - - /** - * Returns the transitive closure of the library projects for this project - * - * @return the transitive closure of the library projects for this project - */ - @NonNull - public List getAllLibraries() { - if (mAllLibraries == null) { - if (mDirectLibraries.isEmpty()) { - return mDirectLibraries; - } - - List all = new ArrayList(); - Set seen = Sets.newHashSet(); - Set path = Sets.newHashSet(); - seen.add(this); - path.add(this); - addLibraryProjects(all, seen, path); - mAllLibraries = all; - } - - return mAllLibraries; - } - - /** - * Adds this project's library project and their library projects - * recursively into the given collection of projects - * - * @param collection the collection to add the projects into - * @param seen full set of projects we've processed - * @param path the current path of library dependencies followed - */ - private void addLibraryProjects(@NonNull Collection collection, - @NonNull Set seen, @NonNull Set path) { - for (Project library : mDirectLibraries) { - if (seen.contains(library)) { - if (path.contains(library)) { - mClient.log(Severity.WARNING, null, - "Internal lint error: cyclic library dependency for %1$s", library); - } - continue; - } - collection.add(library); - seen.add(library); - path.add(library); - // Recurse - library.addLibraryProjects(collection, seen, path); - path.remove(library); - } - } - - /** - * Gets the SDK info for the current project. - * - * @return the SDK info for the current project, never null - */ - @NonNull - public SdkInfo getSdkInfo() { - if (mSdkInfo == null) { - mSdkInfo = mClient.getSdkInfo(this); - } - - return mSdkInfo; - } - - /** - * Gets the paths to the manifest files in this project, if any exists. The manifests - * should be provided such that the main manifest comes first, then any flavor versions, - * then any build types. - * - * @return the path to the manifest file, or null if it does not exist - */ - @NonNull - public List getManifestFiles() { - if (mManifestFiles == null) { - File manifestFile = new File(mDir, ANDROID_MANIFEST_XML); - if (manifestFile.exists()) { - mManifestFiles = Collections.singletonList(manifestFile); - } else { - mManifestFiles = Collections.emptyList(); - } - } - - return mManifestFiles; - } - - /** - * Returns the proguard files configured for this project, if any - * - * @return the proguard files, if any - */ - @NonNull - public List getProguardFiles() { - if (mProguardFiles == null) { - List files = new ArrayList(); - if (mProguardPath != null) { - Splitter splitter = Splitter.on(CharMatcher.anyOf(":;")); //$NON-NLS-1$ - for (String path : splitter.split(mProguardPath)) { - if (path.contains("${")) { //$NON-NLS-1$ - // Don't analyze the global/user proguard files - continue; - } - File file = new File(path); - if (!file.isAbsolute()) { - file = new File(getDir(), path); - } - if (file.exists()) { - files.add(file); - } - } - } - if (files.isEmpty()) { - File file = new File(getDir(), OLD_PROGUARD_FILE); - if (file.exists()) { - files.add(file); - } - file = new File(getDir(), FN_PROJECT_PROGUARD_FILE); - if (file.exists()) { - files.add(file); - } - } - mProguardFiles = files; - } - return mProguardFiles; - } - - /** - * Returns the Gradle build script files configured for this project, if any - * - * @return the Gradle files, if any - */ - @NonNull - public List getGradleBuildScripts() { - if (mGradleFiles == null) { - if (isGradleProject()) { - mGradleFiles = Lists.newArrayListWithExpectedSize(2); - File build = new File(mDir, SdkConstants.FN_BUILD_GRADLE); - if (build.exists()) { - mGradleFiles.add(build); - } - File settings = new File(mDir, SdkConstants.FN_SETTINGS_GRADLE); - if (settings.exists()) { - mGradleFiles.add(settings); - } - } else { - mGradleFiles = Collections.emptyList(); - } - } - - return mGradleFiles; - } - - /** - * Returns the name of the project - * - * @return the name of the project, never null - */ - @NonNull - public String getName() { - if (mName == null) { - mName = mClient.getProjectName(this); - } - - return mName; - } - - /** - * Sets the name of the project - * - * @param name the name of the project, never null - */ - public void setName(@NonNull String name) { - assert !name.isEmpty(); - mName = name; - } - - /** - * Sets whether lint should report issues in this project. See - * {@link #getReportIssues()} for a full description of what that means. - * - * @param reportIssues whether lint should report issues in this project - */ - public void setReportIssues(boolean reportIssues) { - mReportIssues = reportIssues; - } - - /** - * Returns whether lint should report issues in this project. - *

- * If a user specifies a project and its library projects for analysis, then - * those library projects are all "included", and all errors found in all - * the projects are reported. But if the user is only running lint on the - * main project, we shouldn't report errors in any of the library projects. - * We still need to consider them for certain types of checks, such - * as determining whether resources found in the main project are unused, so - * the detectors must still get a chance to look at these projects. The - * {@code #getReportIssues()} attribute is used for this purpose. - * - * @return whether lint should report issues in this project - */ - public boolean getReportIssues() { - return mReportIssues; - } - - /** - * Returns whether manifest merging is in effect - * - * @return true if manifests in library projects should be merged into main projects - */ - public boolean isMergingManifests() { - return mMergeManifests; - } - - - // --------------------------------------------------------------------------- - // Support for running lint on the AOSP source tree itself - - private static Boolean sAospBuild; - - /** Is lint running in an AOSP build environment */ - public static boolean isAospBuildEnvironment() { - if (sAospBuild == null) { - sAospBuild = getAospTop() != null; - } - - return sAospBuild; - } - - /** - * Is this the frameworks or related AOSP project? Needs some hardcoded support since - * it doesn't have a manifest file, etc. - * - * A frameworks AOSP projects can be any directory under "frameworks" that - * 1. Is not the "support" directory (which uses the public support annotations) - * 2. Doesn't have an AndroidManifest.xml (it's an app instead) - * - * @param dir the project directory to check - * @return true if this looks like the frameworks/dir project and does not have - * an AndroidManifest.xml - */ - public static boolean isAospFrameworksRelatedProject(@NonNull File dir) { - if (isAospBuildEnvironment()) { - File frameworks = new File(getAospTop(), "frameworks"); //$NON-NLS-1$ - String frameworksDir = frameworks.getAbsolutePath(); - String supportDir = new File(frameworks, "support").getAbsolutePath(); //$NON-NLS-1$ - if (dir.exists() - && !dir.getAbsolutePath().startsWith(supportDir) - && dir.getAbsolutePath().startsWith(frameworksDir) - && !(new File(dir, FN_ANDROID_MANIFEST_XML).exists())) { - return true; - } - } - return false; - } - - /** - * Is this the actual frameworks project. - * @param dir the project directory to check. - * @return true if this is the frameworks project. - */ - public static boolean isAospFrameworksProject(@NonNull File dir) { - String top = getAospTop(); - if (top != null) { - File toCompare = new File(top, "frameworks" //$NON-NLS-1$ - + File.separator + "base" //$NON-NLS-1$ - + File.separator + "core"); //$NON-NLS-1$ - try { - return dir.getCanonicalFile().equals(toCompare) && dir.exists(); - } catch (IOException e) { - return false; - } - } else { - return false; - } - } - - /** Get the root AOSP dir, if any */ - private static String getAospTop() { - return System.getenv("ANDROID_BUILD_TOP"); //$NON-NLS-1$ - } - - /** Get the host out directory in AOSP, if any */ - private static String getAospHostOut() { - return System.getenv("ANDROID_HOST_OUT"); //$NON-NLS-1$ - } - - /** Get the product out directory in AOSP, if any */ - private static String getAospProductOut() { - return System.getenv("ANDROID_PRODUCT_OUT"); //$NON-NLS-1$ - } - - private List getAospJavaSourcePath() { - List sources = new ArrayList(2); - // Normal sources - File src = new File(mDir, "src"); //$NON-NLS-1$ - if (src.exists()) { - sources.add(src); - } - - // Generates sources - for (File dir : getIntermediateDirs()) { - File classes = new File(dir, "src"); //$NON-NLS-1$ - if (classes.exists()) { - sources.add(classes); - } - } - - if (sources.isEmpty()) { - mClient.log(null, - "Warning: Could not find sources or generated sources for project %1$s", - getName()); - } - - return sources; - } - - private List getAospJavaClassPath() { - List classDirs = new ArrayList(1); - - for (File dir : getIntermediateDirs()) { - File classes = new File(dir, "classes"); //$NON-NLS-1$ - if (classes.exists()) { - classDirs.add(classes); - } else { - classes = new File(dir, "classes.jar"); //$NON-NLS-1$ - if (classes.exists()) { - classDirs.add(classes); - } - } - } - - if (classDirs.isEmpty()) { - mClient.log(null, - "No bytecode found: Has the project been built? (%1$s)", getName()); - } - - return classDirs; - } - - /** Find the _intermediates directories for a given module name */ - private List getIntermediateDirs() { - // See build/core/definitions.mk and in particular the "intermediates-dir-for" definition - List intermediates = new ArrayList(); - - // TODO: Look up the module name, e.g. LOCAL_MODULE. However, - // some Android.mk files do some complicated things with it - and most - // projects use the same module name as the directory name. - String moduleName = mDir.getName(); - try { - // Get the actual directory name instead of '.' that's possible - // when using this via CLI. - moduleName = mDir.getCanonicalFile().getName(); - } catch (IOException ioe) { - // pass - } - - String top = getAospTop(); - final String[] outFolders = new String[] { - top + "/out/host/common/obj", //$NON-NLS-1$ - top + "/out/target/common/obj", //$NON-NLS-1$ - getAospHostOut() + "/obj", //$NON-NLS-1$ - getAospProductOut() + "/obj" //$NON-NLS-1$ - }; - final String[] moduleClasses = new String[] { - "APPS", //$NON-NLS-1$ - "JAVA_LIBRARIES", //$NON-NLS-1$ - }; - - for (String out : outFolders) { - assert new File(out.replace('/', File.separatorChar)).exists() : out; - for (String moduleClass : moduleClasses) { - String path = out + '/' + moduleClass + '/' + moduleName - + "_intermediates"; //$NON-NLS-1$ - File file = new File(path.replace('/', File.separatorChar)); - if (file.exists()) { - intermediates.add(file); - } - } - } - - return intermediates; - } - - private void extractAospMinSdkVersion() { - // Is the SDK level specified by a Makefile? - boolean found = false; - File makefile = new File(mDir, "Android.mk"); //$NON-NLS-1$ - if (makefile.exists()) { - try { - List lines = Files.readLines(makefile, Charsets.UTF_8); - Pattern p = Pattern.compile("LOCAL_SDK_VERSION\\s*:=\\s*(.*)"); //$NON-NLS-1$ - for (String line : lines) { - line = line.trim(); - Matcher matcher = p.matcher(line); - if (matcher.matches()) { - found = true; - String version = matcher.group(1); - if (version.equals("current")) { //$NON-NLS-1$ - mManifestMinSdk = findCurrentAospVersion(); - } else { - mManifestMinSdk = SdkVersionInfo.getVersion(version, - mClient.getTargets()); - } - break; - } - } - } catch (IOException ioe) { - mClient.log(ioe, null); - } - } - - if (!found) { - mManifestMinSdk = findCurrentAospVersion(); - } - } - - /** Cache for {@link #findCurrentAospVersion()} */ - private static AndroidVersion sCurrentVersion; - - /** In an AOSP build environment, identify the currently built image version, if available */ - private static AndroidVersion findCurrentAospVersion() { - if (sCurrentVersion == null) { - File versionMk = new File(getAospTop(), "build/core/version_defaults.mk" //$NON-NLS-1$ - .replace('/', File.separatorChar)); - - if (!versionMk.exists()) { - sCurrentVersion = AndroidVersion.DEFAULT; - return sCurrentVersion; - } - int sdkVersion = LOWEST_ACTIVE_API; - try { - Pattern p = Pattern.compile("PLATFORM_SDK_VERSION\\s*:=\\s*(.*)"); - List lines = Files.readLines(versionMk, Charsets.UTF_8); - for (String line : lines) { - line = line.trim(); - Matcher matcher = p.matcher(line); - if (matcher.matches()) { - String version = matcher.group(1); - try { - sdkVersion = Integer.parseInt(version); - } catch (NumberFormatException nfe) { - // pass - } - break; - } - } - } catch (IOException io) { - // pass - } - sCurrentVersion = new AndroidVersion(sdkVersion, null); - } - - return sCurrentVersion; - } - - /** - * Returns true if this project depends on the given artifact. Note that - * the project doesn't have to be a Gradle project; the artifact is just - * an identifier for name a specific library, such as com.android.support:support-v4 - * to identify the support library - * - * @param artifact the Gradle/Maven name of a library - * @return true if the library is installed, false if it is not, and null if - * we're not sure - */ - @Nullable - public Boolean dependsOn(@NonNull String artifact) { - if (SUPPORT_LIB_ARTIFACT.equals(artifact)) { - if (mSupportLib == null) { - for (File file : getJavaLibraries(true)) { - String name = file.getName(); - if (name.equals("android-support-v4.jar") //$NON-NLS-1$ - || name.startsWith("support-v4-")) { //$NON-NLS-1$ - mSupportLib = true; - break; - } - } - if (mSupportLib == null) { - for (Project dependency : getDirectLibraries()) { - Boolean b = dependency.dependsOn(artifact); - if (b != null && b) { - mSupportLib = true; - break; - } - } - } - if (mSupportLib == null) { - mSupportLib = false; - } - } - - return mSupportLib; - } else if (APPCOMPAT_LIB_ARTIFACT.equals(artifact)) { - if (mAppCompat == null) { - for (File file : getJavaLibraries(true)) { - String name = file.getName(); - if (name.startsWith("appcompat-v7-")) { //$NON-NLS-1$ - mAppCompat = true; - break; - } - } - if (mAppCompat == null) { - for (Project dependency : getDirectLibraries()) { - Boolean b = dependency.dependsOn(artifact); - if (b != null && b) { - mAppCompat = true; - break; - } - } - } - if (mAppCompat == null) { - mAppCompat = false; - } - } - - return mAppCompat; - } - - return null; - } - - private List mCachedApplicableDensities; - - /** - * Returns the set of applicable densities for this project. If null, there are no density - * restrictions and all densities apply. - * - * @return the list of specific densities that apply in this project, or null if all densities - * apply - */ - @Nullable - public List getApplicableDensities() { - if (mCachedApplicableDensities == null) { - // Use the gradle API to set up relevant densities. For example, if the - // build.gradle file contains this: - // android { - // defaultConfig { - // resConfigs "nodpi", "hdpi" - // } - // } - // ...then we should only enforce hdpi densities, not all these others! - if (isGradleProject() && getGradleProjectModel() != null && - getCurrentVariant() != null) { - Set relevantDensities = Sets.newHashSet(); - Variant variant = getCurrentVariant(); - List variantFlavors = variant.getProductFlavors(); - AndroidProject gradleProjectModel = getGradleProjectModel(); - - addResConfigsFromFlavor(relevantDensities, null, - getGradleProjectModel().getDefaultConfig()); - for (ProductFlavorContainer container : gradleProjectModel.getProductFlavors()) { - addResConfigsFromFlavor(relevantDensities, variantFlavors, container); - } - - // Are there any splits that specify densities? - if (relevantDensities.isEmpty()) { - AndroidArtifact mainArtifact = variant.getMainArtifact(); - Collection outputs = mainArtifact.getOutputs(); - for (AndroidArtifactOutput output : outputs) { - for (OutputFile file : output.getOutputs()) { - final String DENSITY_NAME = OutputFile.FilterType.DENSITY.name(); - if (file.getFilterTypes().contains(DENSITY_NAME)) { - for (FilterData data : file.getFilters()) { - if (DENSITY_NAME.equals(data.getFilterType())) { - relevantDensities.add(data.getIdentifier()); - } - } - } - } - } - } - - if (!relevantDensities.isEmpty()) { - mCachedApplicableDensities = Lists.newArrayListWithExpectedSize(10); - for (String density : relevantDensities) { - String folder = ResourceFolderType.DRAWABLE.getName() + '-' + density; - mCachedApplicableDensities.add(folder); - } - Collections.sort(mCachedApplicableDensities); - } else { - mCachedApplicableDensities = Collections.emptyList(); - } - } else { - mCachedApplicableDensities = Collections.emptyList(); - } - } - - return mCachedApplicableDensities.isEmpty() ? null : mCachedApplicableDensities; - } - - /** - * Returns a super class map for this project. The keys and values are internal - * class names (e.g. java/lang/Integer, not java.lang.Integer). - * @return a map, possibly empty but never null - */ - @NonNull - public Map getSuperClassMap() { - if (mSuperClassMap == null) { - mSuperClassMap = mClient.createSuperClassMap(this); - } - - return mSuperClassMap; - } - - /** - * Adds in the resConfig values specified by the given flavor container, assuming - * it's in one of the relevant variantFlavors, into the given set - */ - private static void addResConfigsFromFlavor(@NonNull Set relevantDensities, - @Nullable List variantFlavors, - @NonNull ProductFlavorContainer container) { - ProductFlavor flavor = container.getProductFlavor(); - if (variantFlavors == null || variantFlavors.contains(flavor.getName())) { - if (!flavor.getResourceConfigurations().isEmpty()) { - for (String densityName : flavor.getResourceConfigurations()) { - Density density = Density.getEnum(densityName); - if (density != null && density.isRecommended() - && density != Density.NODPI && density != Density.ANYDPI) { - relevantDensities.add(densityName); - } - } - } - } - } - - /** - * Returns a shared {@link ResourceVisibilityLookup} - * - * @return a shared provider for looking up resource visibility - */ - @NonNull - public ResourceVisibilityLookup getResourceVisibility() { - if (mResourceVisibility == null) { - if (isGradleProject()) { - AndroidProject project = getGradleProjectModel(); - Variant variant = getCurrentVariant(); - if (project != null && variant != null) { - mResourceVisibility = mClient.getResourceVisibilityProvider().get(project, - variant); - - } else if (getGradleLibraryModel() != null) { - try { - mResourceVisibility = mClient.getResourceVisibilityProvider() - .get(getGradleLibraryModel()); - } catch (Exception ignore) { - // Handle talking to older Gradle plugins (where we don't - // have access to the model version to check up front - } - } - } - if (mResourceVisibility == null) { - mResourceVisibility = ResourceVisibilityLookup.NONE; - } - } - - return mResourceVisibility; - } - - /** - * Returns the associated client - * - * @return the client - */ - @NonNull - public LintClient getClient() { - return mClient; - } - - /** - * Returns the compile target to use for this project - * - * @return the compile target to use to build this project - */ - @Nullable - public IAndroidTarget getCompileTarget() { - return mClient.getCompileTarget(this); - } -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/ResourceContext.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/ResourceContext.java.173 deleted file mode 100644 index 33fd6849d25..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/ResourceContext.java.173 +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2014 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.detector.api; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.resources.ResourceFolderType; -import com.android.tools.klint.client.api.LintDriver; -import com.google.common.annotations.Beta; - -import java.io.File; - -/** - * A {@link com.android.tools.lint.detector.api.Context} used when checking resource files - * (both bitmaps and XML files; for XML files a subclass of this context is used: - * {@link com.android.tools.lint.detector.api.XmlContext}.) - *

- * NOTE: This is not a public or final API; if you rely on this be prepared - * to adjust your code for the next tools release. - */ -@Beta -public class ResourceContext extends Context { - private final ResourceFolderType mFolderType; - - /** - * Construct a new {@link com.android.tools.lint.detector.api.ResourceContext} - * - * @param driver the driver running through the checks - * @param project the project containing the file being checked - * @param main the main project if this project is a library project, or - * null if this is not a library project. The main project is - * the root project of all library projects, not necessarily the - * directly including project. - * @param file the file being checked - * @param folderType the {@link com.android.resources.ResourceFolderType} of this file, if any - */ - public ResourceContext( - @NonNull LintDriver driver, - @NonNull Project project, - @Nullable Project main, - @NonNull File file, - @Nullable ResourceFolderType folderType) { - super(driver, project, main, file); - mFolderType = folderType; - } - - /** - * Returns the resource folder type of this XML file, if any. - * - * @return the resource folder type or null - */ - @Nullable - public ResourceFolderType getResourceFolderType() { - return mFolderType; - } - - /** - * Returns the folder version. For example, for the file values-v14/foo.xml, - * it returns 14. - * - * @return the folder version, or -1 if no specific version was specified - */ - public int getFolderVersion() { - return mDriver.getResourceFolderVersion(file); - } -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/ResourceEvaluator.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/ResourceEvaluator.java.173 deleted file mode 100644 index 447731cf446..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/ResourceEvaluator.java.173 +++ /dev/null @@ -1,690 +0,0 @@ -/* - * Copyright (C) 2016 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.detector.api; - -import static com.android.SdkConstants.ANDROID_PKG; -import static com.android.SdkConstants.ANDROID_PKG_PREFIX; -import static com.android.SdkConstants.CLASS_CONTEXT; -import static com.android.SdkConstants.CLASS_FRAGMENT; -import static com.android.SdkConstants.CLASS_RESOURCES; -import static com.android.SdkConstants.CLASS_V4_FRAGMENT; -import static com.android.SdkConstants.R_CLASS; -import static com.android.SdkConstants.SUPPORT_ANNOTATIONS_PREFIX; -import static com.android.tools.klint.client.api.UastLintUtils.toAndroidReferenceViaResolve; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.ide.common.resources.ResourceUrl; -import com.android.resources.ResourceType; -import com.android.tools.klint.client.api.AndroidReference; -import com.android.tools.klint.client.api.JavaEvaluator; -import com.android.tools.klint.client.api.UastLintUtils; -import com.intellij.psi.PsiAnnotation; -import com.intellij.psi.PsiAssignmentExpression; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiConditionalExpression; -import com.intellij.psi.PsiDeclarationStatement; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiExpression; -import com.intellij.psi.PsiExpressionStatement; -import com.intellij.psi.PsiField; -import com.intellij.psi.PsiLocalVariable; -import com.intellij.psi.PsiMethod; -import com.intellij.psi.PsiMethodCallExpression; -import com.intellij.psi.PsiModifierListOwner; -import com.intellij.psi.PsiParameter; -import com.intellij.psi.PsiParenthesizedExpression; -import com.intellij.psi.PsiReference; -import com.intellij.psi.PsiReferenceExpression; -import com.intellij.psi.PsiStatement; -import com.intellij.psi.PsiVariable; -import com.intellij.psi.util.PsiTreeUtil; - -import org.jetbrains.uast.UCallExpression; -import org.jetbrains.uast.UElement; -import org.jetbrains.uast.UExpression; -import org.jetbrains.uast.UIfExpression; -import org.jetbrains.uast.UParenthesizedExpression; -import org.jetbrains.uast.UQualifiedReferenceExpression; -import org.jetbrains.uast.UastUtils; -import org.jetbrains.uast.UReferenceExpression; - -import java.util.EnumSet; -import java.util.List; -import java.util.Locale; - -/** Evaluates constant expressions */ -public class ResourceEvaluator { - - /** - * Marker ResourceType used to signify that an expression is of type {@code @ColorInt}, - * which isn't actually a ResourceType but one we want to specifically compare with. - * We're using {@link ResourceType#PUBLIC} because that one won't appear in the R - * class (and ResourceType is an enum we can't just create new constants for.) - */ - public static final ResourceType COLOR_INT_MARKER_TYPE = ResourceType.PUBLIC; - /** - * Marker ResourceType used to signify that an expression is of type {@code @Px}, - * which isn't actually a ResourceType but one we want to specifically compare with. - * We're using {@link ResourceType#DECLARE_STYLEABLE} because that one doesn't - * have a corresponding {@code *Res} constant (and ResourceType is an enum we can't - * just create new constants for.) - */ - public static final ResourceType PX_MARKER_TYPE = ResourceType.DECLARE_STYLEABLE; - - public static final String COLOR_INT_ANNOTATION = SUPPORT_ANNOTATIONS_PREFIX + "ColorInt"; //$NON-NLS-1$ - public static final String PX_ANNOTATION = SUPPORT_ANNOTATIONS_PREFIX + "Px"; //$NON-NLS-1$ - public static final String RES_SUFFIX = "Res"; - - public static final String CLS_TYPED_ARRAY = "android.content.res.TypedArray"; - - private final JavaContext mContext; - private final JavaEvaluator mEvaluator; - - private boolean mAllowDereference = true; - - /** - * Creates a new resource evaluator - * - * @param context Java context - */ - public ResourceEvaluator(JavaContext context) { - mContext = context; - mEvaluator = context.getEvaluator(); - } - - /** - * Whether we allow dereferencing resources when computing constants; - * e.g. if we ask for the resource for {@code x} when the code is - * {@code x = getString(R.string.name)}, if {@code allowDereference} is - * true we'll return R.string.name, otherwise we'll return null. - * - * @return this for constructor chaining - */ - public ResourceEvaluator allowDereference(boolean allow) { - mAllowDereference = allow; - return this; - } - - /** - * Evaluates the given node and returns the resource reference (type and name) it - * points to, if any - * - * @param context Java context - * @param element the node to compute the constant value for - * @return the corresponding resource url (type and name) - */ - @Nullable - public static ResourceUrl getResource( - @NonNull JavaContext context, - @NonNull PsiElement element) { - return new ResourceEvaluator(context).getResource(element); - } - - /** - * Evaluates the given node and returns the resource reference (type and name) it - * points to, if any - * - * @param context Java context - * @param element the node to compute the constant value for - * @return the corresponding resource url (type and name) - */ - @Nullable - public static ResourceUrl getResource( - @NonNull JavaContext context, - @NonNull UElement element) { - return new ResourceEvaluator(context).getResource(element); - } - - /** - * Evaluates the given node and returns the resource types implied by the given element, - * if any. - * - * @param context Java context - * @param element the node to compute the constant value for - * @return the corresponding resource types - */ - @Nullable - public static EnumSet getResourceTypes( - @NonNull JavaContext context, - @NonNull PsiElement element) { - return new ResourceEvaluator(context).getResourceTypes(element); - } - - /** - * Evaluates the given node and returns the resource types implied by the given element, - * if any. - * - * @param context Java context - * @param element the node to compute the constant value for - * @return the corresponding resource types - */ - @Nullable - public static EnumSet getResourceTypes( - @NonNull JavaContext context, - @NonNull UElement element) { - return new ResourceEvaluator(context).getResourceTypes(element); - } - - /** - * Evaluates the given node and returns the resource reference (type and name) it - * points to, if any - * - * @param element the node to compute the constant value for - * @return the corresponding constant value - a String, an Integer, a Float, and so on - */ - @Nullable - public ResourceUrl getResource(@Nullable UElement element) { - if (element == null) { - return null; - } - - if (element instanceof UIfExpression) { - UIfExpression expression = (UIfExpression) element; - Object known = ConstantEvaluator.evaluate(null, expression.getCondition()); - if (known == Boolean.TRUE && expression.getThenExpression() != null) { - return getResource(expression.getThenExpression()); - } else if (known == Boolean.FALSE && expression.getElseExpression() != null) { - return getResource(expression.getElseExpression()); - } - } else if (element instanceof UParenthesizedExpression) { - UParenthesizedExpression parenthesizedExpression = (UParenthesizedExpression) element; - return getResource(parenthesizedExpression.getExpression()); - } else if (mAllowDereference && element instanceof UQualifiedReferenceExpression) { - UQualifiedReferenceExpression qualifiedExpression = (UQualifiedReferenceExpression) element; - UExpression selector = qualifiedExpression.getSelector(); - if ((selector instanceof UCallExpression)) { - UCallExpression call = (UCallExpression) selector; - PsiMethod function = call.resolve(); - PsiClass containingClass = UastUtils.getContainingClass(function); - if (function != null && containingClass != null) { - String qualifiedName = containingClass.getQualifiedName(); - String name = call.getMethodName(); - if ((CLASS_RESOURCES.equals(qualifiedName) - || CLASS_CONTEXT.equals(qualifiedName) - || CLASS_FRAGMENT.equals(qualifiedName) - || CLASS_V4_FRAGMENT.equals(qualifiedName) - || CLS_TYPED_ARRAY.equals(qualifiedName)) - && name != null - && name.startsWith("get")) { - List args = call.getValueArguments(); - if (!args.isEmpty()) { - return getResource(args.get(0)); - } - } - } - } - } - - if (element instanceof UReferenceExpression) { - ResourceUrl url = getResourceConstant(element); - if (url != null) { - return url; - } - PsiElement resolved = ((UReferenceExpression) element).resolve(); - if (resolved instanceof PsiVariable) { - PsiVariable variable = (PsiVariable) resolved; - UElement lastAssignment = - UastLintUtils.findLastAssignment( - variable, element, mContext); - - if (lastAssignment != null) { - return getResource(lastAssignment); - } - - return null; - } - } - - return null; - } - - /** - * Evaluates the given node and returns the resource reference (type and name) it - * points to, if any - * - * @param element the node to compute the constant value for - * @return the corresponding constant value - a String, an Integer, a Float, and so on - */ - - @Nullable - public ResourceUrl getResource(@Nullable PsiElement element) { - if (element == null) { - return null; - } - if (element instanceof PsiConditionalExpression) { - PsiConditionalExpression expression = (PsiConditionalExpression) element; - Object known = ConstantEvaluator.evaluate(null, expression.getCondition()); - if (known == Boolean.TRUE && expression.getThenExpression() != null) { - return getResource(expression.getThenExpression()); - } else if (known == Boolean.FALSE && expression.getElseExpression() != null) { - return getResource(expression.getElseExpression()); - } - } else if (element instanceof PsiParenthesizedExpression) { - PsiParenthesizedExpression parenthesizedExpression = (PsiParenthesizedExpression) element; - return getResource(parenthesizedExpression.getExpression()); - } else if (element instanceof PsiMethodCallExpression && mAllowDereference) { - PsiMethodCallExpression call = (PsiMethodCallExpression) element; - PsiReferenceExpression expression = call.getMethodExpression(); - PsiMethod method = call.resolveMethod(); - if (method != null && method.getContainingClass() != null) { - String qualifiedName = method.getContainingClass().getQualifiedName(); - String name = expression.getReferenceName(); - if ((CLASS_RESOURCES.equals(qualifiedName) - || CLASS_CONTEXT.equals(qualifiedName) - || CLASS_FRAGMENT.equals(qualifiedName) - || CLASS_V4_FRAGMENT.equals(qualifiedName) - || CLS_TYPED_ARRAY.equals(qualifiedName)) - && name != null - && name.startsWith("get")) { - PsiExpression[] args = call.getArgumentList().getExpressions(); - if (args.length > 0) { - return getResource(args[0]); - } - } - } - } else if (element instanceof PsiReference) { - ResourceUrl url = getResourceConstant(element); - if (url != null) { - return url; - } - PsiElement resolved = ((PsiReference) element).resolve(); - if (resolved instanceof PsiField) { - url = getResourceConstant(resolved); - if (url != null) { - return url; - } - PsiField field = (PsiField) resolved; - if (field.getInitializer() != null) { - return getResource(field.getInitializer()); - } - return null; - } else if (resolved instanceof PsiLocalVariable) { - PsiLocalVariable variable = (PsiLocalVariable) resolved; - PsiStatement statement = PsiTreeUtil.getParentOfType(element, PsiStatement.class, - false); - if (statement != null) { - PsiStatement prev = PsiTreeUtil.getPrevSiblingOfType(statement, - PsiStatement.class); - String targetName = variable.getName(); - if (targetName == null) { - return null; - } - while (prev != null) { - if (prev instanceof PsiDeclarationStatement) { - PsiDeclarationStatement prevStatement = (PsiDeclarationStatement) prev; - for (PsiElement e : prevStatement.getDeclaredElements()) { - if (variable.equals(e)) { - return getResource(variable.getInitializer()); - } - } - } else if (prev instanceof PsiExpressionStatement) { - PsiExpression expression = ((PsiExpressionStatement) prev) - .getExpression(); - if (expression instanceof PsiAssignmentExpression) { - PsiAssignmentExpression assign - = (PsiAssignmentExpression) expression; - PsiExpression lhs = assign.getLExpression(); - if (lhs instanceof PsiReferenceExpression) { - PsiReferenceExpression reference = (PsiReferenceExpression) lhs; - if (targetName.equals(reference.getReferenceName()) && - reference.getQualifier() == null) { - return getResource(assign.getRExpression()); - } - } - } - } - prev = PsiTreeUtil.getPrevSiblingOfType(prev, - PsiStatement.class); - } - } - } - } - - return null; - } - - /** - * Evaluates the given node and returns the resource types applicable to the - * node, if any. - * - * @param element the element to compute the types for - * @return the corresponding resource types - */ - @Nullable - public EnumSet getResourceTypes(@Nullable UElement element) { - if (element == null) { - return null; - } - if (element instanceof UIfExpression) { - UIfExpression expression = (UIfExpression) element; - Object known = ConstantEvaluator.evaluate(null, expression.getCondition()); - if (known == Boolean.TRUE && expression.getThenExpression() != null) { - return getResourceTypes(expression.getThenExpression()); - } else if (known == Boolean.FALSE && expression.getElseExpression() != null) { - return getResourceTypes(expression.getElseExpression()); - } else { - EnumSet left = getResourceTypes( - expression.getThenExpression()); - EnumSet right = getResourceTypes( - expression.getElseExpression()); - if (left == null) { - return right; - } else if (right == null) { - return left; - } else { - EnumSet copy = EnumSet.copyOf(left); - copy.addAll(right); - return copy; - } - } - } else if (element instanceof UParenthesizedExpression) { - UParenthesizedExpression parenthesizedExpression = (UParenthesizedExpression) element; - return getResourceTypes(parenthesizedExpression.getExpression()); - } else if ((element instanceof UQualifiedReferenceExpression && mAllowDereference) - || element instanceof UCallExpression) { - UElement probablyCallExpression = element; - if (element instanceof UQualifiedReferenceExpression) { - UQualifiedReferenceExpression qualifiedExpression = - (UQualifiedReferenceExpression) element; - probablyCallExpression = qualifiedExpression.getSelector(); - } - if ((probablyCallExpression instanceof UCallExpression)) { - UCallExpression call = (UCallExpression) probablyCallExpression; - PsiMethod method = call.resolve(); - PsiClass containingClass = UastUtils.getContainingClass(method); - if (method != null && containingClass != null) { - EnumSet types = getTypesFromAnnotations(method); - if (types != null) { - return types; - } - - String qualifiedName = containingClass.getQualifiedName(); - String name = call.getMethodName(); - if ((CLASS_RESOURCES.equals(qualifiedName) - || CLASS_CONTEXT.equals(qualifiedName) - || CLASS_FRAGMENT.equals(qualifiedName) - || CLASS_V4_FRAGMENT.equals(qualifiedName) - || CLS_TYPED_ARRAY.equals(qualifiedName)) - && name != null - && name.startsWith("get")) { - List args = call.getValueArguments(); - if (!args.isEmpty()) { - types = getResourceTypes(args.get(0)); - if (types != null) { - return types; - } - } - } - } - } - } - - if (element instanceof UReferenceExpression) { - ResourceUrl url = getResourceConstant(element); - if (url != null) { - return EnumSet.of(url.type); - } - - PsiElement resolved = ((UReferenceExpression) element).resolve(); - if (resolved instanceof PsiVariable) { - PsiVariable variable = (PsiVariable) resolved; - UElement lastAssignment = - UastLintUtils.findLastAssignment(variable, element, mContext); - - if (lastAssignment != null) { - return getResourceTypes(lastAssignment); - } - - return null; - } - } - - return null; - } - - /** - * Evaluates the given node and returns the resource types applicable to the - * node, if any. - * - * @param element the element to compute the types for - * @return the corresponding resource types - */ - @Nullable - public EnumSet getResourceTypes(@Nullable PsiElement element) { - if (element == null) { - return null; - } - if (element instanceof PsiConditionalExpression) { - PsiConditionalExpression expression = (PsiConditionalExpression) element; - Object known = ConstantEvaluator.evaluate(null, expression.getCondition()); - if (known == Boolean.TRUE && expression.getThenExpression() != null) { - return getResourceTypes(expression.getThenExpression()); - } else if (known == Boolean.FALSE && expression.getElseExpression() != null) { - return getResourceTypes(expression.getElseExpression()); - } else { - EnumSet left = getResourceTypes( - expression.getThenExpression()); - EnumSet right = getResourceTypes( - expression.getElseExpression()); - if (left == null) { - return right; - } else if (right == null) { - return left; - } else { - EnumSet copy = EnumSet.copyOf(left); - copy.addAll(right); - return copy; - } - } - } else if (element instanceof PsiParenthesizedExpression) { - PsiParenthesizedExpression parenthesizedExpression = (PsiParenthesizedExpression) element; - return getResourceTypes(parenthesizedExpression.getExpression()); - } else if (element instanceof PsiMethodCallExpression && mAllowDereference) { - PsiMethodCallExpression call = (PsiMethodCallExpression) element; - PsiReferenceExpression expression = call.getMethodExpression(); - PsiMethod method = call.resolveMethod(); - if (method != null && method.getContainingClass() != null) { - EnumSet types = getTypesFromAnnotations(method); - if (types != null) { - return types; - } - - String qualifiedName = method.getContainingClass().getQualifiedName(); - String name = expression.getReferenceName(); - if ((CLASS_RESOURCES.equals(qualifiedName) - || CLASS_CONTEXT.equals(qualifiedName) - || CLASS_FRAGMENT.equals(qualifiedName) - || CLASS_V4_FRAGMENT.equals(qualifiedName) - || CLS_TYPED_ARRAY.equals(qualifiedName)) - && name != null - && name.startsWith("get")) { - PsiExpression[] args = call.getArgumentList().getExpressions(); - if (args.length > 0) { - types = getResourceTypes(args[0]); - if (types != null) { - return types; - } - } - } - } - } else if (element instanceof PsiReference) { - ResourceUrl url = getResourceConstant(element); - if (url != null) { - return EnumSet.of(url.type); - } - PsiElement resolved = ((PsiReference) element).resolve(); - if (resolved instanceof PsiField) { - url = getResourceConstant(resolved); - if (url != null) { - return EnumSet.of(url.type); - } - PsiField field = (PsiField) resolved; - if (field.getInitializer() != null) { - return getResourceTypes(field.getInitializer()); - } - return null; - } else if (resolved instanceof PsiParameter) { - return getTypesFromAnnotations((PsiParameter)resolved); - } else if (resolved instanceof PsiLocalVariable) { - PsiLocalVariable variable = (PsiLocalVariable) resolved; - PsiStatement statement = PsiTreeUtil.getParentOfType(element, PsiStatement.class, - false); - if (statement != null) { - PsiStatement prev = PsiTreeUtil.getPrevSiblingOfType(statement, - PsiStatement.class); - String targetName = variable.getName(); - if (targetName == null) { - return null; - } - while (prev != null) { - if (prev instanceof PsiDeclarationStatement) { - PsiDeclarationStatement prevStatement = (PsiDeclarationStatement) prev; - for (PsiElement e : prevStatement.getDeclaredElements()) { - if (variable.equals(e)) { - return getResourceTypes(variable.getInitializer()); - } - } - } else if (prev instanceof PsiExpressionStatement) { - PsiExpression expression = ((PsiExpressionStatement) prev) - .getExpression(); - if (expression instanceof PsiAssignmentExpression) { - PsiAssignmentExpression assign - = (PsiAssignmentExpression) expression; - PsiExpression lhs = assign.getLExpression(); - if (lhs instanceof PsiReferenceExpression) { - PsiReferenceExpression reference = (PsiReferenceExpression) lhs; - if (targetName.equals(reference.getReferenceName()) && - reference.getQualifier() == null) { - return getResourceTypes(assign.getRExpression()); - } - } - } - } - prev = PsiTreeUtil.getPrevSiblingOfType(prev, - PsiStatement.class); - } - } - } - } - - return null; - } - - @Nullable - private EnumSet getTypesFromAnnotations(PsiModifierListOwner owner) { - if (mEvaluator == null) { - return null; - } - for (PsiAnnotation annotation : mEvaluator.getAllAnnotations(owner)) { - String signature = annotation.getQualifiedName(); - if (signature == null) { - continue; - } - if (signature.equals(COLOR_INT_ANNOTATION)) { - return EnumSet.of(COLOR_INT_MARKER_TYPE); - } - if (signature.equals(PX_ANNOTATION)) { - return EnumSet.of(PX_MARKER_TYPE); - } - if (signature.endsWith(RES_SUFFIX) - && signature.startsWith(SUPPORT_ANNOTATIONS_PREFIX)) { - String typeString = signature - .substring(SUPPORT_ANNOTATIONS_PREFIX.length(), - signature.length() - RES_SUFFIX.length()) - .toLowerCase(Locale.US); - ResourceType type = ResourceType.getEnum(typeString); - if (type != null) { - return EnumSet.of(type); - } else if (typeString.equals("any")) { // @AnyRes - return getAnyRes(); - } - } - } - - return null; - } - - /** Returns a resource URL based on the field reference in the code */ - @Nullable - public static ResourceUrl getResourceConstant(@NonNull PsiElement node) { - // R.type.name - if (node instanceof PsiReferenceExpression) { - PsiReferenceExpression expression = (PsiReferenceExpression) node; - if (expression.getQualifier() instanceof PsiReferenceExpression) { - PsiReferenceExpression select = (PsiReferenceExpression) expression.getQualifier(); - if (select.getQualifier() instanceof PsiReferenceExpression) { - PsiReferenceExpression reference = (PsiReferenceExpression) select - .getQualifier(); - if (R_CLASS.equals(reference.getReferenceName())) { - String typeName = select.getReferenceName(); - String name = expression.getReferenceName(); - - ResourceType type = ResourceType.getEnum(typeName); - if (type != null && name != null) { - boolean isFramework = - reference.getQualifier() instanceof PsiReferenceExpression - && ANDROID_PKG - .equals(((PsiReferenceExpression) reference. - getQualifier()).getReferenceName()); - - return ResourceUrl.create(type, name, isFramework, false); - } - } - } - } - } else if (node instanceof PsiField) { - PsiField field = (PsiField) node; - PsiClass typeClass = field.getContainingClass(); - if (typeClass != null) { - PsiClass rClass = typeClass.getContainingClass(); - if (rClass != null && R_CLASS.equals(rClass.getName())) { - String name = field.getName(); - ResourceType type = ResourceType.getEnum(typeClass.getName()); - if (type != null && name != null) { - String qualifiedName = rClass.getQualifiedName(); - boolean isFramework = qualifiedName != null - && qualifiedName.startsWith(ANDROID_PKG_PREFIX); - return ResourceUrl.create(type, name, isFramework, false); - } - } - } - } - return null; - } - - /** Returns a resource URL based on the field reference in the code */ - @Nullable - public static ResourceUrl getResourceConstant(@NonNull UElement node) { - AndroidReference androidReference = toAndroidReferenceViaResolve(node); - if (androidReference == null) { - return null; - } - - String name = androidReference.getName(); - ResourceType type = androidReference.getType(); - boolean isFramework = androidReference.getPackage().equals("android"); - - return ResourceUrl.create(type, name, isFramework, false); - } - - private static EnumSet getAnyRes() { - EnumSet types = EnumSet.allOf(ResourceType.class); - types.remove(ResourceEvaluator.COLOR_INT_MARKER_TYPE); - types.remove(ResourceEvaluator.PX_MARKER_TYPE); - return types; - } -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/ResourceXmlDetector.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/ResourceXmlDetector.java.173 deleted file mode 100644 index 85fdcfcd72f..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/ResourceXmlDetector.java.173 +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2011 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.detector.api; - -import com.android.annotations.NonNull; -import com.android.resources.ResourceFolderType; -import com.google.common.annotations.Beta; - -import java.io.File; - -/** - * Specialized detector intended for XML resources. Detectors that apply to XML - * resources should extend this detector instead since it provides special - * iteration hooks that are more efficient. - *

- * NOTE: This is not a public or final API; if you rely on this be prepared - * to adjust your code for the next tools release. - */ -@Beta -public abstract class ResourceXmlDetector extends Detector implements Detector.XmlScanner { - @Override - public boolean appliesTo(@NonNull Context context, @NonNull File file) { - return LintUtils.isXmlFile(file); - } - - /** - * Returns whether this detector applies to the given folder type. This - * allows the detectors to be pruned from iteration, so for example when we - * are analyzing a string value file we don't need to look up detectors - * related to layout. - * - * @param folderType the folder type to be visited - * @return true if this detector can apply to resources in folders of the - * given type - */ - @Override - public boolean appliesTo(@NonNull ResourceFolderType folderType) { - return true; - } - - @Override - public void run(@NonNull Context context) { - // The infrastructure should never call this method on an xml detector since - // it will run the various visitors instead - assert false; - } -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/Scope.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/Scope.java.173 deleted file mode 100644 index e8201cf3405..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/Scope.java.173 +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright (C) 2011 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.detector.api; - -import static com.android.SdkConstants.ANDROID_MANIFEST_XML; -import static com.android.SdkConstants.DOT_CLASS; -import static com.android.SdkConstants.DOT_GRADLE; -import static com.android.SdkConstants.DOT_JAVA; -import static com.android.SdkConstants.DOT_PNG; -import static com.android.SdkConstants.DOT_PROPERTIES; -import static com.android.SdkConstants.DOT_XML; -import static com.android.SdkConstants.FN_PROJECT_PROGUARD_FILE; -import static com.android.SdkConstants.OLD_PROGUARD_FILE; -import static com.android.SdkConstants.RES_FOLDER; - -import com.android.annotations.NonNull; -import com.google.common.annotations.Beta; - -import java.io.File; -import java.util.Collection; -import java.util.EnumSet; -import java.util.List; - -/** - * The scope of a detector is the set of files a detector must consider when - * performing its analysis. This can be used to determine when issues are - * potentially obsolete, whether a detector should re-run on a file save, etc. - *

- * NOTE: This is not a public or final API; if you rely on this be prepared - * to adjust your code for the next tools release. - */ -@Beta -public enum Scope { - /** - * The analysis only considers a single XML resource file at a time. - *

- * Issues which are only affected by a single resource file can be checked - * for incrementally when a file is edited. - */ - RESOURCE_FILE, - - /** - * The analysis only considers a single binary (typically a bitmap) resource file at a time. - *

- * Issues which are only affected by a single resource file can be checked - * for incrementally when a file is edited. - */ - BINARY_RESOURCE_FILE, - - /** - * The analysis considers the resource folders (which also includes asset folders) - */ - RESOURCE_FOLDER, - - /** - * The analysis considers all the resource file. This scope must not - * be used in conjunction with {@link #RESOURCE_FILE}; an issue scope is - * either considering just a single resource file or all the resources, not - * both. - */ - ALL_RESOURCE_FILES, - - /** - * The analysis only considers a single Java source file at a time. - *

- * Issues which are only affected by a single Java source file can be - * checked for incrementally when a Java source file is edited. - */ - JAVA_FILE, - - /** - * The analysis considers all the Java source files together. - *

- * This flag is mutually exclusive with {@link #JAVA_FILE}. - */ - ALL_JAVA_FILES, - - /** - * The analysis only considers a single Java class file at a time. - *

- * Issues which are only affected by a single Java class file can be checked - * for incrementally when a Java source file is edited and then recompiled. - */ - CLASS_FILE, - - /** - * The analysis considers all the Java class files together. - *

- * This flag is mutually exclusive with {@link #CLASS_FILE}. - */ - ALL_CLASS_FILES, - - /** The analysis considers the manifest file */ - MANIFEST, - - /** The analysis considers the Proguard configuration file */ - PROGUARD_FILE, - - /** - * The analysis considers classes in the libraries for this project. These - * will be analyzed before the classes themselves. NOTE: This excludes - * provided libraries. - */ - JAVA_LIBRARIES, - - /** The analysis considers a Gradle build file */ - GRADLE_FILE, - - /** The analysis considers Java property files */ - PROPERTY_FILE, - - /** The analysis considers test sources as well */ - TEST_SOURCES, - - /** - * Scope for other files. Issues that specify a custom scope will be called unconditionally. - * This will call {@link Detector#run(Context)}} on the detectors unconditionally. - */ - OTHER; - - /** - * Returns true if the given scope set corresponds to scanning a single file - * rather than a whole project - * - * @param scopes the scope set to check - * @return true if the scope set references a single file - */ - public static boolean checkSingleFile(@NonNull EnumSet scopes) { - int size = scopes.size(); - if (size == 2) { - // When single checking a Java source file, we check both its Java source - // and the associated class files - return scopes.contains(JAVA_FILE) && scopes.contains(CLASS_FILE); - } else { - return size == 1 && - (scopes.contains(JAVA_FILE) - || scopes.contains(CLASS_FILE) - || scopes.contains(RESOURCE_FILE) - || scopes.contains(PROGUARD_FILE) - || scopes.contains(PROPERTY_FILE) - || scopes.contains(GRADLE_FILE) - || scopes.contains(MANIFEST)); - } - } - - /** - * Returns the intersection of two scope sets - * - * @param scope1 the first set to intersect - * @param scope2 the second set to intersect - * @return the intersection of the two sets - */ - @NonNull - public static EnumSet intersect( - @NonNull EnumSet scope1, - @NonNull EnumSet scope2) { - EnumSet scope = EnumSet.copyOf(scope1); - scope.retainAll(scope2); - - return scope; - } - - /** - * Infers a suitable scope to use from the given projects to be analyzed - * @param projects the projects to find a suitable scope for - * @return the scope to use - */ - @NonNull - public static EnumSet infer(@NonNull Collection projects) { - // Infer the scope - EnumSet scope = EnumSet.noneOf(Scope.class); - for (Project project : projects) { - List subset = project.getSubset(); - if (subset != null) { - for (File file : subset) { - String name = file.getName(); - if (name.equals(ANDROID_MANIFEST_XML)) { - scope.add(MANIFEST); - } else if (name.endsWith(DOT_XML)) { - scope.add(RESOURCE_FILE); - } else if (name.endsWith(".kt")) { - scope.add(JAVA_FILE); - } else if (name.endsWith(DOT_CLASS)) { - scope.add(CLASS_FILE); - } else if (name.endsWith(DOT_GRADLE)) { - scope.add(GRADLE_FILE); - } else if (name.equals(OLD_PROGUARD_FILE) - || name.equals(FN_PROJECT_PROGUARD_FILE)) { - scope.add(PROGUARD_FILE); - } else if (name.endsWith(DOT_PROPERTIES)) { - scope.add(PROPERTY_FILE); - } else if (name.endsWith(DOT_PNG)) { - scope.add(BINARY_RESOURCE_FILE); - } else if (name.equals(RES_FOLDER) - || file.getParent().equals(RES_FOLDER)) { - scope.add(ALL_RESOURCE_FILES); - scope.add(RESOURCE_FILE); - scope.add(BINARY_RESOURCE_FILE); - scope.add(RESOURCE_FOLDER); - } - } - } else { - // Specified a full project: just use the full project scope - scope = Scope.ALL; - break; - } - } - - return scope; - } - - /** All scopes: running lint on a project will check these scopes */ - public static final EnumSet ALL = EnumSet.allOf(Scope.class); - /** Scope-set used for detectors which are affected by a single resource file */ - public static final EnumSet RESOURCE_FILE_SCOPE = EnumSet.of(RESOURCE_FILE); - /** Scope-set used for detectors which are affected by a single resource folder */ - public static final EnumSet RESOURCE_FOLDER_SCOPE = EnumSet.of(RESOURCE_FOLDER); - /** Scope-set used for detectors which scan all resources */ - public static final EnumSet ALL_RESOURCES_SCOPE = EnumSet.of(ALL_RESOURCE_FILES); - /** Scope-set used for detectors which are affected by a single Java source file */ - public static final EnumSet JAVA_FILE_SCOPE = EnumSet.of(JAVA_FILE); - /** Scope-set used for detectors which are affected by a single Java class file */ - public static final EnumSet CLASS_FILE_SCOPE = EnumSet.of(CLASS_FILE); - /** Scope-set used for detectors which are affected by a single Gradle build file */ - public static final EnumSet GRADLE_SCOPE = EnumSet.of(GRADLE_FILE); - /** Scope-set used for detectors which are affected by the manifest only */ - public static final EnumSet MANIFEST_SCOPE = EnumSet.of(MANIFEST); - /** Scope-set used for detectors which correspond to some other context */ - public static final EnumSet OTHER_SCOPE = EnumSet.of(OTHER); - /** Scope-set used for detectors which are affected by a single ProGuard class file */ - public static final EnumSet PROGUARD_SCOPE = EnumSet.of(PROGUARD_FILE); - /** Scope-set used for detectors which correspond to property files */ - public static final EnumSet PROPERTY_SCOPE = EnumSet.of(PROPERTY_FILE); - /** Resource XML files and manifest files */ - public static final EnumSet MANIFEST_AND_RESOURCE_SCOPE = - EnumSet.of(Scope.MANIFEST, Scope.RESOURCE_FILE); - /** Scope-set used for detectors which are affected by single XML and Java source files */ - public static final EnumSet JAVA_AND_RESOURCE_FILES = - EnumSet.of(RESOURCE_FILE, JAVA_FILE); - /** Scope-set used for analyzing individual class files and all resource files */ - public static final EnumSet CLASS_AND_ALL_RESOURCE_FILES = - EnumSet.of(ALL_RESOURCE_FILES, CLASS_FILE); - /** Scope-set used for analyzing all class files, including those in libraries */ - public static final EnumSet ALL_CLASSES_AND_LIBRARIES = - EnumSet.of(Scope.ALL_CLASS_FILES, Scope.JAVA_LIBRARIES); - /** Scope-set used for detectors which are affected by Java libraries */ - public static final EnumSet JAVA_LIBRARY_SCOPE = EnumSet.of(JAVA_LIBRARIES); - /** Scope-set used for detectors which are affected by a single binary resource file */ - public static final EnumSet BINARY_RESOURCE_FILE_SCOPE = - EnumSet.of(BINARY_RESOURCE_FILE); -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/Severity.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/Severity.java.173 deleted file mode 100644 index c1de962099a..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/Severity.java.173 +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2011 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.detector.api; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.google.common.annotations.Beta; - -/** - * Severity of an issue found by lint - *

- * NOTE: This is not a public or final API; if you rely on this be prepared - * to adjust your code for the next tools release. - */ -@Beta -public enum Severity { - /** - * Fatal: Use sparingly because a warning marked as fatal will be - * considered critical and will abort Export APK etc in ADT - */ - @NonNull - FATAL("Fatal"), - - /** - * Errors: The issue is known to be a real error that must be addressed. - */ - @NonNull - ERROR("Error"), - - /** - * Warning: Probably a problem. - */ - @NonNull - WARNING("Warning"), - - /** - * Information only: Might not be a problem, but the check has found - * something interesting to say about the code. - */ - @NonNull - INFORMATIONAL("Information"), - - /** - * Ignore: The user doesn't want to see this issue - */ - @NonNull - IGNORE("Ignore"); - - @NonNull - private final String mDisplay; - - Severity(@NonNull String display) { - mDisplay = display; - } - - /** - * Returns a description of this severity suitable for display to the user - * - * @return a description of the severity - */ - @NonNull - public String getDescription() { - return mDisplay; - } - - /** Returns the name of this severity */ - @NonNull - public String getName() { - return name(); - } - - /** - * Looks up the severity corresponding to a given named severity. The severity - * string should be one returned by {@link #toString()} - * - * @param name the name to look up - * @return the corresponding severity, or null if it is not a valid severity name - */ - @Nullable - public static Severity fromName(@NonNull String name) { - for (Severity severity : values()) { - if (severity.name().equalsIgnoreCase(name)) { - return severity; - } - } - - return null; - } -} \ No newline at end of file diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/Speed.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/Speed.java.173 deleted file mode 100644 index b790a1a683b..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/Speed.java.173 +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2011 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.detector.api; - -import com.android.annotations.NonNull; -import com.google.common.annotations.Beta; - -/** - * Enum which describes the different computation speeds of various detectors - *

- * NOTE: This is not a public or final API; if you rely on this be prepared - * to adjust your code for the next tools release. - */ -@Beta -public enum Speed { - /** The detector can run very quickly */ - FAST("Fast"), - - /** The detector runs reasonably fast */ - NORMAL("Normal"), - - /** The detector might take a long time to run */ - SLOW("Slow"), - - /** The detector might take a huge amount of time to run */ - REALLY_SLOW("Really Slow"); - - private final String mDisplayName; - - Speed(@NonNull String displayName) { - mDisplayName = displayName; - } - - /** - * Returns the user-visible description of the speed of the given - * detector - * - * @return the description of the speed to display to the user - */ - @NonNull - public String getDisplayName() { - return mDisplayName; - } -} \ No newline at end of file diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/TextFormat.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/TextFormat.java.173 deleted file mode 100644 index c0815831741..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/TextFormat.java.173 +++ /dev/null @@ -1,405 +0,0 @@ -/* - * Copyright (C) 2014 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.detector.api; - -import com.android.annotations.NonNull; -import com.android.utils.SdkUtils; -import com.android.utils.XmlUtils; - -/** - * Lint error message, issue explanations and location descriptions - * are described in a {@link #RAW} format which looks similar to text - * but which can contain bold, symbols and links. These issues can - * also be converted to plain text and to HTML markup, using the - * {@link #convertTo(String, TextFormat)} method. - * - * @see Issue#getExplanation(TextFormat) - * @see Issue#getBriefDescription(TextFormat) - */ -public enum TextFormat { - /** - * Raw output format which is similar to text but allows some markup: - *

    - *
  • HTTP urls (http://...) - *
  • Sentences immediately surrounded by * will be shown as bold. - *
  • Sentences immediately surrounded by ` will be shown using monospace - * fonts - *
- * Furthermore, newlines are converted to br's when converting newlines. - * Note: It does not insert {@code } tags around the fragment for HTML output. - *

- * TODO: Consider switching to the restructured text format - - * http://docutils.sourceforge.net/docs/user/rst/quickstart.html - */ - RAW, - - /** - * Plain text output - */ - TEXT, - - /** - * HTML formatted output (note: does not include surrounding {@code } tags) - */ - HTML, - - /** - * HTML formatted output (note: does not include surrounding {@code } tags). - * This is like {@link #HTML}, but it does not escape unicode characters with entities. - *

- * (This is used for example in the IDE, where some partial HTML support in some - * label widgets support some HTML markup, but not numeric code character entities.) - */ - HTML_WITH_UNICODE; - - /** - * Converts the given text to HTML - * - * @param text the text to format - * @return the corresponding text formatted as HTML - */ - @NonNull - public String toHtml(@NonNull String text) { - return convertTo(text, HTML); - } - - /** - * Converts the given text to plain text - * - * @param text the tetx to format - * @return the corresponding text formatted as HTML - */ - @NonNull - public String toText(@NonNull String text) { - return convertTo(text, TEXT); - } - - /** - * Converts the given message to the given format. Note that some - * conversions are lossy; e.g. once converting away from the raw format - * (which contains all the markup) you can't convert back to it. - * Note that you can convert to the format it's already in; that just - * returns the same string. - * - * @param message the message to convert - * @param to the format to convert to - * @return a converted message - */ - public String convertTo(@NonNull String message, @NonNull TextFormat to) { - if (this == to) { - return message; - } - switch (this) { - case RAW: { - switch (to) { - case RAW: - return message; - case TEXT: - case HTML: - case HTML_WITH_UNICODE: - return to.fromRaw(message); - } - } - case TEXT: { - switch (to) { - case TEXT: - case RAW: - return message; - case HTML: - case HTML_WITH_UNICODE: - return XmlUtils.toXmlTextValue(message); - } - } - case HTML: { - switch (to) { - case HTML: - return message; - case HTML_WITH_UNICODE: - return removeNumericEntities(message); - case RAW: - case TEXT: { - return to.fromHtml(message); - - } - } - } - case HTML_WITH_UNICODE: { - switch (to) { - case HTML: - case HTML_WITH_UNICODE: - return message; - case RAW: - case TEXT: { - return to.fromHtml(message); - - } - } - } - } - return message; - } - - /** Converts to this output format from the given HTML-format text */ - @NonNull - private String fromHtml(@NonNull String html) { - assert this == RAW || this == TEXT : this; - - // Drop all tags; replace all entities, insert newlines - // (this won't do wrapping) - StringBuilder sb = new StringBuilder(html.length()); - boolean inPre = false; - for (int i = 0, n = html.length(); i < n; i++) { - char c = html.charAt(i); - if (c == '<') { - // Strip comments - if (html.startsWith("", i); - if (end == -1) { - break; // Unclosed comment - } else { - i = end + 2; - } - continue; - } - // Tags: scan forward to the end - int begin; - boolean isEndTag = false; - if (html.startsWith("', i); - if (i == -1) { - // Unclosed tag - break; - } - int end = i; - if (html.charAt(i - 1) == '/') { - end--; - isEndTag = true; - } - // TODO: Handle

 such that we don't collapse spaces and reformat there!
-                // (We do need to strip out tags and expand entities)
-                String tag = html.substring(begin, end).trim();
-                if (tag.equalsIgnoreCase("br")) {
-                    sb.append('\n');
-                } else if (tag.equalsIgnoreCase("p") // Most common block tags
-                           || tag.equalsIgnoreCase("div")
-                           || tag.equalsIgnoreCase("pre")
-                           || tag.equalsIgnoreCase("blockquote")
-                           || tag.equalsIgnoreCase("dl")
-                           || tag.equalsIgnoreCase("dd")
-                           || tag.equalsIgnoreCase("dt")
-                           || tag.equalsIgnoreCase("ol")
-                           || tag.equalsIgnoreCase("ul")
-                           || tag.equalsIgnoreCase("li")
-                            || tag.length() == 2 && tag.startsWith("h")
-                                    && Character.isDigit(tag.charAt(1))) {
-                    // Block tag: ensure new line
-                    if (sb.length() > 0 && sb.charAt(sb.length() - 1) != '\n') {
-                        sb.append('\n');
-                    }
-                    if (tag.equals("li") && !isEndTag) {
-                        sb.append("* ");
-                    }
-                    if (tag.equalsIgnoreCase("pre")) {
-                        inPre = !isEndTag;
-                    }
-                }
-            } else if (c == '&') {
-                int end = html.indexOf(';', i);
-                if (end > i) {
-                    String entity = html.substring(i, end + 1);
-                    String s = XmlUtils.fromXmlAttributeValue(entity);
-                    if (s.startsWith("&")) {
-                        // Not an XML entity; for example,  
-                        // Sadly Guava's HtmlEscapes don't handle this either.
-                        if (entity.equalsIgnoreCase(" ")) {
-                            s = " ";
-                        } else if (entity.startsWith("&#")) {
-                            try {
-                                int value = Integer.parseInt(entity.substring(2));
-                                s = Character.toString((char)value);
-                            } catch (NumberFormatException ignore) {
-                            }
-                        }
-                    }
-                    sb.append(s);
-                    i = end;
-                } else {
-                    sb.append(c);
-                }
-            } else if (Character.isWhitespace(c)) {
-                if (inPre) {
-                    sb.append(c);
-                } else if (sb.length() == 0
-                                || !Character.isWhitespace(sb.charAt(sb.length() - 1))) {
-                    sb.append(' ');
-                }
-            } else {
-                sb.append(c);
-            }
-        }
-
-        String s = sb.toString();
-
-        // Line-wrap
-        s = SdkUtils.wrap(s, 60, null);
-
-        return s;
-    }
-
-    private static final String HTTP_PREFIX = "http://"; //$NON-NLS-1$
-
-    /** Converts to this output format from the given raw-format text */
-    @NonNull
-    private String fromRaw(@NonNull String text) {
-        assert this == HTML || this == HTML_WITH_UNICODE || this == TEXT : this;
-        StringBuilder sb = new StringBuilder(3 * text.length() / 2);
-        boolean html = this == HTML || this == HTML_WITH_UNICODE;
-        boolean escapeUnicode = this == HTML;
-
-        char prev = 0;
-        int flushIndex = 0;
-        int n = text.length();
-        for (int i = 0; i < n; i++) {
-            char c = text.charAt(i);
-            if ((c == '*' || c == '`') && i < n - 1) {
-                // Scout ahead for range end
-                if (!Character.isLetterOrDigit(prev)
-                        && !Character.isWhitespace(text.charAt(i + 1))) {
-                    // Found * or ` immediately before a letter, and not in the middle of a word
-                    // Find end
-                    int end = text.indexOf(c, i + 1);
-                    if (end != -1 && (end == n - 1 || !Character.isLetter(text.charAt(end + 1)))) {
-                        if (i > flushIndex) {
-                            appendEscapedText(sb, text, html, flushIndex, i, escapeUnicode);
-                        }
-                        if (html) {
-                            String tag = c == '*' ? "b" : "code"; //$NON-NLS-1$ //$NON-NLS-2$
-                            sb.append('<').append(tag).append('>');
-                            appendEscapedText(sb, text, html, i + 1, end, escapeUnicode);
-                            sb.append('<').append('/').append(tag).append('>');
-                        } else {
-                            appendEscapedText(sb, text, html, i + 1, end, escapeUnicode);
-                        }
-                        flushIndex = end + 1;
-                        i = flushIndex - 1; // -1: account for the i++ in the loop
-                    }
-                }
-            } else if (html && c == 'h' && i < n - 1 && text.charAt(i + 1) == 't'
-                    && text.startsWith(HTTP_PREFIX, i) && !Character.isLetterOrDigit(prev)) {
-                // Find url end
-                int end = i + HTTP_PREFIX.length();
-                while (end < n) {
-                    char d = text.charAt(end);
-                    if (Character.isWhitespace(d)) {
-                        break;
-                    }
-                    end++;
-                }
-                char last = text.charAt(end - 1);
-                if (last == '.' || last == ')' || last == '!') {
-                    end--;
-                }
-                if (end > i + HTTP_PREFIX.length()) {
-                    if (i > flushIndex) {
-                        appendEscapedText(sb, text, html, flushIndex, i, escapeUnicode);
-                    }
-
-                    String url = text.substring(i, end);
-                    sb.append("');
-                    sb.append(url);
-                    sb.append("");              //$NON-NLS-1$
-
-                    flushIndex = end;
-                    i = flushIndex - 1; // -1: account for the i++ in the loop
-                }
-            }
-            prev = c;
-        }
-
-        if (flushIndex < n) {
-            appendEscapedText(sb, text, html, flushIndex, n, escapeUnicode);
-        }
-
-        return sb.toString();
-    }
-
-    private static String removeNumericEntities(@NonNull String html) {
-        if (!html.contains("&#")) {
-            return html;
-        }
-
-        StringBuilder sb = new StringBuilder(html.length());
-        for (int i = 0, n = html.length(); i < n; i++) {
-            char c = html.charAt(i);
-            if (c == '&' && i < n - 1 && html.charAt(i + 1) == '#') {
-                int end = html.indexOf(';', i + 2);
-                if (end != -1) {
-                    String decimal = html.substring(i + 2, end);
-                    try {
-                        c = (char)Integer.parseInt(decimal);
-                        sb.append(c);
-                        i = end;
-                        continue;
-                    } catch (NumberFormatException ignore) {
-                        // fall through to not escape this
-                    }
-                }
-            }
-            sb.append(c);
-        }
-
-        return sb.toString();
-    }
-
-    private static void appendEscapedText(@NonNull StringBuilder sb, @NonNull String text,
-            boolean html, int start, int end, boolean escapeUnicode) {
-        if (html) {
-            for (int i = start; i < end; i++) {
-                char c = text.charAt(i);
-                if (c == '<') {
-                    sb.append("<");                                   //$NON-NLS-1$
-                } else if (c == '&') {
-                    sb.append("&");                                  //$NON-NLS-1$
-                } else if (c == '\n') {
-                    sb.append("
\n"); - } else { - if (c > 255 && escapeUnicode) { - sb.append("&#"); //$NON-NLS-1$ - sb.append(Integer.toString(c)); - sb.append(';'); - } else if (c == '\u00a0') { - sb.append(" "); //$NON-NLS-1$ - } else { - sb.append(c); - } - } - } - } else { - for (int i = start; i < end; i++) { - char c = text.charAt(i); - sb.append(c); - } - } - } -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/TypeEvaluator.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/TypeEvaluator.java.173 deleted file mode 100644 index 74afe269b45..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/TypeEvaluator.java.173 +++ /dev/null @@ -1,417 +0,0 @@ -/* - * Copyright (C) 2015 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.detector.api; - -import static com.android.tools.klint.client.api.JavaParser.TYPE_BOOLEAN; -import static com.android.tools.klint.client.api.JavaParser.TYPE_CHAR; -import static com.android.tools.klint.client.api.JavaParser.TYPE_DOUBLE; -import static com.android.tools.klint.client.api.JavaParser.TYPE_FLOAT; -import static com.android.tools.klint.client.api.JavaParser.TYPE_INT; -import static com.android.tools.klint.client.api.JavaParser.TYPE_LONG; -import static com.android.tools.klint.client.api.JavaParser.TYPE_STRING; -import static com.android.tools.klint.detector.api.JavaContext.getParentOfType; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.tools.klint.client.api.JavaParser.DefaultTypeDescriptor; -import com.android.tools.klint.client.api.JavaParser.ResolvedClass; -import com.android.tools.klint.client.api.JavaParser.ResolvedField; -import com.android.tools.klint.client.api.JavaParser.ResolvedMethod; -import com.android.tools.klint.client.api.JavaParser.ResolvedNode; -import com.android.tools.klint.client.api.JavaParser.ResolvedVariable; -import com.android.tools.klint.client.api.JavaParser.TypeDescriptor; -import com.android.tools.klint.client.api.UastLintUtils; -import com.intellij.psi.PsiAssignmentExpression; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiDeclarationStatement; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiExpression; -import com.intellij.psi.PsiExpressionStatement; -import com.intellij.psi.PsiField; -import com.intellij.psi.PsiLocalVariable; -import com.intellij.psi.PsiMethod; -import com.intellij.psi.PsiReference; -import com.intellij.psi.PsiReferenceExpression; -import com.intellij.psi.PsiStatement; -import com.intellij.psi.PsiType; -import com.intellij.psi.util.PsiTreeUtil; - -import org.jetbrains.uast.UCallExpression; -import org.jetbrains.uast.UElement; -import org.jetbrains.uast.UExpression; -import org.jetbrains.uast.UMethod; -import org.jetbrains.uast.UVariable; -import org.jetbrains.uast.UastUtils; -import org.jetbrains.uast.UReferenceExpression; -import org.jetbrains.uast.util.UastExpressionUtils; - -import java.util.ListIterator; - -import lombok.ast.BinaryExpression; -import lombok.ast.BinaryOperator; -import lombok.ast.BooleanLiteral; -import lombok.ast.Cast; -import lombok.ast.CharLiteral; -import lombok.ast.Expression; -import lombok.ast.ExpressionStatement; -import lombok.ast.FloatingPointLiteral; -import lombok.ast.InlineIfExpression; -import lombok.ast.IntegralLiteral; -import lombok.ast.Literal; -import lombok.ast.Node; -import lombok.ast.NullLiteral; -import lombok.ast.Statement; -import lombok.ast.StringLiteral; -import lombok.ast.UnaryExpression; -import lombok.ast.VariableDeclaration; -import lombok.ast.VariableDefinition; -import lombok.ast.VariableDefinitionEntry; -import lombok.ast.VariableReference; - -/** - * Evaluates the types of nodes. This goes deeper than - * {@link JavaContext#getType(Node)} in that it analyzes the - * flow and for example figures out that if you ask for the type of {@code var} - * in this code snippet: - *
- *     Object o = new StringBuilder();
- *     Object var = o;
- * 
- * it will return "java.lang.StringBuilder". - *

- * NOTE: This type evaluator does not (yet) compute the correct - * types when involving implicit type conversions, so be careful - * if using this for primitives; e.g. for "int * long" it might return - * the type "int". - */ -public class TypeEvaluator { - private final JavaContext mContext; - - /** - * Creates a new constant evaluator - * - * @param context the context to use to resolve field references, if any - */ - public TypeEvaluator(@Nullable JavaContext context) { - mContext = context; - } - - - /** - * Returns the inferred type of the given node - * @deprecated Use {@link #evaluate(PsiElement)} instead - */ - @Deprecated - @Nullable - public TypeDescriptor evaluate(@NonNull Node node) { - ResolvedNode resolved = null; - if (mContext != null) { - resolved = mContext.resolve(node); - } - if (resolved instanceof ResolvedMethod) { - TypeDescriptor type; - ResolvedMethod method = (ResolvedMethod) resolved; - if (method.isConstructor()) { - ResolvedClass containingClass = method.getContainingClass(); - type = containingClass.getType(); - } else { - type = method.getReturnType(); - } - return type; - } - if (resolved instanceof ResolvedField) { - ResolvedField field = (ResolvedField) resolved; - Node astNode = field.findAstNode(); - if (astNode instanceof VariableDeclaration) { - VariableDeclaration declaration = (VariableDeclaration)astNode; - VariableDefinition definition = declaration.astDefinition(); - if (definition != null) { - VariableDefinitionEntry first = definition.astVariables().first(); - if (first != null) { - Expression initializer = first.astInitializer(); - if (initializer != null) { - TypeDescriptor type = evaluate(initializer); - if (type != null) { - return type; - } - } - } - } - } - return field.getType(); - } - - if (node instanceof VariableReference) { - Statement statement = getParentOfType(node, Statement.class, false); - if (statement != null) { - ListIterator iterator = statement.getParent().getChildren().listIterator(); - while (iterator.hasNext()) { - if (iterator.next() == statement) { - if (iterator.hasPrevious()) { // should always be true - iterator.previous(); - } - break; - } - } - - String targetName = ((VariableReference) node).astIdentifier().astValue(); - while (iterator.hasPrevious()) { - Node previous = iterator.previous(); - if (previous instanceof VariableDeclaration) { - VariableDeclaration declaration = (VariableDeclaration) previous; - VariableDefinition definition = declaration.astDefinition(); - for (VariableDefinitionEntry entry : definition.astVariables()) { - if (entry.astInitializer() != null && entry.astName().astValue() - .equals(targetName)) { - return evaluate(entry.astInitializer()); - } - } - } else if (previous instanceof ExpressionStatement) { - ExpressionStatement expressionStatement = (ExpressionStatement) previous; - Expression expression = expressionStatement.astExpression(); - if (expression instanceof BinaryExpression && - ((BinaryExpression) expression).astOperator() - == BinaryOperator.ASSIGN) { - BinaryExpression binaryExpression = (BinaryExpression) expression; - if (targetName.equals(binaryExpression.astLeft().toString())) { - return evaluate(binaryExpression.astRight()); - } - } - } - } - } - } else if (node instanceof Cast) { - Cast cast = (Cast) node; - if (mContext != null) { - ResolvedNode typeReference = mContext.resolve(cast.astTypeReference()); - if (typeReference instanceof ResolvedClass) { - return ((ResolvedClass) typeReference).getType(); - } - } - TypeDescriptor viewType = evaluate(cast.astOperand()); - if (viewType != null) { - return viewType; - } - } else if (node instanceof Literal) { - if (node instanceof NullLiteral) { - return null; - } else if (node instanceof BooleanLiteral) { - return new DefaultTypeDescriptor(TYPE_BOOLEAN); - } else if (node instanceof StringLiteral) { - return new DefaultTypeDescriptor(TYPE_STRING); - } else if (node instanceof CharLiteral) { - return new DefaultTypeDescriptor(TYPE_CHAR); - } else if (node instanceof IntegralLiteral) { - IntegralLiteral literal = (IntegralLiteral) node; - // Don't combine to ?: since that will promote astIntValue to a long - if (literal.astMarkedAsLong()) { - return new DefaultTypeDescriptor(TYPE_LONG); - } else { - return new DefaultTypeDescriptor(TYPE_INT); - } - } else if (node instanceof FloatingPointLiteral) { - FloatingPointLiteral literal = (FloatingPointLiteral) node; - // Don't combine to ?: since that will promote astFloatValue to a double - if (literal.astMarkedAsFloat()) { - return new DefaultTypeDescriptor(TYPE_FLOAT); - } else { - return new DefaultTypeDescriptor(TYPE_DOUBLE); - } - } - } else if (node instanceof UnaryExpression) { - return evaluate(((UnaryExpression) node).astOperand()); - } else if (node instanceof InlineIfExpression) { - InlineIfExpression expression = (InlineIfExpression) node; - if (expression.astIfTrue() != null) { - return evaluate(expression.astIfTrue()); - } else if (expression.astIfFalse() != null) { - return evaluate(expression.astIfFalse()); - } - } else if (node instanceof BinaryExpression) { - BinaryExpression expression = (BinaryExpression) node; - BinaryOperator operator = expression.astOperator(); - switch (operator) { - case LOGICAL_OR: - case LOGICAL_AND: - case EQUALS: - case NOT_EQUALS: - case GREATER: - case GREATER_OR_EQUAL: - case LESS: - case LESS_OR_EQUAL: - return new DefaultTypeDescriptor(TYPE_BOOLEAN); - } - - TypeDescriptor type = evaluate(expression.astLeft()); - if (type != null) { - return type; - } - return evaluate(expression.astRight()); - } - - if (resolved instanceof ResolvedVariable) { - ResolvedVariable variable = (ResolvedVariable) resolved; - return variable.getType(); - } - - return null; - } - - /** - * Returns the inferred type of the given node - */ - @Nullable - public PsiType evaluate(@Nullable PsiElement node) { - if (node == null) { - return null; - } - - PsiElement resolved = null; - if (node instanceof PsiReference) { - resolved = ((PsiReference) node).resolve(); - } - if (resolved instanceof PsiMethod) { - PsiMethod method = (PsiMethod) resolved; - if (method.isConstructor()) { - PsiClass containingClass = method.getContainingClass(); - if (containingClass != null && mContext != null) { - return mContext.getEvaluator().getClassType(containingClass); - } - } else { - return method.getReturnType(); - } - } - - if (resolved instanceof PsiField) { - PsiField field = (PsiField) resolved; - if (field.getInitializer() != null) { - PsiType type = evaluate(field.getInitializer()); - if (type != null) { - return type; - } - } - return field.getType(); - } else if (resolved instanceof PsiLocalVariable) { - PsiLocalVariable variable = (PsiLocalVariable) resolved; - PsiStatement statement = PsiTreeUtil.getParentOfType(node, PsiStatement.class, - false); - if (statement != null) { - PsiStatement prev = PsiTreeUtil.getPrevSiblingOfType(statement, - PsiStatement.class); - String targetName = variable.getName(); - if (targetName == null) { - return null; - } - while (prev != null) { - if (prev instanceof PsiDeclarationStatement) { - for (PsiElement element : ((PsiDeclarationStatement)prev).getDeclaredElements()) { - if (variable.equals(element)) { - return evaluate(variable.getInitializer()); - } - } - } else if (prev instanceof PsiExpressionStatement) { - PsiExpression expression = ((PsiExpressionStatement)prev).getExpression(); - if (expression instanceof PsiAssignmentExpression) { - PsiAssignmentExpression assign = (PsiAssignmentExpression) expression; - PsiExpression lhs = assign.getLExpression(); - if (lhs instanceof PsiReferenceExpression) { - PsiReferenceExpression reference = (PsiReferenceExpression) lhs; - if (targetName.equals(reference.getReferenceName()) && - reference.getQualifier() == null) { - return evaluate(assign.getRExpression()); - } - } - } - } - prev = PsiTreeUtil.getPrevSiblingOfType(prev, - PsiStatement.class); - } - } - - return variable.getType(); - } else if (node instanceof PsiExpression) { - PsiExpression expression = (PsiExpression) node; - return expression.getType(); - } - - return null; - } - - @Nullable - public static PsiType evaluate(@NonNull JavaContext context, @Nullable UElement node) { - if (node == null) { - return null; - } - - UElement resolved = node; - if (resolved instanceof UReferenceExpression) { - resolved = UastUtils.tryResolveUDeclaration(resolved, context.getUastContext()); - } - - if (resolved instanceof UMethod) { - return ((UMethod) resolved).getPsi().getReturnType(); - } else if (resolved instanceof UVariable) { - UVariable variable = (UVariable) resolved; - UElement lastAssignment = UastLintUtils.findLastAssignment(variable, node, context); - if (lastAssignment != null) { - return evaluate(context, lastAssignment); - } - return variable.getType(); - } else if (resolved instanceof UCallExpression) { - if (UastExpressionUtils.isMethodCall(resolved)) { - PsiMethod resolvedMethod = ((UCallExpression) resolved).resolve(); - return resolvedMethod != null ? resolvedMethod.getReturnType() : null; - } else { - return ((UCallExpression) resolved).getExpressionType(); - } - } else if (resolved instanceof UExpression) { - return ((UExpression) resolved).getExpressionType(); - } - - return null; - } - - /** - * Evaluates the given node and returns the likely type of the instance. Convenience - * wrapper which creates a new {@linkplain TypeEvaluator}, evaluates the node and returns - * the result. - * - * @param context the context to use to resolve field references, if any - * @param node the node to compute the type for - * @return the corresponding type descriptor, if found - * @deprecated Use {@link #evaluate(JavaContext, PsiElement)} instead - */ - @Deprecated - @Nullable - public static TypeDescriptor evaluate(@NonNull JavaContext context, @NonNull Node node) { - return new TypeEvaluator(context).evaluate(node); - } - - /** - * Evaluates the given node and returns the likely type of the instance. Convenience - * wrapper which creates a new {@linkplain TypeEvaluator}, evaluates the node and returns - * the result. - * - * @param context the context to use to resolve field references, if any - * @param node the node to compute the type for - * @return the corresponding type descriptor, if found - */ - @Nullable - public static PsiType evaluate(@NonNull JavaContext context, @NonNull PsiElement node) { - return new TypeEvaluator(context).evaluate(node); - } -} diff --git a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/XmlContext.java.173 b/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/XmlContext.java.173 deleted file mode 100644 index ee16bab79bb..00000000000 --- a/plugins/lint/lint-api/src/com/android/tools/klint/detector/api/XmlContext.java.173 +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (C) 2011 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.detector.api; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.resources.ResourceFolderType; -import com.android.tools.klint.client.api.LintDriver; -import com.android.tools.klint.client.api.XmlParser; -import com.google.common.annotations.Beta; - -import org.w3c.dom.Attr; -import org.w3c.dom.Document; -import org.w3c.dom.Node; - -import java.io.File; - -/** - * A {@link Context} used when checking XML files. - *

- * NOTE: This is not a public or final API; if you rely on this be prepared - * to adjust your code for the next tools release. - */ -@Beta -public class XmlContext extends ResourceContext { - static final String SUPPRESS_COMMENT_PREFIX = " - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AddTargetApiQuickFix.kt.173 b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AddTargetApiQuickFix.kt.173 deleted file mode 100644 index 5cf05ff6c70..00000000000 --- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AddTargetApiQuickFix.kt.173 +++ /dev/null @@ -1,93 +0,0 @@ -/* - * 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.android.inspections.klint - -import com.android.SdkConstants -import com.android.tools.klint.checks.ApiDetector.REQUIRES_API_ANNOTATION -import com.intellij.codeInsight.FileModificationService -import com.intellij.psi.PsiElement -import com.intellij.psi.util.PsiTreeUtil -import org.jetbrains.android.util.AndroidBundle -import org.jetbrains.kotlin.android.hasBackingField -import org.jetbrains.kotlin.idea.util.addAnnotation -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.psi.* - - -class AddTargetApiQuickFix( - val api: Int, - val useRequiresApi: Boolean -) : AndroidLintQuickFix { - - private companion object { - val FQNAME_TARGET_API = FqName(SdkConstants.FQCN_TARGET_API) - val FQNAME_REQUIRES_API = FqName(REQUIRES_API_ANNOTATION) - } - - override fun isApplicable(startElement: PsiElement, endElement: PsiElement, contextType: AndroidQuickfixContexts.ContextType): Boolean = - getAnnotationContainer(startElement, useRequiresApi) != null - - override fun getName(): String = getAnnotationValue(false).let { - if (useRequiresApi) { - // Not Available in Android plugin 2.0 - // AndroidBundle.message("android.lint.fix.add.requires.api", it) - "Add @RequiresApi($it) Annotation" - } else { - AndroidBundle.message("android.lint.fix.add.target.api", it) - } - } - - override fun apply(startElement: PsiElement, endElement: PsiElement, context: AndroidQuickfixContexts.Context) { - val annotationContainer = getAnnotationContainer(startElement, useRequiresApi) ?: return - if (!FileModificationService.getInstance().preparePsiElementForWrite(annotationContainer)) { - return - } - - if (annotationContainer is KtModifierListOwner) { - annotationContainer.addAnnotation( - if (useRequiresApi) FQNAME_REQUIRES_API else FQNAME_TARGET_API, - getAnnotationValue(true), - whiteSpaceText = if (annotationContainer.isNewLineNeededForAnnotation()) "\n" else " ") - } - } - - private fun KtElement.isNewLineNeededForAnnotation() = !(this is KtParameter || this is KtTypeParameter || this is KtPropertyAccessor) - - private fun getAnnotationValue(fullyQualified: Boolean) = getVersionField(api, fullyQualified) - - private fun getAnnotationContainer(element: PsiElement, useRequiresApi: Boolean): PsiElement? { - return PsiTreeUtil.findFirstParent(element) { - if (useRequiresApi) - it.isRequiresApiAnnotationValidTarget() - else - it.isTargetApiAnnotationValidTarget() - } - } - - private fun PsiElement.isRequiresApiAnnotationValidTarget(): Boolean { - return this is KtClassOrObject || - (this is KtFunction && this !is KtFunctionLiteral) || - (this is KtProperty && !isLocal && hasBackingField()) || - this is KtPropertyAccessor - } - - private fun PsiElement.isTargetApiAnnotationValidTarget(): Boolean { - return this is KtClassOrObject || - (this is KtFunction && this !is KtFunctionLiteral) || - this is KtPropertyAccessor - } -} \ No newline at end of file diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AddTargetVersionCheckQuickFix.kt.173 b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AddTargetVersionCheckQuickFix.kt.173 deleted file mode 100644 index ec8ebadf849..00000000000 --- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AddTargetVersionCheckQuickFix.kt.173 +++ /dev/null @@ -1,92 +0,0 @@ -/* - * 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.android.inspections.klint - -import com.intellij.codeInsight.FileModificationService -import com.intellij.psi.PsiDocumentManager -import com.intellij.psi.PsiElement -import com.intellij.psi.util.PsiTreeUtil -import org.jetbrains.kotlin.idea.caches.resolve.analyze -import org.jetbrains.kotlin.idea.codeInsight.surroundWith.statement.KotlinIfSurrounder -import org.jetbrains.kotlin.idea.core.ShortenReferences -import org.jetbrains.kotlin.idea.inspections.findExistingEditor -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode - - -class AddTargetVersionCheckQuickFix(val api: Int) : AndroidLintQuickFix { - - override fun apply(startElement: PsiElement, endElement: PsiElement, context: AndroidQuickfixContexts.Context) { - val targetExpression = getTargetExpression(startElement) - val project = targetExpression?.project ?: return - val editor = targetExpression.findExistingEditor() ?: return - - val file = targetExpression.containingFile - val documentManager = PsiDocumentManager.getInstance(project) - val document = documentManager.getDocument(file) ?: return - - if (!FileModificationService.getInstance().prepareFileForWrite(file)) { - return - } - - val surrounder = getSurrounder(targetExpression, "\"VERSION.SDK_INT < ${getVersionField(api, false)}\"") - val conditionRange = surrounder.surroundElements(project, editor, arrayOf(targetExpression)) ?: return - val conditionText = "android.os.Build.VERSION.SDK_INT >= ${getVersionField(api, true)}" - document.replaceString(conditionRange.startOffset, conditionRange.endOffset, conditionText) - documentManager.commitDocument(document) - - ShortenReferences.DEFAULT.process(documentManager.getPsiFile(document) as KtFile, - conditionRange.startOffset, - conditionRange.startOffset + conditionText.length) - } - - override fun isApplicable(startElement: PsiElement, endElement: PsiElement, contextType: AndroidQuickfixContexts.ContextType): Boolean = - getTargetExpression(startElement) != null - - override fun getName(): String = "Surround with if (VERSION.SDK_INT >= VERSION_CODES.${getVersionField(api, false)}) { ... }" - - private fun getTargetExpression(element: PsiElement): KtElement? { - var current = PsiTreeUtil.getParentOfType(element, KtExpression::class.java) - while (current != null) { - if (current.parent is KtBlockExpression || - current.parent is KtContainerNode || - current.parent is KtWhenEntry || - current.parent is KtFunction || - current.parent is KtPropertyAccessor || - current.parent is KtProperty || - current.parent is KtReturnExpression || - current.parent is KtDestructuringDeclaration) { - break - } - current = PsiTreeUtil.getParentOfType(current, KtExpression::class.java, true) - } - - return current - } - - private fun getSurrounder(element: KtElement, todoText: String?): KotlinIfSurrounder { - val used = element.analyze(BodyResolveMode.PARTIAL_WITH_CFA)[BindingContext.USED_AS_EXPRESSION, element] ?: false - return if (used) { - object : KotlinIfSurrounder() { - override fun getCodeTemplate(): String = "if (a) { \n} else {\nTODO(${todoText ?: ""})\n}" - } - } else { - KotlinIfSurrounder() - } - } -} \ No newline at end of file diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidInspectionExtensionsFactory.java.173 b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidInspectionExtensionsFactory.java.173 deleted file mode 100644 index f7da14066d3..00000000000 --- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidInspectionExtensionsFactory.java.173 +++ /dev/null @@ -1,46 +0,0 @@ -package org.jetbrains.android.inspections.klint; - -import com.intellij.codeInspection.HTMLComposer; -import com.intellij.codeInspection.lang.GlobalInspectionContextExtension; -import com.intellij.codeInspection.lang.HTMLComposerExtension; -import com.intellij.codeInspection.lang.InspectionExtensionsFactory; -import com.intellij.codeInspection.lang.RefManagerExtension; -import com.intellij.codeInspection.reference.RefManager; -import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiElement; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class AndroidInspectionExtensionsFactory extends InspectionExtensionsFactory { - @Override - public GlobalInspectionContextExtension createGlobalInspectionContextExtension() { - return new AndroidLintGlobalInspectionContext(); - } - - @Nullable - @Override - public RefManagerExtension createRefManagerExtension(RefManager refManager) { - return null; - } - - @Nullable - @Override - public HTMLComposerExtension createHTMLComposerExtension(HTMLComposer composer) { - return null; - } - - @Override - public boolean isToCheckMember(@NotNull PsiElement element, @NotNull String id) { - return true; - } - - @Override - public String getSuppressedInspectionIdsIn(@NotNull PsiElement element) { - return null; - } - - @Override - public boolean isProjectConfiguredToRunInspections(@NotNull Project project, boolean online) { - return true; - } -} diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintExternalAnnotator.java.173 b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintExternalAnnotator.java.173 deleted file mode 100644 index d1ebf96fb18..00000000000 --- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintExternalAnnotator.java.173 +++ /dev/null @@ -1,443 +0,0 @@ -package org.jetbrains.android.inspections.klint; - -import com.android.tools.klint.client.api.IssueRegistry; -import com.android.tools.klint.client.api.LintDriver; -import com.android.tools.klint.client.api.LintRequest; -import com.android.tools.klint.detector.api.Issue; -import com.android.tools.klint.detector.api.Scope; -import com.intellij.codeHighlighting.HighlightDisplayLevel; -import com.intellij.codeInsight.FileModificationService; -import com.intellij.codeInsight.daemon.DaemonBundle; -import com.intellij.codeInsight.daemon.HighlightDisplayKey; -import com.intellij.codeInsight.intention.HighPriorityAction; -import com.intellij.codeInsight.intention.IntentionAction; -import com.intellij.codeInspection.*; -import com.intellij.codeInspection.ex.CustomEditInspectionToolsSettingsAction; -import com.intellij.codeInspection.ex.DisableInspectionToolAction; -import com.intellij.lang.annotation.Annotation; -import com.intellij.lang.annotation.AnnotationHolder; -import com.intellij.lang.annotation.ExternalAnnotator; -import com.intellij.lang.annotation.HighlightSeverity; -import com.intellij.openapi.actionSystem.IdeActions; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.fileTypes.FileType; -import com.intellij.openapi.fileTypes.FileTypes; -import com.intellij.openapi.fileTypes.StdFileTypes; -import com.intellij.openapi.keymap.Keymap; -import com.intellij.openapi.keymap.KeymapManager; -import com.intellij.openapi.keymap.KeymapUtil; -import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleManager; -import com.intellij.openapi.module.ModuleUtilCore; -import com.intellij.openapi.progress.util.ProgressIndicatorUtils; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.roots.ModuleRootManager; -import com.intellij.openapi.roots.ProjectRootModificationTracker; -import com.intellij.openapi.util.*; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.profile.codeInspection.InspectionProjectProfileManager; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.psi.util.CachedValueProvider; -import com.intellij.psi.util.CachedValuesManager; -import com.intellij.util.IncorrectOperationException; -import com.intellij.util.ui.UIUtil; -import com.intellij.xml.util.XmlStringUtil; -import org.jetbrains.android.compiler.AndroidCompileUtil; -import org.jetbrains.android.facet.AndroidFacet; -import org.jetbrains.android.util.AndroidBundle; -import org.jetbrains.android.util.AndroidCommonUtils; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.kotlin.idea.KotlinFileType; - -import javax.swing.*; -import java.util.ArrayList; -import java.util.Collections; -import java.util.EnumSet; -import java.util.List; - -import static com.android.SdkConstants.*; -import static com.android.tools.klint.detector.api.TextFormat.HTML; -import static com.android.tools.klint.detector.api.TextFormat.RAW; - -public class AndroidLintExternalAnnotator extends ExternalAnnotator { - static final boolean INCLUDE_IDEA_SUPPRESS_ACTIONS = false; - static final boolean IS_UNIT_TEST_MODE = ApplicationManager.getApplication().isUnitTestMode(); - - @Nullable - @Override - public State collectInformation(@NotNull PsiFile file, @NotNull Editor editor, boolean hasErrors) { - return collectInformation(file); - } - - @Override - public State collectInformation(@NotNull PsiFile file) { - final Module module = ModuleUtilCore.findModuleForPsiElement(file); - if (module == null) { - return null; - } - - final AndroidFacet facet = AndroidFacet.getInstance(module); - if (facet == null && !isDependencyOfAnyAndroidModule(module)) { - return null; - } - - final VirtualFile vFile = file.getVirtualFile(); - if (vFile == null) { - return null; - } - - final FileType fileType = file.getFileType(); - - if (fileType == FileTypes.PLAIN_TEXT) { - if (!AndroidCommonUtils.PROGUARD_CFG_FILE_NAME.equals(file.getName()) && - !AndroidCompileUtil.OLD_PROGUARD_CFG_FILE_NAME.equals(file.getName())) { - return null; - } - } - else if (fileType != KotlinFileType.INSTANCE && fileType != StdFileTypes.PROPERTIES) { - return null; - } - - final List issues = getIssuesFromInspections(file.getProject(), file); - if (issues.size() == 0) { - return null; - } - return new State(module, vFile, file.getText(), issues); - } - - private static boolean isDependencyOfAnyAndroidModule(@NotNull Module module) { - return CachedValuesManager - .getManager(module.getProject()) - .getCachedValue(module, - () -> new CachedValueProvider.Result<>( - computeIsDependencyOfAnyAndroidModule(module), - ProjectRootModificationTracker.getInstance(module.getProject()))); - } - - private static boolean computeIsDependencyOfAnyAndroidModule(@NotNull Module dependency) { - Module[] allModules = ModuleManager.getInstance(dependency.getProject()).getModules(); - for (Module module : allModules) { - if (AndroidFacet.getInstance(module) == null) { - continue; - } - - if (ModuleRootManager.getInstance(module).isDependsOn(dependency)) { - return true; - } - } - - return false; - } - - @Override - public State doAnnotate(final State state) { - final IntellijLintClient client = IntellijLintClient.forEditor(state); - try { - final LintDriver lint = new LintDriver(new IntellijLintIssueRegistry(), client); - - EnumSet scope; - VirtualFile mainFile = state.getMainFile(); - final FileType fileType = mainFile.getFileType(); - String name = mainFile.getName(); - if (fileType == StdFileTypes.XML) { - if (name.equals(ANDROID_MANIFEST_XML)) { - scope = Scope.MANIFEST_SCOPE; - } else { - scope = Scope.RESOURCE_FILE_SCOPE; - } - } else if (fileType == KotlinFileType.INSTANCE) { - scope = Scope.JAVA_FILE_SCOPE; - } else if (name.equals(OLD_PROGUARD_FILE) || name.equals(FN_PROJECT_PROGUARD_FILE)) { - scope = EnumSet.of(Scope.PROGUARD_FILE); - } else if (fileType == StdFileTypes.PROPERTIES) { - scope = Scope.PROPERTY_SCOPE; - } else { - // #collectionInformation above should have prevented this - assert false; - return state; - } - - Project project = state.getModule().getProject(); - if (project.isDisposed()) { - return state; - } - - List files = Collections.singletonList(mainFile); - final LintRequest request = new IntellijLintRequest( - client, project, files, Collections.singletonList(state.getModule()), true /* incremental */); - request.setScope(scope); - - if (!IS_UNIT_TEST_MODE) { - ProgressIndicatorUtils.runInReadActionWithWriteActionPriority(new Runnable() { - @Override - public void run() { - lint.analyze(request); - } - }); - } - else { - lint.analyze(request); - } - } - finally { - Disposer.dispose(client); - } - return state; - } - - @NotNull - static List getIssuesFromInspections(@NotNull Project project, @Nullable PsiElement context) { - final List result = new ArrayList(); - final IssueRegistry fullRegistry = new IntellijLintIssueRegistry(); - - for (Issue issue : fullRegistry.getIssues()) { - final String inspectionShortName = AndroidLintInspectionBase.getInspectionShortNameByIssue(project, issue); - if (inspectionShortName == null) { - continue; - } - - final HighlightDisplayKey key = HighlightDisplayKey.find(inspectionShortName); - if (key == null) { - continue; - } - - final InspectionProfile profile = InspectionProjectProfileManager.getInstance(project).getInspectionProfile(); - final boolean enabled = context != null ? profile.isToolEnabled(key, context) : profile.isToolEnabled(key); - - if (!enabled) { - continue; - } else if (!issue.isEnabledByDefault()) { - // If an issue is marked as not enabled by default, lint won't run it, even if it's in the set - // of issues provided by an issue registry. Since in the IDE we're enforcing the enabled-state via - // inspection profiles, mark the issue as enabled to allow users to turn on a lint check directly - // via the inspections UI. - issue.setEnabledByDefault(true); - } - result.add(issue); - } - return result; - } - - @Override - public void apply(@NotNull PsiFile file, State state, @NotNull AnnotationHolder holder) { - if (state.isDirty()) { - return; - } - final Project project = file.getProject(); - - for (ProblemData problemData : state.getProblems()) { - final Issue issue = problemData.getIssue(); - final String message = problemData.getMessage(); - final TextRange range = problemData.getTextRange(); - - if (range.getStartOffset() == range.getEndOffset()) { - continue; - } - - final Pair pair = - AndroidLintUtil.getHighlighLevelAndInspection(project, issue, file); - if (pair == null) { - continue; - } - final AndroidLintInspectionBase inspection = pair.getFirst(); - HighlightDisplayLevel displayLevel = pair.getSecond(); - - if (inspection != null) { - final HighlightDisplayKey key = HighlightDisplayKey.find(inspection.getShortName()); - - if (key != null) { - final PsiElement startElement = file.findElementAt(range.getStartOffset()); - final PsiElement endElement = file.findElementAt(range.getEndOffset() - 1); - - if (startElement != null && endElement != null && !inspection.isSuppressedFor(startElement)) { - if (problemData.getConfiguredSeverity() != null) { - HighlightDisplayLevel configuredLevel = - AndroidLintInspectionBase.toHighlightDisplayLevel(problemData.getConfiguredSeverity()); - if (configuredLevel != null) { - displayLevel = configuredLevel; - } - } - final Annotation annotation = createAnnotation(holder, message, range, displayLevel, issue); - - for (AndroidLintQuickFix fix : inspection.getQuickFixes(startElement, endElement, message)) { - if (fix.isApplicable(startElement, endElement, AndroidQuickfixContexts.EditorContext.TYPE)) { - annotation.registerFix(new MyFixingIntention(fix, startElement, endElement)); - } - } - - for (IntentionAction intention : inspection.getIntentions(startElement, endElement)) { - annotation.registerFix(intention); - } - - String id = key.getID(); - if (IntellijLintIssueRegistry.CUSTOM_ERROR == issue - || IntellijLintIssueRegistry.CUSTOM_WARNING == issue) { - Issue original = IntellijLintClient.findCustomIssue(message); - if (original != null) { - id = original.getId(); - } - } - - annotation.registerFix(new SuppressLintIntentionAction(id, startElement)); - annotation.registerFix(new MyDisableInspectionFix(key)); - annotation.registerFix(new MyEditInspectionToolsSettingsAction(key, inspection)); - - if (INCLUDE_IDEA_SUPPRESS_ACTIONS) { - final SuppressQuickFix[] suppressActions = inspection.getBatchSuppressActions(startElement); - for (SuppressQuickFix action : suppressActions) { - if (action.isAvailable(project, startElement)) { - ProblemHighlightType type = annotation.getHighlightType(); - annotation.registerFix(action, null, key, InspectionManager.getInstance(project).createProblemDescriptor( - startElement, endElement, message, type, true, LocalQuickFix.EMPTY_ARRAY)); - } - } - } - } - } - } - } - } - - @SuppressWarnings("deprecation") - @NotNull - private Annotation createAnnotation(@NotNull AnnotationHolder holder, - @NotNull String message, - @NotNull TextRange range, - @NotNull HighlightDisplayLevel displayLevel, - @NotNull Issue issue) { - // Convert from inspection severity to annotation severity - HighlightSeverity severity; - if (displayLevel == HighlightDisplayLevel.ERROR) { - severity = HighlightSeverity.ERROR; - } else if (displayLevel == HighlightDisplayLevel.WARNING) { - severity = HighlightSeverity.WARNING; - } else if (displayLevel == HighlightDisplayLevel.WEAK_WARNING) { - severity = HighlightSeverity.WEAK_WARNING; - } else if (displayLevel == HighlightDisplayLevel.INFO) { - severity = HighlightSeverity.INFO; - } else { - severity = HighlightSeverity.WARNING; - } - - String link = " " + DaemonBundle.message("inspection.extended.description") - +" " + getShowMoreShortCut(); - String tooltip = XmlStringUtil.wrapInHtml(RAW.convertTo(message, HTML) + link); - - return holder.createAnnotation(severity, range, message, tooltip); - } - - // Based on similar code in the LocalInspectionsPass constructor - private String myShortcutText; - private String getShowMoreShortCut() { - if (myShortcutText == null) { - final KeymapManager keymapManager = KeymapManager.getInstance(); - if (keymapManager != null) { - final Keymap keymap = keymapManager.getActiveKeymap(); - myShortcutText = - keymap == null ? "" : "(" + KeymapUtil.getShortcutsText(keymap.getShortcuts(IdeActions.ACTION_SHOW_ERROR_DESCRIPTION)) + ")"; - } - else { - myShortcutText = ""; - } - } - - return myShortcutText; - } - - private static class MyDisableInspectionFix implements IntentionAction, Iconable { - private final DisableInspectionToolAction myDisableInspectionToolAction; - - private MyDisableInspectionFix(@NotNull HighlightDisplayKey key) { - myDisableInspectionToolAction = new DisableInspectionToolAction(key); - } - - @NotNull - @Override - public String getText() { - return "Disable inspection"; - } - - @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, Editor editor, PsiFile file) throws IncorrectOperationException { - myDisableInspectionToolAction.invoke(project, editor, file); - } - - @Override - public boolean startInWriteAction() { - return myDisableInspectionToolAction.startInWriteAction(); - } - - @Override - public Icon getIcon(@IconFlags int flags) { - return myDisableInspectionToolAction.getIcon(flags); - } - } - - public static class MyFixingIntention implements IntentionAction, HighPriorityAction { - private final AndroidLintQuickFix myQuickFix; - private final PsiElement myStartElement; - private final PsiElement myEndElement; - - public MyFixingIntention(@NotNull AndroidLintQuickFix quickFix, @NotNull PsiElement startElement, @NotNull PsiElement endElement) { - myQuickFix = quickFix; - myStartElement = startElement; - myEndElement = endElement; - } - - @NotNull - @Override - public String getText() { - return myQuickFix.getName(); - } - - @NotNull - @Override - public String getFamilyName() { - return AndroidBundle.message("android.lint.quickfixes.family"); - } - - @Override - public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - return true; - } - - @Override - public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { - FileModificationService.getInstance().prepareFileForWrite(file); - myQuickFix.apply(myStartElement, myEndElement, AndroidQuickfixContexts.EditorContext.getInstance(editor)); - } - - @Override - public boolean startInWriteAction() { - return true; - } - } - - private static class MyEditInspectionToolsSettingsAction extends CustomEditInspectionToolsSettingsAction { - private MyEditInspectionToolsSettingsAction(@NotNull HighlightDisplayKey key, @NotNull final AndroidLintInspectionBase inspection) { - super(key, new Computable() { - @Override - public String compute() { - return "Edit '" + inspection.getDisplayName() + "' inspection settings"; - } - }); - } - } -} diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintGlobalInspectionContext.java.173 b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintGlobalInspectionContext.java.173 deleted file mode 100644 index e213e543b00..00000000000 --- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintGlobalInspectionContext.java.173 +++ /dev/null @@ -1,216 +0,0 @@ -package org.jetbrains.android.inspections.klint; - -import com.android.tools.klint.client.api.LintDriver; -import com.android.tools.klint.client.api.LintRequest; -import com.android.tools.klint.detector.api.Issue; -import com.android.tools.klint.detector.api.Scope; -import com.google.common.collect.Lists; -import com.intellij.analysis.AnalysisScope; -import com.intellij.codeInspection.GlobalInspectionContext; -import com.intellij.codeInspection.ex.InspectionToolWrapper; -import com.intellij.codeInspection.ex.Tools; -import com.intellij.codeInspection.lang.GlobalInspectionContextExtension; -import com.intellij.facet.ProjectFacetManager; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleManager; -import com.intellij.openapi.module.ModuleUtilCore; -import com.intellij.openapi.module.impl.scopes.ModuleWithDependenciesScope; -import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.openapi.progress.ProgressManager; -import com.intellij.openapi.progress.util.ProgressWrapper; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Computable; -import com.intellij.openapi.util.Key; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiElementVisitor; -import com.intellij.psi.PsiFile; -import com.intellij.psi.search.LocalSearchScope; -import com.intellij.psi.search.SearchScope; -import com.intellij.util.containers.HashMap; -import org.jetbrains.android.facet.AndroidFacet; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.io.File; -import java.util.*; - -class AndroidLintGlobalInspectionContext implements GlobalInspectionContextExtension { - static final Key ID = Key.create("AndroidLintGlobalInspectionContext"); - private Map>> myResults; - - @NotNull - @Override - public Key getID() { - return ID; - } - - @Override - public void performPreRunActivities(@NotNull List globalTools, @NotNull List localTools, @NotNull final GlobalInspectionContext context) { - final Project project = context.getProject(); - - if (!ProjectFacetManager.getInstance(project).hasFacets(AndroidFacet.ID)) { - return; - } - - final List issues = AndroidLintExternalAnnotator.getIssuesFromInspections(project, null); - if (issues.size() == 0) { - return; - } - - final Map>> problemMap = new HashMap>>(); - final AnalysisScope scope = context.getRefManager().getScope(); - if (scope == null) { - return; - } - - final IntellijLintClient client = IntellijLintClient.forBatch(project, problemMap, scope, issues); - final LintDriver lint = new LintDriver(new IntellijLintIssueRegistry(), client); - - final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator(); - if (indicator != null) { - ProgressWrapper.unwrap(indicator).setText("Running Android Lint"); - } - - EnumSet lintScope; - //noinspection ConstantConditions - if (!IntellijLintProject.SUPPORT_CLASS_FILES) { - lintScope = EnumSet.copyOf(Scope.ALL); - // Can't run class file based checks - lintScope.remove(Scope.CLASS_FILE); - lintScope.remove(Scope.ALL_CLASS_FILES); - lintScope.remove(Scope.JAVA_LIBRARIES); - } else { - lintScope = Scope.ALL; - } - - List files = null; - final List modules = Lists.newArrayList(); - - int scopeType = scope.getScopeType(); - switch (scopeType) { - case AnalysisScope.MODULE: { - SearchScope searchScope = scope.toSearchScope(); - if (searchScope instanceof ModuleWithDependenciesScope) { - ModuleWithDependenciesScope s = (ModuleWithDependenciesScope)searchScope; - if (!s.isSearchInLibraries()) { - modules.add(s.getModule()); - } - } - break; - } - case AnalysisScope.FILE: - case AnalysisScope.VIRTUAL_FILES: - case AnalysisScope.UNCOMMITTED_FILES: { - files = Lists.newArrayList(); - SearchScope searchScope = ApplicationManager - .getApplication() - .runReadAction((Computable) scope::toSearchScope); - if (searchScope instanceof LocalSearchScope) { - final LocalSearchScope localSearchScope = (LocalSearchScope)searchScope; - final PsiElement[] elements = localSearchScope.getScope(); - final List finalFiles = files; - - ApplicationManager.getApplication().runReadAction(new Runnable() { - @Override - public void run() { - for (PsiElement element : elements) { - if (element instanceof PsiFile) { // should be the case since scope type is FILE - Module module = ModuleUtilCore.findModuleForPsiElement(element); - if (module != null && !modules.contains(module)) { - modules.add(module); - } - VirtualFile virtualFile = ((PsiFile)element).getVirtualFile(); - if (virtualFile != null) { - finalFiles.add(virtualFile); - } - } - } - } - }); - } else { - final List finalList = files; - scope.accept(new PsiElementVisitor() { - @Override - public void visitFile(PsiFile file) { - VirtualFile virtualFile = file.getVirtualFile(); - if (virtualFile != null) { - finalList.add(virtualFile); - } - } - }); - } - if (files.isEmpty()) { - files = null; - } else { - // Lint will compute it lazily based on actual files in the request - lintScope = null; - } - break; - } - case AnalysisScope.PROJECT: { - modules.addAll(Arrays.asList(ModuleManager.getInstance(project).getModules())); - break; - } - case AnalysisScope.CUSTOM: - case AnalysisScope.MODULES: - case AnalysisScope.DIRECTORY: { - // Handled by the getNarrowedComplementaryScope case below - break; - } - - case AnalysisScope.INVALID: - break; - default: - Logger.getInstance(this.getClass()).warn("Unexpected inspection scope " + scope + ", " + scopeType); - } - - if (modules.isEmpty()) { - for (Module module : ModuleManager.getInstance(project).getModules()) { - if (scope.containsModule(module)) { - modules.add(module); - } - } - - if (modules.isEmpty() && files != null) { - for (VirtualFile file : files) { - Module module = ModuleUtilCore.findModuleForFile(file, project); - if (module != null && !modules.contains(module)) { - modules.add(module); - } - } - } - - if (modules.isEmpty()) { - AnalysisScope narrowed = scope.getNarrowedComplementaryScope(project); - for (Module module : ModuleManager.getInstance(project).getModules()) { - if (narrowed.containsModule(module)) { - modules.add(module); - } - } - } - } - - LintRequest request = new IntellijLintRequest(client, project, files, modules, false); - request.setScope(lintScope); - - lint.analyze(request); - - myResults = problemMap; - } - - @Nullable - public Map>> getResults() { - return myResults; - } - - @Override - public void performPostRunActivities(@NotNull List inspections, @NotNull final GlobalInspectionContext context) { - } - - @Override - public void cleanup() { - } -} diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintInspectionBase.java.173 b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintInspectionBase.java.173 deleted file mode 100644 index 8a7424a7435..00000000000 --- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintInspectionBase.java.173 +++ /dev/null @@ -1,492 +0,0 @@ -package org.jetbrains.android.inspections.klint; - -import com.android.annotations.concurrency.GuardedBy; -import com.android.tools.klint.detector.api.*; -import com.intellij.analysis.AnalysisScope; -import com.intellij.codeHighlighting.HighlightDisplayLevel; -import com.intellij.codeInsight.daemon.HighlightDisplayKey; -import com.intellij.codeInsight.intention.IntentionAction; -import com.intellij.codeInspection.*; -import com.intellij.codeInspection.ex.InspectionToolWrapper; -import com.intellij.lang.annotation.ProblemGroup; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.colors.TextAttributesKey; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.TextRange; -import com.intellij.openapi.vfs.LocalFileSystem; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.profile.codeInspection.InspectionProjectProfileManager; -import com.intellij.psi.*; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.util.ArrayUtil; -import com.intellij.util.containers.HashMap; -import org.jetbrains.android.util.AndroidBundle; -import org.jetbrains.annotations.Nls; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.annotations.TestOnly; - -import java.io.File; -import java.util.*; - -import static com.android.tools.klint.detector.api.TextFormat.*; -import static com.intellij.xml.CommonXmlStrings.HTML_END; -import static com.intellij.xml.CommonXmlStrings.HTML_START; - -public abstract class AndroidLintInspectionBase extends GlobalInspectionTool { - private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.inspections.lint.AndroidLintInspectionBase"); - - private static final Object ISSUE_MAP_LOCK = new Object(); - - @GuardedBy("ISSUE_MAP_LOCK") - private static volatile Map ourIssue2InspectionShortName; - - protected final Issue myIssue; - private final String[] myGroupPath; - private final String myDisplayName; - - protected AndroidLintInspectionBase(@NotNull String displayName, @NotNull Issue issue) { - myIssue = issue; - - final Category category = issue.getCategory(); - - myGroupPath = ArrayUtil.mergeArrays(new String[]{AndroidBundle.message("android.inspections.group.name"), - AndroidBundle.message("android.lint.inspections.subgroup.name")}, computeAllNames(category)); - myDisplayName = displayName; - } - - @NotNull - public AndroidLintQuickFix[] getQuickFixes(@NotNull PsiElement startElement, @NotNull PsiElement endElement, @NotNull String message) { - return getQuickFixes(message); - } - - @NotNull - public AndroidLintQuickFix[] getQuickFixes(@NotNull String message) { - return AndroidLintQuickFix.EMPTY_ARRAY; - } - - @NotNull - public IntentionAction[] getIntentions(@NotNull PsiElement startElement, @NotNull PsiElement endElement) { - return IntentionAction.EMPTY_ARRAY; - } - - @Override - public boolean isGraphNeeded() { - return false; - } - - @NotNull - private LocalQuickFix[] getLocalQuickFixes(@NotNull PsiElement startElement, @NotNull PsiElement endElement, @NotNull String message) { - final AndroidLintQuickFix[] fixes = getQuickFixes(startElement, endElement, message); - final LocalQuickFix[] result = new LocalQuickFix[fixes.length]; - - for (int i = 0; i < fixes.length; i++) { - if (fixes[i].isApplicable(startElement, endElement, AndroidQuickfixContexts.BatchContext.TYPE)) { - result[i] = new MyLocalQuickFix(fixes[i]); - } - } - return result; - } - - @Override - public void runInspection(@NotNull AnalysisScope scope, - @NotNull final InspectionManager manager, - @NotNull final GlobalInspectionContext globalContext, - @NotNull final ProblemDescriptionsProcessor problemDescriptionsProcessor) { - final AndroidLintGlobalInspectionContext androidLintContext = globalContext.getExtension(AndroidLintGlobalInspectionContext.ID); - if (androidLintContext == null) { - return; - } - - final Map>> problemMap = androidLintContext.getResults(); - if (problemMap == null) { - return; - } - - final Map> file2ProblemList = problemMap.get(myIssue); - if (file2ProblemList == null) { - return; - } - - for (final Map.Entry> entry : file2ProblemList.entrySet()) { - final File file = entry.getKey(); - final VirtualFile vFile = LocalFileSystem.getInstance().findFileByIoFile(file); - - if (vFile == null) { - continue; - } - ApplicationManager.getApplication().runReadAction(new Runnable() { - @Override - public void run() { - final PsiManager psiManager = PsiManager.getInstance(globalContext.getProject()); - final PsiFile psiFile = psiManager.findFile(vFile); - - if (psiFile != null) { - final ProblemDescriptor[] descriptors = computeProblemDescriptors(psiFile, manager, entry.getValue()); - - if (descriptors.length > 0) { - problemDescriptionsProcessor.addProblemElement(globalContext.getRefManager().getReference(psiFile), descriptors); - } - } else if (vFile.isDirectory()) { - final PsiDirectory psiDirectory = psiManager.findDirectory(vFile); - - if (psiDirectory != null) { - final ProblemDescriptor[] descriptors = computeProblemDescriptors(psiDirectory, manager, entry.getValue()); - - if (descriptors.length > 0) { - problemDescriptionsProcessor.addProblemElement(globalContext.getRefManager().getReference(psiDirectory), descriptors); - } - } - } - } - }); - } - } - - @NotNull - private ProblemDescriptor[] computeProblemDescriptors(@NotNull PsiElement psiFile, - @NotNull InspectionManager manager, - @NotNull List problems) { - final List result = new ArrayList(); - - for (ProblemData problemData : problems) { - final String originalMessage = problemData.getMessage(); - - // We need to have explicit and tags around the text; inspection infrastructure - // such as the {@link com.intellij.codeInspection.ex.DescriptorComposer} will call - // {@link com.intellij.xml.util.XmlStringUtil.isWrappedInHtml}. See issue 177283 for uses. - // Note that we also need to use HTML with unicode characters here, since the HTML display - // in the inspections view does not appear to support numeric code character entities. - String formattedMessage = HTML_START + RAW.convertTo(originalMessage, HTML_WITH_UNICODE) + HTML_END; - - // The inspections UI does not correctly handle - - final TextRange range = problemData.getTextRange(); - - if (range.getStartOffset() == range.getEndOffset()) { - - if (psiFile instanceof PsiBinaryFile || psiFile instanceof PsiDirectory) { - final LocalQuickFix[] fixes = getLocalQuickFixes(psiFile, psiFile, originalMessage); - result.add(new NonTextFileProblemDescriptor((PsiFileSystemItem)psiFile, formattedMessage, fixes)); - } else if (!isSuppressedFor(psiFile)) { - result.add(manager.createProblemDescriptor(psiFile, formattedMessage, false, - getLocalQuickFixes(psiFile, psiFile, originalMessage), - ProblemHighlightType.GENERIC_ERROR_OR_WARNING)); - } - } - else { - final PsiElement startElement = psiFile.findElementAt(range.getStartOffset()); - final PsiElement endElement = psiFile.findElementAt(range.getEndOffset() - 1); - - if (startElement != null && endElement != null && !isSuppressedFor(startElement)) { - result.add(manager.createProblemDescriptor(startElement, endElement, formattedMessage, - ProblemHighlightType.GENERIC_ERROR_OR_WARNING, false, - getLocalQuickFixes(startElement, endElement, originalMessage))); - } - } - } - return result.toArray(new ProblemDescriptor[result.size()]); - } - - @NotNull - @Override - public SuppressQuickFix[] getBatchSuppressActions(@Nullable PsiElement element) { - if (AndroidLintExternalAnnotator.INCLUDE_IDEA_SUPPRESS_ACTIONS) { - final List result = new ArrayList(); - 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()]); - } else { - return new SuppressQuickFix[0]; - } - } - - @TestOnly - public static void invalidateInspectionShortName2IssueMap() { - ourIssue2InspectionShortName = null; - } - - public static String getInspectionShortNameByIssue(@NotNull Project project, @NotNull Issue issue) { - synchronized (ISSUE_MAP_LOCK) { - if (ourIssue2InspectionShortName == null) { - ourIssue2InspectionShortName = new HashMap(); - - final InspectionProfile profile = InspectionProjectProfileManager.getInstance(project).getInspectionProfile(); - - for (InspectionToolWrapper e : profile.getInspectionTools(null)) { - final String shortName = e.getShortName(); - - if (shortName.startsWith("AndroidKLint")) { - final InspectionProfileEntry entry = e.getTool(); - if (entry instanceof AndroidLintInspectionBase) { - final Issue s = ((AndroidLintInspectionBase)entry).getIssue(); - ourIssue2InspectionShortName.put(s, shortName); - } - } - } - } - return ourIssue2InspectionShortName.get(issue); - } - } - - @NotNull - private static String[] computeAllNames(@NotNull Category category) { - final List result = new ArrayList(); - - Category c = category; - - while (c != null) { - final String name = c.getName(); - - if (name == null) { - return ArrayUtil.EMPTY_STRING_ARRAY; - } - result.add(name); - c = c.getParent(); - } - return ArrayUtil.reverseArray(ArrayUtil.toStringArray(result)); - } - - @Nls - @NotNull - @Override - public String getGroupDisplayName() { - return AndroidBundle.message("android.lint.inspections.group.name"); - } - - @NotNull - @Override - public String[] getGroupPath() { - return myGroupPath; - } - - @Nls - @NotNull - @Override - public String getDisplayName() { - return myDisplayName; - } - - @SuppressWarnings("deprecation") - @Override - public String getStaticDescription() { - StringBuilder sb = new StringBuilder(1000); - sb.append(""); - sb.append(myIssue.getBriefDescription(HTML)); - sb.append("

"); - sb.append(myIssue.getExplanation(HTML)); - List urls = myIssue.getMoreInfo(); - if (!urls.isEmpty()) { - boolean separated = false; - for (String url : urls) { - if (!myIssue.getExplanation(RAW).contains(url)) { - if (!separated) { - sb.append("

"); - separated = true; - } else { - sb.append("
"); - } - sb.append(""); - sb.append(url); - sb.append(""); - } - } - } - sb.append(""); - - return sb.toString(); - } - - @Override - public boolean isEnabledByDefault() { - return myIssue.isEnabledByDefault(); - } - - @NotNull - @Override - public String getShortName() { - return InspectionProfileEntry.getShortName(getClass().getSimpleName()); - } - - @NotNull - @Override - public HighlightDisplayLevel getDefaultLevel() { - final Severity defaultSeverity = myIssue.getDefaultSeverity(); - if (defaultSeverity == null) { - return HighlightDisplayLevel.WARNING; - } - final HighlightDisplayLevel displayLevel = toHighlightDisplayLevel(defaultSeverity); - return displayLevel != null ? displayLevel : HighlightDisplayLevel.WARNING; - } - - @Nullable - static HighlightDisplayLevel toHighlightDisplayLevel(@NotNull Severity severity) { - switch (severity) { - case ERROR: - return HighlightDisplayLevel.ERROR; - case FATAL: - return HighlightDisplayLevel.ERROR; - case WARNING: - return HighlightDisplayLevel.WARNING; - case INFORMATIONAL: - return HighlightDisplayLevel.WEAK_WARNING; - case IGNORE: - return null; - default: - LOG.error("Unknown severity " + severity); - return null; - } - } - - /** Returns true if the given analysis scope is adequate for single-file analysis */ - private static boolean isSingleFileScope(EnumSet scopes) { - if (scopes.size() != 1) { - return false; - } - final Scope scope = scopes.iterator().next(); - return scope == Scope.JAVA_FILE || scope == Scope.RESOURCE_FILE || scope == Scope.MANIFEST - || scope == Scope.PROGUARD_FILE || scope == Scope.OTHER; - } - - @Override - public boolean worksInBatchModeOnly() { - Implementation implementation = myIssue.getImplementation(); - if (isSingleFileScope(implementation.getScope())) { - return false; - } - for (EnumSet scopes : implementation.getAnalysisScopes()) { - if (isSingleFileScope(scopes)) { - return false; - } - } - - return true; - } - - @NotNull - public Issue getIssue() { - return myIssue; - } - - static class MyLocalQuickFix implements LocalQuickFix { - private final AndroidLintQuickFix myLintQuickFix; - - MyLocalQuickFix(@NotNull AndroidLintQuickFix lintQuickFix) { - myLintQuickFix = lintQuickFix; - } - - @NotNull - @Override - public String getName() { - return myLintQuickFix.getName(); - } - - @NotNull - @Override - public String getFamilyName() { - return AndroidBundle.message("android.lint.quickfixes.family"); - } - - @Override - public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { - myLintQuickFix.apply(descriptor.getStartElement(), descriptor.getEndElement(), AndroidQuickfixContexts.BatchContext.getInstance()); - } - } - - /** - * A {@link com.intellij.codeInspection.ProblemDescriptor} for image and directory files. This is - * necessary because the {@link InspectionManager}'s createProblemDescriptor methods - * 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. - *

- * This custom descriptor allows the batch lint analysis to correctly handle lint errors - * associated with image files (such as the various {@link com.android.tools.lint.checks.IconDetector} - * warnings), as well as directory errors (such as incorrect locale folders), - * and clicking on them will navigate to the correct icon. - */ - private static class NonTextFileProblemDescriptor implements ProblemDescriptor { - private final PsiFileSystemItem myFile; - private final String myMessage; - private final LocalQuickFix[] myFixes; - private ProblemGroup myGroup; - - public NonTextFileProblemDescriptor(@NotNull PsiFileSystemItem file, @NotNull String message, @NotNull LocalQuickFix[] fixes) { - myFile = file; - myMessage = message; - myFixes = fixes; - } - - @Override - public PsiElement getPsiElement() { - return myFile; - } - - @Override - public PsiElement getStartElement() { - return myFile; - } - - @Override - public PsiElement getEndElement() { - return myFile; - } - - @Override - public TextRange getTextRangeInElement() { - return new TextRange(0, 0); - } - - @Override - public int getLineNumber() { - return 0; - } - - @NotNull - @Override - public ProblemHighlightType getHighlightType() { - return ProblemHighlightType.GENERIC_ERROR_OR_WARNING; - } - - @Override - public boolean isAfterEndOfLine() { - return false; - } - - @Override - public void setTextAttributes(TextAttributesKey key) { - } - - @Nullable - @Override - public ProblemGroup getProblemGroup() { - return myGroup; - } - - @Override - public void setProblemGroup(@Nullable ProblemGroup problemGroup) { - myGroup = problemGroup; - } - - @Override - public boolean showTooltip() { - return false; - } - - @NotNull - @Override - public String getDescriptionTemplate() { - return myMessage; - } - - @Nullable - @Override - public QuickFix[] getFixes() { - return myFixes; - } - } -} diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintInspectionToolProvider.java.173 b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintInspectionToolProvider.java.173 deleted file mode 100644 index a74bd026391..00000000000 --- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintInspectionToolProvider.java.173 +++ /dev/null @@ -1,757 +0,0 @@ -package org.jetbrains.android.inspections.klint; - -import com.android.tools.klint.checks.*; -import com.android.tools.klint.detector.api.Issue; -import com.android.tools.lint.detector.api.TextFormat; -import com.intellij.openapi.project.Project; -import com.intellij.psi.JavaPsiFacade; -import com.intellij.psi.PsiElement; -import com.intellij.psi.search.GlobalSearchScope; -import org.jetbrains.android.util.AndroidBundle; -import org.jetbrains.annotations.NotNull; - -import java.util.regex.Pattern; - -import static com.android.tools.klint.checks.ApiDetector.REQUIRES_API_ANNOTATION; -import static com.android.tools.klint.checks.FragmentDetector.ISSUE; - -/** - * Registrations for all the various Lint rules as local IDE inspections, along with quickfixes for many of them - */ -public class AndroidLintInspectionToolProvider { - public static class AndroidKLintCustomErrorInspection extends AndroidLintInspectionBase { - public AndroidKLintCustomErrorInspection() { - super("Error from Custom Lint Check", IntellijLintIssueRegistry.CUSTOM_ERROR); - } - } - - public static class AndroidKLintCustomWarningInspection extends AndroidLintInspectionBase { - public AndroidKLintCustomWarningInspection() { - super("Warning from Custom Lint Check", IntellijLintIssueRegistry.CUSTOM_WARNING); - } - - } - - public static class AndroidKLintInconsistentLayoutInspection extends AndroidLintInspectionBase { - public AndroidKLintInconsistentLayoutInspection() { - super(AndroidBundle.message("android.lint.inspections.inconsistent.layout"), LayoutConsistencyDetector.INCONSISTENT_IDS); - } - } - - public static class AndroidKLintIconExpectedSizeInspection extends AndroidLintInspectionBase { - public AndroidKLintIconExpectedSizeInspection() { - super(AndroidBundle.message("android.lint.inspections.icon.expected.size"), IconDetector.ICON_EXPECTED_SIZE); - } - } - - public static class AndroidKLintIconDipSizeInspection extends AndroidLintInspectionBase { - public AndroidKLintIconDipSizeInspection() { - super(AndroidBundle.message("android.lint.inspections.icon.dip.size"), IconDetector.ICON_DIP_SIZE); - } - } - - public static class AndroidKLintIconLocationInspection extends AndroidLintInspectionBase { - public AndroidKLintIconLocationInspection() { - super(AndroidBundle.message("android.lint.inspections.icon.location"), IconDetector.ICON_LOCATION); - } - } - - public static class AndroidKLintIconDensitiesInspection extends AndroidLintInspectionBase { - public AndroidKLintIconDensitiesInspection() { - super(AndroidBundle.message("android.lint.inspections.icon.densities"), IconDetector.ICON_DENSITIES); - } - } - - public static class AndroidKLintIconMissingDensityFolderInspection extends AndroidLintInspectionBase { - public AndroidKLintIconMissingDensityFolderInspection() { - super(AndroidBundle.message("android.lint.inspections.icon.missing.density.folder"), IconDetector.ICON_MISSING_FOLDER); - } - } - - public static class AndroidKLintIconMixedNinePatchInspection extends AndroidLintInspectionBase { - public AndroidKLintIconMixedNinePatchInspection() { - super(AndroidBundle.message("android.lint.inspections.icon.mixed.nine.patch"), IconDetector.ICON_MIX_9PNG); - } - } - - public static class AndroidKLintFloatMathInspection extends AndroidLintInspectionBase { - public AndroidKLintFloatMathInspection() { - super("Using FloatMath instead of Math", MathDetector.ISSUE); - } - } - - public static class AndroidKLintGetInstanceInspection extends AndroidLintInspectionBase { - public AndroidKLintGetInstanceInspection() { - super(AndroidBundle.message("android.lint.inspections.get.instance"), CipherGetInstanceDetector.ISSUE); - } - } - - public static class AndroidKLintGifUsageInspection extends AndroidLintInspectionBase { - public AndroidKLintGifUsageInspection() { - super(AndroidBundle.message("android.lint.inspections.gif.usage"), IconDetector.GIF_USAGE); - } - } - - public static class AndroidKLintIconDuplicatesInspection extends AndroidLintInspectionBase { - public AndroidKLintIconDuplicatesInspection() { - super(AndroidBundle.message("android.lint.inspections.icon.duplicates"), IconDetector.DUPLICATES_NAMES); - } - } - - public static class AndroidKLintIconDuplicatesConfigInspection extends AndroidLintInspectionBase { - public AndroidKLintIconDuplicatesConfigInspection() { - super(AndroidBundle.message("android.lint.inspections.icon.duplicates.config"), IconDetector.DUPLICATES_CONFIGURATIONS); - } - } - - public static class AndroidKLintIconNoDpiInspection extends AndroidLintInspectionBase { - public AndroidKLintIconNoDpiInspection() { - super(AndroidBundle.message("android.lint.inspections.icon.no.dpi"), IconDetector.ICON_NODPI); - } - } - - public static class AndroidKLintOverdrawInspection extends AndroidLintInspectionBase { - public AndroidKLintOverdrawInspection() { - super(AndroidBundle.message("android.lint.inspections.overdraw"), OverdrawDetector.ISSUE); - } - } - - public static class AndroidKLintMissingSuperCallInspection extends AndroidLintInspectionBase { - public AndroidKLintMissingSuperCallInspection() { - super(AndroidBundle.message("android.lint.inspections.missing.super.call"), CallSuperDetector.ISSUE); - } - } - - public static class AndroidKLintUnprotectedSMSBroadcastReceiverInspection extends AndroidLintInspectionBase { - public AndroidKLintUnprotectedSMSBroadcastReceiverInspection() { - super(AndroidBundle.message("android.lint.inspections.unprotected.smsbroadcast.receiver"), UnsafeBroadcastReceiverDetector.BROADCAST_SMS); - } - - } - - public static class AndroidKLintUnusedAttributeInspection extends AndroidLintInspectionBase { - public AndroidKLintUnusedAttributeInspection() { - super(AndroidBundle.message("android.lint.inspections.unused.attribute"), ApiDetector.UNUSED); - } - - } - - public static class AndroidKLintAlwaysShowActionInspection extends AndroidLintInspectionBase { - public AndroidKLintAlwaysShowActionInspection() { - super(AndroidBundle.message("android.lint.inspections.always.show.action"), AlwaysShowActionDetector.ISSUE); - } - - } - - public static class AndroidKLintAppCompatMethodInspection extends AndroidLintInspectionBase { - public AndroidKLintAppCompatMethodInspection() { - super(AndroidBundle.message("android.lint.inspections.app.compat.method"), AppCompatCallDetector.ISSUE); - } - - } - - public static class AndroidKLintGoogleAppIndexingUrlErrorInspection extends AndroidLintInspectionBase { - public AndroidKLintGoogleAppIndexingUrlErrorInspection() { - super("URL not supported by app for Google App Indexing", AppIndexingApiDetector.ISSUE_URL_ERROR); - } - - } - - public static class AndroidKLintGoogleAppIndexingWarningInspection extends AndroidLintInspectionBase { - public AndroidKLintGoogleAppIndexingWarningInspection() { - super("Missing support for Google App Indexing", AppIndexingApiDetector.ISSUE_APP_INDEXING); - } - - } - - public static class AndroidKLintGoogleAppIndexingApiWarningInspection extends AndroidLintInspectionBase { - public AndroidKLintGoogleAppIndexingApiWarningInspection() { - super("Missing support for Google App Indexing Api", AppIndexingApiDetector.ISSUE_APP_INDEXING_API); - } - - } - - public static class AndroidKLintStringFormatCountInspection extends AndroidLintInspectionBase { - public AndroidKLintStringFormatCountInspection() { - super(AndroidBundle.message("android.lint.inspections.string.format.count"), StringFormatDetector.ARG_COUNT); - } - } - - public static class AndroidKLintStringFormatMatchesInspection extends AndroidLintInspectionBase { - public AndroidKLintStringFormatMatchesInspection() { - super(AndroidBundle.message("android.lint.inspections.string.format.matches"), StringFormatDetector.ARG_TYPES); - } - } - - public static class AndroidKLintStringFormatInvalidInspection extends AndroidLintInspectionBase { - public AndroidKLintStringFormatInvalidInspection() { - super(AndroidBundle.message("android.lint.inspections.string.format.invalid"), StringFormatDetector.INVALID); - } - } - - public static class AndroidKLintWrongViewCastInspection extends AndroidLintInspectionBase { - public AndroidKLintWrongViewCastInspection() { - super(AndroidBundle.message("android.lint.inspections.wrong.view.cast"), ViewTypeDetector.ISSUE); - } - } - - public static class AndroidKLintCommitTransactionInspection extends AndroidLintInspectionBase { - public AndroidKLintCommitTransactionInspection() { - super(AndroidBundle.message("android.lint.inspections.commit.transaction"), CleanupDetector.COMMIT_FRAGMENT); - } - } - - public static class AndroidKLintBadHostnameVerifierInspection extends AndroidLintInspectionBase { - public AndroidKLintBadHostnameVerifierInspection() { - super("Insecure HostnameVerifier", BadHostnameVerifierDetector.ISSUE); - } - } - - public static class AndroidKLintBatteryLifeInspection extends AndroidLintInspectionBase { - public AndroidKLintBatteryLifeInspection() { - super("Battery Life Issues", BatteryDetector.ISSUE); - } - } - - public static class AndroidKLintHandlerLeakInspection extends AndroidLintInspectionBase { - public AndroidKLintHandlerLeakInspection() { - super(AndroidBundle.message("android.lint.inspections.handler.leak"), HandlerDetector.ISSUE); - } - } - - public static class AndroidKLintDrawAllocationInspection extends AndroidLintInspectionBase { - public AndroidKLintDrawAllocationInspection() { - super(AndroidBundle.message("android.lint.inspections.draw.allocation"), JavaPerformanceDetector.PAINT_ALLOC); - } - } - - public static class AndroidKLintUseSparseArraysInspection extends AndroidLintInspectionBase { - public AndroidKLintUseSparseArraysInspection() { - super(AndroidBundle.message("android.lint.inspections.use.sparse.arrays"), JavaPerformanceDetector.USE_SPARSE_ARRAY); - } - } - - public static class AndroidKLintUseValueOfInspection extends AndroidLintInspectionBase { - public AndroidKLintUseValueOfInspection() { - super(AndroidBundle.message("android.lint.inspections.use.value.of"), JavaPerformanceDetector.USE_VALUE_OF); - } - - } - - public static class AndroidKLintPackageManagerGetSignaturesInspection extends AndroidLintInspectionBase { - public AndroidKLintPackageManagerGetSignaturesInspection() { - super(AndroidBundle.message("android.lint.inspections.package.manager.get.signatures"), GetSignaturesDetector.ISSUE); - } - } - - public static class AndroidKLintParcelClassLoaderInspection extends AndroidLintInspectionBase { - public AndroidKLintParcelClassLoaderInspection() { - super("Default Parcel Class Loader", ReadParcelableDetector.ISSUE); - } - - } - - public static class AndroidKLintParcelCreatorInspection extends AndroidLintInspectionBase { - public AndroidKLintParcelCreatorInspection() { - super(AndroidBundle.message("android.lint.inspections.parcel.creator"), ParcelDetector.ISSUE); - } - @NotNull - @Override - public AndroidLintQuickFix[] getQuickFixes(@NotNull String message) { - return new AndroidLintQuickFix[]{ new ParcelableQuickFix() }; - } - } - - public static class AndroidKLintPluralsCandidateInspection extends AndroidLintInspectionBase { - public AndroidKLintPluralsCandidateInspection() { - super(AndroidBundle.message("android.lint.inspections.plurals.candidate"), StringFormatDetector.POTENTIAL_PLURAL); - } - } - - public static class AndroidKLintPrivateResourceInspection extends AndroidLintInspectionBase { - public AndroidKLintPrivateResourceInspection() { - super(AndroidBundle.message("android.lint.inspections.private.resource"), PrivateResourceDetector.ISSUE); - } - } - - public static class AndroidKLintSdCardPathInspection extends AndroidLintInspectionBase { - public AndroidKLintSdCardPathInspection() { - super(AndroidBundle.message("android.lint.inspections.sd.card.path"), SdCardDetector.ISSUE); - } - } - - public static class AndroidKLintSuspiciousImportInspection extends AndroidLintInspectionBase { - public AndroidKLintSuspiciousImportInspection() { - super(AndroidBundle.message("android.lint.inspections.suspicious.import"), WrongImportDetector.ISSUE); - } - } - - public static class AndroidKLintSQLiteStringInspection extends AndroidLintInspectionBase { - public AndroidKLintSQLiteStringInspection() { - super(AndroidBundle.message("android.lint.inspections.sqlite.string"), SQLiteDetector.ISSUE); - } - } - - public static class AndroidKLintDefaultLocaleInspection extends AndroidLintInspectionBase { - public AndroidKLintDefaultLocaleInspection() { - super("Implied default locale in case conversion", LocaleDetector.STRING_LOCALE); - } - } - - public static class AndroidKLintValidFragmentInspection extends AndroidLintInspectionBase { - public AndroidKLintValidFragmentInspection() { - super(AndroidBundle.message("android.lint.inspections.valid.fragment"), ISSUE); - } - } - - public static class AndroidKLintViewConstructorInspection extends AndroidLintInspectionBase { - public AndroidKLintViewConstructorInspection() { - super(AndroidBundle.message("android.lint.inspections.view.constructor"), ViewConstructorDetector.ISSUE); - } - } - - public static class AndroidKLintViewHolderInspection extends AndroidLintInspectionBase { - public AndroidKLintViewHolderInspection() { - super(AndroidBundle.message("android.lint.inspections.view.holder"), ViewHolderDetector.ISSUE); - } - } - - public static class AndroidKLintViewTagInspection extends AndroidLintInspectionBase { - public AndroidKLintViewTagInspection() { - super("Tagged object leaks", ViewTagDetector.ISSUE); - } - } - - public static class AndroidKLintMergeRootFrameInspection extends AndroidLintInspectionBase { - public AndroidKLintMergeRootFrameInspection() { - super(AndroidBundle.message("android.lint.inspections.merge.root.frame"), MergeRootFrameLayoutDetector.ISSUE); - } - } - - public static class AndroidKLintExportedServiceInspection extends AndroidLintInspectionBase { - public AndroidKLintExportedServiceInspection() { - super(AndroidBundle.message("android.lint.inspections.exported.service"), SecurityDetector.EXPORTED_SERVICE); - } - - } - - public static class AndroidKLintGrantAllUrisInspection extends AndroidLintInspectionBase { - public AndroidKLintGrantAllUrisInspection() { - super(AndroidBundle.message("android.lint.inspections.grant.all.uris"), SecurityDetector.OPEN_PROVIDER); - } - } - - public static class AndroidKLintWorldWriteableFilesInspection extends AndroidLintInspectionBase { - public AndroidKLintWorldWriteableFilesInspection() { - super(AndroidBundle.message("android.lint.inspections.world.writeable.files"), SecurityDetector.WORLD_WRITEABLE); - } - } - - public static class AndroidKLintSSLCertificateSocketFactoryCreateSocketInspection extends AndroidLintInspectionBase { - public AndroidKLintSSLCertificateSocketFactoryCreateSocketInspection() { - super(AndroidBundle.message("android.lint.inspections.sslcertificate.socket.factory.create.socket"), SslCertificateSocketFactoryDetector.CREATE_SOCKET); - } - } - - public static class AndroidKLintSSLCertificateSocketFactoryGetInsecureInspection extends AndroidLintInspectionBase { - public AndroidKLintSSLCertificateSocketFactoryGetInsecureInspection() { - super(AndroidBundle.message("android.lint.inspections.sslcertificate.socket.factory.get.insecure"), SslCertificateSocketFactoryDetector.GET_INSECURE); - } - } - - public static class AndroidKLintSwitchIntDefInspection extends AndroidLintInspectionBase { - public AndroidKLintSwitchIntDefInspection() { - super("Missing @IntDef in Switch", AnnotationDetector.SWITCH_TYPE_DEF); - } - - } - - public static class AndroidKLintTrustAllX509TrustManagerInspection extends AndroidLintInspectionBase { - public AndroidKLintTrustAllX509TrustManagerInspection() { - super("Insecure TLS/SSL trust manager", TrustAllX509TrustManagerDetector.ISSUE); - } - } - - private abstract static class AndroidKLintTypographyInspectionBase extends AndroidLintInspectionBase { - public AndroidKLintTypographyInspectionBase(String displayName, Issue issue) { - super(displayName, issue); - } - - } - - public static class AndroidKLintNewApiInspection extends AndroidLintInspectionBase { - public AndroidKLintNewApiInspection() { - super(AndroidBundle.message("android.lint.inspections.new.api"), ApiDetector.UNSUPPORTED); - } - - @NotNull - @Override - public AndroidLintQuickFix[] getQuickFixes(@NotNull PsiElement startElement, @NotNull PsiElement endElement, @NotNull String message) { - return getApiQuickFixes(startElement, endElement, message); - } - - @NotNull - public static AndroidLintQuickFix[] getApiQuickFixes(@NotNull PsiElement startElement, @NotNull PsiElement endElement, @NotNull String message) { - int api = ApiDetector.getRequiredVersion(TextFormat.RAW.toText(message)); - if (api == -1) { - return AndroidLintQuickFix.EMPTY_ARRAY; - } - - Project project = startElement.getProject(); - if (JavaPsiFacade.getInstance(project).findClass(REQUIRES_API_ANNOTATION, GlobalSearchScope.allScope(project)) != null) { - return new AndroidLintQuickFix[] { - new AddTargetApiQuickFix(api, true), - new AddTargetApiQuickFix(api, false), - new AddTargetVersionCheckQuickFix(api) - }; - } - - return new AndroidLintQuickFix[] { - new AddTargetApiQuickFix(api, false), - new AddTargetVersionCheckQuickFix(api) - }; - } - } - - public static class AndroidKLintInlinedApiInspection extends AndroidLintInspectionBase { - public AndroidKLintInlinedApiInspection() { - super(AndroidBundle.message("android.lint.inspections.inlined.api"), ApiDetector.INLINED); - } - - @NotNull - @Override - public AndroidLintQuickFix[] getQuickFixes(@NotNull PsiElement startElement, @NotNull PsiElement endElement, @NotNull String message) { - return AndroidKLintNewApiInspection.getApiQuickFixes(startElement, endElement, message); - } - } - - public static class AndroidKLintOverrideInspection extends AndroidLintInspectionBase { - public AndroidKLintOverrideInspection() { - super(AndroidBundle.message("android.lint.inspections.override"), ApiDetector.OVERRIDE); - } - - } - - private static final Pattern QUOTED_PARAMETER = Pattern.compile("`.+:(.+)=\"(.*)\"`"); - - public static class AndroidKLintRtlCompatInspection extends AndroidLintInspectionBase { - public AndroidKLintRtlCompatInspection() { - super(AndroidBundle.message("android.lint.inspections.rtl.compat"), RtlDetector.COMPAT); - } - - - } - public static class AndroidKLintRtlEnabledInspection extends AndroidLintInspectionBase { - public AndroidKLintRtlEnabledInspection() { - super(AndroidBundle.message("android.lint.inspections.rtl.enabled"), RtlDetector.ENABLED); - } - } - public static class AndroidKLintRtlHardcodedInspection extends AndroidLintInspectionBase { - public AndroidKLintRtlHardcodedInspection() { - super(AndroidBundle.message("android.lint.inspections.rtl.hardcoded"), RtlDetector.USE_START); - } - } - public static class AndroidKLintRtlSymmetryInspection extends AndroidLintInspectionBase { - public AndroidKLintRtlSymmetryInspection() { - super(AndroidBundle.message("android.lint.inspections.rtl.symmetry"), RtlDetector.SYMMETRY); - } - } - - // Missing the following issues, because they require classfile analysis: - // FloatMath, FieldGetter, Override, OnClick, ViewTag, DefaultLocale, SimpleDateFormat, - // Registered, MissingRegistered, Instantiatable, HandlerLeak, ValidFragment, SecureRandom, - // ViewConstructor, Wakelock, Recycle, CommitTransaction, WrongCall, DalvikOverride - - // I think DefaultLocale is already handled by a regular IDEA code check. - - public static class AndroidKLintAddJavascriptInterfaceInspection extends AndroidLintInspectionBase { - public AndroidKLintAddJavascriptInterfaceInspection() { - super(AndroidBundle.message("android.lint.inspections.add.javascript.interface"), AddJavascriptInterfaceDetector.ISSUE); - } - } - - public static class AndroidKLintAllowAllHostnameVerifierInspection extends AndroidLintInspectionBase { - public AndroidKLintAllowAllHostnameVerifierInspection() { - super("Insecure HostnameVerifier", AllowAllHostnameVerifierDetector.ISSUE); - } - } - - public static class AndroidKLintCommitPrefEditsInspection extends AndroidLintInspectionBase { - public AndroidKLintCommitPrefEditsInspection() { - super(AndroidBundle.message("android.lint.inspections.commit.pref.edits"), CleanupDetector.SHARED_PREF); - } - - } - - public static class AndroidKLintCustomViewStyleableInspection extends AndroidLintInspectionBase { - public AndroidKLintCustomViewStyleableInspection() { - super(AndroidBundle.message("android.lint.inspections.custom.view.styleable"), CustomViewDetector.ISSUE); - } - } - - public static class AndroidKLintCutPasteIdInspection extends AndroidLintInspectionBase { - public AndroidKLintCutPasteIdInspection() { - super(AndroidBundle.message("android.lint.inspections.cut.paste.id"), CutPasteDetector.ISSUE); - } - } - public static class AndroidKLintEasterEggInspection extends AndroidLintInspectionBase { - public AndroidKLintEasterEggInspection() { - super(AndroidBundle.message("android.lint.inspections.easter.egg"), CommentDetector.EASTER_EGG); - } - } - public static class AndroidKLintExportedContentProviderInspection extends AndroidLintInspectionBase { - public AndroidKLintExportedContentProviderInspection() { - super(AndroidBundle.message("android.lint.inspections.exported.content.provider"), SecurityDetector.EXPORTED_PROVIDER); - } - - } - public static class AndroidKLintExportedPreferenceActivityInspection extends AndroidLintInspectionBase { - public AndroidKLintExportedPreferenceActivityInspection() { - super(AndroidBundle.message("android.lint.inspections.exported.preference.activity"), PreferenceActivityDetector.ISSUE); - } - } - public static class AndroidKLintExportedReceiverInspection extends AndroidLintInspectionBase { - public AndroidKLintExportedReceiverInspection() { - super(AndroidBundle.message("android.lint.inspections.exported.receiver"), SecurityDetector.EXPORTED_RECEIVER); - } - - } - public static class AndroidKLintIconColorsInspection extends AndroidLintInspectionBase { - public AndroidKLintIconColorsInspection() { - super(AndroidBundle.message("android.lint.inspections.icon.colors"), IconDetector.ICON_COLORS); - } - } - public static class AndroidKLintIconExtensionInspection extends AndroidLintInspectionBase { - public AndroidKLintIconExtensionInspection() { - super(AndroidBundle.message("android.lint.inspections.icon.extension"), IconDetector.ICON_EXTENSION); - } - } - public static class AndroidKLintIconLauncherShapeInspection extends AndroidLintInspectionBase { - public AndroidKLintIconLauncherShapeInspection() { - super(AndroidBundle.message("android.lint.inspections.icon.launcher.shape"), IconDetector.ICON_LAUNCHER_SHAPE); - } - } - public static class AndroidKLintIconXmlAndPngInspection extends AndroidLintInspectionBase { - public AndroidKLintIconXmlAndPngInspection() { - super(AndroidBundle.message("android.lint.inspections.icon.xml.and.png"), IconDetector.ICON_XML_AND_PNG); - } - } - - public static class AndroidKLintAuthLeakInspection extends AndroidLintInspectionBase { - public AndroidKLintAuthLeakInspection() { - super("Code could contain an credential leak", StringAuthLeakDetector.AUTH_LEAK); - } - } - - public static class AndroidKLintInflateParamsInspection extends AndroidLintInspectionBase { - public AndroidKLintInflateParamsInspection() { - super(AndroidBundle.message("android.lint.inspections.inflate.params"), LayoutInflationDetector.ISSUE); - } - } - - public static class AndroidKLintInvalidUsesTagAttributeInspection extends AndroidLintInspectionBase { - public AndroidKLintInvalidUsesTagAttributeInspection() { - super(AndroidBundle.message("android.lint.inspections.invalid.uses.tag.attribute"), AndroidAutoDetector.INVALID_USES_TAG_ISSUE); - } - } - - public static class AndroidKLintJavascriptInterfaceInspection extends AndroidLintInspectionBase { - public AndroidKLintJavascriptInterfaceInspection() { - super(AndroidBundle.message("android.lint.inspections.javascript.interface"), JavaScriptInterfaceDetector.ISSUE); - } - } - - public static class AndroidKLintLocalSuppressInspection extends AndroidLintInspectionBase { - public AndroidKLintLocalSuppressInspection() { - super(AndroidBundle.message("android.lint.inspections.local.suppress"), AnnotationDetector.INSIDE_METHOD); - } - } - - public static class AndroidKLintLogConditionalInspection extends AndroidLintInspectionBase { - public AndroidKLintLogConditionalInspection() { - super(AndroidBundle.message("android.lint.inspections.log.conditional"), LogDetector.CONDITIONAL); - } - } - - public static class AndroidKLintLogTagMismatchInspection extends AndroidLintInspectionBase { - public AndroidKLintLogTagMismatchInspection() { - super(AndroidBundle.message("android.lint.inspections.log.tag.mismatch"), LogDetector.WRONG_TAG); - } - } - - public static class AndroidKLintLongLogTagInspection extends AndroidLintInspectionBase { - public AndroidKLintLongLogTagInspection() { - super(AndroidBundle.message("android.lint.inspections.long.log.tag"), LogDetector.LONG_TAG); - } - } - - public static class AndroidKLintMissingIntentFilterForMediaSearchInspection extends AndroidLintInspectionBase { - public AndroidKLintMissingIntentFilterForMediaSearchInspection() { - super(AndroidBundle.message("android.lint.inspections.missing.intent.filter.for.media.search"), - AndroidAutoDetector.MISSING_INTENT_FILTER_FOR_MEDIA_SEARCH); - } - } - - public static class AndroidKLintMissingMediaBrowserServiceIntentFilterInspection extends AndroidLintInspectionBase { - public AndroidKLintMissingMediaBrowserServiceIntentFilterInspection() { - super(AndroidBundle.message("android.lint.inspections.missing.media.browser.service.intent.filter"), - AndroidAutoDetector.MISSING_MEDIA_BROWSER_SERVICE_ACTION_ISSUE); - } - } - - public static class AndroidKLintMissingOnPlayFromSearchInspection extends AndroidLintInspectionBase { - public AndroidKLintMissingOnPlayFromSearchInspection() { - super(AndroidBundle.message("android.lint.inspections.missing.on.play.from.search"), - AndroidAutoDetector.MISSING_ON_PLAY_FROM_SEARCH); - } - } - - public static class AndroidKLintOverrideAbstractInspection extends AndroidLintInspectionBase { - public AndroidKLintOverrideAbstractInspection() { - super(AndroidBundle.message("android.lint.inspections.override.abstract"), OverrideConcreteDetector.ISSUE); - } - } - - public static class AndroidKLintRecycleInspection extends AndroidLintInspectionBase { - public AndroidKLintRecycleInspection() { - super(AndroidBundle.message("android.lint.inspections.recycle"), CleanupDetector.RECYCLE_RESOURCE); - } - } - - public static class AndroidKLintRecyclerViewInspection extends AndroidLintInspectionBase { - public AndroidKLintRecyclerViewInspection() { - super("RecyclerView Problems", RecyclerViewDetector.FIXED_POSITION); - } - } - - 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); - } - } - public static class AndroidKLintSecureRandomInspection extends AndroidLintInspectionBase { - public AndroidKLintSecureRandomInspection() { - super("Using a fixed seed with SecureRandom", SecureRandomDetector.ISSUE); - } - } - - public static class AndroidKLintServiceCastInspection extends AndroidLintInspectionBase { - public AndroidKLintServiceCastInspection() { - super(AndroidBundle.message("android.lint.inspections.service.cast"), ServiceCastDetector.ISSUE); - } - } - public static class AndroidKLintSetJavaScriptEnabledInspection extends AndroidLintInspectionBase { - public AndroidKLintSetJavaScriptEnabledInspection() { - super(AndroidBundle.message("android.lint.inspections.set.java.script.enabled"), SetJavaScriptEnabledDetector.ISSUE); - } - } - - public static class AndroidKLintSetTextI18nInspection extends AndroidLintInspectionBase { - public AndroidKLintSetTextI18nInspection() { - super(AndroidBundle.message("android.lint.inspections.set.text.i18n"), SetTextDetector.SET_TEXT_I18N); - } - } - - public static class AndroidKLintSetWorldReadableInspection extends AndroidLintInspectionBase { - public AndroidKLintSetWorldReadableInspection() { - super(AndroidBundle.message("android.lint.inspections.set.world.readable"), SecurityDetector.SET_READABLE); - } - } - - public static class AndroidKLintSetWorldWritableInspection extends AndroidLintInspectionBase { - public AndroidKLintSetWorldWritableInspection() { - super(AndroidBundle.message("android.lint.inspections.set.world.writable"), SecurityDetector.SET_WRITABLE); - } - } - - public static class AndroidKLintShiftFlagsInspection extends AndroidLintInspectionBase { - public AndroidKLintShiftFlagsInspection() { - super(AndroidBundle.message("android.lint.inspections.shift.flags"), AnnotationDetector.FLAG_STYLE); - } - } - - public static class AndroidKLintShortAlarmInspection extends AndroidLintInspectionBase { - public AndroidKLintShortAlarmInspection() { - super(AndroidBundle.message("android.lint.inspections.short.alarm"), AlarmDetector.ISSUE); - } - } - - public static class AndroidKLintShowToastInspection extends AndroidLintInspectionBase { - public AndroidKLintShowToastInspection() { - super(AndroidBundle.message("android.lint.inspections.show.toast"), ToastDetector.ISSUE); - } - } - - public static class AndroidKLintSimpleDateFormatInspection extends AndroidLintInspectionBase { - public AndroidKLintSimpleDateFormatInspection() { - super(AndroidBundle.message("android.lint.inspections.simple.date.format"), DateFormatDetector.DATE_FORMAT); - } - } - - // Maybe not relevant - public static class AndroidKLintStopShipInspection extends AndroidLintInspectionBase { - public AndroidKLintStopShipInspection() { - super(AndroidBundle.message("android.lint.inspections.stop.ship"), CommentDetector.STOP_SHIP); - } - - } - - public static class AndroidKLintSupportAnnotationUsageInspection extends AndroidLintInspectionBase { - public AndroidKLintSupportAnnotationUsageInspection() { - super("Incorrect support annotation usage", AnnotationDetector.ANNOTATION_USAGE); - } - } - - public static class AndroidKLintUniqueConstantsInspection extends AndroidLintInspectionBase { - public AndroidKLintUniqueConstantsInspection() { - super(AndroidBundle.message("android.lint.inspections.unique.constants"), AnnotationDetector.UNIQUE); - } - } - - public static class AndroidKLintUnlocalizedSmsInspection extends AndroidLintInspectionBase { - public AndroidKLintUnlocalizedSmsInspection() { - super(AndroidBundle.message("android.lint.inspections.unlocalized.sms"), NonInternationalizedSmsDetector.ISSUE); - } - } - public static class AndroidKLintWorldReadableFilesInspection extends AndroidLintInspectionBase { - public AndroidKLintWorldReadableFilesInspection() { - super(AndroidBundle.message("android.lint.inspections.world.readable.files"), SecurityDetector.WORLD_READABLE); - } - } - public static class AndroidKLintWrongCallInspection extends AndroidLintInspectionBase { - public AndroidKLintWrongCallInspection() { - super(AndroidBundle.message("android.lint.inspections.wrong.call"), WrongCallDetector.ISSUE); - } - - } - - public static class AndroidKLintPendingBindingsInspection extends AndroidLintInspectionBase { - public AndroidKLintPendingBindingsInspection() { - super("Missing Pending Bindings", RecyclerViewDetector.DATA_BINDER); - } - } - - public static class AndroidKLintUnsafeDynamicallyLoadedCodeInspection extends AndroidLintInspectionBase { - public AndroidKLintUnsafeDynamicallyLoadedCodeInspection() { - super("load used to dynamically load code", UnsafeNativeCodeDetector.LOAD); - } - } - - public static class AndroidKLintUnsafeNativeCodeLocationInspection extends AndroidLintInspectionBase { - public AndroidKLintUnsafeNativeCodeLocationInspection() { - super("Native code outside library directory", UnsafeNativeCodeDetector.UNSAFE_NATIVE_CODE_LOCATION); - } - } - - public static class AndroidKLintUnsafeProtectedBroadcastReceiverInspection extends AndroidLintInspectionBase { - public AndroidKLintUnsafeProtectedBroadcastReceiverInspection() { - super("Unsafe Protected BroadcastReceiver", UnsafeBroadcastReceiverDetector.ACTION_STRING); - } - } -} diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintQuickFix.java.173 b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintQuickFix.java.173 deleted file mode 100644 index 967631afd53..00000000000 --- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintQuickFix.java.173 +++ /dev/null @@ -1,16 +0,0 @@ -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]; - - void apply(@NotNull PsiElement startElement, @NotNull PsiElement endElement, @NotNull AndroidQuickfixContexts.Context context); - - boolean isApplicable(@NotNull PsiElement startElement, @NotNull PsiElement endElement, @NotNull AndroidQuickfixContexts.ContextType contextType); - - @NotNull - String getName(); -} - diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintUtil.java.173 b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintUtil.java.173 deleted file mode 100644 index 9c727a9732d..00000000000 --- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidLintUtil.java.173 +++ /dev/null @@ -1,57 +0,0 @@ -package org.jetbrains.android.inspections.klint; - -import com.android.tools.klint.detector.api.Issue; -import com.intellij.codeHighlighting.HighlightDisplayLevel; -import com.intellij.codeInsight.daemon.HighlightDisplayKey; -import com.intellij.codeInspection.InspectionProfile; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Pair; -import com.intellij.profile.codeInspection.InspectionProjectProfileManager; -import com.intellij.psi.PsiElement; -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class AndroidLintUtil { - @NonNls static final String ATTR_VALUE_VERTICAL = "vertical"; - @NonNls static final String ATTR_VALUE_WRAP_CONTENT = "wrap_content"; - @NonNls static final String ATTR_LAYOUT_HEIGHT = "layout_height"; - @NonNls static final String ATTR_LAYOUT_WIDTH = "layout_width"; - @NonNls static final String ATTR_ORIENTATION = "orientation"; - - private AndroidLintUtil() { - } - - @Nullable - public static Pair getHighlighLevelAndInspection(@NotNull Project project, - @NotNull Issue issue, - @NotNull PsiElement context) { - final String inspectionShortName = AndroidLintInspectionBase.getInspectionShortNameByIssue(project, issue); - if (inspectionShortName == null) { - return null; - } - - final HighlightDisplayKey key = HighlightDisplayKey.find(inspectionShortName); - if (key == null) { - return null; - } - - final InspectionProfile profile = InspectionProjectProfileManager.getInstance(context.getProject()).getInspectionProfile(); - if (!profile.isToolEnabled(key, context)) { - if (!issue.isEnabledByDefault()) { - // Lint will skip issues (and not report them) for issues that have been disabled, - // except for those issues that are explicitly enabled via Gradle. Therefore, if - // we get this far, lint has found this issue to be explicitly enabled, so we let - // that setting override a local enabled/disabled state in the IDE profile. - } else { - return null; - } - } - - final AndroidLintInspectionBase inspection = (AndroidLintInspectionBase)profile.getUnwrappedTool(inspectionShortName, context); - if (inspection == null) return null; - final HighlightDisplayLevel errorLevel = profile.getErrorLevel(key, context); - return Pair.create(inspection, - errorLevel != null ? errorLevel : HighlightDisplayLevel.WARNING); - } -} diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidQuickfixContexts.java.173 b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidQuickfixContexts.java.173 deleted file mode 100644 index f4c9238506b..00000000000 --- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidQuickfixContexts.java.173 +++ /dev/null @@ -1,72 +0,0 @@ -package org.jetbrains.android.inspections.klint; - -import com.intellij.openapi.editor.Editor; -import org.jetbrains.annotations.NotNull; - -public class AndroidQuickfixContexts { - public static abstract class Context { - private final ContextType myType; - - private Context(@NotNull ContextType type) { - myType = type; - } - - @NotNull - public ContextType getType() { - return myType; - } - } - - public static class ContextType { - private ContextType() { - } - } - - public static class BatchContext extends Context { - public static final ContextType TYPE = new ContextType(); - private static final BatchContext INSTANCE = new BatchContext(); - - private BatchContext() { - super(TYPE); - } - - @NotNull - public static BatchContext getInstance() { - return INSTANCE; - } - } - - public static class EditorContext extends Context { - public static final ContextType TYPE = new ContextType(); - private final Editor myEditor; - - private EditorContext(@NotNull Editor editor) { - super(TYPE); - myEditor = editor; - } - - @NotNull - public Editor getEditor() { - return myEditor; - } - - @NotNull - public static EditorContext getInstance(@NotNull Editor editor) { - return new EditorContext(editor); - } - } - - public static class DesignerContext extends Context { - public static final ContextType TYPE = new ContextType(); - private static final DesignerContext INSTANCE = new DesignerContext(); - - private DesignerContext() { - super(TYPE); - } - - @NotNull - public static DesignerContext getInstance() { - return INSTANCE; - } - } -} diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/ApiUtils.kt.173 b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/ApiUtils.kt.173 deleted file mode 100644 index e3509d2c9cf..00000000000 --- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/ApiUtils.kt.173 +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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.android.inspections.klint - -import com.android.sdklib.SdkVersionInfo - - -fun getVersionField(api: Int, fullyQualified: Boolean): String = SdkVersionInfo.getBuildCode(api)?.let { - if (fullyQualified) "android.os.Build.VERSION_CODES.$it" else it -} ?: api.toString() \ No newline at end of file diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/DomPsiConverter.java.173 b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/DomPsiConverter.java.173 deleted file mode 100644 index d0b29f003a3..00000000000 --- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/DomPsiConverter.java.173 +++ /dev/null @@ -1,1302 +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.intellij.openapi.application.Application; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.progress.ProcessCanceledException; -import com.intellij.openapi.util.Computable; -import com.intellij.openapi.util.TextRange; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.PsiElement; -import com.intellij.psi.xml.*; -import com.intellij.util.containers.HashMap; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.w3c.dom.*; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * Converter which takes a PSI hierarchy for an XML file or document, and - * creates a corresponding W3C DOM tree. It attempts to delegate as much - * as possible to the original PSI tree. Note also that the {@link #getTextRange(Node)}} - * method allows us to look up source offsets for the DOM nodes (which plain XML - * DOM parsers do not). - *

- * NOTE: The tree may not be semantically equivalent to the XML PSI structure; this - * converter only attempts to make the DOM correct as far as Lint cares (meaning that it - * only worries about the details Lint cares about; currently this means it only wraps elements, - * text and comment nodes.) - */ -class DomPsiConverter { - private DomPsiConverter() { - } - - /** - * Convert the given {@link XmlFile} to a DOM tree - * - * @param xmlFile the file to be converted - * @return a corresponding W3C DOM tree - */ - @Nullable - public static Document convert(@NotNull XmlFile xmlFile) { - try { - XmlDocument xmlDocument = xmlFile.getDocument(); - if (xmlDocument == null) { - return null; - } - - return convert(xmlDocument); - } - catch (ProcessCanceledException e) { - // Ignore: common occurrence, e.g. we're running lint as part of an editor background - // and while lint is running the user switches files: the inspections framework will - // then cancel the process from within the PSI machinery (which asks the progress manager - // periodically whether the operation is cancelled) and we find ourselves here - return null; - } - catch (Exception e) { - String path = xmlFile.getName(); - VirtualFile virtualFile = xmlFile.getVirtualFile(); - if (virtualFile != null) { - path = virtualFile.getPath(); - } - throw new RuntimeException("Could not convert file " + path, e); - } - } - - /** - * Convert the given {@link XmlDocument} to a DOM tree - * - * @param document the document to be converted - * @return a corresponding W3C DOM tree - */ - @Nullable - private static Document convert(@NotNull XmlDocument document) { - return new DomDocument(document); - } - - /** Gets the {@link TextRange} for a {@link Node} created with this converter */ - @NotNull - public static TextRange getTextRange(@NotNull Node node) { - assert node instanceof DomNode; - DomNode domNode = (DomNode)node; - XmlElement element = domNode.myElement; - - // For elements, don't highlight the entire element range; instead, just - // highlight the element name - if (node.getNodeType() == Node.ELEMENT_NODE) { - return getTextNameRange(node); - } - - return element.getTextRange(); - } - - /** Gets the {@link TextRange} for a {@link Node} created with this converter */ - @NotNull - public static TextRange getTextNameRange(@NotNull Node node) { - assert node instanceof DomNode; - DomNode domNode = (DomNode)node; - XmlElement element = domNode.myElement; - - // For elements and attributes, don't highlight the entire element range; instead, just - // highlight the element name - if (node.getNodeType() == Node.ELEMENT_NODE && element instanceof XmlTag) { - String tag = node.getNodeName(); - int index = element.getText().indexOf(tag); - if (index != -1) { - TextRange textRange = element.getTextRange(); - int start = textRange.getStartOffset() + index; - return new TextRange(start, start + tag.length()); - } - } else if (node.getNodeType() == Node.ATTRIBUTE_NODE && element instanceof XmlAttribute) { - XmlElement nameElement = ((XmlAttribute)element).getNameElement(); - if (nameElement != null) { - return nameElement.getTextRange(); - } - } - - return element.getTextRange(); - } - - /** Gets the {@link TextRange} for the value region of a {@link Node} created with this converter */ - @NotNull - public static TextRange getTextValueRange(@NotNull Node node) { - assert node instanceof DomNode; - DomNode domNode = (DomNode)node; - XmlElement element = domNode.myElement; - TextRange textRange = element.getTextRange(); - - // For attributes, don't highlight the entire element range; instead, just - // highlight the value range - if (node.getNodeType() == Node.ATTRIBUTE_NODE && element instanceof XmlAttribute) { - XmlAttributeValue valueElement = ((XmlAttribute)element).getValueElement(); - if (valueElement != null) { - return valueElement.getValueTextRange(); - } - } - - return textRange; - } - - private static final NodeList EMPTY = new NodeList() { - @NotNull - @Override - public Node item(int i) { - throw new IllegalArgumentException(); - } - - @Override - public int getLength() { - return 0; - } - }; - - @Nullable - private static final NamedNodeMap EMPTY_ATTRIBUTES = new NamedNodeMap() { - @Override - public int getLength() { - return 0; - } - - @Nullable - @Override - public Node getNamedItem(String s) { - return null; - } - - @Nullable - @Override - public Node getNamedItemNS(String s, String s2) throws DOMException { - return null; - } - - @NotNull - @Override - public Node setNamedItem(Node node) throws DOMException { - throw new UnsupportedOperationException(); // Not supported - } - - @NotNull - @Override - public Node removeNamedItem(String s) throws DOMException { - throw new UnsupportedOperationException(); // Not supported - } - - @NotNull - @Override - public Node item(int i) { - throw new UnsupportedOperationException(); // Not supported - } - - @Nullable - @Override - public Node setNamedItemNS(Node node) throws DOMException { - return null; - } - - @NotNull - @Override - public Node removeNamedItemNS(String s, String s2) throws DOMException { - throw new UnsupportedOperationException(); // Not supported - } - }; - - private static class DomNodeList implements NodeList { - protected final List myChildren = new ArrayList(); - - @NotNull - @Override - public Node item(int i) { - return myChildren.get(i); - } - - @Override - public int getLength() { - return myChildren.size(); - } - - void add(@NotNull DomNode node) { - int size = myChildren.size(); - if (size > 0) { - DomNode last = myChildren.get(size - 1); - node.myPrevious = last; - last.myNext = node; - } - myChildren.add(node); - } - } - - private static class DomNamedNodeMap implements NamedNodeMap { - @NotNull protected final Map myMap; - @NotNull protected final Map> myNsMap; - @NotNull protected final List mItems; - - private DomNamedNodeMap(@NotNull DomElement element, @NotNull XmlAttribute[] attributes) { - int count = attributes.length; - int namespaceCount = 0; - for (XmlAttribute attribute : attributes) { - if (!attribute.getNamespace().isEmpty()) { - namespaceCount++; - } - } - myMap = new HashMap(count - namespaceCount); - myNsMap = new HashMap>(namespaceCount); - mItems = new ArrayList(count); - - assert element.myOwner != null; // True for elements, not true for non-Element nodes - for (XmlAttribute attribute : attributes) { - DomAttr attr = new DomAttr(element.myOwner, element, attribute); - mItems.add(attr); - String namespace = attribute.getNamespace(); - if (!namespace.isEmpty()) { - Map map = myNsMap.get(namespace); - if (map == null) { - map = new HashMap(); - myNsMap.put(namespace, map); - } - map.put(attribute.getLocalName(), attr); - } else { - myMap.put(attribute.getName(), attr); - } - } - } - - @Override - public Node item(int i) { - return mItems.get(i); - } - - @Override - public int getLength() { - return mItems.size(); - } - - @Override - public Node getNamedItem(@NotNull String s) { - return myMap.get(s); - } - - @Nullable - @Override - public Node getNamedItemNS(@NotNull String namespace, @NotNull String name) throws DOMException { - Map map = myNsMap.get(namespace); - if (map != null) { - return map.get(name); - } - return null; - } - - @NotNull - @Override - public Node setNamedItem(Node node) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @NotNull - @Override - public Node removeNamedItem(String s) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @NotNull - @Override - public Node setNamedItemNS(Node node) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @NotNull - @Override - public Node removeNamedItemNS(String s, String s2) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - } - - @SuppressWarnings({"UnusedParameters", "UnusedDeclaration"}) // Specifies methods shared by children - private static abstract class DomNode implements Node { - @Nullable protected final Document myOwner; - @Nullable protected final DomNode myParent; - @NotNull protected final XmlElement myElement; - @Nullable protected NodeList myChildren; - @Nullable protected DomNode myNext; - @Nullable protected DomNode myPrevious; - - protected DomNode(@Nullable Document owner, @Nullable DomNode parent, @NotNull XmlElement element) { - myOwner = owner; - myParent = parent; - myElement = element; - } - - @Nullable - @Override - public Node getParentNode() { - return myParent; - } - - @NotNull - @Override - public NodeList getChildNodes() { - if (myChildren == null) { - PsiElement[] children = myElement.getChildren(); - if (children.length > 0) { - DomNodeList list = new DomNodeList(); - myChildren = list; - // True except for in DomDocument, which has custom getChildNodes - assert myOwner != null; - - for (PsiElement child : children) { - if (child instanceof XmlTag) { - list.add(new DomElement(myOwner, this, (XmlTag) child)); - } else if (child instanceof XmlText) { - list.add(new DomText(myOwner, this, (XmlText) child)); - } else if (child instanceof XmlComment) { - list.add(new DomComment(myOwner, this, (XmlComment) child)); - } else { - // Skipping other types for now; lint doesn't care about them. - // TODO: Consider whether we need CDATA. - } - } - } else { - myChildren = EMPTY; - } - } - return myChildren; - } - - @Nullable - @Override - public Node getFirstChild() { - NodeList childNodes = getChildNodes(); - if (childNodes.getLength() > 0) { - return childNodes.item(0); - } - return null; - } - - @Nullable - @Override - public Node getLastChild() { - NodeList childNodes = getChildNodes(); - if (childNodes.getLength() > 0) { - return childNodes.item(0); - } - return null; - } - - @Nullable - @Override - public Node getPreviousSibling() { - return myPrevious; - } - - @Nullable - @Override - public Node getNextSibling() { - return myNext; - } - - @Nullable - @Override - public NamedNodeMap getAttributes() { - throw new UnsupportedOperationException(); // Only supported on elements - } - - @Nullable - @Override - public Document getOwnerDocument() { - return myOwner; - } - - @Override - public void setNodeValue(String s) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @NotNull - @Override - public Node insertBefore(Node node, Node node2) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @NotNull - @Override - public Node replaceChild(Node node, Node node2) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @NotNull - @Override - public Node removeChild(Node node) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @NotNull - @Override - public Node appendChild(Node node) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @Override - public boolean hasChildNodes() { - return getChildNodes().getLength() > 0; - } - - @NotNull - @Override - public Node cloneNode(boolean b) { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @Override - public void normalize() { - } - - @Override - public boolean isSupported(String s, String s2) { - return false; - } - - @NotNull - @Override - public String getNamespaceURI() { - throw new UnsupportedOperationException(); // Only supported on elements in lint - } - - @NotNull - @Override - public String getPrefix() { - throw new UnsupportedOperationException(); // Only supported on elements in lint - } - - @Override - public void setPrefix(String s) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @Nullable - @Override - public String getLocalName() { - return null; - } - - @Override - public boolean hasAttributes() { - return false; - } - - @Nullable - @Override - public String getBaseURI() { - return null; - } - - @Override - public short compareDocumentPosition(Node node) throws DOMException { - throw new UnsupportedOperationException(); // Not supported - } - - @Override - public String getTextContent() throws DOMException { - return myElement.getText(); - } - - @Override - public void setTextContent(String s) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @Override - public boolean isSameNode(Node node) { - throw new UnsupportedOperationException(); // Not supported - } - - @NotNull - @Override - public String lookupPrefix(String s) { - throw new UnsupportedOperationException(); // Not supported - } - - @Override - public boolean isDefaultNamespace(String s) { - throw new UnsupportedOperationException(); // Not supported - } - - @NotNull - @Override - public String lookupNamespaceURI(String s) { - throw new UnsupportedOperationException(); // Not supported - } - - @Override - public boolean isEqualNode(Node node) { - throw new UnsupportedOperationException(); // Not supported - } - - @NotNull - @Override - public Object getFeature(String s, String s2) { - throw new UnsupportedOperationException(); // Not supported - } - - @NotNull - @Override - public Object setUserData(String s, Object o, UserDataHandler userDataHandler) { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @NotNull - @Override - public Object getUserData(String s) { - throw new UnsupportedOperationException(); // Not supported - } - - // From CharacterData - - @NotNull - public String getData() throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - - public void setData(String s) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - - public int getLength() { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @NotNull - public String substringData(int i, int i2) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - - public void appendData(String s) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - - public void insertData(int i, String s) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - - public void deleteData(int i, int i2) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - - public void replaceData(int i, int i2, String s) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - } - - private static class DomDocument extends DomNode implements Document { - @NotNull private final XmlDocument myPsiDocument; - @Nullable private DomElement myRoot; - - private DomDocument(@NotNull XmlDocument document) { - super(null, null, document); - myPsiDocument = document; - } - - // From org.w3c.dom.Node: - - @Nullable - @Override - public String getNodeName() { - return null; - } - - @Nullable - @Override - public String getNodeValue() throws DOMException { - return null; - } - - @Override - public short getNodeType() { - return Node.DOCUMENT_NODE; - } - - @NotNull - @Override - public NodeList getChildNodes() { - if (myChildren == null) { - DomNodeList list = new DomNodeList(); - myChildren = list; - DomNode documentElement = (DomNode)getDocumentElement(); - if (documentElement != null) { - list.add(documentElement); - } - } - - return myChildren; - } - - // From org.w3c.dom.Document: - - @NotNull - @Override - public DocumentType getDoctype() { - throw new UnsupportedOperationException(); // Not supported - } - - @NotNull - @Override - public DOMImplementation getImplementation() { - throw new UnsupportedOperationException(); // Not supported - } - - @Nullable - @Override - public Element getDocumentElement() { - if (myRoot == null) { - XmlTag rootTag = myPsiDocument.getRootTag(); - if (rootTag == null) { - return null; - } - myRoot = new DomElement(this, this, rootTag); - } - - return myRoot; - } - - @NotNull - @Override - public NodeList getElementsByTagName(String s) { - Element root = getDocumentElement(); - if (root != null) { - return root.getElementsByTagName(s); - } - return EMPTY; - } - - @NotNull - @Override - public NodeList getElementsByTagNameNS(String s, String s2) { - throw new UnsupportedOperationException(); // Not supported - } - - @NotNull - @Override - public Element createElement(String s) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @NotNull - @Override - public DocumentFragment createDocumentFragment() { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @NotNull - @Override - public Text createTextNode(String s) { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @NotNull - @Override - public Comment createComment(String s) { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @NotNull - @Override - public CDATASection createCDATASection(String s) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @NotNull - @Override - public ProcessingInstruction createProcessingInstruction(String s, String s2) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @NotNull - @Override - public Attr createAttribute(String s) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @NotNull - @Override - public EntityReference createEntityReference(String s) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @NotNull - @Override - public Node importNode(Node node, boolean b) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @NotNull - @Override - public Element createElementNS(String s, String s2) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @NotNull - @Override - public Attr createAttributeNS(String s, String s2) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @NotNull - @Override - public Element getElementById(String s) { - throw new UnsupportedOperationException(); // Not supported - } - - @NotNull - @Override - public String getInputEncoding() { - throw new UnsupportedOperationException(); // Not supported - } - - @NotNull - @Override - public String getXmlEncoding() { - throw new UnsupportedOperationException(); // Not supported - } - - @Override - public boolean getXmlStandalone() { - throw new UnsupportedOperationException(); // Not supported - } - - @Override - public void setXmlStandalone(boolean b) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @NotNull - @Override - public String getXmlVersion() { - throw new UnsupportedOperationException(); // Not supported - } - - @Override - public void setXmlVersion(String s) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @Override - public boolean getStrictErrorChecking() { - throw new UnsupportedOperationException(); // Not supported - } - - @Override - public void setStrictErrorChecking(boolean b) { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @NotNull - @Override - public String getDocumentURI() { - throw new UnsupportedOperationException(); // Not supported - } - - @Override - public void setDocumentURI(String s) { - throw new UnsupportedOperationException(); // Not supported - } - - @NotNull - @Override - public Node adoptNode(Node node) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @NotNull - @Override - public DOMConfiguration getDomConfig() { - throw new UnsupportedOperationException(); // Not supported - } - - @Override - public void normalizeDocument() { - } - - @NotNull - @Override - public Node renameNode(Node node, String s, String s2) throws DOMException { - throw new UnsupportedOperationException(); // Not supported - } - } - - private static class DomElement extends DomNode implements Element { - private final XmlTag myTag; - @Nullable private NamedNodeMap myAttributes; - - private DomElement(@NotNull Document owner, @NotNull DomNode parent, @NotNull XmlTag tag) { - super(owner, parent, tag); - myTag = tag; - } - - // From org.w3c.dom.Node: - - @NotNull - @Override - public String getNodeName() { - return getTagName(); - } - - @Nullable - @Override - public String getNodeValue() throws DOMException { - return null; - } - - @Override - public short getNodeType() { - return Node.ELEMENT_NODE; - } - - @NotNull - @Override - public NamedNodeMap getAttributes() { - Application application = ApplicationManager.getApplication(); - if (!application.isReadAccessAllowed()) { - return application.runReadAction(new Computable() { - @Override - public NamedNodeMap compute() { - return getAttributes(); - } - }); - } - - if (myAttributes == null) { - XmlAttribute[] attributes = myTag.getAttributes(); - if (attributes.length == 0) { - myAttributes = EMPTY_ATTRIBUTES; - } else { - myAttributes = new DomNamedNodeMap(this, attributes); - } - } - - return myAttributes; - } - - // From org.w3c.dom.Element: - - @NotNull - @Override - public String getTagName() { - Application application = ApplicationManager.getApplication(); - if (!application.isReadAccessAllowed()) { - return application.runReadAction(new Computable() { - @Override - public String compute() { - return getTagName(); - } - }); - } - - return myTag.getName(); - } - - @NotNull - @Override - public String getAttribute(@NotNull String name) { - Node node = getAttributes().getNamedItem(name); - if (node != null) { - return node.getNodeValue(); - } - return ""; - } - - @NotNull - @Override - public String getAttributeNS(@NotNull String namespace, @NotNull String name) throws DOMException { - Node node = getAttributes().getNamedItemNS(namespace, name); - if (node != null) { - return node.getNodeValue(); - } - return ""; - } - - @Nullable - @Override - public Attr getAttributeNodeNS(@NotNull String namespace, @NotNull String name) throws DOMException { - Node node = getAttributes().getNamedItemNS(namespace, name); - if (node != null) { - return (Attr)node; - } - return null; - } - - @Nullable - @Override - public Attr getAttributeNode(@NotNull String name) { - Node node = getAttributes().getNamedItem(name); - if (node != null) { - return (Attr)node; - } - return null; - } - - @Override - public boolean hasAttribute(@NotNull String name) { - return getAttributes().getNamedItem(name) != null; - } - - @Override - public boolean hasAttributeNS(@NotNull String namespace, @NotNull String name) throws DOMException { - return getAttributes().getNamedItemNS(namespace, name) != null; - } - - @NotNull - @Override - public NodeList getElementsByTagName(@NotNull String s) { - NodeList childNodes = getChildNodes(); - if (childNodes == EMPTY) { - return EMPTY; - } - DomNodeList matches = new DomNodeList(); - for (int i = 0, n = childNodes.getLength(); i < n; i++) { - Node node = childNodes.item(i); - if (s.equals(node.getNodeName())) { - matches.add((DomNode)node); - } - } - - return matches; - } - - @NotNull - @Override - public NodeList getElementsByTagNameNS(String s, String s2) throws DOMException { - throw new UnsupportedOperationException(); // Not supported - } - - @NotNull - @Override - public Attr setAttributeNode(Attr attr) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @NotNull - @Override - public Attr removeAttributeNode(Attr attr) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @Override - public void setAttributeNS(String s, String s2, String s3) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @Override - public void removeAttributeNS(String s, String s2) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @Override - public void setAttribute(String s, String s2) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @Override - public void removeAttribute(String s) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @NotNull - @Override - public Attr setAttributeNodeNS(Attr attr) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @NotNull - @Override - public TypeInfo getSchemaTypeInfo() { - throw new UnsupportedOperationException(); // Not supported - } - - @Override - public void setIdAttribute(String s, boolean b) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @Override - public void setIdAttributeNS(String s, String s2, boolean b) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @Override - public void setIdAttributeNode(Attr attr, boolean b) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - } - - private static class DomText extends DomNode implements Text { - @NotNull private final XmlText myText; - - private DomText(@NotNull Document owner, @NotNull DomNode parent, @NotNull XmlText text) { - super(owner, parent, text); - myText = text; - } - - // From org.w3c.dom.Node: - - @Nullable - @Override - public String getNodeName() { - return null; - } - - @NotNull - @Override - public String getNodeValue() throws DOMException { - Application application = ApplicationManager.getApplication(); - if (!application.isReadAccessAllowed()) { - return application.runReadAction(new Computable() { - @Override - public String compute() { - return getNodeValue(); - } - }); - } - - return myText.getText(); - } - - @Override - public short getNodeType() { - return Node.TEXT_NODE; - } - - // From org.w3c.dom.Text: - - @NotNull - @Override - public Text splitText(int i) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @Override - public boolean isElementContentWhitespace() { - String s = myText.getText(); - for (int i = 0, n = s.length(); i < n; i++) { - if (!Character.isWhitespace(s.charAt(i))) { - return false; - } - } - - return true; - } - - @NotNull - @Override - public String getWholeText() { - throw new UnsupportedOperationException(); // Not supported - } - - @NotNull - @Override - public Text replaceWholeText(String s) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - } - - private static class DomComment extends DomNode implements Comment { - @NotNull private final XmlComment myComment; - - private DomComment(@NotNull Document owner, @NotNull DomNode parent, @NotNull XmlComment comment) { - super(owner, parent, comment); - myComment = comment; - } - - // From org.w3c.dom.Node: - - @Nullable - @Override - public String getNodeName() { - return null; - } - - @NotNull - @Override - public String getNodeValue() throws DOMException { - Application application = ApplicationManager.getApplication(); - if (!application.isReadAccessAllowed()) { - return application.runReadAction(new Computable() { - @Override - public String compute() { - return getNodeValue(); - } - }); - } - - return myComment.getText(); - } - - @Override - public short getNodeType() { - return Node.COMMENT_NODE; - } - - @NotNull - @Override - public String getTextContent() throws DOMException { - return getNodeValue(); - } - } - - private static class DomAttr extends DomNode implements Attr { - @NotNull private final DomElement myOwner; - @NotNull private final XmlAttribute myAttribute; - - private DomAttr(@NotNull Document document, @NotNull DomElement owner, @NotNull XmlAttribute attribute) { - super(document, null, attribute); - myOwner = owner; - myAttribute = attribute; - } - - // From org.w3c.dom.Node: - - @NotNull - @Override - public String getNodeName() { - return getName(); - } - - @NotNull - @Override - public String getNodeValue() throws DOMException { - return getValue(); - } - - @Override - public short getNodeType() { - return Node.ATTRIBUTE_NODE; - } - - // From org.w3c.dom.Attr: - - @NotNull - @Override - public String getName() { - Application application = ApplicationManager.getApplication(); - if (!application.isReadAccessAllowed()) { - return application.runReadAction(new Computable() { - @Override - public String compute() { - return getName(); - } - }); - } - return myAttribute.getName(); - } - - @Override - public boolean getSpecified() { - throw new UnsupportedOperationException(); // Not supported - } - - @NotNull - @Override - public String getValue() { - Application application = ApplicationManager.getApplication(); - if (!application.isReadAccessAllowed()) { - return application.runReadAction(new Computable() { - @Override - public String compute() { - return getValue(); - } - }); - } - - String value = myAttribute.getValue(); - if (value == null) { - value = ""; - } - return value; - } - - @NotNull - @Override - public String getLocalName() { - Application application = ApplicationManager.getApplication(); - if (!application.isReadAccessAllowed()) { - return application.runReadAction(new Computable() { - @Override - public String compute() { - return getLocalName(); - } - }); - } - - return myAttribute.getLocalName(); - } - - @NotNull - @Override - public String getPrefix() { - Application application = ApplicationManager.getApplication(); - if (!application.isReadAccessAllowed()) { - return application.runReadAction(new Computable() { - @Override - public String compute() { - return getPrefix(); - } - }); - } - - return myAttribute.getNamespacePrefix(); - } - - @NotNull - @Override - public String getNamespaceURI() { - Application application = ApplicationManager.getApplication(); - if (!application.isReadAccessAllowed()) { - return application.runReadAction(new Computable() { - @Override - public String compute() { - return getNamespaceURI(); - } - }); - } - - return myAttribute.getNamespace(); - } - - @Override - public void setValue(String s) throws DOMException { - throw new UnsupportedOperationException(); // Read-only bridge - } - - @NotNull - @Override - public Element getOwnerElement() { - return myOwner; - } - - @NotNull - @Override - public TypeInfo getSchemaTypeInfo() { - throw new UnsupportedOperationException(); // Not supported - } - - @Override - public boolean isId() { - throw new UnsupportedOperationException(); // Not supported - } - } -} diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/DomPsiParser.java.173 b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/DomPsiParser.java.173 deleted file mode 100644 index 1c0ca05feec..00000000000 --- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/DomPsiParser.java.173 +++ /dev/null @@ -1,183 +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.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.tools.klint.client.api.LintClient; -import com.android.tools.klint.client.api.XmlParser; -import com.android.tools.klint.detector.api.DefaultPosition; -import com.android.tools.klint.detector.api.Location; -import com.android.tools.klint.detector.api.Position; -import com.android.tools.klint.detector.api.XmlContext; -import com.intellij.openapi.application.AccessToken; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.util.Computable; -import com.intellij.openapi.util.TextRange; -import com.intellij.psi.PsiFile; -import com.intellij.psi.xml.XmlFile; -import org.w3c.dom.Attr; -import org.w3c.dom.Document; -import org.w3c.dom.Node; - -import java.io.File; - -/** - * Lint parser which reads in a DOM from a given file, by mapping to the underlying XML PSI structure - */ -class DomPsiParser extends XmlParser { - private final LintClient myClient; - private AccessToken myReadLock; - - public DomPsiParser(LintClient client) { - myClient = client; - } - - @Override - public void dispose(@NonNull XmlContext context, @NonNull Document document) { - if (context.document != null) { - myReadLock.finish(); - myReadLock = null; - context.document = null; - } - } - - @Override - public int getNodeStartOffset(@NonNull XmlContext context, @NonNull Node node) { - TextRange textRange = DomPsiConverter.getTextRange(node); - return textRange.getStartOffset(); - } - - @Override - public int getNodeEndOffset(@NonNull XmlContext context, @NonNull Node node) { - TextRange textRange = DomPsiConverter.getTextRange(node); - return textRange.getEndOffset(); - } - - @Nullable - @Override - public Document parseXml(@NonNull final XmlContext context) { - assert myReadLock == null; - myReadLock = ApplicationManager.getApplication().acquireReadActionLock(); - Document document = parse(context); - if (document == null) { - myReadLock.finish(); - myReadLock = null; - } - return document; - } - - @Nullable - private Document parse(XmlContext context) { - // Should only be called from read thread - assert ApplicationManager.getApplication().isReadAccessAllowed(); - - final PsiFile psiFile = IntellijLintUtils.getPsiFile(context); - if (!(psiFile instanceof XmlFile)) { - return null; - } - XmlFile xmlFile = (XmlFile)psiFile; - - try { - return DomPsiConverter.convert(xmlFile); - } catch (Throwable t) { - myClient.log(t, "Failed converting PSI parse tree to DOM for file %1$s", - context.file.getPath()); - return null; - } - } - - @NonNull - @Override - public Location getLocation(@NonNull XmlContext context, @NonNull Node 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); - } - - @NonNull - @Override - public Location getLocation(@NonNull XmlContext context, @NonNull Node node, int startDelta, int endDelta) { - 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); - } - - @NonNull - @Override - public Location getNameLocation(@NonNull XmlContext context, @NonNull Node 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); - } - - @NonNull - @Override - public Location getValueLocation(@NonNull XmlContext context, @NonNull Attr 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); - } - - @NonNull - @Override - public Location.Handle createLocationHandle(@NonNull XmlContext context, @NonNull Node node) { - return new LocationHandle(context.file, node); - } - - private static class LocationHandle implements Location.Handle { - private final File myFile; - private final Node myNode; - private Object myClientData; - - public LocationHandle(File file, Node node) { - myFile = file; - myNode = node; - } - - @NonNull - @Override - public Location resolve() { - if (!ApplicationManager.getApplication().isReadAccessAllowed()) { - return ApplicationManager.getApplication().runReadAction(new Computable() { - @Override - public Location compute() { - return resolve(); - } - }); - } - 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); - } - - @Override - public void setClientData(@Nullable Object clientData) { - myClientData = clientData; - } - - @Override - @Nullable - public Object getClientData() { - return myClientData; - } - } -} diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IdeaJavaParser.java.173 b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IdeaJavaParser.java.173 deleted file mode 100644 index 5f468cc1078..00000000000 --- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IdeaJavaParser.java.173 +++ /dev/null @@ -1,192 +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.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.tools.klint.client.api.JavaEvaluator; -import com.android.tools.klint.client.api.JavaParser; -import com.android.tools.klint.detector.api.JavaContext; -import com.android.tools.klint.detector.api.Location; -import com.android.tools.klint.detector.api.Severity; -import com.google.common.collect.Sets; -import com.intellij.codeInsight.AnnotationUtil; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.components.ServiceManager; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vfs.VfsUtilCore; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.*; -import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.util.InheritanceUtil; -import lombok.ast.Node; -import lombok.ast.Position; -import org.jetbrains.uast.UastContext; - -import java.io.File; -import java.util.List; - -public class IdeaJavaParser extends JavaParser { - private final IntellijLintClient myClient; - private final Project myProject; - private final UastContext myContext; - private final JavaEvaluator myEvaluator; - - public IdeaJavaParser(IntellijLintClient client, Project myProject) { - this.myClient = client; - this.myProject = myProject; - this.myEvaluator = new MyJavaEvaluator(myProject); - - myContext = ServiceManager.getService(myProject, UastContext.class); - } - - @Override - public UastContext getUastContext() { - return myContext; - } - - @Override - public void prepareJavaParse(@NonNull List contexts) { - - } - - @Override - public PsiJavaFile parseJavaToPsi(@NonNull JavaContext context) { - PsiFile psiFile = IntellijLintUtils.getPsiFile(context); - if (!(psiFile instanceof PsiJavaFile)) { - return null; - } - return (PsiJavaFile)psiFile; - } - - @Override - public JavaEvaluator getEvaluator() { - return myEvaluator; - } - - @Override - public Project getIdeaProject() { - return myProject; - } - - @Override - public Location getRangeLocation( - @NonNull JavaContext context, @NonNull Node from, int fromDelta, @NonNull Node to, int toDelta - ) { - Position position1 = from.getPosition(); - Position position2 = to.getPosition(); - if (position1 == null) { - return getLocation(context, to); - } - else if (position2 == null) { - return getLocation(context, from); - } - - int start = Math.max(0, from.getPosition().getStart() + fromDelta); - int end = to.getPosition().getEnd() + toDelta; - return Location.create(context.file, null, start, end); - } - - @Override - public Location.Handle createLocationHandle(@NonNull JavaContext context, @NonNull Node node) { - return new LocationHandle(context.file, node); - } - - @Override - public void runReadAction(@NonNull Runnable runnable) { - ApplicationManager.getApplication().runReadAction(runnable); - } - - /* Handle for creating positions cheaply and returning full fledged locations later */ - private class LocationHandle implements Location.Handle { - private final File myFile; - private final Node myNode; - private Object mClientData; - - public LocationHandle(File file, Node node) { - myFile = file; - myNode = node; - } - - @NonNull - @Override - public Location resolve() { - Position pos = myNode.getPosition(); - if (pos == null) { - myClient.log(Severity.WARNING, null, "No position data found for node %1$s", myNode); - return Location.create(myFile); - } - return Location.create(myFile, null /*contents*/, pos.getStart(), pos.getEnd()); - } - - @Override - public void setClientData(@Nullable Object clientData) { - mClientData = clientData; - } - - @Override - @Nullable - public Object getClientData() { - return mClientData; - } - } - - private static class MyJavaEvaluator extends JavaEvaluator { - private final Project myProject; - - public MyJavaEvaluator(Project project) { - myProject = project; - } - - @Nullable - @Override - public PsiClass findClass(@NonNull String qualifiedName) { - return JavaPsiFacade.getInstance(myProject).findClass(qualifiedName, GlobalSearchScope.allScope(myProject)); - } - - @Nullable - @Override - public PsiClassType getClassType(@Nullable PsiClass cls) { - return cls != null ? JavaPsiFacade.getElementFactory(myProject).createType(cls) : null; - } - - @NonNull - @Override - public PsiAnnotation[] getAllAnnotations(@NonNull PsiModifierListOwner owner) { - return AnnotationUtil.getAllAnnotations(owner, true, null, true); - } - - @Nullable - @Override - public PsiAnnotation findAnnotationInHierarchy(@NonNull PsiModifierListOwner listOwner, @NonNull String... annotationNames) { - return AnnotationUtil.findAnnotationInHierarchy(listOwner, Sets.newHashSet(annotationNames)); - } - - @Nullable - @Override - public PsiAnnotation findAnnotation(@Nullable PsiModifierListOwner listOwner, @NonNull String... annotationNames) { - return AnnotationUtil.findAnnotation(listOwner, false, annotationNames); - } - - @Nullable - @Override - public File getFile(@NonNull PsiFile file) { - VirtualFile virtualFile = file.getVirtualFile(); - return virtualFile != null ? VfsUtilCore.virtualToIoFile(virtualFile) : null; - } - } -} diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintClient.java.173 b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintClient.java.173 deleted file mode 100644 index 61ed0c97b55..00000000000 --- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintClient.java.173 +++ /dev/null @@ -1,862 +0,0 @@ -package org.jetbrains.android.inspections.klint; - -import com.android.annotations.NonNull; -import com.android.builder.model.AndroidProject; -import com.android.builder.model.LintOptions; -import com.android.ide.common.repository.ResourceVisibilityLookup; -import com.android.ide.common.res2.AbstractResourceRepository; -import com.android.ide.common.res2.ResourceFile; -import com.android.ide.common.res2.ResourceItem; -import com.android.sdklib.repository.AndroidSdkHandler; -import com.android.tools.idea.gradle.util.Projects; -import com.android.tools.idea.project.AndroidProjectInfo; -import com.android.tools.idea.res.AppResourceRepository; -import com.android.tools.idea.res.LocalResourceRepository; -import com.android.tools.idea.sdk.IdeSdks; -import com.android.tools.idea.welcome.install.AndroidSdk; -import com.android.tools.klint.checks.ApiLookup; -import com.android.tools.klint.client.api.*; -import com.android.tools.klint.detector.api.*; -import com.google.common.base.Charsets; -import com.google.common.collect.Lists; -import com.google.common.io.Files; -import com.intellij.analysis.AnalysisScope; -import com.intellij.openapi.Disposable; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.PathManager; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.event.DocumentEvent; -import com.intellij.openapi.editor.event.DocumentListener; -import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleManager; -import com.intellij.openapi.module.ModuleUtilCore; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.projectRoots.Sdk; -import com.intellij.openapi.roots.ModuleRootManager; -import com.intellij.openapi.util.Comparing; -import com.intellij.openapi.util.Computable; -import com.intellij.openapi.util.TextRange; -import com.intellij.openapi.vfs.LocalFileSystem; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.PsiDocumentManager; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiManager; -import com.intellij.psi.xml.XmlElement; -import com.intellij.psi.xml.XmlTag; -import com.intellij.util.PathUtil; -import com.intellij.util.containers.HashMap; -import com.intellij.util.lang.UrlClassLoader; -import com.intellij.util.net.HttpConfigurable; -import org.jetbrains.android.facet.AndroidFacet; -import org.jetbrains.android.facet.AndroidRootUtil; -import org.jetbrains.android.sdk.AndroidSdkData; -import org.jetbrains.android.sdk.AndroidSdkType; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.io.File; -import java.io.IOException; -import java.net.URL; -import java.net.URLConnection; -import java.util.*; - -import static com.android.tools.klint.detector.api.TextFormat.RAW; -import static org.jetbrains.android.inspections.klint.IntellijLintIssueRegistry.CUSTOM_ERROR; -import static org.jetbrains.android.inspections.klint.IntellijLintIssueRegistry.CUSTOM_WARNING; - -/** - * Implementation of the {@linkplain LintClient} API for executing lint within the IDE: - * reading files, reporting issues, logging errors, etc. - */ -public class IntellijLintClient extends LintClient implements Disposable { - protected static final Logger LOG = Logger.getInstance("#org.jetbrains.android.inspections.IntellijLintClient"); - - @NonNull protected Project myProject; - @Nullable protected Map myModuleMap; - - public IntellijLintClient(@NonNull Project project) { - super(CLIENT_STUDIO); - myProject = project; - } - - /** Creates a lint client for batch inspections */ - public static IntellijLintClient forBatch(@NotNull Project project, - @NotNull Map>> problemMap, - @NotNull AnalysisScope scope, - @NotNull List issues) { - return new BatchLintClient(project, problemMap, scope, issues); - } - - /** - * Returns an {@link ApiLookup} service. - * - * @param project the project to use for locating the Android SDK - * @return an API lookup if one can be found - */ - @Nullable - public static ApiLookup getApiLookup(@NotNull Project project) { - return ApiLookup.get(new IntellijLintClient(project)); - } - - /** - * Creates a lint client used for in-editor single file lint analysis (e.g. background checking while user is editing.) - */ - public static IntellijLintClient forEditor(@NotNull State state) { - return new EditorLintClient(state); - } - - @Nullable - protected Module findModuleForLintProject(@NotNull Project project, - @NotNull com.android.tools.klint.detector.api.Project lintProject) { - if (myModuleMap != null) { - Module module = myModuleMap.get(lintProject); - if (module != null) { - return module; - } - } - final File dir = lintProject.getDir(); - final VirtualFile vDir = LocalFileSystem.getInstance().findFileByIoFile(dir); - return vDir != null ? ModuleUtilCore.findModuleForFile(vDir, project) : null; - } - - void setModuleMap(@Nullable Map moduleMap) { - myModuleMap = moduleMap; - } - - @NonNull - @Override - public Configuration getConfiguration(@NonNull com.android.tools.klint.detector.api.Project project, @Nullable final LintDriver driver) { - if (project.isGradleProject() && project.isAndroidProject() && !project.isLibrary()) { - AndroidProject model = project.getGradleProjectModel(); - if (model != null) { - try { - LintOptions lintOptions = model.getLintOptions(); - final Map overrides = lintOptions.getSeverityOverrides(); - if (overrides != null && !overrides.isEmpty()) { - return new DefaultConfiguration(this, project, null) { - @NonNull - @Override - public Severity getSeverity(@NonNull Issue issue) { - Integer severity = overrides.get(issue.getId()); - if (severity != null) { - switch (severity.intValue()) { - case LintOptions.SEVERITY_FATAL: - return Severity.FATAL; - case LintOptions.SEVERITY_ERROR: - return Severity.ERROR; - case LintOptions.SEVERITY_WARNING: - return Severity.WARNING; - case LintOptions.SEVERITY_INFORMATIONAL: - return Severity.INFORMATIONAL; - case LintOptions.SEVERITY_IGNORE: - default: - return Severity.IGNORE; - } - } - - // This is a LIST lookup. I should make this faster! - if (!getIssues().contains(issue) && (driver == null || !driver.isCustomIssue(issue))) { - return Severity.IGNORE; - } - - return super.getSeverity(issue); - } - }; - } - } catch (Exception e) { - LOG.error(e); - } - } - } - return new DefaultConfiguration(this, project, null) { - @Override - public boolean isEnabled(@NonNull Issue issue) { - if (getIssues().contains(issue) && super.isEnabled(issue)) { - return true; - } - - return driver != null && driver.isCustomIssue(issue); - } - }; - } - - @Override - public void report(@NonNull Context context, - @NonNull Issue issue, - @NonNull Severity severity, - @NonNull Location location, - @NonNull String message, - @NonNull TextFormat format) { - assert false : message; - } - - @NonNull protected List getIssues() { - return Collections.emptyList(); - } - - @Nullable - protected Module getModule() { - return null; - } - - /** - * Recursively calls {@link #report} on the secondary location of this error, if any, which in turn may call it on a third - * 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 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() + ")"; - } - report(context, issue, severity, secondary, message, format); - } - } - - @Override - 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 == Severity.WARNING) { - if (format != null) { - LOG.warn(String.format(format, args), exception); - } else if (exception != null) { - LOG.warn(exception); - } - } else { - if (format != null) { - LOG.info(String.format(format, args), exception); - } else if (exception != null) { - LOG.info(exception); - } - } - } - - @Override - public XmlParser getXmlParser() { - return new DomPsiParser(this); - } - - @Nullable - @Override - public JavaParser getJavaParser(@Nullable com.android.tools.klint.detector.api.Project project) { - return new IdeaJavaParser(this, myProject); - } - - @NonNull - @Override - public List getJavaClassFolders(@NonNull com.android.tools.klint.detector.api.Project project) { - // todo: implement when class files checking detectors will be available - return Collections.emptyList(); - } - - @NonNull - @Override - public List getJavaLibraries(@NonNull com.android.tools.klint.detector.api.Project project, boolean includeProvided) { - // todo: implement - return Collections.emptyList(); - } - - @Override - @NonNull - public String readFile(@NonNull final File file) { - final VirtualFile vFile = LocalFileSystem.getInstance().findFileByIoFile(file); - if (vFile == null) { - LOG.debug("Cannot find file " + file.getPath() + " in the VFS"); - return ""; - } - - return ApplicationManager.getApplication().runReadAction(new Computable() { - @Nullable - @Override - public String compute() { - final PsiFile psiFile = PsiManager.getInstance(myProject).findFile(vFile); - if (psiFile == null) { - LOG.info("Cannot find file " + file.getPath() + " in the PSI"); - return null; - } - else { - return psiFile.getText(); - } - } - }); - } - - @Override - public void dispose() { - } - - @Nullable - @Override - public File getSdkHome() { - Module module = getModule(); - if (module != null) { - Sdk moduleSdk = ModuleRootManager.getInstance(module).getSdk(); - if (moduleSdk != null && moduleSdk.getSdkType() instanceof AndroidSdkType) { - String path = moduleSdk.getHomePath(); - if (path != null) { - File home = new File(path); - if (home.exists()) { - return home; - } - } - } - } - - File sdkHome = super.getSdkHome(); - if (sdkHome != null) { - return sdkHome; - } - - for (Module m : ModuleManager.getInstance(myProject).getModules()) { - Sdk moduleSdk = ModuleRootManager.getInstance(m).getSdk(); - if (moduleSdk != null) { - if (moduleSdk.getSdkType() instanceof AndroidSdkType) { - String path = moduleSdk.getHomePath(); - if (path != null) { - File home = new File(path); - if (home.exists()) { - return home; - } - } - } - } - } - - return IdeSdks.getInstance().getAndroidSdkPath(); - } - - @Nullable - @Override - public AndroidSdkHandler getSdk() { - if (mSdk == null) { - Module module = getModule(); - AndroidSdkHandler sdk = getLocalSdk(module); - if (sdk != null) { - mSdk = sdk; - } else { - for (Module m : ModuleManager.getInstance(myProject).getModules()) { - sdk = getLocalSdk(m); - if (sdk != null) { - mSdk = sdk; - break; - } - } - - if (mSdk == null) { - mSdk = super.getSdk(); - } - } - } - - return mSdk; - } - - @Nullable - private static AndroidSdkHandler getLocalSdk(@Nullable Module module) { - if (module != null) { - AndroidFacet facet = AndroidFacet.getInstance(module); - if (facet != null) { - AndroidSdkData sdkData = facet.getSdkData(); - if (sdkData != null) { - return sdkData.getSdkHandler(); - } - } - } - - return null; - } - - @Override - public boolean isGradleProject(com.android.tools.klint.detector.api.Project project) { - Module module = getModule(); - if (module != null) { - AndroidFacet facet = AndroidFacet.getInstance(module); - return facet != null && facet.requiresAndroidModel(); - } - return AndroidProjectInfo.getInstance(this.myProject).requiresAndroidModel(); - } - - // Overridden such that lint doesn't complain about missing a bin dir property in the event - // that no SDK is configured - @Override - @Nullable - public File findResource(@NonNull String relativePath) { - File top = getSdkHome(); - if (top != null) { - File file = new File(top, relativePath); - if (file.exists()) { - return file; - } - } - - return null; - } - - @Nullable private static volatile String ourSystemPath; - - @Override - @Nullable - public File getCacheDir(boolean create) { - final String path = ourSystemPath != null ? ourSystemPath : (ourSystemPath = PathUtil.getCanonicalPath(PathManager.getSystemPath())); - File lint = new File(path, "lint"); - if (create && !lint.exists()) { - lint.mkdirs(); - } - return lint; - } - - @Override - public boolean isProjectDirectory(@NonNull File dir) { - return new File(dir, Project.DIRECTORY_STORE_FOLDER).exists(); - } - - private static List ourReportedCustomIssues; - - private static void recordCustomIssue(@NonNull Issue issue) { - if (ourReportedCustomIssues == null) { - ourReportedCustomIssues = Lists.newArrayList(); - } else if (ourReportedCustomIssues.contains(issue)) { - return; - } - ourReportedCustomIssues.add(issue); - } - - @Nullable - public static Issue findCustomIssue(@NonNull String errorMessage) { - if (ourReportedCustomIssues != null) { - // We stash the original id into the error message such that we can - // find it later - int begin = errorMessage.lastIndexOf('['); - int end = errorMessage.lastIndexOf(']'); - if (begin < end && begin != -1) { - String id = errorMessage.substring(begin + 1, end); - for (Issue issue : ourReportedCustomIssues) { - if (id.equals(issue.getId())) { - return issue; - } - } - } - } - - return null; - } - - /** - * A lint client used for in-editor single file lint analysis (e.g. background checking while user is editing.) - *

- * Since this applies only to a given file and module, it can take some shortcuts over what the general - * {@link BatchLintClient} has to do. - * */ - private static class EditorLintClient extends IntellijLintClient { - private final State myState; - - public EditorLintClient(@NotNull State state) { - super(state.getModule().getProject()); - myState = state; - } - - @Nullable - @Override - protected Module getModule() { - return myState.getModule(); - } - - @NonNull - @Override - protected List getIssues() { - return myState.getIssues(); - } - - @Override - public void report(@NonNull Context context, - @NonNull Issue issue, - @NonNull Severity severity, - @NonNull Location location, - @NonNull String message, - @NonNull TextFormat format) { - if (location != null) { - final File file = location.getFile(); - final VirtualFile vFile = LocalFileSystem.getInstance().findFileByIoFile(file); - - if (context.getDriver().isCustomIssue(issue)) { - // Record original issue id in the message (such that we can find - // it later, in #findCustomIssue) - message += " [" + issue.getId() + "]"; - recordCustomIssue(issue); - issue = Severity.WARNING.compareTo(severity) <= 0 ? CUSTOM_WARNING : CUSTOM_ERROR; - } - - if (myState.getMainFile().equals(vFile)) { - 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; - - Severity configuredSeverity = severity != issue.getDefaultSeverity() ? severity : null; - message = format.convertTo(message, RAW); - myState.getProblems().add(new ProblemData(issue, message, textRange, configuredSeverity)); - } - - Location secondary = location.getSecondary(); - if (secondary != null && myState.getMainFile().equals(LocalFileSystem.getInstance().findFileByIoFile(secondary.getFile()))) { - reportSecondary(context, issue, severity, location, message, format); - } - } - } - - @Override - @NotNull - public String readFile(@NonNull File file) { - final VirtualFile vFile = LocalFileSystem.getInstance().findFileByIoFile(file); - - if (vFile == null) { - try { - return Files.toString(file, Charsets.UTF_8); - } catch (IOException ioe) { - LOG.debug("Cannot find file " + file.getPath() + " in the VFS"); - return ""; - } - } - final String content = getFileContent(vFile); - - if (content == null) { - LOG.info("Cannot find file " + file.getPath() + " in the PSI"); - return ""; - } - return content; - } - - @Nullable - private String getFileContent(final VirtualFile vFile) { - if (Comparing.equal(myState.getMainFile(), vFile)) { - return myState.getMainFileContent(); - } - - return ApplicationManager.getApplication().runReadAction(new Computable() { - @Nullable - @Override - public String compute() { - final Module module = myState.getModule(); - final Project project = module.getProject(); - if (project.isDisposed()) { - return null; - } - - final PsiFile psiFile = PsiManager.getInstance(project).findFile(vFile); - - if (psiFile == null) { - return null; - } - final Document document = PsiDocumentManager.getInstance(project).getDocument(psiFile); - - if (document != null) { - final DocumentListener listener = new DocumentListener() { - @Override - public void beforeDocumentChange(DocumentEvent event) { - } - - @Override - public void documentChanged(DocumentEvent event) { - myState.markDirty(); - } - }; - document.addDocumentListener(listener, EditorLintClient.this); - } - return psiFile.getText(); - } - }); - } - - @NonNull - @Override - public List getJavaSourceFolders(@NonNull com.android.tools.klint.detector.api.Project project) { - final VirtualFile[] sourceRoots = ModuleRootManager.getInstance(myState.getModule()).getSourceRoots(false); - final List result = new ArrayList(sourceRoots.length); - - for (VirtualFile root : sourceRoots) { - result.add(new File(root.getPath())); - } - return result; - } - - @NonNull - @Override - public List getResourceFolders(@NonNull com.android.tools.klint.detector.api.Project project) { - AndroidFacet facet = AndroidFacet.getInstance(myState.getModule()); - if (facet != null) { - return IntellijLintUtils.getResourceDirectories(facet); - } - return super.getResourceFolders(project); - } - } - - /** Lint client used for batch operations */ - private static class BatchLintClient extends IntellijLintClient { - private final Map>> myProblemMap; - private final AnalysisScope myScope; - private final List myIssues; - - public BatchLintClient(@NotNull Project project, - @NotNull Map>> problemMap, - @NotNull AnalysisScope scope, - @NotNull List issues) { - super(project); - myProblemMap = problemMap; - myScope = scope; - myIssues = issues; - } - - @Nullable - @Override - protected Module getModule() { - // No default module - return null; - } - - @NonNull - @Override - protected List getIssues() { - return myIssues; - } - - @Override - public void report(@NonNull Context context, - @NonNull Issue issue, - @NonNull Severity severity, - @NonNull Location location, - @NonNull String message, - @NonNull TextFormat format) { - VirtualFile vFile = null; - File file = null; - - if (location != null) { - file = location.getFile(); - vFile = LocalFileSystem.getInstance().findFileByIoFile(file); - } - else if (context.getProject() != null) { - final Module module = findModuleForLintProject(myProject, context.getProject()); - - if (module != null) { - final AndroidFacet facet = AndroidFacet.getInstance(module); - vFile = facet != null ? AndroidRootUtil.getPrimaryManifestFile(facet) : null; - - if (vFile != null) { - file = new File(vFile.getPath()); - } - } - } - - boolean inScope = vFile != null && myScope.contains(vFile); - // In analysis batch mode, the AnalysisScope contains a specific set of virtual - // files, not directories, so any errors reported against a directory will not - // be considered part of the scope and therefore won't be reported. Correct - // for this. - if (!inScope && vFile != null && vFile.isDirectory()) { - if (myScope.getScopeType() == AnalysisScope.PROJECT) { - inScope = true; - } else if (myScope.getScopeType() == AnalysisScope.MODULE || - myScope.getScopeType() == AnalysisScope.MODULES) { - final Module module = findModuleForLintProject(myProject, context.getProject()); - if (module != null && myScope.containsModule(module)) { - inScope = true; - } - } - } - - if (inScope) { - if (context.getDriver().isCustomIssue(issue)) { - // Record original issue id in the message (such that we can find - // it later, in #findCustomIssue) - message += " [" + issue.getId() + "]"; - recordCustomIssue(issue); - issue = Severity.WARNING.compareTo(severity) <= 0 ? CUSTOM_WARNING : CUSTOM_ERROR; - } - - file = new File(PathUtil.getCanonicalPath(file.getPath())); - - Map> file2ProblemList = myProblemMap.get(issue); - if (file2ProblemList == null) { - file2ProblemList = new HashMap>(); - myProblemMap.put(issue, file2ProblemList); - } - - List problemList = file2ProblemList.get(file); - if (problemList == null) { - problemList = new ArrayList(); - file2ProblemList.put(file, problemList); - } - - TextRange textRange = TextRange.EMPTY_RANGE; - - if (location != null) { - 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()); - } - } - Severity configuredSeverity = severity != issue.getDefaultSeverity() ? severity : null; - message = format.convertTo(message, RAW); - problemList.add(new ProblemData(issue, message, textRange, configuredSeverity)); - - if (location != null && location.getSecondary() != null) { - reportSecondary(context, issue, severity, location, message, format); - } - } - } - - @NonNull - @Override - public List getJavaSourceFolders(@NonNull com.android.tools.klint.detector.api.Project project) { - final Module module = findModuleForLintProject(myProject, project); - if (module == null) { - return Collections.emptyList(); - } - final VirtualFile[] sourceRoots = ModuleRootManager.getInstance(module).getSourceRoots(false); - final List result = new ArrayList(sourceRoots.length); - - for (VirtualFile root : sourceRoots) { - result.add(new File(root.getPath())); - } - return result; - } - - @NonNull - @Override - public List getResourceFolders(@NonNull com.android.tools.klint.detector.api.Project project) { - final Module module = findModuleForLintProject(myProject, project); - if (module != null) { - AndroidFacet facet = AndroidFacet.getInstance(module); - if (facet != null) { - return IntellijLintUtils.getResourceDirectories(facet); - } - } - return super.getResourceFolders(project); - } - } - - @Override - public boolean checkForSuppressComments() { - return false; - } - - @Override - public boolean supportsProjectResources() { - return true; - } - - @Nullable - @Override - public AbstractResourceRepository getProjectResources(com.android.tools.klint.detector.api.Project project, boolean includeDependencies) { - final Module module = findModuleForLintProject(myProject, project); - if (module != null) { - AndroidFacet facet = AndroidFacet.getInstance(module); - if (facet != null) { - return includeDependencies ? facet.getProjectResources(true) : facet.getModuleResources(true); - } - } - - return null; - } - - @Nullable - @Override - public URLConnection openConnection(@NonNull URL url) throws IOException { - return HttpConfigurable.getInstance().openConnection(url.toExternalForm()); - } - - @Override - public ClassLoader createUrlClassLoader(@NonNull URL[] urls, @NonNull ClassLoader parent) { - return UrlClassLoader.build().parent(parent).urls(urls).get(); - } - - @NonNull - @Override - public Location.Handle createResourceItemHandle(@NonNull ResourceItem item) { - XmlTag tag = LocalResourceRepository.getItemTag(myProject, item); - if (tag != null) { - ResourceFile source = item.getSource(); - assert source != null : item; - return new LocationHandle(source.getFile(), tag); - } - return super.createResourceItemHandle(item); - } - - @NonNull - @Override - public ResourceVisibilityLookup.Provider getResourceVisibilityProvider() { - Module module = getModule(); - if (module != null) { - AppResourceRepository appResources = AppResourceRepository.getAppResources(module, true); - if (appResources != null) { - ResourceVisibilityLookup.Provider provider = appResources.getResourceVisibilityProvider(); - if (provider != null) { - return provider; - } - } - } - return super.getResourceVisibilityProvider(); - } - - private static class LocationHandle implements Location.Handle, Computable { - private final File myFile; - private final XmlElement myNode; - private Object myClientData; - - public LocationHandle(File file, XmlElement node) { - myFile = file; - myNode = node; - } - - @NonNull - @Override - public Location resolve() { - if (!ApplicationManager.getApplication().isReadAccessAllowed()) { - return ApplicationManager.getApplication().runReadAction(this); - } - TextRange textRange = myNode.getTextRange(); - - // For elements, don't highlight the entire element range; instead, just - // highlight the element name - if (myNode instanceof XmlTag) { - String tag = ((XmlTag)myNode).getName(); - int index = myNode.getText().indexOf(tag); - if (index != -1) { - int start = textRange.getStartOffset() + index; - textRange = new TextRange(start, start + tag.length()); - } - } - - Position start = new DefaultPosition(-1, -1, textRange.getStartOffset()); - Position end = new DefaultPosition(-1, -1, textRange.getEndOffset()); - return Location.create(myFile, start, end); - } - - @Override - public Location compute() { - return resolve(); - } - - @Override - public void setClientData(@Nullable Object clientData) { - myClientData = clientData; - } - - @Override - @Nullable - public Object getClientData() { - return myClientData; - } - } -} diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintIssueRegistry.java.173 b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintIssueRegistry.java.173 deleted file mode 100644 index 2a47da66fb0..00000000000 --- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintIssueRegistry.java.173 +++ /dev/null @@ -1,107 +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.annotations.NonNull; -import com.android.tools.klint.checks.*; -import com.android.tools.klint.detector.api.*; - -import java.util.ArrayList; -import java.util.EnumSet; -import java.util.List; - -import static org.jetbrains.android.inspections.klint.IntellijLintProject.*; - -/** - * Custom version of the {@link BuiltinIssueRegistry}. This - * variation will filter the default issues and remove - * any issues that aren't usable inside IDEA (e.g. they - * rely on class files), and it will also replace the implementation - * of some issues with IDEA specific ones. - */ -public class IntellijLintIssueRegistry extends BuiltinIssueRegistry { - private static final Implementation DUMMY_IMPLEMENTATION = new Implementation(Detector.class, - EnumSet.noneOf(Scope.class)); - - private static final String CUSTOM_EXPLANATION = - "When custom (third-party) lint rules are integrated in the IDE, they are not available as native IDE inspections, " + - "so the explanation text (which must be statically registered by a plugin) is not available. As a workaround, run the " + - "lint target in Gradle instead; the HTML report will include full explanations."; - - /** - * Issue reported by a custom rule (3rd party detector). We need a placeholder issue to reference for inspections, which - * have to be registered statically (can't load these on the fly from custom jars the way lint does) - */ - @NonNull - public static final Issue CUSTOM_WARNING = Issue.create( - "CustomWarning", "Warning from Custom Rule", CUSTOM_EXPLANATION, Category.CORRECTNESS, 5, Severity.WARNING, DUMMY_IMPLEMENTATION); - - @NonNull - public static final Issue CUSTOM_ERROR = Issue.create( - "CustomError", "Error from Custom Rule", CUSTOM_EXPLANATION, Category.CORRECTNESS, 5, Severity.ERROR, DUMMY_IMPLEMENTATION); - - private static List ourFilteredIssues; - - public IntellijLintIssueRegistry() { - } - - @NonNull - @Override - public List getIssues() { - if (ourFilteredIssues == null) { - List sIssues = super.getIssues(); - List result = new ArrayList(sIssues.size()); - for (Issue issue : sIssues) { - Implementation implementation = issue.getImplementation(); - EnumSet scope = implementation.getScope(); - Class detectorClass = implementation.getDetectorClass(); - if (detectorClass == ApiDetector.class) { - //issue.setImplementation(IntellijApiDetector.IMPLEMENTATION); - } else if (detectorClass == ViewTypeDetector.class) { - issue.setImplementation(IntellijViewTypeDetector.IMPLEMENTATION); - } - 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)) { - //noinspection ConstantConditions - assert !SUPPORT_CLASS_FILES; // When enabled, adjust this to include class detector based issues - - boolean isOk = false; - for (EnumSet analysisScope : implementation.getAnalysisScopes()) { - if (!analysisScope.contains(Scope.CLASS_FILE) && - !analysisScope.contains(Scope.ALL_CLASS_FILES) && - !analysisScope.contains(Scope.JAVA_LIBRARIES)) { - isOk = true; - break; - } - } - if (!isOk) { - // Skip issue: not included inside the IDE - continue; - } - } - result.add(issue); - } - //noinspection AssignmentToStaticFieldFromInstanceMethod - ourFilteredIssues = result; - } - - return ourFilteredIssues; - } -} diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintProject.java.173 b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintProject.java.173 deleted file mode 100644 index a10e5a10f4b..00000000000 --- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintProject.java.173 +++ /dev/null @@ -1,1129 +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.annotations.NonNull; -import com.android.builder.model.*; -import com.android.sdklib.AndroidTargetHash; -import com.android.sdklib.AndroidVersion; -import com.android.tools.idea.gradle.project.model.AndroidModuleModel; -import com.android.tools.idea.gradle.util.GradleUtil; -import com.android.tools.idea.model.AndroidModel; -import com.android.tools.idea.model.AndroidModuleInfo; -import com.android.tools.klint.client.api.LintClient; -import com.android.tools.klint.detector.api.Project; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleManager; -import com.intellij.openapi.roots.*; -import com.intellij.openapi.util.Computable; -import com.intellij.openapi.util.Pair; -import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.vfs.LocalFileSystem; -import com.intellij.openapi.vfs.VfsUtilCore; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.ArrayUtil; -import com.intellij.util.graph.Graph; -import org.jetbrains.android.compiler.AndroidDexCompiler; -import org.jetbrains.android.facet.AndroidFacet; -import org.jetbrains.android.facet.AndroidRootUtil; -import org.jetbrains.android.facet.IdeaSourceProvider; -import org.jetbrains.android.sdk.AndroidPlatform; -import org.jetbrains.android.util.AndroidCommonUtils; -import org.jetbrains.android.util.AndroidUtils; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jps.android.model.impl.JpsAndroidModuleProperties; - -import java.io.File; -import java.util.*; - -import static com.android.SdkConstants.APPCOMPAT_LIB_ARTIFACT; -import static com.android.SdkConstants.SUPPORT_LIB_ARTIFACT; - -/** - * An {@linkplain IntellijLintProject} represents a lint project, which typically corresponds to a {@link Module}, - * but can also correspond to a library "project" such as an {@link AndroidLibrary}. - */ -class IntellijLintProject extends Project { - /** - * Whether we support running .class file checks. No class file checks are currently registered as inspections. - * Since IntelliJ doesn't perform background compilation (e.g. only parsing, so there are no bytecode checks) - * this might need some work before we enable it. - */ - public static final boolean SUPPORT_CLASS_FILES = false; - - protected AndroidVersion mMinSdkVersion; - protected AndroidVersion mTargetSdkVersion; - - IntellijLintProject(@NonNull LintClient client, - @NonNull File dir, - @NonNull File referenceDir) { - super(client, dir, referenceDir); - } - - /** Creates a set of projects for the given IntelliJ modules */ - @NonNull - public static List create(@NonNull IntellijLintClient client, @Nullable List files, @NonNull Module... modules) { - List projects = Lists.newArrayList(); - - Map projectMap = Maps.newHashMap(); - Map moduleMap = Maps.newHashMap(); - Map libraryMap = Maps.newHashMap(); - if (files != null && !files.isEmpty()) { - // Wrap list with a mutable list since we'll be removing the files as we see them - files = Lists.newArrayList(files); - } - for (Module module : modules) { - addProjects(client, module, files, moduleMap, libraryMap, projectMap, projects); - } - - client.setModuleMap(projectMap); - - if (projects.size() > 1) { - // Partition the projects up such that we only return projects that aren't - // included by other projects (e.g. because they are library projects) - Set roots = new HashSet(projects); - for (Project project : projects) { - roots.removeAll(project.getAllLibraries()); - } - return Lists.newArrayList(roots); - } else { - return projects; - } - } - - /** - * Creates a project for a single file. Also optionally creates a main project for the file, if applicable. - * - * @param client the lint client - * @param file the file to create a project for - * @param module the module to create a project for - * @return a project for the file, as well as a project (or null) for the main Android module - */ - @NonNull - public static Pair createForSingleFile(@NonNull IntellijLintClient client, @Nullable VirtualFile file, @NonNull Module module) { - // TODO: Can make this method even more lightweight: we don't need to initialize anything in the project (source paths etc) - // other than the metadata necessary for this file's type - LintModuleProject project = createModuleProject(client, module); - LintModuleProject main = null; - Map projectMap = Maps.newHashMap(); - if (project != null) { - project.setDirectLibraries(Collections.emptyList()); - if (file != null) { - project.addFile(VfsUtilCore.virtualToIoFile(file)); - } - projectMap.put(project, module); - - // Supply a main project too, such that when you for example edit a file in a Java library, - // and lint asks for getMainProject().getMinSdk(), we return the min SDK of an application - // using the library, not "1" (the default for a module without a manifest) - if (!project.isAndroidProject()) { - Module androidModule = findAndroidModule(module); - if (androidModule != null) { - main = createModuleProject(client, androidModule); - if (main != null) { - projectMap.put(main, androidModule); - main.setDirectLibraries(Collections.singletonList(project)); - } - } - } - } - client.setModuleMap(projectMap); - - //noinspection ConstantConditions - return Pair.create(project,main); - } - - /** Find an Android module that depends on this module; prefer app modules over library modules */ - @Nullable - private static Module findAndroidModule(@NonNull final Module module) { - // Search for dependencies of this module - Graph graph = ApplicationManager.getApplication().runReadAction(new Computable>() { - @Override - public Graph compute() { - com.intellij.openapi.project.Project project = module.getProject(); - if (project.isDisposed()) { - return null; - } - return ModuleManager.getInstance(project).moduleGraph(); - } - }); - - if (graph == null) { - return null; - } - - Set facets = Sets.newHashSet(); - HashSet seen = Sets.newHashSet(); - seen.add(module); - addAndroidModules(facets, seen, graph, module); - - // Prefer Android app modules - for (AndroidFacet facet : facets) { - if (!facet.isLibraryProject()) { - return facet.getModule(); - } - } - - // Resort to library modules if no app module depends directly on it - if (!facets.isEmpty()) { - return facets.iterator().next().getModule(); - } - - return null; - } - - private static void addAndroidModules(Set androidFacets, Set seen, Graph graph, Module module) { - Iterator iterator = graph.getOut(module); - while (iterator.hasNext()) { - Module dep = iterator.next(); - AndroidFacet facet = AndroidFacet.getInstance(dep); - if (facet != null) { - androidFacets.add(facet); - } - - if (!seen.contains(dep)) { - seen.add(dep); - addAndroidModules(androidFacets, seen, graph, dep); - } - } - } - - /** - * Recursively add lint projects for the given module, and any other module or library it depends on, and also - * populate the reverse maps so we can quickly map from a lint project to a corresponding module/library (used - * by the lint client - */ - private static void addProjects(@NonNull LintClient client, - @NonNull Module module, - @Nullable List files, - @NonNull Map moduleMap, - @NonNull Map libraryMap, - @NonNull Map projectMap, - @NonNull List projects) { - if (moduleMap.containsKey(module)) { - return; - } - - LintModuleProject project = createModuleProject(client, module); - - if (project == null) { - // It's possible for the module to *depend* on Android code, e.g. in a Gradle - // project there will be a top-level non-Android module - List dependentFacets = AndroidUtils.getAllAndroidDependencies(module, false); - for (AndroidFacet dependentFacet : dependentFacets) { - addProjects(client, dependentFacet.getModule(), files, moduleMap, libraryMap, projectMap, projects); - } - return; - } - - projects.add(project); - moduleMap.put(module, project); - projectMap.put(project, module); - - if (processFileFilter(module, files, project)) { - // No need to process dependencies when doing single file analysis - return; - } - - List dependencies = Lists.newArrayList(); - // No, this shouldn't use getAllAndroidDependencies; we may have non-Android dependencies that this won't include - // (e.g. Java-only modules) - List dependentFacets = AndroidUtils.getAllAndroidDependencies(module, true); - for (AndroidFacet dependentFacet : dependentFacets) { - Project p = moduleMap.get(dependentFacet.getModule()); - if (p != null) { - dependencies.add(p); - } else { - addProjects(client, dependentFacet.getModule(), files, moduleMap, libraryMap, projectMap, dependencies); - } - } - - AndroidFacet facet = AndroidFacet.getInstance(module); - if (facet != null) { - AndroidModuleModel androidModuleModel = AndroidModuleModel.get(facet); - if (androidModuleModel != null) { - addGradleLibraryProjects(client, files, libraryMap, projects, facet, androidModuleModel, project, projectMap, dependencies); - } - } - - project.setDirectLibraries(dependencies); - } - - /** - * Checks whether we have a file filter (e.g. a set of specific files to check in the module rather than all files, - * and if so, and if all the files have been found, returns true) - */ - private static boolean processFileFilter(@NonNull Module module, @Nullable List files, @NonNull LintModuleProject project) { - if (files != null && !files.isEmpty()) { - ListIterator iterator = files.listIterator(); - while (iterator.hasNext()) { - VirtualFile file = iterator.next(); - if (module.getModuleContentScope().accept(file)) { - project.addFile(VfsUtilCore.virtualToIoFile(file)); - iterator.remove(); - } - } - if (files.isEmpty()) { - // We're only scanning a subset of files (typically the current file in the editor); - // in that case, don't initialize all the libraries etc - project.setDirectLibraries(Collections.emptyList()); - return true; - } - } - return false; - } - - /** Creates a new module project */ - @Nullable - private static LintModuleProject createModuleProject(@NonNull LintClient client, @NonNull Module module) { - AndroidFacet facet = AndroidFacet.getInstance(module); - File dir; - - if (facet != null) { - final VirtualFile mainContentRoot = AndroidRootUtil.getMainContentRoot(facet); - - if (mainContentRoot == null) { - return null; - } - dir = new File(FileUtil.toSystemDependentName(mainContentRoot.getPath())); - } else { - String moduleDirPath = AndroidRootUtil.getModuleDirPath(module); - if (moduleDirPath == null) { - return null; - } - dir = new File(FileUtil.toSystemDependentName(moduleDirPath)); - } - LintModuleProject project = null; - if (facet == null) { - project = new LintModuleProject(client, dir, dir, module); - AndroidFacet f = findAndroidFacetInProject(module.getProject()); - if (f != null) { - project.mGradleProject = f.requiresAndroidModel(); - } - } - else if (facet.requiresAndroidModel()) { - AndroidModel androidModel = facet.getAndroidModel(); - if (androidModel instanceof AndroidModuleModel) { - project = new LintGradleProject(client, dir, dir, facet, (AndroidModuleModel)androidModel); - } else { - project = new LintAndroidModelProject(client, dir, dir, facet, androidModel); - } - } - else { - project = new LintAndroidProject(client, dir, dir, facet); - } - if (project != null) { - client.registerProject(dir, project); - } - return project; - } - - public static boolean hasAndroidModule(@NonNull com.intellij.openapi.project.Project project) { - return findAndroidFacetInProject(project) != null; - } - - @Nullable - private static AndroidFacet findAndroidFacetInProject(@NonNull com.intellij.openapi.project.Project project) { - ModuleManager moduleManager = ModuleManager.getInstance(project); - for (Module module : moduleManager.getModules()) { - AndroidFacet facet = AndroidFacet.getInstance(module); - if (facet != null) { - return facet; - } - } - - return null; - } - - /** Adds any gradle library projects to the dependency list */ - private static void addGradleLibraryProjects(@NonNull LintClient client, - @Nullable List files, - @NonNull Map libraryMap, - @NonNull List projects, - @NonNull AndroidFacet facet, - @NonNull AndroidModuleModel AndroidModuleModel, - @NonNull LintModuleProject project, - @NonNull Map projectMap, - @NonNull List dependencies) { - Collection libraries = AndroidModuleModel.getMainArtifact().getDependencies().getLibraries(); - for (AndroidLibrary library : libraries) { - Project p = libraryMap.get(library); - if (p == null) { - File dir = library.getFolder(); - p = new LintGradleLibraryProject(client, dir, dir, library); - libraryMap.put(library, p); - projectMap.put(p, facet.getModule()); - projects.add(p); - - if (files != null) { - VirtualFile libraryDir = LocalFileSystem.getInstance().findFileByIoFile(dir); - if (libraryDir != null) { - ListIterator iterator = files.listIterator(); - while (iterator.hasNext()) { - VirtualFile file = iterator.next(); - if (VfsUtilCore.isAncestor(libraryDir, file, false)) { - project.addFile(VfsUtilCore.virtualToIoFile(file)); - iterator.remove(); - } - } - } - if (files.isEmpty()) { - files = null; // No more work in other modules - } - } - } - dependencies.add(p); - } - } - - @Override - protected void initialize() { - // NOT calling super: super performs ADT/ant initialization. Here we want to use - // the gradle data instead - } - - protected static boolean depsDependsOn(@NonNull Project project, @NonNull String artifact) { - // Checks project dependencies only; used when there is no model - for (Project dependency : project.getDirectLibraries()) { - Boolean b = dependency.dependsOn(artifact); - if (b != null && b) { - return true; - } - } - - return false; - } - - private static class LintModuleProject extends IntellijLintProject { - private Module myModule; - - public void setDirectLibraries(List libraries) { - mDirectLibraries = libraries; - } - - private LintModuleProject(@NonNull LintClient client, @NonNull File dir, @NonNull File referenceDir, Module module) { - super(client, dir, referenceDir); - myModule = module; - } - - @Override - public boolean isAndroidProject() { - return false; - } - - @NonNull - @Override - public List getJavaSourceFolders() { - if (mJavaSourceFolders == null) { - VirtualFile[] sourceRoots = ModuleRootManager.getInstance(myModule).getSourceRoots(false); - List dirs = new ArrayList(sourceRoots.length); - for (VirtualFile root : sourceRoots) { - dirs.add(new File(root.getPath())); - } - mJavaSourceFolders = dirs; - } - - return mJavaSourceFolders; - } - - @NonNull - @Override - public List getTestSourceFolders() { - if (mTestSourceFolders == null) { - ModuleRootManager manager = ModuleRootManager.getInstance(myModule); - VirtualFile[] sourceRoots = manager.getSourceRoots(false); - VirtualFile[] sourceAndTestRoots = manager.getSourceRoots(true); - List dirs = new ArrayList(sourceAndTestRoots.length); - for (VirtualFile root : sourceAndTestRoots) { - if (!ArrayUtil.contains(root, sourceRoots)) { - dirs.add(new File(root.getPath())); - } - } - mTestSourceFolders = dirs; - } - return mTestSourceFolders; - } - - @NonNull - @Override - public List getJavaClassFolders() { - if (SUPPORT_CLASS_FILES) { - if (mJavaClassFolders == null) { - VirtualFile folder = AndroidDexCompiler.getOutputDirectoryForDex(myModule); - if (folder != null) { - mJavaClassFolders = Collections.singletonList(VfsUtilCore.virtualToIoFile(folder)); - } else { - mJavaClassFolders = Collections.emptyList(); - } - } - - return mJavaClassFolders; - } - - return Collections.emptyList(); - } - - @NonNull - @Override - public List getJavaLibraries(boolean includeProvided) { - if (SUPPORT_CLASS_FILES) { - if (mJavaLibraries == null) { - mJavaLibraries = Lists.newArrayList(); - - final OrderEntry[] entries = ModuleRootManager.getInstance(myModule).getOrderEntries(); - // loop in the inverse order to resolve dependencies on the libraries, so that if a library - // is required by two higher level libraries it can be inserted in the correct place - - for (int i = entries.length - 1; i >= 0; i--) { - final OrderEntry orderEntry = entries[i]; - if (orderEntry instanceof LibraryOrderEntry) { - LibraryOrderEntry libraryOrderEntry = (LibraryOrderEntry)orderEntry; - VirtualFile[] classes = libraryOrderEntry.getRootFiles(OrderRootType.CLASSES); - if (classes != null) { - for (VirtualFile file : classes) { - mJavaLibraries.add(VfsUtilCore.virtualToIoFile(file)); - } - } - } - } - } - - return mJavaLibraries; - } - - return Collections.emptyList(); - } - } - - /** Wraps an Android module */ - private static class LintAndroidProject extends LintModuleProject { - protected final AndroidFacet myFacet; - - private LintAndroidProject(@NonNull LintClient client, @NonNull File dir, @NonNull File referenceDir, @NonNull AndroidFacet facet) { - super(client, dir, referenceDir, facet.getModule()); - myFacet = facet; - - mGradleProject = false; - mLibrary = myFacet.isLibraryProject(); - - AndroidPlatform platform = AndroidPlatform.getInstance(myFacet.getModule()); - if (platform != null) { - mBuildSdk = platform.getApiLevel(); - } - } - - @Override - public boolean isAndroidProject() { - return true; - } - - @NonNull - @Override - public String getName() { - return myFacet.getModule().getName(); - } - - @Override - @NonNull - public List getManifestFiles() { - if (mManifestFiles == null) { - VirtualFile manifestFile = AndroidRootUtil.getPrimaryManifestFile(myFacet); - if (manifestFile != null) { - mManifestFiles = Collections.singletonList(VfsUtilCore.virtualToIoFile(manifestFile)); - } else { - mManifestFiles = Collections.emptyList(); - } - } - - return mManifestFiles; - } - - @NonNull - @Override - public List getProguardFiles() { - if (mProguardFiles == null) { - final JpsAndroidModuleProperties properties = myFacet.getProperties(); - - if (properties.RUN_PROGUARD) { - final List urls = properties.myProGuardCfgFiles; - - if (!urls.isEmpty()) { - mProguardFiles = new ArrayList(); - - for (String osPath : AndroidUtils.urlsToOsPaths(urls, null)) { - if (!osPath.contains(AndroidCommonUtils.SDK_HOME_MACRO)) { - mProguardFiles.add(new File(osPath)); - } - } - } - } - - if (mProguardFiles == null) { - mProguardFiles = Collections.emptyList(); - } - } - - return mProguardFiles; - } - - @NonNull - @Override - public List getResourceFolders() { - if (mResourceFolders == null) { - List folders = myFacet.getResourceFolderManager().getFolders(); - List dirs = Lists.newArrayListWithExpectedSize(folders.size()); - for (VirtualFile folder : folders) { - dirs.add(VfsUtilCore.virtualToIoFile(folder)); - } - mResourceFolders = dirs; - } - - return mResourceFolders; - } - - @Nullable - @Override - public Boolean dependsOn(@NonNull String artifact) { - if (SUPPORT_LIB_ARTIFACT.equals(artifact)) { - if (mSupportLib == null) { - final OrderEntry[] entries = ModuleRootManager.getInstance(myFacet.getModule()).getOrderEntries(); - libraries: - for (int i = entries.length - 1; i >= 0; i--) { - final OrderEntry orderEntry = entries[i]; - if (orderEntry instanceof LibraryOrderEntry) { - LibraryOrderEntry libraryOrderEntry = (LibraryOrderEntry)orderEntry; - VirtualFile[] classes = libraryOrderEntry.getRootFiles(OrderRootType.CLASSES); - if (classes != null) { - for (VirtualFile file : classes) { - if (file.getName().equals("android-support-v4.jar")) { - mSupportLib = true; - break libraries; - - } - } - } - } - } - if (mSupportLib == null) { - mSupportLib = depsDependsOn(this, artifact); - } - } - return mSupportLib; - } else if (APPCOMPAT_LIB_ARTIFACT.equals(artifact)) { - if (mSupportLib == null) { - final OrderEntry[] entries = ModuleRootManager.getInstance(myFacet.getModule()).getOrderEntries(); - libraries: - for (int i = entries.length - 1; i >= 0; i--) { - final OrderEntry orderEntry = entries[i]; - if (orderEntry instanceof LibraryOrderEntry) { - LibraryOrderEntry libraryOrderEntry = (LibraryOrderEntry)orderEntry; - VirtualFile[] classes = libraryOrderEntry.getRootFiles(OrderRootType.CLASSES); - if (classes != null) { - for (VirtualFile file : classes) { - if (file.getName().equals("appcompat-v7.jar")) { - mSupportLib = true; - break libraries; - - } - } - } - } - } - if (mSupportLib == null) { - mSupportLib = depsDependsOn(this, artifact); - } - } - return mSupportLib; - } else { - return super.dependsOn(artifact); - } - } - } - - private static class LintAndroidModelProject extends LintAndroidProject { - private final AndroidModel myAndroidModel; - - private LintAndroidModelProject( - @NonNull LintClient client, - @NonNull File dir, - @NonNull File referenceDir, - @NonNull AndroidFacet facet, - @NonNull AndroidModel androidModel) { - super(client, dir, referenceDir, facet); - myAndroidModel = androidModel; - } - - @Nullable - @Override - public String getPackage() { - String manifestPackage = super.getPackage(); - // For now, lint only needs the manifest package; not the potentially variant specific - // package. As part of the Gradle work on the Lint API we should make two separate - // package lookup methods -- one for the manifest package, one for the build package - if (manifestPackage != null) { - return manifestPackage; - } - - return myAndroidModel.getApplicationId(); - } - - @NonNull - @Override - public AndroidVersion getMinSdkVersion() { - if (mMinSdkVersion == null) { - mMinSdkVersion = AndroidModuleInfo.get(myFacet).getMinSdkVersion(); - } - return mMinSdkVersion; - } - - @NonNull - @Override - public AndroidVersion getTargetSdkVersion() { - if (mTargetSdkVersion == null) { - mTargetSdkVersion = AndroidModuleInfo.get(myFacet).getTargetSdkVersion(); - } - - return mTargetSdkVersion; - } - } - - private static class LintGradleProject extends LintAndroidModelProject { - private final AndroidModuleModel myAndroidModuleModel; - - /** - * Creates a new Project. Use one of the factory methods to create. - */ - private LintGradleProject( - @NonNull LintClient client, - @NonNull File dir, - @NonNull File referenceDir, - @NonNull AndroidFacet facet, - @NonNull AndroidModuleModel AndroidModuleModel) { - super(client, dir, referenceDir, facet, AndroidModuleModel); - mGradleProject = true; - mMergeManifests = true; - myAndroidModuleModel = AndroidModuleModel; - } - - @NonNull - @Override - public List getManifestFiles() { - if (mManifestFiles == null) { - mManifestFiles = Lists.newArrayList(); - File mainManifest = myFacet.getMainSourceProvider().getManifestFile(); - if (mainManifest.exists()) { - mManifestFiles.add(mainManifest); - } - - List flavorSourceProviders = myAndroidModuleModel.getFlavorSourceProviders(); - if (flavorSourceProviders != null) { - for (SourceProvider provider : flavorSourceProviders) { - File manifestFile = provider.getManifestFile(); - if (manifestFile.exists()) { - mManifestFiles.add(manifestFile); - } - } - } - - SourceProvider multiProvider = myAndroidModuleModel.getMultiFlavorSourceProvider(); - if (multiProvider != null) { - File manifestFile = multiProvider.getManifestFile(); - if (manifestFile.exists()) { - mManifestFiles.add(manifestFile); - } - } - - SourceProvider buildTypeSourceProvider = myAndroidModuleModel.getBuildTypeSourceProvider(); - if (buildTypeSourceProvider != null) { - File manifestFile = buildTypeSourceProvider.getManifestFile(); - if (manifestFile.exists()) { - mManifestFiles.add(manifestFile); - } - } - - SourceProvider variantProvider = myAndroidModuleModel.getVariantSourceProvider(); - if (variantProvider != null) { - File manifestFile = variantProvider.getManifestFile(); - if (manifestFile.exists()) { - mManifestFiles.add(manifestFile); - } - } - } - - return mManifestFiles; - } - - @NonNull - @Override - public List getAssetFolders() { - if (mAssetFolders == null) { - mAssetFolders = Lists.newArrayList(); - for (SourceProvider provider : IdeaSourceProvider.getAllSourceProviders(myFacet)) { - Collection dirs = provider.getAssetsDirectories(); - for (File dir : dirs) { - if (dir.exists()) { // model returns path whether or not it exists - mAssetFolders.add(dir); - } - } - } - } - - return mAssetFolders; - } - - @NonNull - @Override - public List getProguardFiles() { - if (mProguardFiles == null) { - if (myFacet.requiresAndroidModel()) { - // TODO: b/22928250 - AndroidModuleModel androidModel = AndroidModuleModel.get(myFacet); - if (androidModel != null) { - ProductFlavor flavor = androidModel.getAndroidProject().getDefaultConfig().getProductFlavor(); - mProguardFiles = Lists.newArrayList(); - for (File file : flavor.getProguardFiles()) { - if (file.exists()) { - mProguardFiles.add(file); - } - } - try { - for (File file : flavor.getConsumerProguardFiles()) { - if (file.exists()) { - mProguardFiles.add(file); - } - } - } catch (Throwable t) { - // On some models, this threw - // org.gradle.tooling.model.UnsupportedMethodException: Unsupported method: BaseConfig.getConsumerProguardFiles(). - // Playing it safe for a while. - } - } - } - - if (mProguardFiles == null) { - mProguardFiles = Collections.emptyList(); - } - } - - return mProguardFiles; - } - - @NonNull - @Override - public List getJavaClassFolders() { - if (SUPPORT_CLASS_FILES) { - if (mJavaClassFolders == null) { - // Overridden because we don't synchronize the gradle output directory to - // the AndroidDexCompiler settings the way java source roots are mapped into - // the module content root settings - File dir = myAndroidModuleModel.getMainArtifact().getClassesFolder(); - if (dir != null) { - mJavaClassFolders = Collections.singletonList(dir); - } else { - mJavaClassFolders = Collections.emptyList(); - } - } - - return mJavaClassFolders; - } - - return Collections.emptyList(); - } - - private static boolean sProvidedAvailable = true; - - @NonNull - @Override - public List getJavaLibraries(boolean includeProvided) { - if (SUPPORT_CLASS_FILES) { - if (mJavaLibraries == null) { - if (myFacet.requiresAndroidModel() && myFacet.getAndroidModel() != null) { - Collection libs = myAndroidModuleModel.getMainArtifact().getDependencies().getJavaLibraries(); - mJavaLibraries = Lists.newArrayListWithExpectedSize(libs.size()); - for (JavaLibrary lib : libs) { - if (!includeProvided) { - if (sProvidedAvailable) { - // Method added in 1.4-rc1; gracefully handle running with - // older plugins - try { - if (lib.isProvided()) { - continue; - } - } - catch (Throwable t) { - //noinspection AssignmentToStaticFieldFromInstanceMethod - sProvidedAvailable = false; // don't try again - } - } - } - - File jar = lib.getJarFile(); - if (jar.exists()) { - mJavaLibraries.add(jar); - } - } - } else { - mJavaLibraries = super.getJavaLibraries(includeProvided); - } - } - return mJavaLibraries; - } - - return Collections.emptyList(); - } - - @Override - public int getBuildSdk() { - // TODO: b/22928250 - AndroidModuleModel androidModel = AndroidModuleModel.get(myFacet); - if (androidModel != null) { - String compileTarget = androidModel.getAndroidProject().getCompileTarget(); - AndroidVersion version = AndroidTargetHash.getPlatformVersion(compileTarget); - if (version != null) { - return version.getFeatureLevel(); - } - } - - AndroidPlatform platform = AndroidPlatform.getInstance(myFacet.getModule()); - if (platform != null) { - return platform.getApiVersion().getFeatureLevel(); - } - - return super.getBuildSdk(); - } - - @Nullable - @Override - public AndroidProject getGradleProjectModel() { - // TODO: b/22928250 - AndroidModuleModel androidModel = AndroidModuleModel.get(myFacet); - if (androidModel != null) { - return androidModel.getAndroidProject(); - } - - return null; - } - - @Nullable - @Override - public Variant getCurrentVariant() { - // TODO: b/22928250 - AndroidModuleModel androidModel = AndroidModuleModel.get(myFacet); - if (androidModel != null) { - return androidModel.getSelectedVariant(); - } - - return null; - } - - @Nullable - @Override - public AndroidLibrary getGradleLibraryModel() { - return null; - } - - @Nullable - @Override - public Boolean dependsOn(@NonNull String artifact) { - // TODO: b/22928250 - AndroidModuleModel androidModel = AndroidModuleModel.get(myFacet); - - if (SUPPORT_LIB_ARTIFACT.equals(artifact)) { - if (mSupportLib == null) { - if (myFacet.requiresAndroidModel() && myFacet.getAndroidModel() != null) { - mSupportLib = GradleUtil.dependsOn(androidModel, artifact); - } else { - mSupportLib = depsDependsOn(this, artifact); - } - } - return mSupportLib; - } else if (APPCOMPAT_LIB_ARTIFACT.equals(artifact)) { - if (mAppCompat == null) { - if (myFacet.requiresAndroidModel() && myFacet.getAndroidModel() != null) { - mAppCompat = GradleUtil.dependsOn(androidModel, artifact); - } else { - mAppCompat = depsDependsOn(this, artifact); - } - } - return mAppCompat; - } else { - // Some other (not yet directly cached result) - if (myFacet.requiresAndroidModel() && myFacet.getAndroidModel() != null - && GradleUtil.dependsOn(androidModel, artifact)) { - return true; - } - - return super.dependsOn(artifact); - } - } - } - - private static class LintGradleLibraryProject extends IntellijLintProject { - private final AndroidLibrary myLibrary; - - private LintGradleLibraryProject(@NonNull LintClient client, - @NonNull File dir, - @NonNull File referenceDir, - @NonNull AndroidLibrary library) { - super(client, dir, referenceDir); - myLibrary = library; - - mLibrary = true; - mMergeManifests = true; - mReportIssues = false; - mGradleProject = true; - mDirectLibraries = Collections.emptyList(); - } - - @NonNull - @Override - public List getManifestFiles() { - if (mManifestFiles == null) { - File manifest = myLibrary.getManifest(); - if (manifest.exists()) { - mManifestFiles = Collections.singletonList(manifest); - } else { - mManifestFiles = Collections.emptyList(); - } - } - - return mManifestFiles; - } - - @NonNull - @Override - public List getProguardFiles() { - if (mProguardFiles == null) { - File proguardRules = myLibrary.getProguardRules(); - if (proguardRules.exists()) { - mProguardFiles = Collections.singletonList(proguardRules); - } else { - mProguardFiles = Collections.emptyList(); - } - } - - return mProguardFiles; - } - - @NonNull - @Override - public List getResourceFolders() { - if (mResourceFolders == null) { - File folder = myLibrary.getResFolder(); - if (folder.exists()) { - mResourceFolders = Collections.singletonList(folder); - } else { - mResourceFolders = Collections.emptyList(); - } - } - - return mResourceFolders; - } - - @NonNull - @Override - public List getJavaSourceFolders() { - return Collections.emptyList(); - } - - @NonNull - @Override - public List getJavaClassFolders() { - return Collections.emptyList(); - } - - private static boolean sOptionalAvailable = true; - - @NonNull - @Override - public List getJavaLibraries(boolean includeProvided) { - if (SUPPORT_CLASS_FILES) { - if (!includeProvided) { - if (sOptionalAvailable) { - // Method added in 1.4-rc1; gracefully handle running with - // older plugins - try { - if (myLibrary.isOptional()) { - return Collections.emptyList(); - } - } - catch (Throwable t) { - //noinspection AssignmentToStaticFieldFromInstanceMethod - sOptionalAvailable = false; // don't try again - } - } - } - - if (mJavaLibraries == null) { - mJavaLibraries = Lists.newArrayList(); - File jarFile = myLibrary.getJarFile(); - if (jarFile.exists()) { - mJavaLibraries.add(jarFile); - } - - for (File local : myLibrary.getLocalJars()) { - if (local.exists()) { - mJavaLibraries.add(local); - } - } - } - - return mJavaLibraries; - } - - return Collections.emptyList(); - } - - @Nullable - @Override - public AndroidProject getGradleProjectModel() { - return null; - } - - @Nullable - @Override - public AndroidLibrary getGradleLibraryModel() { - return myLibrary; - } - - @Nullable - @Override - public Boolean dependsOn(@NonNull String artifact) { - if (SUPPORT_LIB_ARTIFACT.equals(artifact)) { - if (mSupportLib == null) { - mSupportLib = GradleUtil.dependsOn(myLibrary, artifact, true); - } - return mSupportLib; - } else if (APPCOMPAT_LIB_ARTIFACT.equals(artifact)) { - if (mAppCompat == null) { - mAppCompat = GradleUtil.dependsOn(myLibrary, artifact, true); - } - return mAppCompat; - } else { - // Some other (not yet directly cached result) - if (GradleUtil.dependsOn(myLibrary, artifact, true)) { - return true; - } - - return super.dependsOn(artifact); - } - } - } -} diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintRequest.java.173 b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintRequest.java.173 deleted file mode 100644 index 13b340d72e6..00000000000 --- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintRequest.java.173 +++ /dev/null @@ -1,122 +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.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.tools.klint.client.api.LintRequest; -import com.android.tools.klint.detector.api.Scope; -import com.intellij.openapi.module.Module; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Pair; -import com.intellij.openapi.vfs.VirtualFile; - -import java.io.File; -import java.util.Collection; -import java.util.Collections; -import java.util.EnumSet; -import java.util.List; - -public class IntellijLintRequest extends LintRequest { - @NonNull private final Project myProject; - @NonNull private final List myModules; - @NonNull private final IntellijLintClient mLintClient; - @Nullable private final List myFileList; - @Nullable private com.android.tools.klint.detector.api.Project myMainProject; - private final boolean myIncremental; - - /** - * Creates a new {@linkplain IntellijLintRequest}. - * @param client the client - * @param project the project where lint is run - * @param fileList an optional list of specific files to check, normally null - * @param modules the set of modules to be checked (or containing the files) - * @param incremental true if this is an incremental (current editor) analysis - */ - public IntellijLintRequest(@NonNull IntellijLintClient client, - @NonNull Project project, - @Nullable List fileList, - @NonNull List modules, - boolean incremental) { - super(client, Collections.emptyList()); - mLintClient = client; - myProject = project; - myModules = modules; - myFileList = fileList; - myIncremental = incremental; - } - - @NonNull - Project getProject() { - return myProject; - } - - @Nullable - @Override - public EnumSet getScope() { - if (mScope == null) { - Collection projects = getProjects(); - if (projects != null) { - mScope = Scope.infer(projects); - - //noinspection ConstantConditions - 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); - mScope.remove(Scope.ALL_CLASS_FILES); - mScope.remove(Scope.JAVA_LIBRARIES); - } - } - } - - return mScope; - } - - @Nullable - @Override - public Collection getProjects() { - if (mProjects == null) { - if (myIncremental && myFileList != null && myFileList.size() == 1 && myModules.size() == 1) { - Pair pair = - IntellijLintProject.createForSingleFile(mLintClient, myFileList.get(0), myModules.get(0)); - mProjects = pair.first != null ? Collections.singletonList(pair.first) - : Collections.emptyList(); - myMainProject = pair.second; - } else if (!myModules.isEmpty()) { - // Make one project for each module, mark each one as a library, - // and add projects for the gradle libraries and set error reporting to - // false on those - //mProjects = computeProjects() - mProjects = IntellijLintProject.create(mLintClient, myFileList, myModules.toArray(new Module[myModules.size()])); - } else { - mProjects = super.getProjects(); - } - } - - return mProjects; - } - - @NonNull - @Override - public com.android.tools.klint.detector.api.Project getMainProject(@NonNull com.android.tools.klint.detector.api.Project project) { - if (myMainProject != null) { - return myMainProject; - } - return super.getMainProject(project); - } -} diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintUtils.java.173 b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintUtils.java.173 deleted file mode 100644 index 891a0477566..00000000000 --- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintUtils.java.173 +++ /dev/null @@ -1,485 +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.SdkConstants; -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.builder.model.SourceProvider; -import com.android.tools.idea.AndroidPsiUtils; -import com.android.tools.idea.model.AndroidModel; -import com.android.tools.klint.client.api.LintRequest; -import com.android.tools.klint.detector.api.*; -import com.google.common.base.Splitter; -import com.intellij.debugger.engine.JVMNameUtil; -import com.intellij.ide.util.JavaAnonymousClassesHelper; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.TextRange; -import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.vfs.VfsUtil; -import com.intellij.openapi.vfs.VfsUtilCore; -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.*; -import org.jetbrains.uast.psi.UElementWithLocation; -import org.jetbrains.uast.util.UastExpressionUtils; - -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} - */ -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"; - - /** - * Gets the location of the given element - * - * @param file the file containing the location - * @param element the element to look up the location for - * @return the location of the given element - */ - @NonNull - 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); - - if (element instanceof PsiClass) { - // Point to the name rather than the beginning of the javadoc - PsiClass clz = (PsiClass)element; - PsiIdentifier nameIdentifier = clz.getNameIdentifier(); - if (nameIdentifier != null) { - element = nameIdentifier; - } - } - - TextRange textRange = element.getTextRange(); - Position start = new DefaultPosition(-1, -1, textRange.getStartOffset()); - Position end = new DefaultPosition(-1, -1, textRange.getEndOffset()); - return Location.create(file, start, end); - } - - /** - * Gets the location of the given element - * - * @param file the file containing the location - * @param element the element to look up the location for - * @return the location of the given element - */ - @NonNull - public static Location getUastLocation(@NonNull File file, @NonNull UElement element) { - //noinspection ConstantConditions - PsiFile containingPsiFile = UastUtils.getContainingFile(element).getPsi(); - assert containingPsiFile.getVirtualFile() == null - || FileUtil.filesEqual(VfsUtilCore.virtualToIoFile(containingPsiFile.getVirtualFile()), file); - - if (element instanceof UClass) { - // Point to the name rather than the beginning of the javadoc - UClass clz = (UClass)element; - UElement nameIdentifier = clz.getUastAnchor(); - if (nameIdentifier != null) { - element = nameIdentifier; - } - } - - TextRange textRange = null; - PsiElement psi = element.getPsi(); - if (psi != null) { - textRange = psi.getTextRange(); - } else if (element instanceof UElementWithLocation) { - UElementWithLocation elementWithLocation = (UElementWithLocation) element; - textRange = new TextRange( - elementWithLocation.getStartOffset(), - elementWithLocation.getEndOffset()); - } - - if (textRange == null) { - return Location.NONE; - } - - 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 Context} - * - * @param context the context to look up the file for - * @return the corresponding {@link PsiFile}, or null - */ - @Nullable - public static PsiFile getPsiFile(@NonNull Context context) { - VirtualFile file = VfsUtil.findFileByIoFile(context.file, false); - if (file == null) { - return null; - } - LintRequest request = context.getDriver().getRequest(); - Project project = ((IntellijLintRequest)request).getProject(); - if (project.isDisposed()) { - return null; - } - return AndroidPsiUtils.getPsiFileSafely(project, file); - } - - /** - * 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 Issue issue) { - // Search upwards for suppress lint and suppress warnings annotations - //noinspection ConstantConditions - 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 != null && (fqcn.equals(SUPPRESS_LINT_FQCN) || fqcn.equals(SUPPRESS_WARNINGS_FQCN))) { - PsiAnnotationParameterList parameterList = annotation.getParameterList(); - for (PsiNameValuePair pair : parameterList.getAttributes()) { - PsiAnnotationMemberValue v = pair.getValue(); - if (v instanceof PsiLiteral) { - PsiLiteral literal = (PsiLiteral)v; - Object value = literal.getValue(); - if (value instanceof String) { - if (isSuppressed(issue, (String) value)) { - return true; - } - } - } 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) { - if (isSuppressed(issue, (String) value)) { - return true; - } - } - } - } - } else if (v != null) { - // This shouldn't be necessary - String text = v.getText().trim(); // UGH! Find better way to access value! - if (!text.isEmpty() && isSuppressed(issue, text)) { - return true; - } - } - } - } - } - } - } - element = element.getParent(); - } - - return false; - } - - /** - * 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 UElement element, @NonNull UFile file, @NonNull Issue issue) { - // Search upwards for suppress lint and suppress warnings annotations - //noinspection ConstantConditions - while (element != null && element != file) { // otherwise it will keep going into directories! - if (element instanceof UAnnotated) { - UAnnotated annotated = (UAnnotated)element; - for (UAnnotation annotation : annotated.getAnnotations()) { - String fqcn = annotation.getQualifiedName(); - if (fqcn != null && (fqcn.equals(SUPPRESS_LINT_FQCN) || fqcn.equals(SUPPRESS_WARNINGS_FQCN))) { - List parameterList = annotation.getAttributeValues(); - for (UNamedExpression pair : parameterList) { - UExpression v = pair.getExpression(); - if (v instanceof ULiteralExpression) { - ULiteralExpression literal = (ULiteralExpression)v; - Object value = literal.getValue(); - if (value instanceof String) { - if (isSuppressed(issue, (String) value)) { - return true; - } - } - } else if (UastExpressionUtils.isArrayInitializer(v)) { - UCallExpression mv = (UCallExpression)v; - for (UExpression mmv : mv.getValueArguments()) { - if (mmv instanceof ULiteralExpression) { - ULiteralExpression literal = (ULiteralExpression) mmv; - Object value = literal.getValue(); - if (value instanceof String) { - if (isSuppressed(issue, (String) value)) { - return true; - } - } - } - } - } - } - } - } - } - element = element.getUastParent(); - } - - return false; - } - - /** - * Returns true if the given issue is suppressed by the given suppress string; this - * is typically the same as the issue id, but is allowed to not match case sensitively, - * and is allowed to be a comma separated list, and can be the string "all" - * - * @param issue the issue id to match - * @param string the suppress string -- typically the id, or "all", or a comma separated list of ids - * @return true if the issue is suppressed by the given string - */ - private static boolean isSuppressed(@NonNull Issue issue, @NonNull String string) { - for (String id : Splitter.on(',').trimResults().split(string)) { - if (id.equals(issue.getId()) || id.equals(SUPPRESS_ALL)) { - return true; - } - } - - 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 ClassContext#getInternalName(String) - */ - @Nullable - public static String getInternalName(@NonNull PsiClass psiClass) { - if (psiClass instanceof PsiAnonymousClass) { - PsiClass parent = PsiTreeUtil.getParentOfType(psiClass, PsiClass.class); - if (parent != null) { - String internalName = getInternalName(parent); - if (internalName == null) { - return null; - } - return internalName + JavaAnonymousClassesHelper.getName((PsiAnonymousClass)psiClass); - } - } - String sig = ClassUtil.getJVMClassName(psiClass); - if (sig == null) { - String qualifiedName = psiClass.getQualifiedName(); - if (qualifiedName != null) { - return ClassContext.getInternalName(qualifiedName); - } - return null; - } else if (sig.indexOf('.') != -1) { - // Workaround -- ClassUtil doesn't treat this correctly! - // .replace('.', '/'); - sig = ClassContext.getInternalName(sig); - } - return sig; - } - - /** - * 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 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 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; - } - - /** Returns the resource directories to use for the given module */ - @NotNull - public static List getResourceDirectories(@NotNull AndroidFacet facet) { - if (facet.requiresAndroidModel()) { - AndroidModel androidModel = facet.getAndroidModel(); - if (androidModel != null) { - List resDirectories = new ArrayList(); - List sourceProviders = androidModel.getActiveSourceProviders(); - for (SourceProvider provider : sourceProviders) { - for (File file : provider.getResDirectories()) { - if (file.isDirectory()) { - resDirectories.add(file); - } - } - } - return resDirectories; - } - } - return new ArrayList(facet.getMainSourceProvider().getResDirectories()); - } -} diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijViewTypeDetector.java.173 b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijViewTypeDetector.java.173 deleted file mode 100644 index 287fe0ef081..00000000000 --- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijViewTypeDetector.java.173 +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2014 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.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.ide.common.res2.AbstractResourceRepository; -import com.android.ide.common.res2.ResourceItem; -import com.android.tools.idea.res.LocalResourceRepository; -import com.android.tools.klint.checks.ViewTypeDetector; -import com.android.tools.klint.detector.api.Context; -import com.android.tools.klint.detector.api.Implementation; -import com.android.tools.klint.detector.api.Scope; - -import java.util.Collection; -import java.util.Collections; - -public class IntellijViewTypeDetector extends ViewTypeDetector { - static final Implementation IMPLEMENTATION = new Implementation( - IntellijViewTypeDetector.class, - Scope.JAVA_FILE_SCOPE); - - @Nullable - @Override - protected Collection getViewTags(@NonNull Context context, @NonNull ResourceItem item) { - AbstractResourceRepository projectResources = context.getClient().getProjectResources(context.getMainProject(), true); - assert projectResources instanceof LocalResourceRepository : projectResources; - LocalResourceRepository repository = (LocalResourceRepository)projectResources; - String viewTag = repository.getViewTag(item); - if (viewTag != null) { - return Collections.singleton(viewTag); - } - - return super.getViewTags(context, item); - } -} diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/LintInspectionDescriptionLinkHandler.java.173 b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/LintInspectionDescriptionLinkHandler.java.173 deleted file mode 100644 index dd910a3ff8c..00000000000 --- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/LintInspectionDescriptionLinkHandler.java.173 +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2014 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.BuiltinIssueRegistry; -import com.android.tools.klint.detector.api.Issue; -import com.android.tools.klint.detector.api.TextFormat; -import com.intellij.codeInsight.highlighting.TooltipLinkHandler; -import com.intellij.codeInspection.InspectionProfile; -import com.intellij.codeInspection.InspectionsBundle; -import com.intellij.codeInspection.ex.InspectionToolWrapper; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; -import com.intellij.profile.codeInspection.InspectionProfileManager; -import com.intellij.psi.PsiDocumentManager; -import com.intellij.psi.PsiFile; -import org.jetbrains.annotations.NotNull; - -public class LintInspectionDescriptionLinkHandler extends TooltipLinkHandler { - private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.inspections.lint.LintInspectionDescriptionLinkHandler"); - - @Override - public String getDescription(@NotNull final String refSuffix, @NotNull final Editor editor) { - final Project project = editor.getProject(); - if (project == null) { - LOG.error(editor); - return null; - } - - final PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); - if (file == null) { - return null; - } - - Issue issue = new BuiltinIssueRegistry().getIssue(refSuffix); - if (issue != null) { - String html = issue.getExplanation(TextFormat.HTML); - // IntelliJ seems to treat newlines in the HTML as needing to also be converted to
(whereas - // Lint includes these for HTML readability but they shouldn't add additional lines since it has - // already added
as well) so strip these out - html = html.replace("\n", ""); - return html; - } - - // TODO: What about custom registries for custom rules, AARs etc? - - LOG.warn("No description for inspection '" + refSuffix + "'"); - return InspectionsBundle.message("inspection.tool.description.under.construction.text"); - } -} \ No newline at end of file diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/ParcelableQuickFix.kt.173 b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/ParcelableQuickFix.kt.173 deleted file mode 100644 index e938134332f..00000000000 --- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/ParcelableQuickFix.kt.173 +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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.android.inspections.klint - -import com.intellij.psi.PsiElement -import com.intellij.psi.util.PsiTreeUtil -import org.jetbrains.android.util.AndroidBundle -import org.jetbrains.kotlin.android.canAddParcelable -import org.jetbrains.kotlin.android.implementParcelable -import org.jetbrains.kotlin.android.isParcelize -import org.jetbrains.kotlin.psi.KtClass - - -class ParcelableQuickFix : AndroidLintQuickFix { - override fun apply(startElement: PsiElement, endElement: PsiElement, context: AndroidQuickfixContexts.Context) { - startElement.getTargetClass()?.implementParcelable() - } - - override fun isApplicable(startElement: PsiElement, endElement: PsiElement, contextType: AndroidQuickfixContexts.ContextType): Boolean { - val targetClass = startElement.getTargetClass() ?: return false - return targetClass.canAddParcelable() && !targetClass.isParcelize() - } - - override fun getName(): String = AndroidBundle.message("implement.parcelable.intention.text") - - private fun PsiElement.getTargetClass(): KtClass? = PsiTreeUtil.getParentOfType(this, KtClass::class.java, false) -} \ No newline at end of file diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/ProblemData.java.173 b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/ProblemData.java.173 deleted file mode 100644 index 33abc54e177..00000000000 --- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/ProblemData.java.173 +++ /dev/null @@ -1,41 +0,0 @@ -package org.jetbrains.android.inspections.klint; - -import com.android.tools.klint.detector.api.Issue; -import com.android.tools.klint.detector.api.Severity; -import com.intellij.openapi.util.TextRange; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class ProblemData { - private final Issue myIssue; - private final String myMessage; - private final TextRange myTextRange; - private final Severity myConfiguredSeverity; - - ProblemData(@NotNull Issue issue, @NotNull String message, @NotNull TextRange textRange, @Nullable Severity configuredSeverity) { - myIssue = issue; - myTextRange = textRange; - myMessage = message; - myConfiguredSeverity = configuredSeverity; - } - - @NotNull - public Issue getIssue() { - return myIssue; - } - - @NotNull - public TextRange getTextRange() { - return myTextRange; - } - - @NotNull - public String getMessage() { - return myMessage; - } - - @Nullable - public Severity getConfiguredSeverity() { - return myConfiguredSeverity; - } -} diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/State.java.173 b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/State.java.173 deleted file mode 100644 index b122b494b16..00000000000 --- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/State.java.173 +++ /dev/null @@ -1,63 +0,0 @@ -package org.jetbrains.android.inspections.klint; - -import com.android.tools.klint.detector.api.Issue; -import com.intellij.openapi.module.Module; -import com.intellij.openapi.vfs.VirtualFile; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.List; - -public class State { - private final Module myModule; - private final VirtualFile myMainFile; - - private final String myMainFileContent; - private final List myProblems = new ArrayList(); - private final List myIssues; - - private volatile boolean myDirty; - - State(@NotNull Module module, - @NotNull VirtualFile mainFile, - @NotNull String mainFileContent, - @NotNull List issues) { - myModule = module; - myMainFile = mainFile; - myMainFileContent = mainFileContent; - myIssues = issues; - } - - @NotNull - public VirtualFile getMainFile() { - return myMainFile; - } - - @NotNull - public String getMainFileContent() { - return myMainFileContent; - } - - public void markDirty() { - myDirty = true; - } - - public boolean isDirty() { - return myDirty; - } - - @NotNull - public Module getModule() { - return myModule; - } - - @NotNull - public List getProblems() { - return myProblems; - } - - @NotNull - public List getIssues() { - return myIssues; - } -} diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/SuppressLintIntentionAction.kt.173 b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/SuppressLintIntentionAction.kt.173 deleted file mode 100644 index 0d8d7501612..00000000000 --- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/SuppressLintIntentionAction.kt.173 +++ /dev/null @@ -1,110 +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.android.SdkConstants.FQCN_SUPPRESS_LINT -import com.intellij.codeInsight.FileModificationService -import com.intellij.codeInsight.intention.IntentionAction -import com.intellij.icons.AllIcons -import com.intellij.openapi.editor.Editor -import com.intellij.openapi.project.Project -import com.intellij.openapi.util.Iconable -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiFile -import com.intellij.psi.util.PsiTreeUtil -import org.jetbrains.android.util.AndroidBundle -import org.jetbrains.kotlin.android.hasBackingField -import org.jetbrains.kotlin.idea.util.addAnnotation -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.psi.* -import javax.swing.Icon - - -class SuppressLintIntentionAction(val id: String, val element: PsiElement) : IntentionAction, Iconable { - - private companion object { - val INTENTION_NAME_PREFIX = "AndroidKLint" - val SUPPRESS_LINT_MESSAGE = "android.lint.fix.suppress.lint.api.annotation" - val FQNAME_SUPPRESS_LINT = FqName(FQCN_SUPPRESS_LINT) - } - - private val lintId = getLintId(id) - - override fun isAvailable(project: Project, editor: Editor?, file: PsiFile?) = true - - override fun getText(): String = AndroidBundle.message(SUPPRESS_LINT_MESSAGE, lintId) - - override fun getFamilyName() = text - - override fun getIcon(flags: Int): Icon? = AllIcons.Actions.Cancel - - override fun startInWriteAction() = true - - override fun invoke(project: Project, editor: Editor?, file: PsiFile?) { - if (file !is KtFile) { - return - } - - val annotationContainer = PsiTreeUtil.findFirstParent(element, true) { it.isSuppressLintTarget() } ?: return - if (!FileModificationService.getInstance().preparePsiElementForWrite(annotationContainer)) { - return - } - - val argument = "\"$lintId\"" - - when (annotationContainer) { - is KtModifierListOwner -> annotationContainer.addAnnotation( - FQNAME_SUPPRESS_LINT, - argument, - whiteSpaceText = if (annotationContainer.isNewLineNeededForAnnotation()) "\n" else " ", - addToExistingAnnotation = { entry -> addArgumentToAnnotation(entry, argument) }) - } - } - - private fun addArgumentToAnnotation(entry: KtAnnotationEntry, argument: String): Boolean { - // add new arguments to an existing entry - val args = entry.valueArgumentList - val psiFactory = KtPsiFactory(entry) - val newArgList = psiFactory.createCallArguments("($argument)") - when { - args == null -> // new argument list - entry.addAfter(newArgList, entry.lastChild) - args.arguments.isEmpty() -> // replace '()' with a new argument list - args.replace(newArgList) - args.arguments.none { it.textMatches(argument) } -> - args.addArgument(newArgList.arguments[0]) - } - - return true - } - - private fun getLintId(intentionId: String) = - if (intentionId.startsWith(INTENTION_NAME_PREFIX)) intentionId.substring(INTENTION_NAME_PREFIX.length) else intentionId - - private fun KtElement.isNewLineNeededForAnnotation(): Boolean { - return !(this is KtParameter || - this is KtTypeParameter || - this is KtPropertyAccessor) - } - - private fun PsiElement.isSuppressLintTarget(): Boolean { - return this is KtDeclaration && - (this as? KtProperty)?.hasBackingField() ?: true && - this !is KtFunctionLiteral && - this !is KtDestructuringDeclaration - } -} \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/JvmDeclarationUElementPlaceholder.kt.173 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/JvmDeclarationUElementPlaceholder.kt.173 deleted file mode 100644 index 54853595af4..00000000000 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/JvmDeclarationUElementPlaceholder.kt.173 +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license - * that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.uast.kotlin - -import org.jetbrains.uast.JvmDeclarationUElement - -/** - * Actual only for 173-bunch, please remove when 173 is over - */ -typealias JvmDeclarationUElementPlaceholder = JvmDeclarationUElement \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.173 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.173 deleted file mode 100644 index 20eb4fbaccd..00000000000 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/KotlinUastLanguagePlugin.kt.173 +++ /dev/null @@ -1,549 +0,0 @@ -/* - * Copyright 2010-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.uast.kotlin - -import com.intellij.lang.Language -import com.intellij.openapi.components.ServiceManager -import com.intellij.openapi.util.Key -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiFile -import com.intellij.psi.impl.source.tree.LeafPsiElement -import org.jetbrains.kotlin.asJava.LightClassUtil -import org.jetbrains.kotlin.asJava.classes.KtLightClass -import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade -import org.jetbrains.kotlin.asJava.elements.* -import org.jetbrains.kotlin.asJava.toLightClass -import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper -import org.jetbrains.kotlin.config.LanguageVersionSettings -import org.jetbrains.kotlin.descriptors.ConstructorDescriptor -import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.idea.KotlinLanguage -import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.getParentOfType -import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall -import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform -import org.jetbrains.uast.* -import org.jetbrains.uast.kotlin.declarations.KotlinUMethod -import org.jetbrains.uast.kotlin.expressions.* -import org.jetbrains.uast.kotlin.psi.UastKotlinPsiParameter -import org.jetbrains.uast.kotlin.psi.UastKotlinPsiVariable - -interface KotlinUastResolveProviderService { - fun getBindingContext(element: KtElement): BindingContext - fun getTypeMapper(element: KtElement): KotlinTypeMapper? - fun getLanguageVersionSettings(element: KtElement): LanguageVersionSettings - fun isJvmElement(psiElement: PsiElement): Boolean -} - -var PsiElement.destructuringDeclarationInitializer: Boolean? by UserDataProperty(Key.create("kotlin.uast.destructuringDeclarationInitializer")) - -class KotlinUastLanguagePlugin : UastLanguagePlugin { - override val priority = 10 - - override val language: Language - get() = KotlinLanguage.INSTANCE - - override fun isFileSupported(fileName: String): Boolean { - return fileName.endsWith(".kt", false) || fileName.endsWith(".kts", false) - } - - private val PsiElement.isJvmElement: Boolean - get() { - val resolveProvider = ServiceManager.getService(project, KotlinUastResolveProviderService::class.java) - return resolveProvider.isJvmElement(this) - } - - override fun convertElement(element: PsiElement, parent: UElement?, requiredType: Class?): UElement? { - if (!element.isJvmElement) return null - return convertDeclarationOrElement(element, parent, requiredType) - } - - override fun convertElementWithParent(element: PsiElement, requiredType: Class?): UElement? { - if (!element.isJvmElement) return null - if (element is PsiFile) return convertDeclaration(element, null, requiredType) - if (element is KtLightClassForFacade) return convertDeclaration(element, null, requiredType) - - return convertDeclarationOrElement(element, null, requiredType) - } - - private fun convertDeclarationOrElement(element: PsiElement, givenParent: UElement?, requiredType: Class?): UElement? { - if (element is UElement) return element - - if (element.isValid) { - element.getUserData(KOTLIN_CACHED_UELEMENT_KEY)?.get()?.let { cachedUElement -> - return if (requiredType == null || requiredType.isInstance(cachedUElement)) cachedUElement else null - } - } - - val uElement = convertDeclaration(element, givenParent, requiredType) - ?: KotlinConverter.convertPsiElement(element, givenParent, requiredType) - /* - if (uElement != null) { - element.putUserData(KOTLIN_CACHED_UELEMENT_KEY, WeakReference(uElement)) - } - */ - return uElement - } - - override fun getMethodCallExpression( - element: PsiElement, - containingClassFqName: String?, - methodName: String - ): UastLanguagePlugin.ResolvedMethod? { - if (element !is KtCallExpression) return null - val resolvedCall = element.getResolvedCall(element.analyze()) ?: return null - val resultingDescriptor = resolvedCall.resultingDescriptor - if (resultingDescriptor !is FunctionDescriptor || resultingDescriptor.name.asString() != methodName) return null - - val parent = element.parent - val parentUElement = convertElementWithParent(parent, null) ?: return null - - val uExpression = KotlinUFunctionCallExpression(element, parentUElement, resolvedCall) - val method = uExpression.resolve() ?: return null - if (method.name != methodName) return null - return UastLanguagePlugin.ResolvedMethod(uExpression, method) - } - - override fun getConstructorCallExpression( - element: PsiElement, - fqName: String - ): UastLanguagePlugin.ResolvedConstructor? { - if (element !is KtCallExpression) return null - val resolvedCall = element.getResolvedCall(element.analyze()) ?: return null - val resultingDescriptor = resolvedCall.resultingDescriptor - if (resultingDescriptor !is ConstructorDescriptor - || resultingDescriptor.returnType.constructor.declarationDescriptor?.name?.asString() != fqName) { - return null - } - - val parent = KotlinConverter.unwrapElements(element.parent) ?: return null - val parentUElement = convertElementWithParent(parent, null) ?: return null - - val uExpression = KotlinUFunctionCallExpression(element, parentUElement, resolvedCall) - val method = uExpression.resolve() ?: return null - val containingClass = method.containingClass ?: return null - return UastLanguagePlugin.ResolvedConstructor(uExpression, method, containingClass) - } - - internal fun convertDeclaration(element: PsiElement, - givenParent: UElement?, - requiredType: Class?): UElement? { - fun

build(ctor: (P, UElement?) -> UElement): () -> UElement? = { ctor(element as P, givenParent) } - - fun

buildKt(ktElement: K, ctor: (P, K, UElement?) -> UElement): () -> UElement? = - { ctor(element as P, ktElement, givenParent) } - - fun

buildKtOpt(ktElement: K?, ctor: (P, K?, UElement?) -> UElement): () -> UElement? = - { ctor(element as P, ktElement, givenParent) } - - val original = element.originalElement - return with(requiredType) { - when (original) { - is KtLightMethod -> el(build(KotlinUMethod.Companion::create)) // .Companion is needed because of KT-13934 - is KtLightClass -> when (original.kotlinOrigin) { - is KtEnumEntry -> el { - convertEnumEntry(original.kotlinOrigin as KtEnumEntry, givenParent) - } - else -> el { KotlinUClass.create(original, givenParent) } - } - is KtLightFieldImpl.KtLightEnumConstant -> el(buildKtOpt(original.kotlinOrigin, ::KotlinUEnumConstant)) - is KtLightField -> el(buildKtOpt(original.kotlinOrigin, ::KotlinUField)) - is KtLightParameter -> el(buildKtOpt(original.kotlinOrigin, ::KotlinUParameter)) - is UastKotlinPsiParameter -> el(buildKt(original.ktParameter, ::KotlinUParameter)) - is UastKotlinPsiVariable -> el(buildKt(original.ktElement, ::KotlinUVariable)) - - is KtEnumEntry -> el { - convertEnumEntry(original, givenParent) - } - is KtClassOrObject -> el { - original.toLightClass()?.let { lightClass -> - KotlinUClass.create(lightClass, givenParent) - } - } - is KtFunction -> - if (original.isLocal) { - el { - val parent = original.parent - if (parent is KtLambdaExpression) { - KotlinULambdaExpression(parent, givenParent) // your parent is the ULambdaExpression - } else if (original.name.isNullOrEmpty()) { - createLocalFunctionLambdaExpression(original, givenParent) - } - else { - val uDeclarationsExpression = createLocalFunctionDeclaration(original, givenParent) - val localFunctionVar = uDeclarationsExpression.declarations.single() as KotlinLocalFunctionUVariable - localFunctionVar.uastInitializer - } - } - } - else { - el { - val lightMethod = LightClassUtil.getLightClassMethod(original) ?: return null - convertDeclaration(lightMethod, givenParent, requiredType) - } - } - - is KtPropertyAccessor -> el { - val lightMethod = LightClassUtil.getLightClassAccessorMethod(original) ?: return null - convertDeclaration(lightMethod, givenParent, requiredType) - } - - is KtProperty -> - if (original.isLocal) { - KotlinConverter.convertPsiElement(element, givenParent, requiredType) - } - else { - convertNonLocalProperty(original, givenParent, requiredType) - } - - is KtParameter -> el { - val ownerFunction = original.ownerFunction as? KtFunction ?: return null - val lightMethod = LightClassUtil.getLightClassMethod(ownerFunction) ?: return null - val lightParameter = lightMethod.parameterList.parameters.find { it.name == original.name } ?: return null - KotlinUParameter(lightParameter, original, givenParent) - } - - is KtFile -> el { KotlinUFile(original, this@KotlinUastLanguagePlugin) } - is FakeFileForLightClass -> el { KotlinUFile(original.navigationElement, this@KotlinUastLanguagePlugin) } - is KtAnnotationEntry -> el(build(::KotlinUAnnotation)) - is KtCallExpression -> - if (requiredType != null && UAnnotation::class.java.isAssignableFrom(requiredType)) { - el { KotlinUNestedAnnotation.tryCreate(original, givenParent) } - } else null - is KtLightAnnotationForSourceEntry -> convertElement(original.kotlinOrigin, givenParent, requiredType) - else -> null - } - } - } - - private fun convertEnumEntry(original: KtEnumEntry, givenParent: UElement?): UElement? { - return LightClassUtil.getLightClassBackingField(original)?.let { psiField -> - if (psiField is KtLightFieldImpl.KtLightEnumConstant) { - KotlinUEnumConstant(psiField, psiField.kotlinOrigin, givenParent) - } - else { - null - } - } - } - - override fun isExpressionValueUsed(element: UExpression): Boolean { - return when (element) { - is KotlinUSimpleReferenceExpression.KotlinAccessorCallExpression -> element.setterValue != null - is KotlinAbstractUExpression -> { - val ktElement = element.psi as? KtElement ?: return false - ktElement.analyze()[BindingContext.USED_AS_EXPRESSION, ktElement] ?: false - } - else -> false - } - } -} - -internal inline fun Class?.el(f: () -> UElement?): UElement? { - return if (this == null || isAssignableFrom(ActualT::class.java)) f() else null -} - -internal inline fun Class?.expr(f: () -> UExpression?): UExpression? { - return if (this == null || isAssignableFrom(ActualT::class.java)) f() else null -} - -private fun convertNonLocalProperty(property: KtProperty, - givenParent: UElement?, - requiredType: Class?): UElement? { - val methods = LightClassUtil.getLightClassPropertyMethods(property) - return methods.backingField?.let { backingField -> - with(requiredType) { - el { KotlinUField(backingField, (backingField as? KtLightElement<*,*>)?.kotlinOrigin, givenParent) } - } - } ?: methods.getter?.let { getter -> - KotlinUastLanguagePlugin().convertDeclaration(getter, givenParent, requiredType) - } -} - -internal object KotlinConverter { - internal tailrec fun unwrapElements(element: PsiElement?): PsiElement? = when (element) { - is KtValueArgumentList -> unwrapElements(element.parent) - is KtValueArgument -> unwrapElements(element.parent) - is KtDeclarationModifierList -> unwrapElements(element.parent) - is KtContainerNode -> unwrapElements(element.parent) - is KtSimpleNameStringTemplateEntry -> unwrapElements(element.parent) - is KtLightParameterList -> unwrapElements(element.parent) - else -> element - } - - internal fun convertPsiElement(element: PsiElement?, - givenParent: UElement?, - requiredType: Class?): UElement? { - fun

build(ctor: (P, UElement?) -> UElement): () -> UElement? { - return { ctor(element as P, givenParent) } - } - - return with (requiredType) { when (element) { - is KtParameterList -> el { - val declarationsExpression = KotlinUDeclarationsExpression(givenParent) - declarationsExpression.apply { - declarations = element.parameters.mapIndexed { i, p -> - KotlinUParameter(UastKotlinPsiParameter.create(p, element, declarationsExpression, i), p, this) - } - } - } - is KtClassBody -> el(build(KotlinUExpressionList.Companion::createClassBody)) - is KtCatchClause -> el(build(::KotlinUCatchClause)) - is KtVariableDeclaration -> - if (element is KtProperty && !element.isLocal) { - el { - LightClassUtil.getLightClassBackingField(element)?.let { - KotlinUField(it, element, givenParent) - } - } - } - else { - el { - convertVariablesDeclaration(element, givenParent).declarations.singleOrNull() - } - } - - is KtExpression -> KotlinConverter.convertExpression(element, givenParent, requiredType) - is KtLambdaArgument -> element.getLambdaExpression()?.let { KotlinConverter.convertExpression(it, givenParent, requiredType) } - is KtLightElementBase -> { - val expression = element.kotlinOrigin - when (expression) { - is KtExpression -> KotlinConverter.convertExpression(expression, givenParent, requiredType) - else -> el { UastEmptyExpression } - } - } - is KtLiteralStringTemplateEntry, is KtEscapeStringTemplateEntry -> el(build(::KotlinStringULiteralExpression)) - is KtStringTemplateEntry -> element.expression?.let { convertExpression(it, givenParent, requiredType) } ?: expr { UastEmptyExpression } - is KtWhenEntry -> el(build(::KotlinUSwitchEntry)) - is KtWhenCondition -> convertWhenCondition(element, givenParent, requiredType) - is KtTypeReference -> el { LazyKotlinUTypeReferenceExpression(element, givenParent) } - is KtConstructorDelegationCall -> - el { KotlinUFunctionCallExpression(element, givenParent) } - is KtSuperTypeCallEntry -> - el { - (element.getParentOfType(true)?.parent as? KtObjectLiteralExpression) - ?.toUElementOfType() - ?: KotlinUFunctionCallExpression(element, givenParent) - } - is KtImportDirective -> el(build(::KotlinUImportStatement)) - else -> { - if (element is LeafPsiElement) { - if (element.elementType == KtTokens.IDENTIFIER) - el(build(::UIdentifier)) - else if (element.elementType == KtTokens.LBRACKET && element.parent is KtCollectionLiteralExpression) - el { - UIdentifier( - element, - KotlinUCollectionLiteralExpression( - element.parent as KtCollectionLiteralExpression, - null - ) - ) - } - else null - } else { - null - } - } - }} - } - - - internal fun convertEntry(entry: KtStringTemplateEntry, - givenParent: UElement?, - requiredType: Class? = null): UExpression? { - return with(requiredType) { - if (entry is KtStringTemplateEntryWithExpression) { - expr { - KotlinConverter.convertOrEmpty(entry.expression, givenParent) - } - } - else { - expr { - if (entry is KtEscapeStringTemplateEntry) - KotlinStringULiteralExpression(entry, givenParent, entry.unescapedValue) - else - KotlinStringULiteralExpression(entry, givenParent) - } - } - } - } - - internal fun convertExpression(expression: KtExpression, - givenParent: UElement?, - requiredType: Class? = null): UExpression? { - fun

build(ctor: (P, UElement?) -> UExpression): () -> UExpression? { - return { ctor(expression as P, givenParent) } - } - - return with (requiredType) { when (expression) { - is KtVariableDeclaration -> expr(build(::convertVariablesDeclaration)) - - is KtStringTemplateExpression -> { - when { - expression.entries.isEmpty() -> { - expr { KotlinStringULiteralExpression(expression, givenParent, "") } - } - expression.entries.size == 1 -> convertEntry(expression.entries[0], givenParent, requiredType) - else -> { - expr { KotlinStringTemplateUPolyadicExpression(expression, givenParent) } - } - } - } - is KtDestructuringDeclaration -> expr { - val declarationsExpression = KotlinUDestructuringDeclarationExpression(givenParent, expression) - declarationsExpression.apply { - val tempAssignment = KotlinULocalVariable(UastKotlinPsiVariable.create(expression, declarationsExpression), expression, declarationsExpression) - val destructuringAssignments = expression.entries.mapIndexed { i, entry -> - val psiFactory = KtPsiFactory(expression.project) - val initializer = psiFactory.createAnalyzableExpression("${tempAssignment.name}.component${i + 1}()", - expression.containingFile) - initializer.destructuringDeclarationInitializer = true - KotlinULocalVariable(UastKotlinPsiVariable.create(entry, tempAssignment.psi, declarationsExpression, initializer), entry, declarationsExpression) - } - declarations = listOf(tempAssignment) + destructuringAssignments - } - } - is KtLabeledExpression -> expr(build(::KotlinULabeledExpression)) - is KtClassLiteralExpression -> expr(build(::KotlinUClassLiteralExpression)) - is KtObjectLiteralExpression -> expr(build(::KotlinUObjectLiteralExpression)) - is KtDotQualifiedExpression -> expr(build(::KotlinUQualifiedReferenceExpression)) - is KtSafeQualifiedExpression -> expr(build(::KotlinUSafeQualifiedExpression)) - is KtSimpleNameExpression -> expr(build(::KotlinUSimpleReferenceExpression)) - is KtCallExpression -> expr(build(::KotlinUFunctionCallExpression)) - is KtCollectionLiteralExpression -> expr(build(::KotlinUCollectionLiteralExpression)) - is KtBinaryExpression -> { - if (expression.operationToken == KtTokens.ELVIS) { - expr(build(::createElvisExpression)) - } - else expr(build(::KotlinUBinaryExpression)) - } - is KtParenthesizedExpression -> expr(build(::KotlinUParenthesizedExpression)) - is KtPrefixExpression -> expr(build(::KotlinUPrefixExpression)) - is KtPostfixExpression -> expr(build(::KotlinUPostfixExpression)) - is KtThisExpression -> expr(build(::KotlinUThisExpression)) - is KtSuperExpression -> expr(build(::KotlinUSuperExpression)) - is KtCallableReferenceExpression -> expr(build(::KotlinUCallableReferenceExpression)) - is KtIsExpression -> expr(build(::KotlinUTypeCheckExpression)) - is KtIfExpression -> expr(build(::KotlinUIfExpression)) - is KtWhileExpression -> expr(build(::KotlinUWhileExpression)) - is KtDoWhileExpression -> expr(build(::KotlinUDoWhileExpression)) - is KtForExpression -> expr(build(::KotlinUForEachExpression)) - is KtWhenExpression -> expr(build(::KotlinUSwitchExpression)) - is KtBreakExpression -> expr(build(::KotlinUBreakExpression)) - is KtContinueExpression -> expr(build(::KotlinUContinueExpression)) - is KtReturnExpression -> expr(build(::KotlinUReturnExpression)) - is KtThrowExpression -> expr(build(::KotlinUThrowExpression)) - is KtBlockExpression -> expr(build(::KotlinUBlockExpression)) - is KtConstantExpression -> expr(build(::KotlinULiteralExpression)) - is KtTryExpression -> expr(build(::KotlinUTryExpression)) - is KtArrayAccessExpression -> expr(build(::KotlinUArrayAccessExpression)) - is KtLambdaExpression -> expr(build(::KotlinULambdaExpression)) - is KtBinaryExpressionWithTypeRHS -> expr(build(::KotlinUBinaryExpressionWithType)) - is KtClassOrObject -> expr { - expression.toLightClass()?.let { lightClass -> - KotlinUDeclarationsExpression(givenParent).apply { - declarations = listOf(KotlinUClass.create(lightClass, this)) - } - } ?: UastEmptyExpression - } - is KtFunction -> if (expression.name.isNullOrEmpty()) { - expr(build(::createLocalFunctionLambdaExpression)) - } - else { - expr(build(::createLocalFunctionDeclaration)) - } - - else -> expr(build(::UnknownKotlinExpression)) - }} - } - - internal fun convertWhenCondition(condition: KtWhenCondition, - givenParent: UElement?, - requiredType: Class? = null): UExpression? { - return with(requiredType) { - when (condition) { - is KtWhenConditionInRange -> expr { - KotlinCustomUBinaryExpression(condition, givenParent).apply { - leftOperand = KotlinStringUSimpleReferenceExpression("it", this) - operator = when { - condition.isNegated -> KotlinBinaryOperators.NOT_IN - else -> KotlinBinaryOperators.IN - } - rightOperand = KotlinConverter.convertOrEmpty(condition.rangeExpression, this) - } - } - is KtWhenConditionIsPattern -> expr { - KotlinCustomUBinaryExpressionWithType(condition, givenParent).apply { - operand = KotlinStringUSimpleReferenceExpression("it", this) - operationKind = when { - condition.isNegated -> KotlinBinaryExpressionWithTypeKinds.NEGATED_INSTANCE_CHECK - else -> UastBinaryExpressionWithTypeKind.INSTANCE_CHECK - } - val typeRef = condition.typeReference - typeReference = typeRef?.let { - LazyKotlinUTypeReferenceExpression(it, this) { typeRef.toPsiType(this, boxed = true) } - } - } - } - - is KtWhenConditionWithExpression -> - condition.expression?.let { KotlinConverter.convertExpression(it, givenParent, requiredType) } - - else -> expr { UastEmptyExpression } - } - } - } - - internal fun convertOrEmpty(expression: KtExpression?, parent: UElement?): UExpression { - return expression?.let { convertExpression(it, parent, null) } ?: UastEmptyExpression - } - - internal fun convertOrNull(expression: KtExpression?, parent: UElement?): UExpression? { - return if (expression != null) convertExpression(expression, parent, null) else null - } - - internal fun KtPsiFactory.createAnalyzableExpression(text: String, context: PsiElement): KtExpression = - createAnalyzableProperty("val x = $text", context).initializer ?: error("Failed to create expression from text: '$text'") - - internal fun KtPsiFactory.createAnalyzableProperty(text: String, context: PsiElement): KtProperty = - createAnalyzableDeclaration(text, context) - - internal fun KtPsiFactory.createAnalyzableDeclaration(text: String, context: PsiElement): TDeclaration { - val file = createAnalyzableFile("dummy.kt", text, context) - val declarations = file.declarations - assert(declarations.size == 1) { "${declarations.size} declarations in $text" } - return declarations.first() as TDeclaration - } -} - -private fun convertVariablesDeclaration( - psi: KtVariableDeclaration, - parent: UElement? -): UDeclarationsExpression { - val declarationsExpression = parent as? KotlinUDeclarationsExpression - ?: psi.parent.toUElementOfType() as? KotlinUDeclarationsExpression - ?: KotlinUDeclarationsExpression(null, parent, psi) - val parentPsiElement = parent?.psi - val variable = KotlinUAnnotatedLocalVariable( - UastKotlinPsiVariable.create(psi, parentPsiElement, declarationsExpression), psi, declarationsExpression) { annotationParent -> - psi.annotationEntries.map { KotlinUAnnotation(it, annotationParent) } - } - return declarationsExpression.apply { declarations = listOf(variable) } -} diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUAnnotation.kt.173 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUAnnotation.kt.173 deleted file mode 100644 index 72c0eed25da..00000000000 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUAnnotation.kt.173 +++ /dev/null @@ -1,142 +0,0 @@ -package org.jetbrains.uast.kotlin - -import com.intellij.psi.PsiAnnotation -import com.intellij.psi.PsiClass -import com.intellij.psi.PsiElement -import org.jetbrains.kotlin.asJava.toLightAnnotation -import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.ClassKind -import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget -import org.jetbrains.kotlin.name.FqNameUnsafe -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall -import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch -import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall -import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe -import org.jetbrains.kotlin.resolve.source.getPsi -import org.jetbrains.kotlin.types.ErrorUtils -import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance -import org.jetbrains.uast.* -import org.jetbrains.uast.kotlin.declarations.KotlinUMethod - -abstract class KotlinUAnnotationBase( - final override val sourcePsi: T, - givenParent: UElement? -) : KotlinAbstractUElement(givenParent), UAnnotation { - - abstract override val javaPsi: PsiAnnotation? - - final override val psi: PsiElement = sourcePsi - - protected abstract fun annotationUseSiteTarget(): AnnotationUseSiteTarget? - - private val resolvedCall: ResolvedCall<*>? get () = sourcePsi.getResolvedCall(sourcePsi.analyze()) - - override val qualifiedName: String? by lz { - computeClassDescriptor().takeUnless(ErrorUtils::isError) - ?.fqNameUnsafe - ?.takeIf(FqNameUnsafe::isSafe) - ?.toSafe() - ?.toString() - } - - override val attributeValues: List by lz { - resolvedCall?.valueArguments?.entries?.mapNotNull { - val arguments = it.value.arguments - val name = it.key.name.asString() - when { - arguments.size == 1 -> - KotlinUNamedExpression.create(name, arguments.first(), this) - arguments.size > 1 -> - KotlinUNamedExpression.create(name, arguments, this) - else -> null - } - } ?: emptyList() - } - - protected abstract fun computeClassDescriptor(): ClassDescriptor? - - override fun resolve(): PsiClass? = computeClassDescriptor()?.toSource()?.getMaybeLightElement(this) as? PsiClass - - override fun findAttributeValue(name: String?): UExpression? = - findDeclaredAttributeValue(name) ?: findAttributeDefaultValue(name ?: "value") - - fun findAttributeValueExpression(arg: ValueArgument): UExpression? { - val mapping = resolvedCall?.getArgumentMapping(arg) - return (mapping as? ArgumentMatch)?.let { match -> - val namedExpression = attributeValues.find { it.name == match.valueParameter.name.asString() } - namedExpression?.expression as? KotlinUVarargExpression ?: namedExpression - } - } - - override fun findDeclaredAttributeValue(name: String?): UExpression? { - return attributeValues.find { - it.name == name || - (name == null && it.name == "value") || - (name == "value" && it.name == null) - }?.expression - } - - private fun findAttributeDefaultValue(name: String): UExpression? { - val parameter = computeClassDescriptor() - ?.unsubstitutedPrimaryConstructor - ?.valueParameters - ?.find { it.name.asString() == name } ?: return null - - val defaultValue = (parameter.source.getPsi() as? KtParameter)?.defaultValue ?: return null - return getLanguagePlugin().convertWithParent(defaultValue) - } - - override fun convertParent(): UElement? { - val superParent = super.convertParent() ?: return null - if (annotationUseSiteTarget() == AnnotationUseSiteTarget.RECEIVER) { - (superParent.uastParent as? KotlinUMethod)?.uastParameters?.firstIsInstance()?.let { - return it - } - } - return superParent - } -} - -class KotlinUAnnotation( - annotationEntry: KtAnnotationEntry, - givenParent: UElement? -) : KotlinUAnnotationBase(annotationEntry, givenParent), UAnnotation { - - override val javaPsi = annotationEntry.toLightAnnotation() - - override fun computeClassDescriptor(): ClassDescriptor? = - sourcePsi.analyze()[BindingContext.ANNOTATION, sourcePsi]?.annotationClass - - override fun annotationUseSiteTarget() = sourcePsi.useSiteTarget?.getAnnotationUseSiteTarget() - -} - -class KotlinUNestedAnnotation private constructor( - original: KtCallExpression, - givenParent: UElement? -) : KotlinUAnnotationBase(original, givenParent) { - override val javaPsi: PsiAnnotation? by lazy { original.toLightAnnotation() } - - override fun computeClassDescriptor(): ClassDescriptor? = classDescriptor(sourcePsi) - - override fun annotationUseSiteTarget(): AnnotationUseSiteTarget? = null - - companion object { - fun tryCreate(original: KtCallExpression, givenParent: UElement?): KotlinUNestedAnnotation? { - if (classDescriptor(original)?.kind == ClassKind.ANNOTATION_CLASS) - return KotlinUNestedAnnotation(original, givenParent) - else - return null - } - - private fun classDescriptor(original: KtCallExpression) = - (original.getResolvedCall(original.analyze())?.resultingDescriptor as? ClassConstructorDescriptor)?.constructedClass - } - -} - - diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUClass.kt.173 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUClass.kt.173 deleted file mode 100644 index c2849708e07..00000000000 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUClass.kt.173 +++ /dev/null @@ -1,325 +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.uast.kotlin - -import com.intellij.psi.* -import com.intellij.psi.impl.light.LightPsiClassBuilder -import org.jetbrains.kotlin.asJava.classes.KtLightClass -import org.jetbrains.kotlin.asJava.classes.KtLightClassForScript -import org.jetbrains.kotlin.asJava.elements.KtLightMethod -import org.jetbrains.kotlin.load.java.JvmAbi -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments -import org.jetbrains.kotlin.utils.SmartList -import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull -import org.jetbrains.uast.* -import org.jetbrains.uast.kotlin.declarations.KotlinUMethod -import org.jetbrains.uast.kotlin.declarations.UastLightIdentifier - -abstract class AbstractKotlinUClass(givenParent: UElement?) : KotlinAbstractUElement(givenParent), UClass, JvmDeclarationUElementPlaceholder { - - override val uastDeclarations by lz { - mutableListOf().apply { - addAll(fields) - addAll(initializers) - addAll(methods) - addAll(innerClasses) - } - } - - override val uastSuperTypes: List - get() { - val ktClass = (psi as? KtLightClass)?.kotlinOrigin ?: return emptyList() - return ktClass.superTypeListEntries.mapNotNull { it.typeReference }.map { - LazyKotlinUTypeReferenceExpression(it, this) - } - } - - override val uastAnchor: UElement? - get() = UIdentifier(psi.nameIdentifier, this) - - override val annotations: List by lz { - (sourcePsi as? KtModifierListOwner)?.annotationEntries.orEmpty().map { KotlinUAnnotation(it, this) } - } - - override fun equals(other: Any?) = other is AbstractKotlinUClass && psi == other.psi - override fun hashCode() = psi.hashCode() - -} - -open class KotlinUClass private constructor( - psi: KtLightClass, - givenParent: UElement? -) : AbstractKotlinUClass(givenParent), PsiClass by psi { - - val ktClass = psi.kotlinOrigin - - override val javaPsi: KtLightClass = psi - - override val sourcePsi: KtClassOrObject? = ktClass - - override val psi = unwrap(psi) - - override fun getSourceElement() = sourcePsi ?: this - - override fun getOriginalElement(): PsiElement? = super.getOriginalElement() - - override fun getNameIdentifier(): PsiIdentifier? = UastLightIdentifier(psi, ktClass) - - override fun getContainingFile(): PsiFile? = unwrapFakeFileForLightClass(psi.containingFile) - - override val uastAnchor: UElement - get() = UIdentifier(nameIdentifier, this) - - override fun getInnerClasses(): Array { - // filter DefaultImpls to avoid processing same methods from original interface multiple times - // filter Enum entry classes to avoid duplication with PsiEnumConstant initializer class - return psi.innerClasses.filter { - it.name != JvmAbi.DEFAULT_IMPLS_CLASS_NAME && !it.isEnumEntryLightClass() - }.mapNotNull { - getLanguagePlugin().convertOpt(it, this) - }.toTypedArray() - } - - override fun getSuperClass(): UClass? = super.getSuperClass() - override fun getFields(): Array = super.getFields() - override fun getInitializers(): Array = super.getInitializers() - - override fun getMethods(): Array { - val hasPrimaryConstructor = ktClass?.hasPrimaryConstructor() ?: false - var secondaryConstructorsCount = 0 - - fun createUMethod(psiMethod: PsiMethod): UMethod { - return if (psiMethod is KtLightMethod && - psiMethod.isConstructor) { - if (!hasPrimaryConstructor && secondaryConstructorsCount++ == 0) - KotlinSecondaryConstructorWithInitializersUMethod(ktClass, psiMethod, this) - else - KotlinConstructorUMethod(ktClass, psiMethod, this) - } else { - getLanguagePlugin().convertOpt(psiMethod, this) ?: reportConvertFailure(psiMethod) - } - } - - fun isDelegatedMethod(psiMethod: PsiMethod) = psiMethod is KtLightMethod && psiMethod.isDelegated - - return psi.methods.asSequence() - .filterNot(::isDelegatedMethod) - .map(::createUMethod) - .toList() - .toTypedArray() - } - - private fun PsiClass.isEnumEntryLightClass() = (this as? KtLightClass)?.kotlinOrigin is KtEnumEntry - - companion object { - fun create(psi: KtLightClass, containingElement: UElement?): UClass = when (psi) { - is PsiAnonymousClass -> KotlinUAnonymousClass(psi, containingElement) - is KtLightClassForScript -> KotlinScriptUClass(psi, containingElement) - else -> KotlinUClass(psi, containingElement) - } - } - -} - -open class KotlinConstructorUMethod( - private val ktClass: KtClassOrObject?, - override val psi: KtLightMethod, - givenParent: UElement? -) : KotlinUMethod(psi, givenParent) { - - val isPrimary: Boolean - get() = psi.kotlinOrigin.let { it is KtPrimaryConstructor || it is KtClassOrObject } - - override val uastBody: UExpression? by lz { - val delegationCall: KtCallElement? = psi.kotlinOrigin.let { - when { - isPrimary -> ktClass?.superTypeListEntries?.firstIsInstanceOrNull() - it is KtSecondaryConstructor -> it.getDelegationCall() - else -> null - } - } - val bodyExpressions = getBodyExpressions() - if (delegationCall == null && bodyExpressions.isEmpty()) return@lz null - KotlinUBlockExpression.KotlinLazyUBlockExpression(this) { uastParent -> - SmartList().apply { - delegationCall?.let { - add(KotlinUFunctionCallExpression(it, uastParent)) - } - bodyExpressions.forEach { - add(KotlinConverter.convertOrEmpty(it, uastParent)) - } - } - } - } - - override val javaPsi = psi - - override val sourcePsi = psi.kotlinOrigin - - open protected fun getBodyExpressions(): List { - if (isPrimary) return getInitializers() - val bodyExpression = (psi.kotlinOrigin as? KtFunction)?.bodyExpression ?: return emptyList() - if (bodyExpression is KtBlockExpression) return bodyExpression.statements - return listOf(bodyExpression) - } - - protected fun getInitializers() = ktClass?.getAnonymousInitializers()?.mapNotNull { it.body } ?: emptyList() - -} - -// This class was created as a workaround for KT-21617 to be the only constructor which includes `init` block -// when there is no primary constructors in the class. -// It is expected to have only one constructor of this type in a UClass. -class KotlinSecondaryConstructorWithInitializersUMethod( - ktClass: KtClassOrObject?, - psi: KtLightMethod, - givenParent: UElement? -) : KotlinConstructorUMethod(ktClass, psi, givenParent) { - override fun getBodyExpressions(): List = getInitializers() + super.getBodyExpressions() -} - -class KotlinUAnonymousClass( - psi: PsiAnonymousClass, - givenParent: UElement? -) : AbstractKotlinUClass(givenParent), UAnonymousClass, PsiAnonymousClass by psi { - - override val psi: PsiAnonymousClass = unwrap(psi) - - override val javaPsi: PsiAnonymousClass = psi - - override val sourcePsi: KtClassOrObject? = (psi as? KtLightClass)?.kotlinOrigin - - override fun getOriginalElement(): PsiElement? = super.getOriginalElement() - - override fun getSuperClass(): UClass? = super.getSuperClass() - override fun getFields(): Array = super.getFields() - override fun getMethods(): Array = super.getMethods() - override fun getInitializers(): Array = super.getInitializers() - override fun getInnerClasses(): Array = super.getInnerClasses() - - override fun getContainingFile(): PsiFile = unwrapFakeFileForLightClass(psi.containingFile) - - override val uastAnchor: UElement? - get() { - val ktClassOrObject = (psi.originalElement as? KtLightClass)?.kotlinOrigin as? KtObjectDeclaration ?: return null - return UIdentifier(ktClassOrObject.getObjectKeyword(), this) - } - -} - -class KotlinScriptUClass( - psi: KtLightClassForScript, - givenParent: UElement? -) : AbstractKotlinUClass(givenParent), PsiClass by psi { - override fun getContainingFile(): PsiFile = unwrapFakeFileForLightClass(psi.containingFile) - - override fun getNameIdentifier(): PsiIdentifier? = UastLightIdentifier(psi, psi.kotlinOrigin) - - override val uastAnchor: UElement - get() = UIdentifier(nameIdentifier, this) - - override val javaPsi: PsiClass = psi - - override val sourcePsi: KtClassOrObject? = psi.kotlinOrigin - - override val psi = unwrap(psi) - - override fun getSuperClass(): UClass? = super.getSuperClass() - - override fun getFields(): Array = super.getFields() - - override fun getInitializers(): Array = super.getInitializers() - - override fun getInnerClasses(): Array = - psi.innerClasses.mapNotNull { getLanguagePlugin().convertOpt(it, this) }.toTypedArray() - - override fun getMethods(): Array = psi.methods.map(this::createUMethod).toTypedArray() - - private fun createUMethod(method: PsiMethod): UMethod { - return if (method.isConstructor) { - KotlinScriptConstructorUMethod(psi.script, method as KtLightMethod, this) - } - else { - getLanguagePlugin().convertOpt(method, this) ?: reportConvertFailure(method) - } - } - - override fun getOriginalElement(): PsiElement? = psi.originalElement - - class KotlinScriptConstructorUMethod( - script: KtScript, - override val psi: KtLightMethod, - givenParent: UElement? - ) : KotlinUMethod(psi, givenParent) { - override val uastBody: UExpression? by lz { - val initializers = script.declarations.filterIsInstance() - KotlinUBlockExpression.create(initializers, this) - } - override val javaPsi = psi - override val sourcePsi = psi.kotlinOrigin - } -} - -/** - * implementation of [UClass] for invalid code, when it is impossible to create a [KtLightClass] - */ -class KotlinInvalidUClass( - override val psi: PsiClass, - givenParent: UElement? -) : AbstractKotlinUClass(givenParent), PsiClass by psi { - - constructor(name: String, context: PsiElement, givenParent: UElement?) : this(LightPsiClassBuilder(context, name), givenParent) - - override fun getContainingFile(): PsiFile? = - (uastParent?.getContainingUFile() as? JvmDeclarationUElementPlaceholder)?.sourcePsi as? PsiFile - - override val sourcePsi: PsiElement? get() = null - - override val uastAnchor: UIdentifier? get() = null - - override val javaPsi: PsiClass get() = psi - - override fun getFields(): Array = emptyArray() - - override fun getInitializers(): Array = emptyArray() - - override fun getInnerClasses(): Array = emptyArray() - - override fun getMethods(): Array = emptyArray() - - override fun getSuperClass(): UClass? = null - - override fun getOriginalElement(): PsiElement? = null -} - -private fun reportConvertFailure(psiMethod: PsiMethod): Nothing { - val isValid = psiMethod.isValid - val report = KotlinExceptionWithAttachments( - "cant convert $psiMethod of ${psiMethod.javaClass} to UMethod" - + if (!isValid) " (method is not valid)" else "" - ) - - if (isValid) { - report.withAttachment("method", psiMethod.text) - psiMethod.containingFile?.let { - report.withAttachment("file", it.text) - } - } - - throw report -} \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUMethod.kt.173 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUMethod.kt.173 deleted file mode 100644 index 7d68de53c03..00000000000 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUMethod.kt.173 +++ /dev/null @@ -1,130 +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.uast.kotlin.declarations - -import com.intellij.psi.PsiCodeBlock -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiFile -import com.intellij.psi.PsiMethod -import org.jetbrains.kotlin.asJava.elements.KtLightElement -import org.jetbrains.kotlin.asJava.elements.KtLightMethod -import org.jetbrains.kotlin.asJava.elements.isGetter -import org.jetbrains.kotlin.asJava.elements.isSetter -import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject -import org.jetbrains.kotlin.utils.SmartList -import org.jetbrains.uast.* -import org.jetbrains.uast.java.internal.JavaUElementWithComments -import org.jetbrains.uast.kotlin.* - -open class KotlinUMethod( - psi: KtLightMethod, - givenParent: UElement? -) : KotlinAbstractUElement(givenParent), UAnnotationMethod, JavaUElementWithComments, PsiMethod by psi { - override val comments: List - get() = super.comments - - override val psi: KtLightMethod = unwrap(psi) - - override val javaPsi = psi - - override val sourcePsi = psi.kotlinOrigin - - override fun getSourceElement() = sourcePsi ?: this - - override val uastDefaultValue by lz { - val annotationParameter = psi.kotlinOrigin as? KtParameter ?: return@lz null - val defaultValue = annotationParameter.defaultValue ?: return@lz null - getLanguagePlugin().convertElement(defaultValue, this) as? UExpression - } - - private val kotlinOrigin = (psi.originalElement as KtLightElement<*, *>).kotlinOrigin - - override fun getContainingFile(): PsiFile? = unwrapFakeFileForLightClass(psi.containingFile) - - override fun getNameIdentifier() = UastLightIdentifier(psi, kotlinOrigin as KtNamedDeclaration?) - - override val annotations by lz { - psi.annotations - .mapNotNull { (it as? KtLightElement<*, *>)?.kotlinOrigin as? KtAnnotationEntry } - .map { KotlinUAnnotation(it, this) } - } - - private val receiver by lz { (sourcePsi as? KtCallableDeclaration)?.receiverTypeReference } - - override val uastParameters by lz { - val lightParams = psi.parameterList.parameters - val receiver = receiver ?: return@lz lightParams.map { - KotlinUParameter(it, (it as? KtLightElement<*, *>)?.kotlinOrigin, this) - } - val receiverLight = lightParams.firstOrNull() ?: return@lz emptyList() - val uParameters = SmartList(KotlinReceiverUParameter(receiverLight, receiver, this)) - lightParams.drop(1).mapTo(uParameters) { KotlinUParameter(it, (it as? KtLightElement<*, *>)?.kotlinOrigin, this) } - uParameters - } - - override val uastAnchor: UElement - get() = UIdentifier(nameIdentifier, this) - - - override val uastBody by lz { - val bodyExpression = when (kotlinOrigin) { - is KtFunction -> kotlinOrigin.bodyExpression - is KtProperty -> when { - psi.isGetter -> kotlinOrigin.getter?.bodyExpression - psi.isSetter -> kotlinOrigin.setter?.bodyExpression - else -> null - } - else -> null - } ?: return@lz null - - when (bodyExpression) { - !is KtBlockExpression -> { - KotlinUBlockExpression.KotlinLazyUBlockExpression(this, { block -> - val implicitReturn = KotlinUImplicitReturnExpression(block) - val uBody = getLanguagePlugin().convertElement(bodyExpression, implicitReturn) as? UExpression - ?: return@KotlinLazyUBlockExpression emptyList() - listOf(implicitReturn.apply { returnExpression = uBody }) - }) - - } - else -> getLanguagePlugin().convertElement(bodyExpression, this) as? UExpression - } - } - - override val isOverride: Boolean - get() = (kotlinOrigin as? KtCallableDeclaration)?.hasModifier(KtTokens.OVERRIDE_KEYWORD) ?: false - - override fun getBody(): PsiCodeBlock? = super.getBody() - - override fun getOriginalElement(): PsiElement? = super.getOriginalElement() - - override fun equals(other: Any?) = other is KotlinUMethod && psi == other.psi - - companion object { - fun create(psi: KtLightMethod, containingElement: UElement?) = - if (psi.kotlinOrigin is KtConstructor<*>) { - KotlinConstructorUMethod( - psi.kotlinOrigin?.containingClassOrObject, - psi, containingElement - ) - } - else - KotlinUMethod(psi, containingElement) - } -} \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUVariable.kt.173 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUVariable.kt.173 deleted file mode 100644 index 27e55774249..00000000000 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/KotlinUVariable.kt.173 +++ /dev/null @@ -1,444 +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.uast.kotlin - -import com.intellij.psi.* -import com.intellij.psi.search.GlobalSearchScope -import com.intellij.psi.util.PsiTypesUtil -import org.jetbrains.annotations.NotNull -import org.jetbrains.annotations.Nullable -import org.jetbrains.kotlin.asJava.classes.KtLightClass -import org.jetbrains.kotlin.asJava.elements.KtLightElement -import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.getParentOfType -import org.jetbrains.kotlin.resolve.calls.callUtil.getType -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.typeUtil.TypeNullability -import org.jetbrains.kotlin.types.typeUtil.nullability -import org.jetbrains.kotlin.utils.SmartList -import org.jetbrains.uast.* -import org.jetbrains.uast.internal.acceptList -import org.jetbrains.uast.kotlin.declarations.UastLightIdentifier -import org.jetbrains.uast.kotlin.psi.UastKotlinPsiParameter -import org.jetbrains.uast.kotlin.psi.UastKotlinPsiVariable -import org.jetbrains.uast.visitor.UastVisitor - -abstract class AbstractKotlinUVariable(givenParent: UElement?) - : KotlinAbstractUElement(givenParent), PsiVariable, UVariable { - - override val uastInitializer: UExpression? - get() { - val psi = psi - val initializerExpression = when (psi) { - is UastKotlinPsiVariable -> psi.ktInitializer - is UastKotlinPsiParameter -> psi.ktDefaultValue - is KtLightElement<*, *> -> { - val origin = psi.kotlinOrigin - when (origin) { - is KtVariableDeclaration -> origin.initializer - is KtParameter -> origin.defaultValue - else -> null - } - } - else -> null - } ?: return null - return getLanguagePlugin().convertElement(initializerExpression, this) as? UExpression ?: UastEmptyExpression - } - - val delegateExpression: UExpression? by lz { - val psi = psi - val expression = when (psi) { - is KtLightElement<*, *> -> (psi.kotlinOrigin as? KtProperty)?.delegateExpression - is UastKotlinPsiVariable -> (psi.ktElement as? KtProperty)?.delegateExpression - else -> null - } - - expression?.let { getLanguagePlugin().convertElement(it, this) as? UExpression } - } - - override fun getNameIdentifier(): PsiIdentifier { - val kotlinOrigin = (psi as? KtLightElement<*, *>)?.kotlinOrigin - return UastLightIdentifier(psi, kotlinOrigin as KtNamedDeclaration?) - } - - override fun getContainingFile(): PsiFile = unwrapFakeFileForLightClass(psi.containingFile) - - override val annotations by lz { - val sourcePsi = sourcePsi ?: return@lz psi.annotations.map { WrappedUAnnotation(it, this) } - val annotations = SmartList(KotlinNullabilityUAnnotation(sourcePsi, this)) - if (sourcePsi is KtModifierListOwner) { - sourcePsi.annotationEntries. - filter { acceptsAnnotationTarget(it.useSiteTarget?.getAnnotationUseSiteTarget()) }. - mapTo(annotations) { KotlinUAnnotation(it, this) } - } - annotations - } - - - abstract protected fun acceptsAnnotationTarget(target: AnnotationUseSiteTarget?): Boolean - - override val typeReference by lz { getLanguagePlugin().convertOpt(psi.typeElement, this) } - - override val uastAnchor: UElement? - get() = UIdentifier(nameIdentifier, this) - - override fun equals(other: Any?) = other is AbstractKotlinUVariable && psi == other.psi - - class WrappedUAnnotation(psiAnnotation: PsiAnnotation, override val uastParent: UElement) : UAnnotation, - JvmDeclarationUElementPlaceholder { - - override val javaPsi: PsiAnnotation = psiAnnotation - override val psi: PsiAnnotation = javaPsi - override val sourcePsi: PsiElement? = null - - override val attributeValues: List by lz { - psi.parameterList.attributes.map { WrappedUNamedExpression(it, this) } - } - - class WrappedUNamedExpression(pair: PsiNameValuePair, override val uastParent: UElement?) : UNamedExpression, JvmDeclarationUElementPlaceholder { - override val name: String? = pair.name - override val psi = pair - override val javaPsi: PsiElement? = psi - override val sourcePsi: PsiElement? = null - override val annotations: List = emptyList() - override val expression: UExpression by lz { toUExpression(psi.value) } - } - - override val qualifiedName: String? = psi.qualifiedName - override fun findAttributeValue(name: String?): UExpression? = psi.findAttributeValue(name)?.let { toUExpression(it) } - override fun findDeclaredAttributeValue(name: String?): UExpression? = psi.findDeclaredAttributeValue(name)?.let { toUExpression(it) } - override fun resolve(): PsiClass? = psi.nameReferenceElement?.resolve() as? PsiClass - } - -} - -private fun toUExpression(psi: PsiElement?): UExpression = psi.toUElementOfType() ?: UastEmptyExpression - -class KotlinUVariable( - psi: PsiVariable, - override val sourcePsi: KtElement, - givenParent: UElement? -) : AbstractKotlinUVariable(givenParent), UVariable, PsiVariable by psi { - - override val javaPsi = unwrap(psi) - - override val psi = javaPsi - - override val typeReference by lz { getLanguagePlugin().convertOpt(psi.typeElement, this) } - - override fun acceptsAnnotationTarget(target: AnnotationUseSiteTarget?): Boolean = true - - override fun getInitializer(): PsiExpression? { - return super.getInitializer() - } - - override fun getOriginalElement(): PsiElement? { - return super.getOriginalElement() - } - - override fun getNameIdentifier(): PsiIdentifier { - return super.getNameIdentifier() - } - - override fun getContainingFile(): PsiFile { - return super.getContainingFile() - } - -} - -open class KotlinUParameter( - psi: PsiParameter, - final override val sourcePsi: KtElement?, - givenParent: UElement? -) : AbstractKotlinUVariable(givenParent), UParameter, PsiParameter by psi { - - final override val javaPsi = unwrap(psi) - - override val psi = javaPsi - - private val isLightConstructorParam by lz { psi.getParentOfType(true)?.isConstructor } - - private val isKtConstructorParam by lz { sourcePsi?.getParentOfType(true)?.let { it is KtConstructor<*> } } - - override fun acceptsAnnotationTarget(target: AnnotationUseSiteTarget?): Boolean { - if (sourcePsi !is KtParameter) return false - if (isKtConstructorParam == isLightConstructorParam && target == null) return true - when (target) { - AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER -> return isLightConstructorParam == true - AnnotationUseSiteTarget.SETTER_PARAMETER -> return isLightConstructorParam != true - else -> return false - } - } - - override fun getInitializer(): PsiExpression? { - return super.getInitializer() - } - - override fun getOriginalElement(): PsiElement? { - return super.getOriginalElement() - } - - override fun getNameIdentifier(): PsiIdentifier { - return super.getNameIdentifier() - } - - override fun getContainingFile(): PsiFile { - return super.getContainingFile() - } -} - -class KotlinReceiverUParameter( - psi: PsiParameter, - private val receiver: KtTypeReference, - givenParent: UElement? -) : KotlinUParameter(psi, receiver, givenParent) { - - override val annotations: List by lz { - receiver.annotationEntries - .filter { it.useSiteTarget?.getAnnotationUseSiteTarget() == AnnotationUseSiteTarget.RECEIVER } - .map { KotlinUAnnotation(it, this) } + - super.annotations - } - -} - -class KotlinNullabilityUAnnotation(val annotatedElement: PsiElement, override val uastParent: UElement) : UAnnotation, JvmDeclarationUElementPlaceholder { - - private fun getTargetType(annotatedElement: PsiElement): KotlinType? { - if (annotatedElement is KtTypeReference) { - annotatedElement.getType()?.let { return it } - } - if (annotatedElement is KtCallableDeclaration) { - annotatedElement.typeReference?.getType()?.let { return it } - } - if (annotatedElement is KtProperty) { - annotatedElement.initializer?.let { it.getType(it.analyze()) }?.let { return it } - annotatedElement.delegateExpression?.let { it.getType(it.analyze())?.arguments?.firstOrNull()?.type }?.let { return it } - } - annotatedElement.getParentOfType(false)?.let { - it.typeReference?.getType() ?: it.initializer?.let { it.getType(it.analyze()) } - }?.let { return it } - return null - } - - val nullability by lz { getTargetType(annotatedElement)?.nullability() } - - override val attributeValues: List - get() = emptyList() - override val psi: PsiElement? - get() = null - override val javaPsi: PsiAnnotation? - get() = null - override val sourcePsi: PsiElement? - get() = null - override val qualifiedName: String? - get() = when (nullability) { - TypeNullability.NOT_NULL -> NotNull::class.qualifiedName - TypeNullability.NULLABLE -> Nullable::class.qualifiedName - TypeNullability.FLEXIBLE -> null - null -> null - } - - override fun findAttributeValue(name: String?): UExpression? = null - - override fun findDeclaredAttributeValue(name: String?): UExpression? = null - - override fun resolve(): PsiClass? = qualifiedName?.let { - val project = annotatedElement.project - JavaPsiFacade.getInstance(project).findClass(it, GlobalSearchScope.allScope(project)) - } - -} - -open class KotlinUField( - psi: PsiField, - override val sourcePsi: KtElement?, - givenParent: UElement? -) : AbstractKotlinUVariable(givenParent), UField, PsiField by psi { - override fun getSourceElement() = sourcePsi ?: this - - override val javaPsi = unwrap(psi) - - override val psi = javaPsi - - override fun acceptsAnnotationTarget(target: AnnotationUseSiteTarget?): Boolean = - target == AnnotationUseSiteTarget.FIELD || - target == AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD || - (sourcePsi is KtProperty) && (target == null || target == AnnotationUseSiteTarget.PROPERTY) - - override fun getInitializer(): PsiExpression? { - return super.getInitializer() - } - - override fun getOriginalElement(): PsiElement? { - return super.getOriginalElement() - } - - override fun getNameIdentifier(): PsiIdentifier { - return super.getNameIdentifier() - } - - override fun getContainingFile(): PsiFile { - return super.getContainingFile() - } - - override fun isPhysical(): Boolean { - return true - } - - override fun accept(visitor: UastVisitor) { - if (visitor.visitField(this)) return - annotations.acceptList(visitor) - uastInitializer?.accept(visitor) - delegateExpression?.accept(visitor) - visitor.afterVisitField(this) - } -} - -open class KotlinULocalVariable( - psi: PsiLocalVariable, - override val sourcePsi: KtElement, - givenParent: UElement? -) : AbstractKotlinUVariable(givenParent), ULocalVariable, PsiLocalVariable by psi { - - override val javaPsi = unwrap(psi) - - override fun acceptsAnnotationTarget(target: AnnotationUseSiteTarget?): Boolean = true - - override val psi = javaPsi - - override fun getInitializer(): PsiExpression? { - return super.getInitializer() - } - - override fun getOriginalElement(): PsiElement? { - return super.getOriginalElement() - } - - override fun getNameIdentifier(): PsiIdentifier { - return super.getNameIdentifier() - } - - override fun getContainingFile(): PsiFile { - return super.getContainingFile() - } - - override fun accept(visitor: UastVisitor) { - if (visitor.visitLocalVariable(this)) return - annotations.acceptList(visitor) - uastInitializer?.accept(visitor) - delegateExpression?.accept(visitor) - visitor.afterVisitLocalVariable(this) - } -} - -open class KotlinUAnnotatedLocalVariable( - psi: PsiLocalVariable, - sourcePsi: KtElement, - uastParent: UElement?, - computeAnnotations: (parent: UElement) -> List -) : KotlinULocalVariable(psi, sourcePsi, uastParent) { - - override val annotations: List by lz { computeAnnotations(this) } -} - -class KotlinUEnumConstant( - psi: PsiEnumConstant, - override val sourcePsi: KtElement?, - givenParent: UElement? -) : AbstractKotlinUVariable(givenParent), UEnumConstant, PsiEnumConstant by psi { - - override val initializingClass: UClass? by lz { - (psi.initializingClass as? KtLightClass)?.let { initializingClass -> - KotlinUClass.create(initializingClass, this) - } - } - - override fun getInitializer(): PsiExpression? = super.getInitializer() - - override fun getOriginalElement(): PsiElement? = super.getOriginalElement() - - override val javaPsi = unwrap(psi) - - override val psi = javaPsi - - override fun acceptsAnnotationTarget(target: AnnotationUseSiteTarget?): Boolean = true - - override fun getContainingFile(): PsiFile { - return super.getContainingFile() - } - - override fun getNameIdentifier(): PsiIdentifier { - return super.getNameIdentifier() - } - - override val kind: UastCallKind - get() = UastCallKind.CONSTRUCTOR_CALL - - override val receiver: UExpression? - get() = null - - override val receiverType: PsiType? - get() = null - - override val methodIdentifier: UIdentifier? - get() = null - - override val classReference: UReferenceExpression? - get() = KotlinEnumConstantClassReference(psi, sourcePsi, this) - - override val typeArgumentCount: Int - get() = 0 - - override val typeArguments: List - get() = emptyList() - - override val valueArgumentCount: Int - get() = psi.argumentList?.expressions?.size ?: 0 - - override val valueArguments by lz(fun(): List { - val ktEnumEntry = sourcePsi as? KtEnumEntry ?: return emptyList() - val ktSuperTypeCallEntry = ktEnumEntry.initializerList?.initializers?.firstOrNull() as? KtSuperTypeCallEntry ?: return emptyList() - return ktSuperTypeCallEntry.valueArguments.map { - it.getArgumentExpression()?.let { getLanguagePlugin().convertElement(it, this) } as? UExpression ?: UastEmptyExpression - } - }) - - override val returnType: PsiType? - get() = uastParent?.getAsJavaPsiElement(PsiClass::class.java)?.let { PsiTypesUtil.getClassType(it) } - - override fun resolve() = psi.resolveMethod() - - override val methodName: String? - get() = null - - private class KotlinEnumConstantClassReference( - override val psi: PsiEnumConstant, - override val sourcePsi: KtElement?, - givenParent: UElement? - ) : KotlinAbstractUExpression(givenParent), USimpleNameReferenceExpression { - override val javaPsi: PsiElement? - get() = psi - - override fun resolve() = psi.containingClass - override val resolvedName: String? - get() = psi.containingClass?.name - override val identifier: String - get() = psi.containingClass?.name ?: "" - } -} \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/UastLightIdentifier.kt.173 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/UastLightIdentifier.kt.173 deleted file mode 100644 index 53f313d6cdf..00000000000 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/declarations/UastLightIdentifier.kt.173 +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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.declarations - -import com.intellij.psi.PsiFile -import com.intellij.psi.PsiNameIdentifierOwner -import org.jetbrains.kotlin.asJava.elements.KtLightIdentifier -import org.jetbrains.kotlin.psi.KtNamedDeclaration -import org.jetbrains.uast.kotlin.unwrapFakeFileForLightClass - -class UastLightIdentifier(lightOwner: PsiNameIdentifierOwner, ktDeclaration: KtNamedDeclaration?) - : KtLightIdentifier(lightOwner, ktDeclaration) { - override fun getContainingFile(): PsiFile = unwrapFakeFileForLightClass(super.getContainingFile()) -} diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/ElvisExpression.kt.173 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/ElvisExpression.kt.173 deleted file mode 100644 index 62fde94b261..00000000000 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/ElvisExpression.kt.173 +++ /dev/null @@ -1,120 +0,0 @@ -package org.jetbrains.uast.kotlin.expressions - -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiMethod -import com.intellij.psi.PsiType -import org.jetbrains.kotlin.psi.KtBinaryExpression -import org.jetbrains.kotlin.psi.KtExpression -import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.types.CommonSupertypes -import org.jetbrains.uast.* -import org.jetbrains.uast.kotlin.* -import org.jetbrains.uast.kotlin.kinds.KotlinSpecialExpressionKinds -import org.jetbrains.uast.kotlin.psi.UastKotlinPsiVariable - - -private fun createVariableReferenceExpression(variable: UVariable, containingElement: UElement?) = - object : USimpleNameReferenceExpression, JvmDeclarationUElementPlaceholder { - override val psi: PsiElement? = null - override fun resolve(): PsiElement? = variable - override val uastParent: UElement? = containingElement - override val resolvedName: String? = variable.name - override val annotations: List = emptyList() - override val identifier: String = variable.name.orAnonymous() - override val javaPsi: PsiElement? = null - override val sourcePsi: PsiElement? = null - } - -private fun createNullLiteralExpression(containingElement: UElement?) = - object : ULiteralExpression, JvmDeclarationUElementPlaceholder { - override val psi: PsiElement? = null - override val uastParent: UElement? = containingElement - override val value: Any? = null - override val annotations: List = emptyList() - override val javaPsi: PsiElement? = null - override val sourcePsi: PsiElement? = null - } - -private fun createNotEqWithNullExpression(variable: UVariable, containingElement: UElement?) = - object : UBinaryExpression, JvmDeclarationUElementPlaceholder { - override val psi: PsiElement? = null - override val uastParent: UElement? = containingElement - override val leftOperand: UExpression by lz { createVariableReferenceExpression(variable, this) } - override val rightOperand: UExpression by lz { createNullLiteralExpression(this) } - override val operator: UastBinaryOperator = UastBinaryOperator.NOT_EQUALS - override val operatorIdentifier: UIdentifier? = UIdentifier(null, this) - override fun resolveOperator(): PsiMethod? = null - override val annotations: List = emptyList() - override val javaPsi: PsiElement? = null - override val sourcePsi: PsiElement? = null - } - -private fun createElvisExpressions( - left: KtExpression, - right: KtExpression, - containingElement: UElement?, - psiParent: PsiElement): List { - - val declaration = KotlinUDeclarationsExpression(containingElement) - val tempVariable = KotlinULocalVariable(UastKotlinPsiVariable.create(left, declaration, psiParent), left, declaration) - declaration.declarations = listOf(tempVariable) - - val ifExpression = object : UIfExpression, JvmDeclarationUElementPlaceholder { - override val psi: PsiElement? = null - override val uastParent: UElement? = containingElement - override val javaPsi: PsiElement? = null - override val sourcePsi: PsiElement? = null - override val condition: UExpression by lz { createNotEqWithNullExpression(tempVariable, this) } - override val thenExpression: UExpression? by lz { createVariableReferenceExpression(tempVariable, this) } - override val elseExpression: UExpression? by lz { KotlinConverter.convertExpression(right, this ) } - override val isTernary: Boolean = false - override val annotations: List = emptyList() - override val ifIdentifier: UIdentifier = UIdentifier(null, this) - override val elseIdentifier: UIdentifier? = UIdentifier(null, this) - } - - return listOf(declaration, ifExpression) -} - -fun createElvisExpression(elvisExpression: KtBinaryExpression, givenParent: UElement?): UExpression { - val left = elvisExpression.left ?: return UastEmptyExpression - val right = elvisExpression.right ?: return UastEmptyExpression - - return KotlinUElvisExpression(elvisExpression, left, right, givenParent) -} - -class KotlinUElvisExpression( - private val elvisExpression: KtBinaryExpression, - private val left: KtExpression, - private val right: KtExpression, - givenParent: UElement? -) : KotlinAbstractUElement(givenParent), UExpressionList, KotlinEvaluatableUElement { - - override val javaPsi: PsiElement? = null - override val sourcePsi: PsiElement? = elvisExpression - override val psi: PsiElement? = sourcePsi - override val kind = KotlinSpecialExpressionKinds.ELVIS - override val annotations: List = emptyList() - override val expressions: List by lz { - createElvisExpressions(left, right, this, elvisExpression.parent) - } - - val lhsDeclaration get() = (expressions[0] as UDeclarationsExpression).declarations.single() - val rhsIfExpression get() = expressions[1] as UIfExpression - - override fun asRenderString(): String { - return kind.name + " " + - expressions.joinToString(separator = "\n", prefix = "{\n", postfix = "\n}") { - it.asRenderString().withMargin - } - } - - override fun getExpressionType(): PsiType? { - val leftType = left.analyze()[BindingContext.EXPRESSION_TYPE_INFO, left]?.type ?: return null - val rightType = right.analyze()[BindingContext.EXPRESSION_TYPE_INFO, right]?.type ?: return null - - return CommonSupertypes - .commonSupertype(listOf(leftType, rightType)) - .toPsiType(this, elvisExpression, boxed = false) - } -} diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUBinaryExpression.kt.173 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUBinaryExpression.kt.173 deleted file mode 100644 index 06c62b035ea..00000000000 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUBinaryExpression.kt.173 +++ /dev/null @@ -1,106 +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.uast.kotlin - -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiMethod -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.psi.KtBinaryExpression -import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe -import org.jetbrains.uast.* - -class KotlinUBinaryExpression( - override val psi: KtBinaryExpression, - givenParent: UElement? -) : KotlinAbstractUExpression(givenParent), UBinaryExpression, KotlinUElementWithType, KotlinEvaluatableUElement { - private companion object { - val BITWISE_OPERATORS = mapOf( - "or" to UastBinaryOperator.BITWISE_OR, - "and" to UastBinaryOperator.BITWISE_AND, - "xor" to UastBinaryOperator.BITWISE_XOR - ) - } - - override val leftOperand by lz { KotlinConverter.convertOrEmpty(psi.left, this) } - override val rightOperand by lz { KotlinConverter.convertOrEmpty(psi.right, this) } - - override val operatorIdentifier: UIdentifier? - get() = UIdentifier(psi.operationReference, this) - - override fun resolveOperator() = psi.operationReference.resolveCallToDeclaration(context = this) as? PsiMethod - - override val operator = when (psi.operationToken) { - KtTokens.EQ -> UastBinaryOperator.ASSIGN - KtTokens.PLUS -> UastBinaryOperator.PLUS - KtTokens.MINUS -> UastBinaryOperator.MINUS - KtTokens.MUL -> UastBinaryOperator.MULTIPLY - KtTokens.DIV -> UastBinaryOperator.DIV - KtTokens.PERC -> UastBinaryOperator.MOD - KtTokens.OROR -> UastBinaryOperator.LOGICAL_OR - KtTokens.ANDAND -> UastBinaryOperator.LOGICAL_AND - KtTokens.EQEQ -> UastBinaryOperator.EQUALS - KtTokens.EXCLEQ -> UastBinaryOperator.NOT_EQUALS - KtTokens.EQEQEQ -> UastBinaryOperator.IDENTITY_EQUALS - KtTokens.EXCLEQEQEQ -> UastBinaryOperator.IDENTITY_NOT_EQUALS - KtTokens.GT -> UastBinaryOperator.GREATER - KtTokens.GTEQ -> UastBinaryOperator.GREATER_OR_EQUALS - KtTokens.LT -> UastBinaryOperator.LESS - KtTokens.LTEQ -> UastBinaryOperator.LESS_OR_EQUALS - KtTokens.PLUSEQ -> UastBinaryOperator.PLUS_ASSIGN - KtTokens.MINUSEQ -> UastBinaryOperator.MINUS_ASSIGN - KtTokens.MULTEQ -> UastBinaryOperator.MULTIPLY_ASSIGN - KtTokens.DIVEQ -> UastBinaryOperator.DIVIDE_ASSIGN - KtTokens.PERCEQ -> UastBinaryOperator.REMAINDER_ASSIGN - KtTokens.IN_KEYWORD -> KotlinBinaryOperators.IN - KtTokens.NOT_IN -> KotlinBinaryOperators.NOT_IN - KtTokens.RANGE -> KotlinBinaryOperators.RANGE_TO - else -> run { // Handle bitwise operators - val other = UastBinaryOperator.OTHER - val ref = psi.operationReference - val resolvedCall = psi.operationReference.getResolvedCall(ref.analyze()) ?: return@run other - val resultingDescriptor = resolvedCall.resultingDescriptor as? FunctionDescriptor ?: return@run other - val applicableOperator = BITWISE_OPERATORS[resultingDescriptor.name.asString()] ?: return@run other - - val containingClass = resultingDescriptor.containingDeclaration as? ClassDescriptor ?: return@run other - if (containingClass.typeConstructor.supertypes.any { - it.constructor.declarationDescriptor?.fqNameSafe?.asString() == "kotlin.Number" - }) applicableOperator else other - } - } -} - -class KotlinCustomUBinaryExpression( - override val psi: PsiElement, - givenParent: UElement? -) : KotlinAbstractUExpression(givenParent), UBinaryExpression { - lateinit override var leftOperand: UExpression - internal set - - lateinit override var operator: UastBinaryOperator - internal set - - lateinit override var rightOperand: UExpression - internal set - - override val operatorIdentifier: UIdentifier? - get() = null - - override fun resolveOperator() = null -} \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUCollectionLiteralExpression.kt.173 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUCollectionLiteralExpression.kt.173 deleted file mode 100644 index 69ec94ebbdb..00000000000 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUCollectionLiteralExpression.kt.173 +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license - * that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.uast.kotlin.expressions - -import com.intellij.psi.PsiArrayType -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiMethod -import com.intellij.psi.PsiType -import org.jetbrains.kotlin.psi.KtCollectionLiteralExpression -import org.jetbrains.uast.* -import org.jetbrains.uast.kotlin.KotlinAbstractUExpression -import org.jetbrains.uast.kotlin.KotlinConverter -import org.jetbrains.uast.kotlin.KotlinUElementWithType - -class KotlinUCollectionLiteralExpression( - override val sourcePsi: KtCollectionLiteralExpression, - givenParent: UElement? -) : KotlinAbstractUExpression(givenParent), UCallExpression, KotlinUElementWithType { - - override val classReference: UReferenceExpression? get() = null - - override val kind: UastCallKind = UastCallKind.NESTED_ARRAY_INITIALIZER - - override val methodIdentifier: UIdentifier? by lazy { UIdentifier(sourcePsi.leftBracket, this) } - - override val methodName: String? get() = null - - override val receiver: UExpression? get() = null - - override val receiverType: PsiType? get() = null - - override val returnType: PsiType? get() = getExpressionType() - - override val typeArgumentCount: Int get() = typeArguments.size - - override val typeArguments: List get() = listOfNotNull((returnType as? PsiArrayType)?.componentType) - - override val valueArgumentCount: Int - get() = sourcePsi.getInnerExpressions().size - - override val valueArguments by lazy { - sourcePsi.getInnerExpressions().map { KotlinConverter.convertOrEmpty(it, this) } - } - - override fun asRenderString(): String = "collectionLiteral[" + valueArguments.joinToString { it.asRenderString() } + "]" - - override fun resolve(): PsiMethod? = null - - override val psi: PsiElement get() = sourcePsi - -} \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUDoWhileExpression.kt.173 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUDoWhileExpression.kt.173 deleted file mode 100644 index 8461fad28e8..00000000000 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUDoWhileExpression.kt.173 +++ /dev/null @@ -1,36 +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.uast.kotlin - -import org.jetbrains.kotlin.psi.KtDoWhileExpression -import org.jetbrains.uast.UDoWhileExpression -import org.jetbrains.uast.UElement -import org.jetbrains.uast.UIdentifier - -class KotlinUDoWhileExpression( - override val psi: KtDoWhileExpression, - givenParent: UElement? -) : KotlinAbstractUExpression(givenParent), UDoWhileExpression { - override val condition by lz { KotlinConverter.convertOrEmpty(psi.condition, this) } - override val body by lz { KotlinConverter.convertOrEmpty(psi.body, this) } - - override val doIdentifier: UIdentifier - get() = UIdentifier(null, this) - - override val whileIdentifier: UIdentifier - get() = UIdentifier(null, this) -} \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUForEachExpression.kt.173 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUForEachExpression.kt.173 deleted file mode 100644 index 7345cbe99d7..00000000000 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUForEachExpression.kt.173 +++ /dev/null @@ -1,42 +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.uast.kotlin - -import org.jetbrains.kotlin.idea.KotlinLanguage -import org.jetbrains.kotlin.psi.KtForExpression -import org.jetbrains.uast.UElement -import org.jetbrains.uast.UForEachExpression -import org.jetbrains.uast.UIdentifier -import org.jetbrains.uast.kotlin.psi.UastKotlinPsiParameter -import org.jetbrains.uast.psi.UastPsiParameterNotResolved - -class KotlinUForEachExpression( - override val psi: KtForExpression, - givenParent: UElement? -) : KotlinAbstractUExpression(givenParent), UForEachExpression { - override val iteratedValue by lz { KotlinConverter.convertOrEmpty(psi.loopRange, this) } - override val body by lz { KotlinConverter.convertOrEmpty(psi.body, this) } - - override val variable by lz { - val parameter = psi.loopParameter?.let { UastKotlinPsiParameter.create(it, psi, this, 0) } - ?: UastPsiParameterNotResolved(psi, KotlinLanguage.INSTANCE) - KotlinUParameter(parameter, psi, this) - } - - override val forIdentifier: UIdentifier - get() = UIdentifier(null, this) -} \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUFunctionCallExpression.kt.173 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUFunctionCallExpression.kt.173 deleted file mode 100644 index 8cbfe870b4d..00000000000 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUFunctionCallExpression.kt.173 +++ /dev/null @@ -1,150 +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.uast.kotlin - -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiMethod -import com.intellij.psi.PsiNamedElement -import com.intellij.psi.PsiType -import org.jetbrains.kotlin.asJava.LightClassUtil -import org.jetbrains.kotlin.asJava.toLightClass -import org.jetbrains.kotlin.descriptors.ConstructorDescriptor -import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.descriptors.Visibilities -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.parents -import org.jetbrains.kotlin.resolve.CompileTimeConstantUtils -import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall -import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall -import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall -import org.jetbrains.uast.* -import org.jetbrains.uast.internal.acceptList -import org.jetbrains.uast.visitor.UastVisitor - -class KotlinUFunctionCallExpression( - override val psi: KtCallElement, - givenParent: UElement?, - private val _resolvedCall: ResolvedCall<*>? -) : KotlinAbstractUExpression(givenParent), UCallExpression, KotlinUElementWithType { - - constructor(psi: KtCallElement, uastParent: UElement?) : this(psi, uastParent, null) - - private val resolvedCall by lz { - _resolvedCall ?: psi.getResolvedCall(psi.analyze()) - } - - override val receiverType by lz { - val resolvedCall = this.resolvedCall ?: return@lz null - val receiver = resolvedCall.dispatchReceiver ?: resolvedCall.extensionReceiver ?: return@lz null - receiver.type.toPsiType(this, psi, boxed = true) - } - - override val methodName by lz { resolvedCall?.resultingDescriptor?.name?.asString() } - - override val classReference by lz { - KotlinClassViaConstructorUSimpleReferenceExpression(psi, methodName.orAnonymous("class"), this) - } - - override val methodIdentifier by lz { - val calleeExpression = psi.calleeExpression ?: return@lz null - UIdentifier(calleeExpression, this) - } - - override val valueArgumentCount: Int - get() = psi.valueArguments.size - - override val valueArguments by lz { psi.valueArguments.map { KotlinConverter.convertOrEmpty(it.getArgumentExpression(), this) } } - - override val typeArgumentCount: Int - get() = psi.typeArguments.size - - override val typeArguments by lz { psi.typeArguments.map { it.typeReference.toPsiType(this, boxed = true) } } - - override val returnType: PsiType? - get() = getExpressionType() - - override val kind: UastCallKind by lz { - val resolvedCall = resolvedCall ?: return@lz UastCallKind.METHOD_CALL - when { - resolvedCall.resultingDescriptor is ConstructorDescriptor -> UastCallKind.CONSTRUCTOR_CALL - this.isAnnotationArgumentArrayInitializer() -> UastCallKind.NESTED_ARRAY_INITIALIZER - else -> UastCallKind.METHOD_CALL - } - } - - override val receiver: UExpression? - get() { - (uastParent as? UQualifiedReferenceExpression)?.let { - if (it.selector == this) return it.receiver - } - - val ktNameReferenceExpression = psi.calleeExpression as? KtNameReferenceExpression ?: return null - val variableCallDescriptor = - (resolvedCall as? VariableAsFunctionResolvedCall)?.variableCall?.resultingDescriptor - ?: (resolvedCall?.resultingDescriptor as? FunctionDescriptor)?.takeIf { it.visibility == Visibilities.LOCAL } - ?: return null - - // an implicit receiver for variables calls (KT-25524) - return object : KotlinAbstractUExpression(this), UReferenceExpression { - - private val resolvedDeclaration = variableCallDescriptor.toSource() - - override val psi: KtNameReferenceExpression get() = ktNameReferenceExpression - - override val resolvedName: String? get() = (resolvedDeclaration as? PsiNamedElement)?.name - - override fun resolve(): PsiElement? = resolvedDeclaration - - } - - } - - override fun resolve(): PsiMethod? { - val descriptor = resolvedCall?.resultingDescriptor ?: return null - val source = descriptor.toSource() - return resolveSource(psi, descriptor, source) - } - - override fun accept(visitor: UastVisitor) { - if (visitor.visitCallExpression(this)) return - methodIdentifier?.accept(visitor) - classReference.accept(visitor) - valueArguments.acceptList(visitor) - - visitor.afterVisitCallExpression(this) - } - - private fun isAnnotationArgumentArrayInitializer(): Boolean { - val resolvedCall = resolvedCall ?: return false - // KtAnnotationEntry -> KtValueArgumentList -> KtValueArgument -> arrayOf call - return psi.parents.elementAtOrNull(2) is KtAnnotationEntry && CompileTimeConstantUtils.isArrayFunctionCall(resolvedCall) - } - - override fun convertParent(): UElement? = super.convertParent().let { result -> - when (result) { - is UMethod -> result.uastBody ?: result - is UClass -> - result.methods - .filterIsInstance() - .firstOrNull { it.isPrimary } - ?.uastBody - ?: result - else -> result - } - } - -} \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinULabeledExpression.kt.173 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinULabeledExpression.kt.173 deleted file mode 100644 index 2130def4799..00000000000 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinULabeledExpression.kt.173 +++ /dev/null @@ -1,35 +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.uast.kotlin - -import org.jetbrains.kotlin.psi.KtLabeledExpression -import org.jetbrains.uast.UElement -import org.jetbrains.uast.UIdentifier -import org.jetbrains.uast.ULabeledExpression - -class KotlinULabeledExpression( - override val psi: KtLabeledExpression, - givenParent: UElement? -) : KotlinAbstractUExpression(givenParent), ULabeledExpression { - override val label: String - get() = psi.getLabelName().orAnonymous("label") - - override val labelIdentifier: UIdentifier? - get() = psi.getTargetLabel()?.let { UIdentifier(it, this) } - - 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/uast/kotlin/expressions/KotlinUNamedExpression.kt.173 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUNamedExpression.kt.173 deleted file mode 100644 index c8779bd6dbf..00000000000 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUNamedExpression.kt.173 +++ /dev/null @@ -1,105 +0,0 @@ -/* - * 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 - -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiType -import org.jetbrains.kotlin.psi.ValueArgument -import org.jetbrains.uast.* - -class KotlinUNamedExpression private constructor( - override val name: String?, - override val sourcePsi: PsiElement?, - givenParent: UElement?, - expressionProducer: (UElement) -> UExpression -) : KotlinAbstractUElement(givenParent), UNamedExpression { - - override val expression: UExpression by lz { expressionProducer(this) } - - override val annotations: List = emptyList() - - override val psi: PsiElement? = null - - override val javaPsi: PsiElement? = null - - companion object { - internal fun create(name: String?, valueArgument: ValueArgument, uastParent: UElement?): UNamedExpression { - val expression = valueArgument.getArgumentExpression() - return KotlinUNamedExpression(name, valueArgument.asElement(), uastParent) { expressionParent -> - expression?.let { expressionParent.getLanguagePlugin().convertOpt(it, expressionParent) } - ?: UastEmptyExpression - } - } - - internal fun create( - name: String?, - valueArguments: List, - uastParent: UElement? - ): UNamedExpression { - return KotlinUNamedExpression(name, null, uastParent) { expressionParent -> - KotlinUVarargExpression(valueArguments, expressionParent) - } - } - } -} - -class KotlinUVarargExpression( - private val valueArgs: List, - uastParent: UElement? -) : KotlinAbstractUExpression(uastParent), UCallExpression { - override val kind: UastCallKind = UastCallKind.NESTED_ARRAY_INITIALIZER - - override val valueArguments: List by lz { - valueArgs.map { - it.getArgumentExpression()?.let { argumentExpression -> - getLanguagePlugin().convert(argumentExpression, this) - } ?: UastEmptyExpression - } - } - - override val valueArgumentCount: Int - get() = valueArgs.size - - override val psi: PsiElement? - get() = null - - override val methodIdentifier: UIdentifier? - get() = null - - override val classReference: UReferenceExpression? - get() = null - - override val methodName: String? - get() = null - - override val typeArgumentCount: Int - get() = 0 - - override val typeArguments: List - get() = emptyList() - - override val returnType: PsiType? - get() = null - - override fun resolve() = null - - override val receiver: UExpression? - get() = null - - override val receiverType: PsiType? - get() = null -} diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUObjectLiteralExpression.kt.173 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUObjectLiteralExpression.kt.173 deleted file mode 100644 index 4851083d1ac..00000000000 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUObjectLiteralExpression.kt.173 +++ /dev/null @@ -1,82 +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.uast.kotlin - -import com.intellij.psi.PsiMethod -import com.intellij.psi.PsiType -import org.jetbrains.kotlin.asJava.toLightClass -import org.jetbrains.kotlin.psi.KtObjectLiteralExpression -import org.jetbrains.kotlin.psi.KtSuperTypeCallEntry -import org.jetbrains.uast.* - -class KotlinUObjectLiteralExpression( - override val psi: KtObjectLiteralExpression, - givenParent: UElement? -) : KotlinAbstractUExpression(givenParent), UObjectLiteralExpression, KotlinUElementWithType { - override val declaration: UClass by lz { - psi.objectDeclaration.toLightClass() - ?.let { getLanguagePlugin().convert(it, this) } - ?: KotlinInvalidUClass("", psi, this) - } - - override fun getExpressionType() = psi.objectDeclaration.toPsiType() - - private val superClassConstructorCall by lz { - psi.objectDeclaration.superTypeListEntries.firstOrNull { it is KtSuperTypeCallEntry } as? KtSuperTypeCallEntry - } - - override val classReference: UReferenceExpression? by lz { superClassConstructorCall?.let { ObjectLiteralClassReference(it, this) } } - - override val valueArgumentCount: Int - get() = superClassConstructorCall?.valueArguments?.size ?: 0 - - override val valueArguments by lz { - val psi = superClassConstructorCall ?: return@lz emptyList() - psi.valueArguments.map { KotlinConverter.convertOrEmpty(it.getArgumentExpression(), this) } - } - - override val typeArgumentCount: Int - get() = superClassConstructorCall?.typeArguments?.size ?: 0 - - override val typeArguments by lz { - val psi = superClassConstructorCall ?: return@lz emptyList() - psi.typeArguments.map { it.typeReference.toPsiType(this, boxed = true) } - } - - override fun resolve() = superClassConstructorCall?.resolveCallToDeclaration(this) as? PsiMethod - - private class ObjectLiteralClassReference( - override val psi: KtSuperTypeCallEntry, - givenParent: UElement? - ) : KotlinAbstractUElement(givenParent), USimpleNameReferenceExpression { - - override val javaPsi = null - override val sourcePsi = psi - - override fun resolve() = (psi.resolveCallToDeclaration(this) as? PsiMethod)?.containingClass - - override val annotations: List - get() = emptyList() - - override val resolvedName: String? - get() = identifier - - override val identifier: String - get() = psi.name ?: "" - } - -} \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUPostfixExpression.kt.173 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUPostfixExpression.kt.173 deleted file mode 100644 index 5e6963bb4fc..00000000000 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUPostfixExpression.kt.173 +++ /dev/null @@ -1,46 +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.uast.kotlin - -import com.intellij.psi.PsiMethod -import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.psi.KtPostfixExpression -import org.jetbrains.uast.* - -class KotlinUPostfixExpression( - override val psi: KtPostfixExpression, - givenParent: UElement? -) : KotlinAbstractUExpression(givenParent), UPostfixExpression, KotlinUElementWithType, KotlinEvaluatableUElement, UResolvable { - override val operand by lz { KotlinConverter.convertOrEmpty(psi.baseExpression, this) } - - override val operator = when (psi.operationToken) { - KtTokens.PLUSPLUS -> UastPostfixOperator.INC - KtTokens.MINUSMINUS -> UastPostfixOperator.DEC - KtTokens.EXCLEXCL -> KotlinPostfixOperators.EXCLEXCL - else -> UastPostfixOperator.UNKNOWN - } - - override val operatorIdentifier: UIdentifier? - get() = UIdentifier(psi.operationReference, this) - - override fun resolveOperator() = psi.operationReference.resolveCallToDeclaration(context = this) as? PsiMethod - - override fun resolve(): PsiMethod? = when (psi.operationToken) { - KtTokens.EXCLEXCL -> operand.tryResolve() as? PsiMethod - else -> null - } -} \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUPrefixExpression.kt.173 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUPrefixExpression.kt.173 deleted file mode 100644 index af7d2f999d3..00000000000 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUPrefixExpression.kt.173 +++ /dev/null @@ -1,46 +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.uast.kotlin - -import com.intellij.psi.PsiMethod -import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.psi.KtPrefixExpression -import org.jetbrains.uast.UElement -import org.jetbrains.uast.UIdentifier -import org.jetbrains.uast.UPrefixExpression -import org.jetbrains.uast.UastPrefixOperator - -class KotlinUPrefixExpression( - override val psi: KtPrefixExpression, - givenParent: UElement? -) : KotlinAbstractUExpression(givenParent), UPrefixExpression, KotlinUElementWithType, KotlinEvaluatableUElement { - override val operand by lz { KotlinConverter.convertOrEmpty(psi.baseExpression, this) } - - override val operatorIdentifier: UIdentifier? - get() = UIdentifier(psi.operationReference, this) - - override fun resolveOperator() = psi.operationReference.resolveCallToDeclaration(context = this) as? PsiMethod - - 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 - KtTokens.MINUSMINUS -> UastPrefixOperator.DEC - else -> UastPrefixOperator.UNKNOWN - } -} \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUSimpleReferenceExpression.kt.173 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUSimpleReferenceExpression.kt.173 deleted file mode 100644 index c3af9a0fd5f..00000000000 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUSimpleReferenceExpression.kt.173 +++ /dev/null @@ -1,220 +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.uast.kotlin - -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiMethod -import com.intellij.psi.PsiNamedElement -import org.jetbrains.kotlin.descriptors.CallableDescriptor -import org.jetbrains.kotlin.descriptors.ConstructorDescriptor -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.getAssignmentByLHS -import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelectorOrThis -import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall -import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall -import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor -import org.jetbrains.kotlin.utils.addToStdlib.constant -import org.jetbrains.uast.* -import org.jetbrains.uast.visitor.UastVisitor - -open class KotlinUSimpleReferenceExpression( - override val psi: KtSimpleNameExpression, - givenParent: UElement? -) : KotlinAbstractUExpression(givenParent), USimpleNameReferenceExpression, KotlinUElementWithType, KotlinEvaluatableUElement { - private val resolvedDeclaration by lz { psi.resolveCallToDeclaration(this) } - - override val identifier get() = psi.getReferencedName() - - override fun resolve() = resolvedDeclaration - - override val resolvedName: String? - get() = (resolvedDeclaration as? PsiNamedElement)?.name - - override fun accept(visitor: UastVisitor) { - visitor.visitSimpleNameReferenceExpression(this) - - if (psi.parent.destructuringDeclarationInitializer != true) { - visitAccessorCalls(visitor) - } - - visitor.afterVisitSimpleNameReferenceExpression(this) - } - - private fun visitAccessorCalls(visitor: UastVisitor) { - // Visit Kotlin get-set synthetic Java property calls as function calls - val bindingContext = psi.analyze() - val access = psi.readWriteAccess() - val resolvedCall = psi.getResolvedCall(bindingContext) - val resultingDescriptor = resolvedCall?.resultingDescriptor as? SyntheticJavaPropertyDescriptor - if (resultingDescriptor != null) { - val setterValue = if (access.isWrite) { - findAssignment(psi, psi.parent)?.right ?: run { - visitor.afterVisitSimpleNameReferenceExpression(this) - return - } - } else { - null - } - - if (resolvedCall != null) { - if (access.isRead) { - val getDescriptor = resultingDescriptor.getMethod - KotlinAccessorCallExpression(psi, this, resolvedCall, getDescriptor, null).accept(visitor) - } - - if (access.isWrite && setterValue != null) { - val setDescriptor = resultingDescriptor.setMethod - if (setDescriptor != null) { - KotlinAccessorCallExpression(psi, this, resolvedCall, setDescriptor, setterValue).accept(visitor) - } - } - } - } - } - - private tailrec fun findAssignment(prev: PsiElement?, element: PsiElement?): KtBinaryExpression? = when (element) { - is KtBinaryExpression -> if (element.left == prev && element.operationToken == KtTokens.EQ) element else null - is KtQualifiedExpression -> findAssignment(element, element.parent) - is KtSimpleNameExpression -> findAssignment(element, element.parent) - else -> null - } - - class KotlinAccessorCallExpression( - override val psi: KtElement, - override val uastParent: KotlinUSimpleReferenceExpression, - private val resolvedCall: ResolvedCall<*>, - private val accessorDescriptor: DeclarationDescriptor, - val setterValue: KtExpression? - ) : UCallExpression, JvmDeclarationUElementPlaceholder { - override val methodName: String? - get() = accessorDescriptor.name.asString() - - override val receiver: UExpression? - get() { - val containingElement = uastParent.uastParent - return if (containingElement is UQualifiedReferenceExpression && containingElement.selector == this) - containingElement.receiver - else - null - } - - override val javaPsi: PsiElement? = null - override val sourcePsi: PsiElement? = psi - - override val annotations: List - get() = emptyList() - - override val receiverType by lz { - val type = (resolvedCall.dispatchReceiver ?: resolvedCall.extensionReceiver)?.type ?: return@lz null - type.toPsiType(this, psi, boxed = true) - } - - override val methodIdentifier: UIdentifier? - get() = UIdentifier(uastParent.psi, this) - - override val classReference: UReferenceExpression? - get() = null - - override val valueArgumentCount: Int - get() = if (setterValue != null) 1 else 0 - - override val valueArguments by lz { - if (setterValue != null) - listOf(KotlinConverter.convertOrEmpty(setterValue, this)) - else - emptyList() - } - - override val typeArgumentCount: Int - get() = resolvedCall.typeArguments.size - - override val typeArguments by lz { - resolvedCall.typeArguments.values.map { it.toPsiType(this, psi, true) } - } - - override val returnType by lz { - (accessorDescriptor as? CallableDescriptor)?.returnType?.toPsiType(this, psi, boxed = false) - } - - override val kind: UastCallKind - get() = UastCallKind.METHOD_CALL - - override fun resolve(): PsiMethod? { - val source = accessorDescriptor.toSource() - return resolveSource(psi, accessorDescriptor, source) - } - } - - enum class ReferenceAccess(val isRead: Boolean, val isWrite: Boolean) { - READ(true, false), WRITE(false, true), READ_WRITE(true, true) - } - - private fun KtExpression.readWriteAccess(): ReferenceAccess { - var expression = getQualifiedExpressionForSelectorOrThis() - loop@ while (true) { - val parent = expression.parent - when (parent) { - is KtParenthesizedExpression, is KtAnnotatedExpression, is KtLabeledExpression -> expression = parent as KtExpression - else -> break@loop - } - } - - val assignment = expression.getAssignmentByLHS() - if (assignment != null) { - return when (assignment.operationToken) { - KtTokens.EQ -> ReferenceAccess.WRITE - else -> ReferenceAccess.READ_WRITE - } - } - - return if ((expression.parent as? KtUnaryExpression)?.operationToken - in constant { setOf(KtTokens.PLUSPLUS, KtTokens.MINUSMINUS) }) - ReferenceAccess.READ_WRITE - else - ReferenceAccess.READ - } -} - -class KotlinClassViaConstructorUSimpleReferenceExpression( - override val psi: KtCallElement, - override val identifier: String, - givenParent: UElement? -) : KotlinAbstractUExpression(givenParent), USimpleNameReferenceExpression, KotlinUElementWithType { - override val resolvedName: String? - get() = (psi.getResolvedCall(psi.analyze())?.resultingDescriptor as? ConstructorDescriptor) - ?.containingDeclaration?.name?.asString() - - override fun resolve(): PsiElement? { - val resolvedCall = psi.getResolvedCall(psi.analyze()) - val resultingDescriptor = resolvedCall?.resultingDescriptor as? ConstructorDescriptor ?: return null - val clazz = resultingDescriptor.containingDeclaration - return clazz.toSource()?.getMaybeLightElement(this) - } -} - -class KotlinStringUSimpleReferenceExpression( - override val identifier: String, - givenParent: UElement? -) : KotlinAbstractUExpression(givenParent), USimpleNameReferenceExpression { - override val psi: PsiElement? - get() = null - override fun resolve() = null - override val resolvedName: String? - get() = identifier -} \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUSuperExpression.kt.173 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUSuperExpression.kt.173 deleted file mode 100644 index b87476a1f9b..00000000000 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUSuperExpression.kt.173 +++ /dev/null @@ -1,36 +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.uast.kotlin - -import org.jetbrains.kotlin.psi.KtSuperExpression -import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.uast.UElement -import org.jetbrains.uast.UIdentifier -import org.jetbrains.uast.USuperExpression - -class KotlinUSuperExpression( - override val psi: KtSuperExpression, - givenParent: UElement? -) : KotlinAbstractUExpression(givenParent), USuperExpression, KotlinUElementWithType, KotlinEvaluatableUElement { - override val label: String? - get() = psi.getLabelName() - - override val labelIdentifier: UIdentifier? - get() = psi.getTargetLabel()?.let { UIdentifier(it, this) } - - override fun resolve() = psi.analyze()[BindingContext.LABEL_TARGET, psi.getTargetLabel()] -} \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUSwitchExpression.kt.173 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUSwitchExpression.kt.173 deleted file mode 100644 index 47e8f14fcc3..00000000000 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUSwitchExpression.kt.173 +++ /dev/null @@ -1,93 +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.uast.kotlin - -import com.intellij.psi.PsiElement -import org.jetbrains.kotlin.psi.KtBlockExpression -import org.jetbrains.kotlin.psi.KtWhenEntry -import org.jetbrains.kotlin.psi.KtWhenExpression -import org.jetbrains.uast.* -import org.jetbrains.uast.kotlin.kinds.KotlinSpecialExpressionKinds - -class KotlinUSwitchExpression( - override val psi: KtWhenExpression, - givenParent: UElement? -) : KotlinAbstractUExpression(givenParent), USwitchExpression, KotlinUElementWithType { - override val expression by lz { KotlinConverter.convertOrNull(psi.subjectExpression, this) } - - override val body: UExpressionList by lz { - object : KotlinUExpressionList(psi, KotlinSpecialExpressionKinds.WHEN, this@KotlinUSwitchExpression) { - override fun asRenderString() = expressions.joinToString("\n") { it.asRenderString().withMargin } - }.apply { - expressions = this@KotlinUSwitchExpression.psi.entries.map { KotlinUSwitchEntry(it, this) } - } - } - - override fun asRenderString() = buildString { - val expr = expression?.let { "(" + it.asRenderString() + ") " } ?: "" - appendln("switch $expr {") - appendln(body.asRenderString()) - appendln("}") - } - - override val switchIdentifier: UIdentifier - get() = UIdentifier(null, this) -} - -class KotlinUSwitchEntry( - override val psi: KtWhenEntry, - givenParent: UElement? -) : KotlinAbstractUExpression(givenParent), USwitchClauseExpressionWithBody { - override val caseValues by lz { - psi.conditions.map { KotlinConverter.convertWhenCondition(it, this) ?: UastEmptyExpression } - } - - override val body: UExpressionList by lz { - object : KotlinUExpressionList(psi, KotlinSpecialExpressionKinds.WHEN_ENTRY, this@KotlinUSwitchEntry) { - override fun asRenderString() = buildString { - appendln("{") - expressions.forEach { appendln(it.asRenderString().withMargin) } - appendln("}") - } - }.apply { - val exprPsi = this@KotlinUSwitchEntry.psi.expression - val userExpressions = when (exprPsi) { - is KtBlockExpression -> exprPsi.statements.map { KotlinConverter.convertOrEmpty(it, this) } - else -> listOf(KotlinConverter.convertOrEmpty(exprPsi, this)) - } - expressions = userExpressions + object : UBreakExpression, JvmDeclarationUElementPlaceholder { - override val javaPsi: PsiElement? = null - override val sourcePsi: PsiElement? = null - override val psi: PsiElement? - get() = null - override val label: String? - get() = null - override val uastParent: UElement? - get() = this@KotlinUSwitchEntry - override val annotations: List - get() = emptyList() - } - } - } - - override fun convertParent(): UElement? { - val result = KotlinConverter.unwrapElements(psi.parent)?.let { parentUnwrapped -> - KotlinUastLanguagePlugin().convertElementWithParent(parentUnwrapped, null) - } - return (result as? KotlinUSwitchExpression)?.body ?: result - } -} \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUThisExpression.kt.173 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUThisExpression.kt.173 deleted file mode 100644 index ca81276a4db..00000000000 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUThisExpression.kt.173 +++ /dev/null @@ -1,36 +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.uast.kotlin - -import org.jetbrains.kotlin.psi.KtThisExpression -import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.uast.UElement -import org.jetbrains.uast.UIdentifier -import org.jetbrains.uast.UThisExpression - -class KotlinUThisExpression( - override val psi: KtThisExpression, - givenParent: UElement? -) : KotlinAbstractUExpression(givenParent), UThisExpression, KotlinUElementWithType, KotlinEvaluatableUElement { - override val label: String? - get() = psi.getLabelName() - - override val labelIdentifier: UIdentifier? - get() = psi.getTargetLabel()?.let { UIdentifier(it, this) } - - override fun resolve() = psi.analyze()[BindingContext.LABEL_TARGET, psi.getTargetLabel()] -} \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUTryExpression.kt.173 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUTryExpression.kt.173 deleted file mode 100644 index 544ea9db537..00000000000 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUTryExpression.kt.173 +++ /dev/null @@ -1,44 +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.uast.kotlin - -import org.jetbrains.kotlin.psi.KtTryExpression -import org.jetbrains.uast.UElement -import org.jetbrains.uast.UIdentifier -import org.jetbrains.uast.UTryExpression -import org.jetbrains.uast.UVariable - -class KotlinUTryExpression( - override val psi: KtTryExpression, - givenParent: UElement? -) : KotlinAbstractUExpression(givenParent), UTryExpression, KotlinUElementWithType { - override val tryClause by lz { KotlinConverter.convertOrEmpty(psi.tryBlock, this) } - override val catchClauses by lz { psi.catchClauses.map { KotlinUCatchClause(it, this) } } - override val finallyClause by lz { psi.finallyBlock?.finalExpression?.let { KotlinConverter.convertExpression(it, this) } } - - override val resourceVariables: List - get() = emptyList() - - override val hasResources: Boolean - get() = false - - override val tryIdentifier: UIdentifier - get() = UIdentifier(null, this) - - override val finallyIdentifier: UIdentifier? - get() = null -} \ No newline at end of file diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUWhileExpression.kt.173 b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUWhileExpression.kt.173 deleted file mode 100644 index 2032dfa4210..00000000000 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/expressions/KotlinUWhileExpression.kt.173 +++ /dev/null @@ -1,33 +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.uast.kotlin - -import org.jetbrains.kotlin.psi.KtWhileExpression -import org.jetbrains.uast.UElement -import org.jetbrains.uast.UIdentifier -import org.jetbrains.uast.UWhileExpression - -class KotlinUWhileExpression( - override val psi: KtWhileExpression, - givenParent: UElement? -) : KotlinAbstractUExpression(givenParent), UWhileExpression { - override val condition by lz { KotlinConverter.convertOrEmpty(psi.condition, this) } - override val body by lz { KotlinConverter.convertOrEmpty(psi.body, this) } - - override val whileIdentifier: UIdentifier - get() = UIdentifier(null, this) -} \ No newline at end of file diff --git a/plugins/uast-kotlin/testData/Anonymous.identifiers.txt.173 b/plugins/uast-kotlin/testData/Anonymous.identifiers.txt.173 deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/plugins/uast-kotlin/testData/ClassAnnotation.identifiers.txt.173 b/plugins/uast-kotlin/testData/ClassAnnotation.identifiers.txt.173 deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/plugins/uast-kotlin/testData/Constructors.identifiers.txt.173 b/plugins/uast-kotlin/testData/Constructors.identifiers.txt.173 deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/plugins/uast-kotlin/testData/LocalDeclarations.identifiers.txt.173 b/plugins/uast-kotlin/testData/LocalDeclarations.identifiers.txt.173 deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/plugins/uast-kotlin/testData/LocalDeclarations.kt.173 b/plugins/uast-kotlin/testData/LocalDeclarations.kt.173 deleted file mode 100644 index ff45265e296..00000000000 --- a/plugins/uast-kotlin/testData/LocalDeclarations.kt.173 +++ /dev/null @@ -1,12 +0,0 @@ -fun foo(): Boolean { - class Local - fun bar() = Local() - - val baz = fun() { - Local() - } - - fun Int.someLocalFun(text: String) = 42 - - return bar() == Local() -} \ No newline at end of file diff --git a/plugins/uast-kotlin/testData/LocalDeclarations.log.txt.173 b/plugins/uast-kotlin/testData/LocalDeclarations.log.txt.173 deleted file mode 100644 index 26480d28ca7..00000000000 --- a/plugins/uast-kotlin/testData/LocalDeclarations.log.txt.173 +++ /dev/null @@ -1,34 +0,0 @@ -UFile (package = ) - UClass (name = LocalDeclarationsKt) - UAnnotationMethod (name = foo) - UBlockExpression - UDeclarationsExpression - UClass (name = Local) - UAnnotationMethod (name = LocalDeclarationsKt$foo$Local) - UDeclarationsExpression - UVariable (name = bar) - ULambdaExpression - UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) - UIdentifier (Identifier (Local)) - USimpleNameReferenceExpression (identifier = ) - UDeclarationsExpression - ULocalVariable (name = baz) - ULambdaExpression - UBlockExpression - UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) - UIdentifier (Identifier (Local)) - USimpleNameReferenceExpression (identifier = ) - UDeclarationsExpression - UVariable (name = someLocalFun) - ULambdaExpression - UParameter (name = text) - UAnnotation (fqName = org.jetbrains.annotations.NotNull) - ULiteralExpression (value = 42) - UReturnExpression - UBinaryExpression (operator = ==) - UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) - UIdentifier (Identifier (bar)) - USimpleNameReferenceExpression (identifier = bar) - UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) - UIdentifier (Identifier (Local)) - USimpleNameReferenceExpression (identifier = ) diff --git a/plugins/uast-kotlin/testData/LocalDeclarations.render.txt.173 b/plugins/uast-kotlin/testData/LocalDeclarations.render.txt.173 deleted file mode 100644 index b287c0bb920..00000000000 --- a/plugins/uast-kotlin/testData/LocalDeclarations.render.txt.173 +++ /dev/null @@ -1,17 +0,0 @@ -public final class LocalDeclarationsKt { - public static final fun foo() : boolean { - public static final class Local { - public fun LocalDeclarationsKt$foo$Local() = UastEmptyExpression - } - var bar: = fun () { - () - } - var baz: kotlin.jvm.functions.Function0 = fun () { - () - } - var someLocalFun: kotlin.jvm.functions.Function2 = fun (@org.jetbrains.annotations.NotNull var text: java.lang.String) { - 42 - } - return bar() == () - } -} diff --git a/plugins/uast-kotlin/testData/LocalDeclarations.types.txt.173 b/plugins/uast-kotlin/testData/LocalDeclarations.types.txt.173 deleted file mode 100644 index 8310b9965b3..00000000000 --- a/plugins/uast-kotlin/testData/LocalDeclarations.types.txt.173 +++ /dev/null @@ -1,34 +0,0 @@ -UFile (package = ) [public final class LocalDeclarationsKt {...] - UClass (name = LocalDeclarationsKt) [public final class LocalDeclarationsKt {...}] - UAnnotationMethod (name = foo) [public static final fun foo() : boolean {...}] - UBlockExpression [{...}] : PsiType:Void - UDeclarationsExpression [public static final class Local {...}] - UClass (name = Local) [public static final class Local {...}] - UAnnotationMethod (name = LocalDeclarationsKt$foo$Local) [public fun LocalDeclarationsKt$foo$Local() = UastEmptyExpression] - UDeclarationsExpression [var bar: = fun () {...}] - UVariable (name = bar) [var bar: = fun () {...}] - ULambdaExpression [fun () {...}] - UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) [()] : PsiType: - UIdentifier (Identifier (Local)) [UIdentifier (Identifier (Local))] - USimpleNameReferenceExpression (identifier = ) [] : PsiType: - UDeclarationsExpression [var baz: kotlin.jvm.functions.Function0 = fun () {...}] - ULocalVariable (name = baz) [var baz: kotlin.jvm.functions.Function0 = fun () {...}] - ULambdaExpression [fun () {...}] - UBlockExpression [{...}] : PsiType: - UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) [()] : PsiType: - UIdentifier (Identifier (Local)) [UIdentifier (Identifier (Local))] - USimpleNameReferenceExpression (identifier = ) [] : PsiType: - UDeclarationsExpression [var someLocalFun: kotlin.jvm.functions.Function2 = fun (@org.jetbrains.annotations.NotNull var text: java.lang.String) {...}] - UVariable (name = someLocalFun) [var someLocalFun: kotlin.jvm.functions.Function2 = fun (@org.jetbrains.annotations.NotNull var text: java.lang.String) {...}] - ULambdaExpression [fun (@org.jetbrains.annotations.NotNull var text: java.lang.String) {...}] - UParameter (name = text) [@org.jetbrains.annotations.NotNull var text: java.lang.String] - UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull] - ULiteralExpression (value = 42) [42] : PsiType:int - UReturnExpression [return bar() == ()] : PsiType:Void - UBinaryExpression (operator = ==) [bar() == ()] : PsiType:boolean - UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) [bar()] : PsiType: - UIdentifier (Identifier (bar)) [UIdentifier (Identifier (bar))] - USimpleNameReferenceExpression (identifier = bar) [bar] : PsiType: - UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) [()] : PsiType: - UIdentifier (Identifier (Local)) [UIdentifier (Identifier (Local))] - USimpleNameReferenceExpression (identifier = ) [] : PsiType: diff --git a/plugins/uast-kotlin/testData/LocalDeclarations.values.txt.173 b/plugins/uast-kotlin/testData/LocalDeclarations.values.txt.173 deleted file mode 100644 index 69f4beabfb2..00000000000 --- a/plugins/uast-kotlin/testData/LocalDeclarations.values.txt.173 +++ /dev/null @@ -1,34 +0,0 @@ -UFile (package = ) [public final class LocalDeclarationsKt {...] - UClass (name = LocalDeclarationsKt) [public final class LocalDeclarationsKt {...}] - UAnnotationMethod (name = foo) [public static final fun foo() : boolean {...}] - UBlockExpression [{...}] = Nothing - UDeclarationsExpression [public static final class Local {...}] = Undetermined - UClass (name = Local) [public static final class Local {...}] - UAnnotationMethod (name = LocalDeclarationsKt$foo$Local) [public fun LocalDeclarationsKt$foo$Local() = UastEmptyExpression] - UDeclarationsExpression [var bar: = fun () {...}] = Undetermined - UVariable (name = bar) [var bar: = fun () {...}] - ULambdaExpression [fun () {...}] = Undetermined - UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) [()] = external ()() - UIdentifier (Identifier (Local)) [UIdentifier (Identifier (Local))] - USimpleNameReferenceExpression (identifier = ) [] = external ()() - UDeclarationsExpression [var baz: kotlin.jvm.functions.Function0 = fun () {...}] = Undetermined - ULocalVariable (name = baz) [var baz: kotlin.jvm.functions.Function0 = fun () {...}] - ULambdaExpression [fun () {...}] = Undetermined - UBlockExpression [{...}] = external ()() - UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) [()] = external ()() - UIdentifier (Identifier (Local)) [UIdentifier (Identifier (Local))] - USimpleNameReferenceExpression (identifier = ) [] = external ()() - UDeclarationsExpression [var someLocalFun: kotlin.jvm.functions.Function2 = fun (@org.jetbrains.annotations.NotNull var text: java.lang.String) {...}] = Undetermined - UVariable (name = someLocalFun) [var someLocalFun: kotlin.jvm.functions.Function2 = fun (@org.jetbrains.annotations.NotNull var text: java.lang.String) {...}] - ULambdaExpression [fun (@org.jetbrains.annotations.NotNull var text: java.lang.String) {...}] = Undetermined - UParameter (name = text) [@org.jetbrains.annotations.NotNull var text: java.lang.String] - UAnnotation (fqName = org.jetbrains.annotations.NotNull) [@org.jetbrains.annotations.NotNull] - ULiteralExpression (value = 42) [42] = 42 - UReturnExpression [return bar() == ()] = Nothing - UBinaryExpression (operator = ==) [bar() == ()] = Undetermined - UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) [bar()] = external bar()() - UIdentifier (Identifier (bar)) [UIdentifier (Identifier (bar))] - USimpleNameReferenceExpression (identifier = bar) [bar] = external bar()() - UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) [()] = external ()() - UIdentifier (Identifier (Local)) [UIdentifier (Identifier (Local))] - USimpleNameReferenceExpression (identifier = ) [] = external ()() diff --git a/plugins/uast-kotlin/testData/SimpleAnnotated.identifiers.txt.173 b/plugins/uast-kotlin/testData/SimpleAnnotated.identifiers.txt.173 deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/plugins/uast-kotlin/testData/SimpleAnnotated.kt.173 b/plugins/uast-kotlin/testData/SimpleAnnotated.kt.173 deleted file mode 100644 index b0742abd2f4..00000000000 --- a/plugins/uast-kotlin/testData/SimpleAnnotated.kt.173 +++ /dev/null @@ -1,9 +0,0 @@ -class SimpleAnnotated { - @Suppress("abc") - fun method() { - println("Hello, world!") - } - - @SinceKotlin("1.0") - val property: String = "Mary" -} \ No newline at end of file diff --git a/plugins/uast-kotlin/tests/AbstractKotlinIdentifiersTest.kt.173 b/plugins/uast-kotlin/tests/AbstractKotlinIdentifiersTest.kt.173 deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/plugins/uast-kotlin/tests/AbstractKotlinRenderLogTest.kt.173 b/plugins/uast-kotlin/tests/AbstractKotlinRenderLogTest.kt.173 deleted file mode 100644 index 23f02ba1b5b..00000000000 --- a/plugins/uast-kotlin/tests/AbstractKotlinRenderLogTest.kt.173 +++ /dev/null @@ -1,140 +0,0 @@ -package org.jetbrains.uast.test.kotlin - -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiFile -import com.intellij.psi.PsiRecursiveElementVisitor -import com.intellij.psi.impl.source.tree.LeafPsiElement -import org.jetbrains.kotlin.psi.KtElement -import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.utils.addToStdlib.assertedCast -import org.jetbrains.uast.UDeclaration -import org.jetbrains.uast.UElement -import org.jetbrains.uast.UFile -import org.jetbrains.uast.kotlin.JvmDeclarationUElementPlaceholder -import org.jetbrains.uast.kotlin.KOTLIN_CACHED_UELEMENT_KEY -import org.jetbrains.uast.kotlin.KotlinUastLanguagePlugin -import org.jetbrains.uast.sourcePsiElement -import org.jetbrains.uast.test.common.RenderLogTestBase -import org.jetbrains.uast.visitor.UastVisitor -import org.junit.Assert -import java.io.File -import java.util.* - -abstract class AbstractKotlinRenderLogTest : AbstractKotlinUastTest(), RenderLogTestBase { - override fun getTestFile(testName: String, ext: String) = - File(File(TEST_KOTLIN_MODEL_DIR, testName).canonicalPath + '.' + ext) - - override fun check(testName: String, file: UFile) { - check(testName, file, true) - } - - fun check(testName: String, file: UFile, checkParentConsistency: Boolean) { - super.check(testName, file) - - if (checkParentConsistency) { - checkParentConsistency(file) - } - - file.checkContainingFileForAllElements() - file.checkJvmDeclarationsImplementations() - } - - private fun checkParentConsistency(file: UFile) { - val parentMap = mutableMapOf>() - - operator fun MutableMap>.get(psi: PsiElement, cls: String?) = - parentMap.getOrPut(psi) { mutableMapOf() }[cls] - - operator fun MutableMap>.set(psi: PsiElement, cls: String, v: String) { - parentMap.getOrPut(psi) { mutableMapOf() }[cls] = v - } - - file.accept(object : UastVisitor { - private val parentStack = Stack() - - override fun visitElement(node: UElement): Boolean { - val parent = node.uastParent - if (parent == null) { - Assert.assertTrue("Wrong parent of $node", parentStack.empty()) - } - else { - Assert.assertEquals("Wrong parent of $node", parentStack.peek(), parent) - } - node.sourcePsiElement?.let { - parentMap[it, node.asLogString()] = parentStack.reversed().joinToString { it.asLogString() } - } - parentStack.push(node) - return false - } - - override fun afterVisitElement(node: UElement) { - super.afterVisitElement(node) - parentStack.pop() - } - }) - - file.psi.clearUastCaches() - - file.psi.accept(object : PsiRecursiveElementVisitor() { - override fun visitElement(element: PsiElement) { - val uElement = KotlinUastLanguagePlugin().convertElementWithParent(element, null) - val expectedParents = parentMap[element, uElement?.asLogString()] - if (expectedParents != null) { - assertNotNull("Expected to be able to convert PSI element $element", uElement) - val parents = generateSequence(uElement!!.uastParent) { it.uastParent }.joinToString { it.asLogString() } - assertEquals("Inconsistent parents for ${uElement.asRenderString()}(${uElement.asLogString()})(${uElement.javaClass}) (converted from $element[${element.text}])", expectedParents, parents) - } - super.visitElement(element) - } - }) - } - - private fun UFile.checkContainingFileForAllElements() { - accept(object : UastVisitor { - override fun visitElement(node: UElement): Boolean { - if (node is PsiElement) { - node.containingFile.assertedCast { "containingFile should be KtFile for ${node.asLogString()}" } - } - - val anchorPsi = (node as? UDeclaration)?.uastAnchor?.psi - if (anchorPsi != null) { - anchorPsi.containingFile.assertedCast { "uastAnchor.containingFile should be KtFile for ${node.asLogString()}" } - } - - return false - } - }) - } - - private fun UFile.checkJvmDeclarationsImplementations() { - accept(object : UastVisitor { - override fun visitElement(node: UElement): Boolean { - - val jvmDeclaration = node as? JvmDeclarationUElementPlaceholder - ?: throw AssertionError("${node.javaClass} should implement 'JvmDeclarationUElement'") - - jvmDeclaration.sourcePsi?.let { - assertTrue("sourcePsi should be physical but ${it.javaClass} found for [${it.text}] " + - "for ${jvmDeclaration.javaClass}->${jvmDeclaration.uastParent?.javaClass}", - it is KtElement || it is LeafPsiElement - ) - } - jvmDeclaration.javaPsi?.let { - assertTrue("javaPsi should be light but ${it.javaClass} found for [${it.text}] " + - "for ${jvmDeclaration.javaClass}->${jvmDeclaration.uastParent?.javaClass}", it !is KtElement) - } - - return false - } - }) - } -} - -private fun PsiFile.clearUastCaches() { - accept(object : PsiRecursiveElementVisitor() { - override fun visitElement(element: PsiElement) { - super.visitElement(element) - element.putUserData(KOTLIN_CACHED_UELEMENT_KEY, null) - } - }) -} diff --git a/plugins/uast-kotlin/tests/KotlinUastApiTest.kt.173 b/plugins/uast-kotlin/tests/KotlinUastApiTest.kt.173 deleted file mode 100644 index 33d093dfcf4..00000000000 --- a/plugins/uast-kotlin/tests/KotlinUastApiTest.kt.173 +++ /dev/null @@ -1,424 +0,0 @@ -package org.jetbrains.uast.test.kotlin - -import com.intellij.psi.PsiAnnotation -import com.intellij.psi.PsiModifier -import com.intellij.testFramework.UsefulTestCase -import org.jetbrains.kotlin.asJava.toLightAnnotation -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.getParentOfType -import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf -import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase -import org.jetbrains.kotlin.utils.addToStdlib.assertedCast -import org.jetbrains.kotlin.utils.addToStdlib.cast -import org.jetbrains.kotlin.utils.sure -import org.jetbrains.uast.* -import org.jetbrains.uast.kotlin.KotlinUastLanguagePlugin -import org.jetbrains.uast.test.env.findElementByText -import org.jetbrains.uast.test.env.findElementByTextFromPsi -import org.jetbrains.uast.visitor.AbstractUastVisitor -import org.junit.Assert -import org.junit.Test - - -class KotlinUastApiTest : AbstractKotlinUastTest() { - override fun check(testName: String, file: UFile) { - } - - @Test fun testAnnotationParameters() { - doTest("AnnotationParameters") { _, file -> - val annotation = file.findElementByText("@IntRange(from = 10, to = 0)") - assertEquals(annotation.findAttributeValue("from")?.evaluate(), 10) - val toAttribute = annotation.findAttributeValue("to")!! - assertEquals(toAttribute.evaluate(), 0) - KtUsefulTestCase.assertInstanceOf(annotation.psi.toUElement(), UAnnotation::class.java) - KtUsefulTestCase.assertInstanceOf( - annotation.psi.cast().toLightAnnotation().toUElement(), - UAnnotation::class.java - ) - KtUsefulTestCase.assertInstanceOf(toAttribute.uastParent, UNamedExpression::class.java) - KtUsefulTestCase.assertInstanceOf(toAttribute.psi.toUElement()?.uastParent, UNamedExpression::class.java) - } - } - - @Test fun testConvertStringTemplate() { - doTest("StringTemplateInClass") { _, file -> - val literalExpression = file.findElementByText("lorem") - val psi = literalExpression.psi!! - Assert.assertTrue(psi is KtLiteralStringTemplateEntry) - val literalExpressionAgain = psi.toUElement() - Assert.assertTrue(literalExpressionAgain is ULiteralExpression) - - } - } - - @Test fun testConvertStringTemplateWithExpectedType() { - doTest("StringTemplateWithVar") { _, file -> - val index = file.psi.text.indexOf("foo") - val stringTemplate = file.psi.findElementAt(index)!!.getParentOfType(false) - val uLiteral = stringTemplate.toUElementOfType() - assertNull(uLiteral) - } - } - - @Test fun testNameContainingFile() { - doTest("NameContainingFile") { _, file -> - val foo = file.findElementByText("class Foo") - assertEquals(file.psi, foo.nameIdentifier!!.containingFile) - - val bar = file.findElementByText("fun bar() {}") - assertEquals(file.psi, bar.nameIdentifier!!.containingFile) - - val xyzzy = file.findElementByText("val xyzzy: Int = 0") - assertEquals(file.psi, xyzzy.nameIdentifier!!.containingFile) - } - } - - @Test fun testInterfaceMethodWithBody() { - doTest("DefaultImpls") { _, file -> - val bar = file.findElementByText("fun bar() = \"Hello!\"") - assertFalse(bar.containingFile.text!!, bar.psi.modifierList.hasExplicitModifier(PsiModifier.DEFAULT)) - assertTrue(bar.containingFile.text!!, bar.psi.modifierList.hasModifierProperty(PsiModifier.DEFAULT)) - } - } - - @Test fun testSAM() { - doTest("SAM") { _, file -> - assertNull(file.findElementByText("{ /* Not SAM */ }").functionalInterfaceType) - - assertEquals("java.lang.Runnable", - file.findElementByText("{/* Variable */}").functionalInterfaceType?.canonicalText) - - assertEquals("java.lang.Runnable", - file.findElementByText("{/* Assignment */}").functionalInterfaceType?.canonicalText) - - assertEquals("java.lang.Runnable", - file.findElementByText("{/* Type Cast */}").functionalInterfaceType?.canonicalText) - - assertEquals("java.lang.Runnable", - file.findElementByText("{/* Argument */}").functionalInterfaceType?.canonicalText) - - assertEquals("java.lang.Runnable", - file.findElementByText("{/* Return */}").functionalInterfaceType?.canonicalText) - - assertEquals( - "java.lang.Runnable", - file.findElementByText("{ /* SAM */ }").functionalInterfaceType?.canonicalText - ) - } - } - - @Test fun testParameterPropertyWithAnnotation() { - doTest("ParameterPropertyWithAnnotation") { _, file -> - val test1 = file.classes.find { it.name == "Test1" }!! - - val constructor1 = test1.methods.find { it.name == "Test1" }!! - assertTrue(constructor1.uastParameters.first().annotations.any { it.qualifiedName == "MyAnnotation" }) - - val getter1 = test1.methods.find { it.name == "getBar" }!! - assertFalse(getter1.annotations.any { it.qualifiedName == "MyAnnotation" }) - - val setter1 = test1.methods.find { it.name == "setBar" }!! - assertFalse(setter1.annotations.any { it.qualifiedName == "MyAnnotation" }) - assertFalse(setter1.uastParameters.first().annotations.any { it.qualifiedName == "MyAnnotation" }) - - - val test2 = file.classes.find { it.name == "Test2" }!! - val constructor2 = test2.methods.find { it.name == "Test2" }!! - assertFalse(constructor2.uastParameters.first().annotations.any { it.qualifiedName?.startsWith("MyAnnotation") ?: false }) - - val getter2 = test2.methods.find { it.name == "getBar" }!! - getter2.annotations.single { it.qualifiedName == "MyAnnotation" } - - val setter2 = test2.methods.find { it.name == "setBar" }!! - setter2.annotations.single { it.qualifiedName == "MyAnnotation2" } - setter2.uastParameters.first().annotations.single { it.qualifiedName == "MyAnnotation3" } - - test2.fields.find { it.name == "bar" }!!.annotations.single { it.qualifiedName == "MyAnnotation5" } - } - } - - @Test fun testConvertTypeInAnnotation() { - doTest("TypeInAnnotation") { _, file -> - val index = file.psi.text.indexOf("Test") - val element = file.psi.findElementAt(index)!!.getParentOfType(false)!! - assertNotNull(element.getUastParentOfType(UAnnotation::class.java)) - } - } - - @Test fun testElvisType() { - doTest("ElvisType") { _, file -> - val elvisExpression = file.findElementByText("text ?: return") - assertEquals("String", elvisExpression.getExpressionType()!!.presentableText) - } - } - - @Test fun testFindAttributeDefaultValue() { - doTest("AnnotationParameters") { _, file -> - val witDefaultValue = file.findElementByText("@WithDefaultValue") - assertEquals(42, witDefaultValue.findAttributeValue("value")!!.evaluate()) - assertEquals(42, witDefaultValue.findAttributeValue(null)!!.evaluate()) - } - } - - @Test fun testIfCondition() { - doTest("IfStatement") { _, file -> - val psiFile = file.psi - val element = psiFile.findElementAt(psiFile.text.indexOf("\"abc\""))!! - val binaryExpression = element.getParentOfType(false)!! - val uBinaryExpression = KotlinUastLanguagePlugin().convertElementWithParent(binaryExpression, null)!! - UsefulTestCase.assertInstanceOf(uBinaryExpression.uastParent, UIfExpression::class.java) - } - } - - @Test - fun testWhenStringLiteral() { - doTest("WhenStringLiteral") { _, file -> - - file.findElementByTextFromPsi("abc").let { literalExpression -> - val psi = literalExpression.psi!! - Assert.assertTrue(psi is KtLiteralStringTemplateEntry) - UsefulTestCase.assertInstanceOf(literalExpression.uastParent, USwitchClauseExpressionWithBody::class.java) - } - - file.findElementByTextFromPsi("def").let { literalExpression -> - val psi = literalExpression.psi!! - Assert.assertTrue(psi is KtLiteralStringTemplateEntry) - UsefulTestCase.assertInstanceOf(literalExpression.uastParent, USwitchClauseExpressionWithBody::class.java) - } - - file.findElementByTextFromPsi("def1").let { literalExpression -> - val psi = literalExpression.psi!! - Assert.assertTrue(psi is KtLiteralStringTemplateEntry) - UsefulTestCase.assertInstanceOf(literalExpression.uastParent, UBlockExpression::class.java) - } - - - } - } - - @Test - fun testWhenAndDestructing() { - doTest("WhenAndDestructing") { _, file -> - - file.findElementByTextFromPsi("val (bindingContext, statementFilter) = arr").let { e -> - val uBlockExpression = e.getParentOfType() - Assert.assertNotNull(uBlockExpression) - val uMethod = uBlockExpression!!.getParentOfType() - Assert.assertNotNull(uMethod) - } - - } - } - - @Test - fun testBrokenMethodTypeResolve() { - doTest("BrokenMethod") { _, file -> - - file.accept(object : AbstractUastVisitor() { - override fun visitCallExpression(node: UCallExpression): Boolean { - node.returnType - return false - } - }) - } - } - - @Test - fun testSimpleAnnotated() { - doTest("SimpleAnnotated") { _, file -> - file.findElementByTextFromPsi("@SinceKotlin(\"1.0\")\n val property: String = \"Mary\"").let { field -> - val annotation = field.annotations.assertedFind("kotlin.SinceKotlin") { it.qualifiedName } - Assert.assertEquals(annotation.findDeclaredAttributeValue("version")?.evaluateString(), "1.0") - } - } - } - - - fun UFile.checkUastSuperTypes(refText: String, superTypes: List) { - findElementByTextFromPsi(refText, false).let { - assertEquals("base classes", superTypes, it.uastSuperTypes.map { it.getQualifiedName() }) - } - } - - - @Test - fun testSuperTypes() { - doTest("SuperCalls") { _, file -> - file.checkUastSuperTypes("B", listOf("A")) - file.checkUastSuperTypes("O", listOf("A")) - file.checkUastSuperTypes("innerObject ", listOf("A")) - file.checkUastSuperTypes("InnerClass", listOf("A")) - file.checkUastSuperTypes("object : A(\"textForAnon\")", listOf("A")) - } - } - - @Test - fun testAnonymousSuperTypes() { - doTest("Anonymous") { _, file -> - file.checkUastSuperTypes("object : Runnable { override fun run() {} }", listOf("java.lang.Runnable")) - file.checkUastSuperTypes( - "object : Runnable, Closeable { override fun close() {} override fun run() {} }", - listOf("java.lang.Runnable", "java.io.Closeable") - ) - file.checkUastSuperTypes( - "object : InputStream(), Runnable { override fun read(): Int = 0; override fun run() {} }", - listOf("java.io.InputStream", "java.lang.Runnable") - ) - } - } - - @Test - fun testLiteralArraysTypes() { - doTest("AnnotationParameters") { _, file -> - file.findElementByTextFromPsi("intArrayOf(1, 2, 3)").let { field -> - Assert.assertEquals("PsiType:int[]", field.returnType.toString()) - } - file.findElementByTextFromPsi("[1, 2, 3]").let { field -> - Assert.assertEquals("PsiType:int[]", field.returnType.toString()) - Assert.assertEquals("PsiType:int", field.typeArguments.single().toString()) - } - file.findElementByTextFromPsi("[\"a\", \"b\", \"c\"]").let { field -> - Assert.assertEquals("PsiType:String[]", field.returnType.toString()) - Assert.assertEquals("PsiType:String", field.typeArguments.single().toString()) - } - - } - } - - @Test - fun testTypeAliases() { - doTest("TypeAliases") { _, file -> - val g = (file.psi as KtFile).declarations.single { it.name == "G" } as KtTypeAlias - val originalType = g.getTypeReference()!!.typeElement as KtFunctionType - val originalTypeParameters = originalType.parameterList.toUElement() as UDeclarationsExpression - Assert.assertTrue((originalTypeParameters.declarations.single() as UParameter).type.isValid) - } - } - - @Test - fun testNestedAnnotation() = doTest("AnnotationComplex") { _, file -> - file.findElementByTextFromPsi("@AnnotationArray(value = Annotation())") - .findElementByTextFromPsi("Annotation()") - .sourcePsiElement - .let { referenceExpression -> - val convertedUAnnotation = referenceExpression - .cast() - .toUElementOfType() - ?: throw AssertionError("haven't got annotation from $referenceExpression(${referenceExpression?.javaClass})") - - assertEquals("Annotation", convertedUAnnotation.qualifiedName) - val lightAnnotation = convertedUAnnotation.getAsJavaPsiElement(PsiAnnotation::class.java) - ?: throw AssertionError("can't get lightAnnotation from $convertedUAnnotation") - assertEquals("Annotation", lightAnnotation.qualifiedName) - } - } - - @Test - fun testResolvedDeserializedMethod() = doTest("Resolve") { _, file -> - val barMethod = file.findElementByTextFromPsi("bar").sourcePsiElement.sure { "sourceElement" } - .parentsWithSelf.mapNotNull { it.toUElementOfType() }.firstOrNull().sure { "parent UMethod" } - - fun UElement.assertResolveCall(callText: String, methodName: String = callText.substringBefore("(")) { - this.findElementByTextFromPsi(callText).let { - val resolve = it.resolve().sure { "resolving '$callText'" } - assertEquals(methodName, resolve.name) - } - } - barMethod.assertResolveCall("foo()") - barMethod.assertResolveCall("inlineFoo()") - barMethod.assertResolveCall("forEach { println(it) }", "forEach") - barMethod.assertResolveCall("joinToString()") - barMethod.assertResolveCall("last()") - } - - @Test - fun testUtilsStreamLambda() { - doTest("Lambdas") { _, file -> - val lambda = file.findElementByTextFromPsi("{ it.isEmpty() }") - assertEquals( - "java.util.function.Predicate", - lambda.functionalInterfaceType?.canonicalText - ) - assertEquals( - "kotlin.jvm.functions.Function1", - lambda.getExpressionType()?.canonicalText - ) - val uCallExpression = lambda.uastParent.assertedCast { "UCallExpression expected" } - assertTrue(uCallExpression.valueArguments.contains(lambda)) - } - } - - @Test - fun testLambdaParamCall() { - doTest("Lambdas") { _, file -> - val lambdaCall = file.findElementByTextFromPsi("selectItemFunction()") - assertEquals( - "UIdentifier (Identifier (selectItemFunction))", - lambdaCall.methodIdentifier?.asLogString() - ) - assertEquals( - "selectItemFunction", - lambdaCall.methodIdentifier?.name - ) - assertEquals( - "invoke", - lambdaCall.methodName - ) - val receiver = lambdaCall.receiver ?: kotlin.test.fail("receiver expected") - assertEquals("UReferenceExpression", receiver.asLogString()) - val uParameter = (receiver as UReferenceExpression).resolve().toUElement() ?: kotlin.test.fail("uelement expected") - assertEquals("UParameter (name = selectItemFunction)", uParameter.asLogString()) - } - } - - @Test - fun testLocalLambdaCall() { - doTest("Lambdas") { _, file -> - val lambdaCall = file.findElementByTextFromPsi("baz()") - assertEquals( - "UIdentifier (Identifier (baz))", - lambdaCall.methodIdentifier?.asLogString() - ) - assertEquals( - "baz", - lambdaCall.methodIdentifier?.name - ) - assertEquals( - "invoke", - lambdaCall.methodName - ) - val receiver = lambdaCall.receiver ?: kotlin.test.fail("receiver expected") - assertEquals("UReferenceExpression", receiver.asLogString()) - val uParameter = (receiver as UReferenceExpression).resolve().toUElement() ?: kotlin.test.fail("uelement expected") - assertEquals("ULocalVariable (name = baz)", uParameter.asLogString()) - } - } - - @Test - fun testLocalDeclarationCall() { - doTest("LocalDeclarations") { _, file -> - val localFunction = file.findElementByTextFromPsi("bar() == Local()"). - findElementByText("bar()") - assertEquals( - "UIdentifier (Identifier (bar))", - localFunction.methodIdentifier?.asLogString() - ) - assertEquals( - "bar", - localFunction.methodIdentifier?.name - ) - assertEquals( - "bar", - localFunction.methodName - ) - assertNull(localFunction.resolve()) - val receiver = localFunction.receiver ?: kotlin.test.fail("receiver expected") - assertEquals("UReferenceExpression", receiver.asLogString()) - val uParameter = (receiver as UReferenceExpression).resolve().toUElement() ?: kotlin.test.fail("uelement expected") - assertEquals("ULambdaExpression", uParameter.asLogString()) - } - } - -} - -fun Iterable.assertedFind(value: R, transform: (T) -> R): T = find { transform(it) == value } ?: throw AssertionError("'$value' not found, only ${this.joinToString { transform(it).toString() }}") diff --git a/plugins/uast-kotlin/tests/KotlinUastIdentifiersTest.kt.173 b/plugins/uast-kotlin/tests/KotlinUastIdentifiersTest.kt.173 deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/plugins/uast-kotlin/tests/org/jetbrains/uast/test/common/IdentifiersTestBase.kt.173 b/plugins/uast-kotlin/tests/org/jetbrains/uast/test/common/IdentifiersTestBase.kt.173 deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/ultimate/build.gradle.kts.173 b/ultimate/build.gradle.kts.173 deleted file mode 100644 index 3a679ced9e7..00000000000 --- a/ultimate/build.gradle.kts.173 +++ /dev/null @@ -1,219 +0,0 @@ - -import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar -import org.gradle.jvm.tasks.Jar - -description = "Kotlin IDEA Ultimate plugin" - -plugins { - kotlin("jvm") -} - -val ideaProjectResources = project(":idea").mainSourceSet.output.resourcesDir - -evaluationDependsOn(":prepare:idea-plugin") - -val intellijUltimateEnabled : Boolean by rootProject.extra - -val springClasspath by configurations.creating - -dependencies { - if (intellijUltimateEnabled) { - testRuntime(intellijUltimateDep()) - } - - compileOnly(project(":kotlin-reflect-api")) - compile(project(":kotlin-stdlib")) - compile(project(":core:descriptors")) { isTransitive = false } - compile(project(":compiler:psi")) { isTransitive = false } - compile(project(":core:descriptors.jvm")) { isTransitive = false } - compile(project(":core:util.runtime")) { isTransitive = false } - compile(project(":compiler:light-classes")) { isTransitive = false } - compile(project(":compiler:frontend")) { isTransitive = false } - compile(project(":compiler:frontend.common")) { isTransitive = false } - compile(project(":compiler:frontend.java")) { isTransitive = false } - compile(project(":js:js.frontend")) { isTransitive = false } - compile(projectClasses(":idea")) - compile(project(":idea:idea-jvm")) { isTransitive = false } - compile(project(":idea:idea-core")) { isTransitive = false } - compile(project(":idea:ide-common")) { isTransitive = false } - compile(project(":idea:idea-gradle")) { isTransitive = false } - compile(project(":compiler:util")) { isTransitive = false } - compile(project(":idea:idea-jps-common")) { isTransitive = false } - compileOnly(intellijCoreDep()) { includeJars("intellij-core") } - - if (intellijUltimateEnabled) { - compileOnly(intellijUltimatePluginDep("NodeJS")) - compileOnly(intellijUltimateDep()) { includeJars("annotations", "trove4j", "openapi", "idea", "util", "jdom") } - compileOnly(intellijUltimatePluginDep("CSS")) - compileOnly(intellijUltimatePluginDep("DatabaseTools")) - compileOnly(intellijUltimatePluginDep("JavaEE")) - compileOnly(intellijUltimatePluginDep("jsp")) - compileOnly(intellijUltimatePluginDep("PersistenceSupport")) - compileOnly(intellijUltimatePluginDep("Spring")) - compileOnly(intellijUltimatePluginDep("properties")) - compileOnly(intellijUltimatePluginDep("java-i18n")) - compileOnly(intellijUltimatePluginDep("gradle")) - compileOnly(intellijUltimatePluginDep("Groovy")) - compileOnly(intellijUltimatePluginDep("junit")) - compileOnly(intellijUltimatePluginDep("uml")) - compileOnly(intellijUltimatePluginDep("JavaScriptLanguage")) - compileOnly(intellijUltimatePluginDep("JavaScriptDebugger")) - } - - testCompile(project(":kotlin-test:kotlin-test-jvm")) - testCompile(projectTests(":idea:idea-test-framework")) { isTransitive = false } - testCompile(project(":plugins:lint")) { isTransitive = false } - testCompile(project(":idea:idea-jvm")) { isTransitive = false } - testCompile(projectTests(":compiler:tests-common")) - testCompile(projectTests(":idea")) { isTransitive = false } - testCompile(projectTests(":generators:test-generator")) - testCompile(commonDep("junit:junit")) - - testCompile(project(":idea:idea-native")) { isTransitive = false } - testCompile(project(":idea:idea-gradle-native")) { isTransitive = false } - testRuntime(project(":kotlin-native:kotlin-native-library-reader")) { isTransitive = false } - testRuntime(project(":kotlin-native:kotlin-native-utils")) { isTransitive = false } - - if (intellijUltimateEnabled) { - testCompileOnly(intellijUltimateDep()) { includeJars("gson", "annotations", "trove4j", "openapi", "idea", "util", "jdom", rootProject = rootProject) } - } - testCompile(commonDep("org.jetbrains.kotlinx", "kotlinx-coroutines-core")) { isTransitive = false } - - testRuntime(project(":kotlin-reflect")) - testRuntime(project(":kotlin-script-runtime")) - testRuntimeOnly(projectRuntimeJar(":kotlin-compiler")) - testRuntime(project(":plugins:android-extensions-ide")) { isTransitive = false } - testRuntime(project(":plugins:android-extensions-compiler")) { isTransitive = false } - testRuntime(project(":plugins:annotation-based-compiler-plugins-ide-support")) { isTransitive = false } - testRuntime(project(":idea:idea-android")) { isTransitive = false } - testRuntime(project(":idea:idea-maven")) { isTransitive = false } - testRuntime(project(":idea:idea-jps-common")) { isTransitive = false } - testRuntime(project(":idea:formatter")) { isTransitive = false } - testRuntime(project(":sam-with-receiver-ide-plugin")) { isTransitive = false } - testRuntime(project(":kotlin-sam-with-receiver-compiler-plugin")) { isTransitive = false } - testRuntime(project(":noarg-ide-plugin")) { isTransitive = false } - testRuntime(project(":kotlin-noarg-compiler-plugin")) { isTransitive = false } - testRuntime(project(":allopen-ide-plugin")) { isTransitive = false } - testRuntime(project(":kotlin-allopen-compiler-plugin")) { isTransitive = false } - testRuntime(project(":kotlin-scripting-idea")) { isTransitive = false } - testRuntime(project(":kotlin-scripting-compiler")) { isTransitive = false } - testRuntime(project(":kotlinx-serialization-compiler-plugin")) { isTransitive = false } - testRuntime(project(":kotlinx-serialization-ide-plugin")) { isTransitive = false } - testRuntime(project(":plugins:kapt3-idea")) { isTransitive = false } - testRuntime(project(":plugins:uast-kotlin")) - testRuntime(project(":plugins:uast-kotlin-idea")) - - if (intellijUltimateEnabled) { - testCompile(intellijUltimatePluginDep("CSS")) - testCompile(intellijUltimatePluginDep("DatabaseTools")) - testCompile(intellijUltimatePluginDep("JavaEE")) - testCompile(intellijUltimatePluginDep("jsp")) - testCompile(intellijUltimatePluginDep("PersistenceSupport")) - testCompile(intellijUltimatePluginDep("Spring")) - testCompile(intellijUltimatePluginDep("uml")) - testCompile(intellijUltimatePluginDep("JavaScriptLanguage")) - testCompile(intellijUltimatePluginDep("JavaScriptDebugger")) - testCompile(intellijUltimatePluginDep("NodeJS")) - testCompile(intellijUltimatePluginDep("properties")) - testCompile(intellijUltimatePluginDep("java-i18n")) - testCompile(intellijUltimatePluginDep("gradle")) - testCompile(intellijUltimatePluginDep("Groovy")) - testCompile(intellijUltimatePluginDep("junit")) - testRuntime(intellijUltimatePluginDep("coverage")) - testRuntime(intellijUltimatePluginDep("maven")) - testRuntime(intellijUltimatePluginDep("android")) - testRuntime(intellijUltimatePluginDep("testng")) - testRuntime(intellijUltimatePluginDep("IntelliLang")) - testRuntime(intellijUltimatePluginDep("copyright")) - testRuntime(intellijUltimatePluginDep("java-decompiler")) - } - - testRuntime(files("${System.getProperty("java.home")}/../lib/tools.jar")) - - springClasspath(commonDep("org.springframework", "spring-core")) - springClasspath(commonDep("org.springframework", "spring-beans")) - springClasspath(commonDep("org.springframework", "spring-context")) - springClasspath(commonDep("org.springframework", "spring-tx")) - springClasspath(commonDep("org.springframework", "spring-web")) -} - -val preparedResources = File(buildDir, "prepResources") - -sourceSets { - "main" { projectDefault() } - "test" { - projectDefault() - resources.srcDir(preparedResources) - } -} - -val ultimatePluginXmlContent: String by lazy { - val sectRex = Regex("""^\s*\s*$""") - File(projectDir, "resources/META-INF/ultimate-plugin.xml") - .readLines() - .filterNot { it.matches(sectRex) } - .joinToString("\n") -} - -val prepareResources by task { - dependsOn(":idea:assemble") - from(ideaProjectResources, { - exclude("META-INF/plugin.xml") - }) - into(preparedResources) -} - -val preparePluginXml by task { - dependsOn(":idea:assemble") - from(ideaProjectResources, { include("META-INF/plugin.xml") }) - into(preparedResources) - filter { - it?.replace("", ultimatePluginXmlContent) - } -} - -val communityPluginProject = ":prepare:idea-plugin" - -val jar = runtimeJar(task("shadowJar")) { - duplicatesStrategy = DuplicatesStrategy.EXCLUDE - dependsOn(preparePluginXml) - dependsOn("$communityPluginProject:shadowJar") - val communityPluginJar = project(communityPluginProject).configurations["runtimeJar"].artifacts.files.singleFile - from(zipTree(communityPluginJar), { exclude("META-INF/plugin.xml") }) - from(preparedResources, { include("META-INF/plugin.xml") }) - from(mainSourceSet.output) - archiveName = "kotlin-plugin.jar" -} - -val ideaPluginDir: File by rootProject.extra -val ideaUltimatePluginDir: File by rootProject.extra - -task("ideaUltimatePlugin") { - dependsOn(":ideaPlugin") - into(ideaUltimatePluginDir) - from(ideaPluginDir) { exclude("lib/kotlin-plugin.jar") } - from(jar, { into("lib") }) -} - -task("idea-ultimate-plugin") { - dependsOn("ideaUltimatePlugin") - doFirst { logger.warn("'$name' task is deprecated, use '${dependsOn.last()}' instead") } -} - -task("ideaUltimatePluginTest") { - dependsOn("check") -} - -projectTest { - dependsOn(prepareResources) - dependsOn(preparePluginXml) - workingDir = rootDir - doFirst { - if (intellijUltimateEnabled) { - systemProperty("idea.home.path", intellijUltimateRootDir().canonicalPath) - } - systemProperty("spring.classpath", springClasspath.asPath) - } -} - -val generateTests by generator("org.jetbrains.kotlin.tests.GenerateUltimateTestsKt") diff --git a/ultimate/resources/META-INF/kotlin-spring.xml.173 b/ultimate/resources/META-INF/kotlin-spring.xml.173 deleted file mode 100644 index 64e157db101..00000000000 --- a/ultimate/resources/META-INF/kotlin-spring.xml.173 +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ultimate/src/org/jetbrains/kotlin/idea/spring/inspections/KotlinFinalClassOrFunSpringInspection.kt.173 b/ultimate/src/org/jetbrains/kotlin/idea/spring/inspections/KotlinFinalClassOrFunSpringInspection.kt.173 deleted file mode 100644 index b584ed6633d..00000000000 --- a/ultimate/src/org/jetbrains/kotlin/idea/spring/inspections/KotlinFinalClassOrFunSpringInspection.kt.173 +++ /dev/null @@ -1,111 +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.kotlin.idea.spring.inspections - -import com.intellij.codeInsight.highlighting.HighlightUsagesDescriptionLocation -import com.intellij.codeInspection.LocalQuickFix -import com.intellij.codeInspection.ProblemDescriptor -import com.intellij.codeInspection.ProblemHighlightType -import com.intellij.codeInspection.ProblemsHolder -import com.intellij.openapi.project.Project -import com.intellij.psi.ElementDescriptionUtil -import com.intellij.psi.PsiElementVisitor -import com.intellij.spring.constants.SpringAnnotationsConstants -import com.intellij.spring.model.jam.stereotype.SpringComponent -import com.intellij.spring.model.jam.stereotype.SpringConfiguration -import com.intellij.spring.model.jam.transaction.SpringTransactionalComponent -import org.jetbrains.kotlin.asJava.toLightClass -import org.jetbrains.kotlin.asJava.toLightMethods -import org.jetbrains.kotlin.descriptors.MemberDescriptor -import org.jetbrains.kotlin.descriptors.Modality -import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny -import org.jetbrains.kotlin.idea.core.isInheritable -import org.jetbrains.kotlin.idea.core.isOverridable -import org.jetbrains.kotlin.idea.inspections.AbstractKotlinInspection -import org.jetbrains.kotlin.idea.spring.isAnnotatedWith -import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject - -class KotlinFinalClassOrFunSpringInspection : AbstractKotlinInspection() { - class QuickFix(private val element: T) : LocalQuickFix { - override fun getName(): String { - return "Make ${ElementDescriptionUtil.getElementDescription(element, HighlightUsagesDescriptionLocation.INSTANCE)} open" - } - - override fun getFamilyName() = "Make declaration open" - - override fun applyFix(project: Project, problemDescriptor: ProblemDescriptor) { - (element as? KtNamedDeclaration)?.containingClassOrObject?.addModifier(KtTokens.OPEN_KEYWORD) - element.addModifier(KtTokens.OPEN_KEYWORD) - } - } - - private fun getMessage(declaration: KtNamedDeclaration): String? { - when (declaration) { - is KtClassOrObject -> { - val lightClass = declaration.toLightClass() ?: return null - val annotation = when { - SpringConfiguration.META.getJamElement(lightClass) != null -> "@Configuration" - SpringComponent.META.getJamElement(lightClass) != null -> "@Component" - SpringTransactionalComponent.META.getJamElement(lightClass) != null -> "@Transactional" - else -> return null - } - return if (declaration is KtClass) "$annotation class should be declared open" else "$annotation should not be applied to object declaration " - } - - is KtNamedFunction -> { - val lightMethod = declaration.toLightMethods().firstOrNull() ?: return null - when { - lightMethod.isAnnotatedWith(SpringAnnotationsConstants.JAVA_SPRING_BEAN) -> return "@Bean function should be declared open" - lightMethod.isAnnotatedWith(SpringAnnotationsConstants.TRANSACTIONAL) -> return "@Transactional function should be declared open" - } - } - } - return null - } - - override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { - return object: KtVisitorVoid() { - private fun KtNamedDeclaration.isOpen(): Boolean { - when (this) { - is KtClass -> if (isInheritable()) return true - is KtObjectDeclaration -> return false - is KtNamedFunction -> if (isOverridable()) return true - else -> return true - } - - val descriptor = resolveToDescriptorIfAny() as? MemberDescriptor - return descriptor?.modality != Modality.FINAL - } - - override fun visitNamedDeclaration(declaration: KtNamedDeclaration) { - if (declaration.isOpen()) return - - val message = getMessage(declaration) ?: return - - val fixes = if (declaration !is KtObjectDeclaration) arrayOf(QuickFix(declaration)) else LocalQuickFix.EMPTY_ARRAY - holder.registerProblem( - declaration.nameIdentifier ?: declaration, - message, - ProblemHighlightType.GENERIC_ERROR_OR_WARNING, - *fixes - ) - } - } - } -} \ No newline at end of file diff --git a/ultimate/src/org/jetbrains/kotlin/idea/spring/inspections/SpringKotlinAutowiringInspection.kt.173 b/ultimate/src/org/jetbrains/kotlin/idea/spring/inspections/SpringKotlinAutowiringInspection.kt.173 deleted file mode 100644 index ad96206bb2f..00000000000 --- a/ultimate/src/org/jetbrains/kotlin/idea/spring/inspections/SpringKotlinAutowiringInspection.kt.173 +++ /dev/null @@ -1,199 +0,0 @@ -package org.jetbrains.kotlin.idea.spring.inspections - -import com.intellij.codeInsight.AnnotationUtil -import com.intellij.codeInsight.FileModificationService -import com.intellij.codeInsight.lookup.LookupElement -import com.intellij.codeInsight.template.* -import com.intellij.codeInspection.LocalQuickFix -import com.intellij.codeInspection.ProblemDescriptor -import com.intellij.codeInspection.ProblemsHolder -import com.intellij.openapi.fileEditor.FileEditorManager -import com.intellij.openapi.fileEditor.OpenFileDescriptor -import com.intellij.openapi.project.Project -import com.intellij.psi.* -import com.intellij.psi.util.PropertyUtil -import com.intellij.spring.CommonSpringModel -import com.intellij.spring.SpringBundle -import com.intellij.spring.model.SpringBeanPointer -import com.intellij.spring.model.converters.SpringConverterUtil -import com.intellij.spring.model.highlighting.autowire.SpringJavaConstructorAutowiringInspection -import com.intellij.spring.model.highlighting.autowire.SpringUastInjectionPointsAutowiringInspection -import com.intellij.spring.model.utils.SpringAutowireUtil -import org.jetbrains.kotlin.asJava.elements.KtLightField -import org.jetbrains.kotlin.asJava.elements.KtLightMethod -import org.jetbrains.kotlin.asJava.toLightClass -import org.jetbrains.kotlin.asJava.toLightElements -import org.jetbrains.kotlin.asJava.toLightMethods -import org.jetbrains.kotlin.idea.core.ShortenReferences -import org.jetbrains.kotlin.idea.inspections.AbstractKotlinInspection -import org.jetbrains.kotlin.idea.inspections.registerWithElementsUnwrapped -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.* -import org.jetbrains.kotlin.utils.SmartList -import org.jetbrains.uast.UClass -import org.jetbrains.uast.UDeclaration -import org.jetbrains.uast.toUElementOfType - -class SpringKotlinAutowiringInspection : AbstractKotlinInspection() { - // Based on SpringJavaInjectionPointsAutowiringInspection.AddSpringBeanQualifierFix - class AddQualifierFix( - modifierListOwner: KtModifierListOwner, - private val beanPointers: Collection>, - private val annotationFqName: String - ) : LocalQuickFix { - private val elementPointer = modifierListOwner.createSmartPointer() - - override fun getName() = SpringBundle.message("SpringAutowiringInspection.add.qualifier.fix") - - override fun getFamilyName() = name - - private fun getQualifierNamesSuggestNamesExpression(expression: KtStringTemplateExpression): Expression { - return object : Expression() { - override fun calculateResult(context: ExpressionContext): Result? { - PsiDocumentManager.getInstance(context.project).commitAllDocuments() - return TextResult(expression.plainContent) - } - - override fun calculateQuickResult(context: ExpressionContext) = this.calculateResult(context) - - override fun calculateLookupItems(context: ExpressionContext): Array? { - PsiDocumentManager.getInstance(context.project).commitAllDocuments() - return beanPointers.sortedBy { it.name ?: "" }.mapNotNull { SpringConverterUtil.createCompletionVariant(it) }.toTypedArray() - } - } - } - - private fun createQualifierNameTemplate(expression: KtStringTemplateExpression): Template { - val builder = TemplateBuilderImpl(expression.containingFile) - builder.replaceRange( - expression.getContentRange().shiftRight(expression.startOffset), - getQualifierNamesSuggestNamesExpression(expression) - ) - return builder.buildInlineTemplate() - } - - override fun applyFix(project: Project, descriptor: ProblemDescriptor) { - val modifierListOwner = elementPointer.element ?: return - if (!FileModificationService.getInstance().preparePsiElementForWrite(modifierListOwner)) return - if (beanPointers.isEmpty()) return - - val defaultBeanName = with(beanPointers.first().name) { if (isNullOrBlank()) "Unknown" else this } - val entry = KtPsiFactory(project).createAnnotationEntry("@$annotationFqName(\"$defaultBeanName\")") - val addedEntry = modifierListOwner.addAnnotationEntry(entry) - - ShortenReferences.DEFAULT.process(addedEntry) - - val stringTemplate = addedEntry.valueArguments.first().getArgumentExpression() as? KtStringTemplateExpression ?: return - val virtualFile = modifierListOwner.containingFile.virtualFile!! - val editor = FileEditorManager.getInstance(project).openTextEditor(OpenFileDescriptor(project, virtualFile, 0), false)!! - PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.document) - TemplateManager.getInstance(project).startTemplate(editor, createQualifierNameTemplate(stringTemplate)) - } - } - - private val uastInspection by lazy { SpringUastInjectionPointsAutowiringInspection() } - private val nonUastInspection by lazy { SpringJavaConstructorAutowiringInspection() } - - override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean) = object : KtVisitorVoid() { - // TODO: SpringJavaInjectionPointsAutowiringInspection.checkAutowiredMethod() is not accessible here - private fun checkAutowiredMethod(psiMethod: PsiMethod, holder: ProblemsHolder, springModel: CommonSpringModel, required: Boolean) { - val resourceAnnotation = SpringAutowireUtil.getResourceAnnotation(psiMethod) - when { - resourceAnnotation != null -> { - val propertyType = PropertyUtil.getPropertyType(psiMethod) ?: return - psiMethod.toUElementOfType()?.let { uMethod -> - SpringUastInjectionPointsAutowiringInspection.checkInjectionPoint(uMethod, propertyType, holder, springModel, required) - } - } - psiMethod.parameterList.parametersCount == 0 && - SpringAutowireUtil.isAutowiredByAnnotation(psiMethod) -> { - val nameIdentifier = psiMethod.nameIdentifier ?: return - val message = SpringBundle.message("bean.autowiring.by.type.no.parameter.for.autowired.method", - if (psiMethod.isConstructor) "constructor" else "method") - holder.registerProblem(nameIdentifier, message) - } - else -> { - for (parameter in psiMethod.parameterList.parameters) { - if (AnnotationUtil.isAnnotated(parameter, "org.springframework.beans.factory.annotation.Value", true)) continue - parameter.toUElementOfType()?.let { uParameter -> - SpringUastInjectionPointsAutowiringInspection.checkInjectionPoint(uParameter, parameter.type, holder, springModel, required) - } - } - } - } - } - - private fun Array.registerAdjustedProblems() { - registerWithElementsUnwrapped(holder, isOnTheFly) { qf, element -> - // Can't access AddSpringBeanQualifierFix class directly - - val klass = qf.javaClass - if (!klass.name.endsWith("AddSpringBeanQualifierFix")) return@registerWithElementsUnwrapped qf - - try { - val fields = klass.declaredFields - @Suppress("UNCHECKED_CAST") - val beanPointers = fields[1].apply { isAccessible = true }.get(qf) as Collection> - val annotationFqName = fields[2].apply { isAccessible = true }.get(qf) as String - val modifierListOwner = element.getNonStrictParentOfType() - ?: return@registerWithElementsUnwrapped qf - AddQualifierFix(modifierListOwner, beanPointers, annotationFqName) - } - catch (e: Exception) { - return@registerWithElementsUnwrapped null - } - } - } - - private fun T.processLightMember( - action: T.(holder: ProblemsHolder, model: CommonSpringModel, required: Boolean) -> Unit - ) { - val model = SpringAutowireUtil.getProcessingSpringModel(containingClass) ?: return - val required = SpringAutowireUtil.isRequired(this) - val tmpHolder = ProblemsHolder(holder.manager, containingFile, isOnTheFly) - action(this, tmpHolder, model, required) - tmpHolder.resultsArray.registerAdjustedProblems() - } - - private fun PsiMethod.processLightMethod() { - if (!SpringAutowireUtil.isInjectionPoint(this)) return - processLightMember { holder, model, required -> checkAutowiredMethod(this, holder, model, required) } - } - - private fun PsiField.processLightField() { - if (!SpringAutowireUtil.isAutowiredByAnnotation(this)) return - processLightMember { holder, model, required -> - this.toUElementOfType()?.let { uDeclaration -> - SpringUastInjectionPointsAutowiringInspection.checkInjectionPoint(uDeclaration, type, holder, model, required) - } - } - } - - private fun PsiClass.processLightClass() { - val reports = SmartList() - this.toUElementOfType()?.let { uClass -> - uastInspection.checkClass(uClass, holder.manager, isOnTheFly)?.let { reports.addAll(it) } - } - nonUastInspection.checkClass(this, holder.manager, isOnTheFly)?.let { reports.addAll(it) } - reports.toTypedArray().registerAdjustedProblems() - } - - override fun visitNamedFunction(function: KtNamedFunction) { - function.toLightMethods().firstOrNull()?.processLightMethod() - } - - override fun visitProperty(property: KtProperty) { - if (property.name != null) // It is here because `lightElement.name` returns `` instead of `null` suddenly - for (lightElement in property.toLightElements()) { - when (lightElement) { - is KtLightMethod -> lightElement.processLightMethod() - is KtLightField -> lightElement.processLightField() - } - } - } - - override fun visitClassOrObject(classOrObject: KtClassOrObject) { - classOrObject.toLightClass()?.processLightClass() - } - } -} \ No newline at end of file diff --git a/ultimate/src/org/jetbrains/kotlin/idea/spring/lineMarking/KotlinSpringClassAnnotator.kt.173 b/ultimate/src/org/jetbrains/kotlin/idea/spring/lineMarking/KotlinSpringClassAnnotator.kt.173 deleted file mode 100644 index 8f693d4e4c9..00000000000 --- a/ultimate/src/org/jetbrains/kotlin/idea/spring/lineMarking/KotlinSpringClassAnnotator.kt.173 +++ /dev/null @@ -1,152 +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.kotlin.idea.spring.lineMarking - -import com.intellij.codeInsight.daemon.GutterIconNavigationHandler -import com.intellij.codeInsight.daemon.LineMarkerInfo -import com.intellij.codeInsight.daemon.RelatedItemLineMarkerInfo -import com.intellij.navigation.GotoRelatedItem -import com.intellij.openapi.editor.markup.GutterIconRenderer -import com.intellij.openapi.util.NotNullLazyValue -import com.intellij.psi.PsiAnnotation -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiNameIdentifierOwner -import com.intellij.psi.impl.source.tree.LeafPsiElement -import com.intellij.spring.gutter.SpringClassAnnotator -import com.intellij.util.Function -import com.intellij.util.SmartList -import org.jetbrains.kotlin.asJava.elements.KtLightAnnotationForSourceEntry -import org.jetbrains.kotlin.asJava.elements.KtLightElement -import org.jetbrains.kotlin.asJava.elements.KtLightIdentifier -import org.jetbrains.kotlin.asJava.elements.KtLightMethod -import org.jetbrains.kotlin.asJava.toLightAnnotation -import org.jetbrains.kotlin.asJava.toLightClass -import org.jetbrains.kotlin.asJava.toLightElements -import org.jetbrains.kotlin.asJava.toLightMethods -import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject -import org.jetbrains.kotlin.psi.psiUtil.getCallNameExpression -import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypeAndBranch -import org.jetbrains.kotlin.resolve.annotations.hasJvmStaticAnnotation -import javax.swing.Icon - -class KotlinSpringClassAnnotator : SpringClassAnnotator() { - override fun getElementToProcess(psiElement: PsiElement): PsiElement? { - if (psiElement is KtLightIdentifier) return psiElement.parent - psiElement.getParentOfTypeAndBranch { nameIdentifier }?.let { return it.toLightClass() } - psiElement.getParentOfTypeAndBranch { nameIdentifier }?.let { function -> - val containingClassOrObject = function.containingClassOrObject - val classForLightMethod = if (containingClassOrObject is KtObjectDeclaration - && containingClassOrObject.isCompanion() - && function.resolveToDescriptor().hasJvmStaticAnnotation()) { - containingClassOrObject.containingClassOrObject - } - else { - containingClassOrObject - } - return classForLightMethod?.toLightClass()?.methods?.firstOrNull { (it as? KtLightMethod)?.kotlinOrigin == function } - } - psiElement.getParentOfTypeAndBranch> { getConstructorKeyword() ?: getValueParameterList() }?.let { - return it.toLightMethods().firstOrNull() - } - psiElement.getParentOfTypeAndBranch { nameIdentifier }?.let { return it } - psiElement.getParentOfTypeAndBranch { nameIdentifier }?.let { if (it.valOrVarKeyword != null) return it } - psiElement.getParentOfTypeAndBranch { - (typeReference?.typeElement as? KtUserType)?.referenceExpression?.getReferencedNameElement() - }?.let { return it.toLightAnnotation() } - return null - } - - private fun doCollectMarkers(psiElement: PsiElement, result: MutableCollection>) { - if (psiElement is KtProperty || psiElement is KtParameter) { - for (it in (psiElement as KtDeclaration).toLightElements()) { - val nameIdentifier = (it as? PsiNameIdentifierOwner)?.nameIdentifier ?: continue - super.collectNavigationMarkers(nameIdentifier, result) - } - return - } - - // Workaround for SpringClassAnnotator - (getElementToProcess(psiElement) as? KtLightAnnotationForSourceEntry)?.let { return super.collectNavigationMarkers(it, result) } - - super.collectNavigationMarkers(psiElement, result) - } - - // TODO - // Weak references to light elements may be reclaimed by GC after original file is modified causing line markers to misbehave - // This workaround allows reuse of SpringClassAnnotator logic and avoids binding of line markers to light elements - - private val toolTipProviderField by lazy { LineMarkerInfo::class.java.getDeclaredField("myTooltipProvider").apply { isAccessible = true } } - private val iconField by lazy { LineMarkerInfo::class.java.getDeclaredField("myIcon").apply { isAccessible = true } } - private val iconAlignmentField by lazy { LineMarkerInfo::class.java.getDeclaredField("myIconAlignment").apply { isAccessible = true } } - private val targetsField by lazy { RelatedItemLineMarkerInfo::class.java.getDeclaredField("myTargets").apply { isAccessible = true } } - - override fun getIdentifierLocal(annotation: PsiAnnotation): PsiElement? { - return when (annotation) { - is KtLightAnnotationForSourceEntry -> annotation.kotlinOrigin.getCallNameExpression()?.getIdentifier() - else -> super.getIdentifierLocal(annotation) - } - } - - override fun collectNavigationMarkers(psiElement: PsiElement, result: MutableCollection>) { - val newItems = SmartList>() - - doCollectMarkers(psiElement, newItems) - - newItems.mapNotNullTo(result) { item -> - val itemElement = item.element - val elementToAnnotate = when (itemElement) { - is KtLightIdentifier -> itemElement.origin.let { ktElement -> - when (ktElement) { - is KtParameterList -> ktElement.leftParenthesis - else -> ktElement - } - } - is KtLightElement<*, *> -> itemElement.kotlinOrigin - is LeafPsiElement -> itemElement - else -> return@mapNotNullTo item - } - if (elementToAnnotate == null) return@mapNotNullTo null - if (alreadyMarked(result, elementToAnnotate, item.navigationHandler)) return@mapNotNullTo null - - @Suppress("UNCHECKED_CAST") - RelatedItemLineMarkerInfo( - elementToAnnotate, - elementToAnnotate.textRange, - iconField.get(item) as Icon?, - item.updatePass, - toolTipProviderField.get(item) as Function, - item.navigationHandler, - iconAlignmentField.get(item) as GutterIconRenderer.Alignment, - targetsField.get(item) as NotNullLazyValue> - ) - } - } - - private fun alreadyMarked(result: MutableCollection>, - elementToAnnotate: PsiElement, - navigationHandler: GutterIconNavigationHandler<*>?) = - result.any { - when (it) { - is RelatedItemLineMarkerInfo<*> -> { - it.element == elementToAnnotate && it.navigationHandler == navigationHandler - } - else -> false - } - } -} \ No newline at end of file diff --git a/ultimate/testData/inspections/spring/autowiring/inspectionData/inspections.test.173 b/ultimate/testData/inspections/spring/autowiring/inspectionData/inspections.test.173 deleted file mode 100644 index f3e24f5d25c..00000000000 --- a/ultimate/testData/inspections/spring/autowiring/inspectionData/inspections.test.173 +++ /dev/null @@ -1,4 +0,0 @@ -// INSPECTION_CLASS: org.jetbrains.kotlin.idea.spring.inspections.SpringKotlinAutowiringInspection -// FIXTURE_CLASS: org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension -// CONFIGURE_SPRING_FILE_SET -// RUNTIME_WITH_FULL_JDK \ No newline at end of file diff --git a/ultimate/testData/inspections/spring/finalSpringAnnotatedDeclaration/inspectionData/expected.xml.173 b/ultimate/testData/inspections/spring/finalSpringAnnotatedDeclaration/inspectionData/expected.xml.173 deleted file mode 100644 index c525c7ca7aa..00000000000 --- a/ultimate/testData/inspections/spring/finalSpringAnnotatedDeclaration/inspectionData/expected.xml.173 +++ /dev/null @@ -1,130 +0,0 @@ - - - test.kt - 22 - light_idea_test_case - - Final Kotlin class or function with Spring annotation - @Configuration class should be declared open - - - test.kt - 25 - light_idea_test_case - - Final Kotlin class or function with Spring annotation - @Configuration class should be declared open - - - test.kt - 36 - light_idea_test_case - - Final Kotlin class or function with Spring annotation - @Component class should be declared open - - - test.kt - 45 - light_idea_test_case - - Final Kotlin class or function with Spring annotation - @Bean function should be declared open - - - test.kt - 48 - light_idea_test_case - - Final Kotlin class or function with Spring annotation - @Bean function should be declared open - - - test.kt - 59 - light_idea_test_case - - Final Kotlin class or function with Spring annotation - @Bean function should be declared open - - - test.kt - 62 - light_idea_test_case - - Final Kotlin class or function with Spring annotation - @Bean function should be declared open - - - test.kt - 74 - light_idea_test_case - - Final Kotlin class or function with Spring annotation - @Transactional class should be declared open - - - test.kt - 76 - light_idea_test_case - - Final Kotlin class or function with Spring annotation - @Transactional function should be declared open - - - test.kt - 79 - light_idea_test_case - - Final Kotlin class or function with Spring annotation - @Transactional function should be declared open - - - test.kt - 91 - light_idea_test_case - - Final Kotlin class or function with Spring annotation - @Transactional function should be declared open - - - test.kt - 94 - light_idea_test_case - - Final Kotlin class or function with Spring annotation - @Transactional function should be declared open - - - test.kt - 106 - light_idea_test_case - - Final Kotlin class or function with Spring annotation - @Configuration should not be applied to object declaration - - - test.kt - 109 - light_idea_test_case - - Final Kotlin class or function with Spring annotation - @Configuration should not be applied to object declaration - - - test.kt - 112 - light_idea_test_case - - Final Kotlin class or function with Spring annotation - @Component should not be applied to object declaration - - - test.kt - 115 - light_idea_test_case - - Final Kotlin class or function with Spring annotation - @Transactional should not be applied to object declaration - - diff --git a/ultimate/testData/inspections/spring/finalSpringAnnotatedDeclaration/inspectionData/inspections.test.173 b/ultimate/testData/inspections/spring/finalSpringAnnotatedDeclaration/inspectionData/inspections.test.173 deleted file mode 100644 index f9437be0350..00000000000 --- a/ultimate/testData/inspections/spring/finalSpringAnnotatedDeclaration/inspectionData/inspections.test.173 +++ /dev/null @@ -1,2 +0,0 @@ -// INSPECTION_CLASS: org.jetbrains.kotlin.idea.spring.inspections.KotlinFinalClassOrFunSpringInspection -// FIXTURE_CLASS: org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension \ No newline at end of file diff --git a/ultimate/testData/inspections/spring/finalSpringAnnotatedDeclaration/test.kt.173 b/ultimate/testData/inspections/spring/finalSpringAnnotatedDeclaration/test.kt.173 deleted file mode 100644 index 26d42ace7d0..00000000000 --- a/ultimate/testData/inspections/spring/finalSpringAnnotatedDeclaration/test.kt.173 +++ /dev/null @@ -1,115 +0,0 @@ - -// WITH_RUNTIME - -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.ComponentScan -import org.springframework.context.annotation.Configuration -import org.springframework.stereotype.Component -import org.springframework.transaction.annotation.Transactional - -@Configuration -annotation class MyConfiguration - -@Bean -annotation class MyBean - -@Transactional -annotation class MyTransactional - -// @Configuration - -@Configuration -class Application1 - -@MyConfiguration -class Application2 - -@Configuration -open class Application3 - -@MyConfiguration -open class Application4 - -// @Component - -@Component -class Component1 - -@Component -open class Component2 - -// @Bean - -class Utils1 { - @Bean - fun foo1() = Component1() - - @MyBean - fun foo2() = Component2() - - @Bean - open fun foo3() = Component3() - - @MyBean - open fun foo4() = Component4() -} - -open class Utils2 { - @Bean - fun foo1() = Component1() - - @MyBean - fun foo2() = Component2() - - @Bean - open fun foo3() = Component3() - - @MyBean - open fun foo4() = Component4() -} - -// @Transactional - -@Transactional -class Trans1 { - @Transactional - fun foo1() = Component1() - - @MyTransactional - fun foo2() = Component2() - - @Transactional - open fun foo3() = Component3() - - @MyTransactional - open fun foo4() = Component4() -} - -@Transactional -open class Trans2 { - @Transactional - fun foo1() = Component1() - - @MyTransactional - fun foo2() = Component2() - - @Transactional - open fun foo3() = Component3() - - @MyTransactional - open fun foo4() = Component4() -} - -// Object declarations - -@Configuration -object Application5 - -@MyConfiguration -object Application6 - -@Component -object Component3 - -@Transactional -object Trans3 \ No newline at end of file diff --git a/ultimate/testData/quickFixes/spring/addQualifierAnnotation/.inspection.173 b/ultimate/testData/quickFixes/spring/addQualifierAnnotation/.inspection.173 deleted file mode 100644 index e188cf5be38..00000000000 --- a/ultimate/testData/quickFixes/spring/addQualifierAnnotation/.inspection.173 +++ /dev/null @@ -1 +0,0 @@ -org.jetbrains.kotlin.idea.spring.inspections.SpringKotlinAutowiringInspection \ No newline at end of file diff --git a/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/.inspection.173 b/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/.inspection.173 deleted file mode 100644 index 4e681838d1b..00000000000 --- a/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/.inspection.173 +++ /dev/null @@ -1 +0,0 @@ -org.jetbrains.kotlin.idea.spring.inspections.KotlinFinalClassOrFunSpringInspection \ No newline at end of file diff --git a/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/classWithComponentRuntime.kt.173 b/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/classWithComponentRuntime.kt.173 deleted file mode 100644 index bd1f35511a7..00000000000 --- a/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/classWithComponentRuntime.kt.173 +++ /dev/null @@ -1,7 +0,0 @@ -// "Make class Bean open" "true" -// FIXTURE_CLASS: org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension -// DISABLE-ERRORS -import org.springframework.stereotype.Component - -@Component -class Bean \ No newline at end of file diff --git a/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/classWithComponentRuntime.kt.after.173 b/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/classWithComponentRuntime.kt.after.173 deleted file mode 100644 index cd8c986adac..00000000000 --- a/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/classWithComponentRuntime.kt.after.173 +++ /dev/null @@ -1,7 +0,0 @@ -// "Make class Bean open" "true" -// FIXTURE_CLASS: org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension -// DISABLE-ERRORS -import org.springframework.stereotype.Component - -@Component -open class Bean \ No newline at end of file diff --git a/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/classWithConfigurationRuntime.kt.173 b/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/classWithConfigurationRuntime.kt.173 deleted file mode 100644 index 2207fdfa6cb..00000000000 --- a/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/classWithConfigurationRuntime.kt.173 +++ /dev/null @@ -1,7 +0,0 @@ -// "Make class Application open" "true" -// FIXTURE_CLASS: org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension -// DISABLE-ERRORS -import org.springframework.context.annotation.Configuration - -@Configuration -class Application \ No newline at end of file diff --git a/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/classWithConfigurationRuntime.kt.after.173 b/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/classWithConfigurationRuntime.kt.after.173 deleted file mode 100644 index 57b7e3216f8..00000000000 --- a/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/classWithConfigurationRuntime.kt.after.173 +++ /dev/null @@ -1,7 +0,0 @@ -// "Make class Application open" "true" -// FIXTURE_CLASS: org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension -// DISABLE-ERRORS -import org.springframework.context.annotation.Configuration - -@Configuration -open class Application \ No newline at end of file diff --git a/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/classWithCustomConfigurationRuntime.kt.173 b/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/classWithCustomConfigurationRuntime.kt.173 deleted file mode 100644 index b162e021593..00000000000 --- a/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/classWithCustomConfigurationRuntime.kt.173 +++ /dev/null @@ -1,10 +0,0 @@ -// "Make class Application open" "true" -// FIXTURE_CLASS: org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension -// DISABLE-ERRORS -import org.springframework.context.annotation.Configuration - -@Configuration -annotation class MyConfiguration - -@MyConfiguration -class Application \ No newline at end of file diff --git a/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/classWithCustomConfigurationRuntime.kt.after.173 b/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/classWithCustomConfigurationRuntime.kt.after.173 deleted file mode 100644 index 67167424348..00000000000 --- a/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/classWithCustomConfigurationRuntime.kt.after.173 +++ /dev/null @@ -1,10 +0,0 @@ -// "Make class Application open" "true" -// FIXTURE_CLASS: org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension -// DISABLE-ERRORS -import org.springframework.context.annotation.Configuration - -@Configuration -annotation class MyConfiguration - -@MyConfiguration -open class Application \ No newline at end of file diff --git a/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/funWithBeanFinalClassRuntime.kt.173 b/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/funWithBeanFinalClassRuntime.kt.173 deleted file mode 100644 index 61ac1ddd46b..00000000000 --- a/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/funWithBeanFinalClassRuntime.kt.173 +++ /dev/null @@ -1,9 +0,0 @@ -// "Make function foo open" "true" -// FIXTURE_CLASS: org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension -// DISABLE-ERRORS -import org.springframework.context.annotation.Bean - -class Foo { - @Bean - fun foo() = "" -} \ No newline at end of file diff --git a/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/funWithBeanFinalClassRuntime.kt.after.173 b/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/funWithBeanFinalClassRuntime.kt.after.173 deleted file mode 100644 index 4dcbfeef188..00000000000 --- a/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/funWithBeanFinalClassRuntime.kt.after.173 +++ /dev/null @@ -1,9 +0,0 @@ -// "Make function foo open" "true" -// FIXTURE_CLASS: org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension -// DISABLE-ERRORS -import org.springframework.context.annotation.Bean - -open class Foo { - @Bean - open fun foo() = "" -} \ No newline at end of file diff --git a/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/funWithBeanOpenClassRuntime.kt.173 b/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/funWithBeanOpenClassRuntime.kt.173 deleted file mode 100644 index b5bd87e370b..00000000000 --- a/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/funWithBeanOpenClassRuntime.kt.173 +++ /dev/null @@ -1,9 +0,0 @@ -// "Make function foo open" "true" -// FIXTURE_CLASS: org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension -// DISABLE-ERRORS -import org.springframework.context.annotation.Bean - -open class Foo { - @Bean - fun foo() = "" -} \ No newline at end of file diff --git a/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/funWithBeanOpenClassRuntime.kt.after.173 b/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/funWithBeanOpenClassRuntime.kt.after.173 deleted file mode 100644 index 4dcbfeef188..00000000000 --- a/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/funWithBeanOpenClassRuntime.kt.after.173 +++ /dev/null @@ -1,9 +0,0 @@ -// "Make function foo open" "true" -// FIXTURE_CLASS: org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension -// DISABLE-ERRORS -import org.springframework.context.annotation.Bean - -open class Foo { - @Bean - open fun foo() = "" -} \ No newline at end of file diff --git a/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/funWithCustomBeanFinalClassRuntime.kt.173 b/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/funWithCustomBeanFinalClassRuntime.kt.173 deleted file mode 100644 index 4f88a0b5a16..00000000000 --- a/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/funWithCustomBeanFinalClassRuntime.kt.173 +++ /dev/null @@ -1,12 +0,0 @@ -// "Make function foo open" "true" -// FIXTURE_CLASS: org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension -// DISABLE-ERRORS -import org.springframework.context.annotation.Bean - -@Bean -annotation class MyBean - -class Foo { - @MyBean - fun foo() = "" -} \ No newline at end of file diff --git a/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/funWithCustomBeanFinalClassRuntime.kt.after.173 b/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/funWithCustomBeanFinalClassRuntime.kt.after.173 deleted file mode 100644 index 777c72f8120..00000000000 --- a/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/funWithCustomBeanFinalClassRuntime.kt.after.173 +++ /dev/null @@ -1,12 +0,0 @@ -// "Make function foo open" "true" -// FIXTURE_CLASS: org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension -// DISABLE-ERRORS -import org.springframework.context.annotation.Bean - -@Bean -annotation class MyBean - -open class Foo { - @MyBean - open fun foo() = "" -} \ No newline at end of file diff --git a/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/funWithCustomBeanOpenClassRuntime.kt.173 b/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/funWithCustomBeanOpenClassRuntime.kt.173 deleted file mode 100644 index d12f89144e2..00000000000 --- a/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/funWithCustomBeanOpenClassRuntime.kt.173 +++ /dev/null @@ -1,12 +0,0 @@ -// "Make function foo open" "true" -// FIXTURE_CLASS: org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension -// DISABLE-ERRORS -import org.springframework.context.annotation.Bean - -@Bean -annotation class MyBean - -open class Foo { - @MyBean - fun foo() = "" -} \ No newline at end of file diff --git a/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/funWithCustomBeanOpenClassRuntime.kt.after.173 b/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/funWithCustomBeanOpenClassRuntime.kt.after.173 deleted file mode 100644 index 777c72f8120..00000000000 --- a/ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/funWithCustomBeanOpenClassRuntime.kt.after.173 +++ /dev/null @@ -1,12 +0,0 @@ -// "Make function foo open" "true" -// FIXTURE_CLASS: org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension -// DISABLE-ERRORS -import org.springframework.context.annotation.Bean - -@Bean -annotation class MyBean - -open class Foo { - @MyBean - open fun foo() = "" -} \ No newline at end of file diff --git a/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/findUsages/SpringFindUsagesTestGenerated.java.173 b/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/findUsages/SpringFindUsagesTestGenerated.java.173 deleted file mode 100644 index 4c08ade96e9..00000000000 --- a/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/findUsages/SpringFindUsagesTestGenerated.java.173 +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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.kotlin.idea.spring.tests.findUsages; - -import com.intellij.testFramework.TestDataPath; -import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; -import org.jetbrains.kotlin.test.KotlinTestUtils; -import org.jetbrains.kotlin.test.TargetBackend; -import org.jetbrains.kotlin.test.TestMetadata; -import org.junit.runner.RunWith; - -import java.io.File; -import java.util.regex.Pattern; - -/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ -@SuppressWarnings("all") -@TestMetadata("ultimate/testData/spring/core/findUsages") -@TestDataPath("$PROJECT_ROOT") -@RunWith(JUnit3RunnerWithInners.class) -public class SpringFindUsagesTestGenerated extends AbstractSpringFindUsagesTest { - public void testAllFilesPresentInFindUsages() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("ultimate/testData/spring/core/findUsages"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); - } - - @TestMetadata("classXml.kt") - public void testClassXml() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/findUsages/classXml.kt"); - doTest(fileName); - } - - @TestMetadata("primaryConstructorArgXml.kt") - public void testPrimaryConstructorArgXml() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/findUsages/primaryConstructorArgXml.kt"); - doTest(fileName); - } - - @TestMetadata("propertyXml.kt") - public void testPropertyXml() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/findUsages/propertyXml.kt"); - doTest(fileName); - } - - @TestMetadata("setterFunXml.kt") - public void testSetterFunXml() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/findUsages/setterFunXml.kt"); - doTest(fileName); - } -} diff --git a/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/generate/GenerateSpringDependencyActionTestGenerated.java.173 b/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/generate/GenerateSpringDependencyActionTestGenerated.java.173 deleted file mode 100644 index 45d599af15c..00000000000 --- a/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/generate/GenerateSpringDependencyActionTestGenerated.java.173 +++ /dev/null @@ -1,116 +0,0 @@ -/* - * 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.kotlin.idea.spring.tests.generate; - -import com.intellij.testFramework.TestDataPath; -import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; -import org.jetbrains.kotlin.test.KotlinTestUtils; -import org.jetbrains.kotlin.test.TargetBackend; -import org.jetbrains.kotlin.test.TestMetadata; -import org.junit.runner.RunWith; - -import java.io.File; -import java.util.regex.Pattern; - -/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ -@SuppressWarnings("all") -@TestMetadata("ultimate/testData/spring/core/generate") -@TestDataPath("$PROJECT_ROOT") -@RunWith(JUnit3RunnerWithInners.class) -public class GenerateSpringDependencyActionTestGenerated extends AbstractGenerateSpringDependencyActionTest { - public void testAllFilesPresentInGenerate() throws Exception { - KotlinTestUtils.assertAllTestsPresentInSingleGeneratedClass(this.getClass(), new File("ultimate/testData/spring/core/generate"), Pattern.compile("^([\\w]+)\\.kt$"), TargetBackend.ANY); - } - - @TestMetadata("autowiredDependencies/duplicatingPropertyAnnotationConfig.kt") - public void testAutowiredDependencies_DuplicatingPropertyAnnotationConfig() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/generate/autowiredDependencies/duplicatingPropertyAnnotationConfig.kt"); - doTest(fileName); - } - - @TestMetadata("autowiredDependencies/duplicatingPropertyXmlConfig.kt") - public void testAutowiredDependencies_DuplicatingPropertyXmlConfig() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/generate/autowiredDependencies/duplicatingPropertyXmlConfig.kt"); - doTest(fileName); - } - - @TestMetadata("autowiredDependencies/multiplePropertiesAnnotationConfig.kt") - public void testAutowiredDependencies_MultiplePropertiesAnnotationConfig() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/generate/autowiredDependencies/multiplePropertiesAnnotationConfig.kt"); - doTest(fileName); - } - - @TestMetadata("autowiredDependencies/multiplePropertiesXmlConfig.kt") - public void testAutowiredDependencies_MultiplePropertiesXmlConfig() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/generate/autowiredDependencies/multiplePropertiesXmlConfig.kt"); - doTest(fileName); - } - - @TestMetadata("autowiredDependencies/propertyWithQualifierAnnotationConfig.kt") - public void testAutowiredDependencies_PropertyWithQualifierAnnotationConfig() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/generate/autowiredDependencies/propertyWithQualifierAnnotationConfig.kt"); - doTest(fileName); - } - - @TestMetadata("autowiredDependencies/propertyWithQualifierXmlConfig.kt") - public void testAutowiredDependencies_PropertyWithQualifierXmlConfig() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/generate/autowiredDependencies/propertyWithQualifierXmlConfig.kt"); - doTest(fileName); - } - - @TestMetadata("autowiredDependencies/singlePropertyAnnotationConfig.kt") - public void testAutowiredDependencies_SinglePropertyAnnotationConfig() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/generate/autowiredDependencies/singlePropertyAnnotationConfig.kt"); - doTest(fileName); - } - - @TestMetadata("autowiredDependencies/singlePropertyXmlConfig.kt") - public void testAutowiredDependencies_SinglePropertyXmlConfig() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/generate/autowiredDependencies/singlePropertyXmlConfig.kt"); - doTest(fileName); - } - - @TestMetadata("beanDependenciesByXml/firstConstructor.kt") - public void testBeanDependenciesByXml_FirstConstructor() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/generate/beanDependenciesByXml/firstConstructor.kt"); - doTest(fileName); - } - - @TestMetadata("beanDependenciesByXml/primaryConstructorAddParam.kt") - public void testBeanDependenciesByXml_PrimaryConstructorAddParam() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/generate/beanDependenciesByXml/primaryConstructorAddParam.kt"); - doTest(fileName); - } - - @TestMetadata("beanDependenciesByXml/property.kt") - public void testBeanDependenciesByXml_Property() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/generate/beanDependenciesByXml/property.kt"); - doTest(fileName); - } - - @TestMetadata("beanDependenciesByXml/secondaryConstructorAddParam.kt") - public void testBeanDependenciesByXml_SecondaryConstructorAddParam() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/generate/beanDependenciesByXml/secondaryConstructorAddParam.kt"); - doTest(fileName); - } - - @TestMetadata("beanDependenciesByXml/setter.kt") - public void testBeanDependenciesByXml_Setter() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/generate/beanDependenciesByXml/setter.kt"); - doTest(fileName); - } -} diff --git a/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/gutter/AbstractSpringClassAnnotatorTest.kt.173 b/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/gutter/AbstractSpringClassAnnotatorTest.kt.173 deleted file mode 100644 index 19079df2504..00000000000 --- a/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/gutter/AbstractSpringClassAnnotatorTest.kt.173 +++ /dev/null @@ -1,110 +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.kotlin.idea.spring.tests.gutter - -import com.google.gson.JsonArray -import com.google.gson.JsonObject -import com.google.gson.JsonParser -import com.intellij.codeInsight.daemon.LineMarkerProviders -import com.intellij.openapi.util.io.FileUtil -import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase -import icons.SpringApiIcons -import junit.framework.Assert -import junit.framework.AssertionFailedError -import org.jetbrains.kotlin.idea.KotlinLanguage -import org.jetbrains.kotlin.idea.jsonUtils.getString -import org.jetbrains.kotlin.idea.spring.lineMarking.KotlinSpringClassAnnotator -import org.jetbrains.kotlin.idea.spring.tests.SpringTestFixtureExtension -import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil -import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase -import org.jetbrains.kotlin.idea.test.PluginTestCaseBase -import org.jetbrains.kotlin.idea.test.TestFixtureExtension -import org.jetbrains.kotlin.test.KotlinTestUtils -import java.io.File - -abstract class AbstractSpringClassAnnotatorTest : KotlinLightCodeInsightFixtureTestCase() { - override fun getProjectDescriptor() = LightCodeInsightFixtureTestCase.JAVA_LATEST - - override fun setUp() { - super.setUp() - TestFixtureExtension.loadFixture(myModule) - Assert.assertTrue("Kotlin-ultimate service was not found, make sure that " + - "is replaced in `plugin.xml` with data from `ultimate-plugin.xml`", - LineMarkerProviders.INSTANCE.allForLanguage(KotlinLanguage.INSTANCE).any { it is KotlinSpringClassAnnotator } - ) - } - - protected fun doTest(path: String) { - val configFilePath = "${KotlinTestUtils.getHomeDirectory()}/$path" - val configFile = File(configFilePath) - val testRoot = configFile.parentFile - - val config = JsonParser().parse(FileUtil.loadFile(configFile, true)) as JsonObject - - PluginTestCaseBase.addJdk(myFixture.projectDisposable, PluginTestCaseBase::mockJdk) - - val withRuntime = config["withRuntime"]?.asBoolean ?: false - if (withRuntime) { - ConfigLibraryUtil.configureKotlinRuntimeAndSdk(myModule, PluginTestCaseBase.mockJdk()) - } - - try { - val springConfigFiles = (config["springConfig"] as JsonArray).map { it.asString } - myFixture.testDataPath = testRoot.absolutePath - for (file in testRoot.listFiles()) { - val name = file.name - if (file.isDirectory) myFixture.copyDirectoryToProject(name, name) else myFixture.configureByFile(name) - } - TestFixtureExtension.getFixture()!!.configureFileSet(myFixture, springConfigFiles) - - val fileName = config.getString("file") - val iconName = config.getString("icon") - val icon = SpringApiIcons.Gutter::class.java.getField(iconName)[null] - - val gutter = myFixture.findGutter(fileName) ?: throw AssertionError("no gutter for '$fileName'") - val gutterMark = gutter.let { - if (it.icon == icon) it - else myFixture.findGuttersAtCaret().let { gutters -> - gutters.firstOrNull() { it.icon == icon } - ?: throw AssertionFailedError("no $icon in gutters: ${gutters.map { it.icon }}") - } - } - - val tooltip = config.getString("tooltip") - Assert.assertEquals(tooltip, gutterMark.tooltipText) - - val naming = config.getString("naming") - val targets = (config["targets"] as JsonArray).map { it.asString } - when (naming) { - "bean" -> checkBeanGutterTargets(gutterMark, targets) - "property" -> checkBeanPropertyTargets(gutterMark, targets) - "generic" -> checkPsiElementGutterTargets(gutterMark, targets) - else -> error("Unexpected naming: $naming") - } - } - finally { - if (withRuntime) { - ConfigLibraryUtil.unConfigureKotlinRuntimeAndSdk(myModule, PluginTestCaseBase.mockJdk()) - } - } - } - - override fun tearDown() { - TestFixtureExtension.unloadFixture() - super.tearDown() - } -} diff --git a/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/gutter/SpringClassAnnotatorTestGenerated.java.173 b/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/gutter/SpringClassAnnotatorTestGenerated.java.173 deleted file mode 100644 index 49869c1ab6d..00000000000 --- a/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/gutter/SpringClassAnnotatorTestGenerated.java.173 +++ /dev/null @@ -1,158 +0,0 @@ -/* - * 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.kotlin.idea.spring.tests.gutter; - -import com.intellij.testFramework.TestDataPath; -import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; -import org.jetbrains.kotlin.test.KotlinTestUtils; -import org.jetbrains.kotlin.test.TargetBackend; -import org.jetbrains.kotlin.test.TestMetadata; -import org.junit.runner.RunWith; - -import java.io.File; -import java.util.regex.Pattern; - -/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ -@SuppressWarnings("all") -@TestMetadata("ultimate/testData/spring/core/gutter") -@TestDataPath("$PROJECT_ROOT") -@RunWith(JUnit3RunnerWithInners.class) -public class SpringClassAnnotatorTestGenerated extends AbstractSpringClassAnnotatorTest { - public void testAllFilesPresentInGutter() throws Exception { - KotlinTestUtils.assertAllTestsPresentInSingleGeneratedClass(this.getClass(), new File("ultimate/testData/spring/core/gutter"), Pattern.compile("^(.+)\\.test$"), TargetBackend.ANY); - } - - @TestMetadata("autowiredBeanCandidates/autowiredBeanCandidates.test") - public void testAutowiredBeanCandidates_AutowiredBeanCandidates() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/gutter/autowiredBeanCandidates/autowiredBeanCandidates.test"); - doTest(fileName); - } - - @TestMetadata("autowiredConstructor/autowiredConstructor.test") - public void testAutowiredConstructor_AutowiredConstructor() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/gutter/autowiredConstructor/autowiredConstructor.test"); - doTest(fileName); - } - - @TestMetadata("autowiredProperty/autowiredProperty.test") - public void testAutowiredProperty_AutowiredProperty() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/gutter/autowiredProperty/autowiredProperty.test"); - doTest(fileName); - } - - @TestMetadata("autowiredSetter/autowiredSetter.test") - public void testAutowiredSetter_AutowiredSetter() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/gutter/autowiredSetter/autowiredSetter.test"); - doTest(fileName); - } - - @TestMetadata("classGutter/classGutter.test") - public void testClassGutter_ClassGutter() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/gutter/classGutter/classGutter.test"); - doTest(fileName); - } - - @TestMetadata("classGutterAbstractShowMappedInheritors/classGutterAbstractShowMappedInheritors.test") - public void testClassGutterAbstractShowMappedInheritors_ClassGutterAbstractShowMappedInheritors() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/gutter/classGutterAbstractShowMappedInheritors/classGutterAbstractShowMappedInheritors.test"); - doTest(fileName); - } - - @TestMetadata("componentScan/componentScan.test") - public void testComponentScan_ComponentScan() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/gutter/componentScan/componentScan.test"); - doTest(fileName); - } - - @TestMetadata("componentScanWithBasePackageClasses/componentScanWithBasePackageClasses.test") - public void testComponentScanWithBasePackageClasses_ComponentScanWithBasePackageClasses() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/gutter/componentScanWithBasePackageClasses/componentScanWithBasePackageClasses.test"); - doTest(fileName); - } - - @TestMetadata("componentScanWithBasePackages/componentScanWithBasePackages.test") - public void testComponentScanWithBasePackages_ComponentScanWithBasePackages() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/gutter/componentScanWithBasePackages/componentScanWithBasePackages.test"); - doTest(fileName); - } - - @TestMetadata("contextBeanInjectionPoints/contextBeanInjectionPoints.test") - public void testContextBeanInjectionPoints_ContextBeanInjectionPoints() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/gutter/contextBeanInjectionPoints/contextBeanInjectionPoints.test"); - doTest(fileName); - } - - @TestMetadata("contextBeanWithQualifierInjectionPoints/contextBeanWithQualifierInjectionPoints.test") - public void testContextBeanWithQualifierInjectionPoints_ContextBeanWithQualifierInjectionPoints() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/gutter/contextBeanWithQualifierInjectionPoints/contextBeanWithQualifierInjectionPoints.test"); - doTest(fileName); - } - - @TestMetadata("importConfigClasses/importConfigClasses.test") - public void testImportConfigClasses_ImportConfigClasses() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/gutter/importConfigClasses/importConfigClasses.test"); - doTest(fileName); - } - - @TestMetadata("innerBean/innerBean.test") - public void testInnerBean_InnerBean() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/gutter/innerBean/innerBean.test"); - doTest(fileName); - } - - @TestMetadata("methodTypeDefaultInitMethod/methodTypeDefaultInitMethod.test") - public void testMethodTypeDefaultInitMethod_MethodTypeDefaultInitMethod() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/gutter/methodTypeDefaultInitMethod/methodTypeDefaultInitMethod.test"); - doTest(fileName); - } - - @TestMetadata("methodTypeFactory/methodTypeFactory.test") - public void testMethodTypeFactory_MethodTypeFactory() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/gutter/methodTypeFactory/methodTypeFactory.test"); - doTest(fileName); - } - - @TestMetadata("methodTypeInitMethod/methodTypeInitMethod.test") - public void testMethodTypeInitMethod_MethodTypeInitMethod() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/gutter/methodTypeInitMethod/methodTypeInitMethod.test"); - doTest(fileName); - } - - @TestMetadata("methodTypeMultiple/methodTypeMultiple.test") - public void testMethodTypeMultiple_MethodTypeMultiple() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/gutter/methodTypeMultiple/methodTypeMultiple.test"); - doTest(fileName); - } - - @TestMetadata("propertyGutterForProperty/propertyGutterForProperty.test") - public void testPropertyGutterForProperty_PropertyGutterForProperty() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/gutter/propertyGutterForProperty/propertyGutterForProperty.test"); - doTest(fileName); - } - - @TestMetadata("propertyGutterForSetter/propertyGutterForSetter.test") - public void testPropertyGutterForSetter_PropertyGutterForSetter() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/gutter/propertyGutterForSetter/propertyGutterForSetter.test"); - doTest(fileName); - } - - @TestMetadata("resourceGutter/resourceGutter.test") - public void testResourceGutter_ResourceGutter() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/gutter/resourceGutter/resourceGutter.test"); - doTest(fileName); - } -} diff --git a/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/inspections/SpringInspectionTestGenerated.java.173 b/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/inspections/SpringInspectionTestGenerated.java.173 deleted file mode 100644 index 08602ca6931..00000000000 --- a/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/inspections/SpringInspectionTestGenerated.java.173 +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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.kotlin.idea.spring.tests.inspections; - -import com.intellij.testFramework.TestDataPath; -import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; -import org.jetbrains.kotlin.test.KotlinTestUtils; -import org.jetbrains.kotlin.test.TargetBackend; -import org.jetbrains.kotlin.test.TestMetadata; -import org.junit.runner.RunWith; - -import java.io.File; -import java.util.regex.Pattern; - -/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ -@SuppressWarnings("all") -@TestMetadata("ultimate/testData/inspections/spring") -@TestDataPath("$PROJECT_ROOT") -@RunWith(JUnit3RunnerWithInners.class) -public class SpringInspectionTestGenerated extends AbstractSpringInspectionTest { - public void testAllFilesPresentInSpring() throws Exception { - KotlinTestUtils.assertAllTestsPresentInSingleGeneratedClass(this.getClass(), new File("ultimate/testData/inspections/spring"), Pattern.compile("^(inspections\\.test)$"), TargetBackend.ANY); - } - - @TestMetadata("autowiredMembersInInvalidClass/inspectionData/inspections.test") - public void testAutowiredMembersInInvalidClass_inspectionData_Inspections_test() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/inspections/spring/autowiredMembersInInvalidClass/inspectionData/inspections.test"); - doTest(fileName); - } - - @TestMetadata("autowiring/inspectionData/inspections.test") - public void testAutowiring_inspectionData_Inspections_test() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/inspections/spring/autowiring/inspectionData/inspections.test"); - doTest(fileName); - } - - @TestMetadata("componentScan/inspectionData/inspections.test") - public void testComponentScan_inspectionData_Inspections_test() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/inspections/spring/componentScan/inspectionData/inspections.test"); - doTest(fileName); - } - - @TestMetadata("finalSpringAnnotatedDeclaration/inspectionData/inspections.test") - public void testFinalSpringAnnotatedDeclaration_inspectionData_Inspections_test() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/inspections/spring/finalSpringAnnotatedDeclaration/inspectionData/inspections.test"); - doTest(fileName); - } - - @TestMetadata("unconfiguredFacet/inspectionData/inspections.test") - public void testUnconfiguredFacet_inspectionData_Inspections_test() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/inspections/spring/unconfiguredFacet/inspectionData/inspections.test"); - doTest(fileName); - } -} diff --git a/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/quickfixes/SpringQuickFixTestGenerated.java.173 b/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/quickfixes/SpringQuickFixTestGenerated.java.173 deleted file mode 100644 index d8f732072b8..00000000000 --- a/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/quickfixes/SpringQuickFixTestGenerated.java.173 +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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.kotlin.idea.spring.tests.quickfixes; - -import com.intellij.testFramework.TestDataPath; -import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; -import org.jetbrains.kotlin.test.KotlinTestUtils; -import org.jetbrains.kotlin.test.TargetBackend; -import org.jetbrains.kotlin.test.TestMetadata; -import org.junit.runner.RunWith; - -import java.io.File; -import java.util.regex.Pattern; - -/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ -@SuppressWarnings("all") -@TestMetadata("ultimate/testData/quickFixes/spring") -@TestDataPath("$PROJECT_ROOT") -@RunWith(JUnit3RunnerWithInners.class) -public class SpringQuickFixTestGenerated extends AbstractSpringQuickFixTest { - public void testAllFilesPresentInSpring() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("ultimate/testData/quickFixes/spring"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), TargetBackend.ANY, true); - } - - @TestMetadata("ultimate/testData/quickFixes/spring/addQualifierAnnotation") - @TestDataPath("$PROJECT_ROOT") - @RunWith(JUnit3RunnerWithInners.class) - public static class AddQualifierAnnotation extends AbstractSpringQuickFixTest { - public void testAllFilesPresentInAddQualifierAnnotation() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("ultimate/testData/quickFixes/spring/addQualifierAnnotation"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), TargetBackend.ANY, true); - } - - @TestMetadata("ambiguousBean.kt") - public void testAmbiguousBean() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/quickFixes/spring/addQualifierAnnotation/ambiguousBean.kt"); - doTest(fileName); - } - } - - @TestMetadata("ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration") - @TestDataPath("$PROJECT_ROOT") - @RunWith(JUnit3RunnerWithInners.class) - public static class FinalSpringAnnotatedDeclaration extends AbstractSpringQuickFixTest { - public void testAllFilesPresentInFinalSpringAnnotatedDeclaration() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), TargetBackend.ANY, true); - } - - @TestMetadata("classWithComponentRuntime.kt") - public void testClassWithComponentRuntime() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/classWithComponentRuntime.kt"); - doTest(fileName); - } - - @TestMetadata("classWithConfigurationRuntime.kt") - public void testClassWithConfigurationRuntime() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/classWithConfigurationRuntime.kt"); - doTest(fileName); - } - - @TestMetadata("classWithCustomConfigurationRuntime.kt") - public void testClassWithCustomConfigurationRuntime() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/classWithCustomConfigurationRuntime.kt"); - doTest(fileName); - } - - @TestMetadata("funWithBeanFinalClassRuntime.kt") - public void testFunWithBeanFinalClassRuntime() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/funWithBeanFinalClassRuntime.kt"); - doTest(fileName); - } - - @TestMetadata("funWithBeanOpenClassRuntime.kt") - public void testFunWithBeanOpenClassRuntime() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/funWithBeanOpenClassRuntime.kt"); - doTest(fileName); - } - - @TestMetadata("funWithCustomBeanFinalClassRuntime.kt") - public void testFunWithCustomBeanFinalClassRuntime() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/funWithCustomBeanFinalClassRuntime.kt"); - doTest(fileName); - } - - @TestMetadata("funWithCustomBeanOpenClassRuntime.kt") - public void testFunWithCustomBeanOpenClassRuntime() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/quickFixes/spring/finalSpringAnnotatedDeclaration/funWithCustomBeanOpenClassRuntime.kt"); - doTest(fileName); - } - } -} diff --git a/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/references/SpringReferenceCompletionHandlerTestGenerated.java.173 b/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/references/SpringReferenceCompletionHandlerTestGenerated.java.173 deleted file mode 100644 index 0321dcf9a5e..00000000000 --- a/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/references/SpringReferenceCompletionHandlerTestGenerated.java.173 +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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.kotlin.idea.spring.tests.references; - -import com.intellij.testFramework.TestDataPath; -import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; -import org.jetbrains.kotlin.test.KotlinTestUtils; -import org.jetbrains.kotlin.test.TargetBackend; -import org.jetbrains.kotlin.test.TestMetadata; -import org.junit.runner.RunWith; - -import java.io.File; -import java.util.regex.Pattern; - -/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ -@SuppressWarnings("all") -@TestMetadata("ultimate/testData/spring/core/references/completion/handler") -@TestDataPath("$PROJECT_ROOT") -@RunWith(JUnit3RunnerWithInners.class) -public class SpringReferenceCompletionHandlerTestGenerated extends AbstractSpringReferenceCompletionHandlerTest { - public void testAllFilesPresentInHandler() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("ultimate/testData/spring/core/references/completion/handler"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); - } - - @TestMetadata("packageReferenceEnter.kt") - public void testPackageReferenceEnter() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/references/completion/handler/packageReferenceEnter.kt"); - doTest(fileName); - } - - @TestMetadata("packageReferenceTab.kt") - public void testPackageReferenceTab() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/references/completion/handler/packageReferenceTab.kt"); - doTest(fileName); - } - - @TestMetadata("qualifierReferenceEnter.kt") - public void testQualifierReferenceEnter() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/references/completion/handler/qualifierReferenceEnter.kt"); - doTest(fileName); - } - - @TestMetadata("qualifierReferenceTab.kt") - public void testQualifierReferenceTab() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/references/completion/handler/qualifierReferenceTab.kt"); - doTest(fileName); - } - - @TestMetadata("scopeReference.kt") - public void testScopeReference() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/references/completion/handler/scopeReference.kt"); - doTest(fileName); - } - - @TestMetadata("springBeanReferenceEnter.kt") - public void testSpringBeanReferenceEnter() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/references/completion/handler/springBeanReferenceEnter.kt"); - doTest(fileName); - } - - @TestMetadata("springBeanReferenceTab.kt") - public void testSpringBeanReferenceTab() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/references/completion/handler/springBeanReferenceTab.kt"); - doTest(fileName); - } -} diff --git a/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/references/SpringReferenceCompletionTestGenerated.java.173 b/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/references/SpringReferenceCompletionTestGenerated.java.173 deleted file mode 100644 index 3338f78d7f4..00000000000 --- a/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/references/SpringReferenceCompletionTestGenerated.java.173 +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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.kotlin.idea.spring.tests.references; - -import com.intellij.testFramework.TestDataPath; -import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; -import org.jetbrains.kotlin.test.KotlinTestUtils; -import org.jetbrains.kotlin.test.TargetBackend; -import org.jetbrains.kotlin.test.TestMetadata; -import org.junit.runner.RunWith; - -import java.io.File; -import java.util.regex.Pattern; - -/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ -@SuppressWarnings("all") -@TestMetadata("ultimate/testData/spring/core/references/completion/variants") -@TestDataPath("$PROJECT_ROOT") -@RunWith(JUnit3RunnerWithInners.class) -public class SpringReferenceCompletionTestGenerated extends AbstractSpringReferenceCompletionTest { - public void testAllFilesPresentInVariants() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("ultimate/testData/spring/core/references/completion/variants"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); - } - - @TestMetadata("beanWithDefaultName.kt") - public void testBeanWithDefaultName() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/references/completion/variants/beanWithDefaultName.kt"); - doTest(fileName); - } - - @TestMetadata("beanWithExplicitName.kt") - public void testBeanWithExplicitName() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/references/completion/variants/beanWithExplicitName.kt"); - doTest(fileName); - } - - @TestMetadata("packageReference.kt") - public void testPackageReference() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/references/completion/variants/packageReference.kt"); - doTest(fileName); - } - - @TestMetadata("qualifierReference1Xml.kt") - public void testQualifierReference1Xml() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/references/completion/variants/qualifierReference1Xml.kt"); - doTest(fileName); - } - - @TestMetadata("qualifierReference2Xml.kt") - public void testQualifierReference2Xml() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/references/completion/variants/qualifierReference2Xml.kt"); - doTest(fileName); - } - - @TestMetadata("scopeReferenceXml.kt") - public void testScopeReferenceXml() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/references/completion/variants/scopeReferenceXml.kt"); - doTest(fileName); - } - - @TestMetadata("springBeanReferenceXml.kt") - public void testSpringBeanReferenceXml() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/references/completion/variants/springBeanReferenceXml.kt"); - doTest(fileName); - } -} diff --git a/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/references/SpringReferenceNavigationTestGenerated.java.173 b/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/references/SpringReferenceNavigationTestGenerated.java.173 deleted file mode 100644 index e6ef23a195a..00000000000 --- a/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/references/SpringReferenceNavigationTestGenerated.java.173 +++ /dev/null @@ -1,92 +0,0 @@ -/* - * 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.kotlin.idea.spring.tests.references; - -import com.intellij.testFramework.TestDataPath; -import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; -import org.jetbrains.kotlin.test.KotlinTestUtils; -import org.jetbrains.kotlin.test.TargetBackend; -import org.jetbrains.kotlin.test.TestMetadata; -import org.junit.runner.RunWith; - -import java.io.File; -import java.util.regex.Pattern; - -/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ -@SuppressWarnings("all") -@TestMetadata("ultimate/testData/spring/core/references/navigation") -@TestDataPath("$PROJECT_ROOT") -@RunWith(JUnit3RunnerWithInners.class) -public class SpringReferenceNavigationTestGenerated extends AbstractSpringReferenceNavigationTest { - public void testAllFilesPresentInNavigation() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("ultimate/testData/spring/core/references/navigation"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); - } - - @TestMetadata("fileReferenceInClasspathResource.kt") - public void testFileReferenceInClasspathResource() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/references/navigation/fileReferenceInClasspathResource.kt"); - doTest(fileName); - } - - @TestMetadata("fileReferenceInClasspathXmlContext.kt") - public void testFileReferenceInClasspathXmlContext() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/references/navigation/fileReferenceInClasspathXmlContext.kt"); - doTest(fileName); - } - - @TestMetadata("packageReferenceInComponentScan.kt") - public void testPackageReferenceInComponentScan() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/references/navigation/packageReferenceInComponentScan.kt"); - doTest(fileName); - } - - @TestMetadata("qualifierReference.kt") - public void testQualifierReference() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/references/navigation/qualifierReference.kt"); - doTest(fileName); - } - - @TestMetadata("scopeReference.kt") - public void testScopeReference() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/references/navigation/scopeReference.kt"); - doTest(fileName); - } - - @TestMetadata("springBeanRefInFactoryContainsBean.kt") - public void testSpringBeanRefInFactoryContainsBean() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/references/navigation/springBeanRefInFactoryContainsBean.kt"); - doTest(fileName); - } - - @TestMetadata("springBeanRefInFactoryGetBean.kt") - public void testSpringBeanRefInFactoryGetBean() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/references/navigation/springBeanRefInFactoryGetBean.kt"); - doTest(fileName); - } - - @TestMetadata("springBeanRefInResource.kt") - public void testSpringBeanRefInResource() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/references/navigation/springBeanRefInResource.kt"); - doTest(fileName); - } - - @TestMetadata("springFactoryBeanRefInResource.kt") - public void testSpringFactoryBeanRefInResource() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/references/navigation/springFactoryBeanRefInResource.kt"); - doTest(fileName); - } -} diff --git a/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/rename/SpringRenameTestGenerated.java.173 b/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/rename/SpringRenameTestGenerated.java.173 deleted file mode 100644 index ad444b28264..00000000000 --- a/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/rename/SpringRenameTestGenerated.java.173 +++ /dev/null @@ -1,176 +0,0 @@ -/* - * 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.kotlin.idea.spring.tests.rename; - -import com.intellij.testFramework.TestDataPath; -import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; -import org.jetbrains.kotlin.test.KotlinTestUtils; -import org.jetbrains.kotlin.test.TargetBackend; -import org.jetbrains.kotlin.test.TestMetadata; -import org.junit.runner.RunWith; - -import java.io.File; -import java.util.regex.Pattern; - -/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ -@SuppressWarnings("all") -@TestMetadata("ultimate/testData/spring/core/rename") -@TestDataPath("$PROJECT_ROOT") -@RunWith(JUnit3RunnerWithInners.class) -public class SpringRenameTestGenerated extends AbstractSpringRenameTest { - public void testAllFilesPresentInRename() throws Exception { - KotlinTestUtils.assertAllTestsPresentInSingleGeneratedClass(this.getClass(), new File("ultimate/testData/spring/core/rename"), Pattern.compile("^(.+)\\.test$"), TargetBackend.ANY); - } - - @TestMetadata("annotationArgBySpELRefInXMLConf/annotationArgBySpELRefInXMLConf.test") - public void testAnnotationArgBySpELRefInXMLConf_AnnotationArgBySpELRefInXMLConf() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/rename/annotationArgBySpELRefInXMLConf/annotationArgBySpELRefInXMLConf.test"); - doTest(fileName); - } - - @TestMetadata("classWithXmlRefs/classWithXmlRef.test") - public void testClassWithXmlRefs_ClassWithXmlRef() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/rename/classWithXmlRefs/classWithXmlRef.test"); - doTest(fileName); - } - - @TestMetadata("classWithXmlRefsByRef/classWithXmlRefByRef.test") - public void testClassWithXmlRefsByRef_ClassWithXmlRefByRef() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/rename/classWithXmlRefsByRef/classWithXmlRefByRef.test"); - doTest(fileName); - } - - @TestMetadata("factoryMethodParam/factoryMethodParam.test") - public void testFactoryMethodParam_FactoryMethodParam() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/rename/factoryMethodParam/factoryMethodParam.test"); - doTest(fileName); - } - - @TestMetadata("factoryMethodParamByXmlRef/factoryMethodParamByXmlRef.test") - public void testFactoryMethodParamByXmlRef_FactoryMethodParamByXmlRef() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/rename/factoryMethodParamByXmlRef/factoryMethodParamByXmlRef.test"); - doTest(fileName); - } - - @TestMetadata("isPropertyWithXmlRefsBySpelRef/isPropertyWithXmlRefBySpelRef.test") - public void testIsPropertyWithXmlRefsBySpelRef_IsPropertyWithXmlRefBySpelRef() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/rename/isPropertyWithXmlRefsBySpelRef/isPropertyWithXmlRefBySpelRef.test"); - doTest(fileName); - } - - @TestMetadata("javaSpelRefToJava/javaSpelRefToJava.test") - public void testJavaSpelRefToJava_JavaSpelRefToJava() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/rename/javaSpelRefToJava/javaSpelRefToJava.test"); - doTest(fileName); - } - - @TestMetadata("javaSpelRefToJavaAnnotated/javaSpelRefToJavaAnnotated.test") - public void testJavaSpelRefToJavaAnnotated_JavaSpelRefToJavaAnnotated() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/rename/javaSpelRefToJavaAnnotated/javaSpelRefToJavaAnnotated.test"); - doTest(fileName); - } - - @TestMetadata("javaSpelRefToKt/javaSpelRefToKt.test") - public void testJavaSpelRefToKt_JavaSpelRefToKt() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/rename/javaSpelRefToKt/javaSpelRefToKt.test"); - doTest(fileName); - } - - @TestMetadata("javaSpelRefToKtAnnotated/javaSpelRefToKtAnnotated.test") - public void testJavaSpelRefToKtAnnotated_JavaSpelRefToKtAnnotated() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/rename/javaSpelRefToKtAnnotated/javaSpelRefToKtAnnotated.test"); - doTest(fileName); - } - - @TestMetadata("ktSpelRefToJava/ktSpelRefToJava.test") - public void testKtSpelRefToJava_KtSpelRefToJava() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/rename/ktSpelRefToJava/ktSpelRefToJava.test"); - doTest(fileName); - } - - @TestMetadata("ktSpelRefToJavaAnnotated/ktSpelRefToJavaAnnotated.test") - public void testKtSpelRefToJavaAnnotated_KtSpelRefToJavaAnnotated() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/rename/ktSpelRefToJavaAnnotated/ktSpelRefToJavaAnnotated.test"); - doTest(fileName); - } - - @TestMetadata("ktSpelRefToKt/ktSpelRefToKt.test") - public void testKtSpelRefToKt_KtSpelRefToKt() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/rename/ktSpelRefToKt/ktSpelRefToKt.test"); - doTest(fileName); - } - - @TestMetadata("ktSpelRefToKtAnnotated/ktSpelRefToKtAnnotated.test") - public void testKtSpelRefToKtAnnotated_KtSpelRefToKtAnnotated() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/rename/ktSpelRefToKtAnnotated/ktSpelRefToKtAnnotated.test"); - doTest(fileName); - } - - @TestMetadata("parameterWithXmlRefsBySpelRef/parameterWithXmlRefBySpelRef.test") - public void testParameterWithXmlRefsBySpelRef_ParameterWithXmlRefBySpelRef() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/rename/parameterWithXmlRefsBySpelRef/parameterWithXmlRefBySpelRef.test"); - doTest(fileName); - } - - @TestMetadata("primaryConstructorArgWithXmlRefs/primaryConstructorArgWithXmlRef.test") - public void testPrimaryConstructorArgWithXmlRefs_PrimaryConstructorArgWithXmlRef() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/rename/primaryConstructorArgWithXmlRefs/primaryConstructorArgWithXmlRef.test"); - doTest(fileName); - } - - @TestMetadata("primaryConstructorArgWithXmlRefsByRef1/primaryConstructorArgWithXmlRefByRef1.test") - public void testPrimaryConstructorArgWithXmlRefsByRef1_PrimaryConstructorArgWithXmlRefByRef1() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/rename/primaryConstructorArgWithXmlRefsByRef1/primaryConstructorArgWithXmlRefByRef1.test"); - doTest(fileName); - } - - @TestMetadata("primaryConstructorArgWithXmlRefsByRef2/primaryConstructorArgWithXmlRefByRef2.test") - public void testPrimaryConstructorArgWithXmlRefsByRef2_PrimaryConstructorArgWithXmlRefByRef2() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/rename/primaryConstructorArgWithXmlRefsByRef2/primaryConstructorArgWithXmlRefByRef2.test"); - doTest(fileName); - } - - @TestMetadata("propertyWithXmlRefs/propertyWithXmlRef.test") - public void testPropertyWithXmlRefs_PropertyWithXmlRef() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/rename/propertyWithXmlRefs/propertyWithXmlRef.test"); - doTest(fileName); - } - - @TestMetadata("propertyWithXmlRefsByRef/propertyWithXmlRefByRef.test") - public void testPropertyWithXmlRefsByRef_PropertyWithXmlRefByRef() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/rename/propertyWithXmlRefsByRef/propertyWithXmlRefByRef.test"); - doTest(fileName); - } - - @TestMetadata("propertyWithXmlRefsBySpelRef/propertyWithXmlRefBySpelRef.test") - public void testPropertyWithXmlRefsBySpelRef_PropertyWithXmlRefBySpelRef() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/rename/propertyWithXmlRefsBySpelRef/propertyWithXmlRefBySpelRef.test"); - doTest(fileName); - } - - @TestMetadata("setterFunWithXmlRefs/setterFunWithXmlRef.test") - public void testSetterFunWithXmlRefs_SetterFunWithXmlRef() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/rename/setterFunWithXmlRefs/setterFunWithXmlRef.test"); - doTest(fileName); - } - - @TestMetadata("setterFunWithXmlRefsByRef/setterFunWithXmlRefByRef.test") - public void testSetterFunWithXmlRefsByRef_SetterFunWithXmlRefByRef() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("ultimate/testData/spring/core/rename/setterFunWithXmlRefsByRef/setterFunWithXmlRefByRef.test"); - doTest(fileName); - } -} diff --git a/usage-statistics/build.gradle.kts.173 b/usage-statistics/build.gradle.kts.173 deleted file mode 100644 index c9081cdbd4d..00000000000 --- a/usage-statistics/build.gradle.kts.173 +++ /dev/null @@ -1,20 +0,0 @@ - -plugins { - kotlin("jvm") - id("jps-compatible") -} - -jvmTarget = "1.6" - -dependencies { - compile(intellijDep()) { - isTransitive = false - } -} - -sourceSets { - "main" { projectDefault() } - "test" {} -} - -ideaPlugin()