private static TextRange buildRangeForBraces( TextRange range, @NotNull ASTNode astNode, IElementType lbraceType, IElementType rbraceType) { ASTNode lBrace = astNode.findChildByType(lbraceType); ASTNode rBrace = astNode.findChildByType(rbraceType); if (lBrace != null && rBrace != null) { range = buildRange(range, lBrace.getStartOffset() + 1, rBrace.getStartOffset()); } return range; }
@NotNull public TextRange getTextRange() { if (myElements.length == 0) { final ASTNode child = XmlChildRole.START_TAG_END_FINDER.findChild((ASTNode) myTag); if (child != null) return new TextRange(child.getStartOffset() + 1, child.getStartOffset() + 1); return new TextRange( myTag.getTextRange().getEndOffset(), myTag.getTextRange().getEndOffset()); } return new TextRange( myElements[0].getTextRange().getStartOffset(), myElements[myElements.length - 1].getTextRange().getEndOffset()); }
private static boolean isEmbraced(@Nullable PsiElement element, int offset) { if (element == null) { return false; } ASTNode node = element.getNode(); if (node == null) { return false; } final ASTNode lbrace = node.findChildByType(CfscriptTokenTypes.L_BRACKET); final ASTNode rbrace = node.findChildByType(CfscriptTokenTypes.R_BRACKET); if (lbrace == null || rbrace == null) { return false; } return lbrace.getStartOffset() < offset && rbrace.getStartOffset() >= offset; }
@Override protected TextRange calculateDefaultRangeInElement() { TextRange _xblockexpression = null; { final ASTNode referencenNode = this.getReferenceNode(); int _startOffset = referencenNode.getStartOffset(); ASTNode _node = this.myElement.getNode(); int _startOffset_1 = _node.getStartOffset(); final int startOffset = (_startOffset - _startOffset_1); ASTNode _referenceNode = this.getReferenceNode(); int _textLength = _referenceNode.getTextLength(); final int endOffset = (startOffset + _textLength); _xblockexpression = new TextRange(startOffset, endOffset); } return _xblockexpression; }
private SchemaPrefixReference createPrefixReference( ASTNode startTagName, String prefix, TagNameReference tagRef) { return new SchemaPrefixReference( this, TextRange.from(startTagName.getStartOffset() - getStartOffset(), prefix.length()), prefix, tagRef); }
private static void addFoldingDescriptors( final List<FoldingDescriptor> descriptors, final PsiElement tag, @NotNull Document document) { TextRange elementRange = tag.getTextRange(); final int start = elementRange.getStartOffset(); final int end = elementRange.getEndOffset(); if (start + 1 < end) { TextRange range = null; ASTNode astNode = tag.getNode(); IElementType astType = astNode.getElementType(); if (tag instanceof CfmlTag) { // if (tag instanceof CfmlTagFunctionImpl || tag instanceof CfmlTagComponentImpl || tag // instanceof CfmlTagScriptImpl) { range = buildRangeForBraces( range, astNode, CfmlTokenTypes.R_ANGLEBRACKET, CfmlTokenTypes.LSLASH_ANGLEBRACKET); // } } else if (astType == CfmlElementTypes.FUNCTIONBODY || astType == CfmlElementTypes.BLOCK_OF_STATEMENTS) { range = buildRange(range, start, end); } else if (astType == CfmlElementTypes.SWITCHEXPRESSION) { ASTNode lparen = astNode.findChildByType(CfscriptTokenTypes.L_CURLYBRACKET); ASTNode rparen = astNode.findChildByType(CfscriptTokenTypes.R_CURLYBRACKET); if (lparen != null && rparen != null) { range = buildRange(range, lparen.getStartOffset(), rparen.getTextRange().getEndOffset()); } } else if (tag instanceof PsiComment) { boolean isColdFusionComment = astNode.getElementType() == CfmlTokenTypes.COMMENT; int endIndex = astNode.getText().lastIndexOf(isColdFusionComment ? "--->" : "*/"); if (endIndex != -1) { String commentText = astNode.getText().substring(0, endIndex); if (commentText.contains("\n")) { int startOffset = tag.getTextRange().getStartOffset(); range = buildRange( range, startOffset + (isColdFusionComment ? "<!---" : "/*").length(), startOffset + commentText.length()); } } } if (range != null) { descriptors.add(new FoldingDescriptor(astNode, range)); } // TODO: insert condition addFoldingDescriptorsFromChildren(descriptors, tag, document); } }
@Override public void updateParameterInfo( @NotNull JetValueArgumentList argumentList, @NotNull UpdateParameterInfoContext context) { if (context.getParameterOwner() != argumentList) context.removeHint(); int offset = context.getOffset(); ASTNode child = argumentList.getNode().getFirstChildNode(); int i = 0; while (child != null && child.getStartOffset() < offset) { if (child.getElementType() == JetTokens.COMMA) ++i; child = child.getTreeNext(); } context.setCurrentParameter(i); }
protected Set<AbstractElement> computeFollowElements(final CompletionParameters parameters) { Editor _editor = parameters.getEditor(); Document _document = _editor.getDocument(); PsiElement _position = parameters.getPosition(); ASTNode _node = _position.getNode(); int _startOffset = _node.getStartOffset(); TextRange _textRange = new TextRange(0, _startOffset); final String text = _document.getText(_textRange); final Collection<FollowElement> followElements = this.contentAssistParser.getFollowElements(text, false); final HashSet<AbstractElement> allElements = CollectionLiterals.<AbstractElement>newHashSet(); this.followElementComputer.computeFollowElements(followElements, allElements); return allElements; }
static void registerProblem( BnfExpression choice, BnfExpression branch, String message, ProblemsHolder problemsHolder, LocalQuickFix... fixes) { TextRange textRange = branch.getTextRange(); if (textRange.isEmpty()) { ASTNode nextOr = TreeUtil.findSibling(branch.getNode(), BnfTypes.BNF_OP_OR); ASTNode prevOr = TreeUtil.findSiblingBackward(branch.getNode(), BnfTypes.BNF_OP_OR); int shift = choice.getTextRange().getStartOffset(); int startOffset = prevOr != null ? prevOr.getStartOffset() - shift : 0; TextRange range = new TextRange( startOffset, nextOr != null ? nextOr.getStartOffset() + 1 - shift : Math.min(startOffset + 2, choice.getTextLength())); problemsHolder.registerProblem(choice, range, message, fixes); } else { problemsHolder.registerProblem(branch, message, fixes); } }
protected int getCloseQuoteOffset() { PsiElement lastChild = getLastChild(); if (lastChild instanceof PerlParsableStringWrapperlImpl) { PsiElement realString = lastChild.getFirstChild(); assert realString instanceof PerlStringImplMixin; return ((PerlStringImplMixin) realString).getCloseQuoteOffset(); } ASTNode currentNode = lastChild.getNode(); if (PerlParserUtil.CLOSE_QUOTES.contains(currentNode.getElementType())) return currentNode.getStartOffset(); // unclosed string return lastChild.getTextOffset() + lastChild.getTextLength(); }
@Nullable private static TextRange getEndTagRange(ASTNode tagNode) { final ASTNode endTagStart = XmlChildRole.CLOSING_TAG_START_FINDER.findChild(tagNode); if (endTagStart == null) { return null; } ASTNode endTagEnd = endTagStart; while (endTagEnd != null && endTagEnd.getElementType() != XmlTokenType.XML_TAG_END) { endTagEnd = endTagEnd.getTreeNext(); } if (endTagEnd == null) { return null; } return new TextRange(endTagStart.getStartOffset(), endTagEnd.getTextRange().getEndOffset()); }
@Override protected String replaceWithPsiInLeaf( final TextRange textRange, String whiteSpace, ASTNode leafElement) { if (!myCanModifyAllWhiteSpaces) { if (leafElement.getElementType() == TokenType.WHITE_SPACE) return null; LOG.assertTrue(leafElement.getPsi().isValid()); ASTNode prevNode = TreeUtil.prevLeaf(leafElement); if (prevNode != null) { IElementType type = prevNode.getElementType(); if (type == TokenType.WHITE_SPACE) { final String text = prevNode.getText(); final @NonNls String cdataStartMarker = "<![CDATA["; final int cdataPos = text.indexOf(cdataStartMarker); if (cdataPos != -1 && whiteSpace.indexOf(cdataStartMarker) == -1) { whiteSpace = mergeWsWithCdataMarker(whiteSpace, text, cdataPos); if (whiteSpace == null) return null; } prevNode = TreeUtil.prevLeaf(prevNode); type = prevNode != null ? prevNode.getElementType() : null; } final @NonNls String cdataEndMarker = "]]>"; if (type == XmlTokenType.XML_CDATA_END && whiteSpace.indexOf(cdataEndMarker) == -1) { final ASTNode at = findElementAt(prevNode.getStartOffset()); if (at != null && at.getPsi() instanceof PsiWhiteSpace) { final String s = at.getText(); final int cdataEndPos = s.indexOf(cdataEndMarker); whiteSpace = mergeWsWithCdataMarker(whiteSpace, s, cdataEndPos); leafElement = at; } else { whiteSpace = null; } if (whiteSpace == null) return null; } } } FormatterUtil.replaceWhiteSpace(whiteSpace, leafElement, TokenType.WHITE_SPACE, textRange); return whiteSpace; }
/** * Current handler inserts closing curly brace (right brace) if necessary. There is a possible * case that it should be located more than one line forward. * * <p><b>Example</b> * * <pre> * if (test1()) { * } else {<caret> if (test2()) { * foo(); * } * </pre> * * <p>We want to get this after the processing: * * <pre> * if (test1()) { * } else { * if (test2()) { * foo(); * } * } * </pre> * * I.e. closing brace should be inserted two lines below current caret line. Hence, we need to * calculate correct offset to use for brace inserting. This method is responsible for that. * * <p>In essence it inspects PSI structure and finds PSE elements with the max length that starts * at caret offset. End offset of that element is used as an insertion point. * * @param file target PSI file * @param text text from the given file * @param offset target offset where line feed will be inserted * @return offset to use for inserting closing brace */ protected int calculateOffsetToInsertClosingBrace( PsiFile file, CharSequence text, final int offset) { PsiElement element = PsiUtilCore.getElementAtOffset(file, offset); ASTNode node = element.getNode(); if (node != null && node.getElementType() == TokenType.WHITE_SPACE) { return CharArrayUtil.shiftForwardUntil(text, offset, "\n"); } for (PsiElement parent = element.getParent(); parent != null; parent = parent.getParent()) { ASTNode parentNode = parent.getNode(); if (parentNode == null || parentNode.getStartOffset() != offset) { break; } element = parent; } if (element.getTextOffset() != offset) { return CharArrayUtil.shiftForwardUntil(text, offset, "\n"); } return element.getTextRange().getEndOffset(); }
@Nullable private static TextRange getStartTagRange(ASTNode tagNode) { final ASTNode startTagStart = XmlChildRole.START_TAG_START_FINDER.findChild(tagNode); if (startTagStart == null) { return null; } ASTNode tagName = startTagStart.getTreeNext(); if (tagName == null || tagName.getElementType() != XmlTokenType.XML_NAME) { return null; } ASTNode next = tagName.getTreeNext(); if (next != null && next.getElementType() == XmlTokenType.XML_TAG_END) { tagName = next; } return new TextRange(startTagStart.getStartOffset(), tagName.getTextRange().getEndOffset()); }
public void getLanguagesToInject( @NotNull final MultiHostRegistrar registrar, @NotNull final PsiElement host) { Pair<ASTNode, ASTNode> pair = parseConditionalCommentBoundaries(host); if (pair == null) { return; } final TextRange textRange = host.getTextRange(); final int startOffset = textRange.getStartOffset(); Language language = host.getParent().getLanguage(); ASTNode conditionalStart = pair.first; ASTNode conditionalEnd = pair.second; TextRange range = new TextRange( conditionalStart.getTextRange().getEndOffset() - startOffset, conditionalEnd.getStartOffset() - startOffset); registrar .startInjecting(language) .addPlace(null, null, (PsiLanguageInjectionHost) host, range) .doneInjecting(); }
protected int getOpenQuoteOffset() { PsiElement firstChild = getFirstChild(); if (firstChild instanceof PerlParsableStringWrapperlImpl) { PsiElement realString = firstChild.getFirstChild(); assert realString instanceof PerlStringImplMixin; return ((PerlStringImplMixin) realString).getOpenQuoteOffset(); } ASTNode currentNode = firstChild.getNode(); while (currentNode != null) { if (PerlParserUtil.OPEN_QUOTES.contains(currentNode.getElementType())) return currentNode.getStartOffset(); currentNode = currentNode.getTreeNext(); } throw new RuntimeException( "Unable to find opening quote inside: " + getText() + " " + getContainingFile().getVirtualFile()); }
public int getTextOffset() { final ASTNode name = getNameNode(); return name != null ? name.getStartOffset() : super.getTextOffset(); }
public static void replaceWhiteSpace( final String whiteSpace, final ASTNode leafElement, final IElementType whiteSpaceToken, @Nullable final TextRange textRange) { final CharTable charTable = SharedImplUtil.findCharTableByTree(leafElement); ASTNode treePrev = findPreviousWhiteSpace(leafElement, whiteSpaceToken); if (treePrev == null) { treePrev = getWsCandidate(leafElement); } if (treePrev != null && treePrev.getText().trim().isEmpty() && treePrev.getElementType() != whiteSpaceToken && treePrev.getTextLength() > 0 && !whiteSpace.isEmpty()) { LeafElement whiteSpaceElement = Factory.createSingleLeafElement( treePrev.getElementType(), whiteSpace, charTable, SharedImplUtil.getManagerByTree(leafElement)); ASTNode treeParent = treePrev.getTreeParent(); treeParent.replaceChild(treePrev, whiteSpaceElement); } else { LeafElement whiteSpaceElement = Factory.createSingleLeafElement( whiteSpaceToken, whiteSpace, charTable, SharedImplUtil.getManagerByTree(leafElement)); if (treePrev == null) { if (!whiteSpace.isEmpty()) { addWhiteSpace(leafElement, whiteSpaceElement); } } else { if (!(treePrev.getElementType() == whiteSpaceToken)) { if (!whiteSpace.isEmpty()) { addWhiteSpace(treePrev, whiteSpaceElement); } } else { if (treePrev.getElementType() == whiteSpaceToken) { final CompositeElement treeParent = (CompositeElement) treePrev.getTreeParent(); if (!whiteSpace.isEmpty()) { // LOG.assertTrue(textRange == null || // treeParent.getTextRange().equals(textRange)); treeParent.replaceChild(treePrev, whiteSpaceElement); } else { treeParent.removeChild(treePrev); } // There is a possible case that more than one PSI element is matched by the target text // range. // That is the case, for example, for Python's multi-line expression. It may looks like // below: // import contextlib,\ // math, decimal // Here single range contains two blocks: '\' & '\n '. So, we may want to replace that // range to another text, hence, // we replace last element located there with it ('\n ') and want to remove any // remaining elements ('\'). ASTNode removeCandidate = findPreviousWhiteSpace(whiteSpaceElement, whiteSpaceToken); while (textRange != null && removeCandidate != null && removeCandidate.getStartOffset() >= textRange.getStartOffset()) { treePrev = findPreviousWhiteSpace(removeCandidate, whiteSpaceToken); removeCandidate.getTreeParent().removeChild(removeCandidate); removeCandidate = treePrev; } // treeParent.subtreeChanged(); } } } } }