Search in sources :

Example 1 with MultiHostInjector

use of com.intellij.lang.injection.MultiHostInjector in project intellij-community by JetBrains.

the class InjectedLanguageManagerImpl method checkInjectorsAreDisposed.

@TestOnly
public static void checkInjectorsAreDisposed(@NotNull Project project) {
    InjectedLanguageManagerImpl cachedManager = (InjectedLanguageManagerImpl) project.getUserData(INSTANCE_CACHE);
    if (cachedManager == null) {
        return;
    }
    try {
        ClassMapCachingNulls<MultiHostInjector> cached = cachedManager.cachedInjectors;
        if (cached == null)
            return;
        for (Map.Entry<Class, MultiHostInjector[]> entry : cached.getBackingMap().entrySet()) {
            Class key = entry.getKey();
            if (cachedManager.myInjectorsClone.isEmpty())
                return;
            MultiHostInjector[] oldInjectors = cachedManager.myInjectorsClone.get(key);
            for (MultiHostInjector injector : entry.getValue()) {
                if (ArrayUtil.indexOf(oldInjectors, injector) == -1) {
                    throw new AssertionError("Injector was not disposed: " + key + " -> " + injector);
                }
            }
        }
    } finally {
        cachedManager.myInjectorsClone.clear();
    }
}
Also used : MultiHostInjector(com.intellij.lang.injection.MultiHostInjector) TestOnly(org.jetbrains.annotations.TestOnly)

Example 2 with MultiHostInjector

use of com.intellij.lang.injection.MultiHostInjector in project intellij-community by JetBrains.

the class InjectedLanguageManagerImpl method getInjectorMap.

private ClassMapCachingNulls<MultiHostInjector> getInjectorMap() {
    ClassMapCachingNulls<MultiHostInjector> cached = cachedInjectors;
    if (cached != null) {
        return cached;
    }
    Map<Class, MultiHostInjector[]> injectors = ContainerUtil.newHashMap();
    List<MultiHostInjector> allInjectors = ContainerUtil.newArrayList();
    allInjectors.addAll(myManualInjectors);
    Collections.addAll(allInjectors, MultiHostInjector.MULTIHOST_INJECTOR_EP_NAME.getExtensions(myProject));
    if (LanguageInjector.EXTENSION_POINT_NAME.getExtensions().length > 0) {
        allInjectors.add(PsiManagerRegisteredInjectorsAdapter.INSTANCE);
    }
    for (MultiHostInjector injector : allInjectors) {
        for (Class<? extends PsiElement> place : injector.elementsToInjectIn()) {
            LOG.assertTrue(place != null, injector);
            MultiHostInjector[] existing = injectors.get(place);
            injectors.put(place, existing == null ? new MultiHostInjector[] { injector } : ArrayUtil.append(existing, injector));
        }
    }
    ClassMapCachingNulls<MultiHostInjector> result = new ClassMapCachingNulls<>(injectors, new MultiHostInjector[0], allInjectors);
    cachedInjectors = result;
    return result;
}
Also used : MultiHostInjector(com.intellij.lang.injection.MultiHostInjector)

Example 3 with MultiHostInjector

use of com.intellij.lang.injection.MultiHostInjector in project intellij-community by JetBrains.

the class MyTestInjector method injectVariousStuffEverywhere.

