diff --git a/plugins/IntelliLang/IntelliLang-tests/test/org/intellij/plugins/intelliLang/AbstractLanguageInjectionTestCase.kt b/plugins/IntelliLang/IntelliLang-tests/test/org/intellij/plugins/intelliLang/AbstractLanguageInjectionTestCase.kt new file mode 100644 index 000000000000..bedae95ef1cb --- /dev/null +++ b/plugins/IntelliLang/IntelliLang-tests/test/org/intellij/plugins/intelliLang/AbstractLanguageInjectionTestCase.kt @@ -0,0 +1,57 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.intellij.plugins.intelliLang + +import com.intellij.lang.injection.InjectedLanguageManager +import com.intellij.openapi.editor.Editor +import com.intellij.openapi.fileEditor.FileEditorManager +import com.intellij.openapi.fileEditor.TextEditor +import com.intellij.openapi.util.TextRange +import com.intellij.psi.PsiFile +import com.intellij.psi.PsiLanguageInjectionHost +import com.intellij.psi.SmartPsiElementPointer +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase +import com.intellij.util.Processor +import junit.framework.TestCase +import org.intellij.plugins.intelliLang.inject.InjectLanguageAction + +abstract class AbstractLanguageInjectionTestCase : LightCodeInsightFixtureTestCase() { + + fun assertInjectedLangAtCaret(lang: String?) { + val injectedElement = injectedLanguageManager.findInjectedElementAt(topLevelFile, topLevelCaretPosition) + if (lang != null) { + TestCase.assertNotNull("injection of '$lang' expected", injectedElement) + TestCase.assertEquals(lang, injectedElement!!.language.id) + } + else { + TestCase.assertNull(injectedElement) + } + } + + val topLevelEditor get() = (FileEditorManager.getInstance(project).getSelectedEditor(topLevelFile.virtualFile) as TextEditor).editor + + val topLevelCaretPosition get() = topLevelEditor.caretModel.offset + + val injectedLanguageManager: InjectedLanguageManager get() = InjectedLanguageManager.getInstance(project) + + val topLevelFile: PsiFile get() = file.let { injectedLanguageManager.getTopLevelFile(it) } + +} + +class StoringFixPresenter : InjectLanguageAction.FixPresenter { + private lateinit var processor: Processor + private lateinit var pointer: SmartPsiElementPointer + + override fun showFix(editor: Editor, + range: TextRange, + pointer: SmartPsiElementPointer, + text: String, + data: Processor) { + this.processor = data + this.pointer = pointer + } + + fun process() = process(pointer.element ?: throw IllegalStateException("element was invalidated")) + + fun process(injectionHost: PsiLanguageInjectionHost) = processor.process(injectionHost) + +} \ No newline at end of file diff --git a/plugins/IntelliLang/IntelliLang-tests/test/org/intellij/plugins/intelliLang/JavaLanguageInjectionSupportTest.kt b/plugins/IntelliLang/IntelliLang-tests/test/org/intellij/plugins/intelliLang/JavaLanguageInjectionSupportTest.kt new file mode 100644 index 000000000000..b4db2ccd4770 --- /dev/null +++ b/plugins/IntelliLang/IntelliLang-tests/test/org/intellij/plugins/intelliLang/JavaLanguageInjectionSupportTest.kt @@ -0,0 +1,103 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.intellij.plugins.intelliLang + +import com.intellij.lang.Language +import com.intellij.psi.PsiMethodCallExpression +import com.intellij.psi.injection.Injectable +import com.intellij.psi.util.parentOfType +import junit.framework.TestCase +import org.intellij.plugins.intelliLang.inject.InjectLanguageAction +import org.intellij.plugins.intelliLang.inject.InjectorUtils +import org.intellij.plugins.intelliLang.inject.UnInjectLanguageAction +import org.intellij.plugins.intelliLang.inject.config.BaseInjection +import org.intellij.plugins.intelliLang.inject.java.JavaLanguageInjectionSupport + +class JavaLanguageInjectionSupportTest : AbstractLanguageInjectionTestCase() { + + fun testAnnotationInjection() { + myFixture.configureByText("Foo.java", """ + class Foo { + void bar() { + baz("{\"a\": 1 }"); + } + + void baz(String json){} + } + """) + + StoringFixPresenter().apply { + InjectLanguageAction.invokeImpl(project, + myFixture.editor, + myFixture.file, + Injectable.fromLanguage(Language.findLanguageByID("JSON")), + this + ) + }.process() + + assertInjectedLangAtCaret("JSON") + + myFixture.checkResult(""" + |import org.intellij.lang.annotations.Language; + | + |class Foo { + | void bar() { + | baz("{\"a\": 1 }"); + | } + | + | void baz(@Language("JSON") String json){} + | } + | """.trimMargin()) + + UnInjectLanguageAction.invokeImpl(project, topLevelEditor, topLevelFile) + + assertInjectedLangAtCaret(null) + } + + + fun testConfigInjection() { + + fun currentPrintlnInjection(): BaseInjection? { + val psiMethod = topLevelFile.findElementAt(topLevelCaretPosition)!!.parentOfType()!!.resolveMethod()!! + val injection = JavaLanguageInjectionSupport.makeParameterInjection(psiMethod, 0, "JSON"); + return InjectorUtils.getEditableInstance(project).findExistingInjection(injection) + } + + + myFixture.configureByText("Foo.java", """ + class Foo { + void bar() { + System.out.println("{\"a\": 1 }"); + } + } + """) + + TestCase.assertNull(currentPrintlnInjection()) + + InjectLanguageAction.invokeImpl(project, + myFixture.editor, + myFixture.file, + Injectable.fromLanguage(Language.findLanguageByID("JSON"))) + + assertInjectedLangAtCaret("JSON") + + TestCase.assertNotNull(currentPrintlnInjection()) + + myFixture.configureByText("Another.java", """ + class Another { + void bar() { + System.out.println("{\"a\": 1 }"); + } + } + """) + + assertInjectedLangAtCaret("JSON") + + UnInjectLanguageAction.invokeImpl(project, topLevelEditor, topLevelFile) + + TestCase.assertNull(currentPrintlnInjection()) + assertInjectedLangAtCaret(null) + } + + +} + diff --git a/plugins/IntelliLang/IntelliLang-tests/test/org/intellij/plugins/intelliLang/ReferenceInjectionTest.java b/plugins/IntelliLang/IntelliLang-tests/test/org/intellij/plugins/intelliLang/ReferenceInjectionTest.java index 3dccf80d2dbc..900525c2877e 100644 --- a/plugins/IntelliLang/IntelliLang-tests/test/org/intellij/plugins/intelliLang/ReferenceInjectionTest.java +++ b/plugins/IntelliLang/IntelliLang-tests/test/org/intellij/plugins/intelliLang/ReferenceInjectionTest.java @@ -1,20 +1,15 @@ package org.intellij.plugins.intelliLang; import com.intellij.lang.Language; -import com.intellij.lang.injection.InjectedLanguageManager; import com.intellij.openapi.command.undo.UndoManager; -import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileEditor.TextEditor; import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.TestDialog; -import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReference; import com.intellij.psi.injection.Injectable; import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; -import com.intellij.util.Processor; import com.intellij.util.ui.UIUtil; import org.intellij.plugins.intelliLang.inject.InjectLanguageAction; import org.intellij.plugins.intelliLang.inject.UnInjectLanguageAction; @@ -22,12 +17,11 @@ import org.intellij.plugins.intelliLang.references.FileReferenceInjector; import org.intellij.plugins.intelliLang.references.InjectedReferencesContributor; import org.intellij.plugins.intelliLang.references.InjectedReferencesInspection; import org.jdom.Element; -import org.jetbrains.annotations.NotNull; /** * @author Dmitry Avdeev */ -public class ReferenceInjectionTest extends LightCodeInsightFixtureTestCase { +public class ReferenceInjectionTest extends AbstractLanguageInjectionTestCase { public void testInjectReference() { myFixture.configureByText("foo.xml", "r\"/>"); @@ -217,18 +211,6 @@ public class ReferenceInjectionTest extends LightCodeInsightFixtureTestCase { assertNull(getInjectedReferences()); } - private void assertInjectedLangAtCaret(String lang) { - InjectedLanguageManager injectedLanguageManager = InjectedLanguageManager.getInstance(getProject()); - PsiElement injectedElement = injectedLanguageManager.findInjectedElementAt(getFile(), getEditor().getCaretModel().getOffset()); - if (lang != null) { - assertNotNull("injection of '" + lang + "' expected", injectedElement); - assertEquals(lang, injectedElement.getLanguage().getID()); - } - else { - assertNull(injectedElement); - } - } - public void testTernary() { myFixture.configureByText("Foo.java", "class Foo {\n" + " void bar() {\n" + @@ -267,22 +249,4 @@ public class ReferenceInjectionTest extends LightCodeInsightFixtureTestCase { myFixture.disableInspections(new InjectedReferencesInspection()); super.tearDown(); } - - private static class StoringFixPresenter implements InjectLanguageAction.FixPresenter { - private Processor processor; - - @Override - public void showFix(@NotNull Editor editor, - @NotNull TextRange range, - @NotNull SmartPsiElementPointer pointer, - @NotNull String text, - @NotNull Processor data) { - this.processor = data; - } - - public void process(PsiLanguageInjectionHost injectionHost) { - if (processor == null) throw new IllegalStateException("fix was not set"); - processor.process(injectionHost); - } - } } diff --git a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/JavaLanguageInjectionSupport.java b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/JavaLanguageInjectionSupport.java index d3defc27be1c..1de5bf84c797 100644 --- a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/JavaLanguageInjectionSupport.java +++ b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/JavaLanguageInjectionSupport.java @@ -294,10 +294,21 @@ public class JavaLanguageInjectionSupport extends AbstractLanguageInjectionSuppo assert containingClass != null; final PsiModifierList classModifiers = containingClass.getModifierList(); if (classModifiers != null && (classModifiers.hasModifierProperty(PsiModifier.PRIVATE) || classModifiers.hasModifierProperty(PsiModifier.PACKAGE_LOCAL))) { - return doAddLanguageAnnotation(project, parameterIndex >= 0? psiMethod.getParameterList().getParameters()[parameterIndex] : psiMethod, + return doAddLanguageAnnotation(project, parameterIndex >= 0 ? psiMethod.getParameterList().getParameters()[parameterIndex] : psiMethod, host, languageId); } + final MethodParameterInjection injection = makeParameterInjection(psiMethod, parameterIndex, languageId); + doEditInjection(project, injection, psiMethod); + return true; + } + + @NotNull + public static MethodParameterInjection makeParameterInjection(@NotNull PsiMethod psiMethod, + int parameterIndex, + @NotNull String languageId) { + final PsiClass containingClass = psiMethod.getContainingClass(); + assert containingClass != null; final String className = containingClass.getQualifiedName(); assert className != null; final MethodParameterInjection injection = new MethodParameterInjection(); @@ -312,8 +323,7 @@ public class JavaLanguageInjectionSupport extends AbstractLanguageInjectionSuppo } injection.setMethodInfos(Collections.singletonList(info)); injection.generatePlaces(); - doEditInjection(project, injection, psiMethod); - return true; + return injection; } static int findParameterIndex(final PsiElement target, final PsiExpressionList parent) { diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/Configuration.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/Configuration.java index 2cc3effaf684..fa6cafef965f 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/Configuration.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/Configuration.java @@ -548,18 +548,13 @@ public class Configuration extends SimpleModificationTracker implements Persiste PsiFile[] psiFiles = StreamEx.ofNullable(hostFile) .append(psiElementsToRemove .stream() - .filter(e -> !(e instanceof PsiCompiledElement)) .map(e -> e.getContainingFile())) + .filter(e -> !(e instanceof PsiCompiledElement)) .toArray(PsiFile.class); DocumentReference[] documentReferences = ContainerUtil .map2Array(psiFiles, DocumentReference.class, file -> DocumentReferenceManager.getInstance().create(file.getVirtualFile())); - if (documentReferences.length == 0) { - LOG.error("documentReferences array is empty, undo-redo for language injection will not be registered for any document/file," + - " please pass a proper `hostFile`, current hostFile = '" + hostFile + "'"); //refer IDEA-109366 - } - final UndoableAction action = new GlobalUndoableAction(documentReferences) { @Override public void undo() {