Skip to content

Commit

Permalink
#811 | Inject Polyglot Query Language into ImpEx string literals
Browse files Browse the repository at this point in the history
  • Loading branch information
mlytvyn authored Nov 29, 2023
1 parent 41da8f0 commit f1a13b9
Show file tree
Hide file tree
Showing 11 changed files with 245 additions and 89 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

### `Polyglot Query` enhancements
- Added possibility to preview preformatted Polyglot Queries and copy them to Clipboard [#810](https://github.com/epam/sap-commerce-intellij-idea-plugin/pull/810)
- Inject Polyglot Query Language into `ImpEx` string literals [#811](https://github.com/epam/sap-commerce-intellij-idea-plugin/pull/811)

### `Cockpit NG` enhancements
- Added Spring bean reference resolution for `wz:custom`:`handler` [#809](https://github.com/epam/sap-commerce-intellij-idea-plugin/pull/809)
Expand Down
2 changes: 2 additions & 0 deletions resources/META-INF/lang/polyglot-query-dependencies.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
<annotator language="Polyglot Query" implementationClass="com.intellij.idea.plugin.hybris.polyglotQuery.lang.annotation.PolyglotQueryAnnotator"/>
<editorNotificationProvider id="pgqEditorNotificationProvider" implementation="com.intellij.idea.plugin.hybris.polyglotQuery.ui.PolyglotQueryEditorNotificationProvider"/>

<languageInjector implementation="com.intellij.idea.plugin.hybris.polyglotQuery.injection.PolyglotQueryInjector"/>

<projectConfigurable id="hybris.project.pgq.settings" parentId="hybris.project.settings" nonDefaultProject="true" dynamic="true"
bundle="i18n.HybrisBundle" key="hybris.settings.project.pgq.title"
provider="com.intellij.idea.plugin.hybris.polyglotQuery.settings.PolyglotQuerySettingsConfigurableProvider"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@
package com.intellij.idea.plugin.hybris.flexibleSearch.injection.impl

import com.intellij.idea.plugin.hybris.common.HybrisConstants
import com.intellij.idea.plugin.hybris.flexibleSearch.FlexibleSearchLanguage
import com.intellij.idea.plugin.hybris.flexibleSearch.FxSUtils
import com.intellij.idea.plugin.hybris.flexibleSearch.injection.FlexibleSearchInjectorProvider
import com.intellij.idea.plugin.hybris.impex.ImpexLanguage
import com.intellij.idea.plugin.hybris.impex.psi.ImpexHeaderLine
import com.intellij.idea.plugin.hybris.impex.psi.ImpexString
import com.intellij.idea.plugin.hybris.impex.psi.ImpexValueGroup
import com.intellij.idea.plugin.hybris.impex.psi.ImpexValueLine
import com.intellij.idea.plugin.hybris.lang.injection.impl.AbstractLanguageInjectorProvider
import com.intellij.idea.plugin.hybris.settings.HybrisProjectSettingsComponent
import com.intellij.lang.Language
import com.intellij.openapi.application.ApplicationManager
Expand All @@ -37,7 +38,7 @@ import com.intellij.psi.util.parentOfType
import java.util.*

@Service
class FlexibleSearchToImpexInjectorProvider : FlexibleSearchInjectorProvider() {
class FlexibleSearchToImpexInjectorProvider : AbstractLanguageInjectorProvider(FlexibleSearchLanguage.INSTANCE) {

override val language: Language = ImpexLanguage.getInstance()

Expand Down Expand Up @@ -110,6 +111,6 @@ class FlexibleSearchToImpexInjectorProvider : FlexibleSearchInjectorProvider() {
}

companion object {
val instance: FlexibleSearchInjectorProvider? = ApplicationManager.getApplication().getService(FlexibleSearchToImpexInjectorProvider::class.java)
val instance: FlexibleSearchToImpexInjectorProvider? = ApplicationManager.getApplication().getService(FlexibleSearchToImpexInjectorProvider::class.java)
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* This file is part of "SAP Commerce Developers Toolset" plugin for Intellij IDEA.
* Copyright (C) 2019 EPAM Systems <[email protected]>
* Copyright (C) 2019-2023 EPAM Systems <[email protected]> and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
Expand All @@ -18,58 +18,18 @@

package com.intellij.idea.plugin.hybris.flexibleSearch.injection.impl

import com.intellij.idea.plugin.hybris.common.HybrisConstants
import com.intellij.idea.plugin.hybris.flexibleSearch.FlexibleSearchLanguage
import com.intellij.idea.plugin.hybris.flexibleSearch.FxSUtils
import com.intellij.idea.plugin.hybris.flexibleSearch.injection.FlexibleSearchInjectorProvider
import com.intellij.lang.Language
import com.intellij.lang.java.JavaLanguage
import com.intellij.idea.plugin.hybris.lang.injection.impl.AbstractLanguageToJavaInjectorProvider
import com.intellij.openapi.application.ApplicationManager
import com.intellij.psi.*
import com.intellij.psi.PsiLiteralExpression

class FlexibleSearchToJavaInjectorProvider : FlexibleSearchInjectorProvider() {
class FlexibleSearchToJavaInjectorProvider : AbstractLanguageToJavaInjectorProvider(FlexibleSearchLanguage.INSTANCE) {

override val language: Language = JavaLanguage.INSTANCE

override fun tryInject(
host: PsiLanguageInjectionHost,
injectionPlacesRegistrar: InjectedLanguagePlaces
) {
val hostParent = host.parent ?: return

if (host is PsiLiteralExpression && hostParent !is PsiPolyadicExpression) {
inject(injectionPlacesRegistrar, host) { FxSUtils.computeExpression(host) }
} else if (hostParent is PsiExpressionList) {
val psiMethod = hostParent.parent as? PsiMethodCallExpression ?: return
inject(psiMethod, injectionPlacesRegistrar, host)
}
}

private fun inject(
injectionPlacesRegistrar: InjectedLanguagePlaces,
host: PsiLiteralExpression,
expressionProvider: () -> String
) {
val expression = expressionProvider.invoke()
if (!FxSUtils.isFlexibleSearchQuery(expression)) return

val quoteLength = if (host.isTextBlock) 3 else 1
registerInjectionPlace(injectionPlacesRegistrar, host, quoteLength)
}

private fun inject(
psi: PsiMethodCallExpression,
injectionPlacesRegistrar: InjectedLanguagePlaces,
host: PsiLanguageInjectionHost
) {
val method = psi.resolveMethod() ?: return
if (HybrisConstants.METHOD_SEARCH_NAME != method.name) return
val containingClass = method.containingClass ?: return
if (HybrisConstants.CLASS_FLEXIBLE_SEARCH_SERVICE_NAME != containingClass.name) return

registerInjectionPlace(injectionPlacesRegistrar, host)
}
override fun computeExpression(host: PsiLiteralExpression) = FxSUtils.computeExpression(host)
override fun canProcess(expression: String) = FxSUtils.isFlexibleSearchQuery(expression)

companion object {
val instance: FlexibleSearchInjectorProvider? = ApplicationManager.getApplication().getService(FlexibleSearchToJavaInjectorProvider::class.java)
val instance: FlexibleSearchToJavaInjectorProvider? = ApplicationManager.getApplication().getService(FlexibleSearchToJavaInjectorProvider::class.java)
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* This file is part of "SAP Commerce Developers Toolset" plugin for Intellij IDEA.
* Copyright (C) 2019 EPAM Systems <[email protected]>
* Copyright (C) 2019-2023 EPAM Systems <[email protected]> and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
Expand All @@ -18,42 +18,17 @@

package com.intellij.idea.plugin.hybris.flexibleSearch.injection.impl

import com.intellij.idea.plugin.hybris.flexibleSearch.FlexibleSearchLanguage
import com.intellij.idea.plugin.hybris.flexibleSearch.FxSUtils
import com.intellij.idea.plugin.hybris.flexibleSearch.injection.FlexibleSearchInjectorProvider
import com.intellij.lang.Language
import com.intellij.idea.plugin.hybris.lang.injection.impl.AbstractLanguageToKotlinInjectorProvider
import com.intellij.openapi.application.ApplicationManager
import com.intellij.psi.InjectedLanguagePlaces
import com.intellij.psi.PsiLanguageInjectionHost
import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.psi.KtBinaryExpression
import org.jetbrains.kotlin.psi.KtReferenceExpression
import org.jetbrains.kotlin.psi.KtStringTemplateExpression

class FlexibleSearchToKotlinInjectorProvider : FlexibleSearchInjectorProvider() {
class FlexibleSearchToKotlinInjectorProvider : AbstractLanguageToKotlinInjectorProvider(FlexibleSearchLanguage.INSTANCE) {

override val language: Language = KotlinLanguage.INSTANCE

override fun tryInject(
host: PsiLanguageInjectionHost,
injectionPlacesRegistrar: InjectedLanguagePlaces
) {
if (host !is KtStringTemplateExpression) return
if (host.parent is KtBinaryExpression) return
if (PsiTreeUtil.findChildOfType(host, KtReferenceExpression::class.java) != null) return

val expression = host.text
if (!FxSUtils.isFlexibleSearchQuery(expression)) return

if (expression.startsWith("\"\"\"")) {
registerInjectionPlace(injectionPlacesRegistrar, host, 3)
} else {
registerInjectionPlace(injectionPlacesRegistrar, host, 1)
}
}
override fun canProcess(expression: String) = FxSUtils.isFlexibleSearchQuery(expression)

companion object {
val instance: FlexibleSearchInjectorProvider? = ApplicationManager.getApplication().getService(FlexibleSearchToKotlinInjectorProvider::class.java)
val instance: FlexibleSearchToKotlinInjectorProvider? = ApplicationManager.getApplication().getService(FlexibleSearchToKotlinInjectorProvider::class.java)
}

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* This file is part of "SAP Commerce Developers Toolset" plugin for Intellij IDEA.
* Copyright (C) 2019 EPAM Systems <[email protected]>
* Copyright (C) 2019-2023 EPAM Systems <[email protected]> and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
Expand All @@ -16,9 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package com.intellij.idea.plugin.hybris.flexibleSearch.injection
package com.intellij.idea.plugin.hybris.lang.injection.impl

import com.intellij.idea.plugin.hybris.flexibleSearch.FlexibleSearchLanguage
import com.intellij.lang.Language
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.progress.ProcessCanceledException
Expand All @@ -27,7 +26,7 @@ import com.intellij.psi.InjectedLanguagePlaces
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiLanguageInjectionHost

abstract class FlexibleSearchInjectorProvider {
abstract class AbstractLanguageInjectorProvider(private val injectLanguage: Language) {

protected abstract val language: Language

Expand All @@ -54,7 +53,7 @@ abstract class FlexibleSearchInjectorProvider {
) {
try {
injectionPlacesRegistrar.addPlace(
FlexibleSearchLanguage.INSTANCE,
injectLanguage,
textRange,
prefix,
suffix
Expand All @@ -67,6 +66,6 @@ abstract class FlexibleSearchInjectorProvider {
}

companion object {
private val LOG = Logger.getInstance(FlexibleSearchInjectorProvider::class.java)
private val LOG = Logger.getInstance(AbstractLanguageInjectorProvider::class.java)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* This file is part of "SAP Commerce Developers Toolset" plugin for Intellij IDEA.
* Copyright (C) 2019-2023 EPAM Systems <[email protected]> and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package com.intellij.idea.plugin.hybris.lang.injection.impl

import com.intellij.idea.plugin.hybris.common.HybrisConstants
import com.intellij.lang.Language
import com.intellij.lang.java.JavaLanguage
import com.intellij.psi.*

abstract class AbstractLanguageToJavaInjectorProvider(injectLanguage: Language) : AbstractLanguageInjectorProvider(injectLanguage) {

override val language: Language = JavaLanguage.INSTANCE

abstract fun computeExpression(host: PsiLiteralExpression): String
abstract fun canProcess(expression: String): Boolean

override fun tryInject(
host: PsiLanguageInjectionHost,
injectionPlacesRegistrar: InjectedLanguagePlaces
) {
val hostParent = host.parent ?: return

if (host is PsiLiteralExpression && hostParent !is PsiPolyadicExpression) {
inject(injectionPlacesRegistrar, host) { computeExpression(host) }
} else if (hostParent is PsiExpressionList) {
val psiMethod = hostParent.parent as? PsiMethodCallExpression ?: return
inject(psiMethod, injectionPlacesRegistrar, host)
}
}


private fun inject(
injectionPlacesRegistrar: InjectedLanguagePlaces,
host: PsiLiteralExpression,
expressionProvider: () -> String
) {
val expression = expressionProvider.invoke()
if (!canProcess(expression)) return

val quoteLength = if (host.isTextBlock) 3 else 1
registerInjectionPlace(injectionPlacesRegistrar, host, quoteLength)
}

private fun inject(
psi: PsiMethodCallExpression,
injectionPlacesRegistrar: InjectedLanguagePlaces,
host: PsiLanguageInjectionHost
) {
val method = psi.resolveMethod() ?: return
if (HybrisConstants.METHOD_SEARCH_NAME != method.name) return
val containingClass = method.containingClass ?: return
if (HybrisConstants.CLASS_FLEXIBLE_SEARCH_SERVICE_NAME != containingClass.name) return

registerInjectionPlace(injectionPlacesRegistrar, host)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* This file is part of "SAP Commerce Developers Toolset" plugin for Intellij IDEA.
* Copyright (C) 2019-2023 EPAM Systems <[email protected]> and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package com.intellij.idea.plugin.hybris.lang.injection.impl

import com.intellij.lang.Language
import com.intellij.psi.InjectedLanguagePlaces
import com.intellij.psi.PsiLanguageInjectionHost
import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.psi.KtBinaryExpression
import org.jetbrains.kotlin.psi.KtReferenceExpression
import org.jetbrains.kotlin.psi.KtStringTemplateExpression

abstract class AbstractLanguageToKotlinInjectorProvider(injectLanguage: Language) : AbstractLanguageInjectorProvider(injectLanguage) {

override val language: Language = KotlinLanguage.INSTANCE

abstract fun canProcess(expression: String): Boolean

override fun tryInject(
host: PsiLanguageInjectionHost,
injectionPlacesRegistrar: InjectedLanguagePlaces
) {
if (host !is KtStringTemplateExpression) return
if (host.parent is KtBinaryExpression) return
if (PsiTreeUtil.findChildOfType(host, KtReferenceExpression::class.java) != null) return

val expression = host.text
if (!canProcess(expression)) return

if (expression.startsWith("\"\"\"")) {
registerInjectionPlace(injectionPlacesRegistrar, host, 3)
} else {
registerInjectionPlace(injectionPlacesRegistrar, host, 1)
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ object PolyglotQueryUtils {
fun isPolyglotQuery(expression: String) = expression.replace("\n", "")
.replace("\"\"\"", "")
.trim()
.startsWith("GET", true)
.startsWith("GET ", true)
&& expression.contains(keywordsRegex)
&& expression.contains(bracesRegex)

Expand Down
Loading

0 comments on commit f1a13b9

Please sign in to comment.