All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.intellij.psi.LiteralTextEscaper Maven / Gradle / Ivy

Go to download

A packaging of the IntelliJ Community Edition core-api library. This is release number 1 of trunk branch 142.

The newest version!
/*
 * Copyright 2000-2009 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.psi;

import com.intellij.openapi.util.TextRange;
import org.jetbrains.annotations.NotNull;

/**
 * @author cdr
*/
public abstract class LiteralTextEscaper {
  protected final T myHost;

  protected LiteralTextEscaper(@NotNull T host) {
    myHost = host;
  }

  /**
   * Add decoded and unescaped characters from the host element to {@code outChars} buffer. If it's impossible to properly decode some chars
   * from the specified range (e.g. if the range starts or ends inside escaped sequence), decode the longest acceptable prefix of the range and return {@code false}
   * @param rangeInsideHost range to be decoded. It's guarantied to be inside {@link #getRelevantTextRange()}
   * @param outChars buffer for output chars. Use {@code append} methods only, it's forbidden to modify or remove existing characters
   * @return {@code true} if whole range was successfully decoded, {@code false} otherwise
   */
  public abstract boolean decode(@NotNull TextRange rangeInsideHost, @NotNull StringBuilder outChars);

  /**
   * This method is called only after {@link #decode}, so it's possible to prepare necessary data in {@link #decode} and then use it here.
   * @param offsetInDecoded offset in the parsed injected file
   * @param rangeInsideHost range where injection is performed,
   *   E.g. if some language fragment xyz was injected into string literal expression "xyz", then rangeInsideHost = (1,4)
   * @return offset in the host PSI element, or -1 if offset is out of host range.
   * E.g. if some language fragment xyz was injected into string literal expression "xyz", then
   *     getOffsetInHost(0)==1 (there is an 'x' at offset 0 in injected fragment,
   *                            and that 'x' occurs in "xyz" string literal at offset 1
   *                            since string literal expression "xyz" starts with double quote)
   *     getOffsetInHost(1)==2
   *     getOffsetInHost(2)==3
   *     getOffsetInHost(3)==-1  (out of range)
   *
   * Similarly, for some language fragment xyz being injected into xml text inside xml tag 'tag': xyz
   *     getOffsetInHost(0)==0 (there is an 'x' at offset 0 in injected fragment,
   *                            and that 'x' occurs in xyz xml text at offset 0)
   *     getOffsetInHost(1)==1
   *     getOffsetInHost(2)==2
   *     getOffsetInHost(3)==-1  (out of range)
   */
  public abstract int getOffsetInHost(int offsetInDecoded, @NotNull TextRange rangeInsideHost);

  /**
   * @return range inside the host where injection can be performed; usually it's range of text without boundary quotes
   */
  @NotNull
  public TextRange getRelevantTextRange() {
    return TextRange.from(0, myHost.getTextLength());
  }

  /**
   * @return {@code true} if the host cannot accept multiline content, {@code false} otherwise
   */
  public abstract boolean isOneLine();

  public static  LiteralTextEscaper createSimple(T element) {
    return new LiteralTextEscaper(element) {
      @Override
      public boolean decode(@NotNull TextRange rangeInsideHost, @NotNull StringBuilder outChars) {
        outChars.append(rangeInsideHost.substring(myHost.getText()));
        return true;
      }

      @Override
      public int getOffsetInHost(int offsetInDecoded, @NotNull TextRange rangeInsideHost) {
        return rangeInsideHost.getStartOffset() + offsetInDecoded;
      }

      @Override
      public boolean isOneLine() {
        return true;
      }
    };
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy