mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-10 08:31:29 +00:00
Cleanup 201 and as41 bunch files
This commit is contained in:
@@ -1,13 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.codegen
|
||||
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
|
||||
// This object should help compiling against different ASM versions from different bunch versions
|
||||
object VersionIndependentOpcodes {
|
||||
const val ACC_RECORD = 0
|
||||
}
|
||||
@@ -1,158 +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.codegen;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.codegen.inline.FileMapping;
|
||||
import org.jetbrains.kotlin.codegen.inline.SMAPBuilder;
|
||||
import org.jetbrains.kotlin.codegen.inline.SourceMapper;
|
||||
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
|
||||
import org.jetbrains.org.objectweb.asm.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.GENERATE_SMAP;
|
||||
|
||||
public abstract class AbstractClassBuilder implements ClassBuilder {
|
||||
protected static final MethodVisitor EMPTY_METHOD_VISITOR = new MethodVisitor(Opcodes.API_VERSION) {};
|
||||
protected static final FieldVisitor EMPTY_FIELD_VISITOR = new FieldVisitor(Opcodes.API_VERSION) {};
|
||||
|
||||
private String thisName;
|
||||
|
||||
private final JvmSerializationBindings serializationBindings = new JvmSerializationBindings();
|
||||
|
||||
private String sourceName;
|
||||
|
||||
private String debugInfo;
|
||||
|
||||
public static class Concrete extends AbstractClassBuilder {
|
||||
private final ClassVisitor v;
|
||||
|
||||
public Concrete(@NotNull ClassVisitor v) {
|
||||
this.v = v;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public ClassVisitor getVisitor() {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public FieldVisitor newField(
|
||||
@NotNull JvmDeclarationOrigin origin,
|
||||
int access,
|
||||
@NotNull String name,
|
||||
@NotNull String desc,
|
||||
@Nullable String signature,
|
||||
@Nullable Object value
|
||||
) {
|
||||
FieldVisitor visitor = getVisitor().visitField(access, name, desc, signature, value);
|
||||
if (visitor == null) {
|
||||
return EMPTY_FIELD_VISITOR;
|
||||
}
|
||||
return visitor;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public MethodVisitor newMethod(
|
||||
@NotNull JvmDeclarationOrigin origin,
|
||||
int access,
|
||||
@NotNull String name,
|
||||
@NotNull String desc,
|
||||
@Nullable String signature,
|
||||
@Nullable String[] exceptions
|
||||
) {
|
||||
MethodVisitor visitor = getVisitor().visitMethod(access, name, desc, signature, exceptions);
|
||||
if (visitor == null) {
|
||||
return EMPTY_METHOD_VISITOR;
|
||||
}
|
||||
return visitor;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public JvmSerializationBindings getSerializationBindings() {
|
||||
return serializationBindings;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public AnnotationVisitor newAnnotation(@NotNull String desc, boolean visible) {
|
||||
return getVisitor().visitAnnotation(desc, visible);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void done() {
|
||||
getVisitor().visitSource(sourceName, debugInfo);
|
||||
getVisitor().visitEnd();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void defineClass(
|
||||
@Nullable PsiElement origin,
|
||||
int version,
|
||||
int access,
|
||||
@NotNull String name,
|
||||
@Nullable String signature,
|
||||
@NotNull String superName,
|
||||
@NotNull String[] interfaces
|
||||
) {
|
||||
thisName = name;
|
||||
getVisitor().visit(version, access, name, signature, superName, interfaces);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSource(@NotNull String name, @Nullable String debug) {
|
||||
assert sourceName == null || sourceName.equals(name) : "inconsistent file name: " + sourceName + " vs " + name;
|
||||
sourceName = name;
|
||||
debugInfo = debug;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSMAP(@NotNull SourceMapper smap, boolean backwardsCompatibleSyntax) {
|
||||
if (!GENERATE_SMAP) return;
|
||||
|
||||
List<FileMapping> fileMappings = smap.getResultMappings();
|
||||
if (fileMappings.isEmpty()) return;
|
||||
|
||||
visitSource(fileMappings.get(0).getName(), SMAPBuilder.INSTANCE.build(fileMappings, backwardsCompatibleSyntax));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOuterClass(@NotNull String owner, @Nullable String name, @Nullable String desc) {
|
||||
getVisitor().visitOuterClass(owner, name, desc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInnerClass(@NotNull String name, @Nullable String outerName, @Nullable String innerName, int access) {
|
||||
getVisitor().visitInnerClass(name, outerName, innerName, access);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getThisName() {
|
||||
assert thisName != null : "This name isn't set";
|
||||
return thisName;
|
||||
}
|
||||
}
|
||||
@@ -1,79 +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.codegen;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.codegen.inline.SourceMapper;
|
||||
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
|
||||
import org.jetbrains.org.objectweb.asm.*;
|
||||
|
||||
public interface ClassBuilder {
|
||||
@NotNull
|
||||
FieldVisitor newField(
|
||||
@NotNull JvmDeclarationOrigin origin,
|
||||
int access,
|
||||
@NotNull String name,
|
||||
@NotNull String desc,
|
||||
@Nullable String signature,
|
||||
@Nullable Object value
|
||||
);
|
||||
|
||||
@NotNull
|
||||
MethodVisitor newMethod(
|
||||
@NotNull JvmDeclarationOrigin origin,
|
||||
int access,
|
||||
@NotNull String name,
|
||||
@NotNull String desc,
|
||||
@Nullable String signature,
|
||||
@Nullable String[] exceptions
|
||||
);
|
||||
|
||||
@NotNull
|
||||
JvmSerializationBindings getSerializationBindings();
|
||||
|
||||
@NotNull
|
||||
AnnotationVisitor newAnnotation(@NotNull String desc, boolean visible);
|
||||
|
||||
void done();
|
||||
|
||||
@NotNull
|
||||
ClassVisitor getVisitor();
|
||||
|
||||
void defineClass(
|
||||
@Nullable PsiElement origin,
|
||||
int version,
|
||||
int access,
|
||||
@NotNull String name,
|
||||
@Nullable String signature,
|
||||
@NotNull String superName,
|
||||
@NotNull String[] interfaces
|
||||
);
|
||||
|
||||
void visitSource(@NotNull String name, @Nullable String debug);
|
||||
|
||||
void visitSMAP(@NotNull SourceMapper smap, boolean backwardsCompatibleSyntax);
|
||||
|
||||
void visitOuterClass(@NotNull String owner, @Nullable String name, @Nullable String desc);
|
||||
|
||||
void visitInnerClass(@NotNull String name, @Nullable String outerName, @Nullable String innerName, int access);
|
||||
|
||||
@NotNull
|
||||
String getThisName();
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.codegen
|
||||
|
||||
@Suppress("UNUSED_PARAMETER", "unused")
|
||||
fun ClassBuilder.addRecordComponent(name: String, desc: String, signature: String?) {
|
||||
// newRecordComponent(name, desc, signature)
|
||||
}
|
||||
@@ -1,118 +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.codegen;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.codegen.inline.SourceMapper;
|
||||
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
|
||||
import org.jetbrains.org.objectweb.asm.*;
|
||||
|
||||
public abstract class DelegatingClassBuilder implements ClassBuilder {
|
||||
@NotNull
|
||||
protected abstract ClassBuilder getDelegate();
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FieldVisitor newField(
|
||||
@NotNull JvmDeclarationOrigin origin,
|
||||
int access,
|
||||
@NotNull String name,
|
||||
@NotNull String desc,
|
||||
@Nullable String signature,
|
||||
@Nullable Object value
|
||||
) {
|
||||
return getDelegate().newField(origin, access, name, desc, signature, value);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public MethodVisitor newMethod(
|
||||
@NotNull JvmDeclarationOrigin origin,
|
||||
int access,
|
||||
@NotNull String name,
|
||||
@NotNull String desc,
|
||||
@Nullable String signature,
|
||||
@Nullable String[] exceptions
|
||||
) {
|
||||
return getDelegate().newMethod(origin, access, name, desc, signature, exceptions);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JvmSerializationBindings getSerializationBindings() {
|
||||
return getDelegate().getSerializationBindings();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public AnnotationVisitor newAnnotation(@NotNull String desc, boolean visible) {
|
||||
return getDelegate().newAnnotation(desc, visible);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void done() {
|
||||
getDelegate().done();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ClassVisitor getVisitor() {
|
||||
return getDelegate().getVisitor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void defineClass(
|
||||
@Nullable PsiElement origin,
|
||||
int version,
|
||||
int access,
|
||||
@NotNull String name,
|
||||
@Nullable String signature,
|
||||
@NotNull String superName,
|
||||
@NotNull String[] interfaces
|
||||
) {
|
||||
getDelegate().defineClass(origin, version, access, name, signature, superName, interfaces);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSource(@NotNull String name, @Nullable String debug) {
|
||||
getDelegate().visitSource(name, debug);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSMAP(@NotNull SourceMapper smap, boolean backwardsCompatibleSyntax) {
|
||||
getDelegate().visitSMAP(smap, backwardsCompatibleSyntax);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOuterClass(@NotNull String owner, @Nullable String name, @Nullable String desc) {
|
||||
getDelegate().visitOuterClass(owner, name, desc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInnerClass(@NotNull String name, @Nullable String outerName, @Nullable String innerName, int access) {
|
||||
getDelegate().visitInnerClass(name, outerName, innerName, access);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getThisName() {
|
||||
return getDelegate().getThisName();
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.codegen.optimization.common
|
||||
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
|
||||
|
||||
typealias TypeAnnotatedFrames = Array<Frame<BasicValue>?>
|
||||
@@ -1,8 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.codegen.state
|
||||
|
||||
typealias JvmMethodExceptionTypes = Array<out String>?
|
||||
@@ -1,14 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.compiler
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.roots.LanguageLevelProjectExtension
|
||||
import com.intellij.pom.java.LanguageLevel
|
||||
|
||||
fun Project.setupHighestLanguageLevel() {
|
||||
// LanguageLevelProjectExtension.getInstance(this).languageLevel = LanguageLevel.JDK_15_PREVIEW
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.compiler
|
||||
|
||||
fun setupIdeaStandaloneExecution() {
|
||||
System.getProperties().setProperty("idea.plugins.compatible.build", "201.6668.13")
|
||||
System.getProperties().setProperty("project.structure.add.tools.jar.to.new.jdk", "false")
|
||||
System.getProperties().setProperty("psi.track.invalidation", "true")
|
||||
System.getProperties().setProperty("psi.incremental.reparse.depth.limit", "1000")
|
||||
System.getProperties().setProperty("ide.hide.excluded.files", "false")
|
||||
System.getProperties().setProperty("ast.loading.filter", "false")
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.classes
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.augment.PsiAugmentProvider
|
||||
|
||||
internal fun <Psi : PsiElement> collectAugments(element: PsiElement, type: Class<out Psi>): List<Psi> {
|
||||
return PsiAugmentProvider.collectAugments(element, type)
|
||||
}
|
||||
@@ -1,154 +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.load.java.structure.impl
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.PsiClass
|
||||
import com.intellij.psi.PsiTypeParameter
|
||||
import com.intellij.psi.search.SearchScope
|
||||
import org.jetbrains.kotlin.asJava.KtLightClassMarker
|
||||
import org.jetbrains.kotlin.asJava.isSyntheticValuesOrValueOfMethod
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.load.java.structure.*
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtPsiUtil
|
||||
|
||||
class JavaClassImpl(psiClass: PsiClass) : JavaClassifierImpl<PsiClass>(psiClass), VirtualFileBoundJavaClass, JavaAnnotationOwnerImpl, JavaModifierListOwnerImpl {
|
||||
init {
|
||||
assert(psiClass !is PsiTypeParameter) { "PsiTypeParameter should be wrapped in JavaTypeParameter, not JavaClass: use JavaClassifier.create()" }
|
||||
}
|
||||
|
||||
override val innerClassNames: Collection<Name>
|
||||
get() = psi.innerClasses.mapNotNull { it.name?.takeIf(Name::isValidIdentifier)?.let(Name::identifier) }
|
||||
|
||||
override fun findInnerClass(name: Name): JavaClass? {
|
||||
return psi.findInnerClassByName(name.asString(), false)?.let(::JavaClassImpl)
|
||||
}
|
||||
|
||||
override val fqName: FqName?
|
||||
get() {
|
||||
val qualifiedName = psi.qualifiedName
|
||||
return if (qualifiedName == null) null else FqName(qualifiedName)
|
||||
}
|
||||
|
||||
override val name: Name
|
||||
get() = KtPsiUtil.safeName(psi.name)
|
||||
|
||||
override val isInterface: Boolean
|
||||
get() = psi.isInterface
|
||||
|
||||
override val isAnnotationType: Boolean
|
||||
get() = psi.isAnnotationType
|
||||
|
||||
override val isEnum: Boolean
|
||||
get() = psi.isEnum
|
||||
|
||||
override val isRecord: Boolean
|
||||
get() = false
|
||||
|
||||
override val isSealed: Boolean
|
||||
get() = JavaElementUtil.isSealed(this)
|
||||
|
||||
override val permittedTypes: Collection<JavaClassifierType>
|
||||
get() = emptyList()
|
||||
|
||||
override val outerClass: JavaClassImpl?
|
||||
get() {
|
||||
val outer = psi.containingClass
|
||||
return if (outer == null) null else JavaClassImpl(outer)
|
||||
}
|
||||
|
||||
override val typeParameters: List<JavaTypeParameter>
|
||||
get() = typeParameters(psi.typeParameters)
|
||||
|
||||
override val supertypes: Collection<JavaClassifierType>
|
||||
get() = classifierTypes(psi.superTypes)
|
||||
|
||||
override val methods: Collection<JavaMethod>
|
||||
get() {
|
||||
assertNotLightClass()
|
||||
// We apply distinct here because PsiClass#getMethods() can return duplicate PSI methods, for example in Lombok (see KT-11778)
|
||||
// Return type seems to be null for example for the 'clone' Groovy method generated by @AutoClone (see EA-73795)
|
||||
return methods(
|
||||
psi.methods.filter { method ->
|
||||
!method.isConstructor && method.returnType != null && !(isEnum && isSyntheticValuesOrValueOfMethod(method))
|
||||
}
|
||||
).distinct()
|
||||
}
|
||||
|
||||
override val fields: Collection<JavaField>
|
||||
get() {
|
||||
assertNotLightClass()
|
||||
return fields(psi.fields.filter {
|
||||
// ex. Android plugin generates LightFields for resources started from '.' (.DS_Store file etc)
|
||||
Name.isValidIdentifier(it.name)
|
||||
})
|
||||
}
|
||||
|
||||
override val constructors: Collection<JavaConstructor>
|
||||
get() {
|
||||
assertNotLightClass()
|
||||
// See for example org.jetbrains.plugins.scala.lang.psi.light.ScFunctionWrapper,
|
||||
// which is present in getConstructors(), but its isConstructor() returns false
|
||||
return constructors(psi.constructors.filter { method -> method.isConstructor })
|
||||
}
|
||||
|
||||
override val recordComponents: Collection<JavaRecordComponent>
|
||||
get() {
|
||||
assertNotLightClass()
|
||||
|
||||
return emptyList<JavaRecordComponent>()
|
||||
}
|
||||
|
||||
override fun hasDefaultConstructor() = !isInterface && constructors.isEmpty()
|
||||
|
||||
override val isAbstract: Boolean
|
||||
get() = JavaElementUtil.isAbstract(this)
|
||||
|
||||
override val isStatic: Boolean
|
||||
get() = JavaElementUtil.isStatic(this)
|
||||
|
||||
override val isFinal: Boolean
|
||||
get() = JavaElementUtil.isFinal(this)
|
||||
|
||||
override val visibility: Visibility
|
||||
get() = JavaElementUtil.getVisibility(this)
|
||||
|
||||
override val lightClassOriginKind: LightClassOriginKind?
|
||||
get() = (psi as? KtLightClassMarker)?.originKind
|
||||
|
||||
override val virtualFile: VirtualFile?
|
||||
get() = psi.containingFile?.virtualFile
|
||||
|
||||
override fun isFromSourceCodeInScope(scope: SearchScope): Boolean = psi.containingFile.virtualFile in scope
|
||||
|
||||
override fun getAnnotationOwnerPsi() = psi.modifierList
|
||||
|
||||
private fun assertNotLightClass() {
|
||||
val psiClass = psi
|
||||
if (psiClass !is KtLightClassMarker) return
|
||||
|
||||
val message = "Querying members of JavaClass created for $psiClass of type ${psiClass::class.java} defined in file ${psiClass.containingFile?.virtualFile?.canonicalPath}"
|
||||
LOGGER.error(message)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val LOGGER = Logger.getInstance(JavaClassImpl::class.java)
|
||||
}
|
||||
}
|
||||
@@ -1,113 +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.load.java.structure.impl;
|
||||
|
||||
import com.intellij.codeInsight.ExternalAnnotationsManager;
|
||||
import com.intellij.psi.PsiAnnotation;
|
||||
import com.intellij.psi.PsiAnnotationOwner;
|
||||
import com.intellij.psi.PsiModifier;
|
||||
import com.intellij.psi.PsiModifierListOwner;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities;
|
||||
import org.jetbrains.kotlin.descriptors.Visibility;
|
||||
import org.jetbrains.kotlin.descriptors.java.JavaVisibilities;
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.jetbrains.kotlin.load.java.structure.impl.JavaElementCollectionFromPsiArrayUtil.annotations;
|
||||
import static org.jetbrains.kotlin.load.java.structure.impl.JavaElementCollectionFromPsiArrayUtil.nullabilityAnnotations;
|
||||
|
||||
/* package */ class JavaElementUtil {
|
||||
private JavaElementUtil() {
|
||||
}
|
||||
|
||||
public static boolean isAbstract(@NotNull JavaModifierListOwnerImpl owner) {
|
||||
return owner.getPsi().hasModifierProperty(PsiModifier.ABSTRACT);
|
||||
}
|
||||
|
||||
public static boolean isStatic(@NotNull JavaModifierListOwnerImpl owner) {
|
||||
return owner.getPsi().hasModifierProperty(PsiModifier.STATIC);
|
||||
}
|
||||
|
||||
public static boolean isFinal(@NotNull JavaModifierListOwnerImpl owner) {
|
||||
return owner.getPsi().hasModifierProperty(PsiModifier.FINAL);
|
||||
}
|
||||
|
||||
public static boolean isSealed(@NotNull JavaModifierListOwnerImpl owner) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Visibility getVisibility(@NotNull JavaModifierListOwnerImpl owner) {
|
||||
PsiModifierListOwner psiOwner = owner.getPsi();
|
||||
if (psiOwner.hasModifierProperty(PsiModifier.PUBLIC)) {
|
||||
return Visibilities.Public.INSTANCE;
|
||||
}
|
||||
if (psiOwner.hasModifierProperty(PsiModifier.PRIVATE)) {
|
||||
return Visibilities.Private.INSTANCE;
|
||||
}
|
||||
if (psiOwner.hasModifierProperty(PsiModifier.PROTECTED)) {
|
||||
return owner.isStatic() ? JavaVisibilities.ProtectedStaticVisibility.INSTANCE : JavaVisibilities.ProtectedAndPackage.INSTANCE;
|
||||
}
|
||||
return JavaVisibilities.PackageVisibility.INSTANCE;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Collection<JavaAnnotation> getAnnotations(@NotNull JavaAnnotationOwnerImpl owner) {
|
||||
PsiAnnotationOwner annotationOwnerPsi = owner.getAnnotationOwnerPsi();
|
||||
if (annotationOwnerPsi != null) {
|
||||
return annotations(annotationOwnerPsi.getAnnotations());
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiAnnotation[] getExternalAnnotations(@NotNull JavaModifierListOwnerImpl modifierListOwner) {
|
||||
PsiModifierListOwner psiModifierListOwner = modifierListOwner.getPsi();
|
||||
ExternalAnnotationsManager externalAnnotationManager = ExternalAnnotationsManager
|
||||
.getInstance(psiModifierListOwner.getProject());
|
||||
return externalAnnotationManager.findExternalAnnotations(psiModifierListOwner);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
static <T extends JavaAnnotationOwnerImpl & JavaModifierListOwnerImpl>
|
||||
Collection<JavaAnnotation> getRegularAndExternalAnnotations(@NotNull T owner) {
|
||||
PsiAnnotation[] externalAnnotations = getExternalAnnotations(owner);
|
||||
if (externalAnnotations == null) {
|
||||
return getAnnotations(owner);
|
||||
}
|
||||
Collection<JavaAnnotation> annotations = new ArrayList<>(getAnnotations(owner));
|
||||
annotations.addAll(nullabilityAnnotations(externalAnnotations));
|
||||
return annotations;
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
public static JavaAnnotation findAnnotation(@NotNull JavaAnnotationOwnerImpl owner, @NotNull FqName fqName) {
|
||||
PsiAnnotationOwner annotationOwnerPsi = owner.getAnnotationOwnerPsi();
|
||||
if (annotationOwnerPsi != null) {
|
||||
PsiAnnotation psiAnnotation = annotationOwnerPsi.findAnnotation(fqName.asString());
|
||||
return psiAnnotation == null ? null : new JavaAnnotationImpl(psiAnnotation);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,247 +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.load.java.structure.impl.classFiles
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.search.SearchScope
|
||||
import gnu.trove.THashMap
|
||||
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||
import org.jetbrains.kotlin.load.java.structure.*
|
||||
import org.jetbrains.kotlin.load.java.structure.impl.VirtualFileBoundJavaClass
|
||||
import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaAnnotation.Companion.computeTypeParameterBound
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.utils.SmartList
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import org.jetbrains.org.objectweb.asm.*
|
||||
import java.text.CharacterIterator
|
||||
import java.text.StringCharacterIterator
|
||||
|
||||
class BinaryJavaClass(
|
||||
override val virtualFile: VirtualFile,
|
||||
override val fqName: FqName,
|
||||
internal val context: ClassifierResolutionContext,
|
||||
private val signatureParser: BinaryClassSignatureParser,
|
||||
override var access: Int = 0,
|
||||
override val outerClass: JavaClass?,
|
||||
classContent: ByteArray? = null
|
||||
) : ClassVisitor(ASM_API_VERSION_FOR_CLASS_READING), VirtualFileBoundJavaClass, BinaryJavaModifierListOwner, MutableJavaAnnotationOwner {
|
||||
override val annotations: MutableCollection<JavaAnnotation> = SmartList()
|
||||
|
||||
override lateinit var typeParameters: List<JavaTypeParameter>
|
||||
override lateinit var supertypes: List<JavaClassifierType>
|
||||
|
||||
override val methods = arrayListOf<JavaMethod>()
|
||||
override val fields = arrayListOf<JavaField>()
|
||||
override val constructors = arrayListOf<JavaConstructor>()
|
||||
override val recordComponents = arrayListOf<JavaRecordComponent>()
|
||||
|
||||
override fun hasDefaultConstructor() = false // never: all constructors explicit in bytecode
|
||||
|
||||
private lateinit var myInternalName: String
|
||||
|
||||
// In accordance with JVMS, super class always comes before the interface list
|
||||
private val superclass: JavaClassifierType? get() = supertypes.firstOrNull()
|
||||
private val implementedInterfaces: List<JavaClassifierType> get() = supertypes.drop(1)
|
||||
|
||||
override val annotationsByFqName by buildLazyValueForMap()
|
||||
|
||||
// Short name of a nested class of this class -> access flags as seen in the InnerClasses attribute value.
|
||||
// Note that it doesn't include classes mentioned in other InnerClasses attribute values (those which are not nested in this class).
|
||||
private val ownInnerClassNameToAccess: MutableMap<Name, Int> = THashMap()
|
||||
|
||||
override val innerClassNames get() = ownInnerClassNameToAccess.keys
|
||||
|
||||
override val name: Name
|
||||
get() = fqName.shortName()
|
||||
|
||||
override val isInterface get() = isSet(Opcodes.ACC_INTERFACE)
|
||||
override val isAnnotationType get() = isSet(Opcodes.ACC_ANNOTATION)
|
||||
override val isEnum get() = isSet(Opcodes.ACC_ENUM)
|
||||
|
||||
override val isRecord get() = false
|
||||
|
||||
override val lightClassOriginKind: LightClassOriginKind? get() = null
|
||||
|
||||
override val isSealed: Boolean get() = permittedTypes.isNotEmpty()
|
||||
override val permittedTypes = arrayListOf<JavaClassifierType>()
|
||||
|
||||
override fun isFromSourceCodeInScope(scope: SearchScope): Boolean = false
|
||||
|
||||
override fun visitTypeAnnotation(typeRef: Int, typePath: TypePath?, descriptor: String?, visible: Boolean): AnnotationVisitor? {
|
||||
if (descriptor == null)
|
||||
return null
|
||||
|
||||
fun getTargetType(baseType: JavaType) =
|
||||
if (typePath != null) BinaryJavaAnnotation.computeTargetType(baseType, typePath) else baseType
|
||||
|
||||
val typeReference = TypeReference(typeRef)
|
||||
|
||||
val annotationOwner = when (typeReference.sort) {
|
||||
TypeReference.CLASS_EXTENDS ->
|
||||
getTargetType(if (typeReference.superTypeIndex == -1) superclass!! else implementedInterfaces[typeReference.superTypeIndex])
|
||||
TypeReference.CLASS_TYPE_PARAMETER -> typeParameters[typeReference.typeParameterIndex]
|
||||
TypeReference.CLASS_TYPE_PARAMETER_BOUND -> getTargetType(computeTypeParameterBound(typeParameters, typeReference))
|
||||
else -> return null
|
||||
}
|
||||
|
||||
if (annotationOwner !is MutableJavaAnnotationOwner) return null
|
||||
|
||||
return BinaryJavaAnnotation.addAnnotation(annotationOwner, descriptor, context, signatureParser, isFreshlySupportedAnnotation = true)
|
||||
}
|
||||
|
||||
override fun visitEnd() {
|
||||
methods.trimToSize()
|
||||
fields.trimToSize()
|
||||
constructors.trimToSize()
|
||||
}
|
||||
|
||||
init {
|
||||
try {
|
||||
ClassReader(classContent ?: virtualFile.contentsToByteArray()).accept(
|
||||
this,
|
||||
ClassReader.SKIP_CODE or ClassReader.SKIP_FRAMES
|
||||
)
|
||||
} catch (e: Throwable) {
|
||||
throw IllegalStateException("Could not read class: $virtualFile", e)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array<out String>?): MethodVisitor? {
|
||||
if (access.isSet(Opcodes.ACC_SYNTHETIC) || access.isSet(Opcodes.ACC_BRIDGE) || name == "<clinit>") return null
|
||||
|
||||
// skip semi-synthetic enum methods
|
||||
if (isEnum) {
|
||||
if (name == "values" && desc.startsWith("()")) return null
|
||||
if (name == "valueOf" && desc.startsWith("(Ljava/lang/String;)")) return null
|
||||
}
|
||||
|
||||
val (member, visitor) = BinaryJavaMethodBase.create(name, access, desc, signature, this, context.copyForMember(), signatureParser)
|
||||
|
||||
when (member) {
|
||||
is JavaMethod -> methods.add(member)
|
||||
is JavaConstructor -> constructors.add(member)
|
||||
else -> error("Unexpected member: ${member.javaClass}")
|
||||
}
|
||||
|
||||
return visitor
|
||||
}
|
||||
|
||||
override fun visitInnerClass(name: String, outerName: String?, innerName: String?, access: Int) {
|
||||
if (access.isSet(Opcodes.ACC_SYNTHETIC)) return
|
||||
if (innerName == null || outerName == null) return
|
||||
|
||||
// Do not read InnerClasses attribute values where full name != outer + $ + inner; treat those classes as top level instead.
|
||||
// This is possible for example for Groovy-generated $Trait$FieldHelper classes.
|
||||
if (name == "$outerName$$innerName") {
|
||||
context.addInnerClass(name, outerName, innerName)
|
||||
|
||||
if (myInternalName == outerName) {
|
||||
ownInnerClassNameToAccess[context.mapInternalNameToClassId(name).shortClassName] = access
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun visit(
|
||||
version: Int,
|
||||
access: Int,
|
||||
name: String,
|
||||
signature: String?,
|
||||
superName: String?,
|
||||
interfaces: Array<out String>?
|
||||
) {
|
||||
this.access = this.access or access
|
||||
this.myInternalName = name
|
||||
|
||||
if (signature != null) {
|
||||
parseClassSignature(signature)
|
||||
} else {
|
||||
this.typeParameters = emptyList()
|
||||
this.supertypes = mutableListOf<JavaClassifierType>().apply {
|
||||
addIfNotNull(superName?.convertInternalNameToClassifierType())
|
||||
interfaces?.forEach {
|
||||
addIfNotNull(it.convertInternalNameToClassifierType())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun parseClassSignature(signature: String) {
|
||||
val iterator = StringCharacterIterator(signature)
|
||||
this.typeParameters =
|
||||
signatureParser
|
||||
.parseTypeParametersDeclaration(iterator, context)
|
||||
.also(context::addTypeParameters)
|
||||
|
||||
val supertypes = SmartList<JavaClassifierType>()
|
||||
supertypes.addIfNotNull(signatureParser.parseClassifierRefSignature(iterator, context))
|
||||
while (iterator.current() != CharacterIterator.DONE) {
|
||||
supertypes.addIfNotNull(signatureParser.parseClassifierRefSignature(iterator, context))
|
||||
}
|
||||
this.supertypes = supertypes
|
||||
}
|
||||
|
||||
private fun String.convertInternalNameToClassifierType(): JavaClassifierType =
|
||||
PlainJavaClassifierType({ context.resolveByInternalName(this) }, emptyList())
|
||||
|
||||
override fun visitField(access: Int, name: String, desc: String, signature: String?, value: Any?): FieldVisitor? {
|
||||
if (access.isSet(Opcodes.ACC_SYNTHETIC)) return null
|
||||
|
||||
val type = signatureParser.parseTypeString(StringCharacterIterator(signature ?: desc), context)
|
||||
val processedValue = processValue(value, type)
|
||||
val filed = BinaryJavaField(Name.identifier(name), access, this, access.isSet(Opcodes.ACC_ENUM), type, processedValue)
|
||||
|
||||
fields.add(filed)
|
||||
|
||||
return AnnotationsCollectorFieldVisitor(filed, context, signatureParser)
|
||||
}
|
||||
|
||||
/**
|
||||
* All the int-like values (including Char/Boolean) come in visitor as Integer instances
|
||||
*/
|
||||
private fun processValue(value: Any?, fieldType: JavaType): Any? {
|
||||
if (fieldType !is JavaPrimitiveType || fieldType.type == null || value !is Int) return value
|
||||
|
||||
return when (fieldType.type) {
|
||||
PrimitiveType.BOOLEAN -> {
|
||||
when (value) {
|
||||
0 -> false
|
||||
1 -> true
|
||||
else -> value
|
||||
}
|
||||
}
|
||||
PrimitiveType.CHAR -> value.toChar()
|
||||
else -> value
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitAnnotation(desc: String, visible: Boolean) =
|
||||
BinaryJavaAnnotation.addAnnotation(this, desc, context, signatureParser)
|
||||
|
||||
override fun findInnerClass(name: Name): JavaClass? = findInnerClass(name, classFileContent = null)
|
||||
|
||||
fun findInnerClass(name: Name, classFileContent: ByteArray?): JavaClass? {
|
||||
val access = ownInnerClassNameToAccess[name] ?: return null
|
||||
|
||||
return virtualFile.parent.findChild("${virtualFile.nameWithoutExtension}$$name.class")?.let {
|
||||
BinaryJavaClass(
|
||||
it, fqName.child(name), context.copyForMember(), signatureParser, access, this,
|
||||
classFileContent
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,346 +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.ide.util.AppPropertiesComponentImpl;
|
||||
import com.intellij.ide.util.PropertiesComponent;
|
||||
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.fileTypes.FileTypeRegistry;
|
||||
import com.intellij.openapi.options.SchemeManagerFactory;
|
||||
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.util.CachedValuesManager;
|
||||
import com.intellij.testFramework.LightVirtualFile;
|
||||
import com.intellij.testFramework.MockSchemeManagerFactory;
|
||||
import com.intellij.testFramework.TestDataFile;
|
||||
import com.intellij.util.CachedValuesManagerImpl;
|
||||
import com.intellij.util.Function;
|
||||
import junit.framework.TestCase;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType;
|
||||
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<Document> 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();
|
||||
final MockEditorFactory editorFactory = new MockEditorFactory();
|
||||
MockFileTypeManager mockFileTypeManager = new MockFileTypeManager(KotlinFileType.INSTANCE);
|
||||
MockFileDocumentManagerImpl mockFileDocumentManager = new MockFileDocumentManagerImpl(new Function<CharSequence, Document>() {
|
||||
@Override
|
||||
public Document fun(CharSequence charSequence) {
|
||||
return editorFactory.createDocument(charSequence);
|
||||
}
|
||||
}, HARD_REF_TO_DOCUMENT_KEY);
|
||||
|
||||
registerApplicationService(PropertiesComponent.class, new AppPropertiesComponentImpl());
|
||||
registerApplicationService(PsiBuilderFactory.class, new PsiBuilderFactoryImpl());
|
||||
registerApplicationService(DefaultASTFactory.class, new CoreASTFactory());
|
||||
registerApplicationService(SchemeManagerFactory.class, new MockSchemeManagerFactory());
|
||||
registerApplicationService(FileTypeManager.class, mockFileTypeManager);
|
||||
registerApplicationService(FileDocumentManager.class, mockFileDocumentManager);
|
||||
|
||||
registerApplicationService(ProgressManager.class, new CoreProgressManager());
|
||||
|
||||
registerComponentInstance(appContainer, FileTypeRegistry.class, mockFileTypeManager);
|
||||
registerComponentInstance(appContainer, FileTypeManager.class, mockFileTypeManager);
|
||||
registerComponentInstance(appContainer, EditorFactory.class, editorFactory);
|
||||
registerComponentInstance(appContainer, FileDocumentManager.class, mockFileDocumentManager);
|
||||
registerComponentInstance(appContainer, PsiDocumentManager.class, new MockPsiDocumentManager());
|
||||
|
||||
|
||||
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 <T> void addExplicitExtension(final LanguageExtension<T> 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 <T> void registerExtensionPoint(final ExtensionPointName<T> extensionPointName, Class<T> aClass) {
|
||||
super.registerExtensionPoint(extensionPointName, aClass);
|
||||
Disposer.register(myProject, new Disposable() {
|
||||
@Override
|
||||
public void dispose() {
|
||||
Extensions.getRootArea().unregisterExtensionPoint(extensionPointName.getName());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected <T> void registerApplicationService(final Class<T> 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<Language> 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()).reparseRange(
|
||||
file, file.getNode(), TextRange.allOf(fileText), fileText, new EmptyProgressIndicator(), fileText);
|
||||
diffLog.performActualPsiChange(file);
|
||||
|
||||
TestCase.assertEquals(psiToStringDefault, DebugUtil.psiToString(file, false, false));
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,17 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.utils
|
||||
|
||||
import com.intellij.util.containers.ConcurrentMultiMap
|
||||
import com.intellij.util.containers.Interner
|
||||
import com.intellij.util.containers.MultiMap
|
||||
import com.intellij.util.containers.StringInterner
|
||||
|
||||
fun createStringInterner(): Interner<String> =
|
||||
StringInterner()
|
||||
|
||||
fun <K, V> createConcurrentMultiMap(): MultiMap<K, V> =
|
||||
ConcurrentMultiMap<K, V>()
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,19 +0,0 @@
|
||||
versions.intellijSdk=201.7223.91
|
||||
versions.idea.NodeJS=193.6494.7
|
||||
versions.jar.asm-all=7.0.1
|
||||
versions.jar.guava=28.2-jre
|
||||
versions.jar.groovy-all=2.4.17
|
||||
versions.jar.lombok-ast=0.2.3
|
||||
versions.jar.swingx-core=1.6.2-2
|
||||
versions.jar.kxml2=2.3.0
|
||||
versions.jar.streamex=0.7.2
|
||||
versions.jar.gson=2.8.6
|
||||
versions.jar.oro=2.0.8
|
||||
versions.jar.picocontainer=1.2
|
||||
versions.jar.serviceMessages=2019.1.4
|
||||
versions.jar.lz4-java=1.7.1
|
||||
ignore.jar.snappy-in-java=true
|
||||
versions.gradle-api=4.5.1
|
||||
versions.shadow=6.1.0
|
||||
versions.junit-bom=5.7.0
|
||||
versions.org.junit.platform=1.7.0
|
||||
@@ -1,23 +0,0 @@
|
||||
versions.intellijSdk=201.7223.91
|
||||
versions.idea.NodeJS=193.6494.7
|
||||
versions.androidStudioRelease=4.1.0.18
|
||||
versions.androidStudioBuild=201.6823847
|
||||
versions.jar.asm-all=7.0.1
|
||||
versions.jar.guava=28.2-jre
|
||||
versions.jar.groovy-all=2.4.17
|
||||
versions.jar.lombok-ast=0.2.3
|
||||
versions.jar.swingx-core=1.6.2-2
|
||||
versions.jar.kxml2=2.3.0
|
||||
versions.jar.streamex=0.7.2
|
||||
versions.jar.gson=2.8.6
|
||||
versions.jar.oro=2.0.8
|
||||
versions.jar.picocontainer=1.2
|
||||
versions.jar.serviceMessages=2019.1.4
|
||||
versions.jar.lz4-java=1.7.1
|
||||
ignore.jar.snappy-in-java=true
|
||||
versions.gradle-api=4.5.1
|
||||
versions.shadow=6.1.0
|
||||
ignore.jar.common=true
|
||||
ignore.jar.lombok-ast=true
|
||||
versions.junit-bom=5.7.0
|
||||
versions.org.junit.platform=1.7.0
|
||||
@@ -1,13 +0,0 @@
|
||||
import org.jetbrains.annotations.PropertyKey
|
||||
|
||||
fun message(@PropertyKey(resourceBundle = "PropertyKeysEmptyString") key: String) = key
|
||||
|
||||
fun test() {
|
||||
message("<caret>")
|
||||
}
|
||||
|
||||
// EXIST: { lookupString: "foo.bar", itemText: "foo.bar", tailText: "1", typeText: "PropertyKeysEmptyString" }
|
||||
// EXIST: { lookupString: "bar.baz", itemText: "bar.baz", tailText: "2", typeText: "PropertyKeysEmptyString" }
|
||||
// EXIST: { lookupString: "foo.bar.baz", itemText: "foo.bar.baz", tailText: "3", typeText: "PropertyKeysEmptyString" }
|
||||
// EXIST: { lookupString: "foo.test", itemText: "foo.test", tailText: "4", typeText: "PropertyKeysEmptyString" }
|
||||
// NOTHING_ELSE
|
||||
@@ -1,13 +0,0 @@
|
||||
import org.jetbrains.annotations.PropertyKey
|
||||
|
||||
fun message(@PropertyKey(resourceBundle = "PropertyKeysNoPrefix") key: String) = key
|
||||
|
||||
fun test() {
|
||||
message("<caret>foo")
|
||||
}
|
||||
|
||||
// EXIST: { lookupString: "foo.bar", itemText: "foo.bar", tailText: "1", typeText: "PropertyKeysNoPrefix" }
|
||||
// EXIST: { lookupString: "bar.baz", itemText: "bar.baz", tailText: "2", typeText: "PropertyKeysNoPrefix" }
|
||||
// EXIST: { lookupString: "foo.bar.baz", itemText: "foo.bar.baz", tailText: "3", typeText: "PropertyKeysNoPrefix" }
|
||||
// EXIST: { lookupString: "foo.test", itemText: "foo.test", tailText: "4", typeText: "PropertyKeysNoPrefix" }
|
||||
// NOTHING_ELSE
|
||||
@@ -1,12 +0,0 @@
|
||||
import org.jetbrains.annotations.PropertyKey
|
||||
|
||||
fun message(@PropertyKey(resourceBundle = "PropertyKeysWithPrefix") key: String) = key
|
||||
|
||||
fun test() {
|
||||
message("foo.<caret>")
|
||||
}
|
||||
|
||||
// EXIST: { lookupString: "foo.bar", itemText: "foo.bar", tailText: "1", typeText: "PropertyKeysWithPrefix" }
|
||||
// EXIST: { lookupString: "foo.bar.baz", itemText: "foo.bar.baz", tailText: "3", typeText: "PropertyKeysWithPrefix" }
|
||||
// EXIST: { lookupString: "foo.test", itemText: "foo.test", tailText: "4", typeText: "PropertyKeysWithPrefix" }
|
||||
// NOTHING_ELSE
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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
|
||||
|
||||
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.fileEditor.FileEditor
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.idea.util.application.getServiceSafe
|
||||
|
||||
class DaemonCodeAnalyzerStatusService(project: Project) : Disposable {
|
||||
companion object {
|
||||
fun getInstance(project: Project): DaemonCodeAnalyzerStatusService = project.getServiceSafe()
|
||||
}
|
||||
|
||||
@Volatile
|
||||
var daemonRunning: Boolean = false
|
||||
private set
|
||||
|
||||
init {
|
||||
val messageBusConnection = project.messageBus.connect(this)
|
||||
messageBusConnection.subscribe(DaemonCodeAnalyzer.DAEMON_EVENT_TOPIC, object : DaemonCodeAnalyzer.DaemonListener {
|
||||
override fun daemonStarting(fileEditors: MutableCollection<FileEditor>) {
|
||||
daemonRunning = true
|
||||
}
|
||||
|
||||
override fun daemonFinished(fileEditors: MutableCollection<FileEditor>) {
|
||||
daemonRunning = false
|
||||
}
|
||||
|
||||
override fun daemonCancelEventOccurred(reason: String) {
|
||||
daemonRunning = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun dispose() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.statistics
|
||||
|
||||
open class KotlinFUSLogger {
|
||||
companion object {
|
||||
fun log(group: FUSEventGroups, event: String) {
|
||||
// Not whitelisted for AS
|
||||
}
|
||||
|
||||
fun log(group: FUSEventGroups, event: String, eventData: Map<String, String>) {
|
||||
// Not whitelisted for AS
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
class ProjectConfigurationCollector {
|
||||
// Not whitelisted
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.actions
|
||||
|
||||
import com.intellij.codeInsight.intention.IntentionAction
|
||||
import com.intellij.ide.actions.RevealFileAction
|
||||
import com.intellij.openapi.actionSystem.AnAction
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.DumbAware
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.ui.MessageType
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory
|
||||
import com.intellij.openapi.util.SystemInfo
|
||||
import com.intellij.openapi.wm.WindowManager
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.ui.BrowserHyperlinkListener
|
||||
import org.jetbrains.kotlin.idea.KotlinIdeaGradleBundle
|
||||
import java.io.File
|
||||
|
||||
class ShowKotlinGradleDslLogs : IntentionAction, AnAction(), DumbAware {
|
||||
override fun invoke(project: Project, editor: Editor?, file: PsiFile?) {
|
||||
openLogsDirIfPresent(project)
|
||||
}
|
||||
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
val project = e.project ?: return
|
||||
openLogsDirIfPresent(project)
|
||||
}
|
||||
|
||||
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile?) = RevealFileAction.isSupported()
|
||||
|
||||
override fun update(e: AnActionEvent) {
|
||||
val presentation = e.presentation
|
||||
presentation.isEnabledAndVisible = e.project != null && RevealFileAction.isSupported()
|
||||
presentation.text = NAME
|
||||
}
|
||||
|
||||
private fun openLogsDirIfPresent(project: Project) {
|
||||
val logsDir = findLogsDir()
|
||||
if (logsDir != null) {
|
||||
RevealFileAction.openDirectory(logsDir)
|
||||
} else {
|
||||
val parent = WindowManager.getInstance().getStatusBar(project)?.component
|
||||
?: WindowManager.getInstance().findVisibleFrame().rootPane
|
||||
JBPopupFactory.getInstance()
|
||||
.createHtmlTextBalloonBuilder(
|
||||
KotlinIdeaGradleBundle.message(
|
||||
"text.gradle.dsl.logs.cannot.be.found.automatically.see.how.to.find.logs",
|
||||
gradleTroubleshootingLink
|
||||
),
|
||||
MessageType.ERROR,
|
||||
BrowserHyperlinkListener.INSTANCE
|
||||
)
|
||||
.setFadeoutTime(5000)
|
||||
.createBalloon()
|
||||
.showInCenterOf(parent)
|
||||
}
|
||||
}
|
||||
|
||||
/** The way how to find Gradle logs is described here
|
||||
* @see org.jetbrains.kotlin.idea.actions.ShowKotlinGradleDslLogs.gradleTroubleshootingLink
|
||||
*/
|
||||
private fun findLogsDir(): File? {
|
||||
val userHome = System.getProperty("user.home")
|
||||
return when {
|
||||
SystemInfo.isMac -> File("$userHome/Library/Logs/gradle-kotlin-dsl")
|
||||
SystemInfo.isLinux -> File("$userHome/.gradle-kotlin-dsl/logs")
|
||||
SystemInfo.isWindows -> File("$userHome/AppData/Local/gradle-kotlin-dsl/log")
|
||||
else -> null
|
||||
}.takeIf { it?.exists() == true }
|
||||
}
|
||||
|
||||
override fun startInWriteAction() = false
|
||||
|
||||
override fun getText() = NAME
|
||||
|
||||
override fun getFamilyName() = NAME
|
||||
|
||||
companion object {
|
||||
private const val gradleTroubleshootingLink = "https://docs.gradle.org/current/userguide/kotlin_dsl.html#troubleshooting"
|
||||
|
||||
val NAME = KotlinIdeaGradleBundle.message("action.text.show.kotlin.gradle.dsl.logs.in", RevealFileAction.getFileManagerName())
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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
|
||||
|
||||
fun KaptImportingTest.isAndroidStudio() = true
|
||||
@@ -1,8 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.codeInsight.gradle
|
||||
|
||||
fun isGradleInspectionTestApplicable() = false
|
||||
@@ -16,7 +16,6 @@ import org.jetbrains.kotlin.tools.projectWizard.plugins.buildSystem.isGradle
|
||||
import org.jetbrains.plugins.gradle.service.project.open.linkAndRefreshGradleProject
|
||||
import java.nio.file.Path
|
||||
|
||||
// FIX ME WHEN BUNCH 201 REMOVED
|
||||
class IdeaGradleWizardService(private val project: Project) : ProjectImportingWizardService,
|
||||
IdeaWizardService {
|
||||
override fun isSuitableFor(buildSystemType: BuildSystemType): Boolean =
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.tools.projectWizard.wizard.service
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import java.nio.file.Path
|
||||
|
||||
class MavenProjectImporter(private val project: Project) {
|
||||
fun importProject(path: Path) {
|
||||
// AS does not support Maven
|
||||
}
|
||||
}
|
||||
@@ -95,7 +95,6 @@ abstract class KotlinLightCodeInsightFixtureTestCase : KotlinLightCodeInsightFix
|
||||
}
|
||||
|
||||
|
||||
runPostStartupActivitiesOnce(project)
|
||||
VfsRootAccess.allowRootAccess(project, KtTestUtil.getHomeDirectory())
|
||||
|
||||
EditorTracker.getInstance(project)
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.test;
|
||||
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.testFramework.TempFiles;
|
||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||
import org.jetbrains.kotlin.test.WithMutedInDatabaseRunTest;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Collection;
|
||||
|
||||
@WithMutedInDatabaseRunTest
|
||||
public abstract class KotlinLightCodeInsightFixtureTestCaseBase extends LightCodeInsightFixtureTestCase {
|
||||
@NotNull
|
||||
@Override
|
||||
public Project getProject() {
|
||||
return super.getProject();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Editor getEditor() {
|
||||
return super.getEditor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiFile getFile() {
|
||||
return super.getFile();
|
||||
}
|
||||
|
||||
protected final Collection<File> myFilesToDelete = new THashSet<>();
|
||||
private final TempFiles myTempFiles = new TempFiles(myFilesToDelete);
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
myTempFiles.deleteAll();
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public VirtualFile createTempFile(
|
||||
@NonNls @NotNull String ext,
|
||||
@Nullable byte[] bom,
|
||||
@NonNls @NotNull String content,
|
||||
@NotNull Charset charset
|
||||
) throws IOException {
|
||||
File temp = FileUtil.createTempFile("copy", "." + ext);
|
||||
setContentOnDisk(temp, bom, content, charset);
|
||||
|
||||
myFilesToDelete.add(temp);
|
||||
final VirtualFile file = getVirtualFile(temp);
|
||||
assert file != null : temp;
|
||||
return file;
|
||||
}
|
||||
|
||||
public static void setContentOnDisk(@NotNull File file, @Nullable byte[] bom, @NotNull String content, @NotNull Charset charset)
|
||||
throws IOException {
|
||||
FileOutputStream stream = new FileOutputStream(file);
|
||||
if (bom != null) {
|
||||
stream.write(bom);
|
||||
}
|
||||
try (OutputStreamWriter writer = new OutputStreamWriter(stream, charset)) {
|
||||
writer.write(content);
|
||||
}
|
||||
}
|
||||
|
||||
protected static VirtualFile getVirtualFile(@NotNull File file) {
|
||||
return LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void runTest() throws Throwable {
|
||||
//noinspection Convert2MethodRef
|
||||
KotlinTestUtils.runTestWithThrowable(this, () -> super.runTest());
|
||||
}
|
||||
|
||||
protected boolean isFirPlugin() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,6 @@ abstract class KotlinLightPlatformCodeInsightFixtureTestCase : LightPlatformCode
|
||||
override fun setUp() {
|
||||
super.setUp()
|
||||
enableKotlinOfficialCodeStyle(project)
|
||||
runPostStartupActivitiesOnce(project)
|
||||
VfsRootAccess.allowRootAccess(KtTestUtil.getHomeDirectory())
|
||||
if (!isFirPlugin()) {
|
||||
invalidateLibraryCache(project)
|
||||
|
||||
@@ -1,137 +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.test;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.projectRoots.JavaSdk;
|
||||
import com.intellij.openapi.projectRoots.ProjectJdkTable;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.projectRoots.impl.JavaSdkImpl;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess;
|
||||
import kotlin.jvm.functions.Function0;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
import org.jetbrains.kotlin.idea.util.IjPlatformUtil;
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||
import org.jetbrains.kotlin.test.TestJdkKind;
|
||||
import org.jetbrains.kotlin.test.util.KtTestUtil;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class PluginTestCaseBase {
|
||||
public static final String TEST_DATA_DIR = "idea/testData";
|
||||
public static final String TEST_DATA_PROJECT_RELATIVE = "/" + TEST_DATA_DIR;
|
||||
|
||||
private PluginTestCaseBase() {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getTestDataPathBase() {
|
||||
return KtTestUtil.getHomeDirectory() + TEST_DATA_PROJECT_RELATIVE;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@TestOnly
|
||||
private static Sdk createMockJdk(@NotNull String name, String path) {
|
||||
return ((JavaSdkImpl)JavaSdk.getInstance()).createMockJdk(name, path, false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Sdk getSdk(String sdkHome, String name) {
|
||||
ProjectJdkTable table = IjPlatformUtil.getProjectJdkTableSafe();
|
||||
Sdk existing = table.findJdk(name);
|
||||
if (existing != null) {
|
||||
return existing;
|
||||
}
|
||||
return JavaSdk.getInstance().createJdk(name, sdkHome, true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Sdk mockJdk() {
|
||||
return getSdk("compiler/testData/mockJDK/jre", "Mock JDK");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Sdk mockJdk6() {
|
||||
return getSdk("compiler/testData/mockJDK/jre", "1.6");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Sdk mockJdk8() {
|
||||
// Using JDK 6, but with version 1.8
|
||||
return getSdk("compiler/testData/mockJDK/jre", "1.8");
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
@NotNull
|
||||
public static Sdk mockJdk9() {
|
||||
return getSdk("compiler/testData/mockJDK9/jre", "9");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Sdk fullJdk() {
|
||||
String javaHome = System.getProperty("java.home");
|
||||
assert new File(javaHome).isDirectory();
|
||||
return getSdk(javaHome, "Full JDK");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Sdk addJdk(@NotNull Disposable disposable, @NotNull Function0<Sdk> getJdk) {
|
||||
Sdk jdk = getJdk.invoke();
|
||||
Sdk[] allJdks = IjPlatformUtil.getProjectJdkTableSafe().getAllJdks();
|
||||
for (Sdk existingJdk : allJdks) {
|
||||
if (existingJdk == jdk) {
|
||||
return existingJdk;
|
||||
}
|
||||
}
|
||||
ApplicationManager.getApplication().runWriteAction(() -> IjPlatformUtil.getProjectJdkTableSafe().addJdk(jdk, disposable));
|
||||
return jdk;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Sdk jdk(@NotNull TestJdkKind kind) {
|
||||
switch (kind) {
|
||||
case MOCK_JDK:
|
||||
return mockJdk();
|
||||
case FULL_JDK_9:
|
||||
String jre9 = KtTestUtil.getJdk9Home().getPath();
|
||||
VfsRootAccess.allowRootAccess(jre9);
|
||||
return getSdk(jre9, "Full JDK 9");
|
||||
case FULL_JDK:
|
||||
return fullJdk();
|
||||
default:
|
||||
throw new UnsupportedOperationException(kind.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isAllFilesPresentTest(@NotNull String testName) {
|
||||
return StringUtil.startsWithIgnoreCase(testName, "allFilesPresentIn");
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
public static void clearSdkTable(@NotNull Disposable disposable) {
|
||||
Disposer.register(disposable, () -> ApplicationManager.getApplication().runWriteAction(() -> {
|
||||
ProjectJdkTable jdkTable = IjPlatformUtil.getProjectJdkTableSafe();
|
||||
for (Sdk sdk : jdkTable.getAllJdks()) {
|
||||
jdkTable.removeJdk(sdk);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.test
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
|
||||
fun runPostStartupActivitiesOnce(project: Project) {
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.test
|
||||
|
||||
import com.intellij.ide.startup.impl.StartupManagerImpl
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.startup.StartupManager
|
||||
|
||||
// FIX ME WHEN BUNCH 201 REMOVED
|
||||
fun runPostStartupActivitiesOnce(project: Project) {
|
||||
(StartupManager.getInstance(project) as StartupManagerImpl).runPostStartupActivitiesRegisteredDynamically()
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.render
|
||||
|
||||
import com.intellij.debugger.DebuggerManagerEx
|
||||
import com.intellij.debugger.engine.DebuggerManagerThreadImpl
|
||||
import com.intellij.debugger.engine.evaluation.EvaluationContext
|
||||
import com.intellij.debugger.settings.NodeRendererSettings
|
||||
import com.intellij.debugger.ui.impl.watch.MessageDescriptor
|
||||
import com.intellij.debugger.ui.impl.watch.NodeManagerImpl
|
||||
import com.intellij.debugger.ui.tree.DebuggerTreeNode
|
||||
import com.intellij.debugger.ui.tree.ValueDescriptor
|
||||
import com.intellij.debugger.ui.tree.render.ChildrenBuilder
|
||||
import com.intellij.debugger.ui.tree.render.ClassRenderer
|
||||
import com.intellij.debugger.ui.tree.render.DescriptorLabelListener
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.xdebugger.settings.XDebuggerSettingsManager
|
||||
import com.sun.jdi.*
|
||||
import org.jetbrains.kotlin.idea.debugger.*
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import java.util.*
|
||||
|
||||
private val LOG = Logger.getInstance(KotlinClassWithDelegatedPropertyRenderer::class.java)
|
||||
private fun notPreparedClassMessage(referenceType: ReferenceType) =
|
||||
"$referenceType ${referenceType.isPrepared} ${referenceType.sourceName()}"
|
||||
|
||||
class KotlinClassWithDelegatedPropertyRenderer : ClassRenderer() {
|
||||
private val rendererSettings = NodeRendererSettings.getInstance()
|
||||
|
||||
override fun isApplicable(jdiType: Type?): Boolean {
|
||||
if (!super.isApplicable(jdiType) || jdiType !is ReferenceType || !jdiType.isPrepared || !jdiType.isInKotlinSources()) {
|
||||
return false
|
||||
}
|
||||
|
||||
try {
|
||||
return jdiType.allFields().any { it.name().endsWith(JvmAbi.DELEGATED_PROPERTY_NAME_SUFFIX) }
|
||||
} catch (notPrepared: ClassNotPreparedException) {
|
||||
LOG.error(notPreparedClassMessage(jdiType), notPrepared)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
override fun calcLabel(
|
||||
descriptor: ValueDescriptor,
|
||||
evaluationContext: EvaluationContext,
|
||||
listener: DescriptorLabelListener
|
||||
): String {
|
||||
val res = calcToStringLabel(descriptor, evaluationContext, listener)
|
||||
if (res != null) {
|
||||
return res
|
||||
}
|
||||
|
||||
return super.calcLabel(descriptor, evaluationContext, listener)
|
||||
}
|
||||
|
||||
private fun calcToStringLabel(
|
||||
descriptor: ValueDescriptor, evaluationContext: EvaluationContext,
|
||||
listener: DescriptorLabelListener
|
||||
): String? {
|
||||
val toStringRenderer = rendererSettings.toStringRenderer
|
||||
if (toStringRenderer.isEnabled && DebuggerManagerEx.getInstanceEx(evaluationContext.project).context.canRunEvaluation) {
|
||||
if (toStringRenderer.isApplicable(descriptor.type)) {
|
||||
return toStringRenderer.calcLabel(descriptor, evaluationContext, listener)
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
override fun buildChildren(value: Value?, builder: ChildrenBuilder, context: EvaluationContext) {
|
||||
DebuggerManagerThreadImpl.assertIsManagerThread()
|
||||
|
||||
if (value !is ObjectReference) return
|
||||
|
||||
val nodeManager = builder.nodeManager!!
|
||||
val nodeDescriptorFactory = builder.descriptorManager!!
|
||||
|
||||
val fields = value.referenceType().allFields()
|
||||
if (fields.isEmpty()) {
|
||||
builder.setChildren(listOf(nodeManager.createMessageNode(MessageDescriptor.CLASS_HAS_NO_FIELDS.label)))
|
||||
return
|
||||
}
|
||||
|
||||
val children = ArrayList<DebuggerTreeNode>()
|
||||
for (field in fields) {
|
||||
if (!shouldDisplay(context, value, field)) {
|
||||
continue
|
||||
}
|
||||
|
||||
val fieldDescriptor = nodeDescriptorFactory.getFieldDescriptor(builder.parentDescriptor, value, field)
|
||||
|
||||
if (field.name().endsWith(JvmAbi.DELEGATED_PROPERTY_NAME_SUFFIX)) {
|
||||
val shouldRenderDelegatedProperty = KotlinDebuggerSettings.getInstance().renderDelegatedProperties
|
||||
if (shouldRenderDelegatedProperty && !ToggleKotlinVariablesState.getService().kotlinVariableView) {
|
||||
children.add(nodeManager.createNode(fieldDescriptor, context))
|
||||
}
|
||||
|
||||
val delegatedPropertyDescriptor = DelegatedPropertyFieldDescriptor(
|
||||
context.debugProcess.project!!,
|
||||
value,
|
||||
field,
|
||||
shouldRenderDelegatedProperty
|
||||
)
|
||||
children.add(nodeManager.createNode(delegatedPropertyDescriptor, context))
|
||||
} else {
|
||||
children.add(nodeManager.createNode(fieldDescriptor, context))
|
||||
}
|
||||
}
|
||||
|
||||
if (XDebuggerSettingsManager.getInstance()!!.dataViewSettings.isSortValues) {
|
||||
children.sortedWith(NodeManagerImpl.getNodeComparator())
|
||||
}
|
||||
|
||||
builder.setChildren(children)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,299 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.test
|
||||
|
||||
import com.intellij.debugger.engine.ContextUtil
|
||||
import com.intellij.debugger.engine.SuspendContextImpl
|
||||
import com.intellij.debugger.engine.evaluation.CodeFragmentKind
|
||||
import com.intellij.debugger.engine.evaluation.EvaluateException
|
||||
import com.intellij.debugger.engine.evaluation.TextWithImportsImpl
|
||||
import com.intellij.debugger.engine.evaluation.expression.EvaluatorBuilderImpl
|
||||
import com.intellij.debugger.impl.DebuggerContextImpl
|
||||
import com.intellij.debugger.impl.DebuggerContextImpl.createDebuggerContext
|
||||
import com.intellij.debugger.ui.impl.watch.NodeDescriptorImpl
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.ui.treeStructure.Tree
|
||||
import com.intellij.xdebugger.impl.ui.tree.ValueMarkup
|
||||
import com.sun.jdi.ObjectReference
|
||||
import org.jetbrains.eval4j.ObjectValue
|
||||
import org.jetbrains.eval4j.Value
|
||||
import org.jetbrains.eval4j.jdi.asValue
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinCodeFragmentFactory
|
||||
import org.jetbrains.kotlin.idea.debugger.test.preference.DebuggerPreferences
|
||||
import org.jetbrains.kotlin.idea.debugger.test.util.FramePrinter
|
||||
import org.jetbrains.kotlin.idea.debugger.test.util.FramePrinterDelegate
|
||||
import org.jetbrains.kotlin.idea.debugger.test.util.KotlinOutputChecker
|
||||
import org.jetbrains.kotlin.idea.debugger.test.util.SteppingInstruction
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils.findLinesWithPrefixesRemoved
|
||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils.findStringWithPrefixes
|
||||
import org.jetbrains.kotlin.test.KotlinBaseTest
|
||||
import org.jetbrains.kotlin.test.TargetBackend
|
||||
import java.io.File
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import javax.swing.tree.TreeNode
|
||||
|
||||
private data class CodeFragment(val text: String, val result: String, val kind: CodeFragmentKind)
|
||||
|
||||
private data class DebugLabel(val name: String, val localName: String)
|
||||
|
||||
private class EvaluationTestData(
|
||||
val instructions: List<SteppingInstruction>,
|
||||
val fragments: List<CodeFragment>,
|
||||
val debugLabels: List<DebugLabel>
|
||||
)
|
||||
|
||||
abstract class AbstractKotlinEvaluateExpressionTest : KotlinDescriptorTestCaseWithStepping(), FramePrinterDelegate {
|
||||
private companion object {
|
||||
private val ID_PART_REGEX = "id=[0-9]*".toRegex()
|
||||
}
|
||||
|
||||
override val debuggerContext: DebuggerContextImpl
|
||||
get() = super.debuggerContext
|
||||
|
||||
private var isMultipleBreakpointsTest = false
|
||||
|
||||
private var framePrinter: FramePrinter? = null
|
||||
|
||||
private val exceptions = ConcurrentHashMap<String, Throwable>()
|
||||
|
||||
fun doSingleBreakpointTest(path: String) {
|
||||
isMultipleBreakpointsTest = false
|
||||
doTest(path)
|
||||
}
|
||||
|
||||
fun doMultipleBreakpointsTest(path: String) {
|
||||
isMultipleBreakpointsTest = true
|
||||
doTest(path)
|
||||
}
|
||||
|
||||
override fun doMultiFileTest(files: TestFiles, preferences: DebuggerPreferences) {
|
||||
val wholeFile = files.wholeFile
|
||||
|
||||
val instructions = SteppingInstruction.parse(wholeFile)
|
||||
val expressions = loadExpressions(wholeFile)
|
||||
val blocks = loadCodeBlocks(files.originalFile)
|
||||
val debugLabels = loadDebugLabels(wholeFile)
|
||||
|
||||
val data = EvaluationTestData(instructions, expressions + blocks, debugLabels)
|
||||
|
||||
framePrinter = FramePrinter(myDebuggerSession, this, preferences, testRootDisposable)
|
||||
|
||||
if (isMultipleBreakpointsTest) {
|
||||
performMultipleBreakpointTest(data)
|
||||
} else {
|
||||
performSingleBreakpointTest(data)
|
||||
}
|
||||
}
|
||||
|
||||
override fun tearDown() {
|
||||
framePrinter?.close()
|
||||
framePrinter = null
|
||||
exceptions.clear()
|
||||
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
private fun performSingleBreakpointTest(data: EvaluationTestData) {
|
||||
process(data.instructions)
|
||||
|
||||
doOnBreakpoint {
|
||||
createDebugLabels(data.debugLabels)
|
||||
|
||||
val exceptions = linkedMapOf<String, Throwable>()
|
||||
|
||||
for ((expression, expected, kind) in data.fragments) {
|
||||
mayThrow(expression) {
|
||||
evaluate(this, expression, kind, expected)
|
||||
}
|
||||
}
|
||||
|
||||
val completion = { resume(this) }
|
||||
framePrinter?.printFrame(completion) ?: completion()
|
||||
}
|
||||
|
||||
finish()
|
||||
}
|
||||
|
||||
private fun performMultipleBreakpointTest(data: EvaluationTestData) {
|
||||
for ((expression, expected) in data.fragments) {
|
||||
doOnBreakpoint {
|
||||
mayThrow(expression) {
|
||||
try {
|
||||
evaluate(this, expression, CodeFragmentKind.EXPRESSION, expected)
|
||||
} finally {
|
||||
val completion = { resume(this) }
|
||||
framePrinter?.printFrame(completion) ?: completion()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finish()
|
||||
}
|
||||
|
||||
override fun evaluate(suspendContext: SuspendContextImpl, textWithImports: TextWithImportsImpl) {
|
||||
evaluate(suspendContext, textWithImports, null)
|
||||
}
|
||||
|
||||
private fun evaluate(suspendContext: SuspendContextImpl, text: String, codeFragmentKind: CodeFragmentKind, expectedResult: String?) {
|
||||
val textWithImports = TextWithImportsImpl(codeFragmentKind, text, "", KotlinFileType.INSTANCE)
|
||||
return evaluate(suspendContext, textWithImports, expectedResult)
|
||||
}
|
||||
|
||||
private fun evaluate(suspendContext: SuspendContextImpl, item: TextWithImportsImpl, expectedResult: String?) {
|
||||
val evaluationContext = this.evaluationContext
|
||||
val sourcePosition = ContextUtil.getSourcePosition(suspendContext)
|
||||
|
||||
// Default test debuggerContext doesn't provide a valid stackFrame so we have to create one more for evaluation purposes.
|
||||
val frameProxy = suspendContext.frameProxy
|
||||
val threadProxy = frameProxy?.threadProxy()
|
||||
val debuggerContext = createDebuggerContext(myDebuggerSession, suspendContext, threadProxy, frameProxy)
|
||||
debuggerContext.initCaches()
|
||||
|
||||
val contextElement = ContextUtil.getContextElement(debuggerContext)!!
|
||||
|
||||
assert(KotlinCodeFragmentFactory().isContextAccepted(contextElement)) {
|
||||
val text = runReadAction { contextElement.text }
|
||||
"KotlinCodeFragmentFactory should be accepted for context element otherwise default evaluator will be called. " +
|
||||
"ContextElement = $text"
|
||||
}
|
||||
|
||||
contextElement.putCopyableUserData(KotlinCodeFragmentFactory.DEBUG_CONTEXT_FOR_TESTS, debuggerContext)
|
||||
|
||||
suspendContext.runActionInSuspendCommand {
|
||||
try {
|
||||
val evaluator = runReadAction {
|
||||
EvaluatorBuilderImpl.build(
|
||||
item,
|
||||
contextElement,
|
||||
sourcePosition,
|
||||
this@AbstractKotlinEvaluateExpressionTest.project
|
||||
)
|
||||
}
|
||||
?: throw AssertionError("Cannot create an Evaluator for Evaluate Expression")
|
||||
|
||||
val value = evaluator.evaluate(evaluationContext)
|
||||
val actualResult = value.asValue().asString()
|
||||
if (expectedResult != null) {
|
||||
assertEquals(
|
||||
"Evaluate expression returns wrong result for ${item.text}:\n" +
|
||||
"expected = $expectedResult\n" +
|
||||
"actual = $actualResult\n",
|
||||
expectedResult, actualResult
|
||||
)
|
||||
}
|
||||
} catch (e: EvaluateException) {
|
||||
val expectedMessage = e.message?.replaceFirst(
|
||||
ID_PART_REGEX,
|
||||
"id=ID"
|
||||
)
|
||||
assertEquals(
|
||||
"Evaluate expression throws wrong exception for ${item.text}:\n" +
|
||||
"expected = $expectedResult\n" +
|
||||
"actual = $expectedMessage\n",
|
||||
expectedResult,
|
||||
expectedMessage
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun logDescriptor(descriptor: NodeDescriptorImpl, text: String) {
|
||||
super.logDescriptor(descriptor, text)
|
||||
}
|
||||
|
||||
override fun expandAll(tree: Tree, runnable: () -> Unit, filter: (TreeNode) -> Boolean, suspendContext: SuspendContextImpl) {
|
||||
super.expandAll(tree, runnable, HashSet(), filter, suspendContext)
|
||||
}
|
||||
|
||||
private fun mayThrow(expression: String, f: () -> Unit) {
|
||||
try {
|
||||
f()
|
||||
} catch (e: Throwable) {
|
||||
exceptions[expression] = e
|
||||
}
|
||||
}
|
||||
|
||||
override fun throwExceptionsIfAny() {
|
||||
if (exceptions.isNotEmpty()) {
|
||||
val isIgnored = InTextDirectivesUtils.isIgnoredTarget(
|
||||
if (useIrBackend()) TargetBackend.JVM_IR else TargetBackend.JVM,
|
||||
getExpectedOutputFile()
|
||||
)
|
||||
|
||||
if (!isIgnored) {
|
||||
for (exc in exceptions.values) {
|
||||
exc.printStackTrace()
|
||||
}
|
||||
val expressionsText = exceptions.entries.joinToString("\n") { (k, v) -> "expression: $k, exception: ${v.message}" }
|
||||
throw AssertionError("Test failed:\n$expressionsText")
|
||||
} else {
|
||||
(checker as KotlinOutputChecker).threwException = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Value.asString(): String {
|
||||
if (this is ObjectValue && this.value is ObjectReference) {
|
||||
return this.toString().replaceFirst(ID_PART_REGEX, "id=ID")
|
||||
}
|
||||
return this.toString()
|
||||
}
|
||||
|
||||
private fun loadExpressions(testFile: KotlinBaseTest.TestFile): List<CodeFragment> {
|
||||
val directives = findLinesWithPrefixesRemoved(testFile.content, "// EXPRESSION: ")
|
||||
val expected = findLinesWithPrefixesRemoved(testFile.content, "// RESULT: ")
|
||||
assert(directives.size == expected.size) { "Sizes of test directives are different" }
|
||||
return directives.zip(expected).map { (text, result) -> CodeFragment(text, result, CodeFragmentKind.EXPRESSION) }
|
||||
}
|
||||
|
||||
private fun loadCodeBlocks(wholeFile: File): List<CodeFragment> {
|
||||
val regexp = (Regex.escape(wholeFile.name) + ".fragment\\d*").toRegex()
|
||||
val fragmentFiles = wholeFile.parentFile.listFiles { _, name -> regexp.matches(name) } ?: emptyArray()
|
||||
|
||||
val codeFragments = mutableListOf<CodeFragment>()
|
||||
|
||||
for (fragmentFile in fragmentFiles) {
|
||||
val contents = FileUtil.loadFile(fragmentFile, true)
|
||||
val value = findStringWithPrefixes(contents, "// RESULT: ") ?: error("'RESULT' directive is missing in $fragmentFile")
|
||||
codeFragments += CodeFragment(contents, value, CodeFragmentKind.CODE_BLOCK)
|
||||
}
|
||||
|
||||
return codeFragments
|
||||
}
|
||||
|
||||
private fun loadDebugLabels(testFile: KotlinBaseTest.TestFile): List<DebugLabel> {
|
||||
return findLinesWithPrefixesRemoved(testFile.content, "// DEBUG_LABEL: ")
|
||||
.map { text ->
|
||||
val labelParts = text.split("=")
|
||||
assert(labelParts.size == 2) { "Wrong format for DEBUG_LABEL directive: // DEBUG_LABEL: {localVariableName} = {labelText}" }
|
||||
|
||||
val localName = labelParts[0].trim()
|
||||
val name = labelParts[1].trim()
|
||||
DebugLabel(name, localName)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createDebugLabels(labels: List<DebugLabel>) {
|
||||
if (labels.isEmpty()) {
|
||||
return
|
||||
}
|
||||
|
||||
val markupMap = NodeDescriptorImpl.getMarkupMap(debugProcess) ?: return
|
||||
|
||||
for ((name, localName) in labels) {
|
||||
val localVariable = evaluationContext.frameProxy!!.visibleVariableByName(localName)
|
||||
assert(localVariable != null) { "Cannot find localVariable for label: name = $localName" }
|
||||
|
||||
val localVariableValue = evaluationContext.frameProxy!!.getValue(localVariable) as? ObjectReference
|
||||
assert(localVariableValue != null) { "Local variable $localName should be an ObjectReference" }
|
||||
|
||||
markupMap[localVariableValue] = ValueMarkup(name, null, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -221,11 +221,7 @@ private class Printer(private val delegate: FramePrinterDelegate, private val co
|
||||
|
||||
if (config.shouldRenderExpression() && descriptor is ValueDescriptorImpl) {
|
||||
val expression = debugProcess.invokeInManagerThread { debuggerContextImpl ->
|
||||
descriptor.getTreeEvaluation((node as XValueNodeImpl).valueContainer as JavaValue, debuggerContextImpl).let {
|
||||
// FIX ME WHEN BUNCH 201 REMOVED: getTreeEvaluation in 202 returns CompletableFuture<PsiElement> but in older platforms it's PsiElement
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
(it as? CompletableFuture<PsiElement>)?.get() ?: it
|
||||
} as? PsiExpression
|
||||
descriptor.getTreeEvaluation((node as XValueNodeImpl).valueContainer as JavaValue, debuggerContextImpl).get()
|
||||
}
|
||||
|
||||
if (expression != null) {
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.testFramework
|
||||
|
||||
import com.intellij.openapi.externalSystem.importing.ImportSpecBuilder
|
||||
import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode
|
||||
import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManagerImpl
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil
|
||||
import com.intellij.openapi.project.DumbService
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.roots.ProjectRootManager
|
||||
import org.jetbrains.plugins.gradle.service.project.open.setupGradleSettings
|
||||
import org.jetbrains.plugins.gradle.settings.GradleProjectSettings
|
||||
import org.jetbrains.plugins.gradle.settings.GradleSettings
|
||||
import org.jetbrains.plugins.gradle.util.GradleConstants
|
||||
import org.jetbrains.plugins.gradle.util.GradleLog
|
||||
import java.io.File
|
||||
import kotlin.test.assertNotNull
|
||||
|
||||
fun refreshGradleProject(projectPath: String, project: Project) {
|
||||
_importProject(File(projectPath).absolutePath, project)
|
||||
|
||||
dispatchAllInvocationEvents()
|
||||
}
|
||||
|
||||
const val GRADLE_JDK_NAME = "Gradle JDK"
|
||||
|
||||
/**
|
||||
* inspired by org.jetbrains.plugins.gradle.service.project.open.importProject(projectDirectory, project)
|
||||
*/
|
||||
private fun _importProject(projectPath: String, project: Project) {
|
||||
GradleLog.LOG.info("Import project at $projectPath")
|
||||
val projectSdk = ProjectRootManager.getInstance(project).projectSdk
|
||||
assertNotNull(projectSdk, "project SDK not found for ${project.name} at $projectPath")
|
||||
val gradleProjectSettings = GradleProjectSettings()
|
||||
|
||||
GradleSettings.getInstance(project).gradleVmOptions =
|
||||
"-Xmx2048m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${System.getProperty("user.dir")}"
|
||||
|
||||
setupGradleSettings(gradleProjectSettings, projectPath, project, projectSdk)
|
||||
gradleProjectSettings.gradleJvm = GRADLE_JDK_NAME
|
||||
|
||||
GradleSettings.getInstance(project).getLinkedProjectSettings(projectPath)?.let { linkedProjectSettings ->
|
||||
linkedProjectSettings.gradleJvm = GRADLE_JDK_NAME
|
||||
}
|
||||
|
||||
_attachGradleProjectAndRefresh(gradleProjectSettings, project)
|
||||
}
|
||||
|
||||
/**
|
||||
* inspired by org.jetbrains.plugins.gradle.service.project.open.attachGradleProjectAndRefresh(gradleProjectSettings, project)
|
||||
* except everything is MODAL_SYNC
|
||||
*/
|
||||
private fun _attachGradleProjectAndRefresh(
|
||||
gradleProjectSettings: GradleProjectSettings,
|
||||
project: Project
|
||||
) {
|
||||
val externalProjectPath = gradleProjectSettings.externalProjectPath
|
||||
ExternalProjectsManagerImpl.getInstance(project).runWhenInitialized {
|
||||
DumbService.getInstance(project).runWhenSmart {
|
||||
ExternalSystemUtil.ensureToolWindowInitialized(project, GradleConstants.SYSTEM_ID)
|
||||
}
|
||||
}
|
||||
val settings = ExternalSystemApiUtil.getSettings(project, GradleConstants.SYSTEM_ID)
|
||||
if (settings.getLinkedProjectSettings(externalProjectPath) == null) {
|
||||
settings.linkProject(gradleProjectSettings)
|
||||
}
|
||||
|
||||
StatefulTestGradleProjectRefreshCallback(externalProjectPath, project).use { callback ->
|
||||
ExternalSystemUtil.refreshProject(
|
||||
externalProjectPath,
|
||||
ImportSpecBuilder(project, GradleConstants.SYSTEM_ID)
|
||||
.use(ProgressExecutionMode.MODAL_SYNC)
|
||||
.callback(callback)
|
||||
.build()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.testFramework
|
||||
|
||||
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer
|
||||
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzerSettings
|
||||
import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl
|
||||
import com.intellij.ide.startup.impl.StartupManagerImpl
|
||||
import com.intellij.lang.LanguageAnnotators
|
||||
import com.intellij.lang.LanguageExtensionPoint
|
||||
import com.intellij.lang.annotation.Annotator
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.application.impl.NonBlockingReadActionImpl
|
||||
import com.intellij.openapi.editor.Document
|
||||
import com.intellij.openapi.extensions.ExtensionPointName
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.project.ex.ProjectManagerEx
|
||||
import com.intellij.openapi.startup.StartupManager
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.psi.impl.PsiDocumentManagerBase
|
||||
import com.intellij.testFramework.ExtensionTestUtil
|
||||
import com.intellij.testFramework.TestApplicationManager
|
||||
import com.intellij.testFramework.runInEdtAndWait
|
||||
import com.intellij.util.ui.UIUtil
|
||||
import org.jetbrains.kotlin.idea.perf.util.logMessage
|
||||
import org.jetbrains.kotlin.idea.test.runPostStartupActivitiesOnce
|
||||
import java.nio.file.Paths
|
||||
|
||||
fun commitAllDocuments() {
|
||||
val fileDocumentManager = FileDocumentManager.getInstance()
|
||||
runInEdtAndWait {
|
||||
fileDocumentManager.saveAllDocuments()
|
||||
}
|
||||
|
||||
ProjectManagerEx.getInstanceEx().openProjects.forEach { project ->
|
||||
val psiDocumentManagerBase = PsiDocumentManager.getInstance(project) as PsiDocumentManagerBase
|
||||
|
||||
runInEdtAndWait {
|
||||
psiDocumentManagerBase.clearUncommittedDocuments()
|
||||
psiDocumentManagerBase.commitAllDocuments()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun commitDocument(project: Project, document: Document) {
|
||||
val psiDocumentManagerBase = PsiDocumentManager.getInstance(project) as PsiDocumentManagerBase
|
||||
runInEdtAndWait {
|
||||
psiDocumentManagerBase.commitDocument(document)
|
||||
}
|
||||
}
|
||||
|
||||
fun saveDocument(document: Document) {
|
||||
val fileDocumentManager = FileDocumentManager.getInstance()
|
||||
|
||||
runInEdtAndWait {
|
||||
fileDocumentManager.saveDocument(document)
|
||||
}
|
||||
}
|
||||
|
||||
fun dispatchAllInvocationEvents() {
|
||||
runInEdtAndWait {
|
||||
UIUtil.dispatchAllInvocationEvents()
|
||||
NonBlockingReadActionImpl.waitForAsyncTaskCompletion();
|
||||
}
|
||||
}
|
||||
|
||||
fun loadProjectWithName(path: String, name: String): Project? =
|
||||
ProjectManagerEx.getInstanceEx().loadProject(Paths.get(path), name)
|
||||
|
||||
fun TestApplicationManager.closeProject(project: Project) {
|
||||
val name = project.name
|
||||
val startupManagerImpl = StartupManager.getInstance(project) as StartupManagerImpl
|
||||
val daemonCodeAnalyzerSettings = DaemonCodeAnalyzerSettings.getInstance()
|
||||
val daemonCodeAnalyzerImpl = DaemonCodeAnalyzer.getInstance(project) as DaemonCodeAnalyzerImpl
|
||||
|
||||
setDataProvider(null)
|
||||
daemonCodeAnalyzerSettings.isImportHintEnabled = true // return default value to avoid unnecessary save
|
||||
startupManagerImpl.checkCleared()
|
||||
daemonCodeAnalyzerImpl.cleanupAfterTest()
|
||||
|
||||
logMessage { "project '$name' is about to be closed" }
|
||||
dispatchAllInvocationEvents()
|
||||
val projectManagerEx = ProjectManagerEx.getInstanceEx()
|
||||
projectManagerEx.forceCloseProject(project)
|
||||
logMessage { "project '$name' successfully closed" }
|
||||
}
|
||||
|
||||
fun runStartupActivities(project: Project) {
|
||||
with(StartupManager.getInstance(project) as StartupManagerImpl) {
|
||||
//scheduleInitialVfsRefresh()
|
||||
runStartupActivities()
|
||||
}
|
||||
runPostStartupActivitiesOnce(project)
|
||||
}
|
||||
|
||||
fun waitForAllEditorsFinallyLoaded(project: Project) {
|
||||
// routing is obsolete in 192
|
||||
}
|
||||
|
||||
fun replaceWithCustomHighlighter(parentDisposable: Disposable, fromImplementationClass: String, toImplementationClass: String) {
|
||||
val pointName = ExtensionPointName.create<LanguageExtensionPoint<Annotator>>(LanguageAnnotators.EP_NAME.name)
|
||||
val extensionPoint = pointName.getPoint(null)
|
||||
|
||||
val point = LanguageExtensionPoint<Annotator>()
|
||||
point.language = "kotlin"
|
||||
point.implementationClass = toImplementationClass
|
||||
|
||||
val extensions = extensionPoint.extensions
|
||||
val filteredExtensions =
|
||||
extensions.filter { it.language != "kotlin" || it.implementationClass != fromImplementationClass }
|
||||
.toList()
|
||||
// custom highlighter is already registered if filteredExtensions has the same size as extensions
|
||||
if (filteredExtensions.size < extensions.size) {
|
||||
ExtensionTestUtil.maskExtensions(pointName, filteredExtensions + listOf(point), parentDisposable)
|
||||
}
|
||||
}
|
||||
@@ -1,221 +0,0 @@
|
||||
<idea-plugin xmlns:xi="http://www.w3.org/2001/XInclude" version="2" url="http://kotlinlang.org" allow-bundled-update="true">
|
||||
<id>org.jetbrains.kotlin</id>
|
||||
|
||||
<name>Kotlin</name>
|
||||
<description><![CDATA[
|
||||
The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
|
||||
<br>
|
||||
<a href="http://kotlinlang.org/docs/tutorials/getting-started.html">Getting Started in IntelliJ IDEA</a><br>
|
||||
<a href="http://kotlinlang.org/docs/tutorials/kotlin-android.html">Getting Started in Android Studio</a><br>
|
||||
<a href="http://slack.kotlinlang.org/">Public Slack</a><br>
|
||||
<a href="https://youtrack.jetbrains.com/issues/KT">Issue tracker</a><br>
|
||||
]]></description>
|
||||
<version>@snapshot@</version>
|
||||
<vendor url="http://www.jetbrains.com">JetBrains</vendor>
|
||||
|
||||
<idea-version since-build="201.7223.91" until-build="201.*"/>
|
||||
|
||||
<change-notes><![CDATA[
|
||||
<h3>1.5.0-M2</h3>
|
||||
<ul>
|
||||
<li><a href="https://kotlinlang.org/docs/fun-interfaces.html?utm_source=product&utm_medium=link">SAM adapters</a> use `invokedynamic` on the JVM by default.</li>
|
||||
<li>Deprecation of `-Xjvm-default=enable` and `-Xjvm-default=compatibility` compiler modes and `@JvmDefault` annotation.</li>
|
||||
<li>Standard library: math functions `floorDiv()` and `mod()`, collection function `firstNotNullOf()`, strict version of String.toBoolean().</li>
|
||||
</ul>
|
||||
Learn more about Kotlin 1.5.0-M2 in the <a href="https://github.com/JetBrains/kotlin/releases/tag/v1.5.0-M2/">changelog</a> and <a href="https://blog.jetbrains.com/kotlin/2021/03/kotlin-1-5-0-m2-released/?utm_source=product&utm_medium=link">this blog post</a>.
|
||||
<br><br>
|
||||
<h3>1.5.0-M1</h3>
|
||||
Released: <b>March 3, 2021</b>
|
||||
<ul>
|
||||
<li><a href="https://kotlinlang.org/docs/whatsnew14.html?utm_source=product&utm_medium=link#new-jvm-ir-backend">JVM IR backend</a> by default.</li>
|
||||
<li>New language features by default: inline value classes, sealed interfaces, and JVM records support.</li>
|
||||
<li>Kotlin/JVM: new default target: 1.8 (1.6 is deprecated), string concatenation uses `invokedynamic` by default.</li>
|
||||
<li>Kotlin/Native compilation time improvements.</li>
|
||||
<li>Fixed compiler exceptions.</li>
|
||||
</ul>
|
||||
Learn more about Kotlin 1.5.0-M1 in the <a href="https://github.com/JetBrains/kotlin/releases/tag/v1.5.0-M1/">changelog</a>.
|
||||
<br><br>
|
||||
<h3>1.4.30</h3>
|
||||
Released: <b>February 4, 2021</b>
|
||||
<ul>
|
||||
<li>Preview of new language features: JVM records support, sealed interfaces, and stable inline classes.</li>
|
||||
<li>Kotlin/JVM: IR backend is now in Beta.</li>
|
||||
<li>Kotlin/Native: performance improvements, new `watchosX64` simulator target, support for Xcode 12.2 libraries.</li>
|
||||
<li>Kotlin/JS: prototype lazy initialization of top-level properties.</li>
|
||||
<li>Support for Gradle configuration cache.</li>
|
||||
<li>Standard library API improvements: locale-agnostic API for upper/lowercasing text and clear Char-to-code and Char-to-digit conversions.</li>
|
||||
</ul>
|
||||
For more details, see <a href="https://kotlinlang.org/docs/reference/whatsnew1430.html?utm_source=product&utm_medium=link">What’s New in Kotlin 1.4.30</a> and <a href="http://blog.jetbrains.com/kotlin/2021/01/1-4-30-is-released-with-a-new-jvm-backend-and-language-and-multiplatform-features/?utm_source=product&utm_medium=link">this blog post</a>.
|
||||
<br><br>
|
||||
<h3>1.4.20</h3>
|
||||
Released: <b>November 23, 2020</b>
|
||||
<ul>
|
||||
<li>Kotlin/JS: New project templates, improved Gradle plugin, experimental <b>compilation with errors mode</b> in the IR compiler.</li>
|
||||
<li>Kotlin/Native: New escape analysis mechanism, wrapping of Objective-C exceptions, various functional and performance improvements.</li>
|
||||
<li>IDE: Experimental support for <a href="https://blog.jetbrains.com/idea/2020/03/intellij-idea-2020-1-beta2/">Code Vision</a>, the <b>Redirect input from</b> option in Kotlin run configurations, and more.</li>
|
||||
<li>JEP 280 (invokedynamic) string concatenation is available on the JVM.</li>
|
||||
<li>Changes to the layout of multiplatform projects.</li>
|
||||
<li>Improved CocoaPods support.</li>
|
||||
<li>Standard library improvements: Extensions for java.nio.file.Path and performance optimizations.</li>
|
||||
<li>Deprecation of the kotlin-android-extensions compiler plugin. Parcelable implementation generator has moved to the new kotlin-parcelize plugin.</li>
|
||||
</ul>
|
||||
For more details, see <a href="https://kotlinlang.org/docs/reference/whatsnew1420.html?utm_source=product&utm_medium=link">What’s New in Kotlin 1.4.20</a> and <a href="https://blog.jetbrains.com/kotlin/2020/11/kotlin-1-4-20-released/?utm_source=product&utm_medium=link">this blog post</a>.
|
||||
<br><br>
|
||||
<h3>1.4.0</h3>
|
||||
Released: <b>August 17, 2020</b>
|
||||
<ul>
|
||||
<li>New compiler with better type inference.</li>
|
||||
<li>IR backends for JVM and JS in Alpha mode (<a href="https://kotlinlang.org/docs/reference/whatsnew14.html#unified-backends-and-extensibility">requires opt-in</a>).</li>
|
||||
<li>A new flexible Kotlin Project Wizard for easy creation and configuration of different types of projects.</li>
|
||||
<li>New IDE functionality to debug coroutines.</li>
|
||||
<li>IDE performance improvements: many actions, such as project opening and autocomplete suggestions now complete up to 4 times faster.</li>
|
||||
<li>New language features such as SAM conversions, trailing comma, and other.</li>
|
||||
<li>Type annotations in the JVM bytecode and new modes for generating default interfaces in Kotlin/JVM.</li>
|
||||
<li>New Gradle DSL for Kotlin/JS.</li>
|
||||
<li>Improved performance and interop with Swift and Objective-C in Kotlin/Native.</li>
|
||||
<li>Support for sharing code in several targets thanks to the hierarchical structure in multiplatform projects.</li>
|
||||
<li>New collection operators, delegated properties improvements, the double-ended queue implementation ArrayDeque, and much more new things in the standard library.</li>
|
||||
</ul>
|
||||
For more details, see <a href="https://kotlinlang.org/docs/reference/whatsnew14.html?utm_source=product&utm_medium=link">What’s New in Kotlin 1.4.0</a> and <a href="http://blog.jetbrains.com/kotlin/2020/08/kotlin-1-4-released-with-a-focus-on-quality-and-performance/?utm_source=product&utm_medium=link">this blog post</a>.
|
||||
<br><br>
|
||||
To get the most out of the changes and improvements introduced in Kotlin 1.4, join our <a href="https://kotlinlang.org/lp/event-14/">Online Event</a> where you will be able to enjoy four days of Kotlin talks, Q&As with the Kotlin team, and more.
|
||||
]]>
|
||||
</change-notes>
|
||||
|
||||
<depends>com.intellij.modules.platform</depends>
|
||||
|
||||
<depends optional="true" config-file="junit.xml">JUnit</depends>
|
||||
<depends optional="true" config-file="gradle.xml">com.intellij.gradle</depends>
|
||||
<depends optional="true" config-file="gradle-java.xml">org.jetbrains.plugins.gradle</depends>
|
||||
<depends optional="true" config-file="kotlin-gradle-testing.xml">org.jetbrains.plugins.gradle</depends>
|
||||
<depends optional="true" config-file="gradle-groovy.xml">org.intellij.groovy</depends>
|
||||
<depends optional="true" config-file="maven.xml">org.jetbrains.idea.maven</depends>
|
||||
<depends optional="true" config-file="testng-j.xml">TestNG-J</depends>
|
||||
<depends optional="true" config-file="coverage.xml">Coverage</depends>
|
||||
<depends optional="true" config-file="i18n.xml">com.intellij.java-i18n</depends>
|
||||
<depends optional="true" config-file="decompiler.xml">org.jetbrains.java.decompiler</depends>
|
||||
<depends optional="true" config-file="git4idea.xml">Git4Idea</depends>
|
||||
<depends optional="true" config-file="stream-debugger.xml">org.jetbrains.debugger.streams</depends>
|
||||
<depends optional="true" config-file="completion-stats.xml">com.intellij.stats.completion</depends>
|
||||
|
||||
<!-- ULTIMATE-PLUGIN-PLACEHOLDER -->
|
||||
|
||||
<!-- CIDR-PLUGIN-PLACEHOLDER-START -->
|
||||
<depends>com.intellij.modules.idea</depends>
|
||||
<depends>com.intellij.modules.java</depends>
|
||||
<depends optional="true" config-file="javaScriptDebug.xml">JavaScriptDebugger</depends>
|
||||
<depends optional="true" config-file="kotlin-copyright.xml">com.intellij.copyright</depends>
|
||||
<depends optional="true" config-file="injection.xml">org.intellij.intelliLang</depends>
|
||||
<!-- CIDR-PLUGIN-PLACEHOLDER-END -->
|
||||
|
||||
<xi:include href="plugin-common.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
|
||||
<!-- CIDR-PLUGIN-EXCLUDE-START -->
|
||||
<xi:include href="jvm-common.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
<xi:include href="jvm.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
<xi:include href="parcelize.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
<!-- CIDR-PLUGIN-EXCLUDE-END -->
|
||||
|
||||
<xi:include href="native-common.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
<xi:include href="native.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
|
||||
<xi:include href="tipsAndTricks.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
|
||||
<xi:include href="extensions/ide.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
|
||||
<xi:include href="kotlinx-serialization.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
|
||||
<xi:include href="scripting-support.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
|
||||
<extensionPoints>
|
||||
<xi:include href="extensions/compiler.xml" xpointer="xpointer(/idea-plugin/extensionPoints/*)"/>
|
||||
|
||||
<extensionPoint qualifiedName="org.jetbrains.kotlin.pluginUpdateVerifier"
|
||||
interface="org.jetbrains.kotlin.idea.update.PluginUpdateVerifier"/>
|
||||
</extensionPoints>
|
||||
|
||||
<xi:include href="plugin-kotlin-extensions.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij.jvm">
|
||||
<declarationSearcher language="kotlin" implementationClass="org.jetbrains.kotlin.idea.jvm.KotlinDeclarationSearcher"/>
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<pathMacroContributor implementation="org.jetbrains.kotlin.idea.KotlinPluginMacros"/>
|
||||
<applicationService serviceImplementation="org.jetbrains.kotlin.idea.PluginStartupApplicationService"/>
|
||||
|
||||
<postStartupActivity implementation="org.jetbrains.kotlin.idea.PluginStartupActivity"/>
|
||||
<projectService serviceImplementation="org.jetbrains.kotlin.idea.PluginStartupService"/>
|
||||
|
||||
<postStartupActivity implementation="org.jetbrains.kotlin.idea.completion.LookupCancelWatcher"/>
|
||||
<postStartupActivity implementation="org.jetbrains.kotlin.idea.caches.KotlinPackageContentModificationListener"/>
|
||||
<postStartupActivity implementation="org.jetbrains.kotlin.idea.configuration.KotlinMigrationProjectComponent"/>
|
||||
|
||||
<projectService serviceImplementation="org.jetbrains.kotlin.idea.completion.LookupCancelService"/>
|
||||
<projectService serviceImplementation="org.jetbrains.kotlin.idea.configuration.KotlinMigrationProjectService"/>
|
||||
|
||||
<highlightVisitor implementation="org.jetbrains.kotlin.idea.highlighter.KotlinHighlightVisitor"/>
|
||||
<highlightingPassFactory implementation="org.jetbrains.kotlin.idea.highlighter.KotlinBeforeResolveHighlightingPass$Registrar"/>
|
||||
<highlightingPassFactory implementation="org.jetbrains.kotlin.idea.highlighter.DebugInfoHighlightingPass$Registrar"/>
|
||||
<highlightingPassFactory implementation="org.jetbrains.kotlin.idea.highlighter.ScriptExternalHighlightingPass$Registrar"/>
|
||||
<highlightingPassFactory implementation="org.jetbrains.kotlin.idea.refactoring.cutPaste.MoveDeclarationsPassFactory$Registrar"/>
|
||||
|
||||
<projectService serviceImplementation="org.jetbrains.kotlin.idea.caches.trackers.KotlinCodeBlockModificationListener"/>
|
||||
|
||||
<statistics.counterUsagesCollector groupId="kotlin.gradle.target" version="2"/>
|
||||
<statistics.counterUsagesCollector groupId="kotlin.maven.target" version="3"/>
|
||||
<statistics.counterUsagesCollector groupId="kotlin.jps.target" version="3"/>
|
||||
<statistics.counterUsagesCollector groupId="kotlin.gradle.library" version="1"/>
|
||||
<statistics.counterUsagesCollector groupId="kotlin.ide.refactoring" version="1"/>
|
||||
<statistics.counterUsagesCollector groupId="kotlin.ide.newFileTempl" version="1"/>
|
||||
<statistics.counterUsagesCollector groupId="kotlin.ide.npwizards" version="2"/>
|
||||
<statistics.counterUsagesCollector groupId="kotlin.ide.debugger" version="2"/>
|
||||
<statistics.counterUsagesCollector groupId="kotlin.ide.j2k" version="1"/>
|
||||
<statistics.counterUsagesCollector groupId="kotlin.ide.editor" version="1"/>
|
||||
<statistics.counterUsagesCollector groupId="kotlin.ide.migrationTool" version="1"/>
|
||||
<statistics.counterUsagesCollector groupId="kotlin.ide.new.wizard" version="1"/>
|
||||
<statistics.counterUsagesCollector groupId="kotlin.gradle.performance" version="1"/>
|
||||
<statistics.projectUsagesCollector implementation="org.jetbrains.kotlin.idea.IDESettingsFUSCollector"/>
|
||||
<statistics.projectUsagesCollector implementation="org.jetbrains.kotlin.idea.formatter.KotlinFormatterUsageCollector"/>
|
||||
<statistics.projectUsagesCollector implementation="org.jetbrains.kotlin.idea.statistics.ProjectConfigurationCollector"/>
|
||||
|
||||
<fileTypeUsageSchemaDescriptor schema="Gradle Script"
|
||||
implementationClass="org.jetbrains.kotlin.idea.core.script.KotlinGradleScriptFileTypeSchemaDetector"/>
|
||||
|
||||
<completion.ml.model implementation="org.jetbrains.kotlin.idea.completion.ml.KotlinMLRankingProvider"/>
|
||||
<completion.ml.contextFeatures language="kotlin"
|
||||
implementationClass="org.jetbrains.kotlin.idea.completion.ml.KotlinContextFeatureProvider"/>
|
||||
<suggestedRefactoringSupport language="kotlin"
|
||||
implementationClass="org.jetbrains.kotlin.idea.refactoring.suggested.KotlinSuggestedRefactoringSupport"/>
|
||||
|
||||
<refactoring.moveInnerHandler language="kotlin"
|
||||
implementationClass="org.jetbrains.kotlin.idea.refactoring.move.MoveKotlinInnerHandler"/>
|
||||
|
||||
<defaultLiveTemplates file="liveTemplates/Kotlin.xml"/>
|
||||
|
||||
<fileType name="Kotlin"
|
||||
implementationClass="org.jetbrains.kotlin.idea.KotlinFileType"
|
||||
fieldName="INSTANCE"
|
||||
language="kotlin"
|
||||
extensions="kt;kts"/>
|
||||
<fileType name="ARCHIVE" extensions="klib"/>
|
||||
<fileType name="KNM"
|
||||
implementationClass="org.jetbrains.kotlin.idea.klib.KlibMetaFileType"
|
||||
fieldName="INSTANCE"
|
||||
extensions="knm"/>
|
||||
<fileType name="KJSM"
|
||||
implementationClass="org.jetbrains.kotlin.idea.decompiler.js.KotlinJavaScriptMetaFileType"
|
||||
fieldName="INSTANCE"
|
||||
extensions="kjsm"/>
|
||||
|
||||
<fileType name="kotlin_builtins"
|
||||
implementationClass="org.jetbrains.kotlin.idea.decompiler.builtIns.KotlinBuiltInFileType"
|
||||
fieldName="INSTANCE"
|
||||
extensions="kotlin_builtins;kotlin_metadata"/>
|
||||
|
||||
<fileType name="kotlin_module"
|
||||
implementationClass="org.jetbrains.kotlin.idea.KotlinModuleFileType"
|
||||
fieldName="INSTANCE"
|
||||
extensions="kotlin_module"/>
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
@@ -1,203 +0,0 @@
|
||||
<idea-plugin xmlns:xi="http://www.w3.org/2001/XInclude" version="2" url="http://kotlinlang.org" allow-bundled-update="true">
|
||||
<id>org.jetbrains.kotlin</id>
|
||||
|
||||
<name>Kotlin</name>
|
||||
<description><![CDATA[
|
||||
The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
|
||||
<br>
|
||||
<a href="http://kotlinlang.org/docs/tutorials/getting-started.html">Getting Started in IntelliJ IDEA</a><br>
|
||||
<a href="http://kotlinlang.org/docs/tutorials/kotlin-android.html">Getting Started in Android Studio</a><br>
|
||||
<a href="http://slack.kotlinlang.org/">Public Slack</a><br>
|
||||
<a href="https://youtrack.jetbrains.com/issues/KT">Issue tracker</a><br>
|
||||
]]></description>
|
||||
<version>@snapshot@</version>
|
||||
<vendor url="http://www.jetbrains.com">JetBrains</vendor>
|
||||
|
||||
<idea-version since-build="201.7223.91" until-build="201.*"/>
|
||||
|
||||
<change-notes><![CDATA[
|
||||
<h3>1.5.0-M2</h3>
|
||||
<ul>
|
||||
<li><a href="https://kotlinlang.org/docs/fun-interfaces.html?utm_source=product&utm_medium=link">SAM adapters</a> use `invokedynamic` on the JVM by default.</li>
|
||||
<li>Deprecation of `-Xjvm-default=enable` and `-Xjvm-default=compatibility` compiler modes and `@JvmDefault` annotation.</li>
|
||||
<li>Standard library: math functions `floorDiv()` and `mod()`, collection function `firstNotNullOf()`, strict version of String.toBoolean().</li>
|
||||
</ul>
|
||||
Learn more about Kotlin 1.5.0-M2 in the <a href="https://github.com/JetBrains/kotlin/releases/tag/v1.5.0-M2/">changelog</a> and <a href="https://blog.jetbrains.com/kotlin/2021/03/kotlin-1-5-0-m2-released/?utm_source=product&utm_medium=link">this blog post</a>.
|
||||
<br><br>
|
||||
<h3>1.5.0-M1</h3>
|
||||
Released: <b>March 3, 2021</b>
|
||||
<ul>
|
||||
<li><a href="https://kotlinlang.org/docs/whatsnew14.html?utm_source=product&utm_medium=link#new-jvm-ir-backend">JVM IR backend</a> by default.</li>
|
||||
<li>New language features by default: inline value classes, sealed interfaces, and JVM records support.</li>
|
||||
<li>Kotlin/JVM: new default target: 1.8 (1.6 is deprecated), string concatenation uses `invokedynamic` by default.</li>
|
||||
<li>Kotlin/Native compilation time improvements.</li>
|
||||
<li>Fixed compiler exceptions.</li>
|
||||
</ul>
|
||||
Learn more about Kotlin 1.5.0-M1 in the <a href="https://github.com/JetBrains/kotlin/releases/tag/v1.5.0-M1/">changelog</a>.
|
||||
<br><br>
|
||||
<h3>1.4.30</h3>
|
||||
Released: <b>February 4, 2021</b>
|
||||
<ul>
|
||||
<li>Preview of new language features: JVM records support, sealed interfaces, and stable inline classes.</li>
|
||||
<li>Kotlin/JVM: IR backend is now in Beta.</li>
|
||||
<li>Kotlin/Native: performance improvements, new `watchosX64` simulator target, support for Xcode 12.2 libraries.</li>
|
||||
<li>Kotlin/JS: prototype lazy initialization of top-level properties.</li>
|
||||
<li>Support for Gradle configuration cache.</li>
|
||||
<li>Standard library API improvements: locale-agnostic API for upper/lowercasing text and clear Char-to-code and Char-to-digit conversions.</li>
|
||||
</ul>
|
||||
For more details, see <a href="https://kotlinlang.org/docs/reference/whatsnew1430.html?utm_source=product&utm_medium=link">What’s New in Kotlin 1.4.30</a> and <a href="http://blog.jetbrains.com/kotlin/2021/01/1-4-30-is-released-with-a-new-jvm-backend-and-language-and-multiplatform-features/?utm_source=product&utm_medium=link">this blog post</a>.
|
||||
<br><br>
|
||||
<h3>1.4.20</h3>
|
||||
Released: <b>November 23, 2020</b>
|
||||
<ul>
|
||||
<li>Kotlin/JS: New project templates, improved Gradle plugin, experimental <b>compilation with errors mode</b> in the IR compiler.</li>
|
||||
<li>Kotlin/Native: New escape analysis mechanism, wrapping of Objective-C exceptions, various functional and performance improvements.</li>
|
||||
<li>IDE: Experimental support for <a href="https://blog.jetbrains.com/idea/2020/03/intellij-idea-2020-1-beta2/">Code Vision</a>, the <b>Redirect input from</b> option in Kotlin run configurations, and more.</li>
|
||||
<li>JEP 280 (invokedynamic) string concatenation is available on the JVM.</li>
|
||||
<li>Changes to the layout of multiplatform projects.</li>
|
||||
<li>Improved CocoaPods support.</li>
|
||||
<li>Standard library improvements: Extensions for java.nio.file.Path and performance optimizations.</li>
|
||||
<li>Deprecation of the kotlin-android-extensions compiler plugin. Parcelable implementation generator has moved to the new kotlin-parcelize plugin.</li>
|
||||
</ul>
|
||||
For more details, see <a href="https://kotlinlang.org/docs/reference/whatsnew1420.html?utm_source=product&utm_medium=link">What’s New in Kotlin 1.4.20</a> and <a href="https://blog.jetbrains.com/kotlin/2020/11/kotlin-1-4-20-released/?utm_source=product&utm_medium=link">this blog post</a>.
|
||||
<br><br>
|
||||
<h3>1.4.0</h3>
|
||||
Released: <b>August 17, 2020</b>
|
||||
<ul>
|
||||
<li>New compiler with better type inference.</li>
|
||||
<li>IR backends for JVM and JS in Alpha mode (<a href="https://kotlinlang.org/docs/reference/whatsnew14.html#unified-backends-and-extensibility">requires opt-in</a>).</li>
|
||||
<li>A new flexible Kotlin Project Wizard for easy creation and configuration of different types of projects.</li>
|
||||
<li>New IDE functionality to debug coroutines.</li>
|
||||
<li>IDE performance improvements: many actions, such as project opening and autocomplete suggestions now complete up to 4 times faster.</li>
|
||||
<li>New language features such as SAM conversions, trailing comma, and other.</li>
|
||||
<li>Type annotations in the JVM bytecode and new modes for generating default interfaces in Kotlin/JVM.</li>
|
||||
<li>New Gradle DSL for Kotlin/JS.</li>
|
||||
<li>Improved performance and interop with Swift and Objective-C in Kotlin/Native.</li>
|
||||
<li>Support for sharing code in several targets thanks to the hierarchical structure in multiplatform projects.</li>
|
||||
<li>New collection operators, delegated properties improvements, the double-ended queue implementation ArrayDeque, and much more new things in the standard library.</li>
|
||||
</ul>
|
||||
For more details, see <a href="https://kotlinlang.org/docs/reference/whatsnew14.html?utm_source=product&utm_medium=link">What’s New in Kotlin 1.4.0</a> and <a href="http://blog.jetbrains.com/kotlin/2020/08/kotlin-1-4-released-with-a-focus-on-quality-and-performance/?utm_source=product&utm_medium=link">this blog post</a>.
|
||||
<br><br>
|
||||
To get the most out of the changes and improvements introduced in Kotlin 1.4, join our <a href="https://kotlinlang.org/lp/event-14/">Online Event</a> where you will be able to enjoy four days of Kotlin talks, Q&As with the Kotlin team, and more.
|
||||
]]>
|
||||
</change-notes>
|
||||
|
||||
<depends>com.intellij.modules.platform</depends>
|
||||
<depends>com.intellij.modules.androidstudio</depends>
|
||||
|
||||
<depends optional="true" config-file="junit.xml">JUnit</depends>
|
||||
<depends optional="true" config-file="gradle.xml">com.intellij.gradle</depends>
|
||||
<depends optional="true" config-file="gradle-java.xml">org.jetbrains.plugins.gradle</depends>
|
||||
<depends optional="true" config-file="kotlin-gradle-testing.xml">org.jetbrains.plugins.gradle</depends>
|
||||
<depends optional="true" config-file="gradle-groovy.xml">org.intellij.groovy</depends>
|
||||
<depends optional="true" config-file="maven.xml">org.jetbrains.idea.maven</depends>
|
||||
<depends optional="true" config-file="testng-j.xml">TestNG-J</depends>
|
||||
<depends optional="true" config-file="coverage.xml">Coverage</depends>
|
||||
<depends optional="true" config-file="i18n.xml">com.intellij.java-i18n</depends>
|
||||
<depends optional="true" config-file="decompiler.xml">org.jetbrains.java.decompiler</depends>
|
||||
<depends optional="true" config-file="git4idea.xml">Git4Idea</depends>
|
||||
<depends optional="true" config-file="stream-debugger.xml">org.jetbrains.debugger.streams</depends>
|
||||
|
||||
<!-- ULTIMATE-PLUGIN-PLACEHOLDER -->
|
||||
|
||||
<!-- CIDR-PLUGIN-PLACEHOLDER-START -->
|
||||
<depends>com.intellij.modules.java</depends>
|
||||
<depends optional="true" config-file="javaScriptDebug.xml">JavaScriptDebugger</depends>
|
||||
<depends optional="true" config-file="kotlin-copyright.xml">com.intellij.copyright</depends>
|
||||
<depends optional="true" config-file="injection.xml">org.intellij.intelliLang</depends>
|
||||
<!-- CIDR-PLUGIN-PLACEHOLDER-END -->
|
||||
|
||||
<xi:include href="plugin-common.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
|
||||
<!-- CIDR-PLUGIN-EXCLUDE-START -->
|
||||
<xi:include href="jvm-common.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
<xi:include href="jvm.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
<xi:include href="parcelize.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
<!-- CIDR-PLUGIN-EXCLUDE-END -->
|
||||
|
||||
<xi:include href="native-common.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
<xi:include href="native.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
|
||||
<xi:include href="tipsAndTricks.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
|
||||
<xi:include href="extensions/ide.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
|
||||
<xi:include href="kotlinx-serialization.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
|
||||
<xi:include href="scripting-support.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
|
||||
<extensionPoints>
|
||||
<xi:include href="extensions/compiler.xml" xpointer="xpointer(/idea-plugin/extensionPoints/*)"/>
|
||||
|
||||
<extensionPoint qualifiedName="org.jetbrains.kotlin.pluginUpdateVerifier"
|
||||
interface="org.jetbrains.kotlin.idea.update.PluginUpdateVerifier"/>
|
||||
</extensionPoints>
|
||||
|
||||
<xi:include href="plugin-kotlin-extensions.xml" xpointer="xpointer(/idea-plugin/*)"/>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij.jvm">
|
||||
<declarationSearcher language="kotlin" implementationClass="org.jetbrains.kotlin.idea.jvm.KotlinDeclarationSearcher"/>
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<pathMacroContributor implementation="org.jetbrains.kotlin.idea.KotlinPluginMacros"/>
|
||||
<applicationService serviceImplementation="org.jetbrains.kotlin.idea.PluginStartupApplicationService" />
|
||||
|
||||
<postStartupActivity implementation="org.jetbrains.kotlin.idea.PluginStartupActivity"/>
|
||||
<projectService serviceImplementation="org.jetbrains.kotlin.idea.PluginStartupService"/>
|
||||
|
||||
<postStartupActivity implementation="org.jetbrains.kotlin.idea.completion.LookupCancelWatcher"/>
|
||||
<postStartupActivity implementation="org.jetbrains.kotlin.idea.caches.KotlinPackageContentModificationListener"/>
|
||||
<postStartupActivity implementation="org.jetbrains.kotlin.idea.configuration.KotlinMigrationProjectComponent"/>
|
||||
|
||||
<projectService serviceImplementation="org.jetbrains.kotlin.idea.completion.LookupCancelService"/>
|
||||
<projectService serviceImplementation="org.jetbrains.kotlin.idea.configuration.KotlinMigrationProjectService"/>
|
||||
|
||||
<highlightVisitor implementation="org.jetbrains.kotlin.idea.highlighter.KotlinHighlightVisitor"/>
|
||||
<highlightingPassFactory implementation="org.jetbrains.kotlin.idea.highlighter.KotlinBeforeResolveHighlightingPass$Registrar"/>
|
||||
<highlightingPassFactory implementation="org.jetbrains.kotlin.idea.highlighter.DebugInfoHighlightingPass$Registrar"/>
|
||||
<highlightingPassFactory implementation="org.jetbrains.kotlin.idea.highlighter.ScriptExternalHighlightingPass$Registrar"/>
|
||||
<highlightingPassFactory implementation="org.jetbrains.kotlin.idea.refactoring.cutPaste.MoveDeclarationsPassFactory$Registrar"/>
|
||||
|
||||
<projectService serviceImplementation="org.jetbrains.kotlin.idea.caches.trackers.KotlinCodeBlockModificationListener"/>
|
||||
|
||||
<fileTypeUsageSchemaDescriptor schema="Gradle Script" implementationClass="org.jetbrains.kotlin.idea.core.script.KotlinGradleScriptFileTypeSchemaDetector"/>
|
||||
|
||||
<completion.ml.model implementation="org.jetbrains.kotlin.idea.completion.ml.KotlinMLRankingProvider"/>
|
||||
<suggestedRefactoringSupport language="kotlin" implementationClass="org.jetbrains.kotlin.idea.refactoring.suggested.KotlinSuggestedRefactoringSupport"/>
|
||||
|
||||
<refactoring.moveInnerHandler language="kotlin"
|
||||
implementationClass="org.jetbrains.kotlin.idea.refactoring.move.MoveKotlinInnerHandler"/>
|
||||
|
||||
<defaultLiveTemplates file="liveTemplates/Kotlin.xml"/>
|
||||
|
||||
<fileType name="Kotlin"
|
||||
implementationClass="org.jetbrains.kotlin.idea.KotlinFileType"
|
||||
fieldName="INSTANCE"
|
||||
language="kotlin"
|
||||
extensions="kt;kts"/>
|
||||
<fileType name="ARCHIVE" extensions="klib"/>
|
||||
<fileType name="KNM"
|
||||
implementationClass="org.jetbrains.kotlin.idea.klib.KlibMetaFileType"
|
||||
fieldName="INSTANCE"
|
||||
extensions="knm"/>
|
||||
<fileType name="KJSM"
|
||||
implementationClass="org.jetbrains.kotlin.idea.decompiler.js.KotlinJavaScriptMetaFileType"
|
||||
fieldName="INSTANCE"
|
||||
extensions="kjsm"/>
|
||||
|
||||
<fileType name="kotlin_builtins"
|
||||
implementationClass="org.jetbrains.kotlin.idea.decompiler.builtIns.KotlinBuiltInFileType"
|
||||
fieldName="INSTANCE"
|
||||
extensions="kotlin_builtins;kotlin_metadata"/>
|
||||
|
||||
<fileType name="kotlin_module"
|
||||
implementationClass="org.jetbrains.kotlin.idea.KotlinModuleFileType"
|
||||
fieldName="INSTANCE"
|
||||
extensions="kotlin_module"/>
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="org.jetbrains.kotlin">
|
||||
<pluginUpdateVerifier implementation="org.jetbrains.kotlin.idea.update.GooglePluginUpdateVerifier"/>
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
@@ -1,5 +0,0 @@
|
||||
<idea-plugin>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<externalAnnotator language="kotlin" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintExternalAnnotator"/>
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
@@ -1,380 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.scratch
|
||||
|
||||
import com.intellij.ide.scratch.ScratchFileService
|
||||
import com.intellij.ide.scratch.ScratchRootType
|
||||
import com.intellij.openapi.actionSystem.AnAction
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.roots.CompilerModuleExtension
|
||||
import com.intellij.openapi.roots.ModuleRootModificationUtil
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess
|
||||
import com.intellij.testFramework.FileEditorManagerTestCase
|
||||
import com.intellij.testFramework.MapDataContext
|
||||
import com.intellij.testFramework.PsiTestUtil
|
||||
import com.intellij.testFramework.TestActionEvent
|
||||
import com.intellij.util.ui.UIUtil
|
||||
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||
import org.jetbrains.kotlin.idea.actions.KOTLIN_WORKSHEET_EXTENSION
|
||||
import org.jetbrains.kotlin.idea.core.script.ScriptConfigurationManager
|
||||
import org.jetbrains.kotlin.idea.debugger.coroutine.util.logger
|
||||
import org.jetbrains.kotlin.idea.highlighter.KotlinHighlightingUtil
|
||||
import org.jetbrains.kotlin.idea.scratch.actions.ClearScratchAction
|
||||
import org.jetbrains.kotlin.idea.scratch.actions.RunScratchAction
|
||||
import org.jetbrains.kotlin.idea.scratch.actions.ScratchCompilationSupport
|
||||
import org.jetbrains.kotlin.idea.scratch.output.InlayScratchFileRenderer
|
||||
import org.jetbrains.kotlin.idea.scratch.ui.KtScratchFileEditorWithPreview
|
||||
import org.jetbrains.kotlin.idea.test.KotlinLightProjectDescriptor
|
||||
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
|
||||
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import org.jetbrains.kotlin.parsing.KotlinParserDefinition.Companion.STD_SCRIPT_SUFFIX
|
||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import org.jetbrains.kotlin.test.MockLibraryUtil
|
||||
import org.jetbrains.kotlin.test.util.KtTestUtil
|
||||
import org.jetbrains.kotlin.utils.PathUtil
|
||||
import org.junit.Assert
|
||||
import java.io.File
|
||||
|
||||
abstract class AbstractScratchRunActionTest : FileEditorManagerTestCase() {
|
||||
|
||||
fun doRightPreviewPanelOutputTest(fileName: String) {
|
||||
doRightPreviewPanelOutputTest(fileName = fileName, isRepl = false)
|
||||
}
|
||||
|
||||
fun doWorksheetReplTest(fileName: String) {
|
||||
doInlayOutputTest(fileName = fileName, isRepl = true, isWorksheet = true)
|
||||
}
|
||||
|
||||
fun doScratchReplTest(fileName: String) {
|
||||
doInlayOutputTest(fileName = fileName, isRepl = true, isWorksheet = false)
|
||||
}
|
||||
|
||||
fun doWorksheetCompilingTest(fileName: String) {
|
||||
doInlayOutputTest(fileName = fileName, isRepl = false, isWorksheet = true)
|
||||
}
|
||||
|
||||
fun doScratchCompilingTest(fileName: String) {
|
||||
doInlayOutputTest(fileName = fileName, isRepl = false, isWorksheet = false)
|
||||
}
|
||||
|
||||
fun doWorksheetMultiFileTest(dirName: String) {
|
||||
doMultiFileTest(dirName, isWorksheet = true)
|
||||
}
|
||||
|
||||
fun doScratchMultiFileTest(dirName: String) {
|
||||
doMultiFileTest(dirName, isWorksheet = false)
|
||||
}
|
||||
|
||||
private fun doMultiFileTest(dirName: String, isWorksheet: Boolean) {
|
||||
val mainFileExtension = if (isWorksheet) KOTLIN_WORKSHEET_EXTENSION else STD_SCRIPT_SUFFIX
|
||||
|
||||
val javaFiles = arrayListOf<File>()
|
||||
val kotlinFiles = arrayListOf<File>()
|
||||
val baseDir = File(testDataPath, dirName)
|
||||
baseDir.walk().forEach {
|
||||
if (it.isFile) {
|
||||
if (it.extension == "java") javaFiles.add(it)
|
||||
if (it.extension == "kt") kotlinFiles.add(it)
|
||||
}
|
||||
}
|
||||
|
||||
val testDataPathFile = File(myFixture.testDataPath)
|
||||
javaFiles.forEach {
|
||||
myFixture.copyFileToProject(
|
||||
FileUtil.getRelativePath(testDataPathFile, it)!!,
|
||||
FileUtil.getRelativePath(baseDir, it)!!
|
||||
)
|
||||
}
|
||||
kotlinFiles.forEach {
|
||||
myFixture.copyFileToProject(
|
||||
FileUtil.getRelativePath(testDataPathFile, it)!!,
|
||||
FileUtil.getRelativePath(baseDir, it)!!
|
||||
)
|
||||
}
|
||||
|
||||
val outputDir = FileUtil.createTempDirectory(dirName, "")
|
||||
|
||||
if (javaFiles.isNotEmpty()) {
|
||||
val options = listOf("-d", outputDir.path)
|
||||
KotlinTestUtils.compileJavaFiles(javaFiles, options)
|
||||
}
|
||||
|
||||
MockLibraryUtil.compileKotlin(baseDir.path, outputDir)
|
||||
|
||||
PsiTestUtil.setCompilerOutputPath(myFixture.module, outputDir.path, false)
|
||||
|
||||
val mainFileName = "$dirName/${getTestName(true)}.$mainFileExtension"
|
||||
doInlayOutputTest(mainFileName, isRepl = false, isWorksheet = isWorksheet)
|
||||
|
||||
launchAction(ClearScratchAction())
|
||||
|
||||
doInlayOutputTest(mainFileName, isRepl = true, isWorksheet = isWorksheet)
|
||||
|
||||
ModuleRootModificationUtil.updateModel(myFixture.module) { model ->
|
||||
model.getModuleExtension(CompilerModuleExtension::class.java).inheritCompilerOutputPath(true)
|
||||
}
|
||||
}
|
||||
|
||||
private fun doInlayOutputTest(fileName: String, isRepl: Boolean, isWorksheet: Boolean) {
|
||||
configureAndLaunchScratch(fileName = fileName, isRepl = isRepl, isWorksheet = isWorksheet)
|
||||
|
||||
val actualOutput = getFileTextWithInlays()
|
||||
|
||||
val expectedFile = getExpectedFile(fileName, isRepl, suffix = "after")
|
||||
KotlinTestUtils.assertEqualsToFile(expectedFile, actualOutput)
|
||||
}
|
||||
|
||||
private fun doRightPreviewPanelOutputTest(fileName: String, isRepl: Boolean) {
|
||||
configureAndLaunchScratch(fileName = fileName, isRepl = isRepl, isWorksheet = false)
|
||||
|
||||
val previewTextWithFoldings = getPreviewTextWithFoldings()
|
||||
|
||||
val expectedFile = getExpectedFile(fileName, isRepl, suffix = "preview")
|
||||
KotlinTestUtils.assertEqualsToFile(expectedFile, previewTextWithFoldings)
|
||||
}
|
||||
|
||||
private fun configureAndLaunchScratch(fileName: String, isRepl: Boolean, isWorksheet: Boolean) {
|
||||
val sourceFile = File(testDataPath, fileName)
|
||||
val fileText = sourceFile.readText().inlinePropertiesValues(isRepl)
|
||||
|
||||
if (isWorksheet) {
|
||||
configureWorksheetByText(sourceFile.name, fileText)
|
||||
} else {
|
||||
configureScratchByText(sourceFile.name, fileText)
|
||||
}
|
||||
|
||||
if (!KotlinHighlightingUtil.shouldHighlight(myFixture.file)) error("Highlighting for scratch file is switched off")
|
||||
|
||||
launchScratch()
|
||||
waitUntilScratchFinishes(isRepl)
|
||||
}
|
||||
|
||||
private fun getExpectedFile(fileName: String, isRepl: Boolean, suffix: String): File {
|
||||
val expectedFileName = if (isRepl) {
|
||||
fileName.replace(".kts", ".repl.$suffix")
|
||||
} else {
|
||||
fileName.replace(".kts", ".comp.$suffix")
|
||||
}
|
||||
|
||||
return File(testDataPath, expectedFileName)
|
||||
}
|
||||
|
||||
protected fun String.inlinePropertiesValues(
|
||||
isRepl: Boolean = false,
|
||||
isInteractiveMode: Boolean = false
|
||||
): String {
|
||||
return replace("~REPL_MODE~", isRepl.toString()).replace("~INTERACTIVE_MODE~", isInteractiveMode.toString())
|
||||
}
|
||||
|
||||
protected fun getFileTextWithInlays(): String {
|
||||
val doc = myFixture.getDocument(myFixture.file) ?: error("Document for ${myFixture.file.name} is null")
|
||||
val actualOutput = StringBuilder(myFixture.file.text)
|
||||
for (line in doc.lineCount - 1 downTo 0) {
|
||||
getInlays(doc.getLineStartOffset(line), doc.getLineEndOffset(line))
|
||||
.forEach { inlay ->
|
||||
val str = inlay.toString()
|
||||
val offset = doc.getLineEndOffset(line)
|
||||
actualOutput.insert(
|
||||
offset,
|
||||
"${str.takeWhile { it.isWhitespace() }}// ${str.trim()}"
|
||||
)
|
||||
}
|
||||
}
|
||||
return actualOutput.toString().trim()
|
||||
}
|
||||
|
||||
private fun getPreviewTextWithFoldings(): String {
|
||||
val scratchFileEditor = getScratchEditorForSelectedFile(myManager, myFixture.file.virtualFile)
|
||||
?: error("Couldn't find scratch panel")
|
||||
|
||||
val previewEditor = scratchFileEditor.getPreviewEditor()
|
||||
return getFoldingData(previewEditor.editor, withCollapseStatus = false)
|
||||
}
|
||||
|
||||
protected fun getInlays(start: Int = 0, end: Int = myFixture.file.textLength): List<InlayScratchFileRenderer> {
|
||||
val inlineElementsInRange = myFixture.editor.inlayModel
|
||||
.getAfterLineEndElementsInRange(start, end)
|
||||
.filter { it.renderer is InlayScratchFileRenderer }
|
||||
return inlineElementsInRange.map { it.renderer as InlayScratchFileRenderer }
|
||||
}
|
||||
|
||||
protected fun configureScratchByText(name: String, text: String): ScratchFile {
|
||||
val scratchVirtualFile = ScratchRootType.getInstance().createScratchFile(
|
||||
project,
|
||||
name,
|
||||
KotlinLanguage.INSTANCE,
|
||||
text,
|
||||
ScratchFileService.Option.create_if_missing
|
||||
) ?: error("Couldn't create scratch file")
|
||||
|
||||
myFixture.openFileInEditor(scratchVirtualFile)
|
||||
|
||||
ScriptConfigurationManager.updateScriptDependenciesSynchronously(myFixture.file)
|
||||
|
||||
val scratchFileEditor = getScratchEditorForSelectedFile(myManager, myFixture.file.virtualFile)
|
||||
?: error("Couldn't find scratch file")
|
||||
|
||||
configureOptions(scratchFileEditor, text, myFixture.module)
|
||||
|
||||
return scratchFileEditor.scratchFile
|
||||
}
|
||||
|
||||
protected fun configureWorksheetByText(name: String, text: String): ScratchFile {
|
||||
val worksheetFile = myFixture.configureByText(name, text).virtualFile
|
||||
|
||||
ScriptConfigurationManager.updateScriptDependenciesSynchronously(myFixture.file)
|
||||
|
||||
val scratchFileEditor = getScratchEditorForSelectedFile(myManager, myFixture.file.virtualFile)
|
||||
?: error("Couldn't find scratch panel")
|
||||
|
||||
// We want to check that correct module is selected automatically,
|
||||
// that's why we set `module` to null so it wouldn't be changed
|
||||
configureOptions(scratchFileEditor, text, null)
|
||||
|
||||
return scratchFileEditor.scratchFile
|
||||
}
|
||||
|
||||
|
||||
protected fun launchScratch() {
|
||||
val action = RunScratchAction()
|
||||
launchAction(action)
|
||||
}
|
||||
|
||||
protected fun launchAction(action: AnAction) {
|
||||
val e = getActionEvent(myFixture.file.virtualFile, action)
|
||||
action.beforeActionPerformedUpdate(e)
|
||||
Assert.assertTrue(e.presentation.isEnabled && e.presentation.isVisible)
|
||||
action.actionPerformed(e)
|
||||
}
|
||||
|
||||
protected fun waitUntilScratchFinishes(shouldStopRepl: Boolean = true) {
|
||||
UIUtil.dispatchAllInvocationEvents()
|
||||
|
||||
val start = System.currentTimeMillis()
|
||||
// wait until output is displayed in editor or for 1 minute
|
||||
while (ScratchCompilationSupport.isAnyInProgress()) {
|
||||
if ((System.currentTimeMillis() - start) > TIME_OUT) {
|
||||
LOG.warn("Waiting timeout $TIME_OUT ms is exceed")
|
||||
break
|
||||
}
|
||||
Thread.sleep(100)
|
||||
}
|
||||
|
||||
if (shouldStopRepl) stopReplProcess()
|
||||
|
||||
UIUtil.dispatchAllInvocationEvents()
|
||||
}
|
||||
|
||||
protected fun stopReplProcess() {
|
||||
if (myFixture.file != null) {
|
||||
val scratchFile = getScratchEditorForSelectedFile(myManager, myFixture.file.virtualFile)?.scratchFile
|
||||
?: error("Couldn't find scratch panel")
|
||||
scratchFile.replScratchExecutor?.stopAndWait()
|
||||
}
|
||||
|
||||
UIUtil.dispatchAllInvocationEvents()
|
||||
}
|
||||
|
||||
private fun getActionEvent(virtualFile: VirtualFile, action: AnAction): TestActionEvent {
|
||||
val context = MapDataContext()
|
||||
context.put(CommonDataKeys.VIRTUAL_FILE_ARRAY, arrayOf(virtualFile))
|
||||
context.put(CommonDataKeys.PROJECT, project)
|
||||
context.put(CommonDataKeys.EDITOR, myFixture.editor)
|
||||
return TestActionEvent(context, action)
|
||||
}
|
||||
|
||||
protected fun testScratchText(): String {
|
||||
return File(testDataPath, "idea/scripting-support/testData/scratch/custom/test_scratch.kts").readText()
|
||||
}
|
||||
|
||||
override fun getTestDataPath() = KtTestUtil.getHomeDirectory()
|
||||
|
||||
|
||||
override fun getProjectDescriptor(): com.intellij.testFramework.LightProjectDescriptor {
|
||||
val testName = getTestName(false)
|
||||
|
||||
return when {
|
||||
testName.endsWith("WithKotlinTest") -> INSTANCE_WITH_KOTLIN_TEST
|
||||
testName.endsWith("NoRuntime") -> INSTANCE_WITHOUT_RUNTIME
|
||||
testName.endsWith("ScriptRuntime") -> INSTANCE_WITH_SCRIPT_RUNTIME
|
||||
else -> KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE_FULL_JDK
|
||||
}
|
||||
}
|
||||
|
||||
override fun setUp() {
|
||||
super.setUp()
|
||||
|
||||
VfsRootAccess.allowRootAccess(KtTestUtil.getHomeDirectory())
|
||||
|
||||
PluginTestCaseBase.addJdk(myFixture.projectDisposable) { PluginTestCaseBase.fullJdk() }
|
||||
}
|
||||
|
||||
override fun tearDown() {
|
||||
super.tearDown()
|
||||
|
||||
VfsRootAccess.disallowRootAccess(KtTestUtil.getHomeDirectory())
|
||||
|
||||
ScratchFileService.getInstance().scratchesMapping.mappings.forEach { file, _ ->
|
||||
runWriteAction { file.delete(this) }
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TIME_OUT = 60000 // 1 min
|
||||
|
||||
private val INSTANCE_WITH_KOTLIN_TEST = object : KotlinWithJdkAndRuntimeLightProjectDescriptor(
|
||||
arrayListOf(
|
||||
ForTestCompileRuntime.runtimeJarForTests(),
|
||||
PathUtil.kotlinPathsForDistDirectory.kotlinTestPath
|
||||
)
|
||||
) {
|
||||
override fun getSdk() = PluginTestCaseBase.fullJdk()
|
||||
}
|
||||
|
||||
private val INSTANCE_WITHOUT_RUNTIME = object : KotlinLightProjectDescriptor() {
|
||||
override fun getSdk() = PluginTestCaseBase.fullJdk()
|
||||
}
|
||||
|
||||
private val INSTANCE_WITH_SCRIPT_RUNTIME = object : KotlinWithJdkAndRuntimeLightProjectDescriptor(
|
||||
arrayListOf(
|
||||
ForTestCompileRuntime.runtimeJarForTests(),
|
||||
ForTestCompileRuntime.scriptRuntimeJarForTests()
|
||||
)
|
||||
) {
|
||||
override fun getSdk() = PluginTestCaseBase.fullJdk()
|
||||
}
|
||||
|
||||
fun configureOptions(
|
||||
scratchFileEditor: KtScratchFileEditorWithPreview,
|
||||
fileText: String,
|
||||
module: Module?
|
||||
) {
|
||||
val scratchFile = scratchFileEditor.scratchFile
|
||||
|
||||
if (InTextDirectivesUtils.getPrefixedBoolean(fileText, "// INTERACTIVE_MODE: ") != true) {
|
||||
scratchFile.saveOptions { copy(isInteractiveMode = false) }
|
||||
}
|
||||
|
||||
if (InTextDirectivesUtils.getPrefixedBoolean(fileText, "// REPL_MODE: ") == true) {
|
||||
scratchFile.saveOptions { copy(isRepl = true) }
|
||||
}
|
||||
|
||||
if (module != null && !InTextDirectivesUtils.isDirectiveDefined(fileText, "// NO_MODULE")) {
|
||||
scratchFile.setModule(module)
|
||||
}
|
||||
|
||||
val isPreviewEnabled = InTextDirectivesUtils.getPrefixedBoolean(fileText, "// PREVIEW_ENABLED: ") == true
|
||||
scratchFileEditor.setPreviewEnabled(isPreviewEnabled)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.scratch
|
||||
|
||||
import com.intellij.codeInsight.daemon.LineMarkerInfo
|
||||
import com.intellij.ide.scratch.ScratchFileService
|
||||
import com.intellij.ide.scratch.ScratchRootType
|
||||
import com.intellij.openapi.editor.Document
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.testFramework.ExpectedHighlightingData
|
||||
import com.intellij.testFramework.FileEditorManagerTestCase
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||
import org.jetbrains.kotlin.idea.codeInsight.AbstractLineMarkersTest
|
||||
import org.jetbrains.kotlin.idea.core.script.ScriptConfigurationManager
|
||||
import org.jetbrains.kotlin.idea.scratch.AbstractScratchRunActionTest.Companion.configureOptions
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import java.io.File
|
||||
|
||||
abstract class AbstractScratchLineMarkersTest : FileEditorManagerTestCase() {
|
||||
fun doScratchTest(path: String) {
|
||||
val fileText = FileUtil.loadFile(File(path))
|
||||
|
||||
val scratchVirtualFile = ScratchRootType.getInstance().createScratchFile(
|
||||
project,
|
||||
"scratch.kts",
|
||||
KotlinLanguage.INSTANCE,
|
||||
fileText,
|
||||
ScratchFileService.Option.create_if_missing
|
||||
) ?: error("Couldn't create scratch file")
|
||||
|
||||
myFixture.openFileInEditor(scratchVirtualFile)
|
||||
|
||||
ScriptConfigurationManager.updateScriptDependenciesSynchronously(myFixture.file)
|
||||
|
||||
val scratchFileEditor = getScratchEditorForSelectedFile(FileEditorManager.getInstance(project), myFixture.file.virtualFile)
|
||||
?: error("Couldn't find scratch panel")
|
||||
|
||||
configureOptions(scratchFileEditor, fileText, null)
|
||||
|
||||
val project = myFixture.project
|
||||
val document = myFixture.editor.document
|
||||
|
||||
val data = ExpectedHighlightingData(document, false, false, false, myFixture.file)
|
||||
data.init()
|
||||
|
||||
PsiDocumentManager.getInstance(project).commitAllDocuments()
|
||||
|
||||
val markers = doAndCheckHighlighting(document, data, File(path))
|
||||
|
||||
AbstractLineMarkersTest.assertNavigationElements(myFixture.project, myFixture.file as KtFile, markers)
|
||||
}
|
||||
|
||||
override fun tearDown() {
|
||||
super.tearDown()
|
||||
|
||||
ScratchFileService.getInstance().scratchesMapping.mappings.forEach { file, _ ->
|
||||
runWriteAction { file.delete(this) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun doAndCheckHighlighting(
|
||||
documentToAnalyze: Document, expectedHighlighting: ExpectedHighlightingData, expectedFile: File
|
||||
): List<LineMarkerInfo<*>> {
|
||||
myFixture.doHighlighting()
|
||||
|
||||
return AbstractLineMarkersTest.checkHighlighting(myFixture.project, documentToAnalyze, expectedHighlighting, expectedFile)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
class IDESettingsFUSCollector {
|
||||
// Not whitelisted
|
||||
}
|
||||
@@ -14,7 +14,7 @@ import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import java.util.function.Consumer
|
||||
|
||||
// FIX ME WHEN BUNCH 201 REMOVED
|
||||
|
||||
class KotlinDocumentationProvider : KotlinDocumentationProviderCompatBase() {
|
||||
|
||||
override fun collectDocComments(file: PsiFile, sink: Consumer<PsiDocCommentBase>) {
|
||||
|
||||
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import java.util.function.Consumer
|
||||
|
||||
// FIX ME WHEN BUNCH 201 REMOVED
|
||||
class KotlinDocumentationProvider : KotlinDocumentationProviderCompatBase() {
|
||||
|
||||
override fun collectDocComments(file: PsiFile, sink: Consumer<in PsiDocCommentBase>) {
|
||||
|
||||
@@ -34,18 +34,14 @@ import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm;
|
||||
import org.jetbrains.kotlin.resolve.konan.diagnostics.ErrorsNative;
|
||||
|
||||
import static org.jetbrains.kotlin.idea.TestResourceBundleKt.registerAdditionalResourceBundleInTests;
|
||||
|
||||
public class PluginStartupActivity implements StartupActivity {
|
||||
private static final Logger LOG = Logger.getInstance(PluginStartupActivity.class);
|
||||
|
||||
@Override
|
||||
public void runActivity(@NotNull Project project) {
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
registerAdditionalResourceBundleInTests();
|
||||
}
|
||||
|
||||
StartupCompatKt.runActivity(project);
|
||||
StartupKt.runActivity(project);
|
||||
PluginStartupService.Companion.getInstance(project).register(project);
|
||||
|
||||
project.getMessageBus().connect().subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootListener() {
|
||||
|
||||
@@ -1,274 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.actions
|
||||
|
||||
import com.intellij.ide.actions.CreateFileFromTemplateAction
|
||||
import com.intellij.ide.actions.CreateFileFromTemplateDialog
|
||||
import com.intellij.ide.actions.CreateFromTemplateAction
|
||||
import com.intellij.ide.fileTemplates.FileTemplate
|
||||
import com.intellij.ide.fileTemplates.FileTemplateManager
|
||||
import com.intellij.ide.fileTemplates.actions.AttributesDefaults
|
||||
import com.intellij.ide.fileTemplates.ui.CreateFromTemplateDialog
|
||||
import com.intellij.openapi.actionSystem.DataContext
|
||||
import com.intellij.openapi.actionSystem.LangDataKeys
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys
|
||||
import com.intellij.openapi.editor.LogicalPosition
|
||||
import com.intellij.openapi.extensions.ExtensionPointName
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.module.ModuleUtilCore
|
||||
import com.intellij.openapi.project.DumbAware
|
||||
import com.intellij.openapi.project.DumbService
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.roots.ProjectRootManager
|
||||
import com.intellij.openapi.ui.InputValidatorEx
|
||||
import com.intellij.psi.PsiDirectory
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.util.IncorrectOperationException
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.idea.KotlinBundle
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.idea.KotlinIcons
|
||||
import org.jetbrains.kotlin.idea.project.getLanguageVersionSettings
|
||||
import org.jetbrains.kotlin.idea.statistics.FUSEventGroups
|
||||
import org.jetbrains.kotlin.idea.statistics.KotlinFUSLogger
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.parsing.KotlinParserDefinition.Companion.STD_SCRIPT_SUFFIX
|
||||
import org.jetbrains.kotlin.psi.KtClass
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
||||
import java.util.*
|
||||
|
||||
class NewKotlinFileAction : CreateFileFromTemplateAction(
|
||||
KotlinBundle.message("action.new.file.text"),
|
||||
KotlinBundle.message("action.new.file.description"),
|
||||
KotlinFileType.INSTANCE.icon
|
||||
), DumbAware {
|
||||
override fun postProcess(createdElement: PsiFile?, templateName: String?, customProperties: Map<String, String>?) {
|
||||
super.postProcess(createdElement, templateName, customProperties)
|
||||
|
||||
val module = ModuleUtilCore.findModuleForPsiElement(createdElement!!)
|
||||
|
||||
if (createdElement is KtFile) {
|
||||
if (module != null) {
|
||||
for (hook in NewKotlinFileHook.EP_NAME.extensions) {
|
||||
hook.postProcess(createdElement, module)
|
||||
}
|
||||
}
|
||||
|
||||
val ktClass = createdElement.declarations.singleOrNull() as? KtNamedDeclaration
|
||||
if (ktClass != null) {
|
||||
CreateFromTemplateAction.moveCaretAfterNameIdentifier(ktClass)
|
||||
} else {
|
||||
val editor = FileEditorManager.getInstance(createdElement.project).selectedTextEditor ?: return
|
||||
if (editor.document == createdElement.viewProvider.document) {
|
||||
val lineCount = editor.document.lineCount
|
||||
if (lineCount > 0) {
|
||||
editor.caretModel.moveToLogicalPosition(LogicalPosition(lineCount - 1, 0))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun buildDialog(project: Project, directory: PsiDirectory, builder: CreateFileFromTemplateDialog.Builder) {
|
||||
builder.setTitle(KotlinBundle.message("action.new.file.dialog.title"))
|
||||
.addKind(
|
||||
KotlinBundle.message("action.new.file.dialog.class.title"),
|
||||
KotlinIcons.CLASS,
|
||||
"Kotlin Class"
|
||||
)
|
||||
.addKind(
|
||||
KotlinBundle.message("action.new.file.dialog.file.title"),
|
||||
KotlinFileType.INSTANCE.icon,
|
||||
"Kotlin File"
|
||||
)
|
||||
.addKind(
|
||||
KotlinBundle.message("action.new.file.dialog.interface.title"),
|
||||
KotlinIcons.INTERFACE,
|
||||
"Kotlin Interface"
|
||||
)
|
||||
|
||||
if (project.getLanguageVersionSettings().supportsFeature(LanguageFeature.SealedInterfaces)) {
|
||||
builder.addKind(
|
||||
KotlinBundle.message("action.new.file.dialog.sealed.interface.title"),
|
||||
KotlinIcons.INTERFACE,
|
||||
"Kotlin Sealed Interface"
|
||||
)
|
||||
}
|
||||
|
||||
builder.addKind(
|
||||
KotlinBundle.message("action.new.file.dialog.data.class.title"),
|
||||
KotlinIcons.CLASS,
|
||||
"Kotlin Data Class"
|
||||
)
|
||||
.addKind(
|
||||
KotlinBundle.message("action.new.file.dialog.enum.title"),
|
||||
KotlinIcons.ENUM,
|
||||
"Kotlin Enum"
|
||||
)
|
||||
.addKind(
|
||||
KotlinBundle.message("action.new.file.dialog.sealed.class.title"),
|
||||
KotlinIcons.CLASS,
|
||||
"Kotlin Sealed Class"
|
||||
)
|
||||
.addKind(
|
||||
KotlinBundle.message("action.new.file.dialog.annotation.title"),
|
||||
KotlinIcons.ANNOTATION,
|
||||
"Kotlin Annotation"
|
||||
)
|
||||
.addKind(
|
||||
KotlinBundle.message("action.new.file.dialog.object.title"),
|
||||
KotlinIcons.OBJECT,
|
||||
"Kotlin Object"
|
||||
)
|
||||
|
||||
builder.setValidator(NameValidator)
|
||||
}
|
||||
|
||||
override fun getActionName(directory: PsiDirectory, newName: String, templateName: String): String =
|
||||
KotlinBundle.message("action.new.file.text")
|
||||
|
||||
override fun isAvailable(dataContext: DataContext): Boolean {
|
||||
if (super.isAvailable(dataContext)) {
|
||||
val ideView = LangDataKeys.IDE_VIEW.getData(dataContext)!!
|
||||
val project = PlatformDataKeys.PROJECT.getData(dataContext)!!
|
||||
val projectFileIndex = ProjectRootManager.getInstance(project).fileIndex
|
||||
return ideView.directories.any { projectFileIndex.isInSourceContent(it.virtualFile) }
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
override fun hashCode(): Int = 0
|
||||
|
||||
override fun equals(other: Any?): Boolean = other is NewKotlinFileAction
|
||||
|
||||
override fun startInWriteAction() = false
|
||||
|
||||
override fun createFileFromTemplate(name: String, template: FileTemplate, dir: PsiDirectory) =
|
||||
createFileFromTemplateWithStat(name, template, dir)
|
||||
|
||||
companion object {
|
||||
private object NameValidator : InputValidatorEx {
|
||||
override fun getErrorText(inputString: String): String? {
|
||||
if (inputString.trim().isEmpty()) {
|
||||
return KotlinBundle.message("action.new.file.error.empty.name")
|
||||
}
|
||||
|
||||
val parts: List<String> = inputString.split(*FQNAME_SEPARATORS)
|
||||
if (parts.any { it.trim().isEmpty() }) {
|
||||
return KotlinBundle.message("action.new.file.error.empty.name.part")
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
override fun checkInput(inputString: String): Boolean = true
|
||||
|
||||
override fun canClose(inputString: String): Boolean = getErrorText(inputString) == null
|
||||
}
|
||||
|
||||
@get:TestOnly
|
||||
val nameValidator: InputValidatorEx
|
||||
get() = NameValidator
|
||||
|
||||
private fun findOrCreateTarget(dir: PsiDirectory, name: String, directorySeparators: CharArray): Pair<String, PsiDirectory> {
|
||||
var className = removeKotlinExtensionIfPresent(name)
|
||||
var targetDir = dir
|
||||
|
||||
for (splitChar in directorySeparators) {
|
||||
if (splitChar in className) {
|
||||
val names = className.trim().split(splitChar)
|
||||
|
||||
for (dirName in names.dropLast(1)) {
|
||||
targetDir = targetDir.findSubdirectory(dirName) ?: runWriteAction {
|
||||
targetDir.createSubdirectory(dirName)
|
||||
}
|
||||
}
|
||||
|
||||
className = names.last()
|
||||
break
|
||||
}
|
||||
}
|
||||
return Pair(className, targetDir)
|
||||
}
|
||||
|
||||
private fun removeKotlinExtensionIfPresent(name: String): String = when {
|
||||
name.endsWith(".$KOTLIN_WORKSHEET_EXTENSION") -> name.removeSuffix(".$KOTLIN_WORKSHEET_EXTENSION")
|
||||
name.endsWith(".$STD_SCRIPT_SUFFIX") -> name.removeSuffix(".$STD_SCRIPT_SUFFIX")
|
||||
name.endsWith(".${KotlinFileType.EXTENSION}") -> name.removeSuffix(".${KotlinFileType.EXTENSION}")
|
||||
else -> name
|
||||
}
|
||||
|
||||
private fun createFromTemplate(dir: PsiDirectory, className: String, template: FileTemplate): PsiFile? {
|
||||
val project = dir.project
|
||||
val defaultProperties = FileTemplateManager.getInstance(project).defaultProperties
|
||||
|
||||
val properties = Properties(defaultProperties)
|
||||
|
||||
val element = try {
|
||||
CreateFromTemplateDialog(
|
||||
project, dir, template,
|
||||
AttributesDefaults(className).withFixedName(true),
|
||||
properties
|
||||
).create()
|
||||
} catch (e: IncorrectOperationException) {
|
||||
throw e
|
||||
} catch (e: Exception) {
|
||||
LOG.error(e)
|
||||
return null
|
||||
}
|
||||
|
||||
return element?.containingFile
|
||||
}
|
||||
|
||||
private val FILE_SEPARATORS = charArrayOf('/', '\\')
|
||||
private val FQNAME_SEPARATORS = charArrayOf('/', '\\', '.')
|
||||
|
||||
fun createFileFromTemplateWithStat(name: String, template: FileTemplate, dir: PsiDirectory): PsiFile? {
|
||||
KotlinFUSLogger.log(FUSEventGroups.NewFileTemplate, template.name)
|
||||
return createFileFromTemplate(name, template, dir)
|
||||
}
|
||||
|
||||
|
||||
fun createFileFromTemplate(name: String, template: FileTemplate, dir: PsiDirectory): PsiFile? {
|
||||
val directorySeparators = when (template.name) {
|
||||
"Kotlin File" -> FILE_SEPARATORS
|
||||
else -> FQNAME_SEPARATORS
|
||||
}
|
||||
val (className, targetDir) = findOrCreateTarget(dir, name, directorySeparators)
|
||||
|
||||
val service = DumbService.getInstance(dir.project)
|
||||
service.isAlternativeResolveEnabled = true
|
||||
try {
|
||||
val psiFile = createFromTemplate(targetDir, className, template)
|
||||
if (psiFile is KtFile) {
|
||||
val singleClass = psiFile.declarations.singleOrNull() as? KtClass
|
||||
if (singleClass != null && !singleClass.isEnum() && !singleClass.isInterface() && name.contains("Abstract")) {
|
||||
runWriteAction {
|
||||
singleClass.addModifier(KtTokens.ABSTRACT_KEYWORD)
|
||||
}
|
||||
}
|
||||
}
|
||||
return psiFile
|
||||
} finally {
|
||||
service.isAlternativeResolveEnabled = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract class NewKotlinFileHook {
|
||||
companion object {
|
||||
val EP_NAME: ExtensionPointName<NewKotlinFileHook> =
|
||||
ExtensionPointName.create<NewKotlinFileHook>("org.jetbrains.kotlin.newFileHook")
|
||||
}
|
||||
|
||||
abstract fun postProcess(createdElement: KtFile, module: Module)
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.codeInsight
|
||||
|
||||
import com.intellij.ide.ui.UISettings
|
||||
import com.intellij.ui.breadcrumbs.BreadcrumbsProvider
|
||||
|
||||
// FIX ME WHEN BUNCH 201 REMOVED
|
||||
abstract class BreadcrumbsProviderCompatBase : BreadcrumbsProvider {
|
||||
override fun isShownByDefault(): Boolean =
|
||||
!UISettings.instance.showMembersInNavigationBar
|
||||
}
|
||||
@@ -5,11 +5,13 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.codeInsight
|
||||
|
||||
import com.intellij.ide.ui.UISettings
|
||||
import com.intellij.openapi.project.DumbService
|
||||
import com.intellij.openapi.project.IndexNotReadyException
|
||||
import com.intellij.psi.ElementDescriptionUtil
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.refactoring.util.RefactoringDescriptionLocation
|
||||
import com.intellij.ui.breadcrumbs.BreadcrumbsProvider
|
||||
import com.intellij.usageView.UsageViewShortNameLocation
|
||||
import org.jetbrains.kotlin.KtNodeTypes
|
||||
import org.jetbrains.kotlin.idea.KotlinBundle
|
||||
@@ -23,8 +25,7 @@ import org.jetbrains.kotlin.renderer.render
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getValueArgumentsInParentheses
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
// FIX ME WHEN BUNCH 201 REMOVED
|
||||
class KotlinBreadcrumbsInfoProvider : BreadcrumbsProviderCompatBase() {
|
||||
class KotlinBreadcrumbsInfoProvider : BreadcrumbsProvider {
|
||||
private abstract class ElementHandler<TElement : KtElement>(val type: KClass<TElement>) {
|
||||
abstract fun elementInfo(element: TElement): String
|
||||
abstract fun elementTooltip(element: TElement): String
|
||||
@@ -428,6 +429,9 @@ class KotlinBreadcrumbsInfoProvider : BreadcrumbsProviderCompatBase() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun isShownByDefault(): Boolean =
|
||||
!UISettings.instance.showMembersInNavigationBar
|
||||
|
||||
private companion object {
|
||||
enum class TextKind(val maxTextLength: Int) {
|
||||
INFO(16), TOOLTIP(100)
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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
|
||||
|
||||
internal object MLCompletionForKotlin {
|
||||
const val isAvailable: Boolean = false
|
||||
|
||||
var isEnabled: Boolean
|
||||
get() = false
|
||||
set(value) {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
}
|
||||
@@ -1,174 +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.highlighter
|
||||
|
||||
import com.intellij.codeInsight.highlighting.HighlightUsagesHandlerBase
|
||||
import com.intellij.codeInsight.highlighting.HighlightUsagesHandlerFactoryBase
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
||||
import com.intellij.psi.tree.TokenSet
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import com.intellij.util.Consumer
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.parents
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsResultOfLambda
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
|
||||
class KotlinHighlightExitPointsHandlerFactory : HighlightUsagesHandlerFactoryBase() {
|
||||
companion object {
|
||||
private val RETURN_AND_THROW = TokenSet.create(KtTokens.RETURN_KEYWORD, KtTokens.THROW_KEYWORD)
|
||||
|
||||
private fun getOnReturnOrThrowUsageHandler(editor: Editor, file: PsiFile, target: PsiElement): HighlightUsagesHandlerBase<*>? {
|
||||
if (target !is LeafPsiElement || target.elementType !in RETURN_AND_THROW) {
|
||||
return null
|
||||
}
|
||||
|
||||
val returnOrThrow = PsiTreeUtil.getParentOfType<KtExpression>(
|
||||
target,
|
||||
KtReturnExpression::class.java,
|
||||
KtThrowExpression::class.java
|
||||
) ?: return null
|
||||
|
||||
return OnExitUsagesHandler(editor, file, returnOrThrow)
|
||||
}
|
||||
|
||||
private fun getOnLambdaCallUsageHandler(editor: Editor, file: PsiFile, target: PsiElement): HighlightUsagesHandlerBase<*>? {
|
||||
if (target !is LeafPsiElement || target.elementType != KtTokens.IDENTIFIER) {
|
||||
return null
|
||||
}
|
||||
|
||||
val refExpr = target.parent as? KtNameReferenceExpression ?: return null
|
||||
val call = refExpr.parent as? KtCallExpression ?: return null
|
||||
if (call.calleeExpression != refExpr) return null
|
||||
|
||||
val lambda = call.lambdaArguments.singleOrNull() ?: return null
|
||||
val literal = lambda.getLambdaExpression()?.functionLiteral ?: return null
|
||||
|
||||
return OnExitUsagesHandler(editor, file, literal, highlightReferences = true)
|
||||
}
|
||||
}
|
||||
|
||||
override fun createHighlightUsagesHandler(editor: Editor, file: PsiFile, target: PsiElement): HighlightUsagesHandlerBase<*>? {
|
||||
return getOnReturnOrThrowUsageHandler(editor, file, target)
|
||||
?: getOnLambdaCallUsageHandler(editor, file, target)
|
||||
}
|
||||
|
||||
private class OnExitUsagesHandler(editor: Editor, file: PsiFile, val target: KtExpression, val highlightReferences: Boolean = false) :
|
||||
HighlightUsagesHandlerBase<PsiElement>(editor, file) {
|
||||
|
||||
override fun getTargets() = listOf(target)
|
||||
|
||||
override fun selectTargets(targets: MutableList<PsiElement>, selectionConsumer: Consumer<MutableList<PsiElement>>) {
|
||||
selectionConsumer.consume(targets)
|
||||
}
|
||||
|
||||
override fun computeUsages(targets: MutableList<PsiElement>?) {
|
||||
val relevantFunction: KtDeclarationWithBody? =
|
||||
if (target is KtFunctionLiteral) {
|
||||
target
|
||||
} else {
|
||||
target.getRelevantDeclaration()
|
||||
}
|
||||
|
||||
relevantFunction?.accept(object : KtVisitorVoid() {
|
||||
override fun visitKtElement(element: KtElement) {
|
||||
element.acceptChildren(this)
|
||||
}
|
||||
|
||||
override fun visitExpression(expression: KtExpression) {
|
||||
if (relevantFunction is KtFunctionLiteral) {
|
||||
if (occurrenceForFunctionLiteralReturnExpression(expression)) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
super.visitExpression(expression)
|
||||
}
|
||||
|
||||
private fun occurrenceForFunctionLiteralReturnExpression(expression: KtExpression): Boolean {
|
||||
if (!KtPsiUtil.isStatement(expression)) return false
|
||||
|
||||
if (expression is KtIfExpression || expression is KtWhenExpression || expression is KtBlockExpression) {
|
||||
return false
|
||||
}
|
||||
|
||||
val bindingContext = expression.analyze(BodyResolveMode.FULL)
|
||||
if (!expression.isUsedAsResultOfLambda(bindingContext)) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (expression.getRelevantDeclaration() != relevantFunction) {
|
||||
return false
|
||||
}
|
||||
|
||||
addOccurrence(expression)
|
||||
return true
|
||||
}
|
||||
|
||||
private fun visitReturnOrThrow(expression: KtExpression) {
|
||||
if (expression.getRelevantDeclaration() == relevantFunction) {
|
||||
addOccurrence(expression)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitReturnExpression(expression: KtReturnExpression) {
|
||||
visitReturnOrThrow(expression)
|
||||
}
|
||||
|
||||
override fun visitThrowExpression(expression: KtThrowExpression) {
|
||||
visitReturnOrThrow(expression)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun highlightReferences() = highlightReferences
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtExpression.getRelevantDeclaration(): KtDeclarationWithBody? {
|
||||
if (this is KtReturnExpression) {
|
||||
(this.getTargetLabel()?.mainReference?.resolve() as? KtFunction)?.let {
|
||||
return it
|
||||
}
|
||||
}
|
||||
|
||||
if (this is KtThrowExpression || this is KtReturnExpression) {
|
||||
for (parent in parents) {
|
||||
if (parent is KtDeclarationWithBody) {
|
||||
if (parent is KtPropertyAccessor) {
|
||||
return parent
|
||||
}
|
||||
|
||||
if (InlineUtil.canBeInlineArgument(parent) &&
|
||||
!InlineUtil.isInlinedArgument(parent as KtFunction, parent.analyze(BodyResolveMode.FULL), false)
|
||||
) {
|
||||
return parent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
return parents.filterIsInstance<KtDeclarationWithBody>().firstOrNull()
|
||||
}
|
||||
@@ -1,58 +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.highlighter
|
||||
|
||||
import com.intellij.codeInsight.highlighting.HighlightUsagesHandlerBase
|
||||
import com.intellij.codeInsight.highlighting.HighlightUsagesHandlerFactoryBase
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
||||
import com.intellij.util.Consumer
|
||||
import org.jetbrains.kotlin.idea.intentions.getLambdaByImplicitItReference
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||
import org.jetbrains.kotlin.psi.KtTreeVisitorVoid
|
||||
|
||||
class KotlinHighlightImplicitItHandlerFactory : HighlightUsagesHandlerFactoryBase() {
|
||||
override fun createHighlightUsagesHandler(editor: Editor, file: PsiFile, target: PsiElement): HighlightUsagesHandlerBase<*>? {
|
||||
if (!(target is LeafPsiElement && target.elementType == KtTokens.IDENTIFIER)) return null
|
||||
val refExpr = target.parent as? KtNameReferenceExpression ?: return null
|
||||
val lambda = getLambdaByImplicitItReference(refExpr) ?: return null
|
||||
return object : HighlightUsagesHandlerBase<KtNameReferenceExpression>(editor, file) {
|
||||
override fun getTargets() = listOf(refExpr)
|
||||
|
||||
override fun selectTargets(
|
||||
targets: MutableList<KtNameReferenceExpression>,
|
||||
selectionConsumer: Consumer<MutableList<KtNameReferenceExpression>>
|
||||
) = selectionConsumer.consume(targets)
|
||||
|
||||
override fun computeUsages(targets: MutableList<KtNameReferenceExpression>?) {
|
||||
lambda.accept(
|
||||
object : KtTreeVisitorVoid() {
|
||||
override fun visitSimpleNameExpression(expression: KtSimpleNameExpression) {
|
||||
if (expression is KtNameReferenceExpression && getLambdaByImplicitItReference(expression) == lambda) {
|
||||
addOccurrence(expression)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,189 +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.highlighter
|
||||
|
||||
import com.intellij.codeHighlighting.Pass
|
||||
import com.intellij.codeInsight.daemon.LineMarkerInfo
|
||||
import com.intellij.codeInsight.daemon.LineMarkerProvider
|
||||
import com.intellij.icons.AllIcons
|
||||
import com.intellij.openapi.editor.markup.GutterIconRenderer
|
||||
import com.intellij.openapi.progress.ProgressManager
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.idea.KotlinBundle
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.highlighter.markers.LineMarkerInfos
|
||||
import org.jetbrains.kotlin.idea.inspections.RecursivePropertyAccessorInspection
|
||||
import org.jetbrains.kotlin.idea.util.getReceiverTargetDescriptor
|
||||
import org.jetbrains.kotlin.lexer.KtToken
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.parents
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.Receiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import java.util.*
|
||||
|
||||
class KotlinRecursiveCallLineMarkerProvider : LineMarkerProvider {
|
||||
override fun getLineMarkerInfo(element: PsiElement) = null
|
||||
|
||||
override fun collectSlowLineMarkers(elements: MutableList<PsiElement>, result: LineMarkerInfos) {
|
||||
val markedLineNumbers = HashSet<Int>()
|
||||
|
||||
for (element in elements) {
|
||||
ProgressManager.checkCanceled()
|
||||
if (element is KtElement) {
|
||||
val lineNumber = element.getLineNumber()
|
||||
if (lineNumber !in markedLineNumbers && isRecursiveCall(element)) {
|
||||
markedLineNumbers.add(lineNumber)
|
||||
result.add(RecursiveMethodCallMarkerInfo(getElementForLineMark(element)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getEnclosingFunction(element: KtElement, stopOnNonInlinedLambdas: Boolean): KtNamedFunction? {
|
||||
for (parent in element.parents) {
|
||||
when (parent) {
|
||||
is KtFunctionLiteral -> if (stopOnNonInlinedLambdas && !InlineUtil.isInlinedArgument(
|
||||
parent,
|
||||
parent.analyze(),
|
||||
false
|
||||
)
|
||||
) return null
|
||||
is KtNamedFunction -> {
|
||||
when (parent.parent) {
|
||||
is KtBlockExpression, is KtClassBody, is KtFile, is KtScript -> return parent
|
||||
else -> if (stopOnNonInlinedLambdas && !InlineUtil.isInlinedArgument(parent, parent.analyze(), false)) return null
|
||||
}
|
||||
}
|
||||
is KtClassOrObject -> return null
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun isRecursiveCall(element: KtElement): Boolean {
|
||||
if (RecursivePropertyAccessorInspection.isRecursivePropertyAccess(element)) return true
|
||||
if (RecursivePropertyAccessorInspection.isRecursiveSyntheticPropertyAccess(element)) return true
|
||||
// Fast check for names without resolve
|
||||
val resolveName = getCallNameFromPsi(element) ?: return false
|
||||
val enclosingFunction = getEnclosingFunction(element, false) ?: return false
|
||||
|
||||
val enclosingFunctionName = enclosingFunction.name
|
||||
if (enclosingFunctionName != OperatorNameConventions.INVOKE.asString()
|
||||
&& enclosingFunctionName != resolveName.asString()
|
||||
) return false
|
||||
|
||||
// Check that there were no not-inlined lambdas on the way to enclosing function
|
||||
if (enclosingFunction != getEnclosingFunction(element, true)) return false
|
||||
|
||||
val bindingContext = element.analyze()
|
||||
val enclosingFunctionDescriptor = bindingContext[BindingContext.FUNCTION, enclosingFunction] ?: return false
|
||||
|
||||
val call = bindingContext[BindingContext.CALL, element] ?: return false
|
||||
val resolvedCall = bindingContext[BindingContext.RESOLVED_CALL, call] ?: return false
|
||||
|
||||
if (resolvedCall.candidateDescriptor.original != enclosingFunctionDescriptor) return false
|
||||
|
||||
fun isDifferentReceiver(receiver: Receiver?): Boolean {
|
||||
if (receiver !is ReceiverValue) return false
|
||||
|
||||
val receiverOwner = receiver.getReceiverTargetDescriptor(bindingContext) ?: return true
|
||||
|
||||
return when (receiverOwner) {
|
||||
is SimpleFunctionDescriptor -> receiverOwner != enclosingFunctionDescriptor
|
||||
is ClassDescriptor -> receiverOwner != enclosingFunctionDescriptor.containingDeclaration
|
||||
else -> return true
|
||||
}
|
||||
}
|
||||
|
||||
if (isDifferentReceiver(resolvedCall.dispatchReceiver)) return false
|
||||
return true
|
||||
}
|
||||
|
||||
private class RecursiveMethodCallMarkerInfo(callElement: PsiElement) : LineMarkerInfo<PsiElement>(
|
||||
callElement,
|
||||
callElement.textRange,
|
||||
AllIcons.Gutter.RecursiveMethod,
|
||||
Pass.LINE_MARKERS,
|
||||
{ KotlinBundle.message("highlighter.tool.tip.text.recursive.call") },
|
||||
null,
|
||||
GutterIconRenderer.Alignment.RIGHT
|
||||
) {
|
||||
|
||||
override fun createGutterRenderer(): GutterIconRenderer? {
|
||||
return object : LineMarkerInfo.LineMarkerGutterIconRenderer<PsiElement>(this) {
|
||||
override fun getClickAction() = null // to place breakpoint on mouse click
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal fun getElementForLineMark(callElement: PsiElement): PsiElement =
|
||||
when (callElement) {
|
||||
is KtSimpleNameExpression -> callElement.getReferencedNameElement()
|
||||
else ->
|
||||
// a fallback,
|
||||
//but who knows what to reference in KtArrayAccessExpression ?
|
||||
generateSequence(callElement, { it.firstChild }).last()
|
||||
}
|
||||
|
||||
private fun PsiElement.getLineNumber(): Int {
|
||||
return PsiDocumentManager.getInstance(project).getDocument(containingFile)!!.getLineNumber(textOffset)
|
||||
}
|
||||
|
||||
private fun getCallNameFromPsi(element: KtElement): Name? {
|
||||
when (element) {
|
||||
is KtSimpleNameExpression -> {
|
||||
val elementParent = element.getParent()
|
||||
when (elementParent) {
|
||||
is KtCallExpression -> return Name.identifier(element.getText())
|
||||
is KtOperationExpression -> {
|
||||
val operationReference = elementParent.operationReference
|
||||
if (element == operationReference) {
|
||||
val node = operationReference.getReferencedNameElementType()
|
||||
return if (node is KtToken) {
|
||||
val conventionName = if (elementParent is KtPrefixExpression)
|
||||
OperatorConventions.getNameForOperationSymbol(node, true, false)
|
||||
else
|
||||
OperatorConventions.getNameForOperationSymbol(node)
|
||||
|
||||
conventionName ?: Name.identifier(element.getText())
|
||||
} else {
|
||||
Name.identifier(element.getText())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
is KtArrayAccessExpression ->
|
||||
return OperatorNameConventions.GET
|
||||
is KtThisExpression ->
|
||||
if (element.getParent() is KtCallExpression) {
|
||||
return OperatorNameConventions.INVOKE
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
@@ -1,126 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.highlighter
|
||||
|
||||
import com.intellij.codeHighlighting.Pass
|
||||
import com.intellij.codeInsight.daemon.LineMarkerInfo
|
||||
import com.intellij.codeInsight.daemon.LineMarkerProvider
|
||||
import com.intellij.openapi.actionSystem.AnAction
|
||||
import com.intellij.openapi.editor.markup.GutterIconRenderer
|
||||
import com.intellij.openapi.progress.ProgressManager
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptorWithAccessors
|
||||
import org.jetbrains.kotlin.descriptors.accessors
|
||||
import org.jetbrains.kotlin.idea.KotlinBundle
|
||||
import org.jetbrains.kotlin.idea.KotlinIcons
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.highlighter.markers.LineMarkerInfos
|
||||
import org.jetbrains.kotlin.idea.refactoring.getLineNumber
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.BindingContext.*
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
|
||||
class KotlinSuspendCallLineMarkerProvider : LineMarkerProvider {
|
||||
private class SuspendCallMarkerInfo(callElement: PsiElement, message: String) : LineMarkerInfo<PsiElement>(
|
||||
callElement,
|
||||
callElement.textRange,
|
||||
KotlinIcons.SUSPEND_CALL,
|
||||
Pass.LINE_MARKERS,
|
||||
{ message },
|
||||
null,
|
||||
GutterIconRenderer.Alignment.RIGHT
|
||||
) {
|
||||
override fun createGutterRenderer(): GutterIconRenderer? {
|
||||
return object : LineMarkerInfo.LineMarkerGutterIconRenderer<PsiElement>(this) {
|
||||
override fun getClickAction(): AnAction? = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getLineMarkerInfo(element: PsiElement): LineMarkerInfo<*>? = null
|
||||
|
||||
override fun collectSlowLineMarkers(
|
||||
elements: MutableList<PsiElement>,
|
||||
result: LineMarkerInfos
|
||||
) {
|
||||
val markedLineNumbers = HashSet<Int>()
|
||||
|
||||
for (element in elements) {
|
||||
ProgressManager.checkCanceled()
|
||||
|
||||
if (element !is KtExpression) continue
|
||||
|
||||
val containingFile = element.containingFile
|
||||
if (containingFile !is KtFile || containingFile is KtCodeFragment) {
|
||||
continue
|
||||
}
|
||||
|
||||
val lineNumber = element.getLineNumber()
|
||||
if (lineNumber in markedLineNumbers) continue
|
||||
if (!element.hasSuspendCalls()) continue
|
||||
|
||||
markedLineNumbers += lineNumber
|
||||
result += if (element is KtForExpression) {
|
||||
SuspendCallMarkerInfo(
|
||||
getElementForLineMark(element.loopRange!!),
|
||||
KotlinBundle.message("highlighter.message.suspending.iteration")
|
||||
)
|
||||
} else {
|
||||
SuspendCallMarkerInfo(getElementForLineMark(element), KotlinBundle.message("highlighter.message.suspend.function.call"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtExpression.isValidCandidateExpression(): Boolean {
|
||||
if (this is KtParenthesizedExpression) return false
|
||||
if (this is KtOperationReferenceExpression || this is KtForExpression || this is KtProperty || this is KtNameReferenceExpression) return true
|
||||
val parent = parent
|
||||
if (parent is KtCallExpression && parent.calleeExpression == this) return true
|
||||
if (this is KtCallExpression && (calleeExpression is KtCallExpression || calleeExpression is KtParenthesizedExpression)) return true
|
||||
return false
|
||||
}
|
||||
|
||||
fun KtExpression.hasSuspendCalls(bindingContext: BindingContext = analyze(BodyResolveMode.PARTIAL)): Boolean {
|
||||
if (!isValidCandidateExpression()) return false
|
||||
|
||||
return when (this) {
|
||||
is KtForExpression -> {
|
||||
val iteratorResolvedCall = bindingContext[LOOP_RANGE_ITERATOR_RESOLVED_CALL, loopRange]
|
||||
val loopRangeHasNextResolvedCall = bindingContext[LOOP_RANGE_HAS_NEXT_RESOLVED_CALL, loopRange]
|
||||
val loopRangeNextResolvedCall = bindingContext[LOOP_RANGE_NEXT_RESOLVED_CALL, loopRange]
|
||||
listOf(iteratorResolvedCall, loopRangeHasNextResolvedCall, loopRangeNextResolvedCall).any {
|
||||
it?.resultingDescriptor?.isSuspend == true
|
||||
}
|
||||
}
|
||||
is KtProperty -> {
|
||||
if (hasDelegateExpression()) {
|
||||
val variableDescriptor = bindingContext[DECLARATION_TO_DESCRIPTOR, this] as? VariableDescriptorWithAccessors
|
||||
val accessors = variableDescriptor?.accessors ?: emptyList()
|
||||
accessors.any { accessor ->
|
||||
val delegatedFunctionDescriptor = bindingContext[DELEGATED_PROPERTY_RESOLVED_CALL, accessor]?.resultingDescriptor
|
||||
delegatedFunctionDescriptor?.isSuspend == true
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
val resolvedCall = getResolvedCall(bindingContext)
|
||||
if ((resolvedCall?.resultingDescriptor as? FunctionDescriptor)?.isSuspend == true) true
|
||||
else {
|
||||
val propertyDescriptor = resolvedCall?.resultingDescriptor as? PropertyDescriptor
|
||||
val s = propertyDescriptor?.fqNameSafe?.asString()
|
||||
s?.startsWith("kotlin.coroutines.") == true && s.endsWith(".coroutineContext")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.highlighter.markers
|
||||
|
||||
import com.intellij.codeInsight.daemon.LineMarkerInfo
|
||||
|
||||
typealias LineMarkerInfos = MutableCollection<LineMarkerInfo<*>>
|
||||
@@ -14,7 +14,7 @@ import org.jetbrains.kotlin.idea.KotlinIcons
|
||||
import org.jetbrains.kotlin.idea.highlighter.dsl.DslHighlighterExtension
|
||||
import javax.swing.Icon
|
||||
|
||||
// FIX ME WHEN BUNCH as41 REMOVED
|
||||
// FIX ME WHEN BUNCH as42 REMOVED
|
||||
internal fun createDslStyleIcon(styleId: Int): Icon {
|
||||
val globalScheme = EditorColorsManager.getInstance().globalScheme
|
||||
val markersColor = globalScheme.getAttributes(DslHighlighterExtension.styleById(styleId)).foregroundColor
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.highlighter.markers
|
||||
|
||||
import com.intellij.icons.AllIcons
|
||||
import javax.swing.Icon
|
||||
|
||||
// FIX ME WHEN BUNCH as41 REMOVED
|
||||
internal fun createDslStyleIcon(styleId: Int): Icon {
|
||||
return AllIcons.Gutter.Colors
|
||||
}
|
||||
@@ -1,192 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.inspections
|
||||
|
||||
import com.intellij.application.options.CodeStyle
|
||||
import com.intellij.codeInspection.LocalQuickFix
|
||||
import com.intellij.codeInspection.ProblemDescriptor
|
||||
import com.intellij.codeInspection.ProblemHighlightType
|
||||
import com.intellij.codeInspection.ProblemsHolder
|
||||
import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiElementVisitor
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager
|
||||
import org.jetbrains.kotlin.idea.KotlinBundle
|
||||
import org.jetbrains.kotlin.idea.formatter.TrailingCommaVisitor
|
||||
import org.jetbrains.kotlin.idea.formatter.kotlinCustomSettings
|
||||
import org.jetbrains.kotlin.idea.formatter.trailingComma.*
|
||||
import org.jetbrains.kotlin.idea.formatter.trailingCommaAllowedInModule
|
||||
import org.jetbrains.kotlin.idea.util.isComma
|
||||
import org.jetbrains.kotlin.idea.util.isLineBreak
|
||||
import org.jetbrains.kotlin.idea.util.leafIgnoringWhitespaceAndComments
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||
import javax.swing.JComponent
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
class TrailingCommaInspection(
|
||||
@JvmField
|
||||
var addCommaWarning: Boolean = false
|
||||
) : AbstractKotlinInspection() {
|
||||
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor = object : TrailingCommaVisitor() {
|
||||
override val recursively: Boolean = false
|
||||
private var useTrailingComma by Delegates.notNull<Boolean>()
|
||||
|
||||
override fun process(trailingCommaContext: TrailingCommaContext) {
|
||||
val element = trailingCommaContext.ktElement
|
||||
val kotlinCustomSettings = CodeStyle.getSettings(element.project).kotlinCustomSettings
|
||||
useTrailingComma = kotlinCustomSettings.addTrailingCommaIsAllowedFor(element)
|
||||
when (trailingCommaContext.state) {
|
||||
TrailingCommaState.MISSING, TrailingCommaState.EXISTS -> {
|
||||
checkCommaPosition(element)
|
||||
checkLineBreaks(element)
|
||||
}
|
||||
else -> Unit
|
||||
}
|
||||
|
||||
checkTrailingComma(trailingCommaContext)
|
||||
}
|
||||
|
||||
private fun checkLineBreaks(commaOwner: KtElement) {
|
||||
val first = TrailingCommaHelper.elementBeforeFirstElement(commaOwner)
|
||||
if (first?.nextLeaf(true)?.isLineBreak() == false) {
|
||||
first.nextSibling?.let {
|
||||
registerProblemForLineBreak(commaOwner, it, ProblemHighlightType.INFORMATION)
|
||||
}
|
||||
}
|
||||
|
||||
val last = TrailingCommaHelper.elementAfterLastElement(commaOwner)
|
||||
if (last?.prevLeaf(true)?.isLineBreak() == false) {
|
||||
registerProblemForLineBreak(
|
||||
commaOwner,
|
||||
last,
|
||||
if (addCommaWarning) ProblemHighlightType.GENERIC_ERROR_OR_WARNING else ProblemHighlightType.INFORMATION,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkCommaPosition(commaOwner: KtElement) {
|
||||
for (invalidComma in TrailingCommaHelper.findInvalidCommas(commaOwner)) {
|
||||
reportProblem(
|
||||
invalidComma,
|
||||
KotlinBundle.message("inspection.trailing.comma.comma.loses.the.advantages.in.this.position"),
|
||||
KotlinBundle.message("inspection.trailing.comma.fix.comma.position")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkTrailingComma(trailingCommaContext: TrailingCommaContext) {
|
||||
val commaOwner = trailingCommaContext.ktElement
|
||||
val trailingCommaOrLastElement = TrailingCommaHelper.trailingCommaOrLastElement(commaOwner) ?: return
|
||||
when (trailingCommaContext.state) {
|
||||
TrailingCommaState.MISSING -> {
|
||||
if (!trailingCommaAllowedInModule(commaOwner)) return
|
||||
reportProblem(
|
||||
trailingCommaOrLastElement,
|
||||
KotlinBundle.message("inspection.trailing.comma.missing.trailing.comma"),
|
||||
KotlinBundle.message("inspection.trailing.comma.add.trailing.comma"),
|
||||
if (addCommaWarning) ProblemHighlightType.GENERIC_ERROR_OR_WARNING else ProblemHighlightType.INFORMATION,
|
||||
)
|
||||
}
|
||||
TrailingCommaState.REDUNDANT -> {
|
||||
reportProblem(
|
||||
trailingCommaOrLastElement,
|
||||
KotlinBundle.message("inspection.trailing.comma.useless.trailing.comma"),
|
||||
KotlinBundle.message("inspection.trailing.comma.remove.trailing.comma"),
|
||||
ProblemHighlightType.LIKE_UNUSED_SYMBOL,
|
||||
checkTrailingCommaSettings = false,
|
||||
)
|
||||
}
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
private fun reportProblem(
|
||||
commaOrElement: PsiElement,
|
||||
message: String,
|
||||
fixMessage: String,
|
||||
highlightType: ProblemHighlightType = ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
|
||||
checkTrailingCommaSettings: Boolean = true,
|
||||
) {
|
||||
val commaOwner = commaOrElement.parent as KtElement
|
||||
// case for KtFunctionLiteral, where PsiWhiteSpace after KtTypeParameterList isn't included in this list
|
||||
val problemOwner = commaOwner.parent
|
||||
holder.registerProblem(
|
||||
problemOwner,
|
||||
message,
|
||||
highlightType.applyCondition(!checkTrailingCommaSettings || useTrailingComma),
|
||||
commaOrElement.textRangeOfCommaOrSymbolAfter.shiftLeft(problemOwner.startOffset),
|
||||
createQuickFix(fixMessage, commaOwner),
|
||||
)
|
||||
}
|
||||
|
||||
private fun registerProblemForLineBreak(
|
||||
commaOwner: KtElement,
|
||||
elementForTextRange: PsiElement,
|
||||
highlightType: ProblemHighlightType,
|
||||
) {
|
||||
val problemElement = commaOwner.parent
|
||||
holder.registerProblem(
|
||||
problemElement,
|
||||
KotlinBundle.message("inspection.trailing.comma.missing.line.break"),
|
||||
highlightType.applyCondition(useTrailingComma),
|
||||
TextRange.from(elementForTextRange.startOffset, 1).shiftLeft(problemElement.startOffset),
|
||||
createQuickFix(KotlinBundle.message("inspection.trailing.comma.add.line.break"), commaOwner),
|
||||
)
|
||||
}
|
||||
|
||||
private fun ProblemHighlightType.applyCondition(condition: Boolean): ProblemHighlightType = when {
|
||||
ApplicationManager.getApplication().isUnitTestMode -> ProblemHighlightType.GENERIC_ERROR_OR_WARNING
|
||||
condition -> this
|
||||
else -> ProblemHighlightType.INFORMATION
|
||||
}
|
||||
|
||||
private fun createQuickFix(
|
||||
fixMessage: String,
|
||||
commaOwner: KtElement,
|
||||
): LocalQuickFix = object : LocalQuickFix {
|
||||
val commaOwnerPointer = commaOwner.createSmartPointer()
|
||||
|
||||
override fun getFamilyName(): String = fixMessage
|
||||
|
||||
override fun applyFix(project: Project, problemDescriptor: ProblemDescriptor) {
|
||||
val element = commaOwnerPointer.element ?: return
|
||||
val range = createFormatterTextRange(element)
|
||||
val settings = CodeStyle.getSettings(project).clone()
|
||||
settings.kotlinCustomSettings.ALLOW_TRAILING_COMMA = true
|
||||
settings.kotlinCustomSettings.ALLOW_TRAILING_COMMA_ON_CALL_SITE = true
|
||||
CodeStyle.doWithTemporarySettings(project, settings) {
|
||||
CodeStyleManager.getInstance(project).reformatRange(element, range.startOffset, range.endOffset)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createFormatterTextRange(commaOwner: KtElement): TextRange {
|
||||
val startElement = TrailingCommaHelper.elementBeforeFirstElement(commaOwner) ?: commaOwner
|
||||
val endElement = TrailingCommaHelper.elementAfterLastElement(commaOwner) ?: commaOwner
|
||||
return TextRange.create(startElement.startOffset, endElement.endOffset)
|
||||
}
|
||||
|
||||
private val PsiElement.textRangeOfCommaOrSymbolAfter: TextRange
|
||||
get() {
|
||||
val textRange = textRange
|
||||
if (isComma) return textRange
|
||||
|
||||
return nextLeaf()?.leafIgnoringWhitespaceAndComments(false)?.endOffset?.takeIf { it > 0 }?.let {
|
||||
TextRange.create(it - 1, it).intersection(textRange)
|
||||
} ?: TextRange.create(textRange.endOffset - 1, textRange.endOffset)
|
||||
}
|
||||
}
|
||||
|
||||
override fun createOptionsPanel(): JComponent? {
|
||||
val panel = MultipleCheckboxOptionsPanel(this)
|
||||
panel.addCheckbox(KotlinBundle.message("inspection.trailing.comma.report.also.a.missing.comma"), "addCommaWarning")
|
||||
return panel
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.refactoring.changeSignature;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.refactoring.util.TextOccurrencesUtil;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
// FIX ME WHEN BUNCH 201 REMOVED
|
||||
final class BunchedDeprecation {
|
||||
public static void findNonCodeUsages(
|
||||
PsiElement element,
|
||||
String stringToSearch,
|
||||
boolean searchInStringsAndComments,
|
||||
boolean searchInNonJavaFiles,
|
||||
String newQName,
|
||||
Collection<? super UsageInfo> results) {
|
||||
TextOccurrencesUtil.findNonCodeUsages(element, GlobalSearchScope.projectScope(element.getProject()),
|
||||
stringToSearch, searchInStringsAndComments, searchInNonJavaFiles, newQName, results);
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.Ref
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.search.searches.MethodReferencesSearch
|
||||
import com.intellij.psi.search.searches.OverridingMethodsSearch
|
||||
import com.intellij.psi.search.searches.ReferencesSearch
|
||||
@@ -20,6 +21,7 @@ import com.intellij.refactoring.rename.UnresolvableCollisionUsageInfo
|
||||
import com.intellij.refactoring.util.CommonRefactoringUtil
|
||||
import com.intellij.refactoring.util.MoveRenameUsageInfo
|
||||
import com.intellij.refactoring.util.RefactoringUIUtil
|
||||
import com.intellij.refactoring.util.TextOccurrencesUtil
|
||||
import com.intellij.usageView.UsageInfo
|
||||
import com.intellij.util.containers.MultiMap
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||
@@ -269,7 +271,10 @@ class KotlinChangeSignatureUsageProcessor : ChangeSignatureUsageProcessor {
|
||||
val oldName = changeInfo.oldName
|
||||
|
||||
if (oldName != null) {
|
||||
BunchedDeprecation.findNonCodeUsages(functionPsi, oldName, true, true, changeInfo.newName, result)
|
||||
TextOccurrencesUtil.findNonCodeUsages(
|
||||
functionPsi, GlobalSearchScope.projectScope(functionPsi.project),
|
||||
oldName, true, true, changeInfo.newName, result
|
||||
)
|
||||
}
|
||||
|
||||
val oldParameters = (functionPsi as KtNamedDeclaration).getValueParameters()
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.refactoring.changeSignature
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
|
||||
|
||||
class KotlinMutableMethodDescriptor(override val original: KotlinMethodDescriptor) : KotlinMethodDescriptor by original {
|
||||
private val parameters: MutableList<KotlinParameterInfo> = original.parameters
|
||||
|
||||
override var receiver: KotlinParameterInfo? = original.receiver
|
||||
set(value: KotlinParameterInfo?) {
|
||||
if (value != null && value !in parameters) {
|
||||
parameters.add(value)
|
||||
}
|
||||
field = value
|
||||
}
|
||||
|
||||
fun addParameter(parameter: KotlinParameterInfo) {
|
||||
parameters.add(parameter)
|
||||
}
|
||||
|
||||
fun addParameter(index: Int, parameter: KotlinParameterInfo) {
|
||||
parameters.add(index, parameter)
|
||||
}
|
||||
|
||||
fun removeParameter(index: Int) {
|
||||
val paramInfo = parameters.removeAt(index)
|
||||
if (paramInfo == receiver) {
|
||||
receiver = null
|
||||
}
|
||||
}
|
||||
|
||||
fun renameParameter(index: Int, newName: String) {
|
||||
parameters[index].name = newName
|
||||
}
|
||||
|
||||
fun clearNonReceiverParameters() {
|
||||
parameters.clear()
|
||||
receiver?.let { parameters.add(it) }
|
||||
}
|
||||
|
||||
override fun getVisibility(): DescriptorVisibility {
|
||||
return original.visibility
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.refactoring.move.moveDeclarations;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.refactoring.util.TextOccurrencesUtil;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
// FIX ME WHEN BUNCH 201 REMOVED
|
||||
final class BunchedDeprecation {
|
||||
public static void findNonCodeUsages(
|
||||
PsiElement element,
|
||||
String stringToSearch,
|
||||
boolean searchInStringsAndComments,
|
||||
boolean searchInNonJavaFiles,
|
||||
String newQName,
|
||||
Collection<? super UsageInfo> results) {
|
||||
TextOccurrencesUtil.findNonCodeUsages(element, GlobalSearchScope.projectScope(element.getProject()),
|
||||
stringToSearch, searchInStringsAndComments, searchInNonJavaFiles, newQName, results);
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import com.intellij.refactoring.move.moveClassesOrPackages.MoveClassHandler
|
||||
import com.intellij.refactoring.rename.RenameUtil
|
||||
import com.intellij.refactoring.util.NonCodeUsageInfo
|
||||
import com.intellij.refactoring.util.RefactoringUIUtil
|
||||
import com.intellij.refactoring.util.TextOccurrencesUtil
|
||||
import com.intellij.usageView.UsageInfo
|
||||
import com.intellij.usageView.UsageViewBundle
|
||||
import com.intellij.usageView.UsageViewDescriptor
|
||||
@@ -224,8 +225,9 @@ class MoveKotlinDeclarationsProcessor(
|
||||
val name = lightElement.getKotlinFqName()?.quoteIfNeeded()?.asString()
|
||||
if (name != null) {
|
||||
fun searchForKotlinNameUsages(results: ArrayList<UsageInfo>) {
|
||||
BunchedDeprecation.findNonCodeUsages(
|
||||
TextOccurrencesUtil.findNonCodeUsages(
|
||||
lightElement,
|
||||
GlobalSearchScope.projectScope(lightElement.project),
|
||||
name,
|
||||
descriptor.searchInCommentsAndStrings,
|
||||
descriptor.searchInNonCode,
|
||||
@@ -242,8 +244,9 @@ class MoveKotlinDeclarationsProcessor(
|
||||
elementName
|
||||
)
|
||||
|
||||
BunchedDeprecation.findNonCodeUsages(
|
||||
TextOccurrencesUtil.findNonCodeUsages(
|
||||
lightElement,
|
||||
GlobalSearchScope.projectScope(lightElement.project),
|
||||
oldFqNameWithFacade,
|
||||
descriptor.searchInCommentsAndStrings,
|
||||
descriptor.searchInNonCode,
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.reporter
|
||||
|
||||
import com.intellij.diagnostic.ITNReporter
|
||||
import com.intellij.openapi.diagnostic.IdeaLoggingEvent
|
||||
import com.intellij.openapi.diagnostic.SubmittedReportInfo
|
||||
import com.intellij.util.Consumer
|
||||
import java.awt.Component
|
||||
|
||||
abstract class ITNReporterCompat : ITNReporter() {
|
||||
final override fun submit(
|
||||
events: Array<IdeaLoggingEvent>,
|
||||
additionalInfo: String?,
|
||||
parentComponent: Component?,
|
||||
consumer: Consumer<SubmittedReportInfo>
|
||||
): Boolean {
|
||||
return submitCompat(events, additionalInfo, parentComponent, consumer)
|
||||
}
|
||||
|
||||
open fun submitCompat(
|
||||
events: Array<IdeaLoggingEvent>,
|
||||
additionalInfo: String?,
|
||||
parentComponent: Component?,
|
||||
consumer: Consumer<SubmittedReportInfo>
|
||||
): Boolean {
|
||||
@Suppress("IncompatibleAPI")
|
||||
return super.submit(events, additionalInfo, parentComponent, consumer)
|
||||
}
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.search.ideaExtensions
|
||||
|
||||
import com.intellij.codeInsight.JavaTargetElementEvaluator
|
||||
import com.intellij.codeInsight.TargetElementEvaluatorEx
|
||||
import com.intellij.codeInsight.TargetElementUtil
|
||||
import com.intellij.codeInsight.TargetElementUtilExtender
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiReference
|
||||
import com.intellij.util.BitUtil
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource
|
||||
import org.jetbrains.kotlin.idea.intentions.isAutoCreatedItUsage
|
||||
import org.jetbrains.kotlin.idea.references.KtDestructuringDeclarationReference
|
||||
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.idea.references.resolveMainReferenceToDescriptors
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
||||
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||
|
||||
class KotlinTargetElementEvaluator : TargetElementEvaluatorEx, TargetElementUtilExtender {
|
||||
companion object {
|
||||
const val DO_NOT_UNWRAP_LABELED_EXPRESSION = 0x100
|
||||
const val BYPASS_IMPORT_ALIAS = 0x200
|
||||
|
||||
// Place caret after the open curly brace in lambda for generated 'it'
|
||||
fun findLambdaOpenLBraceForGeneratedIt(ref: PsiReference): PsiElement? {
|
||||
val element: PsiElement = ref.element
|
||||
if (element.text != "it") return null
|
||||
|
||||
if (element !is KtNameReferenceExpression || !isAutoCreatedItUsage(element)) return null
|
||||
|
||||
val itDescriptor = element.resolveMainReferenceToDescriptors().singleOrNull() ?: return null
|
||||
val descriptorWithSource = itDescriptor.containingDeclaration as? DeclarationDescriptorWithSource ?: return null
|
||||
val lambdaExpression = descriptorWithSource.source.getPsi()?.parent as? KtLambdaExpression ?: return null
|
||||
return lambdaExpression.leftCurlyBrace.treeNext?.psi
|
||||
}
|
||||
|
||||
// Navigate to receiver element for this in extension declaration
|
||||
fun findReceiverForThisInExtensionFunction(ref: PsiReference): PsiElement? {
|
||||
val element: PsiElement = ref.element
|
||||
if (element.text != "this") return null
|
||||
|
||||
if (element !is KtNameReferenceExpression) return null
|
||||
val callableDescriptor = element.resolveMainReferenceToDescriptors().singleOrNull() as? CallableDescriptor ?: return null
|
||||
|
||||
if (!callableDescriptor.isExtension) return null
|
||||
val callableDeclaration = callableDescriptor.source.getPsi() as? KtCallableDeclaration ?: return null
|
||||
|
||||
return callableDeclaration.receiverTypeReference
|
||||
}
|
||||
}
|
||||
|
||||
override fun getAdditionalDefinitionSearchFlags() = 0
|
||||
|
||||
override fun getAdditionalReferenceSearchFlags() = DO_NOT_UNWRAP_LABELED_EXPRESSION or BYPASS_IMPORT_ALIAS
|
||||
|
||||
override fun getAllAdditionalFlags() = additionalDefinitionSearchFlags + additionalReferenceSearchFlags
|
||||
|
||||
override fun includeSelfInGotoImplementation(element: PsiElement): Boolean = !(element is KtClass && element.isAbstract())
|
||||
|
||||
override fun getElementByReference(ref: PsiReference, flags: Int): PsiElement? {
|
||||
if (ref is KtSimpleNameReference && ref.expression is KtLabelReferenceExpression) {
|
||||
val refTarget = ref.resolve() as? KtExpression ?: return null
|
||||
if (!BitUtil.isSet(flags, DO_NOT_UNWRAP_LABELED_EXPRESSION)) {
|
||||
return refTarget.getLabeledParent(ref.expression.getReferencedName()) ?: refTarget
|
||||
}
|
||||
return refTarget
|
||||
}
|
||||
|
||||
if (!BitUtil.isSet(flags, BYPASS_IMPORT_ALIAS)) {
|
||||
(ref.element as? KtSimpleNameExpression)?.mainReference?.getImportAlias()?.let { return it }
|
||||
}
|
||||
|
||||
// prefer destructing declaration entry to its target if element name is accepted
|
||||
if (ref is KtDestructuringDeclarationReference && BitUtil.isSet(flags, TargetElementUtil.ELEMENT_NAME_ACCEPTED)) {
|
||||
return ref.element
|
||||
}
|
||||
|
||||
val refExpression = ref.element as? KtSimpleNameExpression
|
||||
val calleeExpression = refExpression?.getParentOfTypeAndBranch<KtCallElement> { calleeExpression }
|
||||
if (calleeExpression != null) {
|
||||
(ref.resolve() as? KtConstructor<*>)?.let {
|
||||
return if (flags and JavaTargetElementEvaluator().additionalReferenceSearchFlags != 0) it else it.containingClassOrObject
|
||||
}
|
||||
}
|
||||
|
||||
if (BitUtil.isSet(flags, TargetElementUtil.REFERENCED_ELEMENT_ACCEPTED)) {
|
||||
return findLambdaOpenLBraceForGeneratedIt(ref)
|
||||
?: findReceiverForThisInExtensionFunction(ref)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
override fun isIdentifierPart(file: PsiFile, text: CharSequence?, offset: Int): Boolean {
|
||||
val elementAtCaret = file.findElementAt(offset)
|
||||
|
||||
if (elementAtCaret?.node?.elementType == KtTokens.IDENTIFIER) return true
|
||||
// '(' is considered identifier part if it belongs to primary constructor without 'constructor' keyword
|
||||
return elementAtCaret?.getNonStrictParentOfType<KtPrimaryConstructor>()?.textOffset == offset
|
||||
}
|
||||
}
|
||||
@@ -1,127 +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.slicer
|
||||
|
||||
import com.intellij.codeInsight.Nullability
|
||||
import com.intellij.ide.util.treeView.AbstractTreeStructure
|
||||
import com.intellij.openapi.actionSystem.DefaultActionGroup
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.util.parentOfType
|
||||
import com.intellij.slicer.*
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||
import org.jetbrains.kotlin.idea.references.KtReference
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isPlainWithEscapes
|
||||
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
||||
import org.jetbrains.kotlin.psi2ir.deparenthesize
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.types.isError
|
||||
import org.jetbrains.kotlin.types.isNullabilityFlexible
|
||||
|
||||
class KotlinSliceProvider : SliceLanguageSupportProvider, SliceUsageTransformer {
|
||||
companion object {
|
||||
val LEAF_ELEMENT_EQUALITY = object : SliceLeafEquality() {
|
||||
override fun substituteElement(element: PsiElement) = (element as? KtReference)?.resolve() ?: element
|
||||
}
|
||||
}
|
||||
|
||||
class KotlinGroupByNullnessAction(treeBuilder: SliceTreeBuilder) : GroupByNullnessActionBase(treeBuilder) {
|
||||
override fun isAvailable() = true
|
||||
}
|
||||
|
||||
val leafAnalyzer by lazy { SliceLeafAnalyzer(LEAF_ELEMENT_EQUALITY, this) }
|
||||
|
||||
val nullnessAnalyzer: HackedSliceNullnessAnalyzerBase by lazy {
|
||||
object : HackedSliceNullnessAnalyzerBase(LEAF_ELEMENT_EQUALITY, this) {
|
||||
override fun checkNullability(element: PsiElement?): Nullability {
|
||||
val types = when (element) {
|
||||
is KtCallableDeclaration -> listOfNotNull((element.resolveToDescriptorIfAny() as? CallableDescriptor)?.returnType)
|
||||
is KtDeclaration -> emptyList()
|
||||
is KtExpression -> listOfNotNull(element.analyze(BodyResolveMode.PARTIAL).getType(element))
|
||||
else -> emptyList()
|
||||
}
|
||||
return when {
|
||||
types.isEmpty() -> return Nullability.UNKNOWN
|
||||
types.all { KotlinBuiltIns.isNullableNothing(it) } -> Nullability.NULLABLE
|
||||
types.any { it.isError || TypeUtils.isNullableType(it) || it.isNullabilityFlexible() } -> Nullability.UNKNOWN
|
||||
else -> Nullability.NOT_NULL
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun createRootUsage(element: PsiElement, params: SliceAnalysisParams) = KotlinSliceUsage(element, params)
|
||||
|
||||
override fun transform(usage: SliceUsage): Collection<SliceUsage>? {
|
||||
if (usage is KotlinSliceUsage) return null
|
||||
return listOf(KotlinSliceUsage(usage.element, usage.parent, KotlinSliceAnalysisMode.Default, false))
|
||||
}
|
||||
|
||||
override fun getExpressionAtCaret(atCaret: PsiElement, dataFlowToThis: Boolean): KtElement? {
|
||||
val element = atCaret.parentsWithSelf
|
||||
.filterIsInstance<KtElement>()
|
||||
.firstOrNull(::isSliceElement)
|
||||
?.deparenthesize() ?: return null
|
||||
|
||||
if (dataFlowToThis) {
|
||||
if (element is KtConstantExpression) return null
|
||||
if (element is KtStringTemplateExpression && element.isPlainWithEscapes()) return null
|
||||
if (element is KtClassLiteralExpression) return null
|
||||
if (element is KtCallableReferenceExpression) return null
|
||||
}
|
||||
|
||||
return element
|
||||
}
|
||||
|
||||
private fun isSliceElement(element: KtElement): Boolean {
|
||||
return when {
|
||||
element is KtProperty -> true
|
||||
element is KtParameter -> true
|
||||
element is KtDeclarationWithBody -> true
|
||||
element is KtClass && !element.hasExplicitPrimaryConstructor() -> true
|
||||
element is KtExpression && element !is KtDeclaration && element.parentOfType<KtTypeReference>() == null -> true
|
||||
element is KtTypeReference && element == (element.parent as? KtCallableDeclaration)?.receiverTypeReference -> true
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
override fun getElementForDescription(element: PsiElement): PsiElement {
|
||||
return (element as? KtSimpleNameExpression)?.mainReference?.resolve() ?: element
|
||||
}
|
||||
|
||||
override fun getRenderer() = KotlinSliceUsageCellRenderer
|
||||
|
||||
override fun startAnalyzeLeafValues(structure: AbstractTreeStructure, finalRunnable: Runnable) {
|
||||
leafAnalyzer.startAnalyzeValues(structure, finalRunnable)
|
||||
}
|
||||
|
||||
override fun startAnalyzeNullness(structure: AbstractTreeStructure, finalRunnable: Runnable) {
|
||||
nullnessAnalyzer.startAnalyzeNullness(structure, finalRunnable)
|
||||
}
|
||||
|
||||
override fun registerExtraPanelActions(group: DefaultActionGroup, builder: SliceTreeBuilder) {
|
||||
if (builder.dataFlowToThis) {
|
||||
group.add(GroupByLeavesAction(builder))
|
||||
group.add(KotlinGroupByNullnessAction(builder))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,6 @@ import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.util.concurrency.AppExecutorUtil
|
||||
import java.util.concurrent.Callable
|
||||
|
||||
// FIX ME WHEN BUNCH 201 REMOVED
|
||||
|
||||
fun runActivity(project: Project) {
|
||||
nonBlocking(Callable {
|
||||
@@ -1,11 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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
|
||||
|
||||
// Remove the function, when there's no dependency to cidr during running Kotlin tests.
|
||||
// FIX ME WHEN BUNCH as41 REMOVED
|
||||
fun registerAdditionalResourceBundleInTests() {
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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("DEPRECATION")
|
||||
|
||||
package org.jetbrains.kotlin.idea
|
||||
|
||||
import com.intellij.featureStatistics.FeatureStatisticsBundleEP
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.extensions.Extensions
|
||||
import com.jetbrains.cidr.lang.OCBundle
|
||||
|
||||
// Remove the function, when there's no dependency to cidr during running Kotlin tests.
|
||||
fun registerAdditionalResourceBundleInTests() {
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode) {
|
||||
return
|
||||
}
|
||||
|
||||
val extensionPoint = Extensions.getRootArea().getExtensionPoint(FeatureStatisticsBundleEP.EP_NAME)
|
||||
if (extensionPoint.extensions.none { it.qualifiedName == TestOCBundleProvider.qualifiedName }) {
|
||||
extensionPoint.registerExtension(TestOCBundleProvider)
|
||||
}
|
||||
}
|
||||
|
||||
object TestOCBundleProvider : FeatureStatisticsBundleEP() {
|
||||
init {
|
||||
qualifiedName = OCBundle.BUNDLE
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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("DEPRECATION")
|
||||
|
||||
package org.jetbrains.kotlin.idea
|
||||
|
||||
// Remove the function, when there's no dependency to cidr during running Kotlin tests.
|
||||
fun registerAdditionalResourceBundleInTests() {
|
||||
}
|
||||
@@ -1,157 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.update
|
||||
|
||||
import com.intellij.ide.plugins.IdeaPluginDescriptor
|
||||
import com.intellij.ide.plugins.PluginManagerCore
|
||||
import com.intellij.ide.plugins.PluginNode
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import org.jetbrains.kotlin.idea.KotlinBundle
|
||||
import org.jetbrains.kotlin.idea.util.isDev
|
||||
import org.jetbrains.kotlin.idea.util.isEap
|
||||
import java.io.IOException
|
||||
import java.net.URL
|
||||
import java.util.*
|
||||
import javax.xml.bind.JAXBContext
|
||||
import javax.xml.bind.JAXBException
|
||||
import javax.xml.bind.annotation.*
|
||||
|
||||
class GooglePluginUpdateVerifier : PluginUpdateVerifier() {
|
||||
override val verifierName: String
|
||||
get() = KotlinBundle.message("update.name.android.studio")
|
||||
|
||||
// Verifies if a plugin can be installed in Android Studio 3.2+.
|
||||
// Currently used only by KotlinPluginUpdater.
|
||||
override fun verify(pluginDescriptor: IdeaPluginDescriptor): PluginVerifyResult? {
|
||||
if (pluginDescriptor.pluginId.idString != KOTLIN_PLUGIN_ID) {
|
||||
return null
|
||||
}
|
||||
|
||||
val version = pluginDescriptor.version
|
||||
if (isEap(version) || isDev(version)) {
|
||||
return PluginVerifyResult.accept()
|
||||
}
|
||||
|
||||
try {
|
||||
val url = URL(METADATA_FILE_URL)
|
||||
val stream = url.openStream()
|
||||
val context = JAXBContext.newInstance(PluginCompatibility::class.java)
|
||||
val unmarshaller = context.createUnmarshaller()
|
||||
val pluginCompatibility = unmarshaller.unmarshal(stream) as PluginCompatibility
|
||||
|
||||
val release = getRelease(pluginCompatibility)
|
||||
?: return PluginVerifyResult.decline(KotlinBundle.message("update.reason.text.no.verified.versions.for.this.build"))
|
||||
|
||||
return if (release.plugins().any { KOTLIN_PLUGIN_ID == it.id && version == it.version })
|
||||
PluginVerifyResult.accept()
|
||||
else
|
||||
PluginVerifyResult.decline(KotlinBundle.message("update.reason.text.version.to.be.verified"))
|
||||
} catch (e: Exception) {
|
||||
LOG.info("Exception when verifying plugin ${pluginDescriptor.pluginId.idString} version $version", e)
|
||||
return when (e) {
|
||||
is IOException ->
|
||||
PluginVerifyResult.decline(KotlinBundle.message("update.reason.text.unable.to.connect.to.compatibility.verification.repository"))
|
||||
is JAXBException -> PluginVerifyResult.decline(KotlinBundle.message("update.reason.text.unable.to.parse.compatibility.verification.metadata"))
|
||||
else -> PluginVerifyResult.decline(
|
||||
KotlinBundle.message("update.reason.text.exception.during.verification",
|
||||
e.message.toString()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getRelease(pluginCompatibility: PluginCompatibility): StudioRelease? {
|
||||
for (studioRelease in pluginCompatibility.releases()) {
|
||||
if (buildInRange(studioRelease.name, studioRelease.sinceBuild, studioRelease.untilBuild)) {
|
||||
return studioRelease
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun buildInRange(name: String?, sinceBuild: String?, untilBuild: String?): Boolean {
|
||||
val descriptor = PluginNode()
|
||||
descriptor.name = name
|
||||
descriptor.sinceBuild = sinceBuild
|
||||
descriptor.untilBuild = untilBuild
|
||||
return PluginManagerCore.isCompatible(descriptor)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val KOTLIN_PLUGIN_ID = "org.jetbrains.kotlin"
|
||||
private const val METADATA_FILE_URL = "https://dl.google.com/android/studio/plugins/compatibility.xml"
|
||||
|
||||
private val LOG = Logger.getInstance(GooglePluginUpdateVerifier::class.java)
|
||||
|
||||
private fun PluginCompatibility.releases() = studioRelease ?: emptyArray()
|
||||
private fun StudioRelease.plugins() = ideaPlugin ?: emptyArray()
|
||||
|
||||
@XmlRootElement(name = "plugin-compatibility")
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
class PluginCompatibility {
|
||||
@XmlElement(name = "studio-release")
|
||||
var studioRelease: Array<StudioRelease>? = null
|
||||
|
||||
override fun toString(): String {
|
||||
return "PluginCompatibility(studioRelease=${Arrays.toString(studioRelease)})"
|
||||
}
|
||||
}
|
||||
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
class StudioRelease {
|
||||
@XmlAttribute(name = "until-build")
|
||||
var untilBuild: String? = null
|
||||
@XmlAttribute(name = "since-build")
|
||||
var sinceBuild: String? = null
|
||||
@XmlAttribute
|
||||
var name: String? = null
|
||||
@XmlAttribute
|
||||
var channel: String? = null
|
||||
|
||||
@XmlElement(name = "idea-plugin")
|
||||
var ideaPlugin: Array<IdeaPlugin>? = null
|
||||
|
||||
override fun toString(): String {
|
||||
return "StudioRelease(" +
|
||||
"untilBuild=$untilBuild, name=$name, ideaPlugin=${Arrays.toString(ideaPlugin)}, " +
|
||||
"sinceBuild=$sinceBuild, channel=$channel" +
|
||||
")"
|
||||
}
|
||||
}
|
||||
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
class IdeaPlugin {
|
||||
@XmlAttribute
|
||||
var id: String? = null
|
||||
@XmlAttribute
|
||||
var sha256: String? = null
|
||||
@XmlAttribute
|
||||
var channel: String? = null
|
||||
@XmlAttribute
|
||||
var version: String? = null
|
||||
|
||||
@XmlElement(name = "idea-version")
|
||||
var ideaVersion: IdeaVersion? = null
|
||||
|
||||
override fun toString(): String {
|
||||
return "IdeaPlugin(id=$id, sha256=$sha256, ideaVersion=$ideaVersion, channel=$channel, version=$version)"
|
||||
}
|
||||
}
|
||||
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
class IdeaVersion {
|
||||
@XmlAttribute(name = "until-build")
|
||||
var untilBuild: String? = null
|
||||
@XmlAttribute(name = "since-build")
|
||||
var sinceBuild: String? = null
|
||||
|
||||
override fun toString(): String {
|
||||
return "IdeaVersion(untilBuild=$untilBuild, sinceBuild=$sinceBuild)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.update
|
||||
|
||||
import com.intellij.ide.plugins.IdeaPluginDescriptor
|
||||
import com.intellij.openapi.util.registry.Registry
|
||||
import org.jetbrains.kotlin.idea.PluginUpdateStatus
|
||||
|
||||
// Do an additional verification with PluginUpdateVerifier. Enabled only in AS 3.2+
|
||||
fun verify(updateStatus: PluginUpdateStatus.Update): PluginUpdateStatus {
|
||||
@Suppress("InvalidBundleOrProperty")
|
||||
val pluginVerifierEnabled = Registry.`is`("kotlin.plugin.update.verifier.enabled", true)
|
||||
if (!pluginVerifierEnabled) {
|
||||
return updateStatus
|
||||
}
|
||||
|
||||
val pluginDescriptor: IdeaPluginDescriptor = updateStatus.pluginDescriptor
|
||||
val pluginVerifiers = PluginUpdateVerifier.EP_NAME.extensions
|
||||
|
||||
for (pluginVerifier in pluginVerifiers) {
|
||||
val verifyResult = pluginVerifier.verify(pluginDescriptor) ?: continue
|
||||
if (!verifyResult.verified) {
|
||||
return PluginUpdateStatus.Unverified(
|
||||
pluginVerifier.verifierName,
|
||||
verifyResult.declineMessage,
|
||||
updateStatus
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return updateStatus
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
import org.junit.Test
|
||||
|
||||
class <lineMarker descr="Run Test" settings="Nothing here">MyKotlinTest</lineMarker> {
|
||||
@Test
|
||||
fun <lineMarker descr="Run Test" settings="Nothing here">testA</lineMarker>() {
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
import org.junit.Test
|
||||
|
||||
class <lineMarker descr="Run Test" settings="Nothing here">MyKotlinTest</lineMarker> {
|
||||
@Test
|
||||
fun <lineMarker descr="Run Test" settings="Nothing here">testA</lineMarker>() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun <lineMarker descr="Run Test" settings="Nothing here">testB</lineMarker>() {
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
// "Add 'int' as 1st parameter to method 'K'" "true"
|
||||
|
||||
public class J {
|
||||
void foo() {
|
||||
new K(1);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
// "Add 'int' as 1st parameter to method 'K'" "true"
|
||||
|
||||
public class J {
|
||||
void foo() {
|
||||
new K(<caret>1);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
// "Add 'int' as 1st parameter to method 'K'" "true"
|
||||
|
||||
public class J {
|
||||
void foo() {
|
||||
new K(1);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
// "Add 'int' as 1st parameter to method 'K'" "true"
|
||||
|
||||
public class J {
|
||||
void foo() {
|
||||
new K(<caret>1);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
// "Add 'int' as 1st parameter to method 'K'" "true"
|
||||
|
||||
public class J {
|
||||
void foo() {
|
||||
new K(1);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
// "Add 'int' as 1st parameter to method 'K'" "true"
|
||||
|
||||
public class J {
|
||||
void foo() {
|
||||
new K(<caret>1);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
// "Change 2nd parameter of method 'K' from 'boolean' to 'String'" "true"
|
||||
|
||||
public class J {
|
||||
void foo() {
|
||||
new K(1, <caret>"2");
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
// "Change 2nd parameter of method 'K' from 'boolean' to 'String'" "true"
|
||||
|
||||
public class J {
|
||||
void foo() {
|
||||
new K(1, <caret>"2");
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
// "Change 2nd parameter of method 'K' from 'boolean' to 'String'" "true"
|
||||
|
||||
public class J {
|
||||
void foo() {
|
||||
new K(1, <caret>"2");
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
// "Change 2nd parameter of method 'K' from 'boolean' to 'String'" "true"
|
||||
|
||||
public class J {
|
||||
void foo() {
|
||||
new K(1, <caret>"2");
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
// "Add 'int' as 1st parameter to method 'Foo'" "true"
|
||||
|
||||
public class J {
|
||||
void test() {
|
||||
new Foo(<caret>1, 2);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
// "Add 'int' as 1st parameter to method 'Foo'" "true"
|
||||
|
||||
public class J {
|
||||
void test() {
|
||||
new Foo(<caret>1, 2);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
// "Add 'int' as 2nd parameter to method 'Foo'" "true"
|
||||
|
||||
public class J {
|
||||
void test() {
|
||||
new Foo(<caret>1, 2);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user