Package com.intellij.coldFusion.UI.editorActions.matchers

Source Code of com.intellij.coldFusion.UI.editorActions.matchers.CfmlBraceMatcher

/*
* 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 com.intellij.coldFusion.UI.editorActions.matchers;

import com.intellij.codeInsight.highlighting.BraceMatcher;
import com.intellij.coldFusion.model.CfmlLanguage;
import com.intellij.coldFusion.model.CfmlUtil;
import com.intellij.coldFusion.model.files.CfmlFileType;
import com.intellij.coldFusion.model.lexer.CfmlTokenTypes;
import com.intellij.coldFusion.model.lexer.CfscriptTokenTypes;
import com.intellij.ide.highlighter.XmlFileType;
import com.intellij.lang.BracePair;
import com.intellij.lang.Language;
import com.intellij.lang.LanguageBraceMatching;
import com.intellij.lang.PairedBraceMatcher;
import com.intellij.openapi.editor.highlighter.HighlighterIterator;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeExtensionPoint;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
* Created by Lera Nikolaenko
* Date: 09.10.2008
*/
public class CfmlBraceMatcher implements BraceMatcher {
  private static final BracePair[] PAIRS = new BracePair[]{
    // new BracePair(CfmlTokenTypes.OPENER, CfmlTokenTypes.CLOSER, true),
    new BracePair(CfscriptTokenTypes.L_BRACKET, CfscriptTokenTypes.R_BRACKET, false),
    new BracePair(CfscriptTokenTypes.L_SQUAREBRACKET, CfscriptTokenTypes.R_SQUAREBRACKET, false),
    new BracePair(CfscriptTokenTypes.L_CURLYBRACKET, CfscriptTokenTypes.R_CURLYBRACKET, false),
    new BracePair(CfscriptTokenTypes.OPENSHARP, CfscriptTokenTypes.CLOSESHARP, true),/*
            new BracePair(CfscriptTokenTypes.DOUBLE_QUOTE, CfscriptTokenTypes.DOUBLE_QUOTE_CLOSER, false),
            new BracePair(CfscriptTokenTypes.SINGLE_QUOTE, CfscriptTokenTypes.SINGLE_QUOTE_CLOSER, false),*/
    new BracePair(CfmlTokenTypes.START_EXPRESSION, CfmlTokenTypes.END_EXPRESSION, true)/*,
            new BracePair(CfmlTokenTypes.DOUBLE_QUOTE, CfmlTokenTypes.DOUBLE_QUOTE_CLOSER, false),
            new BracePair(CfmlTokenTypes.SINGLE_QUOTE, CfmlTokenTypes.SINGLE_QUOTE_CLOSER, false)*/
  };

  public int getBraceTokenGroupId(IElementType tokenType) {
    final Language l = tokenType.getLanguage();
    return l.hashCode();
        /*
        PairedBraceMatcher matcher = LanguageBraceMatching.INSTANCE.forLanguage(l);
        if (matcher != null) {
          BracePair[] pairs = matcher.getPairs();
          for (BracePair pair : pairs) {
            if (pair.getLeftBraceType() == tokenType || pair.getRightBraceType() == tokenType ) {
              return l.hashCode();
            }
          }
        }
        FileType tokenFileType = tokenType.getLanguage().getAssociatedFileType();
        if (tokenFileType != CfmlFileType.INSTANCE) {
            for(FileTypeExtensionPoint<BraceMatcher> ext : Extensions.getExtensions(BraceMatcher.EP_NAME)) {
                if (tokenFileType.getName().equals(ext.filetype)) {
                    return ext.getInstance().getBraceTokenGroupId(tokenType);
                }
            }
        }
        return l.hashCode();
        */
  }

  public boolean isLBraceToken(HighlighterIterator iterator, CharSequence fileText, FileType fileType) {
    final IElementType tokenType = iterator.getTokenType();
    PairedBraceMatcher matcher = LanguageBraceMatching.INSTANCE.forLanguage(tokenType.getLanguage());
    if (matcher != null) {
      BracePair[] pairs = matcher.getPairs();
      for (BracePair pair : pairs) {
        if (pair.getLeftBraceType() == tokenType) return true;
      }
    }

    if (!tokenType.getLanguage().equals(CfmlLanguage.INSTANCE)) {
      FileType tokenFileType = iterator.getTokenType().getLanguage().getAssociatedFileType();
      if (tokenFileType != null && tokenFileType != CfmlFileType.INSTANCE) {
        for (FileTypeExtensionPoint<BraceMatcher> ext : Extensions.getExtensions(BraceMatcher.EP_NAME)) {
          if (ext.filetype != null && ext.filetype.equals(tokenFileType.getName())) {
            return ext.getInstance().isLBraceToken(iterator, fileText,
                                                   tokenFileType instanceof XmlFileType ? StdFileTypes.HTML : tokenFileType);
          }
        }
      }
    }

    for (BracePair pair : PAIRS) {
      if (pair.getLeftBraceType() == tokenType) {
        return true;
      }
    }
    return tokenType.equals(CfmlTokenTypes.OPENER) &&
           (!CfmlUtil.isEndTagRequired(getTagName(fileText, iterator), null) || findEndTag(fileText, iterator));
  }

