Package cz.juzna.latte.completion

Source Code of cz.juzna.latte.completion.KeywordCompletionProvider

package cz.juzna.latte.completion;

import com.intellij.codeInsight.completion.CompletionParameters;
import com.intellij.codeInsight.completion.CompletionProvider;
import com.intellij.codeInsight.completion.CompletionResultSet;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiWhiteSpace;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlElement;
import com.intellij.util.ProcessingContext;
import cz.juzna.latte.lexer.LatteTokenTypes;
import cz.juzna.latte.psi.impl.MacroNodeImpl;
import org.jetbrains.annotations.NotNull;

import java.util.*;

/**
* Provides keywords to be auto-completed
*/
public class KeywordCompletionProvider extends CompletionProvider<CompletionParameters> {
    // constant lists
    private static final String[] KEYWORDS = {
        // CoreMacros.php
        "if", "ifset", "for", "foreach", "while", "first", "last", "sep", "class", "attr", "captute",
        "var", "default", "dump", "debugbreak", "l", "r",

        // FormMacros.php
        "form", "input", "label", "formContainer",

        // UIMacros.php
        "include", "extends", "block", "define", "snippet", "widget", "control", "href", "link", "plink", "contentType", "status",
    };

  private static final List<String> PAIR_MACROS = Arrays.asList(
      "if", "ifset", "for", "foreach", "while", "first", "last", "sep"
  );

  private static final String[] FILTERS = {
      // static
      "normalize", "toascii", "webalize", "truncate", "lower", "upper", "firstupper", "capitalize", "trim", "padleft", "padright",
      "replacere", "url", "striptags", "nl2br", "substr", "repeat", "implode", "number",

      // methods in Helpers.php
      "espaceHtml", "escapeHtmlComment", "escapeXML", "escapeCss", "escapeJs", "strip", "indent", "date", "bytes",
      "length", "replace", "dataStream", "null",
  };


  // CompletionResultSet wants list of LookupElements
    private List<LookupElementBuilder> KEYWORD_LOOKUPS = new ArrayList();
    private List<LookupElementBuilder> ATTR_LOOKUPS = new ArrayList();
    private List<LookupElementBuilder> FILTER_LOOKUPS = new ArrayList();
  private HashMap<String, LookupElementBuilder> CLOSING_LOOKUPS = new HashMap<String, LookupElementBuilder>();

    public KeywordCompletionProvider() {
        super();

        for(String keyword: KEYWORDS) {
          KEYWORD_LOOKUPS.add(LookupElementBuilder.create(keyword));
          ATTR_LOOKUPS.add(LookupElementBuilder.create("n:" + keyword));
        }
        for(String filter: FILTERS) FILTER_LOOKUPS.add(LookupElementBuilder.create(filter));
    }

    @Override
    protected void addCompletions(@NotNull CompletionParameters params,
                                  ProcessingContext ctx,
                                  @NotNull CompletionResultSet results) {

      PsiElement curr = params.getPosition().getOriginalElement();

      // n: attributes
      if(curr.getParent() instanceof XmlAttribute) {
        for(LookupElementBuilder x: ATTR_LOOKUPS) results.addElement(x);
        return;
      }

      // Keywords
        if(curr.getNode().getElementType() == LatteTokenTypes.MACRO_NAME) {
            for(LookupElementBuilder x: KEYWORD_LOOKUPS) results.addElement(x);

          HashSet<String> openedMacros = new HashSet<String>(); // macros which are opened before (should complete closing)
          HashSet<String> closedMacros = new HashSet<String>(); // which are closed (should not complete closing)

          // Go up and find open keywords (and offer them for closing)
          PsiElement cursor = curr;
          while(cursor != null && (cursor.getPrevSibling() != null || cursor.getParent() != null)) {
            // macro found {xx} found
            if(cursor instanceof MacroNodeImpl) {
              MacroNodeImpl node = (MacroNodeImpl) cursor;
              String name = node.getMacroName();

              if(name.charAt(0) == '/') { // closing macro
                closedMacros.add(name.substring(1));
              } else if(PAIR_MACROS.contains(name)) {
                if(closedMacros.contains(name)) closedMacros.remove(name); // is closed later
                else openedMacros.add(name); // not closed, let us close it
              }
            }


            PsiElement tmp;
            if((tmp = cursor.getPrevSibling()) != null) cursor = tmp; // Go prev if possible...
            else cursor =  cursor.getParent(); // ... or up
          }

          for(String name: openedMacros) {
            if(name.equals("if")) {
              results.addElement(reuseClosingTag("else"));
              results.addElement(reuseClosingTag("elseif"));
            }
            results.addElement(reuseClosingTag("/" + name));
          }

          results.stopHere();
        }

      // Modifiers (if after pipe)
      PsiElement prev = curr.getPrevSibling();
      if(prev != null && prev instanceof PsiWhiteSpace) prev = prev.getPrevSibling();
      if(prev != null && prev.getNode().getElementType() == LatteTokenTypes.MODIFIER) {
        for(LookupElementBuilder x: FILTER_LOOKUPS) results.addElement(x);
        results.stopHere();
      }
    }

  // Get closing tag
  private LookupElementBuilder reuseClosingTag(String name) {
    if(!CLOSING_LOOKUPS.containsKey(name)) {
      CLOSING_LOOKUPS.put(name, LookupElementBuilder.create(name));
    }

    return CLOSING_LOOKUPS.get(name);
  }
}
TOP

Related Classes of cz.juzna.latte.completion.KeywordCompletionProvider

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.