Skip to content

Commit 0c5be1f

Browse files
committed
as42: Additional fixes for AS42 and 202 platform
1 parent 32e21cf commit 0c5be1f

File tree

3 files changed

+541
-0
lines changed

3 files changed

+541
-0
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
3+
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
4+
*/
5+
package org.jetbrains.kotlin.cli.jvm.compiler;
6+
7+
import com.intellij.DynamicBundle;
8+
import com.intellij.codeInsight.ContainerProvider;
9+
import com.intellij.codeInsight.runner.JavaMainMethodProvider;
10+
import com.intellij.core.JavaCoreApplicationEnvironment;
11+
import com.intellij.lang.MetaLanguage;
12+
import com.intellij.openapi.Disposable;
13+
import com.intellij.openapi.extensions.Extensions;
14+
import com.intellij.openapi.vfs.VirtualFileSystem;
15+
import com.intellij.psi.FileContextProvider;
16+
import com.intellij.psi.augment.PsiAugmentProvider;
17+
import com.intellij.psi.compiled.ClassFileDecompilers;
18+
import com.intellij.psi.meta.MetaDataContributor;
19+
import org.jetbrains.annotations.NotNull;
20+
import org.jetbrains.annotations.Nullable;
21+
import org.jetbrains.kotlin.cli.jvm.modules.CoreJrtFileSystem;
22+
23+
public class KotlinCoreApplicationEnvironment extends JavaCoreApplicationEnvironment {
24+
public static KotlinCoreApplicationEnvironment create(@NotNull Disposable parentDisposable, boolean unitTestMode) {
25+
KotlinCoreApplicationEnvironment environment = new KotlinCoreApplicationEnvironment(parentDisposable, unitTestMode);
26+
registerExtensionPoints();
27+
return environment;
28+
}
29+
30+
private KotlinCoreApplicationEnvironment(@NotNull Disposable parentDisposable, boolean unitTestMode) {
31+
super(parentDisposable, unitTestMode);
32+
}
33+
34+
private static void registerExtensionPoints() {
35+
registerApplicationExtensionPoint(DynamicBundle.LanguageBundleEP.EP_NAME, DynamicBundle.LanguageBundleEP.class);
36+
registerApplicationExtensionPoint(FileContextProvider.EP_NAME, FileContextProvider.class);
37+
38+
registerApplicationExtensionPoint(MetaDataContributor.EP_NAME, MetaDataContributor.class);
39+
registerApplicationExtensionPoint(PsiAugmentProvider.EP_NAME, PsiAugmentProvider.class);
40+
registerApplicationExtensionPoint(JavaMainMethodProvider.EP_NAME, JavaMainMethodProvider.class);
41+
42+
registerApplicationExtensionPoint(ContainerProvider.EP_NAME, ContainerProvider.class);
43+
registerApplicationExtensionPoint(ClassFileDecompilers.getInstance().EP_NAME, ClassFileDecompilers.Decompiler.class);
44+
45+
registerApplicationExtensionPoint(MetaLanguage.EP_NAME, MetaLanguage.class);
46+
47+
IdeaExtensionPoints.INSTANCE.registerVersionSpecificAppExtensionPoints(Extensions.getRootArea());
48+
}
49+
50+
@Nullable
51+
@Override
52+
protected VirtualFileSystem createJrtFileSystem() {
53+
return new CoreJrtFileSystem();
54+
}
55+
}
Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
/*
2+
* Copyright 2010-2015 JetBrains s.r.o.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.jetbrains.kotlin.idea.actions
18+
19+
import com.intellij.ide.actions.CreateFileFromTemplateAction
20+
import com.intellij.ide.actions.CreateFileFromTemplateDialog
21+
import com.intellij.ide.actions.CreateFromTemplateAction
22+
import com.intellij.ide.fileTemplates.FileTemplate
23+
import com.intellij.ide.fileTemplates.FileTemplateManager
24+
import com.intellij.ide.fileTemplates.actions.AttributesDefaults
25+
import com.intellij.ide.fileTemplates.ui.CreateFromTemplateDialog
26+
import com.intellij.openapi.actionSystem.DataContext
27+
import com.intellij.openapi.actionSystem.LangDataKeys
28+
import com.intellij.openapi.actionSystem.PlatformDataKeys
29+
import com.intellij.openapi.editor.LogicalPosition
30+
import com.intellij.openapi.extensions.ExtensionPointName
31+
import com.intellij.openapi.fileEditor.FileEditorManager
32+
import com.intellij.openapi.module.Module
33+
import com.intellij.openapi.module.ModuleUtilCore
34+
import com.intellij.openapi.project.DumbAware
35+
import com.intellij.openapi.project.DumbService
36+
import com.intellij.openapi.project.Project
37+
import com.intellij.openapi.roots.ProjectRootManager
38+
import com.intellij.openapi.ui.InputValidatorEx
39+
import com.intellij.psi.PsiDirectory
40+
import com.intellij.psi.PsiFile
41+
import com.intellij.util.IncorrectOperationException
42+
import org.jetbrains.annotations.TestOnly
43+
import org.jetbrains.kotlin.idea.KotlinBundle
44+
import org.jetbrains.kotlin.idea.KotlinFileType
45+
import org.jetbrains.kotlin.idea.KotlinIcons
46+
import org.jetbrains.kotlin.idea.statistics.FUSEventGroups
47+
import org.jetbrains.kotlin.idea.statistics.KotlinFUSLogger
48+
import org.jetbrains.kotlin.idea.util.application.runWriteAction
49+
import org.jetbrains.kotlin.lexer.KtTokens
50+
import org.jetbrains.kotlin.parsing.KotlinParserDefinition.Companion.STD_SCRIPT_SUFFIX
51+
import org.jetbrains.kotlin.psi.KtClass
52+
import org.jetbrains.kotlin.psi.KtFile
53+
import org.jetbrains.kotlin.psi.KtNamedDeclaration
54+
import java.util.*
55+
56+
class NewKotlinFileAction : CreateFileFromTemplateAction(
57+
KotlinBundle.message("action.new.file.text"),
58+
KotlinBundle.message("action.new.file.description"),
59+
KotlinFileType.INSTANCE.icon
60+
), DumbAware {
61+
override fun postProcess(createdElement: PsiFile, templateName: String?, customProperties: Map<String, String>?) {
62+
super.postProcess(createdElement, templateName, customProperties)
63+
64+
val module = ModuleUtilCore.findModuleForPsiElement(createdElement!!)
65+
66+
if (createdElement is KtFile) {
67+
if (module != null) {
68+
for (hook in NewKotlinFileHook.EP_NAME.extensions) {
69+
hook.postProcess(createdElement, module)
70+
}
71+
}
72+
73+
val ktClass = createdElement.declarations.singleOrNull() as? KtNamedDeclaration
74+
if (ktClass != null) {
75+
CreateFromTemplateAction.moveCaretAfterNameIdentifier(ktClass)
76+
} else {
77+
val editor = FileEditorManager.getInstance(createdElement.project).selectedTextEditor ?: return
78+
if (editor.document == createdElement.viewProvider.document) {
79+
val lineCount = editor.document.lineCount
80+
if (lineCount > 0) {
81+
editor.caretModel.moveToLogicalPosition(LogicalPosition(lineCount - 1, 0))
82+
}
83+
}
84+
}
85+
}
86+
}
87+
88+
override fun buildDialog(project: Project, directory: PsiDirectory, builder: CreateFileFromTemplateDialog.Builder) {
89+
builder.setTitle(KotlinBundle.message("action.new.file.dialog.title"))
90+
.addKind(
91+
KotlinBundle.message("action.new.file.dialog.file.title"),
92+
KotlinFileType.INSTANCE.icon,
93+
"Kotlin File"
94+
)
95+
.addKind(
96+
KotlinBundle.message("action.new.file.dialog.class.title"),
97+
KotlinIcons.CLASS,
98+
"Kotlin Class"
99+
)
100+
.addKind(
101+
KotlinBundle.message("action.new.file.dialog.interface.title"),
102+
KotlinIcons.INTERFACE,
103+
"Kotlin Interface"
104+
)
105+
.addKind(
106+
KotlinBundle.message("action.new.file.dialog.enum.title"),
107+
KotlinIcons.ENUM,
108+
"Kotlin Enum"
109+
)
110+
.addKind(
111+
KotlinBundle.message("action.new.file.dialog.object.title"),
112+
KotlinIcons.OBJECT,
113+
"Kotlin Object"
114+
)
115+
116+
builder.setValidator(NameValidator)
117+
}
118+
119+
override fun getActionName(directory: PsiDirectory, newName: String, templateName: String): String =
120+
KotlinBundle.message("action.new.file.text")
121+
122+
override fun isAvailable(dataContext: DataContext): Boolean {
123+
if (super.isAvailable(dataContext)) {
124+
val ideView = LangDataKeys.IDE_VIEW.getData(dataContext)!!
125+
val project = PlatformDataKeys.PROJECT.getData(dataContext)!!
126+
val projectFileIndex = ProjectRootManager.getInstance(project).fileIndex
127+
return ideView.directories.any { projectFileIndex.isInSourceContent(it.virtualFile) }
128+
}
129+
130+
return false
131+
}
132+
133+
override fun hashCode(): Int = 0
134+
135+
override fun equals(other: Any?): Boolean = other is NewKotlinFileAction
136+
137+
override fun startInWriteAction() = false
138+
139+
override fun createFileFromTemplate(name: String, template: FileTemplate, dir: PsiDirectory) =
140+
createFileFromTemplateWithStat(name, template, dir)
141+
142+
companion object {
143+
private object NameValidator : InputValidatorEx {
144+
override fun getErrorText(inputString: String): String? {
145+
if (inputString.trim().isEmpty()) {
146+
return KotlinBundle.message("action.new.file.error.empty.name")
147+
}
148+
149+
val parts: List<String> = inputString.split(*FQNAME_SEPARATORS)
150+
if (parts.any { it.trim().isEmpty() }) {
151+
return KotlinBundle.message("action.new.file.error.empty.name.part")
152+
}
153+
154+
return null
155+
}
156+
157+
override fun checkInput(inputString: String): Boolean = true
158+
159+
override fun canClose(inputString: String): Boolean = getErrorText(inputString) == null
160+
}
161+
162+
@get:TestOnly
163+
val nameValidator: InputValidatorEx
164+
get() = NameValidator
165+
166+
private fun findOrCreateTarget(dir: PsiDirectory, name: String, directorySeparators: CharArray): Pair<String, PsiDirectory> {
167+
var className = removeKotlinExtensionIfPresent(name)
168+
var targetDir = dir
169+
170+
for (splitChar in directorySeparators) {
171+
if (splitChar in className) {
172+
val names = className.trim().split(splitChar)
173+
174+
for (dirName in names.dropLast(1)) {
175+
targetDir = targetDir.findSubdirectory(dirName) ?: runWriteAction {
176+
targetDir.createSubdirectory(dirName)
177+
}
178+
}
179+
180+
className = names.last()
181+
break
182+
}
183+
}
184+
return Pair(className, targetDir)
185+
}
186+
187+
private fun removeKotlinExtensionIfPresent(name: String): String = when {
188+
name.endsWith(".$KOTLIN_WORKSHEET_EXTENSION") -> name.removeSuffix(".$KOTLIN_WORKSHEET_EXTENSION")
189+
name.endsWith(".$STD_SCRIPT_SUFFIX") -> name.removeSuffix(".$STD_SCRIPT_SUFFIX")
190+
name.endsWith(".${KotlinFileType.EXTENSION}") -> name.removeSuffix(".${KotlinFileType.EXTENSION}")
191+
else -> name
192+
}
193+
194+
private fun createFromTemplate(dir: PsiDirectory, className: String, template: FileTemplate): PsiFile? {
195+
val project = dir.project
196+
val defaultProperties = FileTemplateManager.getInstance(project).defaultProperties
197+
198+
val properties = Properties(defaultProperties)
199+
200+
val element = try {
201+
CreateFromTemplateDialog(
202+
project, dir, template,
203+
AttributesDefaults(className).withFixedName(true),
204+
properties
205+
).create()
206+
} catch (e: IncorrectOperationException) {
207+
throw e
208+
} catch (e: Exception) {
209+
LOG.error(e)
210+
return null
211+
}
212+
213+
return element?.containingFile
214+
}
215+
216+
private val FILE_SEPARATORS = charArrayOf('/', '\\')
217+
private val FQNAME_SEPARATORS = charArrayOf('/', '\\', '.')
218+
219+
fun createFileFromTemplateWithStat(name: String, template: FileTemplate, dir: PsiDirectory): PsiFile? {
220+
KotlinFUSLogger.log(FUSEventGroups.NewFileTemplate, template.name)
221+
return createFileFromTemplate(name, template, dir)
222+
}
223+
224+
225+
fun createFileFromTemplate(name: String, template: FileTemplate, dir: PsiDirectory): PsiFile? {
226+
val directorySeparators = when (template.name) {
227+
"Kotlin File" -> FILE_SEPARATORS
228+
else -> FQNAME_SEPARATORS
229+
}
230+
val (className, targetDir) = findOrCreateTarget(dir, name, directorySeparators)
231+
232+
val service = DumbService.getInstance(dir.project)
233+
service.isAlternativeResolveEnabled = true
234+
try {
235+
val psiFile = createFromTemplate(targetDir, className, template)
236+
if (psiFile is KtFile) {
237+
val singleClass = psiFile.declarations.singleOrNull() as? KtClass
238+
if (singleClass != null && !singleClass.isEnum() && !singleClass.isInterface() && name.contains("Abstract")) {
239+
runWriteAction {
240+
singleClass.addModifier(KtTokens.ABSTRACT_KEYWORD)
241+
}
242+
}
243+
}
244+
return psiFile
245+
} finally {
246+
service.isAlternativeResolveEnabled = false
247+
}
248+
}
249+
}
250+
}
251+
252+
abstract class NewKotlinFileHook {
253+
companion object {
254+
val EP_NAME: ExtensionPointName<NewKotlinFileHook> =
255+
ExtensionPointName.create<NewKotlinFileHook>("org.jetbrains.kotlin.newFileHook")
256+
}
257+
258+
abstract fun postProcess(createdElement: KtFile, module: Module)
259+
}

0 commit comments

Comments
 (0)