diff --git a/kotlin-bundled-compiler/META-INF/MANIFEST.MF b/kotlin-bundled-compiler/META-INF/MANIFEST.MF index ef0e69108..d5c401fed 100644 --- a/kotlin-bundled-compiler/META-INF/MANIFEST.MF +++ b/kotlin-bundled-compiler/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Bundled Kotlin Compiler Bundle-SymbolicName: org.jetbrains.kotlin.bundled-compiler;singleton:=true -Bundle-Version: 0.8.7.qualifier +Bundle-Version: 0.8.8.qualifier Bundle-Vendor: JetBrains Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-ClassPath: ., diff --git a/kotlin-bundled-compiler/build.properties b/kotlin-bundled-compiler/build.properties index ee8fdd479..516ab323b 100644 --- a/kotlin-bundled-compiler/build.properties +++ b/kotlin-bundled-compiler/build.properties @@ -31,7 +31,8 @@ bin.includes = META-INF/,\ lib/kotlin-script-runtime.jar,\ lib/allopen-compiler-plugin.jar,\ lib/sam-with-receiver-compiler-plugin.jar,\ - lib/noarg-compiler-plugin.jar + lib/noarg-compiler-plugin.jar,\ + lib/annotations-13.0.jar src.includes = lib/ bin.excludes = lib/kotlin-compiler-sources.jar,\ lib/downloads/ diff --git a/kotlin-bundled-compiler/get_bundled.xml b/kotlin-bundled-compiler/get_bundled.xml index d34bbae12..170c309e7 100644 --- a/kotlin-bundled-compiler/get_bundled.xml +++ b/kotlin-bundled-compiler/get_bundled.xml @@ -1,16 +1,16 @@ - + - + - + + value="${teamcity-base}/guestAuth/app/rest/builds/buildType:Kotlin_130_CompilerAllPlugins,status:success,count:1/artifacts/content"/> @@ -86,7 +86,7 @@ @@ -192,6 +192,7 @@ + @@ -218,16 +219,16 @@ - + - + RANGE_COMPARATOR = new Comparator() { + @Override + public int compare(TextRange range1, TextRange range2) { + int startOffsetDiff = range1.getStartOffset() - range2.getStartOffset(); + return startOffsetDiff != 0 ? startOffsetDiff : range1.getEndOffset() - range2.getEndOffset(); + } + }; + + private TextRangeUtil() { + } + + /** + * Excludes ranges from the original range. For example, if the original range is [30..100] and ranges to exclude are + * [20..50] and [60..90], resulting ranges will be [50..60] and [90..100]. The ranges may overlap and follow in any order. In the latter + * case the original list of excluded ranges is sorted by start/end offset. + * + * @param original The original range to exclude the ranges from. + * @param excludedRanges The list of ranges to exclude. + * @return A list of ranges after excluded ranges have been applied. + */ + public static Iterable excludeRanges(@NotNull TextRange original, @NotNull List excludedRanges) { + if (!excludedRanges.isEmpty()) { + if (excludedRanges.size() > 1) { + Collections.sort(excludedRanges, RANGE_COMPARATOR); + } + int enabledRangeStart = original.getStartOffset(); + List enabledRanges = new ArrayList(); + for (TextRange excludedRange : excludedRanges) { + if (excludedRange.getEndOffset() < enabledRangeStart) continue; + int excludedRangeStart = excludedRange.getStartOffset(); + if (excludedRangeStart > original.getEndOffset()) break; + if (excludedRangeStart > enabledRangeStart) { + enabledRanges.add(new TextRange(enabledRangeStart, excludedRangeStart)); + } + enabledRangeStart = excludedRange.getEndOffset(); + } + if (enabledRangeStart < original.getEndOffset()) { + enabledRanges.add(new TextRange(enabledRangeStart, original.getEndOffset())); + } + return enabledRanges; + } + return Collections.singletonList(original); + } + + /** + * Return least text range that contains all of passed text ranges. + * For example for {[0, 3],[3, 7],[10, 17]} this method will return [0, 17] + * @param textRanges The list of ranges to process + * @return least text range that contains all of passed text ranges + */ + @NotNull + public static TextRange getEnclosingTextRange(@NotNull List textRanges) { + if(textRanges.isEmpty()) + return TextRange.EMPTY_RANGE; + int lowerBound = textRanges.get(0).getStartOffset(); + int upperBound = textRanges.get(0).getEndOffset(); + for(int i = 1; i < textRanges.size(); ++i) { + TextRange textRange = textRanges.get(i); + lowerBound = Math.min(lowerBound, textRange.getStartOffset()); + upperBound = Math.max(upperBound, textRange.getEndOffset()); + } + return new TextRange(lowerBound, upperBound); + } + + public static int getDistance(@NotNull Segment r2, @NotNull Segment r1) { + int s1 = r1.getStartOffset(); + int e1 = r1.getEndOffset(); + int s2 = r2.getStartOffset(); + int e2 = r2.getEndOffset(); + return Math.max(s1, s2) <= Math.min(e1, e2) ? 0 : Math.min(Math.abs(s1 - e2), Math.abs(s2 - e1)); + } +} diff --git a/kotlin-eclipse-aspects/.classpath b/kotlin-eclipse-aspects/.classpath index 1ee93acd9..9fcfb446e 100644 --- a/kotlin-eclipse-aspects/.classpath +++ b/kotlin-eclipse-aspects/.classpath @@ -3,6 +3,8 @@ + + diff --git a/kotlin-eclipse-aspects/.project b/kotlin-eclipse-aspects/.project index 3da7649e3..2ff8cf783 100644 --- a/kotlin-eclipse-aspects/.project +++ b/kotlin-eclipse-aspects/.project @@ -5,6 +5,11 @@ + + org.jetbrains.kotlin.ui.kotlinBuilder + + + org.eclipse.ajdt.core.ajbuilder @@ -25,6 +30,7 @@ org.eclipse.ajdt.ui.ajnature org.eclipse.pde.PluginNature org.eclipse.jdt.core.javanature + org.jetbrains.kotlin.core.kotlinNature diff --git a/kotlin-eclipse-aspects/META-INF/MANIFEST.MF b/kotlin-eclipse-aspects/META-INF/MANIFEST.MF index 1334ee20f..e4d10767a 100644 --- a/kotlin-eclipse-aspects/META-INF/MANIFEST.MF +++ b/kotlin-eclipse-aspects/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: kotlin-eclipse-aspects Bundle-SymbolicName: org.jetbrains.kotlin.aspects -Bundle-Version: 0.8.7.qualifier +Bundle-Version: 0.8.8.qualifier Bundle-Activator: org.jetbrains.kotlin.aspects.Activator Require-Bundle: org.eclipse.ui, org.eclipse.core.runtime, @@ -33,7 +33,9 @@ Import-Package: org.eclipse.core.resources, org.eclipse.jdt.launching.sourcelookup.containers, org.eclipse.jface.text, org.eclipse.ui.ide, - org.eclipse.jdt.internal.ui.viewsupport + org.eclipse.jdt.internal.ui.packageview, + org.eclipse.jdt.internal.ui.viewsupport, + org.eclipse.swt.graphics Eclipse-SupplementBundle: org.eclipse.jdt.debug.ui, org.eclipse.jdt.debug, diff --git a/kotlin-eclipse-aspects/pom.xml b/kotlin-eclipse-aspects/pom.xml index 0fcc5d3b1..661b502fc 100644 --- a/kotlin-eclipse-aspects/pom.xml +++ b/kotlin-eclipse-aspects/pom.xml @@ -8,7 +8,7 @@ ../pom.xml kotlin.eclipse kotlin.eclipse.plugin - 0.8.7-SNAPSHOT + 0.8.8-SNAPSHOT org.jetbrains.kotlin.aspects diff --git a/kotlin-eclipse-core/META-INF/MANIFEST.MF b/kotlin-eclipse-core/META-INF/MANIFEST.MF index 73f866837..4a76e5885 100644 --- a/kotlin-eclipse-core/META-INF/MANIFEST.MF +++ b/kotlin-eclipse-core/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: kotlin-eclipse-core Bundle-SymbolicName: org.jetbrains.kotlin.core;singleton:=true -Bundle-Version: 0.8.7.qualifier +Bundle-Version: 0.8.8.qualifier Bundle-Activator: org.jetbrains.kotlin.core.Activator Bundle-Vendor: JetBrains Require-Bundle: org.jetbrains.kotlin.bundled-compiler, @@ -32,6 +32,7 @@ Export-Package: org.jetbrains.kotlin.core, org.jetbrains.kotlin.core.compiler, org.jetbrains.kotlin.core.debug, org.jetbrains.kotlin.core.filesystem, + org.jetbrains.kotlin.core.formatting, org.jetbrains.kotlin.core.launch, org.jetbrains.kotlin.core.log, org.jetbrains.kotlin.core.model, diff --git a/kotlin-eclipse-core/plugin.xml b/kotlin-eclipse-core/plugin.xml index 5fa81bcd6..9505b515b 100644 --- a/kotlin-eclipse-core/plugin.xml +++ b/kotlin-eclipse-core/plugin.xml @@ -3,6 +3,7 @@ + + + + + + + diff --git a/kotlin-eclipse-core/pom.xml b/kotlin-eclipse-core/pom.xml index fc208faf3..76881d210 100644 --- a/kotlin-eclipse-core/pom.xml +++ b/kotlin-eclipse-core/pom.xml @@ -8,7 +8,7 @@ ../pom.xml kotlin.eclipse kotlin.eclipse.plugin - 0.8.7-SNAPSHOT + 0.8.8-SNAPSHOT org.jetbrains.kotlin.core diff --git a/kotlin-eclipse-core/preferences.ini b/kotlin-eclipse-core/preferences.ini index ec9e681f4..c71553e45 100644 --- a/kotlin-eclipse-core/preferences.ini +++ b/kotlin-eclipse-core/preferences.ini @@ -11,3 +11,4 @@ compilerPlugins/jpa/jarPath=$KOTLIN_HOME/lib/noarg-compiler-plugin.jar compilerPlugins/jpa/args=org.jetbrains.kotlin.noarg:preset=jpa compilerPlugins/sam-with-receiver/active=false compilerPlugins/sam-with-receiver/jarPath=$KOTLIN_HOME/lib/sam-with-receiver-compiler-plugin.jar +codeStyle/codeStyleId=KOTLIN_OLD_DEFAULTS diff --git a/kotlin-eclipse-core/schema/org.jetbrains.kotlin.core.predefinedKotlinCodeStyle.exsd b/kotlin-eclipse-core/schema/org.jetbrains.kotlin.core.predefinedKotlinCodeStyle.exsd new file mode 100644 index 000000000..e9dc42bba --- /dev/null +++ b/kotlin-eclipse-core/schema/org.jetbrains.kotlin.core.predefinedKotlinCodeStyle.exsd @@ -0,0 +1,102 @@ + + + + + + + + + [Enter description of this extension point.] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + [Enter the first release in which this extension point appears.] + + + + + + + + + [Enter extension point usage example here.] + + + + + + + + + [Enter API information here.] + + + + + + + + + [Enter information about supplied implementation of this extension point.] + + + + + diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/KotlinClasspathContainer.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/KotlinClasspathContainer.kt index fcc71451f..c5f849ed6 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/KotlinClasspathContainer.kt +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/KotlinClasspathContainer.kt @@ -24,34 +24,34 @@ import org.eclipse.jdt.core.IJavaProject import org.eclipse.jdt.core.JavaCore import org.jetbrains.kotlin.core.model.KotlinJavaManager import org.jetbrains.kotlin.core.utils.ProjectUtils -import java.util.ArrayList -import kotlin.jvm.JvmStatic +import java.util.* val runtimeContainerId: IPath = Path("org.jetbrains.kotlin.core.KOTLIN_CONTAINER") fun newExportedLibraryEntry(path: IPath): IClasspathEntry = JavaCore.newLibraryEntry(path, null, null, true) -public class KotlinClasspathContainer(val javaProject: IJavaProject) : IClasspathContainer { +class KotlinClasspathContainer(val javaProject: IJavaProject) : IClasspathContainer { companion object { val CONTAINER_ENTRY: IClasspathEntry = JavaCore.newContainerEntry(runtimeContainerId) val LIB_RUNTIME_NAME = "kotlin-stdlib" val LIB_RUNTIME_SRC_NAME = "kotlin-stdlib-sources" val LIB_REFLECT_NAME = "kotlin-reflect" val LIB_SCRIPT_RUNTIME_NAME = "kotlin-script-runtime" - + val LIB_ANNOTATIONS_1_3 = "annotations-13.0" + @JvmStatic - public fun getPathToLightClassesFolder(javaProject: IJavaProject): IPath { - return Path(javaProject.getProject().getName()).append(KotlinJavaManager.KOTLIN_BIN_FOLDER).makeAbsolute() + fun getPathToLightClassesFolder(javaProject: IJavaProject): IPath { + return Path(javaProject.project.name).append(KotlinJavaManager.KOTLIN_BIN_FOLDER).makeAbsolute() } } - - override public fun getClasspathEntries() : Array { + + override fun getClasspathEntries(): Array { val entries = ArrayList() val kotlinBinFolderEntry = newExportedLibraryEntry(getPathToLightClassesFolder(javaProject)) entries.add(kotlinBinFolderEntry) - - val project = javaProject.getProject() + + val project = javaProject.project if (!ProjectUtils.isMavenProject(project) && !ProjectUtils.isGradleProject(project)) { val kotlinRuntimeEntry = JavaCore.newLibraryEntry( LIB_RUNTIME_NAME.buildLibPath(), @@ -60,20 +60,22 @@ public class KotlinClasspathContainer(val javaProject: IJavaProject) : IClasspat true) val kotlinReflectEntry = newExportedLibraryEntry(LIB_REFLECT_NAME.buildLibPath()) val kotlinScriptRuntime = newExportedLibraryEntry(LIB_SCRIPT_RUNTIME_NAME.buildLibPath()) + val annotations13 = newExportedLibraryEntry(LIB_ANNOTATIONS_1_3.buildLibPath()) entries.add(kotlinRuntimeEntry) entries.add(kotlinReflectEntry) entries.add(kotlinScriptRuntime) + entries.add(annotations13) } return entries.toTypedArray() } - - override public fun getDescription() : String = "Kotlin Runtime Library" - - override public fun getKind() : Int = IClasspathContainer.K_APPLICATION - - override public fun getPath() : IPath = runtimeContainerId + + override fun getDescription(): String = "Kotlin Runtime Library" + + override fun getKind(): Int = IClasspathContainer.K_APPLICATION + + override fun getPath(): IPath = runtimeContainerId } fun String.buildLibPath(): Path = Path(ProjectUtils.buildLibPath(this)) \ No newline at end of file diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/builder/KotlinPsiManager.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/builder/KotlinPsiManager.kt index 70c3dfa0c..ea2ebd001 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/builder/KotlinPsiManager.kt +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/builder/KotlinPsiManager.kt @@ -59,13 +59,22 @@ interface PsiFilesStorage { fun removeFile(file: IFile) } +private fun parseFile(file: IFile): KtFile = + KotlinPsiManager.parseFile(file) ?: throw IllegalStateException("Can't parse file $file") + +private fun parseIfNotSame(file: IFile, ktFile: KtFile?, expectedSourceCode: String): KtFile = + if (ktFile != null && ktFile.getText().equals(StringUtilRt.convertLineSeparators(expectedSourceCode))) { + ktFile + } + else parseFile(file) + private class ScriptsFilesStorage : PsiFilesStorage { private val cachedKtFiles = ConcurrentHashMap() override fun getPsiFile(eclipseFile: IFile): KtFile { assert(isApplicable(eclipseFile)) { "$eclipseFile is not applicable for Kotlin scripts storage" } - return cachedKtFiles.getOrPut(eclipseFile) { KotlinPsiManager.parseFile(eclipseFile)!! } + return cachedKtFiles.getOrPut(eclipseFile) { parseFile(eclipseFile) } } @Synchronized @@ -94,109 +103,113 @@ private class ProjectSourceFiles : PsiFilesStorage { fun isKotlinFile(file: IFile): Boolean = KotlinFileType.INSTANCE.getDefaultExtension() == file.fileExtension } - private val projectFiles = hashMapOf>() - private val cachedKtFiles = hashMapOf() - private val mapOperationLock = Any() + private val projectFiles = ConcurrentHashMap>() + private val cachedKtFiles = ConcurrentHashMap() override fun getPsiFile(eclipseFile: IFile): KtFile { - synchronized (mapOperationLock) { - updateProjectPsiSourcesIfNeeded(eclipseFile.getProject()) + updateProjectPsiSourcesIfNeeded(eclipseFile.getProject()) - assert(existsInProjectSources(eclipseFile), { "File(" + eclipseFile.getName() + ") does not contain in the psiFiles" }) + assert(existsInProjectSources(eclipseFile), { "File(" + eclipseFile.getName() + ") does not contain in the psiFiles" }) - return cachedKtFiles.getOrPut(eclipseFile) { - KotlinPsiManager.parseFile(eclipseFile) ?: throw IllegalStateException("Can't parse file $eclipseFile") - } - } + return cachedKtFiles.getOrPut(eclipseFile) { parseFile(eclipseFile) } } override fun getPsiFile(file: IFile, expectedSourceCode: String): KtFile { - synchronized (mapOperationLock) { - updatePsiFile(file, expectedSourceCode) - return getPsiFile(file) - } + updateProjectPsiSourcesIfNeeded(file.getProject()) + + assert(existsInProjectSources(file), { "File(" + file.getName() + ") does not contain in the psiFiles" }) + + return cachedKtFiles.compute(file) { _,cachedKtFile -> + parseIfNotSame(file, cachedKtFile, expectedSourceCode) + }!! } override fun isApplicable(file: IFile): Boolean = existsInProjectSources(file) fun existsInProjectSources(file: IFile): Boolean { - synchronized (mapOperationLock) { - val project = file.getProject() ?: return false - - updateProjectPsiSourcesIfNeeded(project) - - val files = projectFiles[project] - return if (files != null) files.contains(file) else false + val project = file.getProject() ?: return false + + val exists = projectFiles.compute(project) { _,origFiles -> + origFiles ?: computeProjectPsiSources(project, origFiles) } + ?.contains(file) ?: false + + return exists } fun containsProject(project: IProject): Boolean { - return synchronized (mapOperationLock) { - projectFiles.containsKey(project) - } + return projectFiles.containsKey(project) } fun getFilesByProject(project: IProject): Set { - synchronized (mapOperationLock) { - updateProjectPsiSourcesIfNeeded(project) - - if (projectFiles.containsKey(project)) { - return Collections.unmodifiableSet(projectFiles[project]) - } - - return emptySet() + val files = projectFiles.compute(project) { _,origFiles -> + origFiles ?: computeProjectPsiSources(project, origFiles) } + + return if (files != null) + Collections.unmodifiableSet(files) + else + emptySet() } fun addFile(file: IFile) { - synchronized (mapOperationLock) { - assert(KotlinNature.hasKotlinNature(file.getProject()), - { "Project (" + file.getProject().getName() + ") does not have Kotlin nature" }) - - assert(!existsInProjectSources(file), { "File(" + file.getName() + ") is already added" }) - - projectFiles - .getOrPut(file.project) { hashSetOf() } - .add(file) + assert(KotlinNature.hasKotlinNature(file.getProject()), + { "Project (" + file.getProject().getName() + ") does not have Kotlin nature" }) + + assert(!existsInProjectSources(file), { "File(" + file.getName() + ") is already added" }) + + projectFiles.compute(file.project) { _,origFiles -> + val files = origFiles ?: hashSetOf() + files.add(file) + files } } override fun removeFile(file: IFile) { - synchronized (mapOperationLock) { - assert(existsInProjectSources(file), { "File(" + file.getName() + ") does not contain in the psiFiles" }) - + assert(existsInProjectSources(file), { "File(" + file.getName() + ") does not contain in the psiFiles" }) + + projectFiles.compute(file.project) { _,origFiles -> cachedKtFiles.remove(file) - projectFiles.get(file.project)?.remove(file) - } + origFiles?.remove(file) + origFiles + } } fun addProject(project: IProject) { - synchronized (mapOperationLock) { - if (ProjectUtils.isAccessibleKotlinProject(project)) { - addFilesToParse(JavaCore.create(project)) - } + projectFiles.compute(project) { _,origFiles -> + computeProjectPsiSources(project, origFiles) } } + fun computeProjectPsiSources(project: IProject, origFiles: HashSet? = null) = + if (ProjectUtils.isAccessibleKotlinProject(project)) { + getFilesToParse(JavaCore.create(project)) + } + else origFiles + fun removeProject(project: IProject) { - synchronized (mapOperationLock) { - val files = getFilesByProject(project) - - projectFiles.remove(project) - for (file in files) { + projectFiles.computeIfPresent(project) { _,origFiles -> + for (file in origFiles) { cachedKtFiles.remove(file) } + null } } fun addFilesToParse(javaProject: IJavaProject) { + projectFiles.compute(javaProject.getProject()) { _,_ -> + getFilesToParse(javaProject) + } + } + + fun getFilesToParse(javaProject: IJavaProject): HashSet { + val files = hashSetOf() + try { - projectFiles.put(javaProject.getProject(), HashSet()) - for (sourceFolder in javaProject.sourceFolders) { sourceFolder.getResource().accept { resource -> if (resource is IFile && isKotlinFile(resource)) { - addFile(resource) + files.add(resource) } true @@ -205,15 +218,13 @@ private class ProjectSourceFiles : PsiFilesStorage { } catch (e: CoreException) { KotlinLogger.logError(e) } + + return files; } fun updateProjectPsiSourcesIfNeeded(project: IProject) { - if (projectFiles.containsKey(project)) { - return - } - - if (ProjectUtils.isAccessibleKotlinProject(project)) { - updateProjectPsiSources(project, IResourceDelta.ADDED) + projectFiles.computeIfAbsent(project) { _ -> + computeProjectPsiSources(project)!! } } @@ -227,20 +238,6 @@ private class ProjectSourceFiles : PsiFilesStorage { fun invalidateProjectSourceFiles() { cachedKtFiles.clear() } - - private fun updatePsiFile(file: IFile, sourceCode: String) { - val sourceCodeWithouCR = StringUtilRt.convertLineSeparators(sourceCode) - - synchronized (mapOperationLock) { - assert(existsInProjectSources(file), { "File(" + file.getName() + ") does not contain in the psiFiles" }) - - val currentParsedFile = getPsiFile(file) - if (!currentParsedFile.getText().equals(sourceCodeWithouCR)) { - val jetFile = KotlinPsiManager.parseText(sourceCodeWithouCR, file)!! - cachedKtFiles.put(file, jetFile) - } - } - } } object KotlinPsiManager { diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/formatting/KotlinCodeStyleManager.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/formatting/KotlinCodeStyleManager.kt new file mode 100644 index 000000000..71201a6ed --- /dev/null +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/formatting/KotlinCodeStyleManager.kt @@ -0,0 +1,60 @@ +package org.jetbrains.kotlin.core.formatting + +import com.intellij.psi.codeStyle.CodeStyleSettings +import org.eclipse.core.internal.registry.ExtensionRegistry +import org.eclipse.core.resources.IProject +import org.eclipse.core.resources.ProjectScope +import org.jetbrains.kotlin.core.model.loadExecutableEP +import org.jetbrains.kotlin.core.preferences.KotlinCodeStyleProperties +import org.jetbrains.kotlin.idea.formatter.KotlinObsoleteCodeStyle +import org.jetbrains.kotlin.idea.formatter.KotlinPredefinedCodeStyle +import org.jetbrains.kotlin.idea.formatter.KotlinStyleGuideCodeStyle +import java.util.concurrent.ConcurrentHashMap + +private const val CODESTYLE_EXTENSION_POINT = "org.jetbrains.kotlin.core.predefinedKotlinCodeStyle" + +object KotlinCodeStyleManager { + private val stylesCache = ConcurrentHashMap() + + private val predefinedStyles: Map by lazy { + loadPredefinedCodeStyles() + .map { it.codeStyleId to it } + .toMap() + } + + val styles: List + get() = (predefinedStyles.keys + stylesCache.keys).sorted() + + // Can be used in the future to provide user defined code styles + fun getOrCreate(id: String, settingsApplier: CodeStyleSettings.() -> Unit): CodeStyleSettings = + stylesCache.getOrPut(id) { CodeStyleSettings().also { it.settingsApplier() } } + + fun get(id: String): CodeStyleSettings? = stylesCache[id] ?: createStyleFromPredef(id) + + // Uses the same logic as ConcurrentHashMap.getOrPut() but due to possible nullability cannot be expressed by that method. + private fun createStyleFromPredef(id: String): CodeStyleSettings? = predefinedStyles[id] + ?.let { CodeStyleSettings().also(it::apply) } + ?.let { stylesCache.putIfAbsent(id, it) ?: it } + + fun invalidate(id: String) { + stylesCache -= id + } + + fun getStyleLabel(id: String?) = + id?.let { predefinedStyles[it]?.name ?: it } ?: "unknown" +} + +private val IProject.codeStyleSettings + get() = KotlinCodeStyleProperties(ProjectScope(this)) + .takeIf { it.globalsOverridden } + ?: KotlinCodeStyleProperties.workspaceInstance + +val IProject.codeStyle: CodeStyleSettings + get() = codeStyleSettings + .codeStyleId + ?.let { KotlinCodeStyleManager.get(it) } + ?: CodeStyleSettings() + +private fun loadPredefinedCodeStyles() = + loadExecutableEP(CODESTYLE_EXTENSION_POINT) + .mapNotNull { it.createProvider() } \ No newline at end of file diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/KotlinEnvironment.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/KotlinEnvironment.kt index 7bfea76cb..a2e80b480 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/KotlinEnvironment.kt +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/KotlinEnvironment.kt @@ -29,7 +29,9 @@ import org.eclipse.core.resources.IFile import org.eclipse.core.resources.IProject import org.eclipse.core.resources.IResource import org.eclipse.core.resources.ProjectScope +import org.eclipse.core.runtime.IProgressMonitor import org.eclipse.core.runtime.Status +import org.eclipse.core.runtime.jobs.IJobChangeEvent import org.eclipse.core.runtime.jobs.Job import org.eclipse.jdt.core.IClasspathContainer import org.eclipse.jdt.core.IClasspathEntry @@ -242,7 +244,7 @@ class KotlinScriptEnvironment private constructor( val definitions = arrayListOf() val classpath = arrayListOf() - runJob("Initialize Script Definitions", Job.DECORATE, constructFamilyForInitialization(eclipseFile), { monitor -> + runJob("Initialize Script Definitions", Job.DECORATE, 0, constructFamilyForInitialization(eclipseFile), { monitor -> val definitionsAndClasspath = loadAndCreateDefinitionsByTemplateProviders(eclipseFile, monitor) KotlinLogger.logInfo("Found definitions: ${definitionsAndClasspath.first.joinToString()}") definitions.addAll(definitionsAndClasspath.first) @@ -251,7 +253,7 @@ class KotlinScriptEnvironment private constructor( monitor.done() Status.OK_STATUS - }, { _ -> + }, { isScriptDefinitionsInitialized = true isInitializingScriptDefinitions = false postTask(definitions, classpath) diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/KotlinNature.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/KotlinNature.kt index 87954d892..2821a0bb7 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/KotlinNature.kt +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/KotlinNature.kt @@ -16,14 +16,11 @@ *******************************************************************************/ package org.jetbrains.kotlin.core.model -import org.eclipse.core.resources.ICommand import org.eclipse.core.resources.IProject -import org.eclipse.core.resources.IProjectDescription import org.eclipse.core.resources.IProjectNature -import org.eclipse.core.runtime.CoreException +import org.eclipse.core.resources.ProjectScope import kotlin.properties.Delegates import org.jetbrains.kotlin.core.builder.KotlinPsiManager -import org.eclipse.core.resources.IResourceDelta import java.util.LinkedList import org.eclipse.core.runtime.jobs.Job import org.eclipse.core.runtime.IProgressMonitor @@ -32,8 +29,9 @@ import org.eclipse.jdt.core.JavaCore import java.util.Collections import org.eclipse.core.runtime.Status import org.eclipse.core.resources.ResourcesPlugin +import org.jetbrains.kotlin.core.preferences.KotlinCodeStyleProperties -public class KotlinNature: IProjectNature { +class KotlinNature: IProjectNature { companion object { val KOTLIN_NATURE: String = "org.jetbrains.kotlin.core.kotlinNature" @JvmField val KOTLIN_BUILDER: String = "org.jetbrains.kotlin.ui.kotlinBuilder" @@ -47,64 +45,70 @@ public class KotlinNature: IProjectNature { fun hasKotlinBuilder(project: IProject) : Boolean { if (!project.isAccessible) return false - return project.getDescription().getBuildSpec().any { - KOTLIN_BUILDER == it.getBuilderName() + return project.description.buildSpec.any { + KOTLIN_BUILDER == it.builderName } } @JvmStatic fun addNature(project:IProject) { if (!hasKotlinNature(project)) { - val description = project.getDescription() - - val newNatureIds = description.getNatureIds().toMutableList() - newNatureIds.add(KotlinNature.KOTLIN_NATURE) - - description.setNatureIds(newNatureIds.toTypedArray()) + val description = project.description + description.natureIds += KOTLIN_NATURE project.setDescription(description, null) } } } - - public var eclipseProject: IProject by Delegates.notNull() - - override public fun configure() { + + var eclipseProject: IProject by Delegates.notNull() + + override fun configure() { addKotlinBuilder(eclipseProject) + setPreferredCodeStyle(eclipseProject) } - - override public fun deconfigure() { + + override fun deconfigure() { removeKotlinBuilder(eclipseProject) KotlinPsiManager.removeProjectFromManager(eclipseProject) KotlinAnalysisFileCache.resetCache() KotlinAnalysisProjectCache.resetCache(eclipseProject) } - - override public fun setProject(project: IProject) { + + override fun setProject(project: IProject) { eclipseProject = project } - - override public fun getProject(): IProject = eclipseProject + + override fun getProject(): IProject = eclipseProject private fun addKotlinBuilder(project: IProject) { if (!hasKotlinBuilder(project)) { - val description = project.getDescription() + val description = project.description - val kotlinBuilderCommand = description.newCommand().apply { setBuilderName(KOTLIN_BUILDER) } + val kotlinBuilderCommand = description.newCommand().apply { builderName = KOTLIN_BUILDER } - val newBuildCommands = description.getBuildSpec().toCollection(LinkedList()) + val newBuildCommands = description.buildSpec.toCollection(LinkedList()) newBuildCommands.addFirst(kotlinBuilderCommand) - - description.setBuildSpec(newBuildCommands.toTypedArray()) + + description.buildSpec = newBuildCommands.toTypedArray() project.setDescription(description, null) } } + + private fun setPreferredCodeStyle(eclipseProject: IProject) { + KotlinCodeStyleProperties(ProjectScope(eclipseProject)).apply { + codeStyleId = "KOTLIN_OFFICIAL" + globalsOverridden = true + saveChanges() + } + + } private fun removeKotlinBuilder(project: IProject) { if (hasKotlinBuilder(project)) { - val description = project.getDescription() - val newBuildCommands = description.getBuildSpec().filter { it.getBuilderName() != KotlinNature.KOTLIN_BUILDER } - - description.setBuildSpec(newBuildCommands.toTypedArray()) + val description = project.description + val newBuildCommands = description.buildSpec.filter { it.builderName != KotlinNature.KOTLIN_BUILDER } + + description.buildSpec = newBuildCommands.toTypedArray() project.setDescription(description, null) } } @@ -114,23 +118,23 @@ public class KotlinNature: IProjectNature { fun setKotlinBuilderBeforeJavaBuilder(project: IProject) { val job = object : Job("Swap Kotlin builder with Java Builder") { override fun run(monitor: IProgressMonitor?): IStatus? { - val description = project.getDescription() + val description = project.description - val builders = description.getBuildSpec().toCollection(LinkedList()) - val kotlinBuilderIndex = builders.indexOfFirst { it.getBuilderName() == KotlinNature.KOTLIN_BUILDER } - val javaBuilderIndex = builders.indexOfFirst { it.getBuilderName() == JavaCore.BUILDER_ID } + val builders = description.buildSpec.toCollection(LinkedList()) + val kotlinBuilderIndex = builders.indexOfFirst { it.builderName == KotlinNature.KOTLIN_BUILDER } + val javaBuilderIndex = builders.indexOfFirst { it.builderName == JavaCore.BUILDER_ID } if (kotlinBuilderIndex >= 0 && javaBuilderIndex >= 0 && javaBuilderIndex < kotlinBuilderIndex) { Collections.swap(builders, kotlinBuilderIndex, javaBuilderIndex) - - description.setBuildSpec(builders.toTypedArray()) + + description.buildSpec = builders.toTypedArray() project.setDescription(description, monitor) } return Status.OK_STATUS } } - - job.setRule(ResourcesPlugin.getWorkspace().getRoot()) + + job.rule = ResourcesPlugin.getWorkspace().root job.schedule() } \ No newline at end of file diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/kotlinModelUtils.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/kotlinModelUtils.kt index 44dacd5b0..d917e86b0 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/kotlinModelUtils.kt +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/kotlinModelUtils.kt @@ -73,13 +73,14 @@ fun isConfigurationMissing(project: IProject): Boolean { } } -fun runJob(name: String, priority: Int = Job.LONG, action: (IProgressMonitor) -> IStatus) { - runJob(name, priority, null, action, {}) -} +fun runJob(name: String, priority: Int = Job.LONG, delay: Long = 0, action: (IProgressMonitor) -> IStatus) = + runJob(name, priority, delay, null, action, {}) + fun runJob( name: String, priority: Int = Job.LONG, + delay: Long = 0, jobFamily: Any? = null, action: (IProgressMonitor) -> IStatus, postTask: (IJobChangeEvent) -> Unit @@ -102,7 +103,7 @@ fun runJob( } }) - job.schedule() + job.schedule(delay) return job } \ No newline at end of file diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/preferences/KotlinCodeStyleProperties.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/preferences/KotlinCodeStyleProperties.kt new file mode 100644 index 000000000..6091c099d --- /dev/null +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/preferences/KotlinCodeStyleProperties.kt @@ -0,0 +1,23 @@ +package org.jetbrains.kotlin.core.preferences + +import org.eclipse.core.resources.ProjectScope +import org.eclipse.core.runtime.preferences.IScopeContext +import org.eclipse.core.runtime.preferences.InstanceScope +import org.jetbrains.kotlin.core.Activator +import org.jetbrains.kotlin.core.builder.KotlinPsiManager +import org.jetbrains.kotlin.core.formatting.KotlinCodeStyleManager +import org.jetbrains.kotlin.idea.formatter.KotlinPredefinedCodeStyle +import org.jetbrains.kotlin.idea.formatter.KotlinStyleGuideCodeStyle +import org.jetbrains.kotlin.psi.KtFile + +class KotlinCodeStyleProperties(scope: IScopeContext = InstanceScope.INSTANCE) + : Preferences(scope, "${Activator.PLUGIN_ID}/codeStyle" +) { + var globalsOverridden by BooleanPreference() + + var codeStyleId by StringPreference() + + companion object { + val workspaceInstance by lazy { KotlinCodeStyleProperties() } + } +} \ No newline at end of file diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/preferences/KotlinProperties.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/preferences/KotlinProperties.kt index 058c6bf14..ce19be98a 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/preferences/KotlinProperties.kt +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/preferences/KotlinProperties.kt @@ -1,13 +1,11 @@ package org.jetbrains.kotlin.core.preferences -import org.jetbrains.kotlin.core.Activator -import org.jetbrains.kotlin.config.JvmTarget -import org.eclipse.core.runtime.preferences.IScopeContext import org.eclipse.core.runtime.preferences.DefaultScope -import org.osgi.service.prefs.Preferences as InternalPreferences +import org.eclipse.core.runtime.preferences.IScopeContext import org.eclipse.core.runtime.preferences.InstanceScope -import org.jetbrains.kotlin.config.ApiVersion -import org.jetbrains.kotlin.config.LanguageVersion +import org.jetbrains.kotlin.config.* +import org.jetbrains.kotlin.core.Activator +import org.osgi.service.prefs.Preferences as InternalPreferences class KotlinProperties(scope: IScopeContext = InstanceScope.INSTANCE) : Preferences(scope, Activator.PLUGIN_ID) { var globalsOverridden by BooleanPreference() @@ -57,3 +55,6 @@ class CompilerPlugin(scope: IScopeContext, path: String) : Preferences(scope, pa var active by BooleanPreference() } + +val KotlinProperties.languageVersionSettings: LanguageVersionSettings + get() = LanguageVersionSettingsImpl(languageVersion, apiVersion) \ No newline at end of file diff --git a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/EclipseAnalyzerFacadeForJVM.kt b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/EclipseAnalyzerFacadeForJVM.kt index 09187148e..2b4646750 100644 --- a/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/EclipseAnalyzerFacadeForJVM.kt +++ b/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/EclipseAnalyzerFacadeForJVM.kt @@ -26,7 +26,6 @@ import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.SourceOrBinaryModuleClassResolver import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.config.CompilerConfiguration -import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl import org.jetbrains.kotlin.container.ComponentProvider import org.jetbrains.kotlin.context.ContextForNewModule import org.jetbrains.kotlin.context.MutableModuleContext @@ -34,6 +33,7 @@ import org.jetbrains.kotlin.context.ProjectContext import org.jetbrains.kotlin.core.log.KotlinLogger import org.jetbrains.kotlin.core.model.KotlinEnvironment import org.jetbrains.kotlin.core.model.KotlinScriptEnvironment +import org.jetbrains.kotlin.core.preferences.languageVersionSettings import org.jetbrains.kotlin.core.utils.ProjectUtils import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.PackageFragmentProvider @@ -51,8 +51,7 @@ import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.util.KotlinFrontEndException -import java.util.ArrayList -import java.util.LinkedHashSet +import java.util.* import org.jetbrains.kotlin.frontend.java.di.createContainerForTopDownAnalyzerForJvm as createContainerForScript data class AnalysisResultWithProvider(val analysisResult: AnalysisResult, val componentProvider: ComponentProvider?) { @@ -61,8 +60,8 @@ data class AnalysisResultWithProvider(val analysisResult: AnalysisResult, val co } } -public object EclipseAnalyzerFacadeForJVM { - public fun analyzeFilesWithJavaIntegration( +object EclipseAnalyzerFacadeForJVM { + fun analyzeFilesWithJavaIntegration( environment: KotlinEnvironment, filesToAnalyze: Collection): AnalysisResultWithProvider { val filesSet = filesToAnalyze.toSet() @@ -90,9 +89,7 @@ public object EclipseAnalyzerFacadeForJVM { val sourceScope = TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, filesToAnalyze) val moduleClassResolver = SourceOrBinaryModuleClassResolver(sourceScope) - val languageVersionSettings = LanguageVersionSettingsImpl( - environment.compilerProperties.languageVersion, - environment.compilerProperties.apiVersion) + val languageVersionSettings = environment.compilerProperties.languageVersionSettings val optionalBuiltInsModule = JvmBuiltIns(storageManager).apply { initialize(module, true) }.builtInsModule @@ -167,11 +164,11 @@ public object EclipseAnalyzerFacadeForJVM { } return AnalysisResultWithProvider( - AnalysisResult.success(trace.getBindingContext(), module), + AnalysisResult.success(trace.bindingContext, module), container) } - - public fun analyzeScript( + + fun analyzeScript( environment: KotlinScriptEnvironment, scriptFile: KtFile): AnalysisResultWithProvider { @@ -201,11 +198,11 @@ public object EclipseAnalyzerFacadeForJVM { } return AnalysisResultWithProvider( - AnalysisResult.success(trace.getBindingContext(), container.get()), + AnalysisResult.success(trace.bindingContext, container.get()), container) } - - private fun getPath(jetFile: KtFile): String? = jetFile.getVirtualFile()?.getPath() + + private fun getPath(jetFile: KtFile): String? = jetFile.virtualFile?.path private fun createModuleContext( project: Project, diff --git a/kotlin-eclipse-feature/feature.xml b/kotlin-eclipse-feature/feature.xml index c24381f9c..d5fbcd4d9 100644 --- a/kotlin-eclipse-feature/feature.xml +++ b/kotlin-eclipse-feature/feature.xml @@ -2,7 +2,7 @@ diff --git a/kotlin-eclipse-feature/pom.xml b/kotlin-eclipse-feature/pom.xml index 311b86bb5..115079480 100644 --- a/kotlin-eclipse-feature/pom.xml +++ b/kotlin-eclipse-feature/pom.xml @@ -8,12 +8,12 @@ ../pom.xml kotlin.eclipse kotlin.eclipse.plugin - 0.8.7-SNAPSHOT + 0.8.8-SNAPSHOT org.jetbrains.kotlin.feature kotlin.eclipse - 0.8.7-SNAPSHOT + 0.8.8-SNAPSHOT eclipse-feature \ No newline at end of file diff --git a/kotlin-eclipse-maven/META-INF/MANIFEST.MF b/kotlin-eclipse-maven/META-INF/MANIFEST.MF index e8b582ef1..c92df7f7b 100644 --- a/kotlin-eclipse-maven/META-INF/MANIFEST.MF +++ b/kotlin-eclipse-maven/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: kotlin-eclipse-maven Bundle-SymbolicName: org.jetbrains.kotlin.maven;singleton:=true -Bundle-Version: 0.8.7.qualifier +Bundle-Version: 0.8.8.qualifier Bundle-Activator: org.jetbrains.kotlin.maven.Activator Bundle-Vendor: JetBrains Require-Bundle: org.eclipse.core.runtime, diff --git a/kotlin-eclipse-maven/pom.xml b/kotlin-eclipse-maven/pom.xml index f21fe3af3..a9f70e760 100644 --- a/kotlin-eclipse-maven/pom.xml +++ b/kotlin-eclipse-maven/pom.xml @@ -8,7 +8,7 @@ ../pom.xml kotlin.eclipse kotlin.eclipse.plugin - 0.8.7-SNAPSHOT + 0.8.8-SNAPSHOT org.jetbrains.kotlin.maven diff --git a/kotlin-eclipse-p2updatesite/category.xml b/kotlin-eclipse-p2updatesite/category.xml index c0e979315..bdc959099 100644 --- a/kotlin-eclipse-p2updatesite/category.xml +++ b/kotlin-eclipse-p2updatesite/category.xml @@ -1,6 +1,6 @@ - + diff --git a/kotlin-eclipse-p2updatesite/pom.xml b/kotlin-eclipse-p2updatesite/pom.xml index d6bf15a87..a9c067320 100644 --- a/kotlin-eclipse-p2updatesite/pom.xml +++ b/kotlin-eclipse-p2updatesite/pom.xml @@ -8,12 +8,12 @@ ../pom.xml kotlin.eclipse kotlin.eclipse.plugin - 0.8.7-SNAPSHOT + 0.8.8-SNAPSHOT org.jetbrains.kotlin.p2updatesite kotlin.eclipse - 0.8.7-SNAPSHOT + 0.8.8-SNAPSHOT eclipse-repository \ No newline at end of file diff --git a/kotlin-eclipse-policy/feature.xml b/kotlin-eclipse-policy/feature.xml index 1c921a581..083ae685f 100644 --- a/kotlin-eclipse-policy/feature.xml +++ b/kotlin-eclipse-policy/feature.xml @@ -2,7 +2,7 @@ diff --git a/kotlin-eclipse-policy/pom.xml b/kotlin-eclipse-policy/pom.xml index fbab69e55..7e8d73ab1 100644 --- a/kotlin-eclipse-policy/pom.xml +++ b/kotlin-eclipse-policy/pom.xml @@ -8,12 +8,12 @@ ../pom.xml kotlin.eclipse kotlin.eclipse.plugin - 0.8.7-SNAPSHOT + 0.8.8-SNAPSHOT org.jetbrains.kotlin.policy kotlin.eclipse - 0.8.7-SNAPSHOT + 0.8.8-SNAPSHOT eclipse-feature \ No newline at end of file diff --git a/kotlin-eclipse-test-framework/.classpath b/kotlin-eclipse-test-framework/.classpath index 1fa3e6803..f98be78ce 100644 --- a/kotlin-eclipse-test-framework/.classpath +++ b/kotlin-eclipse-test-framework/.classpath @@ -3,5 +3,6 @@ + diff --git a/kotlin-eclipse-test-framework/.project b/kotlin-eclipse-test-framework/.project index ff755ca20..f507c9f5e 100644 --- a/kotlin-eclipse-test-framework/.project +++ b/kotlin-eclipse-test-framework/.project @@ -5,6 +5,11 @@ + + org.jetbrains.kotlin.ui.kotlinBuilder + + + org.eclipse.jdt.core.javabuilder @@ -24,5 +29,13 @@ org.eclipse.pde.PluginNature org.eclipse.jdt.core.javanature + org.jetbrains.kotlin.core.kotlinNature + + + kotlin_bin + 2 + org.jetbrains.kotlin.core.filesystem:/kotlin-eclipse-test-framework/kotlin_bin + + diff --git a/kotlin-eclipse-test-framework/META-INF/MANIFEST.MF b/kotlin-eclipse-test-framework/META-INF/MANIFEST.MF index 583b3a360..1c0e0efb0 100644 --- a/kotlin-eclipse-test-framework/META-INF/MANIFEST.MF +++ b/kotlin-eclipse-test-framework/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: kotlin-eclipse-testframework Bundle-SymbolicName: org.jetbrains.kotlin.testframework -Bundle-Version: 0.8.7.qualifier +Bundle-Version: 0.8.8.qualifier Bundle-Activator: org.jetbrains.kotlin.testframework.Activator Require-Bundle: org.jetbrains.kotlin.core, org.jetbrains.kotlin.ui, diff --git a/kotlin-eclipse-test-framework/pom.xml b/kotlin-eclipse-test-framework/pom.xml index dd6a595c3..b3b9c33af 100644 --- a/kotlin-eclipse-test-framework/pom.xml +++ b/kotlin-eclipse-test-framework/pom.xml @@ -8,9 +8,31 @@ ../pom.xml kotlin.eclipse kotlin.eclipse.plugin - 0.8.7-SNAPSHOT + 0.8.8-SNAPSHOT org.jetbrains.kotlin.testframework eclipse-plugin + + + src + + + + org.jetbrains.kotlin + kotlin-maven-plugin + ${kotlin.version} + + + + compile + process-sources + + compile + + + + + + \ No newline at end of file diff --git a/kotlin-eclipse-test-framework/src/org/jetbrains/kotlin/testframework/utils/CodeStyleConfigurator.kt b/kotlin-eclipse-test-framework/src/org/jetbrains/kotlin/testframework/utils/CodeStyleConfigurator.kt new file mode 100644 index 000000000..133aa1c64 --- /dev/null +++ b/kotlin-eclipse-test-framework/src/org/jetbrains/kotlin/testframework/utils/CodeStyleConfigurator.kt @@ -0,0 +1,67 @@ +package org.jetbrains.kotlin.testframework.utils + +import org.eclipse.core.resources.IProject +import org.eclipse.core.resources.ProjectScope +import org.jetbrains.kotlin.core.formatting.KotlinCodeStyleManager +import org.jetbrains.kotlin.core.preferences.KotlinCodeStyleProperties +import org.jetbrains.kotlin.idea.KotlinLanguage +import org.jetbrains.kotlin.idea.core.formatter.KotlinCodeStyleSettings +import java.util.* +import kotlin.reflect.KFunction +import kotlin.reflect.KMutableProperty + +object CodeStyleConfigurator { + fun configure(project: IProject, fileText: String) { + val generatedId = UUID.randomUUID().toString() + + KotlinCodeStyleProperties(ProjectScope(project)).apply { + codeStyleId = generatedId + globalsOverridden = true + saveChanges() + } + + KotlinCodeStyleManager.getOrCreate(generatedId) { + val kotlinSettings = getCustomSettings(KotlinCodeStyleSettings::class.java) + val commonSettings = getCommonSettings(KotlinLanguage.INSTANCE) + + fun setDynamic(prop: String, value: Any) { + kotlinSettings.setDynamic(prop, value) or commonSettings.setDynamic(prop, value) + } + + InTextDirectivesUtils.findListWithPrefixes(fileText, "SET_TRUE:") + .forEach { setDynamic(it, true) } + + InTextDirectivesUtils.findListWithPrefixes(fileText, "SET_FALSE:") + .forEach { setDynamic(it, false) } + + InTextDirectivesUtils.findListWithPrefixes(fileText, "SET_INT:") + .map { it.split("=", limit = 2) } + .forEach { (prop, value) -> setDynamic(prop, value.trim().toInt()) } + + InTextDirectivesUtils.findStringWithPrefixes(fileText, "RIGHT_MARGIN: ") + ?.also { commonSettings.RIGHT_MARGIN = it.trim().toInt() } + } + } + + fun deconfigure(project: IProject) { + KotlinCodeStyleProperties(ProjectScope(project)).apply { + globalsOverridden = false + codeStyleId?.also { KotlinCodeStyleManager.invalidate(it) } + saveChanges() + } + } + + private fun Any.setDynamic(name: String, value: Any): Boolean = + this::class.members.singleOrNull { it.name in setOf(name) } + ?.let { + when (it) { + is KMutableProperty -> it.setter + is KFunction -> it + else -> null + } + } + ?.call(this, value) + ?.let { true } + ?: false + +} \ No newline at end of file diff --git a/kotlin-eclipse-test-framework/src/org/jetbrains/kotlin/testframework/utils/TestJavaProject.java b/kotlin-eclipse-test-framework/src/org/jetbrains/kotlin/testframework/utils/TestJavaProject.java index 95b13ec89..c7677f48f 100644 --- a/kotlin-eclipse-test-framework/src/org/jetbrains/kotlin/testframework/utils/TestJavaProject.java +++ b/kotlin-eclipse-test-framework/src/org/jetbrains/kotlin/testframework/utils/TestJavaProject.java @@ -213,6 +213,10 @@ public IJavaProject getJavaProject() { return javaProject; } + public IProject getProject() { + return project; + } + public void addKotlinRuntime() throws CoreException { ProjectUtils.addKotlinRuntime(javaProject); } diff --git a/kotlin-eclipse-ui-test/META-INF/MANIFEST.MF b/kotlin-eclipse-ui-test/META-INF/MANIFEST.MF index 8cff744bd..a8865d599 100644 --- a/kotlin-eclipse-ui-test/META-INF/MANIFEST.MF +++ b/kotlin-eclipse-ui-test/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: kotlin-eclipse-ui-test Bundle-SymbolicName: org.jetbrains.kotlin.ui.tests;singleton:=true -Bundle-Version: 0.8.7.qualifier +Bundle-Version: 0.8.8.qualifier Bundle-Vendor: JetBrains Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-ClassPath: ., diff --git a/kotlin-eclipse-ui-test/pom.xml b/kotlin-eclipse-ui-test/pom.xml index dee1d7e2c..fc207d858 100644 --- a/kotlin-eclipse-ui-test/pom.xml +++ b/kotlin-eclipse-ui-test/pom.xml @@ -8,7 +8,7 @@ ../pom.xml kotlin.eclipse kotlin.eclipse.plugin - 0.8.7-SNAPSHOT + 0.8.8-SNAPSHOT org.jetbrains.kotlin.ui.tests diff --git a/kotlin-eclipse-ui-test/src/org/jetbrains/kotlin/core/tests/launch/KotlinLaunchTestCase.kt b/kotlin-eclipse-ui-test/src/org/jetbrains/kotlin/core/tests/launch/KotlinLaunchTestCase.kt index 2157faca0..c17bfea25 100644 --- a/kotlin-eclipse-ui-test/src/org/jetbrains/kotlin/core/tests/launch/KotlinLaunchTestCase.kt +++ b/kotlin-eclipse-ui-test/src/org/jetbrains/kotlin/core/tests/launch/KotlinLaunchTestCase.kt @@ -23,6 +23,7 @@ import org.eclipse.debug.core.ILaunchListener import org.eclipse.debug.internal.ui.DebugUIPlugin import org.eclipse.debug.internal.ui.IInternalDebugUIConstants import org.eclipse.jface.dialogs.MessageDialogWithToggle +import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl import org.jetbrains.kotlin.testframework.editor.KotlinEditorTestCase import org.jetbrains.kotlin.testframework.utils.KotlinTestUtils import org.jetbrains.kotlin.ui.launch.KotlinLaunchShortcut @@ -32,26 +33,26 @@ import org.junit.Assert import org.junit.Before abstract class KotlinLaunchTestCase : KotlinEditorTestCase() { - val compileWithErrorPreference = DebugUIPlugin.getDefault().getPreferenceStore() + val compileWithErrorPreference = DebugUIPlugin.getDefault().preferenceStore .getString(IInternalDebugUIConstants.PREF_CONTINUE_WITH_COMPILE_ERROR) @Before fun before() { - DebugUIPlugin.getDefault().getPreferenceStore().setValue( + DebugUIPlugin.getDefault().preferenceStore.setValue( IInternalDebugUIConstants.PREF_CONTINUE_WITH_COMPILE_ERROR, MessageDialogWithToggle.ALWAYS) } @After fun after() { - DebugUIPlugin.getDefault().getPreferenceStore().setValue( + DebugUIPlugin.getDefault().preferenceStore.setValue( IInternalDebugUIConstants.PREF_CONTINUE_WITH_COMPILE_ERROR, compileWithErrorPreference) } fun doTest(input: String, projectName: String, packageName: String, additionalSrcFolderName: String?) { testEditor = configureEditor("Test.kt", input, projectName, packageName) - testEditor.getTestJavaProject().addKotlinRuntime() + testEditor.testJavaProject.addKotlinRuntime() if (additionalSrcFolderName != null) { - testEditor.getTestJavaProject().createSourceFolder(additionalSrcFolderName) + testEditor.testJavaProject.createSourceFolder(additionalSrcFolderName) } KotlinTestUtils.joinBuildThread() @@ -76,13 +77,13 @@ abstract class KotlinLaunchTestCase : KotlinEditorTestCase() { override fun launchAdded(launch: ILaunch) { } } - - DebugPlugin.getDefault().getLaunchManager().addLaunchListener(launchListener) + + DebugPlugin.getDefault().launchManager.addLaunchListener(launchListener) var launch: ILaunch? = null try { - val entryPoint = getEntryPoint(getEditor().parsedFile!!) - val launchConfiguration = KotlinLaunchShortcut.createConfiguration(entryPoint!!, testEditor.getEclipseProject()) + val entryPoint = getEntryPoint(editor.parsedFile!!, LanguageVersionSettingsImpl.DEFAULT) + val launchConfiguration = KotlinLaunchShortcut.createConfiguration(entryPoint!!, testEditor.eclipseProject) launch = DebugUIPlugin.buildAndLaunch(launchConfiguration, "run", NullProgressMonitor()) synchronized (launch) { @@ -95,7 +96,7 @@ abstract class KotlinLaunchTestCase : KotlinEditorTestCase() { if (!launch.isTerminated) stdout.append("Launch not terminated") } finally { launch?.terminate() - DebugPlugin.getDefault().getLaunchManager().removeLaunchListener(launchListener) + DebugPlugin.getDefault().launchManager.removeLaunchListener(launchListener) } return stdout.toString() diff --git a/kotlin-eclipse-ui-test/src/org/jetbrains/kotlin/ui/tests/editors/KotlinAutoIndentTestCase.kt b/kotlin-eclipse-ui-test/src/org/jetbrains/kotlin/ui/tests/editors/KotlinAutoIndentTestCase.kt index 150ab4c0f..cd7ba9683 100644 --- a/kotlin-eclipse-ui-test/src/org/jetbrains/kotlin/ui/tests/editors/KotlinAutoIndentTestCase.kt +++ b/kotlin-eclipse-ui-test/src/org/jetbrains/kotlin/ui/tests/editors/KotlinAutoIndentTestCase.kt @@ -7,8 +7,8 @@ import org.eclipse.ui.editors.text.EditorsUI import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants import org.jetbrains.kotlin.testframework.utils.EditorTestUtils import org.jetbrains.kotlin.ui.tests.editors.formatter.KotlinFormatActionTestCase -import org.jetbrains.kotlin.ui.formatter.settings import com.intellij.psi.codeStyle.CodeStyleSettings +import org.jetbrains.kotlin.testframework.utils.CodeStyleConfigurator import org.junit.After abstract class KotlinAutoIndentTestCase : KotlinEditorWithAfterFileTestCase() { @@ -19,11 +19,11 @@ abstract class KotlinAutoIndentTestCase : KotlinEditorWithAfterFileTestCase() { @After fun setDefaultSettings() { - settings = CodeStyleSettings() + CodeStyleConfigurator.deconfigure(testProject.project) } override fun performTest(fileText: String, expectedFileText: String) { - KotlinFormatActionTestCase.configureSettings(fileText) + CodeStyleConfigurator.configure(testProject.project, fileText) EditorsUI.getPreferenceStore().setValue(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SPACES_FOR_TABS, true) EditorsUI.getPreferenceStore().setValue(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TAB_WIDTH, 4) diff --git a/kotlin-eclipse-ui-test/src/org/jetbrains/kotlin/ui/tests/editors/formatter/KotlinFormatActionTestCase.java b/kotlin-eclipse-ui-test/src/org/jetbrains/kotlin/ui/tests/editors/formatter/KotlinFormatActionTestCase.java index e4545c0fc..cd544c701 100644 --- a/kotlin-eclipse-ui-test/src/org/jetbrains/kotlin/ui/tests/editors/formatter/KotlinFormatActionTestCase.java +++ b/kotlin-eclipse-ui-test/src/org/jetbrains/kotlin/ui/tests/editors/formatter/KotlinFormatActionTestCase.java @@ -16,34 +16,18 @@ *******************************************************************************/ package org.jetbrains.kotlin.ui.tests.editors.formatter; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.List; - import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.TextUtilities; import org.eclipse.ui.editors.text.EditorsUI; import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants; -import org.jetbrains.kotlin.idea.KotlinLanguage; -import org.jetbrains.kotlin.idea.core.formatter.KotlinCodeStyleSettings; import org.jetbrains.kotlin.testframework.editor.KotlinEditorWithAfterFileTestCase; +import org.jetbrains.kotlin.testframework.utils.CodeStyleConfigurator; import org.jetbrains.kotlin.testframework.utils.EditorTestUtils; -import org.jetbrains.kotlin.testframework.utils.InTextDirectivesUtils; import org.junit.After; import org.junit.Assert; import org.junit.Before; -import com.intellij.psi.codeStyle.CodeStyleSettings; -import com.intellij.psi.codeStyle.CommonCodeStyleSettings; - -import kotlin.Pair; -import kotlin.collections.CollectionsKt; -import kotlin.jvm.functions.Function1; -import org.jetbrains.kotlin.ui.formatter.KotlinFormatterKt; - public abstract class KotlinFormatActionTestCase extends KotlinEditorWithAfterFileTestCase { @Before public void before() { @@ -52,7 +36,7 @@ public void before() { @After public void setDefaultSettings() { - KotlinFormatterKt.setSettings(new CodeStyleSettings()); + CodeStyleConfigurator.INSTANCE.deconfigure(getTestProject().getProject()); } @Override @@ -61,8 +45,8 @@ protected void performTest(String fileText, String content) { EditorsUI.getPreferenceStore().setValue(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SPACES_FOR_TABS, true); EditorsUI.getPreferenceStore().setValue(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TAB_WIDTH, 4); - - configureSettings(fileText); + + CodeStyleConfigurator.INSTANCE.configure(getTestProject().getProject(), fileText); getTestEditor().runFormatAction(); @@ -79,94 +63,4 @@ private void assertLineDelimiters(String expectedLineDelimiter, IDocument docume throw new RuntimeException(e); } } - - public static void configureSettings(String fileText) { - List settingsToTrue = InTextDirectivesUtils.findListWithPrefixes(fileText, "SET_TRUE:"); - List settingsToFalse = InTextDirectivesUtils.findListWithPrefixes(fileText, "SET_FALSE:"); - List settingsToIntValue = CollectionsKt.map(InTextDirectivesUtils.findListWithPrefixes(fileText, "SET_INT:"), new Function1() { - @Override - public Pair invoke(String s) { - String[] tokens = s.split("="); - return new Pair(tokens[0].trim(), Integer.valueOf(tokens[1].trim())); - } - }); - - KotlinCodeStyleSettings kotlinSettings = KotlinFormatterKt.getSettings().getCustomSettings(KotlinCodeStyleSettings.class); - CommonCodeStyleSettings commonSettings = KotlinFormatterKt.getSettings().getCommonSettings(KotlinLanguage.INSTANCE); - - List objects = Arrays.asList(kotlinSettings, commonSettings); - - for (String trueSetting : settingsToTrue) { - setBooleanSetting(trueSetting, true, objects); - } - - for (String falseSetting : settingsToFalse) { - setBooleanSetting(falseSetting, false, objects); - } - - for (Pair setting : settingsToIntValue) { - setIntSetting(setting.getFirst(), setting.getSecond(), objects); - } - - String rightMarginString = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// RIGHT_MARGIN: "); - if (rightMarginString != null) { - Integer rightMargin = Integer.parseInt(rightMarginString); - commonSettings.RIGHT_MARGIN = rightMargin; - } - - } - - public static void setBooleanSetting(String setting, Boolean value, List objects) { - setSettingValue(setting, value, boolean.class, objects); - } - - public static void setIntSetting(String setting, Integer value, List objects) { - setSettingValue(setting, value, int.class, objects); - } - - public static void setSettingValue(String settingName, Object value, Class valueType, List objects) { - for (Object object : objects) { - if (setSettingWithField(settingName, object, value) || setSettingWithMethod(settingName, object, value, valueType)) { - return; - } - } - - throw new IllegalArgumentException(String.format( - "There's no property or method with name '%s' in given objects: %s", settingName, objects)); - } - - private static boolean setSettingWithField(String settingName, Object object, Object value) { - try { - Field field = object.getClass().getDeclaredField(settingName); - field.set(object, value); - return true; - } - catch (IllegalAccessException e) { - throw new IllegalArgumentException(String.format("Can't set property with the name %s in object %s", settingName, object)); - } - catch (NoSuchFieldException e) { - // Do nothing - will try other variants - } - - return false; - } - - private static boolean setSettingWithMethod(String setterName, Object object, Object value, Class valueType) { - try { - Method method = object.getClass().getMethod(setterName, valueType); - method.invoke(object, value); - return true; - } - catch (InvocationTargetException e) { - throw new IllegalArgumentException(String.format("Can't call method with name %s for object %s", setterName, object)); - } - catch (IllegalAccessException e) { - throw new IllegalArgumentException(String.format("Can't access to method with name %s for object %s", setterName, object)); - } - catch (NoSuchMethodException e) { - // Do nothing - will try other variants - } - - return false; - } } \ No newline at end of file diff --git a/kotlin-eclipse-ui-test/src/org/jetbrains/kotlin/ui/tests/editors/formatter/KotlinIdeaFormatActionTest.java b/kotlin-eclipse-ui-test/src/org/jetbrains/kotlin/ui/tests/editors/formatter/KotlinIdeaFormatActionTest.java index 0491ba2ba..5e9c8d88a 100644 --- a/kotlin-eclipse-ui-test/src/org/jetbrains/kotlin/ui/tests/editors/formatter/KotlinIdeaFormatActionTest.java +++ b/kotlin-eclipse-ui-test/src/org/jetbrains/kotlin/ui/tests/editors/formatter/KotlinIdeaFormatActionTest.java @@ -1,6 +1,5 @@ package org.jetbrains.kotlin.ui.tests.editors.formatter; -import org.junit.Ignore; import org.junit.Test; public class KotlinIdeaFormatActionTest extends KotlinFormatActionTestCase { @@ -34,25 +33,21 @@ public void ArrayAccess() { doAutoTest(); } - @Ignore @Test public void BinaryExpressionAlignmentSpread() { doAutoTest(); } - @Ignore @Test public void BinaryExpressions() { doAutoTest(); } - @Ignore @Test public void BinaryExpressionsBoolean() { doAutoTest(); } - @Ignore @Test public void BinaryExpressionsWithoutAlignment() { doAutoTest(); @@ -63,7 +58,6 @@ public void BlockFor() { doAutoTest(); } - @Ignore @Test public void CatchFinallyOnNewLine() { doAutoTest(); @@ -94,19 +88,6 @@ public void CommentInFunctionLiteral() { doAutoTest(); } - @Ignore - @Test - public void ConsecutiveCalls() { - doAutoTest(); - } - - @Ignore - @Test - public void ConsecutiveSafeCallsIndent() { - doAutoTest(); - } - - @Ignore @Test public void DelegationList() { doAutoTest(); @@ -127,13 +108,11 @@ public void DoWhileSpacing() { doAutoTest(); } - @Ignore @Test public void ElseOnNewLine() { doAutoTest(); } - @Ignore @Test public void Elvis() { doAutoTest(); @@ -164,7 +143,6 @@ public void EmptyLineBetweenClasses() { doAutoTest(); } - @Ignore @Test public void EmptyLineBetweenEnumEntries() { doAutoTest(); @@ -190,13 +168,11 @@ public void ForLineBreak() { doAutoTest(); } - @Ignore @Test public void FormatFirstColumnComments() { doAutoTest(); } - @Ignore @Test public void FormatFirstColumnCommentsBeforeDeclaration() { doAutoTest(); @@ -217,7 +193,6 @@ public void FunctionalType() { doAutoTest(); } - @Ignore @Test public void FunctionCallParametersAlign() { doAutoTest(); @@ -237,13 +212,7 @@ public void FunctionExpression() { public void FunctionLineBreak() { doAutoTest(); } - - @Ignore - @Test - public void FunctionLiteralsInChainCalls() { - doAutoTest(); - } - + @Test public void FunctionWithInference() { doAutoTest(); @@ -364,7 +333,6 @@ public void ReturnExpression() { doAutoTest(); } - @Ignore @Test public void RightBracketOnNewLine() { doAutoTest(); @@ -415,13 +383,11 @@ public void SpacedInsideParans() { doAutoTest(); } - @Ignore @Test public void SpacesAroundOperations() { doAutoTest(); } - @Ignore @Test public void SpacesAroundUnaryOperations() { doAutoTest(); @@ -482,7 +448,6 @@ public void WhileLineBreak() { doAutoTest(); } - @Ignore @Test public void WhileOnNewLine() { doAutoTest(); diff --git a/kotlin-eclipse-ui/META-INF/MANIFEST.MF b/kotlin-eclipse-ui/META-INF/MANIFEST.MF index bda955e2f..24eb3a34f 100644 --- a/kotlin-eclipse-ui/META-INF/MANIFEST.MF +++ b/kotlin-eclipse-ui/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: kotlin-eclipse-ui Bundle-SymbolicName: org.jetbrains.kotlin.ui;singleton:=true -Bundle-Version: 0.8.7.qualifier +Bundle-Version: 0.8.8.qualifier Bundle-Activator: org.jetbrains.kotlin.ui.Activator Bundle-Vendor: JetBrains Require-Bundle: org.eclipse.ui, diff --git a/kotlin-eclipse-ui/plugin.xml b/kotlin-eclipse-ui/plugin.xml index 2e6132c79..03b3c18b0 100644 --- a/kotlin-eclipse-ui/plugin.xml +++ b/kotlin-eclipse-ui/plugin.xml @@ -212,22 +212,16 @@ + class="org.jetbrains.kotlin.preferences.style.WorkspaceCodeStylePropertyPage" + id="kotlin-eclipse-ui.preferences.style" + name="Code style"> - - @@ -892,7 +886,7 @@ @@ -901,5 +895,15 @@ + + + + + + diff --git a/kotlin-eclipse-ui/pom.xml b/kotlin-eclipse-ui/pom.xml index 15f5007b8..ac6245132 100644 --- a/kotlin-eclipse-ui/pom.xml +++ b/kotlin-eclipse-ui/pom.xml @@ -8,7 +8,7 @@ ../pom.xml kotlin.eclipse kotlin.eclipse.plugin - 0.8.7-SNAPSHOT + 0.8.8-SNAPSHOT org.jetbrains.kotlin.ui diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/CompilerPluginDialog.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/compiler/CompilerPluginDialog.kt similarity index 98% rename from kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/CompilerPluginDialog.kt rename to kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/compiler/CompilerPluginDialog.kt index e4154ae71..53a3dd6e5 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/CompilerPluginDialog.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/compiler/CompilerPluginDialog.kt @@ -1,4 +1,4 @@ -package org.jetbrains.kotlin.preferences +package org.jetbrains.kotlin.preferences.compiler import org.eclipse.jface.dialogs.IDialogConstants import org.eclipse.jface.dialogs.MessageDialog @@ -8,7 +8,6 @@ import org.eclipse.swt.layout.GridLayout import org.eclipse.swt.widgets.Composite import org.eclipse.swt.widgets.Control import org.eclipse.swt.widgets.Shell -import org.eclipse.swt.widgets.Text import org.jetbrains.kotlin.core.preferences.CompilerPlugin import org.jetbrains.kotlin.core.preferences.PreferencesCollection import org.jetbrains.kotlin.swt.builders.* diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/ProjectCompilerPropertyPage.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/compiler/ProjectCompilerPropertyPage.kt similarity index 92% rename from kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/ProjectCompilerPropertyPage.kt rename to kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/compiler/ProjectCompilerPropertyPage.kt index b0a30321e..5d3c8e744 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/ProjectCompilerPropertyPage.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/compiler/ProjectCompilerPropertyPage.kt @@ -1,4 +1,4 @@ -package org.jetbrains.kotlin.preferences +package org.jetbrains.kotlin.preferences.compiler import org.eclipse.core.resources.IProject import org.eclipse.core.resources.IncrementalProjectBuilder @@ -6,6 +6,7 @@ import org.eclipse.swt.widgets.Composite import org.eclipse.swt.widgets.Control import org.eclipse.ui.IWorkbenchPropertyPage import org.jetbrains.kotlin.core.model.KotlinEnvironment +import org.jetbrains.kotlin.preferences.BasePropertyPage import org.jetbrains.kotlin.preferences.views.projectCompilerPropertiesView import org.jetbrains.kotlin.swt.builders.asView diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/RebuildJob.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/compiler/RebuildJob.kt similarity index 92% rename from kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/RebuildJob.kt rename to kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/compiler/RebuildJob.kt index 4a301710d..65c1b49ef 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/RebuildJob.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/compiler/RebuildJob.kt @@ -1,4 +1,4 @@ -package org.jetbrains.kotlin.preferences +package org.jetbrains.kotlin.preferences.compiler import org.eclipse.core.runtime.CoreException import org.eclipse.core.runtime.IProgressMonitor diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/WorkspaceCompilerPropertyPage.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/compiler/WorkspaceCompilerPropertyPage.kt similarity index 91% rename from kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/WorkspaceCompilerPropertyPage.kt rename to kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/compiler/WorkspaceCompilerPropertyPage.kt index 9bb2c703f..808074b71 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/WorkspaceCompilerPropertyPage.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/compiler/WorkspaceCompilerPropertyPage.kt @@ -1,4 +1,4 @@ -package org.jetbrains.kotlin.preferences +package org.jetbrains.kotlin.preferences.compiler import org.eclipse.core.resources.IncrementalProjectBuilder.FULL_BUILD import org.eclipse.core.resources.ResourcesPlugin @@ -8,6 +8,7 @@ import org.eclipse.ui.IWorkbench import org.eclipse.ui.IWorkbenchPreferencePage import org.jetbrains.kotlin.core.model.KotlinEnvironment import org.jetbrains.kotlin.core.preferences.KotlinProperties +import org.jetbrains.kotlin.preferences.BasePropertyPage import org.jetbrains.kotlin.preferences.views.compilerPropertiesView import org.jetbrains.kotlin.swt.builders.asView diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/style/ProjectCodeStylePropertyPage.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/style/ProjectCodeStylePropertyPage.kt new file mode 100644 index 000000000..7659d42cc --- /dev/null +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/style/ProjectCodeStylePropertyPage.kt @@ -0,0 +1,36 @@ +package org.jetbrains.kotlin.preferences.style + +import org.eclipse.core.resources.IProject +import org.eclipse.core.resources.ProjectScope +import org.eclipse.swt.widgets.Composite +import org.eclipse.swt.widgets.Control +import org.eclipse.ui.IWorkbenchPropertyPage +import org.jetbrains.kotlin.core.preferences.KotlinCodeStyleProperties +import org.jetbrains.kotlin.preferences.BasePropertyPage +import org.jetbrains.kotlin.preferences.views.codeStylePropertiesView +import org.jetbrains.kotlin.swt.builders.* +import org.jetbrains.kotlin.utils.LazyObservable +import kotlin.properties.Delegates + +class ProjectCodeStylePropertyPage : BasePropertyPage(), IWorkbenchPropertyPage { + // project must be lazy initialized, because getElement() called during construction of page object returns null + val project: IProject by lazy { element.getAdapter(IProject::class.java) } + + private var overrideFlag by LazyObservable({ properties.globalsOverridden }) { _, _, v -> + properties.globalsOverridden = v + settingsView.enabled = v + } + + private lateinit var settingsView: View + + override val properties by lazy { KotlinCodeStyleProperties(ProjectScope(project)) } + + override fun createUI(parent: Composite): Control = + parent.asView.apply { + checkbox(::overrideFlag, "Enable project speciffic settings") + separator { layout(horizontalGrab = true) } + settingsView = codeStylePropertiesView(properties) { + enabled = properties.globalsOverridden + } + }.control +} \ No newline at end of file diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/style/WorkspaceCodeStylePropertyPage.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/style/WorkspaceCodeStylePropertyPage.kt new file mode 100644 index 000000000..97e9f9c4c --- /dev/null +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/style/WorkspaceCodeStylePropertyPage.kt @@ -0,0 +1,23 @@ +package org.jetbrains.kotlin.preferences.style + +import org.eclipse.swt.widgets.Composite +import org.eclipse.swt.widgets.Control +import org.eclipse.ui.IWorkbench +import org.eclipse.ui.IWorkbenchPreferencePage +import org.jetbrains.kotlin.core.preferences.KotlinCodeStyleProperties +import org.jetbrains.kotlin.preferences.BasePropertyPage +import org.jetbrains.kotlin.preferences.views.codeStylePropertiesView +import org.jetbrains.kotlin.swt.builders.* + +class WorkspaceCodeStylePropertyPage : BasePropertyPage(), IWorkbenchPreferencePage { + + override val properties = KotlinCodeStyleProperties.workspaceInstance + + override fun init(workbench: IWorkbench?) { + } + + override fun createUI(parent: Composite): Control = + parent.asView.apply { + codeStylePropertiesView(properties) + }.control +} diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/views/CompilerPropertiesView.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/views/CompilerPropertiesView.kt index b197147b2..b04f419f7 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/views/CompilerPropertiesView.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/views/CompilerPropertiesView.kt @@ -11,7 +11,7 @@ import org.jetbrains.kotlin.config.JvmTarget import org.jetbrains.kotlin.config.LanguageVersion import org.jetbrains.kotlin.core.preferences.CompilerPlugin import org.jetbrains.kotlin.core.preferences.KotlinProperties -import org.jetbrains.kotlin.preferences.CompilerPluginDialog +import org.jetbrains.kotlin.preferences.compiler.CompilerPluginDialog import org.jetbrains.kotlin.swt.builders.* import org.jetbrains.kotlin.utils.LazyObservable import kotlin.properties.Delegates diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/views/codeStylePropertiesView.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/views/codeStylePropertiesView.kt new file mode 100644 index 000000000..b366b99aa --- /dev/null +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/views/codeStylePropertiesView.kt @@ -0,0 +1,20 @@ +package org.jetbrains.kotlin.preferences.views + +import org.eclipse.swt.widgets.Composite +import org.jetbrains.kotlin.core.formatting.KotlinCodeStyleManager +import org.jetbrains.kotlin.core.preferences.KotlinCodeStyleProperties +import org.jetbrains.kotlin.swt.builders.* + +fun View.codeStylePropertiesView( + properties: KotlinCodeStyleProperties, + operations: View.() -> Unit = {} +) = + gridContainer(cols = 2) { + label("Code style:") + singleOptionPreference( + properties::codeStyleId, + KotlinCodeStyleManager.styles, + KotlinCodeStyleManager::getStyleLabel + ) { layout(horizontalGrab = true) } + operations() + } diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/ScriptClasspathUpdater.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/ScriptClasspathUpdater.kt index daafcf526..3587c0d2c 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/ScriptClasspathUpdater.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/ScriptClasspathUpdater.kt @@ -46,7 +46,7 @@ private fun tryUpdateScriptClasspath(file: IFile) { val dependenciesProvider = ScriptDependenciesProvider.getInstance(environment.project) - runJob("Check script dependencies", Job.DECORATE, null, { + runJob("Check script dependencies", Job.DECORATE, 0,null, { val newDependencies = dependenciesProvider.getScriptDependencies(KotlinPsiManager.getParsedFile(file)) // KotlinLogger.logInfo("Check for script definition: ${dependenciesProvider}") // KotlinLogger.logInfo("New dependencies: ${newDependencies?.classpath?.joinToString("\n") { it.absolutePath }}") diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/commands/j2k/JavaToKotlinActionHandler.java b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/commands/j2k/JavaToKotlinActionHandler.java index 6c782bec1..3f8caacde 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/commands/j2k/JavaToKotlinActionHandler.java +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/commands/j2k/JavaToKotlinActionHandler.java @@ -42,6 +42,7 @@ import org.eclipse.ui.ide.undo.CreateFileOperation; import org.eclipse.ui.ide.undo.DeleteResourcesOperation; import org.jetbrains.annotations.NotNull; +import org.jetbrains.kotlin.core.formatting.KotlinCodeStyleManagerKt; import org.jetbrains.kotlin.core.log.KotlinLogger; import org.jetbrains.kotlin.core.model.KotlinEnvironment; import org.jetbrains.kotlin.core.model.KotlinNature; @@ -213,7 +214,7 @@ private ConvertedKotlinData getConvertedFileData(@NotNull CompilationUnit compil jetFile.getNode().getText(), jetFile.getName(), KtPsiFactoryKt.KtPsiFactory(jetFile), - getDefaultLineDelimiter(compilationUnit)); + KotlinCodeStyleManagerKt.getCodeStyle(eclipseProject)); String fileName = FileUtil.getNameWithoutExtension(compilationUnit.getElementName()); IFile file = FileCreationOp.makeFile((IPackageFragment) compilationUnit.getParent(), compilationUnit.getPackageFragmentRoot(), fileName); diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/KotlinAutoIndentStrategy.java b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/KotlinAutoIndentStrategy.java index a95354d0f..c1c31001f 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/KotlinAutoIndentStrategy.java +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/KotlinAutoIndentStrategy.java @@ -16,14 +16,13 @@ *******************************************************************************/ package org.jetbrains.kotlin.ui.editors; +import com.intellij.formatting.FormatterImpl; +import com.intellij.formatting.Indent; +import com.intellij.psi.codeStyle.CodeStyleSettings; import org.eclipse.core.resources.IFile; -import org.eclipse.jface.text.BadLocationException; -import org.eclipse.jface.text.Document; -import org.eclipse.jface.text.DocumentCommand; -import org.eclipse.jface.text.IAutoEditStrategy; -import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.text.IRegion; -import org.eclipse.jface.text.TextUtilities; +import org.eclipse.jface.text.*; +import org.jetbrains.kotlin.core.formatting.KotlinCodeStyleManager; +import org.jetbrains.kotlin.core.formatting.KotlinCodeStyleManagerKt; import org.jetbrains.kotlin.core.log.KotlinLogger; import org.jetbrains.kotlin.eclipse.ui.utils.IndenterUtil; import org.jetbrains.kotlin.eclipse.ui.utils.LineEndUtil; @@ -34,10 +33,6 @@ import org.jetbrains.kotlin.ui.formatter.KotlinFormatterKt; import org.jetbrains.kotlin.ui.formatter.KotlinSpacingBuilderUtilImpl; -import com.intellij.formatting.FormatterImpl; -import com.intellij.formatting.Indent; -import com.intellij.psi.codeStyle.CodeStyleSettings; - public class KotlinAutoIndentStrategy implements IAutoEditStrategy { private static final char OPENING_BRACE_CHAR = '{'; @@ -56,7 +51,7 @@ public void customizeDocumentCommand(IDocument document, DocumentCommand command if (command.doit == false) { return; } - + if (command.length == 0 && command.text != null && isNewLine(document, command.text)) { autoEditAfterNewLine(document, command); } else if (CLOSING_BRACE_STRING.equals(command.text)) { @@ -117,8 +112,9 @@ private String getIndent(IDocument tempDocument, int offset) throws BadLocationE KtFile ktFile = KotlinFormatterKt.createKtFile(tempDocument.get(), psiFactory, eclipseFile.getName()); int line = tempDocument.getLineOfOffset(offset); - - CodeStyleSettings settings = KotlinFormatterKt.getSettings(); + + + CodeStyleSettings settings = KotlinCodeStyleManagerKt.getCodeStyle(eclipseFile.getProject()); KotlinBlock rootBlock = new KotlinBlock(ktFile.getNode(), KotlinFormatterKt.getNULL_ALIGNMENT_STRATEGY(), Indent.getNoneIndent(), diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/KotlinFormatAction.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/KotlinFormatAction.kt index 3bae6fc2f..77d5906c2 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/KotlinFormatAction.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/KotlinFormatAction.kt @@ -20,6 +20,7 @@ import org.eclipse.jdt.ui.actions.IJavaEditorActionDefinitionIds import org.eclipse.jdt.ui.actions.SelectionDispatchAction import org.eclipse.jface.text.ITextSelection import org.jetbrains.kotlin.core.builder.KotlinPsiManager +import org.jetbrains.kotlin.core.formatting.codeStyle import org.jetbrains.kotlin.core.log.KotlinLogger import org.jetbrains.kotlin.ui.formatter.EclipseDocumentRange import org.jetbrains.kotlin.ui.formatter.createPsiFactory @@ -42,7 +43,7 @@ class KotlinFormatAction(private val editor: KotlinEditor) : SelectionDispatchAc return } - formatRange(editor.document, getRange(selection), createPsiFactory(file), file.name) + formatRange(editor.document, getRange(selection), createPsiFactory(file), file.name, file.project.codeStyle) KotlinPsiManager.commitFile(file, editor.document) } diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/annotations/AnnotationManager.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/annotations/AnnotationManager.kt index 0d4f9c0a6..fd9a3fa0b 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/annotations/AnnotationManager.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/annotations/AnnotationManager.kt @@ -49,8 +49,8 @@ import org.jetbrains.kotlin.core.model.KotlinScriptEnvironment public object AnnotationManager { val MARKER_TYPE = "org.jetbrains.kotlin.ui.marker" - @JvmField val ANNOTATION_ERROR_TYPE = "org.jetbrains.kotlin.ui.annotation.error" - @JvmField val ANNOTATION_WARNING_TYPE = "org.jetbrains.kotlin.ui.annotation.warning" + const val ANNOTATION_ERROR_TYPE = "org.jetbrains.kotlin.ui.annotation.error" + const val ANNOTATION_WARNING_TYPE = "org.jetbrains.kotlin.ui.annotation.warning" val MARKED_TEXT = "markedText" @JvmField val IS_UNRESOLVED_REFERENCE = "isUnresolvedReference" @JvmField val MARKER_PROBLEM_TYPE = IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/occurrences/KotlinMarkOccurrences.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/occurrences/KotlinMarkOccurrences.kt index 4604cb7bc..082af34ca 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/occurrences/KotlinMarkOccurrences.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/occurrences/KotlinMarkOccurrences.kt @@ -17,7 +17,7 @@ package org.jetbrains.kotlin.ui.editors.occurrences import org.eclipse.core.resources.IFile -import org.eclipse.core.runtime.NullProgressMonitor +import org.eclipse.core.runtime.IProgressMonitor import org.eclipse.core.runtime.Status import org.eclipse.core.runtime.jobs.Job import org.eclipse.jdt.core.search.IJavaSearchConstants @@ -29,82 +29,102 @@ import org.eclipse.search.ui.text.Match import org.eclipse.ui.ISelectionListener import org.eclipse.ui.IWorkbenchPart import org.jetbrains.kotlin.core.builder.KotlinPsiManager +import org.jetbrains.kotlin.core.model.runJob import org.jetbrains.kotlin.core.references.resolveToSourceDeclaration import org.jetbrains.kotlin.descriptors.SourceElement import org.jetbrains.kotlin.eclipse.ui.utils.EditorUtil import org.jetbrains.kotlin.eclipse.ui.utils.getTextDocumentOffset -import org.jetbrains.kotlin.core.model.runJob import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.ui.commands.findReferences.KotlinScopedQuerySpecification import org.jetbrains.kotlin.ui.editors.KotlinCommonEditor import org.jetbrains.kotlin.ui.editors.KotlinEditor -import org.jetbrains.kotlin.ui.editors.KotlinFileEditor import org.jetbrains.kotlin.ui.editors.annotations.AnnotationManager import org.jetbrains.kotlin.ui.refactorings.rename.getLengthOfIdentifier import org.jetbrains.kotlin.ui.search.KotlinElementMatch import org.jetbrains.kotlin.ui.search.KotlinQueryParticipant import org.jetbrains.kotlin.ui.search.getContainingClassOrObjectForConstructor +import java.util.concurrent.atomic.AtomicReference public class KotlinMarkOccurrences(val kotlinEditor: KotlinCommonEditor) : ISelectionListener { companion object { private val ANNOTATION_TYPE = "org.eclipse.jdt.ui.occurrences" } - + + private val currentJob = AtomicReference(null) + override fun selectionChanged(part: IWorkbenchPart, selection: ISelection) { if (!kotlinEditor.isActive()) return - - runJob("Update occurrence annotations", Job.DECORATE) { - if (part is KotlinCommonEditor && selection is ITextSelection) { + + if (part is KotlinCommonEditor && selection is ITextSelection) { + currentJob.updateAndGet { + it?.cancel() + runOccurencesJob(part, selection) + } + } + } + + private fun runOccurencesJob(part: KotlinCommonEditor, selection: ITextSelection) = + runJob("Update occurrence annotations", Job.DECORATE, 300) { monitor -> + val file = part.eclipseFile - if (file == null || !file.exists()) return@runJob Status.CANCEL_STATUS - + if (file == null || !file.exists()) { + return@runJob Status.CANCEL_STATUS + } + val document = part.getDocumentSafely() if (document == null) return@runJob Status.CANCEL_STATUS - + KotlinPsiManager.getKotlinFileIfExist(file, document.get()) - + + if (monitor.isCanceled) { + return@runJob Status.CANCEL_STATUS + } + val ktElement = EditorUtil.getJetElement(part, selection.getOffset()) if (ktElement == null) { return@runJob Status.CANCEL_STATUS } - - val occurrences = findOccurrences(part, ktElement, file) + + val occurrences = findOccurrences(part, ktElement, file, monitor) + + if (monitor.isCanceled) { + return@runJob Status.CANCEL_STATUS + } + updateOccurrences(part, occurrences) + + Status.OK_STATUS } - - Status.OK_STATUS - } - } - + private fun updateOccurrences(editor: KotlinEditor, occurrences: List) { val annotationMap = occurrences.associateBy { Annotation(ANNOTATION_TYPE, false, null) } AnnotationManager.updateAnnotations(editor, annotationMap, ANNOTATION_TYPE) } - - private fun findOccurrences(editor: KotlinCommonEditor, jetElement: KtElement, file: IFile): List { + + private fun findOccurrences(editor: KotlinCommonEditor, jetElement: KtElement, file: IFile, monitor: IProgressMonitor?): List { val sourceElements = jetElement.resolveToSourceDeclaration() if (sourceElements.isEmpty()) return emptyList() - + val searchingElements = getSearchingElements(sourceElements) - - val querySpecification = KotlinScopedQuerySpecification(searchingElements, listOf(file), + + val querySpecification = KotlinScopedQuerySpecification(searchingElements, listOf(file), IJavaSearchConstants.ALL_OCCURRENCES, "Searching in ${file.getName()}") - + val occurrences = arrayListOf() - KotlinQueryParticipant().search({ occurrences.add(it) }, querySpecification, NullProgressMonitor()) - - return occurrences.map { + KotlinQueryParticipant().search({ occurrences.add(it) }, querySpecification, monitor) + + return occurrences.map { if (it !is KotlinElementMatch) return@map null - + val element = it.jetElement val length = getLengthOfIdentifier(element) if (length == null) return@map null - + val document = editor.getDocumentSafely() ?: return@map null Position(element.getTextDocumentOffset(document), length) }.filterNotNull() } - + private fun getSearchingElements(sourceElements: List): List { val classOrObjects = getContainingClassOrObjectForConstructor(sourceElements) return if (classOrObjects.isNotEmpty()) classOrObjects else sourceElements diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/organizeImports/KotlinOrganizeImportsAction.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/organizeImports/KotlinOrganizeImportsAction.kt index 408cca7f2..67227708d 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/organizeImports/KotlinOrganizeImportsAction.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/organizeImports/KotlinOrganizeImportsAction.kt @@ -1,20 +1,20 @@ /******************************************************************************* -* 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. -* -*******************************************************************************/ + * 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.ui.editors.organizeImports import org.eclipse.jdt.core.search.TypeNameMatch @@ -27,10 +27,12 @@ import org.eclipse.jdt.ui.actions.SelectionDispatchAction import org.eclipse.jface.window.Window import org.eclipse.ui.PlatformUI import org.jetbrains.kotlin.core.builder.KotlinPsiManager +import org.jetbrains.kotlin.core.formatting.codeStyle import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.eclipse.ui.utils.getBindingContext import org.jetbrains.kotlin.idea.core.formatter.KotlinCodeStyleSettings +import org.jetbrains.kotlin.idea.formatter.kotlinCustomSettings import org.jetbrains.kotlin.idea.imports.OptimizedImportsBuilder import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.ImportPath @@ -38,84 +40,83 @@ import org.jetbrains.kotlin.ui.editors.KotlinCommonEditor import org.jetbrains.kotlin.ui.editors.quickfix.findApplicableTypes import org.jetbrains.kotlin.ui.editors.quickfix.placeImports import org.jetbrains.kotlin.ui.editors.quickfix.replaceImports -import org.jetbrains.kotlin.ui.formatter.settings -import java.util.ArrayList +import java.util.* class KotlinOrganizeImportsAction(private val editor: KotlinCommonEditor) : SelectionDispatchAction(editor.site) { init { - setActionDefinitionId(IJavaEditorActionDefinitionIds.ORGANIZE_IMPORTS) - - setText(ActionMessages.OrganizeImportsAction_label); - setToolTipText(ActionMessages.OrganizeImportsAction_tooltip); - setDescription(ActionMessages.OrganizeImportsAction_description); + actionDefinitionId = IJavaEditorActionDefinitionIds.ORGANIZE_IMPORTS - PlatformUI.getWorkbench().getHelpSystem().setHelp(this, IJavaHelpContextIds.ORGANIZE_IMPORTS_ACTION); + text = ActionMessages.OrganizeImportsAction_label + toolTipText = ActionMessages.OrganizeImportsAction_tooltip + description = ActionMessages.OrganizeImportsAction_description + + PlatformUI.getWorkbench().helpSystem.setHelp(this, IJavaHelpContextIds.ORGANIZE_IMPORTS_ACTION) } - + companion object { - val ACTION_ID = "OrganizeImports" + const val ACTION_ID = "OrganizeImports" } - + override fun run() { val bindingContext = getBindingContext(editor) ?: return val ktFile = editor.parsedFile ?: return val file = editor.eclipseFile ?: return - + val typeNamesToImport = bindingContext.diagnostics .filter { it.factory == Errors.UNRESOLVED_REFERENCE && it.psiFile == ktFile } .map { it.psiElement.text } .distinct() - + val (uniqueImports, ambiguousImports) = findTypesToImport(typeNamesToImport) - + val allRequiredImports = ArrayList(uniqueImports) if (ambiguousImports.isNotEmpty()) { - val chosenImports = chooseImports(ambiguousImports) - if (chosenImports == null) return - + val chosenImports = chooseImports(ambiguousImports) ?: return + allRequiredImports.addAll(chosenImports) } - + placeImports(allRequiredImports, file, editor.document) - + KotlinPsiManager.commitFile(file, editor.document) - + optimizeImports() } - + private fun optimizeImports() { val ktFile = editor.parsedFile ?: return val file = editor.eclipseFile ?: return val descriptorsToImport = collectDescriptorsToImport(ktFile) - - val optimizedImports = prepareOptimizedImports(ktFile, descriptorsToImport) ?: return - + val kotlinCodeStyleSettings = file.project.codeStyle.kotlinCustomSettings + + val optimizedImports = prepareOptimizedImports(ktFile, descriptorsToImport, kotlinCodeStyleSettings) ?: return + replaceImports(optimizedImports.map { it.toString() }, file, editor.document) } - + // null signalizes about cancelling operation private fun chooseImports(ambiguousImports: List>): List? { val labelProvider = TypeNameMatchLabelProvider(TypeNameMatchLabelProvider.SHOW_FULLYQUALIFIED) - - val dialog = MultiElementListSelectionDialog(getShell(), labelProvider) + + val dialog = MultiElementListSelectionDialog(shell, labelProvider) dialog.setTitle(ActionMessages.OrganizeImportsAction_selectiondialog_title) dialog.setMessage(ActionMessages.OrganizeImportsAction_selectiondialog_message) - - val arrayImports = Array>(ambiguousImports.size) { i -> + + val arrayImports = Array>(ambiguousImports.size) { i -> Array(ambiguousImports[i].size) { j -> ambiguousImports[i][j] } } - + dialog.setElements(arrayImports) - + return if (dialog.open() == Window.OK) { - dialog.result.mapNotNull { (it as Array<*>).firstOrNull() as? TypeNameMatch } - } else { - null - } + dialog.result.mapNotNull { (it as Array<*>).firstOrNull() as? TypeNameMatch } + } else { + null + } } - + private fun findTypesToImport(typeNames: List): UniqueAndAmbiguousImports { val uniqueImports = arrayListOf() val ambiguousImports = arrayListOf>() @@ -127,25 +128,23 @@ class KotlinOrganizeImportsAction(private val editor: KotlinCommonEditor) : Sele else -> ambiguousImports.add(typesToImport) } } - + return UniqueAndAmbiguousImports(uniqueImports, ambiguousImports) } - + private data class UniqueAndAmbiguousImports( - val uniqueImports: List, + val uniqueImports: List, val ambiguousImports: List>) } fun prepareOptimizedImports(file: KtFile, - descriptorsToImport: Collection): List? { - val settings = settings.getCustomSettings(KotlinCodeStyleSettings::class.java) - - return OptimizedImportsBuilder( - file, - OptimizedImportsBuilder.InputData(descriptorsToImport.toSet(), emptyList()), - OptimizedImportsBuilder.Options( - settings.NAME_COUNT_TO_USE_STAR_IMPORT, - settings.NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS, - { fqName -> fqName.asString() in settings.PACKAGES_TO_USE_STAR_IMPORTS }) - ).buildOptimizedImports() -} \ No newline at end of file + descriptorsToImport: Collection, + settings: KotlinCodeStyleSettings): List? = + OptimizedImportsBuilder( + file, + OptimizedImportsBuilder.InputData(descriptorsToImport.toSet(), emptyList()), + OptimizedImportsBuilder.Options( + settings.NAME_COUNT_TO_USE_STAR_IMPORT, + settings.NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS + ) { fqName -> fqName.asString() in settings.PACKAGES_TO_USE_STAR_IMPORTS } + ).buildOptimizedImports() \ No newline at end of file diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickassist/KotlinConvertToBlockBodyAssistProposal.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickassist/KotlinConvertToBlockBodyAssistProposal.kt index 8f5148e11..957726c72 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickassist/KotlinConvertToBlockBodyAssistProposal.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickassist/KotlinConvertToBlockBodyAssistProposal.kt @@ -22,6 +22,7 @@ import com.intellij.psi.PsiWhiteSpace import com.intellij.psi.util.PsiTreeUtil import org.eclipse.jface.text.IDocument import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.core.formatting.codeStyle import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.eclipse.ui.utils.getBindingContext import org.jetbrains.kotlin.psi.KtBlockExpression @@ -96,7 +97,8 @@ class KotlinConvertToBlockBodyAssistProposal(editor: KotlinEditor) : KotlinQuick editor.document, TextRange(anchorStartOffset, anchorStartOffset + newBodyText.length), factory, - file.name) + file.name, + file.project.codeStyle) } private fun specifyType(declaration: KtDeclarationWithBody, factory: KtPsiFactory, context: BindingContext) { diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickassist/KotlinConvertToExpressionBodyAssistProposal.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickassist/KotlinConvertToExpressionBodyAssistProposal.kt index 52d717a90..8d4664054 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickassist/KotlinConvertToExpressionBodyAssistProposal.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickassist/KotlinConvertToExpressionBodyAssistProposal.kt @@ -24,6 +24,7 @@ import org.eclipse.jface.text.IDocument import org.eclipse.jface.text.TextUtilities import org.jetbrains.kotlin.builtins.DefaultBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.core.formatting.codeStyle import org.jetbrains.kotlin.eclipse.ui.utils.getBindingContext import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers import org.jetbrains.kotlin.lexer.KtTokens @@ -87,7 +88,7 @@ public class KotlinConvertToExpressionBodyAssistProposal(editor: KotlinEditor) : val lineDelimiter = TextUtilities.getDefaultLineDelimiter(editor.javaEditor.getViewer().getDocument()) val file = editor.eclipseFile ?: return - val valueText = formatCode(newBody.node.text, file.name, psiFactory, lineDelimiter) + val valueText = formatCode(newBody.node.text, file.name, psiFactory, file.project.codeStyle) replace(body, "$eqToken $valueText") } diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickassist/KotlinImplementMethodsProposal.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickassist/KotlinImplementMethodsProposal.kt index 77cbca20e..31057961e 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickassist/KotlinImplementMethodsProposal.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickassist/KotlinImplementMethodsProposal.kt @@ -23,6 +23,7 @@ import com.intellij.psi.util.PsiTreeUtil import org.eclipse.jface.text.IDocument import org.eclipse.jface.text.TextUtilities import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.core.formatting.codeStyle import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor @@ -113,7 +114,8 @@ public class KotlinImplementMethodsProposal( document, EclipseDocumentRange(insertOffset, insertOffset + generatedText.length), psiFactory, - file.name) + file.name, + file.project.codeStyle) } private fun removeWhitespaceAfterLBrace(body: KtClassBody, document: IDocument, editor: KotlinEditor) { diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/templates/KotlinTemplateFormatter.java b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/templates/KotlinTemplateFormatter.java index 1f887b761..e715ae8b0 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/templates/KotlinTemplateFormatter.java +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/templates/KotlinTemplateFormatter.java @@ -27,6 +27,7 @@ import org.eclipse.core.resources.IProject; import org.eclipse.jface.text.templates.TemplateBuffer; import org.eclipse.jface.text.templates.TemplateVariable; +import org.jetbrains.kotlin.core.formatting.KotlinCodeStyleManagerKt; import org.jetbrains.kotlin.core.model.KotlinEnvironment; import org.jetbrains.kotlin.psi.KtFile; import org.jetbrains.kotlin.psi.KtPsiFactory; @@ -160,12 +161,10 @@ public void format(TemplateBuffer buffer, String lineDelimiter, IProject eclipse VariableOffsetsTracker offsetsTracker = new VariableOffsetsTracker(buffer.getString(), buffer.getVariables()); Project ideaProject = KotlinEnvironment.Companion.getEnvironment(eclipseProject).getProject(); KtFile parsedFile = new KtPsiFactory(ideaProject).createFile(offsetsTracker.getMarkedString()); - - assert parsedFile != null; - + KtPsiFactory psiFactory = KtPsiFactoryKt.KtPsiFactory(parsedFile); String formatted = KotlinFormatterKt.formatCode(parsedFile.getNode().getText(), parsedFile.getName(), - psiFactory, lineDelimiter); + psiFactory, KotlinCodeStyleManagerKt.getCodeStyle(eclipseProject)); offsetsTracker.unmark(formatted); diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/formatter/kotlinFormatter.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/formatter/kotlinFormatter.kt index d4e64709d..b1636fe24 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/formatter/kotlinFormatter.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/formatter/kotlinFormatter.kt @@ -1,19 +1,11 @@ package org.jetbrains.kotlin.ui.formatter -import com.intellij.formatting.Block -import com.intellij.formatting.DependantSpacingImpl -import com.intellij.formatting.DependentSpacingRule -import com.intellij.formatting.FormatTextRanges -import com.intellij.formatting.FormatterImpl -import com.intellij.formatting.Indent -import com.intellij.formatting.Spacing +import com.intellij.formatting.* import com.intellij.lang.ASTNode -import com.intellij.lang.Language import com.intellij.openapi.editor.impl.DocumentImpl import com.intellij.openapi.util.TextRange import com.intellij.openapi.util.text.StringUtil import com.intellij.psi.codeStyle.CodeStyleSettings -import com.intellij.psi.codeStyle.CommonCodeStyleSettings import com.intellij.psi.codeStyle.CommonCodeStyleSettings.IndentOptions import com.intellij.psi.formatter.FormatterUtil import com.intellij.util.text.CharArrayUtil @@ -23,32 +15,48 @@ import org.eclipse.jface.text.IDocument import org.jetbrains.kotlin.core.model.getEnvironment import org.jetbrains.kotlin.eclipse.ui.utils.IndenterUtil import org.jetbrains.kotlin.eclipse.ui.utils.LineEndUtil -import org.jetbrains.kotlin.idea.KotlinLanguage -import org.jetbrains.kotlin.idea.formatter.KotlinCommonCodeStyleSettings import org.jetbrains.kotlin.idea.formatter.KotlinSpacingBuilderUtil import org.jetbrains.kotlin.idea.formatter.createSpacingBuilder import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtPsiFactory import com.intellij.openapi.editor.Document as IdeaDocument -@Volatile -var settings: CodeStyleSettings = CodeStyleSettings(true) +fun formatCode( + source: String, + fileName: String, + psiFactory: KtPsiFactory, + settings: CodeStyleSettings +) = KotlinFormatter(source, fileName, psiFactory, settings).formatCode() -fun formatCode(source: String, fileName: String, psiFactory: KtPsiFactory, lineSeparator: String): String { - return KotlinFormatter(source, fileName, psiFactory, lineSeparator).formatCode() -} -fun reformatAll(containingFile: KtFile, rootBlock: Block, settings: CodeStyleSettings, document: IDocument) { +fun reformatAll( + containingFile: KtFile, + rootBlock: Block, + settings: CodeStyleSettings, + document: IDocument +) { formatRange(containingFile, rootBlock, settings, document, containingFile.textRange) } -fun formatRange(document: IDocument, range: EclipseDocumentRange, psiFactory: KtPsiFactory, fileName: String) { - formatRange(document, range.toPsiRange(document), psiFactory, fileName) +fun formatRange( + document: IDocument, + range: EclipseDocumentRange, + psiFactory: KtPsiFactory, + fileName: String, + settings: CodeStyleSettings +) { + formatRange(document, range.toPsiRange(document), psiFactory, fileName, settings) } -fun formatRange(document: IDocument, range: TextRange, psiFactory: KtPsiFactory, fileName: String) { +fun formatRange( + document: IDocument, + range: TextRange, + psiFactory: KtPsiFactory, + fileName: String, + settings: CodeStyleSettings +) { val ktFile = createKtFile(document.get(), psiFactory, fileName) - val rootBlock = KotlinBlock(ktFile.getNode(), + val rootBlock = KotlinBlock(ktFile.node, NULL_ALIGNMENT_STRATEGY, Indent.getNoneIndent(), null, @@ -63,7 +71,8 @@ private fun formatRange( rootBlock: Block, settings: CodeStyleSettings, document: IDocument, - range: TextRange) { + range: TextRange +) { val formattingModel = buildModel(containingFile, rootBlock, settings, document, false) val ranges = FormatTextRanges(range, true) @@ -109,7 +118,7 @@ private fun buildModel( initializaSettings(settings.indentOptions!!) val formattingDocumentModel = EclipseFormattingModel( - DocumentImpl(containingFile.getViewProvider().getContents(), true), + DocumentImpl(containingFile.viewProvider.contents, true), containingFile, settings, forLineIndentation) @@ -121,28 +130,32 @@ private fun buildModel( private fun getSignificantRange(file: KtFile, offset: Int): TextRange { val elementAtOffset = file.findElementAt(offset) if (elementAtOffset == null) { - val significantRangeStart = CharArrayUtil.shiftBackward(file.getText(), offset - 1, "\r\t "); - return TextRange(Math.max(significantRangeStart, 0), offset); + val significantRangeStart = CharArrayUtil.shiftBackward(file.text, offset - 1, "\r\t ") + return TextRange(Math.max(significantRangeStart, 0), offset) } - return elementAtOffset.getTextRange() + return elementAtOffset.textRange } -private class KotlinFormatter(source: String, fileName: String, psiFactory: KtPsiFactory, val lineSeparator: String) { - +private class KotlinFormatter( + source: String, + fileName: String, + psiFactory: KtPsiFactory, + val settings: CodeStyleSettings +) { val ktFile = createKtFile(source, psiFactory, fileName) - val sourceDocument = Document(source) + val sourceDocument = Document(source) - fun formatCode(): String { - FormatterImpl() - val rootBlock = KotlinBlock(ktFile.getNode(), - NULL_ALIGNMENT_STRATEGY, - Indent.getNoneIndent(), - null, - settings, - createSpacingBuilder(settings, KotlinSpacingBuilderUtilImpl)) + fun formatCode(): String { + FormatterImpl() + val rootBlock = KotlinBlock(ktFile.node, + NULL_ALIGNMENT_STRATEGY, + Indent.getNoneIndent(), + null, + settings, + createSpacingBuilder(settings, KotlinSpacingBuilderUtilImpl)) reformatAll(ktFile, rootBlock, settings, sourceDocument) diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/launch/KotlinLaunchShortcut.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/launch/KotlinLaunchShortcut.kt index f337f56df..b07a4a60c 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/launch/KotlinLaunchShortcut.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/launch/KotlinLaunchShortcut.kt @@ -16,35 +16,29 @@ *******************************************************************************/ package org.jetbrains.kotlin.ui.launch -import java.util.ArrayList import org.eclipse.core.resources.IContainer import org.eclipse.core.resources.IFile import org.eclipse.core.resources.IProject import org.eclipse.core.resources.IResource -import org.eclipse.core.runtime.CoreException -import org.eclipse.core.runtime.IAdaptable import org.eclipse.debug.core.DebugPlugin import org.eclipse.debug.core.ILaunchConfiguration import org.eclipse.debug.core.ILaunchConfigurationType -import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy import org.eclipse.debug.ui.DebugUITools import org.eclipse.debug.ui.ILaunchShortcut import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants import org.eclipse.jface.viewers.ISelection -import org.eclipse.jface.viewers.IStructuredSelection import org.eclipse.ui.IEditorPart +import org.jetbrains.kotlin.core.KOTLIN_CLASSPATH_PROVIDER_ID import org.jetbrains.kotlin.core.builder.KotlinPsiManager import org.jetbrains.kotlin.core.log.KotlinLogger -import org.jetbrains.kotlin.core.utils.ProjectUtils -import org.jetbrains.kotlin.eclipse.ui.utils.EditorUtil +import org.jetbrains.kotlin.core.model.KotlinEnvironment +import org.jetbrains.kotlin.core.preferences.languageVersionSettings import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil import org.jetbrains.kotlin.idea.KotlinFileType import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.ui.editors.KotlinFileEditor -import org.eclipse.jdt.core.JavaCore import org.jetbrains.kotlin.psi.KtDeclaration -import org.jetbrains.kotlin.core.KOTLIN_CLASSPATH_PROVIDER_ID +import org.jetbrains.kotlin.ui.editors.KotlinFileEditor +import java.util.* class KotlinLaunchShortcut : ILaunchShortcut { @@ -53,9 +47,9 @@ class KotlinLaunchShortcut : ILaunchShortcut { val classFqName = getStartClassFqName(entryPoint) if (classFqName == null) return null - val configWC = getLaunchConfigurationType().newInstance(null, "Config - " + entryPoint.getContainingKtFile().getName()).apply { + val configWC = getLaunchConfigurationType().newInstance(null, "Config - " + entryPoint.containingKtFile.name).apply { setAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, classFqName.asString()) - setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, project.getName()) + setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, project.name) setAttribute(IJavaLaunchConfigurationConstants.ATTR_CLASSPATH_PROVIDER, KOTLIN_CLASSPATH_PROVIDER_ID) } @@ -68,7 +62,7 @@ class KotlinLaunchShortcut : ILaunchShortcut { } private fun getLaunchConfigurationType(): ILaunchConfigurationType { - return DebugPlugin.getDefault().getLaunchManager().getLaunchConfigurationType(IJavaLaunchConfigurationConstants.ID_JAVA_APPLICATION) + return DebugPlugin.getDefault().launchManager.getLaunchConfigurationType(IJavaLaunchConfigurationConstants.ID_JAVA_APPLICATION) } } @@ -76,10 +70,11 @@ class KotlinLaunchShortcut : ILaunchShortcut { val mainFile = findFileToLaunch(selection) ?: return val ktFile = KotlinPsiManager.getParsedFile(mainFile) - - val entryPoint = getEntryPoint(ktFile) + + val entryPoint = getEntryPoint(ktFile, languageVersionFor(mainFile)) + if (entryPoint != null) { - launchWithMainClass(entryPoint, mainFile.getProject(), mode) + launchWithMainClass(entryPoint, mainFile.project, mode) } } @@ -94,8 +89,8 @@ class KotlinLaunchShortcut : ILaunchShortcut { val parsedFile = editor.parsedFile if (parsedFile == null) return - - val entryPoint = getEntryPoint(parsedFile) + + val entryPoint = getEntryPoint(parsedFile, languageVersionFor(file)) if (entryPoint != null) { launchWithMainClass(entryPoint, file.project, mode) return @@ -115,7 +110,7 @@ class KotlinLaunchShortcut : ILaunchShortcut { configurationType: ILaunchConfigurationType, entryPoint: KtDeclaration, project: IProject): ILaunchConfiguration? { - val configs = DebugPlugin.getDefault().getLaunchManager().getLaunchConfigurations(configurationType) + val configs = DebugPlugin.getDefault().launchManager.getLaunchConfigurations(configurationType) val mainClassName = getStartClassFqName(entryPoint)?.asString() if (mainClassName == null) return null @@ -130,10 +125,10 @@ class KotlinLaunchShortcut : ILaunchShortcut { } private fun addFiles(files: ArrayList, resource: IResource) { - when (resource.getType()) { + when (resource.type) { IResource.FILE -> { val file = resource as IFile - if (resource.getFileExtension() == KotlinFileType.INSTANCE.getDefaultExtension()) { + if (resource.getFileExtension() == KotlinFileType.INSTANCE.defaultExtension) { files.add(file) } } @@ -146,4 +141,7 @@ class KotlinLaunchShortcut : ILaunchShortcut { } } } -} \ No newline at end of file +} + +private fun languageVersionFor(file: IFile) = + KotlinEnvironment.getEnvironment(file.project).compilerProperties.languageVersionSettings \ No newline at end of file diff --git a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/launch/KotlinLaunchableTester.kt b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/launch/KotlinLaunchableTester.kt index 8d7427185..20acf154f 100644 --- a/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/launch/KotlinLaunchableTester.kt +++ b/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/launch/KotlinLaunchableTester.kt @@ -16,51 +16,43 @@ *******************************************************************************/ package org.jetbrains.kotlin.ui.launch +import com.intellij.psi.util.PsiTreeUtil import org.eclipse.core.expressions.PropertyTester import org.eclipse.core.resources.IFile import org.eclipse.core.runtime.IAdaptable -import org.eclipse.jdt.core.IJavaProject -import org.eclipse.jdt.core.JavaCore +import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.core.builder.KotlinPsiManager import org.jetbrains.kotlin.core.model.KotlinAnalysisFileCache -import org.jetbrains.kotlin.idea.MainFunctionDetector -import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.resolve.BindingContext -import java.util.ArrayList -import org.jetbrains.kotlin.psi.KtDeclaration -import org.jetbrains.kotlin.psi.KtClass -import org.jetbrains.kotlin.psi.KtObjectDeclaration -import org.eclipse.jdt.internal.core.JavaProject -import org.jetbrains.kotlin.psi.KtNamedFunction -import org.jetbrains.kotlin.psi.KtDeclarationContainer -import com.intellij.psi.util.PsiTreeUtil -import org.jetbrains.kotlin.psi.KtClassOrObject +import org.jetbrains.kotlin.core.model.KotlinEnvironment +import org.jetbrains.kotlin.core.preferences.languageVersionSettings import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil +import org.jetbrains.kotlin.idea.MainFunctionDetector import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.psi.* class KotlinLaunchableTester : PropertyTester() { override fun test(receiver: Any?, property: String?, args: Array?, expectedValue: Any?): Boolean { if (receiver !is IAdaptable) return false - - val file = receiver.getAdapter(IFile::class.java) - if (file == null) return false - - val ktFile = KotlinPsiManager.getKotlinParsedFile(file) - if (ktFile == null) return false - - return checkFileHasMain(ktFile) + + val file = receiver.getAdapter(IFile::class.java) ?: return false + + val ktFile = KotlinPsiManager.getKotlinParsedFile(file) ?: return false + + return checkFileHasMain( + ktFile, + KotlinEnvironment.getEnvironment(file.project).compilerProperties.languageVersionSettings) } } -fun checkFileHasMain(ktFile: KtFile): Boolean { - return getEntryPoint(ktFile) != null +fun checkFileHasMain(ktFile: KtFile, languageVersion: LanguageVersionSettings): Boolean { + return getEntryPoint(ktFile, languageVersion) != null } fun getStartClassFqName(mainFunctionDeclaration: KtDeclaration): FqName? { val container = mainFunctionDeclaration.declarationContainer() return when (container) { is KtFile -> JvmFileClassUtil.getFileClassInfoNoResolve(container).facadeClassFqName - + is KtClassOrObject -> { if (container is KtObjectDeclaration && container.isCompanion()) { val containerClass = PsiTreeUtil.getParentOfType(container, KtClass::class.java) @@ -69,32 +61,32 @@ fun getStartClassFqName(mainFunctionDeclaration: KtDeclaration): FqName? { container.fqName } } - + else -> null } } -fun getEntryPoint(ktFile: KtFile): KtDeclaration? { +fun getEntryPoint(ktFile: KtFile, languageVersion: LanguageVersionSettings): KtDeclaration? { val bindingContext = KotlinAnalysisFileCache.getAnalysisResult(ktFile).analysisResult.bindingContext - val mainFunctionDetector = MainFunctionDetector(bindingContext) - - val topLevelDeclarations = ktFile.getDeclarations() + val mainFunctionDetector = MainFunctionDetector(bindingContext, languageVersion) + + val topLevelDeclarations = ktFile.declarations for (declaration in topLevelDeclarations) { val mainFunction = when (declaration) { is KtNamedFunction -> if (mainFunctionDetector.isMain(declaration)) declaration else null - + is KtClass -> { - mainFunctionDetector.findMainFunction(declaration.getCompanionObjects().flatMap { it.declarations }) + mainFunctionDetector.findMainFunction(declaration.companionObjects.flatMap { it.declarations }) } - + is KtObjectDeclaration -> mainFunctionDetector.findMainFunction(declaration.declarations) - + else -> null } - + if (mainFunction != null) return mainFunction } - + return null } diff --git a/kotlin-weaving-feature/feature.xml b/kotlin-weaving-feature/feature.xml index 96c889cbd..b1ea49dff 100644 --- a/kotlin-weaving-feature/feature.xml +++ b/kotlin-weaving-feature/feature.xml @@ -2,7 +2,7 @@ ../pom.xml kotlin.eclipse kotlin.eclipse.plugin - 0.8.7-SNAPSHOT + 0.8.8-SNAPSHOT org.jetbrains.kotlin.weaving.feature kotlin.eclipse - 0.8.7-SNAPSHOT + 0.8.8-SNAPSHOT eclipse-feature \ No newline at end of file diff --git a/pom.xml b/pom.xml index d7e69d009..215b15fa1 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 kotlin.eclipse kotlin.eclipse.plugin - 0.8.7-SNAPSHOT + 0.8.8-SNAPSHOT pom @@ -28,7 +28,7 @@ http://download.eclipse.org/tools/ajdt/46/dev/update - 1.2.70-eap-40 + 1.3.0-rc-80 1.8.7 1.8