Skip to content

Commit c5d6cf3

Browse files
committed
feat(intellij): implemented support for highlightning embedded arguments, escape sequences, python expressions and so on
1 parent 039682d commit c5d6cf3

19 files changed

+251
-151
lines changed

intellij-client/build.gradle.kts

Lines changed: 46 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import org.jetbrains.changelog.Changelog
22
import org.jetbrains.changelog.markdownToHTML
33
import org.jetbrains.intellij.platform.gradle.Constants.Constraints
4+
import org.jetbrains.intellij.platform.gradle.IntelliJPlatformType
45
import org.jetbrains.intellij.platform.gradle.TestFrameworkType
6+
import org.jetbrains.intellij.platform.gradle.tasks.PrepareSandboxTask
57
import java.net.URI
68
import java.net.http.HttpClient
79
import java.net.http.HttpRequest
@@ -29,7 +31,7 @@ kotlin {
2931
// Configure project's dependencies
3032
repositories {
3133
mavenCentral()
32-
34+
3335
// IntelliJ Platform Gradle Plugin Repositories Extension - read more: https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-repositories-extension.html
3436
intellijPlatform {
3537
defaultRepositories()
@@ -41,39 +43,19 @@ dependencies {
4143
compileOnly(libs.kotlinxSerialization)
4244
testImplementation(kotlin("test"))
4345
testImplementation(libs.junit)
44-
46+
4547
// IntelliJ Platform Gradle Plugin Dependencies Extension - read more: https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-dependencies-extension.html
4648
intellijPlatform {
4749
create(
4850
providers.gradleProperty("platformType"),
4951
providers.gradleProperty("platformVersion"),
5052
useInstaller = false
5153
)
52-
54+
5355
// Plugin Dependencies. Uses `platformBundledPlugins` property from the gradle.properties file for bundled IntelliJ Platform plugins.
5456
bundledPlugins(providers.gradleProperty("platformBundledPlugins").map { it.split(',') })
55-
56-
// Plugin Dependencies. Uses `platformPlugins` property from the gradle.properties file for plugin from JetBrains Marketplace.
57-
// plugins(providers.gradleProperty("platformPlugins").map { it.split(',') })
58-
59-
val platformPlugins = ArrayList<String>()
60-
// val localLsp4ij = file("../lsp4ij.old/build/idea-sandbox/plugins/LSP4IJ").absoluteFile
61-
// if (localLsp4ij.isDirectory) {
62-
// // In case Gradle fails to build because it can't find some missing jar, try deleting
63-
// // ~/.gradle/caches/modules-2/files-2.1/com.jetbrains.intellij.idea/unzipped.com.jetbrains.plugins/com.redhat.devtools.lsp4ij*
64-
// localPlugin(localLsp4ij.toString())
65-
// } else {
66-
// // When running on CI or when there's no local lsp4ij
67-
// val latestLsp4ijNightlyVersion = fetchLatestLsp4ijNightlyVersion()
68-
// platformPlugins.add("com.redhat.devtools.lsp4ij:$latestLsp4ijNightlyVersion@nightly")
69-
// }
70-
71-
platformPlugins.add("com.redhat.devtools.lsp4ij:0.9.0")
72-
//Uses `platformPlugins` property from the gradle.properties file.
73-
platformPlugins.addAll(providers.gradleProperty("platformPlugins").map { it.split(',').map(String::trim).filter(String::isNotEmpty) }.get())
74-
75-
plugins(platformPlugins)
76-
57+
plugins(providers.gradleProperty("platformPlugins").map { it.split(',') })
58+
7759
pluginVerifier()
7860
zipSigner()
7961
testFramework(TestFrameworkType.Platform)
@@ -85,20 +67,20 @@ intellijPlatform {
8567
pluginConfiguration {
8668
name = providers.gradleProperty("pluginName")
8769
version = providers.gradleProperty("pluginVersion")
88-
70+
8971
// Extract the <!-- Plugin description --> section from README.md and provide for the plugin's manifest
9072
description = providers.fileContents(layout.projectDirectory.file("README.md")).asText.map {
9173
val start = "<!-- Plugin description -->"
9274
val end = "<!-- Plugin description end -->"
93-
75+
9476
with(it.lines()) {
9577
if (!containsAll(listOf(start, end))) {
9678
throw GradleException("Plugin description section not found in README.md:\n$start ... $end")
9779
}
9880
subList(indexOf(start) + 1, indexOf(end)).joinToString("\n").let(::markdownToHTML)
9981
}
10082
}
101-
83+
10284
val changelog = project.changelog // local variable for configuration cache compatibility
10385
// Get the latest available change notes from the changelog file
10486
changeNotes = providers.gradleProperty("pluginVersion").map { pluginVersion ->
@@ -111,19 +93,19 @@ intellijPlatform {
11193
)
11294
}
11395
}
114-
96+
11597
ideaVersion {
11698
sinceBuild = providers.gradleProperty("pluginSinceBuild")
11799
untilBuild = providers.gradleProperty("pluginUntilBuild")
118100
}
119101
}
120-
102+
121103
signing {
122104
certificateChain = providers.environmentVariable("CERTIFICATE_CHAIN")
123105
privateKey = providers.environmentVariable("PRIVATE_KEY")
124106
password = providers.environmentVariable("PRIVATE_KEY_PASSWORD")
125107
}
126-
108+
127109
publishing {
128110
token = providers.environmentVariable("PUBLISH_TOKEN")
129111
// The pluginVersion is based on the SemVer (https://semver.org) and supports pre-release labels, like 2.1.7-alpha.3
@@ -132,7 +114,7 @@ intellijPlatform {
132114
channels = providers.gradleProperty("pluginVersion")
133115
.map { listOf(it.substringAfter('-', "").substringBefore('.').ifEmpty { "default" }) }
134116
}
135-
117+
136118
pluginVerification {
137119
ides {
138120
recommended()
@@ -158,6 +140,15 @@ kover {
158140
}
159141
}
160142

143+
val prepareSandboxConfig: PrepareSandboxTask.() -> Unit = {
144+
from("..") {
145+
include("package.json", "language-configuration.json", "syntaxes/**/*", "bundled/**/*")
146+
exclude("**/bin")
147+
exclude("**/__pycache__")
148+
into("robotcode4ij/data")
149+
}
150+
}
151+
161152
tasks {
162153
runIde {
163154
// From https://app.slack.com/client/T5P9YATH9/C5U8BM1MK
@@ -166,25 +157,20 @@ tasks {
166157
// systemProperty("terminal.new.ui", "false")
167158
// systemProperty("ide.tree.painter.compact.default", "true")
168159
}
169-
160+
170161
wrapper {
171162
gradleVersion = providers.gradleProperty("gradleVersion").get()
172163
}
173-
164+
174165
publishPlugin {
175166
dependsOn(patchChangelog)
176167
}
177-
prepareSandbox {
178-
from("..") {
179-
include("package.json", "language-configuration.json", "syntaxes/**/*", "bundled/**/*" )
180-
181-
exclude("**/bin")
182-
exclude("**/__pycache__")
183-
into("robotcode4ij/data")
184-
}
185-
}
168+
169+
prepareSandbox(prepareSandboxConfig)
186170
}
187171

172+
173+
188174
// Configure UI tests plugin
189175
// Read more: https://github.com/JetBrains/intellij-ui-test-robot
190176
val runIdeForUiTests by intellijPlatformTesting.runIde.registering {
@@ -198,12 +184,26 @@ val runIdeForUiTests by intellijPlatformTesting.runIde.registering {
198184
)
199185
}
200186
}
201-
187+
188+
prepareSandboxTask(prepareSandboxConfig)
189+
202190
plugins {
203191
robotServerPlugin(Constraints.LATEST_VERSION)
204192
}
205193
}
206194

195+
val runIdePyCharmProf by intellijPlatformTesting.runIde.registering {
196+
type = IntelliJPlatformType.PyCharmProfessional
197+
198+
prepareSandboxTask(prepareSandboxConfig)
199+
}
200+
201+
val runIdeIntellijIdeaC by intellijPlatformTesting.runIde.registering {
202+
type = IntelliJPlatformType.IntellijIdeaCommunity
203+
204+
prepareSandboxTask(prepareSandboxConfig)
205+
}
206+
207207
fun fetchLatestLsp4ijNightlyVersion(): String {
208208
val client = HttpClient.newBuilder().build();
209209
var onlineVersion = ""
@@ -220,10 +220,10 @@ fun fetchLatestLsp4ijNightlyVersion(): String {
220220
onlineVersion = matcher.group(1)
221221
println("Latest approved nightly build: $onlineVersion")
222222
}
223-
} catch (e:Exception) {
223+
} catch (e: Exception) {
224224
println("Failed to fetch LSP4IJ nightly build version: ${e.message}")
225225
}
226-
226+
227227
val minVersion = "0.0.1-20231213-012910"
228228
return if (minVersion < onlineVersion) onlineVersion else minVersion
229229
}

intellij-client/gradle.properties

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ platformVersion = 2024.3.1
1717

1818
# Plugin Dependencies -> https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html
1919
# Example: platformPlugins = com.jetbrains.php:203.4449.22, org.intellij.scala:2023.3.27@EAP
20-
#platformPlugins = com.redhat.devtools.lsp4ij:0.3.0
21-
platformPlugins =
20+
platformPlugins = com.redhat.devtools.lsp4ij:0.9.0
2221
# Example: platformBundledPlugins = com.intellij.java
2322
platformBundledPlugins = PythonCore, org.jetbrains.plugins.textmate
2423

intellij-client/src/main/kotlin/dev/robotcode/robotcode4ij/execution/RobotCodeRunConfiguration.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package dev.robotcode.robotcode4ij.execution
22

33
import com.intellij.execution.Executor
4+
import com.intellij.execution.compound.CompoundRunConfigurationSettingsEditor
45
import com.intellij.execution.configurations.ConfigurationFactory
56
import com.intellij.execution.configurations.LocatableConfigurationBase
67
import com.intellij.execution.configurations.RunConfiguration
@@ -17,7 +18,8 @@ class RobotCodeRunConfiguration(project: Project, factory: ConfigurationFactory)
1718
}
1819

1920
override fun getConfigurationEditor(): SettingsEditor<out RunConfiguration> {
20-
TODO("Not yet implemented")
21+
// TODO: Implement configuration editor
22+
return RobotCodeRunConfigurationEditor()
2123
}
2224

2325
var suite: String = ""
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package dev.robotcode.robotcode4ij.execution
2+
3+
import com.intellij.execution.configuration.EnvironmentVariablesComponent
4+
import com.intellij.util.ui.ComponentWithEmptyText
5+
import com.intellij.ui.RawCommandLineEditor
6+
import com.intellij.openapi.options.SettingsEditor
7+
import com.intellij.ui.dsl.builder.AlignX
8+
import com.intellij.ui.dsl.builder.panel
9+
import javax.swing.JComponent
10+
11+
class RobotCodeRunConfigurationEditor : SettingsEditor<RobotCodeRunConfiguration>() {
12+
13+
private val environmentVariablesField = EnvironmentVariablesComponent()
14+
15+
private val argumentsField =
16+
RawCommandLineEditor().apply {
17+
if (textField is ComponentWithEmptyText) {
18+
(textField as ComponentWithEmptyText).emptyText.text =
19+
"Additional flags, e.g. --skip-cache, or --parallel=2"
20+
}
21+
}
22+
23+
override fun resetEditorFrom(s: RobotCodeRunConfiguration) {
24+
// TODO("Not yet implemented")
25+
}
26+
27+
override fun applyEditorTo(s: RobotCodeRunConfiguration) {
28+
// TODO("Not yet implemented")
29+
}
30+
31+
override fun createEditor(): JComponent {
32+
return panel {
33+
row("&Robot:") {
34+
textField().label("Suite:")
35+
}
36+
row(environmentVariablesField.label) {
37+
cell(environmentVariablesField.component).align(AlignX.FILL)
38+
}
39+
row("A&rguments:") { cell(argumentsField).align(AlignX.FILL) }
40+
}
41+
}
42+
43+
}

intellij-client/src/main/kotlin/dev/robotcode/robotcode4ij/execution/RobotCodeRunProfileState.kt

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,21 @@
11
package dev.robotcode.robotcode4ij.execution
22

33
import com.intellij.execution.configurations.CommandLineState
4-
import com.intellij.execution.configurations.GeneralCommandLine
54
import com.intellij.execution.process.KillableProcessHandler
65
import com.intellij.execution.process.ProcessHandler
76
import com.intellij.execution.process.ProcessTerminatedListener
8-
97
import com.intellij.execution.runners.ExecutionEnvironment
10-
import com.jetbrains.python.sdk.pythonSdk
11-
import dev.robotcode.robotcode4ij.RobotCodeHelpers
12-
import kotlin.io.path.pathString
8+
import dev.robotcode.robotcode4ij.buildRobotCodeCommandLine
139

1410
class RobotCodeRunProfileState(environment: ExecutionEnvironment) : CommandLineState(environment) {
1511
override fun startProcess(): ProcessHandler {
1612
val project = environment.project
17-
val pythonInterpreter = project.pythonSdk?.homePath
18-
?: throw IllegalArgumentException("PythonSDK is not defined for project ${project.name}")
13+
val profile = environment.runProfile as? RobotCodeRunConfiguration
14+
// TODO: Add support for configurable paths
15+
val defaultPaths = arrayOf("--default-path", ".")
16+
17+
val commandLine = project.buildRobotCodeCommandLine(arrayOf(*defaultPaths, "run"))
1918

20-
val commandLine = GeneralCommandLine(
21-
pythonInterpreter, "-u", "-X", "utf8",
22-
RobotCodeHelpers.robotCodePath.pathString,
23-
//"--log", "--log-level", "DEBUG",
24-
// "--debugpy",
25-
// "--debugpy-wait-for-client"
26-
"run"
27-
).withWorkDirectory(project.basePath).withCharset(Charsets.UTF_8)
2819
val handler = KillableProcessHandler(commandLine)
2920
ProcessTerminatedListener.attach(handler)
3021
return handler

intellij-client/src/main/kotlin/dev/robotcode/robotcode4ij/highlighting/Colors.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import com.intellij.openapi.editor.DefaultLanguageHighlighterColors
44
import com.intellij.openapi.editor.colors.TextAttributesKey
55
import com.intellij.openapi.editor.colors.TextAttributesKey.createTextAttributesKey
66

7-
object RobotColors {
7+
object Colors {
88

99
val HEADER: TextAttributesKey =
1010
createTextAttributesKey("ROBOTFRAMEWORK_HEADER", DefaultLanguageHighlighterColors.KEYWORD)

intellij-client/src/main/kotlin/dev/robotcode/robotcode4ij/highlighting/RobotCodeLexer.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import org.jetbrains.plugins.textmate.language.syntax.lexer.TextMateScope
2929
import java.util.*
3030
import kotlin.math.min
3131

32-
class RobotCodeTextMateHighlightingLexer : LexerBase() {
32+
class RobotCodeLexer : LexerBase() {
3333
companion object {
3434
val mapping by lazy {
3535
mapOf(

intellij-client/src/main/kotlin/dev/robotcode/robotcode4ij/highlighting/RobotCodeSyntaxHighlighter.kt

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -30,31 +30,31 @@ import org.jetbrains.plugins.textmate.language.syntax.lexer.TextMateScope
3030
import java.util.function.Function
3131

3232

33-
class RobotCodeHighlighter : SyntaxHighlighterBase() {
33+
class RobotCodeSyntaxHighlighter : SyntaxHighlighterBase() {
3434
companion object {
3535
val elementTypeMap = mapOf(
36-
COMMENT_LINE to arrayOf(RobotColors.LINE_COMMENT),
37-
COMMENT_BLOCK to arrayOf(RobotColors.BLOCK_COMMENT),
38-
VARIABLE_BEGIN to arrayOf(RobotColors.VARIABLE_BEGIN),
39-
VARIABLE_END to arrayOf(RobotColors.VARIABLE_END),
40-
ENVIRONMENT_VARIABLE_BEGIN to arrayOf(RobotColors.VARIABLE_BEGIN),
41-
ENVIRONMENT_VARIABLE_END to arrayOf(RobotColors.VARIABLE_END),
42-
TESTCASE_NAME to arrayOf(RobotColors.TESTCASE_NAME),
43-
KEYWORD_NAME to arrayOf(RobotColors.KEYWORD_NAME),
44-
HEADER to arrayOf(RobotColors.HEADER),
45-
SETTING to arrayOf(RobotColors.SETTING),
46-
KEYWORD_CALL to arrayOf(RobotColors.KEYWORD_CALL),
47-
CONTROL_FLOW to arrayOf(RobotColors.CONTROL_FLOW),
48-
VARIABLE to arrayOf(RobotColors.VARIABLE),
49-
OPERATOR to arrayOf(RobotColors.OPERATOR),
50-
ARGUMENT to arrayOf(RobotColors.ARGUMENT),
51-
CONTINUATION to arrayOf(RobotColors.CONTINUATION),
36+
COMMENT_LINE to arrayOf(Colors.LINE_COMMENT),
37+
COMMENT_BLOCK to arrayOf(Colors.BLOCK_COMMENT),
38+
VARIABLE_BEGIN to arrayOf(Colors.VARIABLE_BEGIN),
39+
VARIABLE_END to arrayOf(Colors.VARIABLE_END),
40+
ENVIRONMENT_VARIABLE_BEGIN to arrayOf(Colors.VARIABLE_BEGIN),
41+
ENVIRONMENT_VARIABLE_END to arrayOf(Colors.VARIABLE_END),
42+
TESTCASE_NAME to arrayOf(Colors.TESTCASE_NAME),
43+
KEYWORD_NAME to arrayOf(Colors.KEYWORD_NAME),
44+
HEADER to arrayOf(Colors.HEADER),
45+
SETTING to arrayOf(Colors.SETTING),
46+
KEYWORD_CALL to arrayOf(Colors.KEYWORD_CALL),
47+
CONTROL_FLOW to arrayOf(Colors.CONTROL_FLOW),
48+
VARIABLE to arrayOf(Colors.VARIABLE),
49+
OPERATOR to arrayOf(Colors.OPERATOR),
50+
ARGUMENT to arrayOf(Colors.ARGUMENT),
51+
CONTINUATION to arrayOf(Colors.CONTINUATION),
5252
)
5353

5454
val PLAIN_SYNTAX_HIGHLIGHTER: PlainSyntaxHighlighter = PlainSyntaxHighlighter()
5555
}
5656

57-
private val myLexer = RobotTextMateHighlightingLexer()
57+
private val myLexer = RobotCodeLexer()
5858

5959
override fun getHighlightingLexer(): Lexer {
6060
return myLexer

intellij-client/src/main/kotlin/dev/robotcode/robotcode4ij/highlighting/RobotCodeSyntaxHighlighterFactory.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ import com.intellij.openapi.vfs.VirtualFile
77

88
class RobotCodeSyntaxHighlighterFactory : SyntaxHighlighterFactory() {
99
override fun getSyntaxHighlighter(project: Project?, virtualFile: VirtualFile?): SyntaxHighlighter {
10-
return RobotCodeHighlighter()
10+
return RobotCodeSyntaxHighlighter()
1111
}
1212
}

0 commit comments

Comments
 (0)