com.intellij.psi.LiteralTextEscaper Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of core-api Show documentation
Show all versions of core-api Show documentation
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;
}
};
}
}