private static void injectVariousStuffEverywhere(Disposable parent, final PsiManager psiManager) {
    final Language ql = Language.findLanguageByID("JPAQL");
    final Language js = Language.findLanguageByID("JavaScript 1.6");
    final Language html = Language.findLanguageByID("HTML");
    if (ql == null || js == null)
        return;
    final Language ecma4 = Language.findLanguageByID("ECMA Script Level 4");
    final MultiHostInjector myMultiHostInjector = new MultiHostInjector() {

        @Override
        public void getLanguagesToInject(@NotNull MultiHostRegistrar registrar, @NotNull PsiElement context) {
            XmlAttributeValue value = (XmlAttributeValue) context;
            PsiElement parent = value.getParent();
            if (parent instanceof XmlAttribute) {
                @NonNls String attrName = ((XmlAttribute) parent).getLocalName();
                if ("jsInBraces".equals(attrName)) {
                    registrar.startInjecting(js);
                    String text = value.getText();
                    int index = 0;
                    while (text.indexOf('{', index) != -1) {
                        int lbrace = text.indexOf('{', index);
                        int rbrace = text.indexOf('}', index);
                        registrar.addPlace("", "", (PsiLanguageInjectionHost) value, new TextRange(lbrace + 1, rbrace));
                        index = rbrace + 1;
                    }
                    registrar.doneInjecting();
                }
            }
        }

        @Override
        @NotNull
        public List<? extends Class<? extends PsiElement>> elementsToInjectIn() {
            return Arrays.asList(XmlAttributeValue.class);
        }
    };
    InjectedLanguageManager.getInstance(psiManager.getProject()).registerMultiHostInjector(myMultiHostInjector);
    Disposer.register(parent, new Disposable() {

        @Override
        public void dispose() {
            boolean b = InjectedLanguageManager.getInstance(psiManager.getProject()).unregisterMultiHostInjector(myMultiHostInjector);
            assert b;
        }
    });
    final LanguageInjector myInjector = new LanguageInjector() {

        @Override
        public void getLanguagesToInject(@NotNull PsiLanguageInjectionHost host, @NotNull InjectedLanguagePlaces placesToInject) {
            if (host instanceof XmlAttributeValue) {
                XmlAttributeValue value = (XmlAttributeValue) host;
                PsiElement parent = value.getParent();
                if (parent instanceof XmlAttribute) {
                    @NonNls String attrName = ((XmlAttribute) parent).getLocalName();
                    if ("ql".equals(attrName)) {
                        inject(host, placesToInject, ql);
                        return;
                    }
                    if ("js".equals(attrName)) {
                        inject(host, placesToInject, js);
                        return;
                    }
                    if ("jsprefix".equals(attrName)) {
                        inject(host, placesToInject, js, "function foo(doc, window){", "}");
                        return;
                    }
                }
            }
            if (host instanceof XmlText) {
                // inject to xml tags named 'ql'
                final XmlText xmlText = (XmlText) host;
                XmlTag tag = xmlText.getParentTag();
                if (tag == null)
                    return;
                if ("ql".equals(tag.getLocalName())) {
                    inject(host, placesToInject, ql);
                    return;
                }
                if ("js".equals(tag.getLocalName())) {
                    inject(host, placesToInject, js);
                    return;
                }
                if ("htmlInject".equals(tag.getLocalName())) {
                    inject(host, placesToInject, html);
                    return;
                }
                if (ecma4 != null && "ecma4".equals(tag.getLocalName())) {
                    inject(host, placesToInject, ecma4);
                    return;
                }
                if ("jsprefix".equals(tag.getLocalName())) {
                    inject(host, placesToInject, js, "function foo(doc, window){", "}");
                    return;
                }
                if ("jsInHash".equals(tag.getLocalName())) {
                    String text = xmlText.getText();
                    if (text.contains("#")) {
                        int start = text.indexOf('#');
                        int end = text.lastIndexOf('#');
                        if (start != end && start != -1) {
                            placesToInject.addPlace(js, new TextRange(start + 1, end), null, null);
                            return;
                        }
                    }
                }
            }
            if (host instanceof PsiComment && ((PsiComment) host).getTokenType() == JavaTokenType.C_STYLE_COMMENT) {
                /* {{{
           *   js code
           *   js code
           * }}}
           */
                String text = host.getText();
                String prefix = "/*\n * {{{\n";
                String suffix = " }}}\n */";
                if (text.startsWith(prefix) && text.endsWith(suffix)) {
                    String s = StringUtil.trimEnd(StringUtil.trimStart(text, prefix), suffix);
                    int off = 0;
                    while (!s.isEmpty()) {
                        String t = s.trim();
                        if (t.startsWith("*"))
                            t = t.substring(1).trim();
                        int i = s.length() - t.length();
                        off += i;
                        int endOfLine = t.indexOf('\n');
                        if (endOfLine == -1)
                            endOfLine = t.length();
                        placesToInject.addPlace(js, TextRange.from(prefix.length() + off, endOfLine), "", "\n");
                        off += endOfLine;
                        s = s.substring(i + endOfLine);
                    }
                    return;
                }
            }
            if (host instanceof PsiCommentImpl) {
                String text = host.getText();
                if (text.startsWith("/*--{") && text.endsWith("}--*/")) {
                    TextRange textRange = new TextRange(4, text.length() - 4);
                    if (!(host.getParent() instanceof PsiMethod))
                        return;
                    PsiMethod method = (PsiMethod) host.getParent();
                    if (!method.hasModifierProperty(PsiModifier.NATIVE) || !method.hasModifierProperty(PsiModifier.PUBLIC))
                        return;
                    String paramList = "";
                    for (PsiParameter parameter : method.getParameterList().getParameters()) {
                        if (!paramList.isEmpty())
                            paramList += ",";
                        paramList += parameter.getName();
                    }
                    @NonNls String header = "function " + method.getName() + "(" + paramList + ") {";
                    Language gwt = Language.findLanguageByID("GWT JavaScript");
                    placesToInject.addPlace(gwt, textRange, header, "}");
                    return;
                }
                PsiElement parent = host.getParent();
                if (parent instanceof PsiMethod && ((PsiMethod) parent).getName().equals("xml")) {
                    placesToInject.addPlace(StdLanguages.XML, new TextRange(2, host.getTextLength() - 2), null, null);
                    return;
                }
            }
            // inject to all string literal initializers of variables named 'ql'
            if (host instanceof PsiLiteralExpression && ((PsiLiteralExpression) host).getValue() instanceof String) {
                PsiVariable variable = PsiTreeUtil.getParentOfType(host, PsiVariable.class);
                if (variable == null)
                    return;
                if (host.getParent() instanceof PsiPolyadicExpression)
                    return;
                if ("ql".equals(variable.getName())) {
                    placesToInject.addPlace(ql, textRangeToInject(host), null, null);
                }
                if ("xml".equals(variable.getName())) {
                    placesToInject.addPlace(StdLanguages.XML, textRangeToInject(host), null, null);
                }
                if ("js".equals(variable.getName())) {
                    // with prefix/suffix
                    placesToInject.addPlace(js, textRangeToInject(host), "function foo(doc,window) {", "}");
                }
                if ("lang".equals(variable.getName())) {
                    // various lang depending on field "languageID" content
                    PsiClass aClass = PsiTreeUtil.getParentOfType(variable, PsiClass.class);
                    aClass = aClass.findInnerClassByName("Language", false);
                    String text = aClass.getInitializers()[0].getBody().getFirstBodyElement().getNextSibling().getText().substring(2);
                    Language language = Language.findLanguageByID(text);
                    if (language != null) {
                        placesToInject.addPlace(language, textRangeToInject(host), "", "");
                    }
                }
            }
        }
    };
    final ExtensionPoint<LanguageInjector> extensionPoint = Extensions.getRootArea().getExtensionPoint(LanguageInjector.EXTENSION_POINT_NAME);
    extensionPoint.registerExtension(myInjector);
    Disposer.register(parent, new Disposable() {

        @Override
        public void dispose() {
            extensionPoint.unregisterExtension(myInjector);
        }
    });
}
Also used : MultiHostInjector(com.intellij.lang.injection.MultiHostInjector) NotNull(org.jetbrains.annotations.NotNull) Language(com.intellij.lang.Language) JavaLanguage(com.intellij.lang.java.JavaLanguage) PsiCommentImpl(com.intellij.psi.impl.source.tree.PsiCommentImpl) Disposable(com.intellij.openapi.Disposable) NonNls(org.jetbrains.annotations.NonNls) ProperTextRange(com.intellij.openapi.util.ProperTextRange) TextRange(com.intellij.openapi.util.TextRange) ExtensionPoint(com.intellij.openapi.extensions.ExtensionPoint) MultiHostRegistrar(com.intellij.lang.injection.MultiHostRegistrar)

Aggregations

MultiHostInjector (com.intellij.lang.injection.MultiHostInjector)3 Language (com.intellij.lang.Language)1 MultiHostRegistrar (com.intellij.lang.injection.MultiHostRegistrar)1 JavaLanguage (com.intellij.lang.java.JavaLanguage)1 Disposable (com.intellij.openapi.Disposable)1 ExtensionPoint (com.intellij.openapi.extensions.ExtensionPoint)1 ProperTextRange (com.intellij.openapi.util.ProperTextRange)1 TextRange (com.intellij.openapi.util.TextRange)1 PsiCommentImpl (com.intellij.psi.impl.source.tree.PsiCommentImpl)1 NonNls (org.jetbrains.annotations.NonNls)1 NotNull (org.jetbrains.annotations.NotNull)1 TestOnly (org.jetbrains.annotations.TestOnly)1