  public boolean isRBraceToken(HighlighterIterator iterator, CharSequence fileText, FileType fileType) {
    final IElementType tokenType = iterator.getTokenType();

    PairedBraceMatcher matcher = LanguageBraceMatching.INSTANCE.forLanguage(tokenType.getLanguage());
    if (matcher != null) {
      BracePair[] pairs = matcher.getPairs();
      for (BracePair pair : pairs) {
        if (pair.getRightBraceType() == tokenType) return true;
      }
    }

    if (!tokenType.getLanguage().equals(CfmlLanguage.INSTANCE)) {
      FileType tokenFileType = iterator.getTokenType().getLanguage().getAssociatedFileType();
      if (tokenFileType != null && tokenFileType != CfmlFileType.INSTANCE) {
        for (FileTypeExtensionPoint<BraceMatcher> ext : Extensions.getExtensions(BraceMatcher.EP_NAME)) {
          if (ext.filetype != null && ext.filetype.equals(tokenFileType.getName())) {
            return ext.getInstance().isRBraceToken(iterator, fileText,
                                                   tokenFileType instanceof XmlFileType ? StdFileTypes.HTML : tokenFileType);
          }
        }
      }
    }

    for (BracePair pair : PAIRS) {
      if (pair.getRightBraceType() == tokenType) return true;
    }
    return ((tokenType.equals(CfmlTokenTypes.CLOSER)) && findBeginTag(fileText, iterator)) ||
           (tokenType.equals(CfmlTokenTypes.R_ANGLEBRACKET) &&
            !CfmlUtil.isEndTagRequired(getTagName(fileText, iterator), null) &&
            !findEndTag(fileText, iterator));
  }

  public boolean isPairBraces(IElementType tokenType1, IElementType tokenType2) {
    PairedBraceMatcher matcher = LanguageBraceMatching.INSTANCE.forLanguage(tokenType1.getLanguage());
    if (matcher != null) {
      BracePair[] pairs = matcher.getPairs();
      for (BracePair pair : pairs) {
        if (pair.getLeftBraceType() == tokenType1) return pair.getRightBraceType() == tokenType2;
        if (pair.getRightBraceType() == tokenType1) return pair.getLeftBraceType() == tokenType2;
      }
    }

    FileType tokenFileType1 = tokenType1.getLanguage().getAssociatedFileType();
    FileType tokenFileType2 = tokenType2.getLanguage().getAssociatedFileType();
    if (tokenFileType2 != tokenFileType1) {
      return false;
    }
    if (tokenFileType1 != CfmlFileType.INSTANCE && tokenFileType1 != null) {
      for (FileTypeExtensionPoint<BraceMatcher> ext : Extensions.getExtensions(BraceMatcher.EP_NAME)) {
        if (ext.filetype.equals(tokenFileType1.getName())) {
          return ext.getInstance().isPairBraces(tokenType1, tokenType2);
        }
      }
    }

    for (BracePair pair : PAIRS) {
      if (pair.getLeftBraceType() == tokenType1) return pair.getRightBraceType() == tokenType2;
      if (pair.getRightBraceType() == tokenType1) return pair.getLeftBraceType() == tokenType2;
    }
    return (tokenType1.equals(CfmlTokenTypes.OPENER) && tokenType2.equals(CfmlTokenTypes.CLOSER)) ||
           (tokenType1.equals(CfmlTokenTypes.CLOSER) && tokenType2.equals(CfmlTokenTypes.OPENER)) ||
           (tokenType1.equals(CfmlTokenTypes.R_ANGLEBRACKET) && tokenType2.equals(CfmlTokenTypes.OPENER)) ||
           (tokenType1.equals(CfmlTokenTypes.OPENER) && tokenType2.equals(CfmlTokenTypes.R_ANGLEBRACKET));
  }

  public boolean isStructuralBrace(HighlighterIterator iterator, CharSequence text, FileType fileType) {
    IElementType type = iterator.getTokenType();
    if (type == CfscriptTokenTypes.L_BRACKET || type == CfscriptTokenTypes.R_BRACKET) {
      return false;
    }
    return true;
        /*
        for(FileTypeExtensionPoint<BraceMatcher> ext : Extensions.getExtensions(BraceMatcher.EP_NAME)) {
            if (StdFileTypes.HTML.getName().equals(ext.filetype)) {
                return ext.getInstance().isStructuralBrace(iterator, text, StdFileTypes.HTML);
            }
        }
        IElementType tokenType = iterator.getTokenType();

        PairedBraceMatcher matcher = LanguageBraceMatching.INSTANCE.forLanguage(tokenType.getLanguage());
        if (matcher != null) {
          BracePair[] pairs = matcher.getPairs();
          for (BracePair pair : pairs) {
            if ((pair.getLeftBraceType() == tokenType || pair.getRightBraceType() == tokenType) &&
                pair.isStructural()) return true;
          }
        }
        for (BracePair pair : PAIRS) {
            if ((pair.getLeftBraceType() == tokenType || pair.getRightBraceType() == tokenType) &&
                    pair.isStructural()) return true;
        }
        return tokenType.equals(CfmlTokenTypes.OPENER) || tokenType.equals(CfmlTokenTypes.CLOSER);
        */
  }

