mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
intelliLang: replaceInjectionsWithUndo filters compiled elements + tests added (IDEA-CR-33537)
This commit is contained in:
+57
@@ -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<PsiLanguageInjectionHost>
|
||||
private lateinit var pointer: SmartPsiElementPointer<PsiLanguageInjectionHost>
|
||||
|
||||
override fun showFix(editor: Editor,
|
||||
range: TextRange,
|
||||
pointer: SmartPsiElementPointer<PsiLanguageInjectionHost>,
|
||||
text: String,
|
||||
data: Processor<PsiLanguageInjectionHost>) {
|
||||
this.processor = data
|
||||
this.pointer = pointer
|
||||
}
|
||||
|
||||
fun process() = process(pointer.element ?: throw IllegalStateException("element was invalidated"))
|
||||
|
||||
fun process(injectionHost: PsiLanguageInjectionHost) = processor.process(injectionHost)
|
||||
|
||||
}
|
||||
+103
@@ -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\": <caret> 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<PsiMethodCallExpression>()!!.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\": <caret> 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\": <caret> 1 }");
|
||||
}
|
||||
}
|
||||
""")
|
||||
|
||||
assertInjectedLangAtCaret("JSON")
|
||||
|
||||
UnInjectLanguageAction.invokeImpl(project, topLevelEditor, topLevelFile)
|
||||
|
||||
TestCase.assertNull(currentPrintlnInjection())
|
||||
assertInjectedLangAtCaret(null)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+1
-37
@@ -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", "<foo xmlns=\"http://foo.bar\" \n" +
|
||||
" xxx=\"ba<caret>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<PsiLanguageInjectionHost> processor;
|
||||
|
||||
@Override
|
||||
public void showFix(@NotNull Editor editor,
|
||||
@NotNull TextRange range,
|
||||
@NotNull SmartPsiElementPointer<PsiLanguageInjectionHost> pointer,
|
||||
@NotNull String text,
|
||||
@NotNull Processor<PsiLanguageInjectionHost> data) {
|
||||
this.processor = data;
|
||||
}
|
||||
|
||||
public void process(PsiLanguageInjectionHost injectionHost) {
|
||||
if (processor == null) throw new IllegalStateException("fix was not set");
|
||||
processor.process(injectionHost);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+13
-3
@@ -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) {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user