From 1da42e6777e015978e552115e721ba5d16e046ae Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Wed, 27 Jul 2016 16:28:30 +0300 Subject: [PATCH] use completion contributor instead of completion data: rnc --- xml/relaxng/src/META-INF/relaxng-plugin.xml | 2 +- .../compact/RncCompletionContributor.java | 108 ++++++++++++++ .../relaxNG/compact/RncCompletionData.java | 136 ------------------ 3 files changed, 109 insertions(+), 137 deletions(-) create mode 100644 xml/relaxng/src/org/intellij/plugins/relaxNG/compact/RncCompletionContributor.java delete mode 100644 xml/relaxng/src/org/intellij/plugins/relaxNG/compact/RncCompletionData.java diff --git a/xml/relaxng/src/META-INF/relaxng-plugin.xml b/xml/relaxng/src/META-INF/relaxng-plugin.xml index caa6a0a850a30..c24f00c8454e4 100644 --- a/xml/relaxng/src/META-INF/relaxng-plugin.xml +++ b/xml/relaxng/src/META-INF/relaxng-plugin.xml @@ -5,7 +5,7 @@ - + diff --git a/xml/relaxng/src/org/intellij/plugins/relaxNG/compact/RncCompletionContributor.java b/xml/relaxng/src/org/intellij/plugins/relaxNG/compact/RncCompletionContributor.java new file mode 100644 index 0000000000000..e8f13f3962177 --- /dev/null +++ b/xml/relaxng/src/org/intellij/plugins/relaxNG/compact/RncCompletionContributor.java @@ -0,0 +1,108 @@ +/* + * Copyright 2000-2016 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.relaxNG.compact; + +import com.intellij.codeInsight.TailType; +import com.intellij.codeInsight.completion.*; +import com.intellij.codeInsight.lookup.LookupElementBuilder; +import com.intellij.codeInsight.lookup.TailTypeDecorator; +import com.intellij.patterns.ElementPattern; +import com.intellij.patterns.PsiElementPattern; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiWhiteSpace; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.ArrayUtil; +import com.intellij.util.ProcessingContext; +import org.intellij.plugins.relaxNG.compact.psi.RncDecl; +import org.intellij.plugins.relaxNG.compact.psi.RncDefine; +import org.intellij.plugins.relaxNG.compact.psi.RncGrammar; +import org.intellij.plugins.relaxNG.compact.psi.util.EscapeUtil; +import org.jetbrains.annotations.NotNull; + +import static com.intellij.patterns.PlatformPatterns.psiElement; +import static com.intellij.patterns.StandardPatterns.and; +import static com.intellij.patterns.StandardPatterns.not; + +/** + * @author Dennis.Ushakov + */ +public class RncCompletionContributor extends CompletionContributor { + private static final ElementPattern TOP_LEVEL = + not(psiElement().inside(psiElement(RncGrammar.class) + .inside(true, psiElement(RncGrammar.class)))); + + private static final PsiElementPattern DECL_PATTERN = + psiElement().inside(psiElement(RncDecl.class)); + + private static final PsiElementPattern DEFAULT_PATTERN = + DECL_PATTERN.afterLeaf(psiElement().withText("default")); + + private static final ElementPattern DEFINE_PATTERN = + and(psiElement().withParent(RncDefine.class), psiElement().afterLeafSkipping(psiElement(PsiWhiteSpace.class), psiElement().withText("="))); + + private static final String[] DECL_KEYWORDS = new String[]{ "default", "namespace", "datatypes" }; + private static final String[] GRAMMAR_CONTENT_KEYWORDS = new String[]{ "include", "div", "start" }; + private static final String[] PATTERN_KEYWORDS = new String[]{ "attribute", "element", "grammar", + "notAllowed", "text", "empty", "external", "parent", "list", "mixed" }; + + + public RncCompletionContributor() { + CompletionProvider provider = new CompletionProvider() { + @Override + protected void addCompletions(@NotNull CompletionParameters parameters, + ProcessingContext context, + @NotNull CompletionResultSet result) { + String[] keywords = getKeywords(parameters.getPosition()); + for (String keyword : keywords) { + result.addElement(TailTypeDecorator.withTail(LookupElementBuilder.create(keyword).bold(), TailType.SPACE)); + } + } + }; + extend(null, psiElement().afterLeaf(psiElement(RncTokenTypes.KEYWORD_DEFAULT)), provider); + extend(null, psiElement().andNot(psiElement().inside(psiElement(RncTokenTypes.LITERAL))). + andNot(psiElement().afterLeaf(psiElement().withElementType(RncTokenTypes.KEYWORDS))), provider); + } + + + private static String[] getKeywords(PsiElement context) { + final PsiElement next = PsiTreeUtil.skipSiblingsForward(context, PsiWhiteSpace.class); + if (next != null && EscapeUtil.unescapeText(next).equals("=")) { + return new String[]{ "start" }; + } + + if (DEFAULT_PATTERN.accepts(context)) { + return new String[]{ "namespace" }; + } else if (DECL_PATTERN.accepts(context)) { + return ArrayUtil.EMPTY_STRING_ARRAY; + } else if (context.getParent() instanceof RncDefine && context.getParent().getFirstChild() == context) { + if (DEFINE_PATTERN.accepts(context)) { + return ArrayUtil.EMPTY_STRING_ARRAY; + } + if (TOP_LEVEL.accepts(context)) { + if (!afterPattern(context)) { + return ArrayUtil.mergeArrays(DECL_KEYWORDS, ArrayUtil.mergeArrays(GRAMMAR_CONTENT_KEYWORDS, PATTERN_KEYWORDS)); + } + } + return GRAMMAR_CONTENT_KEYWORDS; + } + return PATTERN_KEYWORDS; + } + + private static boolean afterPattern(PsiElement context) { + // TODO: recognize all patterns + return PsiTreeUtil.getPrevSiblingOfType(context.getParent(), RncDefine.class) != null; + } +} diff --git a/xml/relaxng/src/org/intellij/plugins/relaxNG/compact/RncCompletionData.java b/xml/relaxng/src/org/intellij/plugins/relaxNG/compact/RncCompletionData.java deleted file mode 100644 index dd2fbdb9d10c9..0000000000000 --- a/xml/relaxng/src/org/intellij/plugins/relaxNG/compact/RncCompletionData.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright 2007 Sascha Weinreuter - * - * 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.relaxNG.compact; - -import com.intellij.codeInsight.TailType; -import com.intellij.codeInsight.completion.CompletionContext; -import com.intellij.codeInsight.completion.CompletionData; -import com.intellij.codeInsight.completion.CompletionVariant; -import com.intellij.codeInsight.lookup.LookupElement; -import com.intellij.codeInsight.lookup.LookupElementBuilder; -import com.intellij.codeInsight.lookup.TailTypeDecorator; -import com.intellij.patterns.ElementPattern; -import com.intellij.patterns.PsiElementPattern; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiWhiteSpace; -import com.intellij.psi.filters.AndFilter; -import com.intellij.psi.filters.ContextGetter; -import com.intellij.psi.filters.ElementFilter; -import com.intellij.psi.filters.position.PatternFilter; -import com.intellij.psi.impl.source.tree.LeafPsiElement; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.util.ArrayUtil; -import com.intellij.util.Function; -import com.intellij.util.containers.ContainerUtil; -import org.intellij.plugins.relaxNG.compact.psi.RncDecl; -import org.intellij.plugins.relaxNG.compact.psi.RncDefine; -import org.intellij.plugins.relaxNG.compact.psi.RncElement; -import org.intellij.plugins.relaxNG.compact.psi.RncGrammar; -import org.intellij.plugins.relaxNG.compact.psi.util.EscapeUtil; - -import static com.intellij.patterns.PlatformPatterns.psiElement; -import static com.intellij.patterns.StandardPatterns.*; - -public class RncCompletionData extends CompletionData { - - public RncCompletionData() { - declareFinalScope(RncElement.class); - - final CompletionVariant variant = new CompletionVariant(new AndFilter( - new ElementFilter() { - @Override - public boolean isAcceptable(Object element, PsiElement context) { - return true; - } - - @Override - public boolean isClassAcceptable(Class hintClass) { - return PsiElement.class.isAssignableFrom(hintClass); - } - }, - new PatternFilter(or( - psiElement().afterLeaf(psiElement(RncTokenTypes.KEYWORD_DEFAULT)), - not( - or( - psiElement().inside(psiElement(RncTokenTypes.LITERAL)), - psiElement().afterLeaf(psiElement().withElementType(RncTokenTypes.KEYWORDS)) - ) - ) - )) - )); - - variant.includeScopeClass(LeafPsiElement.class, true); - - variant.addCompletion(new KeywordGetter()); - - registerVariant(variant); - } - - private static class KeywordGetter implements ContextGetter { - private static final ElementPattern TOP_LEVEL = - not(psiElement().inside(psiElement(RncGrammar.class) - .inside(true, psiElement(RncGrammar.class)))); - - private static final PsiElementPattern DECL_PATTERN = - psiElement().inside(psiElement(RncDecl.class)); - - private static final PsiElementPattern DEFAULT_PATTERN = - DECL_PATTERN.afterLeaf(psiElement().withText("default")); - - private static final ElementPattern DEFINE_PATTERN = - and(psiElement().withParent(RncDefine.class), psiElement().afterLeafSkipping(psiElement(PsiWhiteSpace.class), psiElement().withText("="))); - - private static final String[] DECL_KEYWORDS = new String[]{ "default", "namespace", "datatypes" }; - private static final String[] GRAMMAR_CONTENT_KEYWORDS = new String[]{ "include", "div", "start" }; - private static final String[] PATTERN_KEYWORDS = new String[]{ "attribute", "element", "grammar", - "notAllowed", "text", "empty", "external", "parent", "list", "mixed" }; - - @Override - public Object[] get(PsiElement context, CompletionContext completionContext) { - return ContainerUtil.map2Array(doGetKeywords(context), LookupElement.class, (Function)s -> TailTypeDecorator.withTail(LookupElementBuilder.create(s).bold(), TailType.SPACE)); - } - - private String[] doGetKeywords(PsiElement context) { - final PsiElement next = PsiTreeUtil.skipSiblingsForward(context, PsiWhiteSpace.class); - if (next != null && EscapeUtil.unescapeText(next).equals("=")) { - return new String[]{ "start" }; - } - - if (DEFAULT_PATTERN.accepts(context)) { - return new String[]{ "namespace" }; - } else if (DECL_PATTERN.accepts(context)) { - return ArrayUtil.EMPTY_STRING_ARRAY; - } else if (context.getParent() instanceof RncDefine && context.getParent().getFirstChild() == context) { - if (DEFINE_PATTERN.accepts(context)) { - return ArrayUtil.EMPTY_STRING_ARRAY; - } - if (TOP_LEVEL.accepts(context)) { - if (!afterPattern(context)) { - return ArrayUtil.mergeArrays(DECL_KEYWORDS, ArrayUtil.mergeArrays(GRAMMAR_CONTENT_KEYWORDS, PATTERN_KEYWORDS)); - } - } - return GRAMMAR_CONTENT_KEYWORDS; - } - return PATTERN_KEYWORDS; - } - - private boolean afterPattern(PsiElement context) { - // TODO: recognize all patterns - return PsiTreeUtil.getPrevSiblingOfType(context.getParent(), RncDefine.class) != null; - } - } -} \ No newline at end of file