  public boolean isPairedBracesAllowedBeforeType(@NotNull final IElementType lbraceType, @Nullable final IElementType contextType) {
    return true;
  }

  private static boolean findBeginTag(CharSequence fileText, HighlighterIterator iterator) {
    IElementType tokenType;
    final String name = getTagName(fileText, iterator);
    if (name == null) {
      return false;
    }
    int balance = 0;
    int count = 0;
    while (balance < 1) {
      iterator.retreat();
      count++;
      if (iterator.atEnd()) break;
      tokenType = iterator.getTokenType();
      String currentTagName = getTagName(fileText, iterator);
      if (tokenType == CfmlTokenTypes.CLOSER && name.equals(currentTagName)) {
        balance--;
      }
      else if (tokenType == CfmlTokenTypes.OPENER &&
               name.equals(currentTagName)) {
        balance++;
      }
    }
    while (count-- > 0) iterator.advance();
    return balance == 1;
  }

  private static boolean findEndTag(CharSequence fileText, HighlighterIterator iterator) {
    IElementType tokenType;
    final String name = getTagName(fileText, iterator);
    if (name == null) {
      return false;
    }
    int balance = 0;
    int count = 0;
    while (balance > -1 && !iterator.atEnd()) {
      iterator.advance();
      count++;
      if (iterator.atEnd()) break;
      tokenType = iterator.getTokenType();
      String currrentTagName = getTagName(fileText, iterator);
      if (tokenType == CfmlTokenTypes.OPENER &&
          name.equals(currrentTagName)) {
        balance++;
      }
      else if (tokenType == CfmlTokenTypes.CLOSER && name.equals(currrentTagName)) {
        balance--;
      }
    }
    while (count-- > 0) iterator.retreat();
    return balance == -1;
  }

  @Nullable
  public static String getTagName(CharSequence fileText, HighlighterIterator iterator) {
    final IElementType tokenType = iterator.getTokenType();
    String name = null;
    if (tokenType == CfmlTokenTypes.CLOSER || tokenType == CfmlTokenTypes.R_ANGLEBRACKET) {
      iterator.retreat();
      IElementType tokenType1 = (!iterator.atEnd() ? iterator.getTokenType() : null);

      if (tokenType1 == CfmlTokenTypes.CF_TAG_NAME) {
        name = fileText.subSequence(iterator.getStart(), iterator.getEnd()).toString();
      }
      else {
        int counter = 0;
        while (!iterator.atEnd()) {
          if (iterator.getTokenType() == CfmlTokenTypes.CF_TAG_NAME) {
            name = fileText.subSequence(iterator.getStart(), iterator.getEnd()).toString();
            break;
          }
          if (iterator.getTokenType() == CfmlTokenTypes.CLOSER ||
              iterator.getTokenType() == CfmlTokenTypes.R_ANGLEBRACKET) {
            break;
          }
          iterator.retreat();
          counter++;
        }
        while (counter-- > 0) iterator.advance();
      }
      iterator.advance();
    }
    else if (tokenType == CfmlTokenTypes.OPENER) {
      iterator.advance();
      IElementType tokenType1 = (!iterator.atEnd() ? iterator.getTokenType() : null);

      if (tokenType1 == CfmlTokenTypes.CF_TAG_NAME) {
        name = fileText.subSequence(iterator.getStart(), iterator.getEnd()).toString();
      }
      iterator.retreat();
    }
    return name == null ? name : name.toLowerCase();
  }

  public IElementType getOppositeBraceTokenType(@NotNull final IElementType type) {
    for (BracePair pair : PAIRS) {
      if (pair.getLeftBraceType() == type) return pair.getRightBraceType();
      if (pair.getRightBraceType() == type) return pair.getLeftBraceType();
    }
    if (type == CfmlTokenTypes.OPENER) return CfmlTokenTypes.R_ANGLEBRACKET;
    if (type == CfmlTokenTypes.CLOSER) return CfmlTokenTypes.OPENER;
    if (type == CfmlTokenTypes.R_ANGLEBRACKET) return CfmlTokenTypes.OPENER;
    return null;
  }

  public int getCodeConstructStart(final PsiFile file, int openingBraceOffset) {
    PsiElement element = file.findElementAt(openingBraceOffset);
    if (element == null || element instanceof PsiFile) return openingBraceOffset;
    PsiElement parent = element.getParent();
    return parent.getTextRange().getStartOffset();
  }
}
TOP

Related Classes of com.intellij.coldFusion.UI.editorActions.matchers.CfmlBraceMatcher

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.