private static boolean navigateInCurrentEditor( @NotNull PsiElement element, @NotNull PsiFile currentFile, @NotNull Editor currentEditor) { if (element.getContainingFile() == currentFile) { int offset = element.getTextOffset(); PsiElement leaf = currentFile.findElementAt(offset); // check that element is really physically inside the file // there are fake elements with custom navigation (e.g. opening URL in browser) that override // getContainingFile for various reasons if (leaf != null && PsiTreeUtil.isAncestor(element, leaf, false)) { Project project = element.getProject(); CommandProcessor.getInstance() .executeCommand( project, () -> { IdeDocumentHistory.getInstance(project).includeCurrentCommandAsNavigation(); new OpenFileDescriptor( project, currentFile.getViewProvider().getVirtualFile(), offset) .navigateIn(currentEditor); }, "", null); return true; } } return false; }
@Nullable private Navigatable getSelectedNavigatable( final CommonProblemDescriptor descriptor, final PsiElement psiElement) { if (descriptor instanceof ProblemDescriptorBase) { Navigatable navigatable = ((ProblemDescriptorBase) descriptor).getNavigatable(); if (navigatable != null) { return navigatable; } } if (psiElement == null || !psiElement.isValid()) return null; PsiFile containingFile = psiElement.getContainingFile(); VirtualFile virtualFile = containingFile == null ? null : containingFile.getVirtualFile(); if (virtualFile != null) { int startOffset = psiElement.getTextOffset(); if (descriptor instanceof ProblemDescriptorBase) { final TextRange textRange = ((ProblemDescriptorBase) descriptor).getTextRangeForNavigation(); if (textRange != null) { if (virtualFile instanceof VirtualFileWindow) { virtualFile = ((VirtualFileWindow) virtualFile).getDelegate(); } startOffset = textRange.getStartOffset(); } } return new OpenFileDescriptor(myProject, virtualFile, startOffset); } return null; }
public Info(@NotNull PsiElement elementAtPointer) { this( elementAtPointer, Collections.singletonList( new TextRange( elementAtPointer.getTextOffset(), elementAtPointer.getTextOffset() + elementAtPointer.getTextLength()))); }
public static void addImportIfNeeded(@NotNull PsiClass aClass, @NotNull PsiElement context) { final PsiFile file = context.getContainingFile(); if (!(file instanceof PsiJavaFile)) { return; } final PsiJavaFile javaFile = (PsiJavaFile) file; final PsiClass outerClass = aClass.getContainingClass(); if (outerClass == null) { if (PsiTreeUtil.isAncestor(javaFile, aClass, true)) { return; } } else if (PsiTreeUtil.isAncestor(outerClass, context, true)) { final PsiElement brace = outerClass.getLBrace(); if (brace != null && brace.getTextOffset() < context.getTextOffset()) { return; } } final String qualifiedName = aClass.getQualifiedName(); if (qualifiedName == null) { return; } final PsiImportList importList = javaFile.getImportList(); if (importList == null) { return; } final String containingPackageName = javaFile.getPackageName(); @NonNls final String packageName = ClassUtil.extractPackageName(qualifiedName); if (containingPackageName.equals(packageName) || importList.findSingleClassImportStatement(qualifiedName) != null) { return; } if (importList.findOnDemandImportStatement(packageName) != null && !hasDefaultImportConflict(qualifiedName, javaFile) && !hasOnDemandImportConflict(qualifiedName, javaFile)) { return; } final Project project = importList.getProject(); final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project); final PsiElementFactory elementFactory = psiFacade.getElementFactory(); final PsiImportStatement importStatement = elementFactory.createImportStatement(aClass); importList.add(importStatement); }
/** * Try to visit possible class name for PsiElements with text like "Foo\|Bar", "Foo|\Bar", * "\Foo|\Bar" Cursor must have position in PsiElement * * @param psiElement the element context, cursor should be in it * @param cursorOffset current cursor editor eg from completion context * @param visitor callback on matching class */ public static void visitNamespaceClassForCompletion( PsiElement psiElement, int cursorOffset, ClassForCompletionVisitor visitor) { int cursorOffsetClean = cursorOffset - psiElement.getTextOffset(); if (cursorOffsetClean < 1) { return; } String content = psiElement.getText(); int length = content.length(); if (!(length >= cursorOffsetClean)) { return; } String beforeCursor = content.substring(0, cursorOffsetClean); boolean isValid; // espend\|Container, espend\Cont|ainer <- fallback to last full namespace // espend|\Container <- only on known namespace "espend" String namespace = beforeCursor; // if no backslash or its equal in first position, fallback on namespace completion int lastSlash = beforeCursor.lastIndexOf("\\"); if (lastSlash <= 0) { isValid = PhpIndexUtil.hasNamespace(psiElement.getProject(), beforeCursor); } else { isValid = true; namespace = beforeCursor.substring(0, lastSlash); } if (!isValid) { return; } // format namespaces and add prefix for fluent completion String prefix = ""; if (namespace.startsWith("\\")) { prefix = "\\"; } else { namespace = "\\" + namespace; } // search classes in current namespace and child namespaces for (PhpClass phpClass : PhpIndexUtil.getPhpClassInsideNamespace(psiElement.getProject(), namespace)) { String presentableFQN = phpClass.getPresentableFQN(); if (presentableFQN != null && fr.adrienbrault.idea.symfony2plugin.util.StringUtils.startWithEqualClassname( presentableFQN, beforeCursor)) { visitor.visit(phpClass, presentableFQN, prefix); } } }
private static void doAddImport(GoFile file, Editor editor, String pathToImport) { GoImportDeclarations[] ids = file.getImportDeclarations(); Document document = editor.getDocument(); if (ids.length == 0) { addImportUnderPackage(file, document, pathToImport); return; } GoImportDeclarations importDeclarations = ids[ids.length - 1]; GoImportDeclaration[] imports = importDeclarations.getDeclarations(); if (imports.length == 0) { addImportUnderPackage(file, document, pathToImport); return; } GoImportDeclaration lastImport = imports[imports.length - 1]; PsiElement lastChild = getPrevSiblingIfItsWhiteSpaceOrComment(importDeclarations.getLastChild()); if (lastChild == null) { addImportUnderPackage(file, document, pathToImport); return; } if (")".equals(lastChild.getText())) { document.insertString(lastChild.getTextOffset(), "\"" + pathToImport + "\"\n"); int line = document.getLineNumber(lastChild.getTextOffset()); reformatLines(file, editor, line, line); } else { String oldImport = lastImport.getText(); int start = lastImport.getTextOffset(); int end = start + lastImport.getTextLength(); String declarations = String.format("(\n%s\n\"%s\"\n)", oldImport, pathToImport); document.replaceString(start, end, declarations); reformatPositions(file, start, start + declarations.length()); } }
@Override protected boolean isInContext(PsiElement element) { PsiFile file = element.getContainingFile(); if (file != null && ErlangParserUtil.isConsole(file)) return false; int offset = element.getTextOffset(); if (offset > 0 && file != null) { PsiElement prev = file.findElementAt(offset - 1); if (ErlangPsiImplUtil.is(prev, ErlangTypes.ERL_DOT)) return false; } PsiElement parent = element.getParent(); return parent instanceof ErlangFile || parent instanceof PsiErrorElement && parent.getParent() instanceof ErlangFile; }
private void highlightUsages() { Editor e = getEditor(); if (e == null) return; boolean foundVisibleElement = false; int offset = Integer.MAX_VALUE; for (SearchResult sr : searchResults.values()) { Map<Node, PsiElement> match = sr.getMatch(); TextAttributes textAttributes = createUniqueTextAttrsFor(sr); PsiElement targetElement = match.get(pattern.getTheOne()); if (!foundVisibleElement && insideVisibleArea(e, targetElement)) { foundVisibleElement = true; } if (!foundVisibleElement && targetElement.getTextOffset() < offset) { offset = targetElement.getTextOffset(); } for (PsiElement element : match.values()) { TextAttributes attributes = textAttributes; if (element == targetElement) { attributes = MAIN_TARGET_ATTRIBUTES; } if (element instanceof XmlTag) { element = element.getFirstChild().getNextSibling(); } TextRange textRange = element.getTextRange(); e.getMarkupModel() .addRangeHighlighter( textRange.getStartOffset(), textRange.getEndOffset(), HighlighterLayer.SELECTION + 1, attributes, HighlighterTargetArea.EXACT_RANGE); } } if (!foundVisibleElement && offset != Integer.MAX_VALUE) { e.getScrollingModel().scrollTo(e.offsetToLogicalPosition(offset), ScrollType.CENTER); } }
@Override public void actionPerformed(AnActionEvent e) { PsiElement element = myElements[myIndex]; PsiElement navigationElement = element.getNavigationElement(); PsiFile file = getContainingFile(navigationElement); if (file == null) return; VirtualFile virtualFile = file.getVirtualFile(); if (virtualFile == null) return; Project project = element.getProject(); FileEditorManagerEx fileEditorManager = FileEditorManagerEx.getInstanceEx(project); OpenFileDescriptor descriptor = new OpenFileDescriptor(project, virtualFile, navigationElement.getTextOffset()); fileEditorManager.openTextEditor(descriptor, myFocusEditor); }
private static void shortenWithStaticImports( PsiElement affectedElement, int startOffset, int endOffset) { final int elementOffset = affectedElement.getTextOffset(); final int finalStartOffset = startOffset + elementOffset; final int finalEndOffset = endOffset + elementOffset; final List<PsiReferenceExpression> references = new ArrayList<PsiReferenceExpression>(); final JavaRecursiveElementVisitor collector = new JavaRecursiveElementVisitor() { @Override public void visitReferenceExpression(PsiReferenceExpression expression) { final int offset = expression.getTextOffset(); if (offset > finalEndOffset) { return; } super.visitReferenceExpression(expression); if (offset + expression.getTextLength() < finalStartOffset) if (expression.getQualifierExpression() == null) { return; } references.add(expression); } }; affectedElement.accept(collector); for (PsiReferenceExpression expression : references) { final PsiElement target = expression.resolve(); if (!(target instanceof PsiMember)) { continue; } final PsiMember member = (PsiMember) target; final PsiClass containingClass = member.getContainingClass(); if (containingClass == null) { continue; } final String className = containingClass.getQualifiedName(); if (className == null) { continue; } final String name = member.getName(); if (name == null) { continue; } if (ImportUtils.addStaticImport(className, name, expression)) { final PsiExpression qualifierExpression = expression.getQualifierExpression(); if (qualifierExpression != null) { qualifierExpression.delete(); } } } }
private static boolean shouldSkipLine(final PsiFile file, Document doc, int line) { final int start = doc.getLineStartOffset(line); final int end = doc.getLineEndOffset(line); final int _start = CharArrayUtil.shiftForward(doc.getCharsSequence(), start, " \n\t"); if (_start >= end) { return true; } TextRange alreadyChecked = null; for (PsiElement elem = file.findElementAt(_start); elem != null && elem.getTextOffset() <= end && (alreadyChecked == null || !alreadyChecked.contains(elem.getTextRange())); elem = elem.getNextSibling()) { for (PsiElement _elem = elem; _elem.getTextOffset() >= _start; _elem = _elem.getParent()) { alreadyChecked = _elem.getTextRange(); if (_elem instanceof PsiDeclarationStatement) { final PsiElement[] declared = ((PsiDeclarationStatement) _elem).getDeclaredElements(); for (PsiElement declaredElement : declared) { if (declaredElement instanceof PsiVariable) { return false; } } } if (_elem instanceof PsiJavaCodeReferenceElement) { final PsiElement resolved = ((PsiJavaCodeReferenceElement) _elem).resolve(); if (resolved instanceof PsiVariable) { return false; } } } } return true; }
@Override public Result preprocessEnter( @NotNull final PsiFile file, @NotNull final Editor editor, @NotNull final Ref<Integer> caretOffsetRef, @NotNull final Ref<Integer> caretAdvance, @NotNull final DataContext dataContext, final EditorActionHandler originalHandler) { int caretOffset = caretOffsetRef.get().intValue(); PsiElement psiAtOffset = file.findElementAt(caretOffset); if (psiAtOffset != null && psiAtOffset.getTextOffset() < caretOffset) { ASTNode token = psiAtOffset.getNode(); Document document = editor.getDocument(); CharSequence text = document.getText(); final Language language = psiAtOffset.getLanguage(); final Commenter languageCommenter = LanguageCommenters.INSTANCE.forLanguage(language); final CodeDocumentationAwareCommenter commenter = languageCommenter instanceof CodeDocumentationAwareCommenter ? (CodeDocumentationAwareCommenter) languageCommenter : null; if (commenter != null && token.getElementType() == commenter.getLineCommentTokenType()) { final int offset = CharArrayUtil.shiftForward(text, caretOffset, " \t"); if (offset < document.getTextLength() && text.charAt(offset) != '\n') { String prefix = commenter.getLineCommentPrefix(); assert prefix != null : "Line Comment type is set but Line Comment Prefix is null!"; if (!StringUtil.startsWith(text, offset, prefix)) { if (text.charAt(caretOffset) != ' ' && !prefix.endsWith(" ")) { prefix += " "; } document.insertString(caretOffset, prefix); return Result.Default; } else { int afterPrefix = offset + prefix.length(); if (afterPrefix < document.getTextLength() && text.charAt(afterPrefix) != ' ') { document.insertString(afterPrefix, " "); // caretAdvance.set(0); } caretOffsetRef.set(offset); } return Result.Default; } } } return Result.Continue; }
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 List<PsiLambdaExpression> collectLambdas( @NotNull SourcePosition position, final boolean onlyOnTheLine) { ApplicationManager.getApplication().assertReadAccessAllowed(); PsiFile file = position.getFile(); final int line = position.getLine(); final Document document = PsiDocumentManager.getInstance(file.getProject()).getDocument(file); if (document == null || line >= document.getLineCount()) { return Collections.emptyList(); } PsiElement element = position.getElementAt(); final TextRange lineRange = DocumentUtil.getLineTextRange(document, line); do { PsiElement parent = element.getParent(); if (parent == null || (parent.getTextOffset() < lineRange.getStartOffset())) { break; } element = parent; } while (true); final List<PsiLambdaExpression> lambdas = new ArrayList<PsiLambdaExpression>(3); final PsiElementVisitor lambdaCollector = new JavaRecursiveElementVisitor() { @Override public void visitLambdaExpression(PsiLambdaExpression expression) { super.visitLambdaExpression(expression); if (!onlyOnTheLine || getFirstElementOnTheLine(expression, document, line) != null) { lambdas.add(expression); } } }; element.accept(lambdaCollector); // add initial lambda if we're inside already PsiElement method = getContainingMethod(element); if (method instanceof PsiLambdaExpression) { lambdas.add((PsiLambdaExpression) method); } for (PsiElement sibling = getNextElement(element); sibling != null; sibling = getNextElement(sibling)) { if (!intersects(lineRange, sibling)) { break; } sibling.accept(lambdaCollector); } return lambdas; }
private boolean hasMethodOrFieldsAtLine( @NotNull Document document, @NotNull PsiFile file, int lineNumber) { int lineStartOffset = document.getLineStartOffset(lineNumber); int lineEndOffset = document.getLineEndOffset(lineNumber); Class<? extends PsiElement>[] elementsLookingFor = new Class[] {PsiMethod.class, PsiField.class}; for (int i = lineStartOffset; i < lineEndOffset; ++i) { for (Class<? extends PsiElement> elementClass : elementsLookingFor) { PsiElement psiElement = PsiTreeUtil.findElementOfClassAtOffset(file, i, elementClass, true); if (psiElement != null && document.getLineNumber(psiElement.getTextOffset()) == lineNumber) { return true; } } } return false; }
/** * 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(); }
@NotNull @Override public ThreeState shouldSkipAutopopup( @NotNull PsiElement contextElement, @NotNull PsiFile psiFile, int offset) { if (PsiUtil.isLeafElementOfType(contextElement, TokenSets.STRING_LITERALS)) { @SuppressWarnings("ConstantConditions") PsiElement parent = contextElement.getParent(); if (parent != null) { for (PsiReference reference : parent.getReferences()) { if (!reference.isSoft() && reference .getRangeInElement() .shiftRight(parent.getTextOffset()) .containsOffset(offset)) { return ThreeState.NO; } } } return ThreeState.YES; } return ThreeState.UNSURE; }
/** Should be invoked in command and write action */ @SuppressWarnings({"HardCodedStringLiteral"}) public static void generateDataBindingMethods(final WizardData data) throws MyException { if (data.myBindToNewBean) { data.myBeanClass = createBeanClass(data); } else { if (!CommonRefactoringUtil.checkReadOnlyStatus( data.myBeanClass.getProject(), data.myBeanClass)) { return; } } final HashMap<String, String> binding2beanGetter = new HashMap<String, String>(); final HashMap<String, String> binding2beanSetter = new HashMap<String, String>(); final FormProperty2BeanProperty[] bindings = data.myBindings; for (final FormProperty2BeanProperty form2bean : bindings) { if (form2bean == null || form2bean.myBeanProperty == null) { continue; } // check that bean contains the property, and if not, try to add the property to the bean { final String setterName = PropertyUtil.suggestSetterName(form2bean.myBeanProperty.myName); final PsiMethod[] methodsByName = data.myBeanClass.findMethodsByName(setterName, true); if (methodsByName.length < 1) { // bean does not contain this property // try to add... LOG.assertTrue( !data.myBindToNewBean); // just generated bean class should contain all necessary // properties if (!data.myBeanClass.isWritable()) { throw new MyException( "Cannot add property to non writable class " + data.myBeanClass.getQualifiedName()); } final StringBuffer membersBuffer = new StringBuffer(); final StringBuffer methodsBuffer = new StringBuffer(); final Project project = data.myBeanClass.getProject(); final CodeStyleManager formatter = CodeStyleManager.getInstance(project); final JavaCodeStyleManager styler = JavaCodeStyleManager.getInstance(project); generateProperty( styler, form2bean.myBeanProperty.myName, form2bean.myBeanProperty.myType, membersBuffer, methodsBuffer); final PsiClass fakeClass; try { fakeClass = JavaPsiFacade.getInstance(data.myBeanClass.getProject()) .getElementFactory() .createClassFromText(membersBuffer.toString() + methodsBuffer.toString(), null); final PsiField[] fields = fakeClass.getFields(); { final PsiElement result = data.myBeanClass.add(fields[0]); styler.shortenClassReferences(result); formatter.reformat(result); } final PsiMethod[] methods = fakeClass.getMethods(); { final PsiElement result = data.myBeanClass.add(methods[0]); styler.shortenClassReferences(result); formatter.reformat(result); } { final PsiElement result = data.myBeanClass.add(methods[1]); styler.shortenClassReferences(result); formatter.reformat(result); } } catch (IncorrectOperationException e) { throw new MyException(e.getMessage()); } } } final PsiMethod propertySetter = PropertyUtil.findPropertySetter( data.myBeanClass, form2bean.myBeanProperty.myName, false, true); final PsiMethod propertyGetter = PropertyUtil.findPropertyGetter( data.myBeanClass, form2bean.myBeanProperty.myName, false, true); if (propertyGetter == null) { // todo continue; } if (propertySetter == null) { // todo continue; } final String binding = form2bean.myFormProperty.getLwComponent().getBinding(); binding2beanGetter.put(binding, propertyGetter.getName()); binding2beanSetter.put(binding, propertySetter.getName()); } final String dataBeanClassName = data.myBeanClass.getQualifiedName(); final LwRootContainer[] rootContainer = new LwRootContainer[1]; final FormProperty[] formProperties = exposeForm(data.myProject, data.myFormFile, rootContainer); final StringBuffer getDataBody = new StringBuffer(); final StringBuffer setDataBody = new StringBuffer(); final StringBuffer isModifiedBody = new StringBuffer(); // iterate exposed formproperties for (final FormProperty formProperty : formProperties) { final String binding = formProperty.getLwComponent().getBinding(); if (!binding2beanGetter.containsKey(binding)) { continue; } getDataBody.append("data."); getDataBody.append(binding2beanSetter.get(binding)); getDataBody.append("("); getDataBody.append(binding); getDataBody.append("."); getDataBody.append(formProperty.getComponentPropertyGetterName()); getDataBody.append("());\n"); setDataBody.append(binding); setDataBody.append("."); setDataBody.append(formProperty.getComponentPropertySetterName()); setDataBody.append("(data."); setDataBody.append(binding2beanGetter.get(binding)); setDataBody.append("());\n"); final String propertyClassName = formProperty.getComponentPropertyClassName(); if ("boolean".equals(propertyClassName)) { isModifiedBody.append("if ("); // isModifiedBody.append(binding); isModifiedBody.append("."); isModifiedBody.append(formProperty.getComponentPropertyGetterName()); isModifiedBody.append("()"); // isModifiedBody.append("!= "); // isModifiedBody.append("data."); isModifiedBody.append(binding2beanGetter.get(binding)); isModifiedBody.append("()"); // isModifiedBody.append(") return true;\n"); } else { isModifiedBody.append("if ("); // isModifiedBody.append(binding); isModifiedBody.append("."); isModifiedBody.append(formProperty.getComponentPropertyGetterName()); isModifiedBody.append("()"); // isModifiedBody.append("!= null ? "); // isModifiedBody.append("!"); // isModifiedBody.append(binding); isModifiedBody.append("."); isModifiedBody.append(formProperty.getComponentPropertyGetterName()); isModifiedBody.append("()"); // isModifiedBody.append(".equals("); // isModifiedBody.append("data."); isModifiedBody.append(binding2beanGetter.get(binding)); isModifiedBody.append("()"); isModifiedBody.append(") : "); // isModifiedBody.append("data."); isModifiedBody.append(binding2beanGetter.get(binding)); isModifiedBody.append("()"); isModifiedBody.append("!= null"); // isModifiedBody.append(") return true;\n"); } } isModifiedBody.append("return false;\n"); final String textOfMethods = "public void setData(" + dataBeanClassName + " data){\n" + setDataBody.toString() + "}\n" + "\n" + "public void getData(" + dataBeanClassName + " data){\n" + getDataBody.toString() + "}\n" + "\n" + "public boolean isModified(" + dataBeanClassName + " data){\n" + isModifiedBody.toString() + "}\n"; // put them to the bound class final Module module = ModuleUtil.findModuleForFile(data.myFormFile, data.myProject); LOG.assertTrue(module != null); final PsiClass boundClass = FormEditingUtil.findClassToBind(module, rootContainer[0].getClassToBind()); LOG.assertTrue(boundClass != null); if (!CommonRefactoringUtil.checkReadOnlyStatus(module.getProject(), boundClass)) { return; } // todo: check that this method does not exist yet final PsiClass fakeClass; try { fakeClass = JavaPsiFacade.getInstance(data.myProject) .getElementFactory() .createClassFromText(textOfMethods, null); final PsiMethod methodSetData = fakeClass.getMethods()[0]; final PsiMethod methodGetData = fakeClass.getMethods()[1]; final PsiMethod methodIsModified = fakeClass.getMethods()[2]; final PsiMethod existing1 = boundClass.findMethodBySignature(methodSetData, false); final PsiMethod existing2 = boundClass.findMethodBySignature(methodGetData, false); final PsiMethod existing3 = boundClass.findMethodBySignature(methodIsModified, false); // warning already shown if (existing1 != null) { existing1.delete(); } if (existing2 != null) { existing2.delete(); } if (existing3 != null) { existing3.delete(); } final CodeStyleManager formatter = CodeStyleManager.getInstance(module.getProject()); final JavaCodeStyleManager styler = JavaCodeStyleManager.getInstance(module.getProject()); final PsiElement setData = boundClass.add(methodSetData); styler.shortenClassReferences(setData); formatter.reformat(setData); final PsiElement getData = boundClass.add(methodGetData); styler.shortenClassReferences(getData); formatter.reformat(getData); if (data.myGenerateIsModified) { final PsiElement isModified = boundClass.add(methodIsModified); styler.shortenClassReferences(isModified); formatter.reformat(isModified); } final OpenFileDescriptor descriptor = new OpenFileDescriptor( setData.getProject(), setData.getContainingFile().getVirtualFile(), setData.getTextOffset()); FileEditorManager.getInstance(data.myProject).openTextEditor(descriptor, true); } catch (IncorrectOperationException e) { throw new MyException(e.getMessage()); } }
public void performAction(IntroduceOperation operation) { final PsiFile file = operation.getFile(); if (!CommonRefactoringUtil.checkReadOnlyStatus(file)) { return; } final Editor editor = operation.getEditor(); if (editor.getSettings().isVariableInplaceRenameEnabled()) { final TemplateState templateState = TemplateManagerImpl.getTemplateState(operation.getEditor()); if (templateState != null && !templateState.isFinished()) { return; } } PsiElement element1 = null; PsiElement element2 = null; final SelectionModel selectionModel = editor.getSelectionModel(); boolean singleElementSelection = false; if (selectionModel.hasSelection()) { element1 = file.findElementAt(selectionModel.getSelectionStart()); element2 = file.findElementAt(selectionModel.getSelectionEnd() - 1); if (element1 instanceof PsiWhiteSpace) { int startOffset = element1.getTextRange().getEndOffset(); element1 = file.findElementAt(startOffset); } if (element2 instanceof PsiWhiteSpace) { int endOffset = element2.getTextRange().getStartOffset(); element2 = file.findElementAt(endOffset - 1); } if (element1 == element2) { singleElementSelection = true; } } else { if (smartIntroduce(operation)) { return; } final CaretModel caretModel = editor.getCaretModel(); final Document document = editor.getDocument(); int lineNumber = document.getLineNumber(caretModel.getOffset()); if ((lineNumber >= 0) && (lineNumber < document.getLineCount())) { element1 = file.findElementAt(document.getLineStartOffset(lineNumber)); element2 = file.findElementAt(document.getLineEndOffset(lineNumber) - 1); } } final Project project = operation.getProject(); if (element1 == null || element2 == null) { showCannotPerformError(project, editor); return; } element1 = PyRefactoringUtil.getSelectedExpression(project, file, element1, element2); if (element1 == null) { showCannotPerformError(project, editor); return; } if (singleElementSelection && element1 instanceof PyStringLiteralExpression) { final PyStringLiteralExpression literal = (PyStringLiteralExpression) element1; // Currently introduce for substrings of a multi-part string literals is not supported if (literal.getStringNodes().size() > 1) { showCannotPerformError(project, editor); return; } final int offset = element1.getTextOffset(); final TextRange selectionRange = TextRange.create(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd()); final TextRange elementRange = element1.getTextRange(); if (!elementRange.equals(selectionRange) && elementRange.contains(selectionRange)) { final TextRange innerRange = literal.getStringValueTextRange(); final TextRange intersection = selectionRange.shiftRight(-offset).intersection(innerRange); final TextRange finalRange = intersection != null ? intersection : selectionRange; final String text = literal.getText(); if (getFormatValueExpression(literal) != null && breaksStringFormatting(text, finalRange) || getNewStyleFormatValueExpression(literal) != null && breaksNewStyleStringFormatting(text, finalRange) || breaksStringEscaping(text, finalRange)) { showCannotPerformError(project, editor); return; } element1.putUserData( PyReplaceExpressionUtil.SELECTION_BREAKS_AST_NODE, Pair.create(element1, finalRange)); } } if (!checkIntroduceContext(file, editor, element1)) { return; } operation.setElement(element1); performActionOnElement(operation); }
@NotNull @Override public List<SearchScope> getPredefinedScopes( @NotNull final Project project, @Nullable final DataContext dataContext, boolean suggestSearchInLibs, boolean prevSearchFiles, boolean currentSelection, boolean usageView, boolean showEmptyScopes) { Collection<SearchScope> result = ContainerUtil.newLinkedHashSet(); result.add(GlobalSearchScope.projectScope(project)); if (suggestSearchInLibs) { result.add(GlobalSearchScope.allScope(project)); } if (ModuleUtil.isSupportedRootType(project, JavaSourceRootType.TEST_SOURCE)) { result.add(GlobalSearchScopesCore.projectProductionScope(project)); result.add(GlobalSearchScopesCore.projectTestScope(project)); } final GlobalSearchScope openFilesScope = GlobalSearchScopes.openFilesScope(project); if (openFilesScope != GlobalSearchScope.EMPTY_SCOPE) { result.add(openFilesScope); } else if (showEmptyScopes) { result.add( new LocalSearchScope(PsiElement.EMPTY_ARRAY, IdeBundle.message("scope.open.files"))); } final Editor selectedTextEditor = ApplicationManager.getApplication().isDispatchThread() ? FileEditorManager.getInstance(project).getSelectedTextEditor() : null; final PsiFile psiFile = (selectedTextEditor != null) ? PsiDocumentManager.getInstance(project).getPsiFile(selectedTextEditor.getDocument()) : null; PsiFile currentFile = psiFile; if (dataContext != null) { PsiElement dataContextElement = CommonDataKeys.PSI_FILE.getData(dataContext); if (dataContextElement == null) { dataContextElement = CommonDataKeys.PSI_ELEMENT.getData(dataContext); } if (dataContextElement == null && psiFile != null) { dataContextElement = psiFile; } if (dataContextElement != null) { if (!PlatformUtils.isCidr()) { // TODO: have an API to disable module scopes. Module module = ModuleUtilCore.findModuleForPsiElement(dataContextElement); if (module == null) { module = LangDataKeys.MODULE.getData(dataContext); } if (module != null && !(ModuleType.get(module) instanceof InternalModuleType)) { result.add(module.getModuleScope()); } } if (currentFile == null) { currentFile = dataContextElement.getContainingFile(); } } } if (currentFile != null || showEmptyScopes) { PsiElement[] scope = currentFile != null ? new PsiElement[] {currentFile} : PsiElement.EMPTY_ARRAY; result.add(new LocalSearchScope(scope, IdeBundle.message("scope.current.file"))); } if (currentSelection && selectedTextEditor != null && psiFile != null) { SelectionModel selectionModel = selectedTextEditor.getSelectionModel(); if (selectionModel.hasSelection()) { int start = selectionModel.getSelectionStart(); final PsiElement startElement = psiFile.findElementAt(start); if (startElement != null) { int end = selectionModel.getSelectionEnd(); final PsiElement endElement = psiFile.findElementAt(end); if (endElement != null) { final PsiElement parent = PsiTreeUtil.findCommonParent(startElement, endElement); if (parent != null) { final List<PsiElement> elements = new ArrayList<PsiElement>(); final PsiElement[] children = parent.getChildren(); TextRange selection = new TextRange(start, end); for (PsiElement child : children) { if (!(child instanceof PsiWhiteSpace) && child.getContainingFile() != null && selection.contains(child.getTextOffset())) { elements.add(child); } } if (!elements.isEmpty()) { SearchScope local = new LocalSearchScope( PsiUtilCore.toPsiElementArray(elements), IdeBundle.message("scope.selection")); result.add(local); } } } } } } if (usageView) { addHierarchyScope(project, result); UsageView selectedUsageView = UsageViewManager.getInstance(project).getSelectedUsageView(); if (selectedUsageView != null && !selectedUsageView.isSearchInProgress()) { final Set<Usage> usages = ContainerUtil.newTroveSet(selectedUsageView.getUsages()); usages.removeAll(selectedUsageView.getExcludedUsages()); final List<PsiElement> results = new ArrayList<PsiElement>(usages.size()); if (prevSearchFiles) { final Set<VirtualFile> files = collectFiles(usages, true); if (!files.isEmpty()) { GlobalSearchScope prev = new GlobalSearchScope(project) { private Set<VirtualFile> myFiles = null; @NotNull @Override public String getDisplayName() { return IdeBundle.message("scope.files.in.previous.search.result"); } @Override public synchronized boolean contains(@NotNull VirtualFile file) { if (myFiles == null) { myFiles = collectFiles(usages, false); } return myFiles.contains(file); } @Override public int compare(@NotNull VirtualFile file1, @NotNull VirtualFile file2) { return 0; } @Override public boolean isSearchInModuleContent(@NotNull Module aModule) { return true; } @Override public boolean isSearchInLibraries() { return true; } }; result.add(prev); } } else { for (Usage usage : usages) { if (usage instanceof PsiElementUsage) { final PsiElement element = ((PsiElementUsage) usage).getElement(); if (element != null && element.isValid() && element.getContainingFile() != null) { results.add(element); } } } if (!results.isEmpty()) { result.add( new LocalSearchScope( PsiUtilCore.toPsiElementArray(results), IdeBundle.message("scope.previous.search.results"))); } } } } final FavoritesManager favoritesManager = FavoritesManager.getInstance(project); if (favoritesManager != null) { for (final String favorite : favoritesManager.getAvailableFavoritesListNames()) { final Collection<TreeItem<Pair<AbstractUrl, String>>> rootUrls = favoritesManager.getFavoritesListRootUrls(favorite); if (rootUrls.isEmpty()) continue; // ignore unused root result.add( new GlobalSearchScope(project) { @NotNull @Override public String getDisplayName() { return "Favorite \'" + favorite + "\'"; } @Override public boolean contains(@NotNull final VirtualFile file) { return ApplicationManager.getApplication() .runReadAction( (Computable<Boolean>) () -> favoritesManager.contains(favorite, file)); } @Override public int compare( @NotNull final VirtualFile file1, @NotNull final VirtualFile file2) { return 0; } @Override public boolean isSearchInModuleContent(@NotNull final Module aModule) { return true; } @Override public boolean isSearchInLibraries() { return true; } }); } } ContainerUtil.addIfNotNull(result, getSelectedFilesScope(project, dataContext)); return ContainerUtil.newArrayList(result); }
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { if (!myField.isValid()) return; // weird. should not get here when field becomes invalid final Collection<PsiReference> refs = ReferencesSearch.search(myField).findAll(); if (refs.isEmpty()) return; Set<PsiReference> refsSet = new HashSet<PsiReference>(refs); PsiCodeBlock anchorBlock = findAnchorBlock(refs); if (anchorBlock == null) return; // was assert, but need to fix the case when obsolete inspection highlighting is // left if (!CodeInsightUtil.preparePsiElementsForWrite(anchorBlock)) return; final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(project).getElementFactory(); final JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(project); final String propertyName = styleManager.variableNameToPropertyName(myField.getName(), VariableKind.FIELD); String localName = styleManager.propertyNameToVariableName(propertyName, VariableKind.LOCAL_VARIABLE); localName = RefactoringUtil.suggestUniqueVariableName(localName, anchorBlock, myField); PsiElement firstElement = getFirstElement(refs); boolean mayBeFinal = mayBeFinal(refsSet, firstElement); PsiElement newDeclaration = null; try { final PsiElement anchor = getAnchorElement(anchorBlock, firstElement); if (anchor instanceof PsiExpressionStatement && ((PsiExpressionStatement) anchor).getExpression() instanceof PsiAssignmentExpression) { final PsiAssignmentExpression expression = (PsiAssignmentExpression) ((PsiExpressionStatement) anchor).getExpression(); if (expression.getOperationTokenType() == JavaTokenType.EQ && expression.getLExpression() instanceof PsiReferenceExpression && ((PsiReference) expression.getLExpression()).isReferenceTo(myField)) { final PsiExpression initializer = expression.getRExpression(); final PsiDeclarationStatement decl = elementFactory.createVariableDeclarationStatement( localName, myField.getType(), initializer); if (!mayBeFinal) { PsiUtil.setModifierProperty( ((PsiModifierListOwner) decl.getDeclaredElements()[0]), PsiModifier.FINAL, false); } newDeclaration = anchor.replace(decl); refsSet.remove(expression.getLExpression()); retargetReferences(elementFactory, localName, refsSet); } else { newDeclaration = addDeclarationWithFieldInitializerAndRetargetReferences( elementFactory, localName, anchorBlock, anchor, refsSet); } } else { newDeclaration = addDeclarationWithFieldInitializerAndRetargetReferences( elementFactory, localName, anchorBlock, anchor, refsSet); } } catch (IncorrectOperationException e) { LOG.error(e); } if (newDeclaration != null) { final PsiFile psiFile = myField.getContainingFile(); final Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor(); if (editor != null && IJSwingUtilities.hasFocus(editor.getComponent())) { final PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); if (file == psiFile) { editor.getCaretModel().moveToOffset(newDeclaration.getTextOffset()); editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); } } } try { myField.normalizeDeclaration(); myField.delete(); } catch (IncorrectOperationException e) { LOG.error(e); } }
public Result beforeCharTyped( final char c, final Project project, final Editor editor, final PsiFile editedFile, final FileType fileType) { final XmlEditorOptions xmlEditorOptions = XmlEditorOptions.getInstance(); if (c == '>' && xmlEditorOptions != null && xmlEditorOptions.isAutomaticallyInsertClosingTag() && (editedFile.getLanguage() instanceof XMLLanguage || editedFile.getViewProvider().getBaseLanguage() instanceof XMLLanguage)) { PsiDocumentManager.getInstance(project).commitAllDocuments(); PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); FileViewProvider provider = editedFile.getViewProvider(); int offset = editor.getCaretModel().getOffset(); PsiElement element, elementAtCaret = null; if (offset < editor.getDocument().getTextLength()) { elementAtCaret = element = provider.findElementAt(offset, XMLLanguage.class); if (!(element instanceof PsiWhiteSpace)) { boolean nonAcceptableDelimiter = true; if (element instanceof XmlToken) { IElementType tokenType = ((XmlToken) element).getTokenType(); if (tokenType == XmlTokenType.XML_START_TAG_START || tokenType == XmlTokenType.XML_END_TAG_START) { if (offset > 0) { PsiElement previousElement = provider.findElementAt(offset - 1, XMLLanguage.class); if (previousElement instanceof XmlToken) { tokenType = ((XmlToken) previousElement).getTokenType(); element = previousElement; nonAcceptableDelimiter = false; } } } else if (tokenType == XmlTokenType.XML_NAME) { if (element.getNextSibling() instanceof PsiErrorElement) { nonAcceptableDelimiter = false; } } if (tokenType == XmlTokenType.XML_TAG_END || tokenType == XmlTokenType.XML_EMPTY_ELEMENT_END && element.getTextOffset() == offset - 1) { editor.getCaretModel().moveToOffset(offset + 1); editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); return Result.STOP; } } if (nonAcceptableDelimiter) return Result.CONTINUE; } else { // check if right after empty end PsiElement previousElement = provider.findElementAt(offset - 1, XMLLanguage.class); if (previousElement instanceof XmlToken) { final IElementType tokenType = ((XmlToken) previousElement).getTokenType(); if (tokenType == XmlTokenType.XML_EMPTY_ELEMENT_END) { return Result.STOP; } } } PsiElement parent = element.getParent(); if (parent instanceof XmlText) { final String text = parent.getText(); // check / final int index = offset - parent.getTextOffset() - 1; if (index >= 0 && text.charAt(index) == '/') { return Result.CONTINUE; // already seen / } element = parent.getPrevSibling(); } else if (parent instanceof XmlTag && !(element.getPrevSibling() instanceof XmlTag)) { element = parent; } else if (parent instanceof XmlAttributeValue) { element = parent; } } else { element = provider.findElementAt(editor.getDocument().getTextLength() - 1, XMLLanguage.class); if (element == null) return Result.CONTINUE; element = element.getParent(); } if (offset > 0 && offset <= editor.getDocument().getTextLength()) { if (editor.getDocument().getCharsSequence().charAt(offset - 1) == '/') { // Some languages (e.g. GSP) allow character '/' in tag name. return Result.CONTINUE; } } if (element instanceof XmlAttributeValue) { element = element.getParent().getParent(); } while (element instanceof PsiWhiteSpace) element = element.getPrevSibling(); if (element instanceof XmlDocument) { // hack for closing tags in RHTML element = element.getLastChild(); } if (element == null) return Result.CONTINUE; if (!(element instanceof XmlTag)) { if (element instanceof XmlTokenImpl && element.getPrevSibling() != null && element.getPrevSibling().getText().equals("<")) { // tag is started and there is another text in the end editor.getDocument().insertString(offset, "</" + element.getText() + ">"); } return Result.CONTINUE; } XmlTag tag = (XmlTag) element; if (XmlUtil.getTokenOfType(tag, XmlTokenType.XML_TAG_END) != null) return Result.CONTINUE; if (XmlUtil.getTokenOfType(tag, XmlTokenType.XML_EMPTY_ELEMENT_END) != null) return Result.CONTINUE; final XmlToken startToken = XmlUtil.getTokenOfType(tag, XmlTokenType.XML_START_TAG_START); if (startToken == null || !startToken.getText().equals("<")) return Result.CONTINUE; String name = tag.getName(); if (elementAtCaret instanceof XmlToken && ((XmlToken) elementAtCaret).getTokenType() == XmlTokenType.XML_NAME) { name = name.substring(0, offset - elementAtCaret.getTextOffset()); } if (tag instanceof HtmlTag && HtmlUtil.isSingleHtmlTag(name)) return Result.CONTINUE; if ("".equals(name)) return Result.CONTINUE; int tagOffset = tag.getTextRange().getStartOffset(); final XmlToken nameToken = XmlUtil.getTokenOfType(tag, XmlTokenType.XML_NAME); if (nameToken != null && nameToken.getTextRange().getStartOffset() > offset) return Result.CONTINUE; HighlighterIterator iterator = ((EditorEx) editor).getHighlighter().createIterator(tagOffset); if (BraceMatchingUtil.matchBrace( editor.getDocument().getCharsSequence(), editedFile.getFileType(), iterator, true, true)) { PsiElement parent = tag.getParent(); boolean hasBalance = true; while (parent instanceof XmlTag && name.equals(((XmlTag) parent).getName())) { ASTNode astNode = XmlChildRole.CLOSING_TAG_NAME_FINDER.findChild(parent.getNode()); if (astNode == null) { hasBalance = false; break; } parent = parent.getParent(); } if (hasBalance) { hasBalance = false; for (ASTNode node = parent.getNode().getLastChildNode(); node != null; node = node.getTreePrev()) { ASTNode leaf = node; if (leaf.getElementType() == TokenType.ERROR_ELEMENT) { ASTNode firstChild = leaf.getFirstChildNode(); if (firstChild != null) leaf = firstChild; else { PsiElement psiElement = PsiTreeUtil.nextLeaf(leaf.getPsi()); leaf = psiElement != null ? psiElement.getNode() : null; } if (leaf != null && leaf.getElementType() == TokenType.WHITE_SPACE) { PsiElement psiElement = PsiTreeUtil.nextLeaf(leaf.getPsi()); if (psiElement != null) leaf = psiElement.getNode(); } } if (leaf != null && leaf.getElementType() == XmlTokenType.XML_END_TAG_START) { ASTNode treeNext = leaf.getTreeNext(); IElementType treeNextType; if (treeNext != null && ((treeNextType = treeNext.getElementType()) == XmlTokenType.XML_NAME || treeNextType == XmlTokenType.XML_TAG_NAME)) { if (name.equals(treeNext.getText())) { ASTNode parentEndName = parent instanceof XmlTag ? XmlChildRole.CLOSING_TAG_NAME_FINDER.findChild(parent.getNode()) : null; hasBalance = !(parent instanceof XmlTag) || parentEndName != null && !parentEndName.getText().equals(name); break; } } } } } if (hasBalance) return Result.CONTINUE; } TextRange cdataReformatRange = null; final XmlElementDescriptor descriptor = tag.getDescriptor(); if (descriptor instanceof XmlElementDescriptorWithCDataContent) { final XmlElementDescriptorWithCDataContent cDataContainer = (XmlElementDescriptorWithCDataContent) descriptor; if (cDataContainer.requiresCdataBracesInContext(tag)) { int rangeStart = offset; @NonNls final String cDataStart = "><![CDATA["; final String inserted = cDataStart + "\n]]>"; editor.getDocument().insertString(offset, inserted); final int newoffset = offset + cDataStart.length(); editor.getCaretModel().moveToOffset(newoffset); offset += inserted.length(); cdataReformatRange = new TextRange(rangeStart, offset + 1); } } editor.getDocument().insertString(offset, "</" + name + ">"); if (cdataReformatRange != null) { PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument()); try { CodeStyleManager.getInstance(project) .reformatText( file, cdataReformatRange.getStartOffset(), cdataReformatRange.getEndOffset()); } catch (IncorrectOperationException e) { LOG.error(e); } } return cdataReformatRange != null ? Result.STOP : Result.CONTINUE; } return Result.CONTINUE; }
private boolean insideVisibleArea(Editor e, PsiElement targetElement) { Rectangle visibleArea = e.getScrollingModel().getVisibleArea(); Point point = e.logicalPositionToXY(e.offsetToLogicalPosition(targetElement.getTextOffset())); return visibleArea.contains(point); }