diff --git a/buildSrc/build.gradle.kts.182 b/buildSrc/build.gradle.kts.182 new file mode 100644 index 00000000000..ad887218a28 --- /dev/null +++ b/buildSrc/build.gradle.kts.182 @@ -0,0 +1,94 @@ + +buildscript { + val buildSrcKotlinVersion: String by extra(findProperty("buildSrc.kotlin.version")?.toString() ?: embeddedKotlinVersion) + val buildSrcKotlinRepo: String? by extra(findProperty("buildSrc.kotlin.repo") as String?) + extra["versions.shadow"] = "2.0.2" + extra["versions.native-platform"] = "0.14" + + repositories { + buildSrcKotlinRepo?.let { + maven(url = it) + } + } + + dependencies { + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$buildSrcKotlinVersion") + classpath("org.jetbrains.kotlin:kotlin-sam-with-receiver:$buildSrcKotlinVersion") + } +} + +logger.info("buildSrcKotlinVersion: " + extra["buildSrcKotlinVersion"]) +logger.info("buildSrc kotlin compiler version: " + org.jetbrains.kotlin.config.KotlinCompilerVersion.VERSION) +logger.info("buildSrc stdlib version: " + KotlinVersion.CURRENT) + +apply { + plugin("kotlin") + plugin("kotlin-sam-with-receiver") +} + +plugins { + `kotlin-dsl` + `java-gradle-plugin` +} + +gradlePlugin { + (plugins) { + "pill-configurable" { + id = "pill-configurable" + implementationClass = "org.jetbrains.kotlin.pill.PillConfigurablePlugin" + } + "jps-compatible" { + id = "jps-compatible" + implementationClass = "org.jetbrains.kotlin.pill.JpsCompatiblePlugin" + } + } +} + +fun Project.getBooleanProperty(name: String): Boolean? = this.findProperty(name)?.let { + val v = it.toString() + if (v.isBlank()) true + else v.toBoolean() +} + +rootProject.apply { + from(rootProject.file("../versions.gradle.kts")) +} + +val isTeamcityBuild = project.hasProperty("teamcity") || System.getenv("TEAMCITY_VERSION") != null +val intellijUltimateEnabled by extra(project.getBooleanProperty("intellijUltimateEnabled") ?: isTeamcityBuild) +val intellijSeparateSdks by extra(project.getBooleanProperty("intellijSeparateSdks") ?: false) + +extra["intellijRepo"] = "https://www.jetbrains.com/intellij-repository" +extra["intellijReleaseType"] = "snapshots" // or "snapshots" +extra["versions.androidDxSources"] = "5.0.0_r2" + +extra["customDepsOrg"] = "kotlin.build.custom.deps" + +repositories { + extra["buildSrcKotlinRepo"]?.let { + maven(url = it) + } + maven(url = "https://repo.gradle.org/gradle/ext-releases-local") // for native-platform + jcenter() +} + +dependencies { + compile("net.rubygrapefruit:native-platform:${property("versions.native-platform")}") + compile("net.rubygrapefruit:native-platform-windows-amd64:${property("versions.native-platform")}") + compile("net.rubygrapefruit:native-platform-windows-i386:${property("versions.native-platform")}") + compile("com.jakewharton.dex:dex-method-list:3.0.0") + // TODO: adding the dep to the plugin breaks the build unexpectedly, resolve and uncomment +// compile("org.jetbrains.kotlin:kotlin-gradle-plugin:${rootProject.extra["bootstrap_kotlin_version"]}") + // Shadow plugin is used in many projects of the main build. Once it's no longer used in buildSrc, please move this dependency to the root project + compile("com.github.jengelman.gradle.plugins:shadow:${property("versions.shadow")}") + compile("org.ow2.asm:asm-all:6.0_BETA") +} + +samWithReceiver { + annotation("org.gradle.api.HasImplicitReceiver") +} + +fun Project.`samWithReceiver`(configure: org.jetbrains.kotlin.samWithReceiver.gradle.SamWithReceiverExtension.() -> Unit): Unit = + extensions.configure("samWithReceiver", configure) + +tasks["build"].dependsOn(":prepare-deps:android-dx:build", ":prepare-deps:intellij-sdk:build") diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/KtCodeFragment.kt.182 b/compiler/psi/src/org/jetbrains/kotlin/psi/KtCodeFragment.kt.182 new file mode 100644 index 00000000000..18a68eecdd2 --- /dev/null +++ b/compiler/psi/src/org/jetbrains/kotlin/psi/KtCodeFragment.kt.182 @@ -0,0 +1,203 @@ +/* + * 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.psi + +import com.intellij.openapi.diagnostic.Logger +import com.intellij.openapi.project.Project +import com.intellij.openapi.util.Key +import com.intellij.psi.* +import com.intellij.psi.impl.PsiManagerEx +import com.intellij.psi.impl.source.tree.FileElement +import com.intellij.psi.search.GlobalSearchScope +import com.intellij.psi.tree.IElementType +import com.intellij.testFramework.LightVirtualFile +import org.jetbrains.kotlin.idea.KotlinFileType +import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext +import org.jetbrains.kotlin.types.KotlinType +import java.util.* + +abstract class KtCodeFragment( + private val _project: Project, + name: String, + text: CharSequence, + imports: String?, // Should be separated by JetCodeFragment.IMPORT_SEPARATOR + elementType: IElementType, + private val context: PsiElement? +) : KtFile( + (PsiManager.getInstance(_project) as PsiManagerEx).fileManager.createFileViewProvider( + LightVirtualFile( + name, + KotlinFileType.INSTANCE, + text + ), true + ), false +), JavaCodeFragment { + + private var viewProvider = super.getViewProvider() as SingleRootFileViewProvider + private var imports = LinkedHashSet() + + private val fakeContextForJavaFile: PsiElement? by lazy { + this.getCopyableUserData(FAKE_CONTEXT_FOR_JAVA_FILE)?.invoke() + } + + init { + getViewProvider().forceCachedPsi(this) + init(TokenType.CODE_FRAGMENT, elementType) + if (context != null) { + initImports(imports) + } + } + + override final fun init(elementType: IElementType, contentElementType: IElementType?) { + super.init(elementType, contentElementType) + } + + private var resolveScope: GlobalSearchScope? = null + private var thisType: PsiType? = null + private var superType: PsiType? = null + private var exceptionHandler: JavaCodeFragment.ExceptionHandler? = null + private var isPhysical = true + + abstract fun getContentElement(): KtElement? + + override fun forceResolveScope(scope: GlobalSearchScope?) { + resolveScope = scope + } + + override fun getForcedResolveScope() = resolveScope + + override fun isPhysical() = isPhysical + + override fun isValid() = true + + override fun getContext(): PsiElement? { + if (fakeContextForJavaFile != null) return fakeContextForJavaFile + if (context !is KtElement) { + LOG.warn("CodeFragment with non-kotlin context should have fakeContextForJavaFile set: \noriginalContext = ${context?.getElementTextWithContext()}") + return null + } + + return context + } + + override fun getResolveScope() = context?.resolveScope ?: super.getResolveScope() + + override fun clone(): KtCodeFragment { + val clone = cloneImpl(calcTreeElement().clone() as FileElement) as KtCodeFragment + clone.isPhysical = false + clone.originalFile = this + clone.imports = imports + clone.viewProvider = + SingleRootFileViewProvider(PsiManager.getInstance(_project), LightVirtualFile(name, KotlinFileType.INSTANCE, text), false) + clone.viewProvider.forceCachedPsi(clone) + return clone + } + + final override fun getViewProvider() = viewProvider + + override fun getThisType() = thisType + + override fun setThisType(psiType: PsiType?) { + thisType = psiType + } + + override fun getSuperType() = superType + + override fun setSuperType(superType: PsiType?) { + this.superType = superType + } + + override fun importsToString(): String { + return imports.joinToString(IMPORT_SEPARATOR) + } + + override fun addImportsFromString(imports: String?) { + if (imports == null || imports.isEmpty()) return + + imports.split(IMPORT_SEPARATOR).forEach { + addImport(it) + } + + // we need this code to force re-highlighting, otherwise it does not work by some reason + val tempElement = KtPsiFactory(project).createColon() + add(tempElement).delete() + } + + fun addImport(import: String) { + val contextFile = getContextContainingFile() + if (contextFile != null) { + if (contextFile.importDirectives.find { it.text == import } == null) { + imports.add(import) + } + } + } + + fun importsAsImportList(): KtImportList? { + if (!imports.isEmpty() && context != null) { + return KtPsiFactory(this).createAnalyzableFile("imports_for_codeFragment.kt", imports.joinToString("\n"), context).importList + } + return null + } + + override val importDirectives: List + get() = importsAsImportList()?.imports ?: emptyList() + + override fun setVisibilityChecker(checker: JavaCodeFragment.VisibilityChecker?) {} + + override fun getVisibilityChecker() = JavaCodeFragment.VisibilityChecker.EVERYTHING_VISIBLE + + override fun setExceptionHandler(checker: JavaCodeFragment.ExceptionHandler?) { + exceptionHandler = checker + } + + override fun getExceptionHandler() = exceptionHandler + + override fun importClass(aClass: PsiClass): Boolean { + return true + } + + fun getContextContainingFile(): KtFile? { + return getOriginalContext()?.containingKtFile + } + + fun getOriginalContext(): KtElement? { + val contextElement = getContext() as? KtElement + val contextFile = contextElement?.containingKtFile + if (contextFile is KtCodeFragment) { + return contextFile.getOriginalContext() + } + return contextElement + } + + private fun initImports(imports: String?) { + if (imports != null && !imports.isEmpty()) { + + val importsWithPrefix = imports.split(IMPORT_SEPARATOR).map { it.takeIf { it.startsWith("import ") } ?: "import ${it.trim()}" } + importsWithPrefix.forEach { + addImport(it) + } + } + } + + companion object { + val IMPORT_SEPARATOR: String = "," + val RUNTIME_TYPE_EVALUATOR: Key> = Key.create("RUNTIME_TYPE_EVALUATOR") + val FAKE_CONTEXT_FOR_JAVA_FILE: Key> = Key.create("FAKE_CONTEXT_FOR_JAVA_FILE") + + private val LOG = Logger.getInstance(KtCodeFragment::class.java) + } +} diff --git a/j2k/tests/org/jetbrains/kotlin/j2k/AbstractJavaToKotlinConverterForWebDemoTest.kt.182 b/j2k/tests/org/jetbrains/kotlin/j2k/AbstractJavaToKotlinConverterForWebDemoTest.kt.182 new file mode 100644 index 00000000000..c8790da5fc6 --- /dev/null +++ b/j2k/tests/org/jetbrains/kotlin/j2k/AbstractJavaToKotlinConverterForWebDemoTest.kt.182 @@ -0,0 +1,138 @@ +/* + * 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.j2k + +import com.intellij.codeInsight.ContainerProvider +import com.intellij.codeInsight.NullableNotNullManager +import com.intellij.codeInsight.runner.JavaMainMethodProvider +import com.intellij.core.CoreApplicationEnvironment +import com.intellij.core.JavaCoreApplicationEnvironment +import com.intellij.core.JavaCoreProjectEnvironment +import com.intellij.lang.MetaLanguage +import com.intellij.lang.jvm.facade.JvmElementProvider +import com.intellij.openapi.extensions.Extensions +import com.intellij.openapi.extensions.ExtensionsArea +import com.intellij.openapi.fileTypes.FileTypeExtensionPoint +import com.intellij.openapi.util.Disposer +import com.intellij.openapi.util.io.FileUtil +import com.intellij.psi.* +import com.intellij.psi.augment.PsiAugmentProvider +import com.intellij.psi.augment.TypeAnnotationModifier +import com.intellij.psi.compiled.ClassFileDecompilers +import com.intellij.psi.impl.JavaClassSupersImpl +import com.intellij.psi.impl.PsiTreeChangePreprocessor +import com.intellij.psi.impl.compiled.ClsCustomNavigationPolicy +import com.intellij.psi.meta.MetaDataContributor +import com.intellij.psi.stubs.BinaryFileStubBuilders +import com.intellij.psi.util.JavaClassSupers +import junit.framework.TestCase +import org.jetbrains.kotlin.utils.PathUtil +import java.io.File +import java.net.URLClassLoader + +abstract class AbstractJavaToKotlinConverterForWebDemoTest : TestCase() { + val DISPOSABLE = Disposer.newDisposable() + + fun doTest(javaPath: String) { + try { + val fileContents = FileUtil.loadFile(File(javaPath), true) + val javaCoreEnvironment: JavaCoreProjectEnvironment = setUpJavaCoreEnvironment() + translateToKotlin(fileContents, javaCoreEnvironment.project) + } + finally { + Disposer.dispose(DISPOSABLE) + } + } + + fun setUpJavaCoreEnvironment(): JavaCoreProjectEnvironment { + Extensions.cleanRootArea(DISPOSABLE) + val area = Extensions.getRootArea() + + registerExtensionPoints(area) + + val applicationEnvironment = JavaCoreApplicationEnvironment(DISPOSABLE) + val javaCoreEnvironment = object : JavaCoreProjectEnvironment(DISPOSABLE, applicationEnvironment) { + override fun preregisterServices() { + val projectArea = Extensions.getArea(project) + CoreApplicationEnvironment.registerExtensionPoint(projectArea, PsiTreeChangePreprocessor.EP_NAME, PsiTreeChangePreprocessor::class.java) + CoreApplicationEnvironment.registerExtensionPoint(projectArea, PsiElementFinder.EP_NAME, PsiElementFinder::class.java) + CoreApplicationEnvironment.registerExtensionPoint(projectArea, JvmElementProvider.EP_NAME, JvmElementProvider::class.java) + } + } + + javaCoreEnvironment.project.registerService(NullableNotNullManager::class.java, object : NullableNotNullManager(javaCoreEnvironment.project) { + override fun isNullable(owner: PsiModifierListOwner, checkBases: Boolean) = !isNotNull(owner, checkBases) + override fun isNotNull(owner: PsiModifierListOwner, checkBases: Boolean) = true + override fun hasHardcodedContracts(element: PsiElement): Boolean = false + override fun getNullables() = emptyList() + override fun setNullables(vararg p0: String) = Unit + override fun getNotNulls() = emptyList() + override fun setNotNulls(vararg p0: String) = Unit + override fun getDefaultNullable() = "" + override fun setDefaultNullable(defaultNullable: String) = Unit + override fun getDefaultNotNull() = "" + override fun setDefaultNotNull(p0: String) = Unit + override fun setInstrumentedNotNulls(p0: List) = Unit + override fun getInstrumentedNotNulls() = emptyList() + override fun isJsr305Default(psiAnnotation: PsiAnnotation, p1: Array) = null + }) + + applicationEnvironment.application.registerService(JavaClassSupers::class.java, JavaClassSupersImpl::class.java) + + for (root in PathUtil.getJdkClassesRootsFromCurrentJre()) { + javaCoreEnvironment.addJarToClassPath(root) + } + val annotations: File? = findAnnotations() + if (annotations != null && annotations.exists()) { + javaCoreEnvironment.addJarToClassPath(annotations) + } + return javaCoreEnvironment + } + + private fun registerExtensionPoints(area: ExtensionsArea) { + CoreApplicationEnvironment.registerExtensionPoint(area, BinaryFileStubBuilders.EP_NAME, FileTypeExtensionPoint::class.java) + CoreApplicationEnvironment.registerExtensionPoint(area, FileContextProvider.EP_NAME, FileContextProvider::class.java) + + CoreApplicationEnvironment.registerExtensionPoint(area, MetaDataContributor.EP_NAME, MetaDataContributor::class.java) + CoreApplicationEnvironment.registerExtensionPoint(area, PsiAugmentProvider.EP_NAME, PsiAugmentProvider::class.java) + CoreApplicationEnvironment.registerExtensionPoint(area, JavaMainMethodProvider.EP_NAME, JavaMainMethodProvider::class.java) + + CoreApplicationEnvironment.registerExtensionPoint(area, ContainerProvider.EP_NAME, ContainerProvider::class.java) + CoreApplicationEnvironment.registerExtensionPoint(area, ClsCustomNavigationPolicy.EP_NAME, ClsCustomNavigationPolicy::class.java) + CoreApplicationEnvironment.registerExtensionPoint(area, ClassFileDecompilers.EP_NAME, ClassFileDecompilers.Decompiler::class.java) + + CoreApplicationEnvironment.registerExtensionPoint(area, TypeAnnotationModifier.EP_NAME, TypeAnnotationModifier::class.java) + CoreApplicationEnvironment.registerExtensionPoint(area, MetaLanguage.EP_NAME, MetaLanguage::class.java) + CoreApplicationEnvironment.registerExtensionPoint(area, JavaModuleSystem.EP_NAME, JavaModuleSystem::class.java) + } + + fun findAnnotations(): File? { + var classLoader = JavaToKotlinTranslator::class.java.classLoader + while (classLoader != null) { + val loader = classLoader + if (loader is URLClassLoader) { + for (url in loader.urLs) { + if ("file" == url.protocol && url.file!!.endsWith("/annotations.jar")) { + return File(url.file!!) + } + } + } + classLoader = classLoader.parent + } + return null + } +} diff --git a/versions.gradle.kts.182 b/versions.gradle.kts.182 index b4c9a4638c0..e2d51946de3 100644 --- a/versions.gradle.kts.182 +++ b/versions.gradle.kts.182 @@ -1,5 +1,5 @@ -extra["versions.intellijSdk"] = "182.2371.4" +extra["versions.intellijSdk"] = "182-SNAPSHOT" extra["versions.androidBuildTools"] = "r23.0.1" extra["versions.idea.NodeJS"] = "181.3494.12" //extra["versions.androidStudioRelease"] = "3.1.0.5"