use of com.perl5.lang.perl.psi.impl.PerlHeredocElementImpl in project Perl5-IDEA by Camelcade.
the class PerlDocumentBasedFormattingModel method shiftIndentInsideDocumentRange.
@Override
public TextRange shiftIndentInsideDocumentRange(Document document, ASTNode node, TextRange range, int indent) {
if (!HEREDOC_BODIES_TOKENSET.contains(PsiUtilCore.getElementType(node))) {
return null;
}
PsiElement psi = node.getPsi();
assert psi instanceof PerlHeredocElementImpl : "Got " + psi + " instead of heredoc from " + PsiUtilCore.getElementType(node);
if (!((PerlHeredocElementImpl) psi).isIndentable()) {
return null;
}
final int newLength = shiftIndentInside(range, indent);
return new TextRange(range.getStartOffset(), range.getStartOffset() + newLength);
}
use of com.perl5.lang.perl.psi.impl.PerlHeredocElementImpl in project Perl5-IDEA by Camelcade.
the class PerlIndentProcessor method getNodeIndent.
@NotNull
public Indent getNodeIndent(@NotNull ASTNode node) {
IElementType nodeType = node.getElementType();
ASTNode parent = node.getTreeParent();
ASTNode grandParent = parent != null ? parent.getTreeParent() : null;
IElementType parentNodeType = parent != null ? parent.getElementType() : null;
IElementType grandParentNodeType = grandParent != null ? grandParent.getElementType() : null;
ASTNode prevSibling = FormatterUtil.getPreviousNonWhitespaceSibling(node);
IElementType prevSiblingElementType = prevSibling != null ? prevSibling.getElementType() : null;
ASTNode nextSibling = FormatterUtil.getNextNonWhitespaceSibling(node);
IElementType nextSiblingElementType = nextSibling != null ? nextSibling.getElementType() : null;
boolean isFirst = prevSibling == null;
boolean isLast = nextSibling == null;
if (parentNodeType == ATTRIBUTES) {
return Indent.getContinuationIndent();
}
if (isFirst && BLOCK_OPENERS.contains(nodeType) || isLast && BLOCK_CLOSERS.contains(nodeType)) {
return Indent.getNoneIndent();
}
if (VARIABLE_DECLARATIONS.contains(parentNodeType) && (nodeType == LEFT_PAREN || nodeType == RIGHT_PAREN)) {
return Indent.getNoneIndent();
}
boolean forceFirstIndent = false;
if (HEREDOC_BODIES_TOKENSET.contains(nodeType)) {
PsiElement psi = node.getPsi();
assert psi instanceof PerlHeredocElementImpl;
if (!((PerlHeredocElementImpl) psi).isIndentable()) {
return Indent.getAbsoluteNoneIndent();
}
forceFirstIndent = true;
}
if (getAbsoluteUnindentableTokens().contains(nodeType)) {
return Indent.getAbsoluteNoneIndent();
}
if (nodeType == BLOCK && MULTI_PARAM_BLOCK_CONTAINERS.contains(parentNodeType)) {
return Indent.getNoneIndent();
}
if (parent == null || grandParent == null && nodeType != HEREDOC_END_INDENTABLE && !HEREDOC_BODIES_TOKENSET.contains(nodeType)) {
return Indent.getNoneIndent();
}
if (getUnindentableTokens().contains(nodeType) || (nodeType instanceof PerlPolyNamedElementType && !(node.getPsi() instanceof PerlPolyNamedNestedCallElementBase))) {
return Indent.getNoneIndent();
}
if (parentNodeType == STRING_LIST && (nodeType == QUOTE_SINGLE_OPEN || nodeType == QUOTE_SINGLE_CLOSE)) {
return Indent.getNoneIndent();
}
if (nodeType == STRING_CONTENT && (parentNodeType == STRING_LIST || parentNodeType == LP_STRING_QW)) {
return Indent.getContinuationIndent();
}
// defined by parent
if (getUnindentableContainers().contains(parentNodeType)) {
// a little magic for sub attributes
if (parentNodeType == SUB_DEFINITION) {
if (nodeType == COLON && nextSiblingElementType == ATTRIBUTE || nodeType == ATTRIBUTE && prevSiblingElementType != COLON) {
return Indent.getContinuationIndent();
}
}
return Indent.getNoneIndent();
}
if (PerlFormattingContext.COMMA_LIKE_SEQUENCES.contains(parentNodeType)) {
return grandParentNodeType == STATEMENT ? Indent.getContinuationWithoutFirstIndent() : Indent.getContinuationIndent();
}
if (parentNodeType == CALL_ARGUMENTS) {
return Indent.getContinuationIndent();
}
if (getBlockLikeContainers().contains(parentNodeType)) {
return Indent.getNormalIndent();
}
return forceFirstIndent ? Indent.getContinuationIndent() : Indent.getContinuationWithoutFirstIndent();
}
use of com.perl5.lang.perl.psi.impl.PerlHeredocElementImpl in project Perl5-IDEA by Camelcade.
the class PerlEnterHeredocClosingHandler method postProcessEnter.
@Override
public Result postProcessEnter(@NotNull PsiFile file, @NotNull Editor editor, @NotNull DataContext dataContext) {
if (!file.getLanguage().is(PerlLanguage.INSTANCE)) {
return Result.Continue;
}
final CaretModel caretModel = editor.getCaretModel();
int offset = caretModel.getOffset();
PsiElement currentElement = file.findElementAt(offset);
if (currentElement != null && (!(currentElement.getParent() instanceof PerlHeredocElementImpl) || !Perl5CodeInsightSettings.getInstance().HEREDOC_AUTO_INSERTION)) {
return Result.Continue;
}
LogicalPosition currentPosition = caretModel.getLogicalPosition();
final int enterLine = currentPosition.line - 1;
final int currentOffset = caretModel.getOffset();
if (enterLine <= -1 || currentOffset <= 0) {
return Result.Continue;
}
final Document document = editor.getDocument();
final PsiDocumentManager manager = PsiDocumentManager.getInstance(file.getProject());
manager.commitDocument(document);
final int lineStartOffset = document.getLineStartOffset(enterLine);
PsiElement firstLineElement = file.findElementAt(lineStartOffset);
if (firstLineElement == null) {
return Result.Continue;
}
HeredocCollector collector = new HeredocCollector(currentOffset - 1);
PerlPsiUtil.iteratePsiElementsRight(firstLineElement, collector);
SmartPsiElementPointer<PerlHeredocOpener> lastOpenerPointer = null;
for (SmartPsiElementPointer<PerlHeredocOpener> currentOpenerPointer : collector.getResult()) {
PerlHeredocOpener currentOpener = currentOpenerPointer.getElement();
if (currentOpener == null) {
// System.err.println("Opener invalidated on reparse");
return Result.Continue;
}
String openerName = currentOpener.getName();
boolean emptyOpener = StringUtil.isEmpty(openerName);
PsiReference inboundReference = ReferencesSearch.search(currentOpener).findFirst();
if (inboundReference != null) {
boolean falseAlarm = false;
PsiElement run = inboundReference.getElement().getPrevSibling();
while (run instanceof PsiWhiteSpace) {
run = run.getPrevSibling();
}
if (run instanceof PerlHeredocElementImpl) {
Pattern openerPattern = EMPTY_OPENER_PATTERN;
if (!emptyOpener) {
openerPattern = Pattern.compile("<<~?(\\s*)(?:" + "\"" + openerName + "\"" + "|" + "`" + openerName + "`" + "|" + "'" + openerName + "'" + "|" + "\\\\" + openerName + "|" + openerName + ")");
}
falseAlarm = openerPattern.matcher(run.getNode().getChars()).find();
}
if (// looks like overlapping heredocs
falseAlarm) {
inboundReference = null;
} else {
lastOpenerPointer = currentOpenerPointer;
}
}
if (// disclosed marker
inboundReference == null) {
int addOffset;
String closeMarker = "\n" + openerName + "\n";
if (// first one
lastOpenerPointer == null) {
addOffset = currentOffset;
} else // sequentional
{
PerlHeredocOpener lastOpener = lastOpenerPointer.getElement();
if (lastOpener == null) {
return Result.Continue;
}
PsiReference lastOpenerReference = ReferencesSearch.search(lastOpener).findFirst();
if (lastOpenerReference != null) {
PsiElement element = lastOpenerReference.getElement();
addOffset = element.getTextRange().getEndOffset();
if (!emptyOpener) {
closeMarker = "\n" + closeMarker;
}
} else {
return Result.Continue;
}
}
document.insertString(addOffset, closeMarker);
manager.commitDocument(document);
CodeStyleManager.getInstance(file.getProject()).reformatRange(file, addOffset, addOffset + closeMarker.length());
currentOpener = currentOpenerPointer.getElement();
if (currentOpener == null) {
return Result.Continue;
}
inboundReference = ReferencesSearch.search(currentOpener).findFirst();
if (inboundReference != null) {
lastOpenerPointer = currentOpenerPointer;
} else {
return Result.Continue;
}
}
}
return Result.Continue;
}
use of com.perl5.lang.perl.psi.impl.PerlHeredocElementImpl in project Perl5-IDEA by Camelcade.
the class PerlHeredocFormattingBlock method getTextRange.
@NotNull
@Override
public TextRange getTextRange() {
TextRange originalRange = super.getTextRange();
if (originalRange.isEmpty()) {
return originalRange;
}
TextRange trimmedRange = TextRange.create(originalRange.getStartOffset(), originalRange.getEndOffset() - 1);
PerlHeredocElementImpl heredocElement = getPsi();
if (!heredocElement.isIndentable()) {
return trimmedRange;
}
PerlHeredocTerminatorElement terminatorElement = heredocElement.getTerminatorElement();
if (terminatorElement == null) {
return trimmedRange;
}
// perlop: Tabs and spaces can be mixed, but are matched exactly. One tab will not be equal to 8 spaces!
int spacesBeforeTerminator = terminatorElement.getTextRange().getStartOffset() - trimmedRange.getEndOffset() - 1;
if (spacesBeforeTerminator == 0) {
return trimmedRange;
}
CharSequence nodeChars = trimmedRange.shiftRight(-myNode.getStartOffset()).subSequence(myNode.getChars());
int effectiveCharsLength = nodeChars.length();
int realSpaces;
int offset = 0;
OUTER: while (offset < effectiveCharsLength) {
for (realSpaces = 0; realSpaces <= spacesBeforeTerminator && offset < effectiveCharsLength; realSpaces++) {
if (realSpaces == spacesBeforeTerminator) {
break OUTER;
}
char currentChar = nodeChars.charAt(offset);
if (currentChar == '\n') {
offset++;
break;
} else if (!Character.isWhitespace(currentChar)) {
break OUTER;
} else {
offset++;
}
}
}
return TextRange.create(trimmedRange.getStartOffset() + offset, trimmedRange.getEndOffset());
}
use of com.perl5.lang.perl.psi.impl.PerlHeredocElementImpl in project Perl5-IDEA by Camelcade.
the class PerlDocUtil method getPerlOpDoc.
@Nullable
public static PsiElement getPerlOpDoc(@NotNull PsiElement element) {
final Project project = element.getProject();
String text = element.getText();
String redirect = myOperatorsRedirections.get(text);
if (redirect != null) {
return resolveDocLink(redirect, element);
}
// fixme use map?
PodDocumentPattern pattern = PodDocumentPattern.indexPattern(text);
if (element instanceof PerlHeredocOpener || element instanceof PerlHeredocTerminatorElement || element instanceof PerlHeredocElementImpl) {
// searches with X<>
pattern.setIndexKey("heredoc");
} else if (text.matches("-[rwxoRWXOeszfdlpSbctugkTBMAC]")) {
pattern.setIndexKey("-X");
} else if ("?".equals(text) || ":".equals(text)) {
pattern.setIndexKey("?:");
}
return searchPodElementInFile(project, PodSearchHelper.PERL_OP_FILE_NAME, pattern);
}
Aggregations