@Override public void postProcess(PsiElement affectedElement, ReplaceOptions options) { if (!affectedElement.isValid()) { return; } if (options.isToUseStaticImport()) { shortenWithStaticImports(affectedElement, 0, affectedElement.getTextLength()); } if (options.isToShortenFQN()) { final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(affectedElement.getProject()); codeStyleManager.shortenClassReferences(affectedElement, 0, affectedElement.getTextLength()); } }
@Override public TextRange getRangeInElement() { final PsiElement token = getOpToken(); assert token != null; final int offset = token.getStartOffsetInParent(); return new TextRange(offset, offset + token.getTextLength()); }
@Override protected void collectAdditionalElementsToRename(List<Pair<PsiElement, TextRange>> stringUsages) { if (isReplaceAllOccurrences()) { for (E expression : getOccurrences()) { LOG.assertTrue(expression.isValid(), expression.getText()); stringUsages.add( Pair.<PsiElement, TextRange>create( expression, new TextRange(0, expression.getTextLength()))); } } else if (getExpr() != null) { correctExpression(); final E expr = getExpr(); LOG.assertTrue(expr.isValid(), expr.getText()); stringUsages.add( Pair.<PsiElement, TextRange>create(expr, new TextRange(0, expr.getTextLength()))); } final V localVariable = getLocalVariable(); if (localVariable != null) { final PsiElement nameIdentifier = localVariable.getNameIdentifier(); if (nameIdentifier != null) { int length = nameIdentifier.getTextLength(); stringUsages.add( Pair.<PsiElement, TextRange>create(nameIdentifier, new TextRange(0, length))); } } }
public static PsiElement[] parsePattern( Project project, String context, String pattern, FileType fileType, Language language, String extension, boolean physical) { int offset = context.indexOf(PATTERN_PLACEHOLDER); final int patternLength = pattern.length(); final String patternInContext = context.replace(PATTERN_PLACEHOLDER, pattern); final String ext = extension != null ? extension : fileType.getDefaultExtension(); final String name = "__dummy." + ext; final PsiFileFactory factory = PsiFileFactory.getInstance(project); final PsiFile file = language == null ? factory.createFileFromText( name, fileType, patternInContext, LocalTimeCounter.currentTime(), physical, true) : factory.createFileFromText(name, language, patternInContext, physical, true); if (file == null) { return PsiElement.EMPTY_ARRAY; } final List<PsiElement> result = new ArrayList<PsiElement>(); PsiElement element = file.findElementAt(offset); if (element == null) { return PsiElement.EMPTY_ARRAY; } PsiElement topElement = element; element = element.getParent(); while (element != null) { if (element.getTextRange().getStartOffset() == offset && element.getTextLength() <= patternLength) { topElement = element; } element = element.getParent(); } if (topElement instanceof PsiFile) { return topElement.getChildren(); } final int endOffset = offset + patternLength; result.add(topElement); topElement = topElement.getNextSibling(); while (topElement != null && topElement.getTextRange().getEndOffset() <= endOffset) { result.add(topElement); topElement = topElement.getNextSibling(); } return result.toArray(new PsiElement[result.size()]); }
public TextRange getRangeInElement() { final PsiElement element = commandElement(); if (element == null) { return TextRange.from(0, getTextLength()); } return TextRange.from(element.getStartOffsetInParent(), element.getTextLength()); }
public Info(@NotNull PsiElement elementAtPointer) { this( elementAtPointer, Collections.singletonList( new TextRange( elementAtPointer.getTextOffset(), elementAtPointer.getTextOffset() + elementAtPointer.getTextLength()))); }
@Override protected void processIntention(@NotNull PsiElement element, Project project, Editor editor) throws IncorrectOperationException { final GrMethodCallExpression expression = (GrMethodCallExpression) element; final GrClosableBlock block = expression.getClosureArguments()[0]; final GrParameterList parameterList = block.getParameterList(); final GrParameter[] parameters = parameterList.getParameters(); String var; if (parameters.length == 1) { var = parameters[0].getText(); var = StringUtil.replace(var, GrModifier.DEF, ""); } else { var = "it"; } final GrExpression invokedExpression = expression.getInvokedExpression(); GrExpression qualifier = ((GrReferenceExpression) invokedExpression).getQualifierExpression(); final GroovyPsiElementFactory elementFactory = GroovyPsiElementFactory.getInstance(element.getProject()); if (qualifier == null) { qualifier = elementFactory.createExpressionFromText("this"); } StringBuilder builder = new StringBuilder(); builder.append("for (").append(var).append(" in ").append(qualifier.getText()).append(") {\n"); String text = block.getText(); final PsiElement blockArrow = block.getArrow(); int index; if (blockArrow != null) { index = blockArrow.getStartOffsetInParent() + blockArrow.getTextLength(); } else { index = 1; } while (index < text.length() && Character.isWhitespace(text.charAt(index))) index++; text = text.substring(index, text.length() - 1); builder.append(text); builder.append("}"); final GrStatement statement = elementFactory.createStatementFromText(builder.toString()); GrForStatement forStatement = (GrForStatement) expression.replaceWithStatement(statement); final GrForClause clause = forStatement.getClause(); GrVariable variable = clause.getDeclaredVariable(); forStatement = updateReturnStatements(forStatement); if (variable == null) return; if (ApplicationManager.getApplication().isUnitTestMode()) return; final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project); final Document doc = documentManager.getDocument(element.getContainingFile()); if (doc == null) return; documentManager.doPostponedOperationsAndUnblockDocument(doc); editor.getCaretModel().moveToOffset(variable.getTextOffset()); new VariableInplaceRenamer(variable, editor).performInplaceRename(); }
@Override public void visitElement(PsiElement element) { super.visitElement(element); final EquivalenceDescriptorProvider descriptorProvider = EquivalenceDescriptorProvider.getInstance(element); if (descriptorProvider != null) { final EquivalenceDescriptor descriptor1 = descriptorProvider.buildDescriptor(element); final EquivalenceDescriptor descriptor2 = descriptorProvider.buildDescriptor(myGlobalVisitor.getElement()); if (descriptor1 != null && descriptor2 != null) { final boolean result = DuplocatorUtil.match( descriptor1, descriptor2, myGlobalVisitor, Collections.<PsiElementRole>emptySet(), null); myGlobalVisitor.setResult(result); return; } } if (isLiteral(element)) { visitLiteral(element); return; } if (canBePatternVariable(element) && myGlobalVisitor.getMatchContext().getPattern().isRealTypedVar(element) && !shouldIgnoreVarNode(element)) { PsiElement matchedElement = myGlobalVisitor.getElement(); PsiElement newElement = SkippingHandler.skipNodeIfNeccessary(matchedElement); while (newElement != matchedElement) { matchedElement = newElement; newElement = SkippingHandler.skipNodeIfNeccessary(matchedElement); } myGlobalVisitor.setResult(myGlobalVisitor.handleTypedElement(element, matchedElement)); } else if (element instanceof LeafElement) { myGlobalVisitor.setResult(element.getText().equals(myGlobalVisitor.getElement().getText())); } else if (element.getFirstChild() == null && element.getTextLength() == 0) { myGlobalVisitor.setResult(true); } else { PsiElement patternChild = element.getFirstChild(); PsiElement matchedChild = myGlobalVisitor.getElement().getFirstChild(); FilteringNodeIterator patternIterator = new SsrFilteringNodeIterator(patternChild); FilteringNodeIterator matchedIterator = new SsrFilteringNodeIterator(matchedChild); boolean matched = myGlobalVisitor.matchSequentially(patternIterator, matchedIterator); myGlobalVisitor.setResult(matched); } }
/** * There is a following possible use-case: * * <pre> * <ul> * <li> * <b>Particular document has valid text:</b> * <pre> * [caret] * class A { * int foo() { * return 1 */*comment*/ 1; * } * } * </pre> * </li> * <li> * <b>The user starts comment (inserts comment start symbols):</b> * <pre> * /**[caret] * class A { * int foo() { * return 1 */*comment*/ 1; * } * } * </pre> * </li> * <li>The user presses <code>'enter'</code>;</li> * </ul> * </pre> * * We want to understand that doc comment is incomplete now, i.e. don't want to consider '*/' * before '*comment*/ 1;' as comment end. Current approach is to check if next PSI sibling to * the current PSI comment is invalid. This method allows to perform such an examination. */ private static boolean isInvalidPsi(@NotNull PsiElement base) { for (PsiElement current = base.getNextSibling(); current != null; current = current.getNextSibling()) { if (current.getTextLength() != 0) { return current instanceof PsiErrorElement; } } return false; }
protected final void registerError(@NotNull PsiElement location, Object... infos) { if (location.getTextLength() == 0) { return; } final InspectionGadgetsFix[] fixes = createFixes(infos); for (InspectionGadgetsFix fix : fixes) { fix.setOnTheFly(onTheFly); } final String description = inspection.buildErrorString(infos); holder.registerProblem(location, description, fixes); }
@NotNull public static PsiReference[] getReferences(BnfListEntry o) { BnfAttr attr = PsiTreeUtil.getParentOfType(o, BnfAttr.class); if (attr == null || !Comparing.equal(KnownAttribute.METHODS.getName(), attr.getName())) return PsiReference.EMPTY_ARRAY; PsiElement id = o.getId(); BnfLiteralExpression value = o.getLiteralExpression(); if (id == null || value != null) return PsiReference.EMPTY_ARRAY; final String psiImplUtilClass = getRootAttribute(attr, KnownAttribute.PSI_IMPL_UTIL_CLASS); final JavaHelper javaHelper = JavaHelper.getJavaHelper(o); return new PsiReference[] { new PsiPolyVariantReferenceBase<BnfListEntry>( o, TextRange.from(id.getStartOffsetInParent(), id.getTextLength())) { private List<NavigatablePsiElement> getTargetMethods(String methodName) { BnfRule rule = PsiTreeUtil.getParentOfType(getElement(), BnfRule.class); String mixinClass = rule == null ? null : getAttribute(rule, KnownAttribute.MIXIN); List<NavigatablePsiElement> implMethods = findRuleImplMethods(javaHelper, psiImplUtilClass, methodName, rule); if (!implMethods.isEmpty()) return implMethods; List<NavigatablePsiElement> mixinMethods = javaHelper.findClassMethods( mixinClass, JavaHelper.MethodType.INSTANCE, methodName, -1); return ContainerUtil.concat(implMethods, mixinMethods); } @NotNull @Override public ResolveResult[] multiResolve(boolean b) { return PsiElementResolveResult.createResults(getTargetMethods(getElement().getText())); } @NotNull @Override public Object[] getVariants() { List<LookupElement> list = ContainerUtil.newArrayList(); for (NavigatablePsiElement element : getTargetMethods("*")) { list.add(LookupElementBuilder.createWithIcon((PsiNamedElement) element)); } return ArrayUtil.toObjectArray(list); } @Override public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException { BnfListEntry element = getElement(); PsiElement id = ObjectUtils.assertNotNull(element.getId()); id.replace(BnfElementFactory.createLeafFromText(element.getProject(), newElementName)); return element; } } }; }
private void appendAdditionalElement( Collection<Pair<PsiElement, TextRange>> stringUsages, PsiNamedElement variable, PsiElement element) { if (element != variable && element instanceof PsiNameIdentifierOwner && !notSameFile(null, element.getContainingFile())) { final PsiElement identifier = ((PsiNameIdentifierOwner) element).getNameIdentifier(); if (identifier != null) { stringUsages.add(Pair.create(identifier, new TextRange(0, identifier.getTextLength()))); } } }
protected void updateTitle(@Nullable V variable, String value) { if (variable == null) return; final String variableText = variable.getText(); final PsiElement identifier = variable.getNameIdentifier(); if (identifier != null) { final int startOffsetInParent = identifier.getStartOffsetInParent(); setPreviewText( variableText.substring(0, startOffsetInParent) + value + variableText.substring(startOffsetInParent + identifier.getTextLength())); } else { setPreviewText(variableText.replaceFirst(variable.getName(), value)); } revalidate(); }
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(); }
public static void sendBeforeChildrenChangeEvent( @NotNull PsiManagerImpl manager, @NotNull PsiElement scope, boolean isGenericChange) { if (!scope.isPhysical()) { manager.beforeChange(false); return; } PsiTreeChangeEventImpl event = new PsiTreeChangeEventImpl(manager); event.setParent(scope); event.setFile(scope.getContainingFile()); TextRange range = scope.getTextRange(); event.setOffset(range == null ? 0 : range.getStartOffset()); event.setOldLength(scope.getTextLength()); // the "generic" event is being sent on every PSI change. It does not carry any specific info // except the fact that "something has changed" event.setGenericChange(isGenericChange); manager.beforeChildrenChange(event); }
@Override public String getUnescapedText(@NotNull final PsiElement injectedNode) { final StringBuilder text = new StringBuilder(injectedNode.getTextLength()); // gather text from (patched) leaves injectedNode.accept( new PsiRecursiveElementWalkingVisitor() { @Override public void visitElement(PsiElement element) { String leafText = InjectedLanguageUtil.getUnescapedLeafText(element, false); if (leafText != null) { text.append(leafText); return; } super.visitElement(element); } }); return text.toString(); }
@NotNull public PsiReference[] getReferencesByElement( @NotNull PsiElement element, @NotNull final ProcessingContext context) { boolean soft = myDefaultSoft; if (element instanceof XmlAttributeValue) { final XmlAttribute xmlAttribute = (XmlAttribute) element.getParent(); if (element.getTextLength() < 2) { return PsiReference.EMPTY_ARRAY; } final XmlTag tag = xmlAttribute.getParent(); String value = null; String bundle = tag.getAttributeValue("bundle"); if ("key".equals(xmlAttribute.getName())) { value = xmlAttribute.getValue(); } else if ("groupKey".equals(xmlAttribute.getName())) { value = xmlAttribute.getValue(); final String groupBundle = tag.getAttributeValue("groupBundle"); if (groupBundle != null) { bundle = groupBundle; } } if (value != null) { return new PsiReference[] { new PropertyReference(value, xmlAttribute.getValueElement(), bundle, soft) { @Override protected List<PropertiesFile> retrievePropertyFilesByBundleName( String bundleName, PsiElement element) { final Project project = element.getProject(); return PropertiesReferenceManager.getInstance(project) .findPropertiesFiles( GlobalSearchScope.projectScope(project), bundleName, BundleNameEvaluator.DEFAULT); } } }; } } return PsiReference.EMPTY_ARRAY; }
@Override public String getUnescapedText(@NotNull final PsiElement injectedNode) { final StringBuilder text = new StringBuilder(injectedNode.getTextLength()); // gather text from (patched) leaves injectedNode.accept( new PsiRecursiveElementWalkingVisitor() { @Override public void visitElement(PsiElement element) { String unescaped = element.getCopyableUserData(UNESCAPED_TEXT); if (unescaped != null) { text.append(unescaped); return; } if (element.getFirstChild() == null) { text.append(element.getText()); return; } super.visitElement(element); } }); return text.toString(); }
@NotNull public GrStatement addStatementBefore(@NotNull GrStatement element, @Nullable GrStatement anchor) throws IncorrectOperationException { if (anchor == null && getRBrace() == null) { throw new IncorrectOperationException(); } if (anchor != null && !this.equals(anchor.getParent())) { throw new IncorrectOperationException(); } final LeafElement nls = Factory.createSingleLeafElement(GroovyTokenTypes.mNLS, "\n", 0, 1, null, getManager()); PsiElement actualAnchor = anchor == null ? getRBrace() : anchor; if (mayUseNewLinesAsSeparators()) { PsiElement prev = actualAnchor.getPrevSibling(); if (prev instanceof GrParameterList && prev.getTextLength() == 0 && prev.getPrevSibling() != null) { prev = prev.getPrevSibling(); } if (!PsiUtil.isLineFeed(prev)) { addBefore(nls.getPsi(), actualAnchor); } } element = (GrStatement) addBefore(element, actualAnchor); if (mayUseNewLinesAsSeparators()) { addBefore(nls.getPsi(), actualAnchor); } else { addBefore( Factory.createSingleLeafElement(GroovyTokenTypes.mNLS, "\n", 0, 1, null, getManager()) .getPsi(), actualAnchor); } return element; }
public void visitLiteral(PsiElement literal) { final PsiElement l2 = myGlobalVisitor.getElement(); MatchingHandler handler = (MatchingHandler) literal.getUserData(CompiledPattern.HANDLER_KEY); if (handler instanceof SubstitutionHandler) { int offset = 0; int length = l2.getTextLength(); final String text = l2.getText(); if (length > 2 && (text.charAt(0) == '"' && text.charAt(length - 1) == '"') || (text.charAt(0) == '\'' && text.charAt(length - 1) == '\'')) { length--; offset++; } myGlobalVisitor.setResult( ((SubstitutionHandler) handler) .handle(l2, offset, length, myGlobalVisitor.getMatchContext())); } else if (handler != null) { myGlobalVisitor.setResult(handler.match(literal, l2, myGlobalVisitor.getMatchContext())); } else { myGlobalVisitor.setResult(literal.textMatches(l2)); } }
@Override protected void checkTag( @NotNull final XmlTag tag, @NotNull final ProblemsHolder holder, final boolean isOnTheFly) { if (!(tag instanceof HtmlTag) || !XmlHighlightVisitor.shouldBeValidated(tag) || isInSpecialHtml5Namespace(tag)) { return; } XmlElementDescriptor descriptorFromContext = XmlUtil.getDescriptorFromContext(tag); PsiElement parent = tag.getParent(); XmlElementDescriptor parentDescriptor = parent instanceof XmlTag ? ((XmlTag) parent).getDescriptor() : null; XmlElementDescriptor ownDescriptor = isAbstractDescriptor(descriptorFromContext) ? tag.getDescriptor() : descriptorFromContext; if (isAbstractDescriptor(ownDescriptor) || (parentDescriptor instanceof HtmlElementDescriptorImpl && ownDescriptor instanceof HtmlElementDescriptorImpl && isAbstractDescriptor(descriptorFromContext))) { final String name = tag.getName(); if (!isCustomValuesEnabled() || !isCustomValue(name)) { final AddCustomTagOrAttributeIntentionAction action = new AddCustomTagOrAttributeIntentionAction( TAG_KEY, name, XmlEntitiesInspection.UNKNOWN_TAG); // todo: support "element is not allowed" message for html5 // some tags in html5 cannot be found in xhtml5.xsd if they are located in incorrect // context, so they get any-element descriptor (ex. "canvas: tag) final String message = isAbstractDescriptor(ownDescriptor) ? XmlErrorMessages.message("unknown.html.tag", name) : XmlErrorMessages.message("element.is.not.allowed.here", name); final PsiElement startTagName = XmlTagUtil.getStartTagNameElement(tag); assert startTagName != null; final PsiElement endTagName = XmlTagUtil.getEndTagNameElement(tag); List<LocalQuickFix> quickfixes = new ArrayList<LocalQuickFix>(); quickfixes.add(action); if (isOnTheFly) { ContainerUtil.addIfNotNull( CreateNSDeclarationIntentionFix.createFix(startTagName, ""), quickfixes); } if (HtmlUtil.isHtml5Tag(name) && !HtmlUtil.hasNonHtml5Doctype(tag)) { quickfixes.add(new SwitchToHtml5WithHighPriorityAction()); } ProblemHighlightType highlightType = tag.getContainingFile().getContext() == null ? ProblemHighlightType.GENERIC_ERROR_OR_WARNING : ProblemHighlightType.INFORMATION; if (startTagName.getTextLength() > 0) { holder.registerProblem( startTagName, message, highlightType, quickfixes.toArray(new LocalQuickFix[quickfixes.size()])); } if (endTagName != null) { holder.registerProblem( endTagName, message, highlightType, quickfixes.toArray(new LocalQuickFix[quickfixes.size()])); } } } }
private static void divideInsideAndOutside( @NotNull PsiFile root, int startOffset, int endOffset, @NotNull TextRange range, @NotNull List<PsiElement> inside, @NotNull List<PsiElement> outside, boolean includeParents) { final int currentOffset = root.getTextRange().getStartOffset(); final Condition<PsiElement>[] filters = Extensions.getExtensions(CollectHighlightsUtil.EP_NAME); int offset = currentOffset; final TIntStack starts = new TIntStack(STARTING_TREE_HEIGHT); starts.push(startOffset); final Stack<PsiElement> elements = new Stack<PsiElement>(STARTING_TREE_HEIGHT); final Stack<PsiElement> children = new Stack<PsiElement>(STARTING_TREE_HEIGHT); PsiElement element = root; PsiElement child = PsiUtilBase.NULL_PSI_ELEMENT; while (true) { ProgressManager.checkCanceled(); for (Condition<PsiElement> filter : filters) { if (!filter.value(element)) { assert child == PsiUtilBase.NULL_PSI_ELEMENT; child = null; // do not want to process children break; } } boolean startChildrenVisiting; if (child == PsiUtilBase.NULL_PSI_ELEMENT) { startChildrenVisiting = true; child = element.getFirstChild(); } else { startChildrenVisiting = false; } if (child == null) { if (startChildrenVisiting) { // leaf element offset += element.getTextLength(); } int start = starts.pop(); if (startOffset <= start && offset <= endOffset) { if (range.containsRange(start, offset)) { inside.add(element); } else { outside.add(element); } } if (elements.isEmpty()) break; element = elements.pop(); child = children.pop(); } else { // composite element if (offset > endOffset) break; children.push(child.getNextSibling()); starts.push(offset); elements.push(element); element = child; child = PsiUtilBase.NULL_PSI_ELEMENT; } } if (includeParents) { PsiElement parent = !outside.isEmpty() ? outside.get(outside.size() - 1) : !inside.isEmpty() ? inside.get(inside.size() - 1) : CollectHighlightsUtil.findCommonParent(root, startOffset, endOffset); while (parent != null && parent != root) { parent = parent.getParent(); if (parent != null) outside.add(parent); } } }
public boolean textMatches(@NotNull PsiElement element) { return getTextLength() == element.getTextLength() && textMatches(element.getText()); }
public static boolean areParenthesesNecessary( @NotNull JetExpression innerExpression, @NotNull JetExpression currentInner, @NotNull JetExpression parentExpression) { if (parentExpression instanceof JetParenthesizedExpression || innerExpression instanceof JetParenthesizedExpression) { return false; } if (parentExpression instanceof JetWhenExpression || innerExpression instanceof JetWhenExpression) { return false; } if (innerExpression instanceof JetIfExpression) { PsiElement current = parentExpression; while (!(current instanceof JetBlockExpression || current instanceof JetDeclaration || current instanceof JetStatementExpression)) { if (current.getTextRange().getEndOffset() != currentInner.getTextRange().getEndOffset()) { return current.getText().charAt(current.getTextLength() - 1) != ')'; // if current expression is "guarded" by parenthesis, no extra parenthesis is // necessary } current = current.getParent(); } } IElementType innerOperation = getOperation(innerExpression); IElementType parentOperation = getOperation(parentExpression); // 'return (@label{...})' case if (parentExpression instanceof JetReturnExpression && innerOperation == JetTokens.LABEL_IDENTIFIER) { return true; } // '(x: Int) < y' case if (innerExpression instanceof JetBinaryExpressionWithTypeRHS && parentOperation == JetTokens.LT) { return true; } int innerPriority = getPriority(innerExpression); int parentPriority = getPriority(parentExpression); if (innerPriority == parentPriority) { if (parentExpression instanceof JetBinaryExpression) { if (innerOperation == JetTokens.ANDAND || innerOperation == JetTokens.OROR) { return false; } return ((JetBinaryExpression) parentExpression).getRight() == currentInner; } // '-(-x)' case if (parentExpression instanceof JetPrefixExpression && innerExpression instanceof JetPrefixExpression) { return innerOperation == parentOperation && (innerOperation == JetTokens.PLUS || innerOperation == JetTokens.MINUS); } return false; } return innerPriority < parentPriority; }
@Override public TextRange getRangeInElement() { final PsiElement opToken = getOperationToken(); final int offset = opToken.getStartOffsetInParent(); return new TextRange(offset, offset + opToken.getTextLength()); }