mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-97264 IntelliLang support for "Path to File" language
This commit is contained in:
@@ -24,11 +24,12 @@
|
||||
*/
|
||||
package com.intellij.util;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.util.CachedValue;
|
||||
import com.intellij.psi.util.CachedValueProvider;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public abstract class CachedValueImpl<T> extends CachedValueBase<T> implements CachedValue<T> {
|
||||
public class CachedValueImpl<T> extends CachedValueBase<T> implements CachedValue<T> {
|
||||
private final CachedValueProvider<T> myProvider;
|
||||
|
||||
public CachedValueImpl(@NotNull CachedValueProvider<T> provider) {
|
||||
@@ -50,4 +51,9 @@ public abstract class CachedValueImpl<T> extends CachedValueBase<T> implements C
|
||||
public T getValue() {
|
||||
return getValueWithLock(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFromMyProject(Project project) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,5 +26,11 @@ public interface PairProcessor<S, T> {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
PairProcessor FALSE = new PairProcessor() {
|
||||
@Override
|
||||
public boolean process(Object o, Object o1) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
boolean process(S s, T t);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="testFramework-java" />
|
||||
<orderEntry type="module" module-name="IntelliLang" />
|
||||
<orderEntry type="module" module-name="IntelliLang-xml" />
|
||||
<orderEntry type="module" module-name="xml" />
|
||||
<orderEntry type="module" module-name="IntelliLang-java" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package org.intellij.plugins.intelliLang;
|
||||
|
||||
import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
|
||||
import org.intellij.plugins.intelliLang.inject.InjectLanguageAction;
|
||||
import org.intellij.plugins.intelliLang.inject.UnInjectLanguageAction;
|
||||
import org.intellij.plugins.intelliLang.references.FileReferenceInjector;
|
||||
|
||||
/**
|
||||
* @author Dmitry Avdeev
|
||||
* Date: 02.08.13
|
||||
*/
|
||||
public class ReferenceInjectionTest extends LightPlatformCodeInsightFixtureTestCase {
|
||||
|
||||
public void testInjectReference() throws Exception {
|
||||
|
||||
myFixture.configureByText("foo.xml", "<foo xmlns=\"http://foo.bar\" \n" +
|
||||
" xxx=\"ba<caret>r\"/>");
|
||||
assertNull(myFixture.getReferenceAtCaretPosition());
|
||||
|
||||
InjectLanguageAction.invokeImpl(getProject(), myFixture.getEditor(), myFixture.getFile(), new FileReferenceInjector());
|
||||
assertNotNull(myFixture.getReferenceAtCaretPosition());
|
||||
|
||||
UnInjectLanguageAction.invokeImpl(getProject(), myFixture.getEditor(), myFixture.getFile());
|
||||
assertNull(myFixture.getReferenceAtCaretPosition());
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,9 @@
|
||||
<extensionPoints>
|
||||
<extensionPoint name="languageSupport" interface="org.intellij.plugins.intelliLang.inject.LanguageInjectionSupport"/>
|
||||
<extensionPoint name="injectionConfig" beanClass="org.intellij.plugins.intelliLang.inject.LanguageInjectionConfigBean"/>
|
||||
<extensionPoint name="referenceInjector" interface="org.intellij.plugins.intelliLang.references.ReferenceInjector"/>
|
||||
</extensionPoints>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<errorHandler implementation="com.intellij.diagnostic.ITNReporter" />
|
||||
<intentionAction>
|
||||
@@ -48,5 +50,12 @@
|
||||
serviceImplementation="org.intellij.plugins.intelliLang.Configuration$Prj"/>
|
||||
<compileServer.plugin classpath="intellilang-jps-plugin.jar"/>
|
||||
|
||||
<psi.referenceContributor implementation="org.intellij.plugins.intelliLang.references.InjectedReferencesContributor"/>
|
||||
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="org.intellij.intelliLang">
|
||||
<referenceInjector implementation="org.intellij.plugins.intelliLang.references.FileReferenceInjector"/>
|
||||
</extensions>
|
||||
|
||||
</idea-plugin>
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.intellij.plugins.intelliLang;
|
||||
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.command.UndoConfirmationPolicy;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.command.undo.GlobalUndoableAction;
|
||||
@@ -30,11 +31,14 @@ import com.intellij.psi.PsiCompiledElement;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiLanguageInjectionHost;
|
||||
import com.intellij.psi.util.CachedValue;
|
||||
import com.intellij.psi.util.CachedValueProvider;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.util.*;
|
||||
import com.intellij.util.containers.ConcurrentFactoryMap;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.Convertor;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import gnu.trove.THashMap;
|
||||
import gnu.trove.THashSet;
|
||||
import org.intellij.plugins.intelliLang.inject.InjectorUtils;
|
||||
@@ -65,6 +69,12 @@ import java.util.*;
|
||||
public class Configuration implements PersistentStateComponent<Element>, ModificationTracker {
|
||||
|
||||
static final Logger LOG = Logger.getInstance(Configuration.class.getName());
|
||||
private static final Condition<BaseInjection> LANGUAGE_INJECTION_CONDITION = new Condition<BaseInjection>() {
|
||||
@Override
|
||||
public boolean value(BaseInjection o) {
|
||||
return Language.findLanguageByID(o.getInjectedLanguageId()) != null;
|
||||
}
|
||||
};
|
||||
|
||||
@State(
|
||||
name = Configuration.COMPONENT_NAME,
|
||||
@@ -126,6 +136,13 @@ public class Configuration implements PersistentStateComponent<Element>, Modific
|
||||
return myParentConfiguration.getDefaultInjections();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<BaseInjection> getAllInjections() {
|
||||
Collection<BaseInjection> injections = super.getAllInjections();
|
||||
injections.addAll(myParentConfiguration.getAllInjections());
|
||||
return injections;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<BaseInjection> getInjections(final String injectorId) {
|
||||
@@ -149,8 +166,8 @@ public class Configuration implements PersistentStateComponent<Element>, Modific
|
||||
List<? extends BaseInjection> originalInjections,
|
||||
boolean forceLevel) {
|
||||
if (!forceLevel && !originalInjections.isEmpty()) {
|
||||
if (myParentConfiguration.replaceInjections(Collections.<BaseInjection>emptyList(), originalInjections, forceLevel)) {
|
||||
myParentConfiguration.replaceInjections(newInjections, Collections.<BaseInjection>emptyList(), forceLevel);
|
||||
if (myParentConfiguration.replaceInjections(Collections.<BaseInjection>emptyList(), originalInjections, false)) {
|
||||
myParentConfiguration.replaceInjections(newInjections, Collections.<BaseInjection>emptyList(), false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -190,6 +207,26 @@ public class Configuration implements PersistentStateComponent<Element>, Modific
|
||||
}
|
||||
};
|
||||
|
||||
protected Collection<BaseInjection> getAllInjections() {
|
||||
ArrayList<BaseInjection> injections = new ArrayList<BaseInjection>();
|
||||
for (List<BaseInjection> list : myInjections.values()) {
|
||||
injections.addAll(list);
|
||||
}
|
||||
return injections;
|
||||
}
|
||||
|
||||
private CachedValue<MultiMap<String, BaseInjection>> myInjectionsById = new CachedValueImpl<MultiMap<String, BaseInjection>>(new CachedValueProvider<MultiMap<String, BaseInjection>>() {
|
||||
@Nullable
|
||||
@Override
|
||||
public Result<MultiMap<String, BaseInjection>> compute() {
|
||||
MultiMap<String, BaseInjection> map = new MultiMap<String, BaseInjection>();
|
||||
for (BaseInjection injection : getAllInjections()) {
|
||||
map.putValue(injection.getInjectedLanguageId(), injection);
|
||||
}
|
||||
return Result.create(map, Configuration.this);
|
||||
}
|
||||
});
|
||||
|
||||
private volatile long myModificationCount;
|
||||
|
||||
public Configuration() {
|
||||
@@ -206,7 +243,7 @@ public class Configuration implements PersistentStateComponent<Element>, Modific
|
||||
supports.put(support.getId(), support);
|
||||
}
|
||||
loadStateOld(element, supports.get(LanguageInjectionSupport.XML_SUPPORT_ID), supports.get(LanguageInjectionSupport.JAVA_SUPPORT_ID));
|
||||
for (Element child : (List<Element>)element.getChildren("injection")){
|
||||
for (Element child : element.getChildren("injection")){
|
||||
final String key = child.getAttributeValue("injector-id");
|
||||
final LanguageInjectionSupport support = supports.get(key);
|
||||
final BaseInjection injection = support == null ? new BaseInjection(key) : support.createInjection(child);
|
||||
@@ -350,6 +387,10 @@ public class Configuration implements PersistentStateComponent<Element>, Modific
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public Collection<BaseInjection> getInjectionsByLanguageId(String languageId) {
|
||||
return myInjectionsById.getValue().get(languageId);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Configuration load(final InputStream is) throws IOException, JDOMException {
|
||||
try {
|
||||
@@ -438,7 +479,7 @@ public class Configuration implements PersistentStateComponent<Element>, Modific
|
||||
}
|
||||
}
|
||||
|
||||
public void configurationModified() {
|
||||
private void configurationModified() {
|
||||
myModificationCount ++;
|
||||
}
|
||||
|
||||
@@ -492,6 +533,9 @@ public class Configuration implements PersistentStateComponent<Element>, Modific
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param injectorId see {@link org.intellij.plugins.intelliLang.inject.LanguageInjectionSupport#getId()}
|
||||
*/
|
||||
@NotNull
|
||||
public List<BaseInjection> getInjections(final String injectorId) {
|
||||
return Collections.unmodifiableList(myInjections.get(injectorId));
|
||||
@@ -506,7 +550,10 @@ public class Configuration implements PersistentStateComponent<Element>, Modific
|
||||
public boolean process(final List<? extends BaseInjection> add,
|
||||
final List<? extends BaseInjection> remove) {
|
||||
replaceInjectionsWithUndoInner(add, remove);
|
||||
FileContentUtil.reparseOpenedFiles();
|
||||
if (ContainerUtil.find(add, LANGUAGE_INJECTION_CONDITION) != null || ContainerUtil.find(remove,
|
||||
LANGUAGE_INJECTION_CONDITION) != null) {
|
||||
FileContentUtil.reparseOpenedFiles();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
-5
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.intellij.plugins.intelliLang.inject;
|
||||
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.fileTypes.FileTypeManager;
|
||||
@@ -49,10 +48,6 @@ public abstract class AbstractLanguageInjectionSupport extends LanguageInjection
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean addInjectionInPlace(final Language language, final PsiLanguageInjectionHost psiElement) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean removeInjectionInPlace(final PsiLanguageInjectionHost psiElement) {
|
||||
return false;
|
||||
}
|
||||
|
||||
+30
-27
@@ -17,12 +17,9 @@ package org.intellij.plugins.intelliLang.inject;
|
||||
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.injected.editor.EditorWindow;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.lang.LanguageUtil;
|
||||
import com.intellij.lang.injection.InjectedLanguageManager;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.options.Configurable;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.PopupChooserBuilder;
|
||||
@@ -32,6 +29,8 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiLanguageInjectionHost;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.impl.PsiModificationTrackerImpl;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.ui.ListCellRendererWrapper;
|
||||
import com.intellij.ui.components.JBList;
|
||||
@@ -39,14 +38,13 @@ import com.intellij.util.FileContentUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.ui.EmptyIcon;
|
||||
import org.intellij.plugins.intelliLang.Configuration;
|
||||
import org.intellij.plugins.intelliLang.references.Injectable;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -80,12 +78,13 @@ public class InjectLanguageAction implements IntentionAction {
|
||||
}
|
||||
|
||||
public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException {
|
||||
doChooseLanguageToInject(editor, new Processor<Language>() {
|
||||
public boolean process(final Language language) {
|
||||
if (project.isDisposed()) return false;
|
||||
doChooseLanguageToInject(editor, new Processor<Injectable>() {
|
||||
public boolean process(final Injectable injectable) {
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
invokeImpl(project, editor, file, language);
|
||||
if (!project.isDisposed()) {
|
||||
invokeImpl(project, editor, file, injectable);
|
||||
}
|
||||
}
|
||||
});
|
||||
return false;
|
||||
@@ -93,46 +92,50 @@ public class InjectLanguageAction implements IntentionAction {
|
||||
});
|
||||
}
|
||||
|
||||
private static void invokeImpl(Project project, Editor editor, PsiFile file, Language language) {
|
||||
public static void invokeImpl(Project project, Editor editor, PsiFile file, Injectable injectable) {
|
||||
final PsiLanguageInjectionHost host = findInjectionHost(editor, file);
|
||||
if (host == null) return;
|
||||
if (defaultFunctionalityWorked(host, language)) return;
|
||||
if (defaultFunctionalityWorked(host, injectable.getId())) return;
|
||||
|
||||
try {
|
||||
for (LanguageInjectionSupport support : InjectorUtils.getActiveInjectionSupports()) {
|
||||
if (support.addInjectionInPlace(language, host)) return;
|
||||
if (support.addInjectionInPlace(injectable, host)) {
|
||||
((PsiModificationTrackerImpl)PsiManager.getInstance(project).getModificationTracker()).incCounter();
|
||||
return;
|
||||
}
|
||||
}
|
||||
TemporaryPlacesRegistry.getInstance(project).getLanguageInjectionSupport().addInjectionInPlace(language, host);
|
||||
TemporaryPlacesRegistry.getInstance(project).getLanguageInjectionSupport().addInjectionInPlace(injectable, host);
|
||||
}
|
||||
finally {
|
||||
FileContentUtil.reparseFiles(project, Collections.<VirtualFile>emptyList(), true);
|
||||
if (injectable.getLanguage() != null) { // no need for reference injection
|
||||
FileContentUtil.reparseFiles(project, Collections.<VirtualFile>emptyList(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean defaultFunctionalityWorked(final PsiLanguageInjectionHost host, final Language language) {
|
||||
return Configuration.getProjectInstance(host.getProject()).setHostInjectionEnabled(host, Collections.singleton(language.getID()), true);
|
||||
private static boolean defaultFunctionalityWorked(final PsiLanguageInjectionHost host, String id) {
|
||||
return Configuration.getProjectInstance(host.getProject()).setHostInjectionEnabled(host, Collections.singleton(id), true);
|
||||
}
|
||||
|
||||
private static boolean doChooseLanguageToInject(Editor editor, final Processor<Language> onChosen) {
|
||||
final Language[] languages = InjectedLanguage.getAvailableLanguages();
|
||||
Arrays.sort(languages, LanguageUtil.LANGUAGE_COMPARATOR);
|
||||
private static boolean doChooseLanguageToInject(Editor editor, final Processor<Injectable> onChosen) {
|
||||
final List<Injectable> injectables = Injectable.getAllInjectables();
|
||||
|
||||
final JList list = new JBList(languages);
|
||||
list.setCellRenderer(new ListCellRendererWrapper<Language>() {
|
||||
final JList list = new JBList(injectables);
|
||||
list.setCellRenderer(new ListCellRendererWrapper<Injectable>() {
|
||||
@Override
|
||||
public void customize(JList list, Language language, int index, boolean selected, boolean hasFocus) {
|
||||
final FileType ft = language.getAssociatedFileType();
|
||||
setIcon(ft != null ? ft.getIcon() : EmptyIcon.ICON_16);
|
||||
setText(language.getDisplayName() + (ft != null ? " (" + ft.getDescription() + ")" : ""));
|
||||
public void customize(JList list, Injectable language, int index, boolean selected, boolean hasFocus) {
|
||||
setIcon(language.getIcon());
|
||||
setText(language.getDisplayName());
|
||||
}
|
||||
});
|
||||
new PopupChooserBuilder(list).setItemChoosenCallback(new Runnable() {
|
||||
public void run() {
|
||||
onChosen.process((Language)list.getSelectedValue());
|
||||
onChosen.process((Injectable)list.getSelectedValue());
|
||||
}
|
||||
}).setFilteringEnabled(new Function<Object, String>() {
|
||||
@Override
|
||||
public String fun(Object language) {
|
||||
return ((Language)language).getDisplayName();
|
||||
return ((Injectable)language).getDisplayName();
|
||||
}
|
||||
})
|
||||
.createPopup().showInBestPositionFor(editor);
|
||||
|
||||
+21
-1
@@ -28,6 +28,7 @@ import com.intellij.ui.SimpleColoredText;
|
||||
import com.intellij.util.Consumer;
|
||||
import org.intellij.plugins.intelliLang.Configuration;
|
||||
import org.intellij.plugins.intelliLang.inject.config.BaseInjection;
|
||||
import org.intellij.plugins.intelliLang.references.Injectable;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -56,7 +57,26 @@ public abstract class LanguageInjectionSupport {
|
||||
|
||||
public abstract boolean useDefaultInjector(final PsiElement host);
|
||||
|
||||
public abstract boolean addInjectionInPlace(final Language language, final PsiLanguageInjectionHost psiElement);
|
||||
public boolean addInjectionInPlace(final Language language, final PsiLanguageInjectionHost psiElement) {
|
||||
return addInjectionInPlace(language.getID(), psiElement);
|
||||
}
|
||||
|
||||
public boolean addInjectionInPlace(final String id, final PsiLanguageInjectionHost psiElement) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public final boolean addInjectionInPlace(final Injectable injectable, final PsiLanguageInjectionHost psiElement) {
|
||||
if (injectable.getLanguage() == null) {
|
||||
boolean result = addInjectionInPlace(injectable.getId(), psiElement);
|
||||
if (result) {
|
||||
psiElement.putUserData(INJECTOR_SUPPORT, this);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
return addInjectionInPlace(injectable.getLanguage(), psiElement);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract boolean removeInjectionInPlace(final PsiLanguageInjectionHost psiElement);
|
||||
|
||||
|
||||
+25
-10
@@ -25,14 +25,14 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiLanguageInjectionHost;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiModificationTrackerImpl;
|
||||
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
|
||||
import com.intellij.util.FileContentUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import gnu.trove.THashSet;
|
||||
import org.intellij.plugins.intelliLang.Configuration;
|
||||
import org.intellij.plugins.intelliLang.references.InjectedReferencesContributor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collections;
|
||||
@@ -55,10 +55,13 @@ public class UnInjectLanguageAction implements IntentionAction, LowPriorityActio
|
||||
|
||||
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
|
||||
final int offset = editor.getCaretModel().getOffset();
|
||||
final PsiFile psiFile = InjectedLanguageUtil.findInjectedPsiNoCommit(file, offset);
|
||||
if (psiFile == null) return false;
|
||||
final LanguageInjectionSupport support = psiFile.getUserData(LanguageInjectionSupport.INJECTOR_SUPPORT);
|
||||
return support != null;
|
||||
PsiElement element = InjectedLanguageUtil.findInjectedPsiNoCommit(file, offset);
|
||||
if (element == null) {
|
||||
PsiReference reference = file.findReferenceAt(offset);
|
||||
if (reference == null) return false;
|
||||
return reference.getElement().getUserData(InjectedReferencesContributor.INJECTED_REFERENCE) != null;
|
||||
}
|
||||
return element.getUserData(LanguageInjectionSupport.INJECTOR_SUPPORT) != null;
|
||||
}
|
||||
|
||||
public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException {
|
||||
@@ -69,9 +72,21 @@ public class UnInjectLanguageAction implements IntentionAction, LowPriorityActio
|
||||
});
|
||||
}
|
||||
|
||||
private static void invokeImpl(Project project, Editor editor, PsiFile file) {
|
||||
final PsiFile psiFile = InjectedLanguageUtil.findInjectedPsiNoCommit(file, editor.getCaretModel().getOffset());
|
||||
if (psiFile == null) return;
|
||||
public static void invokeImpl(Project project, Editor editor, PsiFile file) {
|
||||
int offset = editor.getCaretModel().getOffset();
|
||||
final PsiFile psiFile = InjectedLanguageUtil.findInjectedPsiNoCommit(file, offset);
|
||||
if (psiFile == null) {
|
||||
PsiReference reference = file.findReferenceAt(offset);
|
||||
if (reference != null) {
|
||||
PsiElement element = reference.getElement();
|
||||
LanguageInjectionSupport support = element.getUserData(LanguageInjectionSupport.INJECTOR_SUPPORT);
|
||||
if (support != null && element instanceof PsiLanguageInjectionHost) {
|
||||
support.removeInjectionInPlace((PsiLanguageInjectionHost)element);
|
||||
((PsiModificationTrackerImpl)PsiManager.getInstance(project).getModificationTracker()).incCounter();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
final PsiLanguageInjectionHost host = InjectedLanguageManager.getInstance(project).getInjectionHost(psiFile);
|
||||
if (host == null) return;
|
||||
final LanguageInjectionSupport support = psiFile.getUserData(LanguageInjectionSupport.INJECTOR_SUPPORT);
|
||||
|
||||
+6
-2
@@ -65,7 +65,7 @@ public class BaseInjection implements Injection, PersistentStateComponent<Elemen
|
||||
private Pattern myCompiledValuePattern;
|
||||
private boolean mySingleFile;
|
||||
|
||||
public BaseInjection(final String id) {
|
||||
public BaseInjection(@NotNull final String id) {
|
||||
mySupportId = id;
|
||||
}
|
||||
|
||||
@@ -244,7 +244,7 @@ public class BaseInjection implements Injection, PersistentStateComponent<Elemen
|
||||
setValuePattern(element.getChildText("value-pattern"));
|
||||
mySingleFile = element.getChild("single-file") != null;
|
||||
readExternalImpl(element);
|
||||
final List<Element> placeElements = (List<Element>)element.getChildren("place");
|
||||
final List<Element> placeElements = element.getChildren("place");
|
||||
myPlaces = InjectionPlace.ARRAY_FACTORY.create(placeElements.size());
|
||||
for (int i = 0, placeElementsSize = placeElements.size(); i < placeElementsSize; i++) {
|
||||
Element placeElement = placeElements.get(i);
|
||||
@@ -384,6 +384,10 @@ public class BaseInjection implements Injection, PersistentStateComponent<Elemen
|
||||
}
|
||||
}
|
||||
|
||||
public boolean acceptForReference(PsiElement element) {
|
||||
return acceptsPsiElement(element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getInjectedLanguageId()+ "->" +getDisplayName();
|
||||
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.intellij.plugins.intelliLang.references;
|
||||
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceSet;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author Dmitry Avdeev
|
||||
* Date: 01.08.13
|
||||
*/
|
||||
public class FileReferenceInjector extends ReferenceInjector {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getId() {
|
||||
return "file-reference";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return "File Reference";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiReference[] getReferences(@NotNull PsiElement element, @NotNull ProcessingContext context, @NotNull TextRange range) {
|
||||
String text = range.substring(element.getText());
|
||||
return new FileReferenceSet(text, element, range.getStartOffset(), null, true).getAllReferences();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.intellij.plugins.intelliLang.references;
|
||||
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.util.ui.EmptyIcon;
|
||||
import org.intellij.plugins.intelliLang.inject.InjectedLanguage;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Dmitry Avdeev
|
||||
* Date: 01.08.13
|
||||
*/
|
||||
public abstract class Injectable implements Comparable<Injectable> {
|
||||
|
||||
/** Unique ID among injected language and reference injector IDs */
|
||||
@NotNull
|
||||
public abstract String getId();
|
||||
|
||||
@NotNull
|
||||
public abstract String getDisplayName();
|
||||
|
||||
@NotNull
|
||||
public Icon getIcon() {
|
||||
return EmptyIcon.ICON_16;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NotNull Injectable o) {
|
||||
return getDisplayName().compareTo(o.getDisplayName());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null for reference injections
|
||||
*/
|
||||
@Nullable
|
||||
public abstract Language getLanguage();
|
||||
|
||||
public static List<Injectable> getAllInjectables() {
|
||||
Language[] languages = InjectedLanguage.getAvailableLanguages();
|
||||
List<Injectable> list = new ArrayList<Injectable>();
|
||||
for (Language language : languages) {
|
||||
list.add(fromLanguage(language));
|
||||
}
|
||||
list.addAll(Arrays.asList(ReferenceInjector.EXTENSION_POINT_NAME.getExtensions()));
|
||||
Collections.sort(list);
|
||||
return list;
|
||||
}
|
||||
|
||||
public static Injectable fromLanguage(final Language language) {
|
||||
return new Injectable() {
|
||||
@NotNull
|
||||
@Override
|
||||
public String getId() {
|
||||
return language.getID();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
final FileType ft = language.getAssociatedFileType();
|
||||
return language.getDisplayName() + (ft != null ? " (" + ft.getDescription() + ")" : "");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Icon getIcon() {
|
||||
final FileType ft = language.getAssociatedFileType();
|
||||
//noinspection ConstantConditions
|
||||
return ft != null && ft.getIcon() != null ? ft.getIcon() : EmptyIcon.ICON_16;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Language getLanguage() {
|
||||
return language;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.intellij.plugins.intelliLang.references;
|
||||
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.patterns.PlatformPatterns;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import org.intellij.plugins.intelliLang.Configuration;
|
||||
import org.intellij.plugins.intelliLang.inject.config.BaseInjection;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Dmitry Avdeev
|
||||
* Date: 01.08.13
|
||||
*/
|
||||
public class InjectedReferencesContributor extends PsiReferenceContributor {
|
||||
|
||||
public static final Key<ReferenceInjector> INJECTED_REFERENCE = Key.create("injected reference");
|
||||
|
||||
@Override
|
||||
public void registerReferenceProviders(PsiReferenceRegistrar registrar) {
|
||||
registrar.registerReferenceProvider(PlatformPatterns.psiElement(), new PsiReferenceProvider() {
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) {
|
||||
element.putUserData(INJECTED_REFERENCE, null);
|
||||
ReferenceInjector[] extensions = ReferenceInjector.EXTENSION_POINT_NAME.getExtensions();
|
||||
PsiReference[] references = new PsiReference[0];
|
||||
Configuration configuration = Configuration.getProjectInstance(element.getProject());
|
||||
for (ReferenceInjector extension : extensions) {
|
||||
Collection<BaseInjection> injections = configuration.getInjectionsByLanguageId(extension.getId());
|
||||
for (BaseInjection injection : injections) {
|
||||
if (injection.acceptForReference(element)) {
|
||||
element.putUserData(INJECTED_REFERENCE, extension);
|
||||
List<TextRange> area = injection.getInjectedArea(element);
|
||||
for (TextRange range : area) {
|
||||
references = ArrayUtil.mergeArrays(references, extension.getReferences(element, context, range));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return references;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.intellij.plugins.intelliLang.references;
|
||||
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author Dmitry Avdeev
|
||||
* Date: 01.08.13
|
||||
*/
|
||||
public abstract class ReferenceInjector extends Injectable {
|
||||
|
||||
final static ExtensionPointName<ReferenceInjector> EXTENSION_POINT_NAME = ExtensionPointName.create("org.intellij.intelliLang.referenceInjector");
|
||||
|
||||
@Override
|
||||
public final Language getLanguage() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public abstract PsiReference[] getReferences(@NotNull PsiElement element, @NotNull final ProcessingContext context, @NotNull TextRange range);
|
||||
}
|
||||
+9
-4
@@ -17,7 +17,6 @@ package org.intellij.plugins.intelliLang.inject.config;
|
||||
|
||||
import com.intellij.openapi.util.JDOMExternalizer;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.patterns.compiler.PatternCompiler;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.xml.XmlAttribute;
|
||||
import com.intellij.psi.xml.XmlAttributeValue;
|
||||
@@ -26,9 +25,6 @@ import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.intellij.plugins.intelliLang.inject.InjectorUtils.appendStringPattern;
|
||||
|
||||
public class XmlAttributeInjection extends AbstractTagInjection {
|
||||
@@ -151,4 +147,13 @@ public class XmlAttributeInjection extends AbstractTagInjection {
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptForReference(PsiElement element) {
|
||||
if (element instanceof XmlAttributeValue) {
|
||||
PsiElement parent = element.getParent();
|
||||
return parent instanceof XmlAttribute && acceptsPsiElement(parent);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-4
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.intellij.plugins.intelliLang.inject.xml;
|
||||
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.options.Configurable;
|
||||
@@ -89,13 +88,13 @@ public class XmlLanguageInjectionSupport extends AbstractLanguageInjectionSuppor
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean addInjectionInPlace(final Language language, final PsiLanguageInjectionHost psiElement) {
|
||||
public boolean addInjectionInPlace(final String id, final PsiLanguageInjectionHost psiElement) {
|
||||
if (!isMine(psiElement)) return false;
|
||||
if (psiElement instanceof XmlAttributeValue) {
|
||||
return doInjectInAttributeValue((XmlAttributeValue)psiElement, language.getID());
|
||||
return doInjectInAttributeValue((XmlAttributeValue)psiElement, id);
|
||||
}
|
||||
else if (psiElement instanceof XmlText) {
|
||||
return doInjectInXmlText((XmlText)psiElement, language.getID());
|
||||
return doInjectInXmlText((XmlText)psiElement, id);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user