From b6959a6219d2d6d173d5d536b54a04e09c6e2615 Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Wed, 10 Mar 2010 12:29:46 +0300 Subject: [PATCH 001/212] groovy change signature dialog --- .../java/JavaRefactoringSupportProvider.java | 9 +- .../actions/ChangeSignatureAction.java | 25 ++- .../ChangeSignatureDialog.java | 8 +- .../ChangeSignatureProcessor.java | 12 +- .../ChangeSignatureTargetUtil.java | 77 -------- .../changeSignature/ChangeSignatureUtil.java | 11 +- ...r.java => JavaChangeSignatureHandler.java} | 54 +++++- .../changeSignature/ParameterTableModel.java | 7 +- ...vaRefactoringActionHandlerFactoryImpl.java | 4 +- .../ChangeSignatureTargetTest.java | 4 +- .../DefaultRefactoringSupportProvider.java | 5 + .../RefactoringSupportProvider.java | 7 + .../ChangeSignatureHandler.java | 33 ++++ .../GroovyRefactoringBundle.properties | 6 + .../GroovyRefactoringSupportProvider.java | 7 + .../GrChangeSignatureDialog.form | 181 ++++++++++++++++++ .../GrChangeSignatureDialog.java | 67 +++++++ .../GrChangeSignatureHandler.java | 103 ++++++++++ .../changeSignature/GrParameterInfo.java | 85 ++++++++ .../GrParameterTableModel.java | 138 +++++++++++++ 20 files changed, 737 insertions(+), 106 deletions(-) delete mode 100644 java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureTargetUtil.java rename java/java-impl/src/com/intellij/refactoring/changeSignature/{ChangeSignatureHandler.java => JavaChangeSignatureHandler.java} (65%) create mode 100644 platform/lang-api/src/com/intellij/refactoring/changeSignature/ChangeSignatureHandler.java create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.form create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureHandler.java create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterTableModel.java diff --git a/java/java-impl/src/com/intellij/lang/java/JavaRefactoringSupportProvider.java b/java/java-impl/src/com/intellij/lang/java/JavaRefactoringSupportProvider.java index 64747b2d233d..264d26b3a72d 100644 --- a/java/java-impl/src/com/intellij/lang/java/JavaRefactoringSupportProvider.java +++ b/java/java-impl/src/com/intellij/lang/java/JavaRefactoringSupportProvider.java @@ -21,9 +21,11 @@ import com.intellij.psi.search.LocalSearchScope; import com.intellij.psi.search.SearchScope; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.RefactoringActionHandler; -import com.intellij.refactoring.extractSuperclass.ExtractSuperclassHandler; +import com.intellij.refactoring.changeSignature.ChangeSignatureHandler; +import com.intellij.refactoring.changeSignature.JavaChangeSignatureHandler; import com.intellij.refactoring.extractInterface.ExtractInterfaceHandler; import com.intellij.refactoring.extractMethod.ExtractMethodHandler; +import com.intellij.refactoring.extractSuperclass.ExtractSuperclassHandler; import com.intellij.refactoring.introduceField.IntroduceConstantHandler; import com.intellij.refactoring.introduceField.IntroduceFieldHandler; import com.intellij.refactoring.introduceParameter.IntroduceParameterHandler; @@ -84,6 +86,11 @@ public class JavaRefactoringSupportProvider extends DefaultRefactoringSupportPro return new ExtractSuperclassHandler(); } + @Override + public ChangeSignatureHandler getChangeSignatureHandler() { + return new JavaChangeSignatureHandler(); + } + public static boolean mayRenameInplace(PsiElement elementToRename, final PsiElement nameSuggestionContext) { if (!(elementToRename instanceof PsiVariable)) return false; if (nameSuggestionContext != null && nameSuggestionContext.getContainingFile() != elementToRename.getContainingFile()) return false; diff --git a/java/java-impl/src/com/intellij/refactoring/actions/ChangeSignatureAction.java b/java/java-impl/src/com/intellij/refactoring/actions/ChangeSignatureAction.java index 1da3be897e59..382cc4adb1ed 100644 --- a/java/java-impl/src/com/intellij/refactoring/actions/ChangeSignatureAction.java +++ b/java/java-impl/src/com/intellij/refactoring/actions/ChangeSignatureAction.java @@ -15,13 +15,16 @@ */ package com.intellij.refactoring.actions; +import com.intellij.lang.Language; +import com.intellij.lang.LanguageRefactoringSupport; import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.actionSystem.LangDataKeys; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.psi.*; import com.intellij.refactoring.RefactoringActionHandler; import com.intellij.refactoring.changeSignature.ChangeSignatureHandler; -import com.intellij.refactoring.changeSignature.ChangeSignatureTargetUtil; +import org.jetbrains.annotations.Nullable; public class ChangeSignatureAction extends BaseRefactoringAction { public boolean isAvailableInEditorOnly() { @@ -35,13 +38,29 @@ public class ChangeSignatureAction extends BaseRefactoringAction { protected boolean isAvailableOnElementInEditor(final PsiElement element, final Editor editor) { final Document document = editor.getDocument(); final PsiFile file = PsiDocumentManager.getInstance(element.getProject()).getPsiFile(document); - if (file != null && ChangeSignatureTargetUtil.findTargetMember(file, editor) != null) { + final ChangeSignatureHandler handler = getChangeSignatureHandler(element.getLanguage()); + if (handler == null) return false; + if (file != null && handler.findTargetMember(file, editor) != null) { return true; } return element instanceof PsiMethod || element instanceof PsiClass; } public RefactoringActionHandler getHandler(DataContext dataContext) { - return new ChangeSignatureHandler(); + final Language language = LangDataKeys.LANGUAGE.getData(dataContext); + if (language != null) { + return getChangeSignatureHandler(language); + } + return null; + } + + @Override + protected boolean isAvailableForLanguage(Language language) { + return getChangeSignatureHandler(language) != null; + } + + @Nullable + private static ChangeSignatureHandler getChangeSignatureHandler(Language language) { + return LanguageRefactoringSupport.INSTANCE.forLanguage(language).getChangeSignatureHandler(); } } diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureDialog.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureDialog.java index 510c5e1892c4..7ccd058327b1 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureDialog.java @@ -282,8 +282,12 @@ public class ChangeSignatureDialog extends RefactoringDialog { panel.add(subPanel, BorderLayout.CENTER); JPanel subPanel1 = new JPanel(new GridBagLayout()); - subPanel1.add(createExceptionsPanel(), new GridBagConstraints(0, 0, 1, 1, 0.5, 0.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(4,4,4,0), 0, 0)); - subPanel1.add(createSignaturePanel(), new GridBagConstraints(1, 0, 1, 1, 0.5, 0.0, GridBagConstraints.EAST, GridBagConstraints.BOTH, new Insets(4,0,4,4), 0, 0)); + subPanel1.add(createExceptionsPanel(), + new GridBagConstraints(0, 0, 1, 1, 0.5, 0.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(4, 4, 4, 0), 0, + 0)); + subPanel1.add(createSignaturePanel(), + new GridBagConstraints(1, 0, 1, 1, 0.5, 0.0, GridBagConstraints.EAST, GridBagConstraints.BOTH, new Insets(4, 0, 4, 4), 0, + 0)); panel.add(subPanel1, BorderLayout.SOUTH); return panel; diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java index 909b200d8e67..2c7a3c5f9e79 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java @@ -58,6 +58,7 @@ import com.intellij.util.VisibilityUtil; import com.intellij.util.containers.HashSet; import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.*; @@ -479,7 +480,7 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor { protected boolean isProcessCovariantOverriders() { return Messages.showYesNoDialog(myProject, RefactoringBundle.message("do.you.want.to.process.overriding.methods.with.covariant.return.type"), - ChangeSignatureHandler.REFACTORING_NAME, Messages.getQuestionIcon()) + JavaChangeSignatureHandler.REFACTORING_NAME, Messages.getQuestionIcon()) == DialogWrapper.OK_EXIT_CODE; } @@ -941,17 +942,13 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor { newArgs [newNonVarargCount] = createActualArgument(list, changeInfo.newParms [newNonVarargCount], toInsertDefaultValue, args); } else { - for (int i = 0; i < newVarargInitializers.length; i++) { - newArgs [i + newNonVarargCount] = newVarargInitializers [i]; - } + System.arraycopy(newVarargInitializers, 0, newArgs, newNonVarargCount, newVarargInitializers.length); } } else { final int newVarargCount = newArgsLength - newNonVarargCount; LOG.assertTrue(newVarargCount == 0 || newVarargCount == varargCount); - for (int i = 0; i < newVarargCount; i++) { - newArgs[newNonVarargCount + i] = args[nonVarargCount + i]; - } + System.arraycopy(args, nonVarargCount, newArgs, newNonVarargCount, newVarargCount); } ChangeSignatureUtil.synchronizeList(list, Arrays.asList(newArgs), ExpressionList.INSTANCE, changeInfo.toRemoveParm); } @@ -973,6 +970,7 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor { } } + @Nullable private PsiExpression createDefaultValue(final PsiElementFactory factory, final ParameterInfoImpl info, final PsiExpressionList list) throws IncorrectOperationException { if (info.useAnySingleVariable) { diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureTargetUtil.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureTargetUtil.java deleted file mode 100644 index 5c947f4c48bb..000000000000 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureTargetUtil.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * User: anna - * Date: 24-Nov-2009 - */ -package com.intellij.refactoring.changeSignature; - -import com.intellij.openapi.editor.Editor; -import com.intellij.psi.*; -import com.intellij.psi.util.PsiTreeUtil; -import org.jetbrains.annotations.Nullable; - -public class ChangeSignatureTargetUtil { - private ChangeSignatureTargetUtil() {} - - @Nullable - public static PsiMember findTargetMember(PsiFile file, Editor editor) { - PsiElement element = file.findElementAt(editor.getCaretModel().getOffset()); - if (PsiTreeUtil.getParentOfType(element, PsiParameterList.class) != null) { - return PsiTreeUtil.getParentOfType(element, PsiMethod.class); - } - - final PsiMethodCallExpression expression = PsiTreeUtil.getParentOfType(element, PsiMethodCallExpression.class); - if (expression != null) { - assert element != null; - final PsiExpression qualifierExpression = expression.getMethodExpression().getQualifierExpression(); - if (PsiTreeUtil.isAncestor(qualifierExpression, element, false)) { - final PsiExpressionList expressionList = PsiTreeUtil.getParentOfType(qualifierExpression, PsiExpressionList.class); - if (expressionList != null) { - final PsiElement parent = expressionList.getParent(); - if (parent instanceof PsiMethodCallExpression) { - return ((PsiMethodCallExpression)parent).resolveMethod(); - } - } - } else { - return expression.resolveMethod(); - } - } - - final PsiTypeParameterList typeParameterList = PsiTreeUtil.getParentOfType(element, PsiTypeParameterList.class); - if (typeParameterList != null) { - return PsiTreeUtil.getParentOfType(typeParameterList, PsiMember.class); - } - - final PsiReferenceParameterList referenceParameterList = PsiTreeUtil.getParentOfType(element, PsiReferenceParameterList.class); - if (referenceParameterList != null) { - final PsiJavaCodeReferenceElement referenceElement = - PsiTreeUtil.getParentOfType(referenceParameterList, PsiJavaCodeReferenceElement.class); - if (referenceElement != null) { - final PsiElement resolved = referenceElement.resolve(); - if (resolved instanceof PsiClass) { - return (PsiMember)resolved; - } - else if (resolved instanceof PsiMethod) { - return (PsiMember)resolved; - } - } - } - return null; - } - -} diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureUtil.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureUtil.java index 708bb92ebf5e..96275d137b80 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureUtil.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureUtil.java @@ -26,10 +26,13 @@ import java.util.List; * @author dsl */ public class ChangeSignatureUtil { - private ChangeSignatureUtil() {} + private ChangeSignatureUtil() { + } - public static - void synchronizeList(Parent list, final List newElements, ChildrenGenerator generator, final boolean[] shouldRemoveChild) + public static void synchronizeList(Parent list, + final List newElements, + ChildrenGenerator generator, + final boolean[] shouldRemoveChild) throws IncorrectOperationException { ArrayList elementsToRemove = null; @@ -72,7 +75,7 @@ public class ChangeSignatureUtil { } } - public static interface ChildrenGenerator { + public interface ChildrenGenerator { List getChildren(Parent parent); } } diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureHandler.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureHandler.java similarity index 65% rename from java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureHandler.java rename to java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureHandler.java index 5c099c16bb49..d8d683553901 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureHandler.java @@ -24,20 +24,19 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.ScrollType; import com.intellij.openapi.project.Project; import com.intellij.psi.*; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.HelpID; -import com.intellij.refactoring.RefactoringActionHandler; import com.intellij.refactoring.RefactoringBundle; import com.intellij.refactoring.changeClassSignature.ChangeClassSignatureDialog; import com.intellij.refactoring.util.CommonRefactoringUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class ChangeSignatureHandler implements RefactoringActionHandler { - public static final String REFACTORING_NAME = RefactoringBundle.message("changeSignature.refactoring.name"); +public class JavaChangeSignatureHandler implements ChangeSignatureHandler { public void invoke(@NotNull Project project, Editor editor, PsiFile file, DataContext dataContext) { editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE); - PsiElement element = ChangeSignatureTargetUtil.findTargetMember(file, editor); + PsiElement element = findTargetMember(file, editor); if (element == null) { element = LangDataKeys.PSI_ELEMENT.getData(dataContext); } @@ -96,4 +95,51 @@ public class ChangeSignatureHandler implements RefactoringActionHandler { ChangeClassSignatureDialog dialog = new ChangeClassSignatureDialog(aClass); dialog.show(); } + + @Nullable + public PsiMember findTargetMember(PsiFile file, Editor editor) { + PsiElement element = file.findElementAt(editor.getCaretModel().getOffset()); + if (PsiTreeUtil.getParentOfType(element, PsiParameterList.class) != null) { + return PsiTreeUtil.getParentOfType(element, PsiMethod.class); + } + + final PsiMethodCallExpression expression = PsiTreeUtil.getParentOfType(element, PsiMethodCallExpression.class); + if (expression != null) { + assert element != null; + final PsiExpression qualifierExpression = expression.getMethodExpression().getQualifierExpression(); + if (PsiTreeUtil.isAncestor(qualifierExpression, element, false)) { + final PsiExpressionList expressionList = PsiTreeUtil.getParentOfType(qualifierExpression, PsiExpressionList.class); + if (expressionList != null) { + final PsiElement parent = expressionList.getParent(); + if (parent instanceof PsiMethodCallExpression) { + return ((PsiMethodCallExpression)parent).resolveMethod(); + } + } + } + else { + return expression.resolveMethod(); + } + } + + final PsiTypeParameterList typeParameterList = PsiTreeUtil.getParentOfType(element, PsiTypeParameterList.class); + if (typeParameterList != null) { + return PsiTreeUtil.getParentOfType(typeParameterList, PsiMember.class); + } + + final PsiReferenceParameterList referenceParameterList = PsiTreeUtil.getParentOfType(element, PsiReferenceParameterList.class); + if (referenceParameterList != null) { + final PsiJavaCodeReferenceElement referenceElement = + PsiTreeUtil.getParentOfType(referenceParameterList, PsiJavaCodeReferenceElement.class); + if (referenceElement != null) { + final PsiElement resolved = referenceElement.resolve(); + if (resolved instanceof PsiClass) { + return (PsiMember)resolved; + } + else if (resolved instanceof PsiMethod) { + return (PsiMember)resolved; + } + } + } + return null; + } } diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/ParameterTableModel.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/ParameterTableModel.java index bd09d2a2e501..ed0baa199151 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/ParameterTableModel.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/ParameterTableModel.java @@ -116,8 +116,7 @@ class ParameterTableModel extends AbstractTableModel implements RowEditableTable public void setValueAt(Object aValue, int rowIndex, int columnIndex) { if (rowIndex < 0 || rowIndex >= myParameterInfos.size()) return; - String s = aValue instanceof String ? (String)aValue : null; - if (s == null) s = ""; + String s = aValue instanceof String ? (String)aValue : ""; s = s.trim(); ParameterInfoImpl info = myParameterInfos.get(rowIndex); switch (columnIndex) { @@ -186,8 +185,8 @@ class ParameterTableModel extends AbstractTableModel implements RowEditableTable } private JavaCodeFragment createDefaultValueCodeFragment(final String expressionText, final PsiType expectedType) { - PsiExpressionCodeFragment codeFragment = JavaPsiFacade.getInstance(myParameterList.getProject()).getElementFactory().createExpressionCodeFragment(expressionText, - myReferenceExpression, expectedType, true); + PsiExpressionCodeFragment codeFragment = JavaPsiFacade.getInstance(myParameterList.getProject()).getElementFactory() + .createExpressionCodeFragment(expressionText, myReferenceExpression, expectedType, true); codeFragment.setVisibilityChecker(JavaCodeFragment.VisibilityChecker.EVERYTHING_VISIBLE); return codeFragment; } diff --git a/java/java-impl/src/com/intellij/refactoring/openapi/impl/JavaRefactoringActionHandlerFactoryImpl.java b/java/java-impl/src/com/intellij/refactoring/openapi/impl/JavaRefactoringActionHandlerFactoryImpl.java index d2f23b4831a6..23d965134c31 100644 --- a/java/java-impl/src/com/intellij/refactoring/openapi/impl/JavaRefactoringActionHandlerFactoryImpl.java +++ b/java/java-impl/src/com/intellij/refactoring/openapi/impl/JavaRefactoringActionHandlerFactoryImpl.java @@ -18,7 +18,7 @@ package com.intellij.refactoring.openapi.impl; import com.intellij.refactoring.JavaRefactoringActionHandlerFactory; import com.intellij.refactoring.RefactoringActionHandler; import com.intellij.refactoring.anonymousToInner.AnonymousToInnerHandler; -import com.intellij.refactoring.changeSignature.ChangeSignatureHandler; +import com.intellij.refactoring.changeSignature.JavaChangeSignatureHandler; import com.intellij.refactoring.convertToInstanceMethod.ConvertToInstanceMethodHandler; import com.intellij.refactoring.encapsulateFields.EncapsulateFieldsHandler; import com.intellij.refactoring.extractInterface.ExtractInterfaceHandler; @@ -86,7 +86,7 @@ public class JavaRefactoringActionHandlerFactoryImpl extends JavaRefactoringActi } public RefactoringActionHandler createChangeSignatureHandler() { - return new ChangeSignatureHandler(); + return new JavaChangeSignatureHandler(); } public RefactoringActionHandler createExtractSuperclassHandler() { diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTargetTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTargetTest.java index 6ac077915e71..c2161d9179ce 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTargetTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTargetTest.java @@ -8,7 +8,7 @@ import com.intellij.JavaTestUtil; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.projectRoots.impl.JavaSdkImpl; import com.intellij.psi.PsiMember; -import com.intellij.refactoring.changeSignature.ChangeSignatureTargetUtil; +import com.intellij.refactoring.changeSignature.JavaChangeSignatureHandler; import com.intellij.testFramework.LightCodeInsightTestCase; import org.jetbrains.annotations.NonNls; @@ -43,7 +43,7 @@ public class ChangeSignatureTargetTest extends LightCodeInsightTestCase { String basePath = "/refactoring/changeSignatureTarget/" + getTestName(true); @NonNls final String filePath = basePath + ".java"; configureByFile(filePath); - final PsiMember member = ChangeSignatureTargetUtil.findTargetMember(getFile(), getEditor()); + final PsiMember member = new JavaChangeSignatureHandler().findTargetMember(getFile(), getEditor()); assertNotNull(member); assertEquals(expectedMemberName, member.getName()); } diff --git a/platform/lang-api/src/com/intellij/lang/refactoring/DefaultRefactoringSupportProvider.java b/platform/lang-api/src/com/intellij/lang/refactoring/DefaultRefactoringSupportProvider.java index e1d5f95e8bb2..3db3337d1493 100644 --- a/platform/lang-api/src/com/intellij/lang/refactoring/DefaultRefactoringSupportProvider.java +++ b/platform/lang-api/src/com/intellij/lang/refactoring/DefaultRefactoringSupportProvider.java @@ -18,6 +18,7 @@ package com.intellij.lang.refactoring; import com.intellij.psi.PsiElement; import com.intellij.refactoring.RefactoringActionHandler; +import com.intellij.refactoring.changeSignature.ChangeSignatureHandler; import org.jetbrains.annotations.Nullable; /** @@ -69,4 +70,8 @@ public class DefaultRefactoringSupportProvider implements RefactoringSupportProv public boolean doInplaceRenameFor(final PsiElement element, final PsiElement context) { return false; } + + public ChangeSignatureHandler getChangeSignatureHandler() { + return null; + } } diff --git a/platform/lang-api/src/com/intellij/lang/refactoring/RefactoringSupportProvider.java b/platform/lang-api/src/com/intellij/lang/refactoring/RefactoringSupportProvider.java index 46b8ed98a5db..7aa9480d5e7b 100644 --- a/platform/lang-api/src/com/intellij/lang/refactoring/RefactoringSupportProvider.java +++ b/platform/lang-api/src/com/intellij/lang/refactoring/RefactoringSupportProvider.java @@ -17,6 +17,7 @@ package com.intellij.lang.refactoring; import com.intellij.psi.PsiElement; import com.intellij.refactoring.RefactoringActionHandler; +import com.intellij.refactoring.changeSignature.ChangeSignatureHandler; import org.jetbrains.annotations.Nullable; /** @@ -91,5 +92,11 @@ public interface RefactoringSupportProvider { */ @Nullable RefactoringActionHandler getExtractSuperClassHandler(); + /** + * @return handler for changing signature in this language + * @see com.intellij.refactoring.RefactoringActionHandler + */ + @Nullable ChangeSignatureHandler getChangeSignatureHandler(); + boolean doInplaceRenameFor(PsiElement element, PsiElement context); } diff --git a/platform/lang-api/src/com/intellij/refactoring/changeSignature/ChangeSignatureHandler.java b/platform/lang-api/src/com/intellij/refactoring/changeSignature/ChangeSignatureHandler.java new file mode 100644 index 000000000000..00a88165b802 --- /dev/null +++ b/platform/lang-api/src/com/intellij/refactoring/changeSignature/ChangeSignatureHandler.java @@ -0,0 +1,33 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.refactoring.changeSignature; + +import com.intellij.openapi.editor.Editor; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.refactoring.RefactoringActionHandler; +import com.intellij.refactoring.RefactoringBundle; +import org.jetbrains.annotations.Nullable; + +/** + * @author Maxim.Medvedev + */ +public interface ChangeSignatureHandler extends RefactoringActionHandler{ + String REFACTORING_NAME = RefactoringBundle.message("changeSignature.refactoring.name"); + + @Nullable + PsiElement findTargetMember(PsiFile file, Editor editor); +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties index 10fd18f55e55..eb617f3e9cb6 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties @@ -99,3 +99,9 @@ variable.conflicts.with.field.0=Chosen name will conflict with field {0} introduce.parameter.title=Introduce Parameter groovy.does.not.support.inner.classes.but.it.is.used.in.parameter.initializer=Groovy does not support inner classes but it is used in parameter initializer. groovy.does.not.support.anonymous.classes.but.it.is.used.in.parameter.initializer=Groovy does not support anonymous classes but it is used in parameter initializer. +error.wrong.caret.position.method.name=The caret should be positioned at the name of the method to be refactored. +changeSignature.refactoring.name=Change Signature +column.name.type=Type +column.name.name=Name +column.name.default.initializer=Default initializer +column.name.default.value=Default value\ diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringSupportProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringSupportProvider.java index 1aa3631adcf4..61e08638e865 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringSupportProvider.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringSupportProvider.java @@ -19,8 +19,10 @@ package org.jetbrains.plugins.groovy.refactoring; import com.intellij.lang.refactoring.DefaultRefactoringSupportProvider; import com.intellij.psi.PsiElement; import com.intellij.refactoring.RefactoringActionHandler; +import com.intellij.refactoring.changeSignature.ChangeSignatureHandler; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; +import org.jetbrains.plugins.groovy.refactoring.changeSignature.GrChangeSignatureHandler; import org.jetbrains.plugins.groovy.refactoring.extractMethod.GroovyExtractMethodHandler; import org.jetbrains.plugins.groovy.refactoring.introduceVariable.GroovyIntroduceVariableHandler; @@ -47,4 +49,9 @@ public class GroovyRefactoringSupportProvider extends DefaultRefactoringSupportP public RefactoringActionHandler getExtractMethodHandler() { return new GroovyExtractMethodHandler(); } + + @Override + public ChangeSignatureHandler getChangeSignatureHandler() { + return new GrChangeSignatureHandler(); + } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.form b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.form new file mode 100644 index 000000000000..8afbd5ea2cca --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.form @@ -0,0 +1,181 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java new file mode 100644 index 000000000000..ae0a8c0726df --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java @@ -0,0 +1,67 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.groovy.refactoring.changeSignature; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.DialogWrapper; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; + +import javax.swing.*; + +/** + * @author Maxim.Medvedev + */ +public class GrChangeSignatureDialog extends DialogWrapper { + private JTextField myNameField; + private JTextField myReturnTypeField; + private JRadioButton myPublicRadioButton; + + private JRadioButton myProtectedRadioButton; + private JRadioButton myPrivateRadioButton1; + private JPanel myParametersPanel; + private JTable myParameterTable; + private JButton myAddButton; + private JButton myRemoveButton; + private JButton myMoveUpButton; + private JButton myMoveDownButton; + private JPanel contentPane; + private GrParameterTableModel myParameterModel; + private GrMethod myMethod; + + public GrChangeSignatureDialog(@NotNull Project project, GrMethod method) { + super(project, true); + myMethod = method; + myParameterModel = new GrParameterTableModel(myMethod, this); + myParameterTable.setModel(myParameterModel); + myParameterTable.setCellSelectionEnabled(true); + init(); + } + + public GrChangeSignatureDialog() { + super(true); + } + + @Override + protected void doOKAction() { + super.doOKAction(); + } + + @Override + protected JComponent createCenterPanel() { + return contentPane; + } +} \ No newline at end of file diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureHandler.java new file mode 100644 index 000000000000..7383624792f6 --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureHandler.java @@ -0,0 +1,103 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.groovy.refactoring.changeSignature; + +import com.intellij.codeInsight.TargetElementUtil; +import com.intellij.ide.util.SuperMethodWarningUtil; +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.actionSystem.LangDataKeys; +import com.intellij.openapi.actionSystem.PlatformDataKeys; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.ScrollType; +import com.intellij.openapi.project.Project; +import com.intellij.psi.*; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.refactoring.HelpID; +import com.intellij.refactoring.RefactoringBundle; +import com.intellij.refactoring.changeSignature.ChangeSignatureHandler; +import com.intellij.refactoring.util.CommonRefactoringUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterList; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; +import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle; + +/** + * @author Maxim.Medvedev + */ +public class GrChangeSignatureHandler implements ChangeSignatureHandler { + public static final String REFACTORING_NAME = GroovyRefactoringBundle.message("changeSignature.refactoring.name"); + + public void invoke(@NotNull Project project, Editor editor, PsiFile file, DataContext dataContext) { + editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE); + PsiElement element = findTargetMember(file, editor); + if (element == null) { + element = LangDataKeys.PSI_ELEMENT.getData(dataContext); + } + invokeOnElement(project, editor, element); + } + + private static void invokeOnElement(Project project, Editor editor, PsiElement element) { + if (element instanceof PsiMethod) { + invoke((PsiMethod)element, project, editor); + } + else { + String message = + RefactoringBundle.getCannotRefactorMessage(GroovyRefactoringBundle.message("error.wrong.caret.position.method.name")); + CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.CHANGE_SIGNATURE); + } + } + + public void invoke(@NotNull final Project project, @NotNull final PsiElement[] elements, final DataContext dataContext) { + if (elements.length != 1) return; + Editor editor = PlatformDataKeys.EDITOR.getData(dataContext); + invokeOnElement(project, editor, elements[0]); + } + + private static void invoke(final PsiMethod method, final Project project, @Nullable final Editor editor) { + if (!CommonRefactoringUtil.checkReadOnlyStatus(project, method)) return; + + PsiMethod newMethod = SuperMethodWarningUtil.checkSuperMethod(method, RefactoringBundle.message("to.refactor")); + if (newMethod == null) return; + + if (!newMethod.equals(method)) { + invoke(newMethod, project, editor); + return; + } + + if (!CommonRefactoringUtil.checkReadOnlyStatus(project, method)) return; + + final PsiClass containingClass = method.getContainingClass(); + final PsiReference refExpr = editor != null ? TargetElementUtil.findReference(editor) : null; + if (!(method instanceof GrMethod)) return; //todo + final GrChangeSignatureDialog dialog = new GrChangeSignatureDialog(project, (GrMethod)method); + dialog.show(); + } + + @Nullable + public PsiMethod findTargetMember(PsiFile file, Editor editor) { + final PsiElement element = file.findElementAt(editor.getCaretModel().getOffset()); + final GrParameterList parameterList = PsiTreeUtil.getParentOfType(element, GrParameterList.class); + if (parameterList != null) { + final PsiElement parent = parameterList.getParent(); + if (parent instanceof PsiMethod) return (PsiMethod)parent; + } + final GrMethodCallExpression expression = PsiTreeUtil.getParentOfType(element, GrMethodCallExpression.class); + if (expression == null) return null; + return expression.resolveMethod(); + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java new file mode 100644 index 000000000000..8df0e66339c7 --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java @@ -0,0 +1,85 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.groovy.refactoring.changeSignature; + +import com.intellij.psi.PsiType; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; + +/** + * @author Maxim.Medvedev + */ +public class GrParameterInfo { + private String myName = ""; + private String myDefaultValue = ""; + private String myType = ""; + private String myDefaultInitializer = ""; + private final int myPosition; + + public GrParameterInfo(GrParameter parameter, int position) { + myPosition = position; + myName = parameter.getName(); + final PsiType type = parameter.getDeclaredType(); + if (type != null) { + myType = type.getCanonicalText(); + } + final GrExpression defaultInitializer = parameter.getDefaultInitializer(); + if (defaultInitializer != null) { + myDefaultInitializer = defaultInitializer.getText(); + } + } + + + public GrParameterInfo() { + this.myPosition = -1; + } + + public String getName() { + return myName; + } + + public String getDefaultValue() { + return myDefaultValue; + } + + public String getType() { + return myType; + } + + public String getDefaultInitializer() { + return myDefaultInitializer; + } + + public void setName(String name) { + myName = name; + } + + public void setDefaultValue(String defaultValue) { + myDefaultValue = defaultValue; + } + + public void setType(String type) { + myType = type; + } + + public void setDefaultInitializer(String defaultInitializer) { + myDefaultInitializer = defaultInitializer; + } + + public int getPosition() { + return myPosition; + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterTableModel.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterTableModel.java new file mode 100644 index 000000000000..5dfd38f676cb --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterTableModel.java @@ -0,0 +1,138 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.groovy.refactoring.changeSignature; + +import com.intellij.ui.RowEditableTableModel; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; +import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle; + +import javax.swing.table.AbstractTableModel; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Maxim.Medvedev + */ +public class GrParameterTableModel extends AbstractTableModel implements RowEditableTableModel { + private final List infos; + private final GrMethod myMethod; + private final GrChangeSignatureDialog myDialog; + + + public GrParameterTableModel(GrMethod method, GrChangeSignatureDialog dialog) { + myMethod = method; + myDialog = dialog; + final GrParameter[] parameters = myMethod.getParameters(); + infos = new ArrayList(parameters.length); + for (int i = 0; i < parameters.length; i++) { + GrParameter parameter = parameters[i]; + infos.add(new GrParameterInfo(parameter, i)); + } + } + + public void addRow() { + final int row = infos.size(); + infos.add(new GrParameterInfo()); + fireTableRowsInserted(row, row); + } + + public void removeRow(int index) { + infos.remove(index); + fireTableRowsDeleted(index, index); + } + + public void exchangeRows(int index1, int index2) { + final GrParameterInfo info = infos.get(index1); + infos.set(index1, infos.get(index2)); + infos.set(index2, info); + fireTableRowsUpdated(Math.min(index1, index2), Math.max(index1, index2)); + } + + + public int getRowCount() { + return infos.size(); + } + + public int getColumnCount() { + return 4; + } + + @Nullable + public Object getValueAt(int rowIndex, int columnIndex) { + if (rowIndex < 0 || rowIndex >= infos.size()) return null; + final GrParameterInfo info = infos.get(rowIndex); + switch (columnIndex) { + case 0: + return info.getType(); + case 1: + return info.getName(); + case 2: + return info.getDefaultInitializer(); + case 3: + return info.getDefaultValue(); + default: + throw new IllegalArgumentException(); + } + } + + @Override + public void setValueAt(Object value, int rowIndex, int columnIndex) { + if (rowIndex < 0 || rowIndex >= infos.size()) return; + if (columnIndex < 0 || columnIndex > 3) return; + + String s = value instanceof String ? (String)value : ""; + s = s.trim(); + final GrParameterInfo info = infos.get(rowIndex); + switch (columnIndex) { + case 0: + info.setType(s); + case 1: + info.setName(s); + case 2: + info.setDefaultInitializer(s); + case 3: + info.setDefaultValue(s); + } + fireTableCellUpdated(rowIndex, columnIndex); + } + + + @Override + public String getColumnName(int column) { + switch (column) { + case 0: + return GroovyRefactoringBundle.message("column.name.type"); + case 1: + return GroovyRefactoringBundle.message("column.name.name"); + case 2: + return GroovyRefactoringBundle.message("column.name.default.initializer"); + case 3: + return GroovyRefactoringBundle.message("column.name.default.value"); + default: + throw new IllegalArgumentException(); + } + } + + @Override + public Class getColumnClass(int columnIndex) { + if (columnIndex < 0 || columnIndex > 3) throw new IllegalArgumentException(); + return String.class; + } + + +} \ No newline at end of file From ada065b476d223dc3ec63efe6acfce34decd324a Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Sat, 13 Mar 2010 17:21:43 +0300 Subject: [PATCH 002/212] change signature dialog --- .../GrChangeSignatureDialog.form | 67 ++++--- .../GrChangeSignatureDialog.java | 175 +++++++++++++++++- .../GrChangeSignatureProcessor.java | 59 ++++++ .../changeSignature/GrParameterInfo.java | 51 +++-- .../GrParameterTableModel.java | 35 +++- .../ui/GrCodeFragmentTableCellEditor.java | 70 +++++++ .../ui/GrCodeFragmentTableCellRenderer.java | 67 +++++++ 7 files changed, 452 insertions(+), 72 deletions(-) create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/ui/GrCodeFragmentTableCellEditor.java create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/ui/GrCodeFragmentTableCellRenderer.java diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.form b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.form index 8afbd5ea2cca..6baa6a42b2b4 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.form +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.form @@ -18,14 +18,6 @@ - - - - - - - - @@ -34,14 +26,6 @@ - - - - - - - - @@ -60,18 +44,10 @@ - - - - - - - - - + @@ -115,6 +91,19 @@ + + + + + + + + + + + + + @@ -160,15 +149,39 @@ - + - + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java index ae0a8c0726df..6b812eb426e7 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java @@ -15,53 +15,212 @@ */ package org.jetbrains.plugins.groovy.refactoring.changeSignature; +import com.intellij.openapi.editor.Document; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.psi.JavaPsiFacade; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiTypeCodeFragment; +import com.intellij.refactoring.ui.CodeFragmentTableCellEditor; +import com.intellij.refactoring.ui.CodeFragmentTableCellRenderer; +import com.intellij.ui.EditorTextField; +import com.intellij.util.ui.Table; import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.groovy.GroovyFileType; +import org.jetbrains.plugins.groovy.debugger.fragments.GroovyCodeFragment; +import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; +import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement; +import org.jetbrains.plugins.groovy.refactoring.ui.GrCodeFragmentTableCellEditor; +import org.jetbrains.plugins.groovy.refactoring.ui.GrCodeFragmentTableCellRenderer; import javax.swing.*; +import javax.swing.event.TableModelEvent; +import javax.swing.event.TableModelListener; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.List; /** * @author Maxim.Medvedev */ public class GrChangeSignatureDialog extends DialogWrapper { - private JTextField myNameField; - private JTextField myReturnTypeField; + private EditorTextField myNameField; + private EditorTextField myReturnTypeField; private JRadioButton myPublicRadioButton; private JRadioButton myProtectedRadioButton; private JRadioButton myPrivateRadioButton1; private JPanel myParametersPanel; - private JTable myParameterTable; + private Table myParameterTable; private JButton myAddButton; private JButton myRemoveButton; private JButton myMoveUpButton; private JButton myMoveDownButton; private JPanel contentPane; + private JLabel mySignatureLabel; private GrParameterTableModel myParameterModel; private GrMethod myMethod; + private Project myProject; + private PsiTypeCodeFragment myReturnTypeCodeFragment; public GrChangeSignatureDialog(@NotNull Project project, GrMethod method) { super(project, true); + myProject = project; myMethod = method; - myParameterModel = new GrParameterTableModel(myMethod, this); - myParameterTable.setModel(myParameterModel); - myParameterTable.setCellSelectionEnabled(true); init(); + configureParameterButtons(); + updateSignature(); } - public GrChangeSignatureDialog() { - super(true); + private void configureParameterButtons() { + myAddButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + int selectedColumn = myParameterTable.getSelectedColumn(); + myParameterModel.addRow(); + myParameterTable.setRowSelectionInterval(myParameterModel.getRowCount() - 1, myParameterModel.getRowCount() - 1); + myParameterTable.setColumnSelectionInterval(selectedColumn, selectedColumn); + } + }); + myRemoveButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + int selectedRow = myParameterTable.getSelectedRow(); + int selectedColumn = myParameterTable.getSelectedColumn(); + + myParameterModel.removeRow(myParameterTable.getSelectedRow()); + + if (selectedRow == myParameterModel.getRowCount()) selectedRow--; + if (myParameterModel.getRowCount() == 0) return; + myParameterTable.setRowSelectionInterval(selectedRow, selectedRow); + myParameterTable.setColumnSelectionInterval(selectedColumn, selectedColumn); + } + }); + + myMoveUpButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + final int selectedRow = myParameterTable.getSelectedRow(); + int selectedColumn = myParameterTable.getSelectedColumn(); + myParameterModel.exchangeRows(selectedRow, selectedRow - 1); + myParameterTable.setRowSelectionInterval(selectedRow - 1, selectedRow - 1); + myParameterTable.setColumnSelectionInterval(selectedColumn, selectedColumn); + } + }); + + myMoveDownButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + final int selectedRow = myParameterTable.getSelectedRow(); + int selectedColumn = myParameterTable.getSelectedColumn(); + myParameterModel.exchangeRows(selectedRow, selectedRow + 1); + myParameterTable.setRowSelectionInterval(selectedRow + 1, selectedRow + 1); + myParameterTable.setColumnSelectionInterval(selectedColumn, selectedColumn); + } + }); + } + + protected void init() { + super.init(); } @Override protected void doOKAction() { super.doOKAction(); + } @Override protected JComponent createCenterPanel() { return contentPane; } + + + private void createUIComponents() { + createNameAndReturnTypeEditors(); + createParametersModel(); + } + + private void createNameAndReturnTypeEditors() { + myNameField = new EditorTextField("", myProject, GroovyFileType.GROOVY_FILE_TYPE); + myReturnTypeCodeFragment = JavaPsiFacade.getInstance(myProject).getElementFactory().createTypeCodeFragment("", myMethod, true, true); + final Document document = PsiDocumentManager.getInstance(myProject).getDocument(myReturnTypeCodeFragment); + myReturnTypeField = new EditorTextField(document, myProject, myReturnTypeCodeFragment.getFileType()); + + myNameField.setText(myMethod.getName()); + final GrTypeElement element = myMethod.getReturnTypeElementGroovy(); + if (element != null) { + myReturnTypeField.setText(element.getText()); + } + } + + private void createParametersModel() { + myParameterModel = new GrParameterTableModel(myMethod, this, myProject); + myParameterTable = new Table(myParameterModel); + myParameterTable.setCellSelectionEnabled(true); + + myParameterTable.getColumnModel().getColumn(0).setCellRenderer(new CodeFragmentTableCellRenderer(myProject)); + myParameterTable.getColumnModel().getColumn(1).setCellRenderer(new GrCodeFragmentTableCellRenderer(myProject)); + myParameterTable.getColumnModel().getColumn(2).setCellRenderer(new GrCodeFragmentTableCellRenderer(myProject)); + myParameterTable.getColumnModel().getColumn(3).setCellRenderer(new GrCodeFragmentTableCellRenderer(myProject)); + + myParameterTable.getColumnModel().getColumn(0).setCellEditor(new CodeFragmentTableCellEditor(myProject)); + myParameterTable.getColumnModel().getColumn(1).setCellEditor(new GrCodeFragmentTableCellEditor(myProject)); + myParameterTable.getColumnModel().getColumn(2).setCellEditor(new GrCodeFragmentTableCellEditor(myProject)); + myParameterTable.getColumnModel().getColumn(3).setCellEditor(new GrCodeFragmentTableCellEditor(myProject)); + + myParameterTable.setRowSelectionInterval(0, 0); + myParameterTable.setColumnSelectionInterval(0, 0); + + myParameterModel.addTableModelListener(new TableModelListener() { + public void tableChanged(TableModelEvent e) { + updateSignature(); + } + }); + + } + + private void updateSignature() { + final int selectedRow = myParameterTable.getSelectedRow(); + final int rowCount = myParameterModel.getRowCount(); + myMoveUpButton.setEnabled(selectedRow > 0); + myMoveDownButton.setEnabled(selectedRow + 1 < rowCount && rowCount > 1); + myRemoveButton.setEnabled(rowCount > 0); + + mySignatureLabel.setText(generateSignatureText()); + } + + private String generateSignatureText() { + String name = myNameField.getText().trim(); + String type = myReturnTypeField.getText().trim(); + if (type.length() == 0) { + type = GrModifier.DEF; + } + + StringBuilder builder = new StringBuilder(); + builder.append(type).append(' '); + builder.append(name).append('('); + final List infos = myParameterModel.getParameterInfos(); + for (int i = 0, infosSize = infos.size() - 1; i < infosSize; i++) { + generateParameterText(infos.get(i), builder); + builder.append(", "); + } + if (infos.size() > 0) { + generateParameterText(infos.get(infos.size() - 1), builder); + } + + builder.append(')'); + return builder.toString(); + } + + + private static void generateParameterText(GrParameterInfo info, StringBuilder builder) { + final PsiTypeCodeFragment typeFragment = info.getType(); + builder.append(typeFragment != null ? typeFragment.getText().trim() : GrModifier.DEF).append(' '); + final GroovyCodeFragment nameFragment = info.getName(); + builder.append(nameFragment != null ? nameFragment.getText().trim() : ""); + final GroovyCodeFragment defaultInitializer = info.getDefaultInitializer(); + + final String defaultInitializerText = defaultInitializer != null ? defaultInitializer.getText().trim() : ""; + if (defaultInitializerText.length() > 0) { + builder.append(" = ").append(defaultInitializerText); + } + } } \ No newline at end of file diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java new file mode 100644 index 000000000000..76d650d3d2f3 --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java @@ -0,0 +1,59 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.groovy.refactoring.changeSignature; + +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiElement; +import com.intellij.refactoring.BaseRefactoringProcessor; +import com.intellij.usageView.UsageInfo; +import com.intellij.usageView.UsageViewDescriptor; +import org.jetbrains.annotations.NotNull; + +/** + * @author Maxim.Medvedev + */ +public class GrChangeSignatureProcessor extends BaseRefactoringProcessor{ + public GrChangeSignatureProcessor(Project project) { + super(project); + } + + @Override + protected UsageViewDescriptor createUsageViewDescriptor(UsageInfo[] usages) { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @NotNull + @Override + protected UsageInfo[] findUsages() { + return new UsageInfo[0]; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + protected void refreshElements(PsiElement[] elements) { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + protected void performRefactoring(UsageInfo[] usages) { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + protected String getCommandName() { + return ""; + //return RefactoringBundle.message("changing.signature.of.0", UsageViewUtil.getDescriptiveName(myChangeInfo.getMethod())); + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java index 8df0e66339c7..bdf0ff357c4f 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java @@ -15,7 +15,12 @@ */ package org.jetbrains.plugins.groovy.refactoring.changeSignature; +import com.intellij.openapi.project.Project; +import com.intellij.psi.JavaPsiFacade; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiType; +import com.intellij.psi.PsiTypeCodeFragment; +import org.jetbrains.plugins.groovy.debugger.fragments.GroovyCodeFragment; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; @@ -23,62 +28,50 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; * @author Maxim.Medvedev */ public class GrParameterInfo { - private String myName = ""; - private String myDefaultValue = ""; - private String myType = ""; - private String myDefaultInitializer = ""; + private GroovyCodeFragment myName; + private GroovyCodeFragment myDefaultValue; + private PsiTypeCodeFragment myType; + private GroovyCodeFragment myDefaultInitializer; private final int myPosition; public GrParameterInfo(GrParameter parameter, int position) { myPosition = position; - myName = parameter.getName(); + final Project project = parameter.getProject(); + myName = new GroovyCodeFragment(project, parameter.getName()); final PsiType type = parameter.getDeclaredType(); if (type != null) { - myType = type.getCanonicalText(); + myType = JavaPsiFacade.getElementFactory(project).createTypeCodeFragment(type.getCanonicalText(), parameter, true, true); } final GrExpression defaultInitializer = parameter.getDefaultInitializer(); if (defaultInitializer != null) { - myDefaultInitializer = defaultInitializer.getText(); + myDefaultInitializer = new GroovyCodeFragment(project, defaultInitializer.getText()); } } - - public GrParameterInfo() { + public GrParameterInfo(Project project, PsiElement context) { this.myPosition = -1; + myName = new GroovyCodeFragment(project, ""); + myDefaultValue = new GroovyCodeFragment(project, ""); + myType = JavaPsiFacade.getElementFactory(project).createTypeCodeFragment("", context, true, true); + myDefaultInitializer = new GroovyCodeFragment(project, ""); } - public String getName() { + public GroovyCodeFragment getName() { return myName; } - public String getDefaultValue() { + public GroovyCodeFragment getDefaultValue() { return myDefaultValue; } - public String getType() { + public PsiTypeCodeFragment getType() { return myType; } - public String getDefaultInitializer() { + public GroovyCodeFragment getDefaultInitializer() { return myDefaultInitializer; } - public void setName(String name) { - myName = name; - } - - public void setDefaultValue(String defaultValue) { - myDefaultValue = defaultValue; - } - - public void setType(String type) { - myType = type; - } - - public void setDefaultInitializer(String defaultInitializer) { - myDefaultInitializer = defaultInitializer; - } - public int getPosition() { return myPosition; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterTableModel.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterTableModel.java index 5dfd38f676cb..821c2c9ae415 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterTableModel.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterTableModel.java @@ -15,8 +15,11 @@ */ package org.jetbrains.plugins.groovy.refactoring.changeSignature; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiCodeFragment; import com.intellij.ui.RowEditableTableModel; import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.debugger.fragments.GroovyCodeFragment; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle; @@ -32,9 +35,9 @@ public class GrParameterTableModel extends AbstractTableModel implements RowEdit private final List infos; private final GrMethod myMethod; private final GrChangeSignatureDialog myDialog; + private final Project myProject; - - public GrParameterTableModel(GrMethod method, GrChangeSignatureDialog dialog) { + public GrParameterTableModel(GrMethod method, GrChangeSignatureDialog dialog, Project project) { myMethod = method; myDialog = dialog; final GrParameter[] parameters = myMethod.getParameters(); @@ -43,11 +46,12 @@ public class GrParameterTableModel extends AbstractTableModel implements RowEdit GrParameter parameter = parameters[i]; infos.add(new GrParameterInfo(parameter, i)); } + myProject=project; } public void addRow() { final int row = infos.size(); - infos.add(new GrParameterInfo()); + infos.add(new GrParameterInfo(myProject, myMethod)); fireTableRowsInserted(row, row); } @@ -95,7 +99,7 @@ public class GrParameterTableModel extends AbstractTableModel implements RowEdit if (rowIndex < 0 || rowIndex >= infos.size()) return; if (columnIndex < 0 || columnIndex > 3) return; - String s = value instanceof String ? (String)value : ""; + /*String s = value instanceof String ? (String)value : ""; s = s.trim(); final GrParameterInfo info = infos.get(rowIndex); switch (columnIndex) { @@ -107,7 +111,7 @@ public class GrParameterTableModel extends AbstractTableModel implements RowEdit info.setDefaultInitializer(s); case 3: info.setDefaultValue(s); - } + }*/ fireTableCellUpdated(rowIndex, columnIndex); } @@ -130,9 +134,24 @@ public class GrParameterTableModel extends AbstractTableModel implements RowEdit @Override public Class getColumnClass(int columnIndex) { - if (columnIndex < 0 || columnIndex > 3) throw new IllegalArgumentException(); - return String.class; + switch (columnIndex) { + case 0: + return PsiCodeFragment.class; + case 1: + case 2: + case 3: + return GroovyCodeFragment.class; + default: + throw new IllegalArgumentException(); + } } - + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) { + return true; + } + + public List getParameterInfos() { + return infos; + } } \ No newline at end of file diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/ui/GrCodeFragmentTableCellEditor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/ui/GrCodeFragmentTableCellEditor.java new file mode 100644 index 000000000000..b14f9b10085b --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/ui/GrCodeFragmentTableCellEditor.java @@ -0,0 +1,70 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.groovy.refactoring.ui; + +import com.intellij.codeInsight.daemon.impl.JavaReferenceImporter; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.ui.EditorTextField; +import org.jetbrains.plugins.groovy.GroovyFileType; +import org.jetbrains.plugins.groovy.debugger.fragments.GroovyCodeFragment; + +import javax.swing.*; +import javax.swing.table.TableCellEditor; +import java.awt.*; + +/** + * @author Maxim.Medvedev + */ +public class GrCodeFragmentTableCellEditor extends AbstractCellEditor implements TableCellEditor { + private GroovyCodeFragment myCodeFragment; + private Document myDocument; + private Project myProject; + private EditorTextField myEditorTextField; + + public GrCodeFragmentTableCellEditor(Project project) { + myProject = project; + } + + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + myCodeFragment = (GroovyCodeFragment)value; + + myDocument = PsiDocumentManager.getInstance(myProject).getDocument(myCodeFragment); + myEditorTextField = new EditorTextField(myDocument, myProject, GroovyFileType.GROOVY_FILE_TYPE) { + protected boolean shouldHaveBorder() { + return false; + } + }; + return myEditorTextField; + } + + public Object getCellEditorValue() { + return myCodeFragment; + } + + @Override + public boolean stopCellEditing() { + final Editor editor = myEditorTextField.getEditor(); + if (editor != null) { + JavaReferenceImporter.autoImportReferenceAtCursor(editor, myCodeFragment, true); + } + super.stopCellEditing(); + PsiDocumentManager.getInstance(myProject).commitDocument(myDocument); + return true; + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/ui/GrCodeFragmentTableCellRenderer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/ui/GrCodeFragmentTableCellRenderer.java new file mode 100644 index 000000000000..6b56982bb90d --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/ui/GrCodeFragmentTableCellRenderer.java @@ -0,0 +1,67 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.groovy.refactoring.ui; + +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiCodeFragment; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.ui.EditorTextField; +import org.jetbrains.plugins.groovy.GroovyFileType; +import org.jetbrains.plugins.groovy.debugger.fragments.GroovyCodeFragment; + +import javax.swing.*; +import javax.swing.table.TableCellRenderer; +import java.awt.*; + +/** + * @author Maxim.Medvedev + */ +public class GrCodeFragmentTableCellRenderer implements TableCellRenderer { + private final Project myProject; + + public GrCodeFragmentTableCellRenderer(Project project) { + myProject = project; + } + + public Component getTableCellRendererComponent(JTable table, + Object value, + boolean isSelected, + final boolean hasFocus, + int row, + int column) { + PsiCodeFragment codeFragment = (GroovyCodeFragment)value; + + final EditorTextField editorTextField; + if (codeFragment != null) { + Document document = PsiDocumentManager.getInstance(myProject).getDocument(codeFragment); + editorTextField = new EditorTextField(document, myProject, GroovyFileType.GROOVY_FILE_TYPE) { + protected boolean shouldHaveBorder() { + return false; + } + }; + } + else { + editorTextField = new EditorTextField("", myProject, GroovyFileType.GROOVY_FILE_TYPE) { + protected boolean shouldHaveBorder() { + return false; + } + }; + } + editorTextField.setBorder(hasFocus ? BorderFactory.createLineBorder(table.getForeground()) : null); + return editorTextField; + } +} From f304012e1a5a1834d27a7be4e6382b099eed3232 Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Mon, 15 Mar 2010 19:20:33 +0300 Subject: [PATCH 003/212] change signature dialog --- .../ChangeSignatureViewDescriptor.java | 4 +- .../GrChangeSignatureDialog.form | 2 +- .../GrChangeSignatureDialog.java | 139 +++++++++++++++--- .../GrChangeSignatureProcessor.java | 108 +++++++++++++- .../changeSignature/GrParameterInfo.java | 17 ++- 5 files changed, 239 insertions(+), 31 deletions(-) diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureViewDescriptor.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureViewDescriptor.java index 86ce5b030019..cd453595851e 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureViewDescriptor.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureViewDescriptor.java @@ -20,16 +20,16 @@ */ package com.intellij.refactoring.changeSignature; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiMethod; import com.intellij.refactoring.RefactoringBundle; import com.intellij.usageView.UsageViewBundle; import com.intellij.usageView.UsageViewDescriptor; import com.intellij.usageView.UsageViewUtil; -import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NotNull; -class ChangeSignatureViewDescriptor implements UsageViewDescriptor { +public class ChangeSignatureViewDescriptor implements UsageViewDescriptor { private final PsiMethod myMethod; private final String myProcessedElementsHeader; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.form b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.form index 6baa6a42b2b4..9036d53d1a4a 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.form +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.form @@ -132,7 +132,7 @@ - + diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java index 6b812eb426e7..22cf9c2333eb 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java @@ -17,17 +17,23 @@ package org.jetbrains.plugins.groovy.refactoring.changeSignature; import com.intellij.openapi.editor.Document; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.JavaPsiFacade; import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiType; import com.intellij.psi.PsiTypeCodeFragment; +import com.intellij.refactoring.HelpID; import com.intellij.refactoring.ui.CodeFragmentTableCellEditor; import com.intellij.refactoring.ui.CodeFragmentTableCellRenderer; +import com.intellij.refactoring.ui.RefactoringDialog; +import com.intellij.refactoring.util.CanonicalTypes; +import com.intellij.refactoring.util.CommonRefactoringUtil; import com.intellij.ui.EditorTextField; +import com.intellij.ui.TableUtil; import com.intellij.util.ui.Table; import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.groovy.GroovyFileType; import org.jetbrains.plugins.groovy.debugger.fragments.GroovyCodeFragment; +import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement; @@ -44,13 +50,12 @@ import java.util.List; /** * @author Maxim.Medvedev */ -public class GrChangeSignatureDialog extends DialogWrapper { +public class GrChangeSignatureDialog extends RefactoringDialog { private EditorTextField myNameField; private EditorTextField myReturnTypeField; private JRadioButton myPublicRadioButton; - private JRadioButton myProtectedRadioButton; - private JRadioButton myPrivateRadioButton1; + private JRadioButton myPrivateRadioButton; private JPanel myParametersPanel; private Table myParameterTable; private JButton myAddButton; @@ -61,12 +66,12 @@ public class GrChangeSignatureDialog extends DialogWrapper { private JLabel mySignatureLabel; private GrParameterTableModel myParameterModel; private GrMethod myMethod; - private Project myProject; +// private Project myProject; private PsiTypeCodeFragment myReturnTypeCodeFragment; + private GroovyCodeFragment myNameCodeFragment; public GrChangeSignatureDialog(@NotNull Project project, GrMethod method) { super(project, true); - myProject = project; myMethod = method; init(); configureParameterButtons(); @@ -121,10 +126,8 @@ public class GrChangeSignatureDialog extends DialogWrapper { super.init(); } - @Override - protected void doOKAction() { - super.doOKAction(); - + private void stopEditing() { + TableUtil.stopEditing(myParameterTable); } @Override @@ -139,7 +142,10 @@ public class GrChangeSignatureDialog extends DialogWrapper { } private void createNameAndReturnTypeEditors() { - myNameField = new EditorTextField("", myProject, GroovyFileType.GROOVY_FILE_TYPE); + myNameCodeFragment = new GroovyCodeFragment(myProject, ""); + myNameField = new EditorTextField(PsiDocumentManager.getInstance(myProject).getDocument(myNameCodeFragment), myProject, + myNameCodeFragment.getFileType()); + myReturnTypeCodeFragment = JavaPsiFacade.getInstance(myProject).getElementFactory().createTypeCodeFragment("", myMethod, true, true); final Document document = PsiDocumentManager.getInstance(myProject).getDocument(myReturnTypeCodeFragment); myReturnTypeField = new EditorTextField(document, myProject, myReturnTypeCodeFragment.getFileType()); @@ -166,8 +172,10 @@ public class GrChangeSignatureDialog extends DialogWrapper { myParameterTable.getColumnModel().getColumn(2).setCellEditor(new GrCodeFragmentTableCellEditor(myProject)); myParameterTable.getColumnModel().getColumn(3).setCellEditor(new GrCodeFragmentTableCellEditor(myProject)); - myParameterTable.setRowSelectionInterval(0, 0); - myParameterTable.setColumnSelectionInterval(0, 0); + if (myParameterTable.getRowCount() > 0) { + myParameterTable.setRowSelectionInterval(0, 0); + myParameterTable.setColumnSelectionInterval(0, 0); + } myParameterModel.addTableModelListener(new TableModelListener() { public void tableChanged(TableModelEvent e) { @@ -188,13 +196,19 @@ public class GrChangeSignatureDialog extends DialogWrapper { } private String generateSignatureText() { - String name = myNameField.getText().trim(); + String name = getNewName(); String type = myReturnTypeField.getText().trim(); - if (type.length() == 0) { - type = GrModifier.DEF; - } StringBuilder builder = new StringBuilder(); + if (myPublicRadioButton.isSelected() && type.length() == 0) { + builder.append(GrModifier.DEF); + } + if (myPrivateRadioButton.isSelected()) { + builder.append(GrModifier.PRIVATE).append(' '); + } + else if (myProtectedRadioButton.isSelected()) { + builder.append(GrModifier.PROTECTED).append(' '); + } builder.append(type).append(' '); builder.append(name).append('('); final List infos = myParameterModel.getParameterInfos(); @@ -214,7 +228,7 @@ public class GrChangeSignatureDialog extends DialogWrapper { private static void generateParameterText(GrParameterInfo info, StringBuilder builder) { final PsiTypeCodeFragment typeFragment = info.getType(); builder.append(typeFragment != null ? typeFragment.getText().trim() : GrModifier.DEF).append(' '); - final GroovyCodeFragment nameFragment = info.getName(); + final GroovyCodeFragment nameFragment = info.getNameFragment(); builder.append(nameFragment != null ? nameFragment.getText().trim() : ""); final GroovyCodeFragment defaultInitializer = info.getDefaultInitializer(); @@ -223,4 +237,91 @@ public class GrChangeSignatureDialog extends DialogWrapper { builder.append(" = ").append(defaultInitializerText); } } + + @Override + protected void doAction() { + if (!validateInputData()) { + return; + } + + stopEditing(); + String modifier = ""; + if (myPublicRadioButton.isSelected()) { + modifier = GrModifier.PUBLIC; + } + else if (myPrivateRadioButton.isSelected()) { + modifier = GrModifier.PRIVATE; + } + else if (myProtectedRadioButton.isSelected()) { + modifier = GrModifier.PROTECTED; + } + + PsiType returnType = null; + try { + returnType = myReturnTypeCodeFragment.getType(); + } + catch (PsiTypeCodeFragment.TypeSyntaxException e) { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } + catch (PsiTypeCodeFragment.NoTypeException e) { + returnType = PsiType.NULL; + } + + String newName = getNewName(); + final List parameterInfos = myParameterModel.getParameterInfos(); + invokeRefactoring(new GrChangeSignatureProcessor(myProject, new GrChangeSignatureProcessor.GrChangeInfoImpl(myMethod, modifier, + CanonicalTypes.createTypeWrapper( + returnType), newName, + parameterInfos))); + + } + + private String getNewName() { + return myNameField.getText().trim(); + } + + private boolean validateInputData() { + if (!checkName()) { + CommonRefactoringUtil.showErrorHint(myProject, null, "Name is wrong", "Incorrect data", HelpID.CHANGE_SIGNATURE); + return false; + } + + if (!checkType(myReturnTypeCodeFragment)) { + CommonRefactoringUtil.showErrorHint(myProject, null, "Return type is wrong", "Incorrect data", HelpID.CHANGE_SIGNATURE); + } + + for (GrParameterInfo info : myParameterModel.getParameterInfos()) { + if (!checkType(info.getType())) { + CommonRefactoringUtil + .showErrorHint(myProject, null, "Type for parameter " + info.getName() + " is wrong", "Incorrect data", HelpID.CHANGE_SIGNATURE); + return false; + } + } + return true; + } + + private boolean checkType(PsiTypeCodeFragment typeCodeFragment) { + try { + typeCodeFragment.getType(); + } + catch (PsiTypeCodeFragment.TypeSyntaxException e) { + return false; + } + catch (PsiTypeCodeFragment.NoTypeException e) { + return true; + } + return true; + } + + private boolean checkName() { + final String newName = getNewName(); + if (StringUtil.isJavaIdentifier(newName)) return true; + try { + GroovyPsiElementFactory.getInstance(myProject).createMethodFromText("def " + newName + "(){}"); + } + catch (Throwable e) { + return false; + } + return true; + } } \ No newline at end of file diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java index 76d650d3d2f3..0826dcf688e4 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java @@ -16,23 +16,38 @@ package org.jetbrains.plugins.groovy.refactoring.changeSignature; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Ref; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiMethod; import com.intellij.refactoring.BaseRefactoringProcessor; +import com.intellij.refactoring.changeSignature.ChangeInfo; +import com.intellij.refactoring.changeSignature.ChangeSignatureViewDescriptor; +import com.intellij.refactoring.changeSignature.ParameterInfo; +import com.intellij.refactoring.util.CanonicalTypes; import com.intellij.usageView.UsageInfo; import com.intellij.usageView.UsageViewDescriptor; +import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; + +import java.util.List; /** * @author Maxim.Medvedev */ -public class GrChangeSignatureProcessor extends BaseRefactoringProcessor{ - public GrChangeSignatureProcessor(Project project) { +public class GrChangeSignatureProcessor extends BaseRefactoringProcessor { + private final GrChangeInfoImpl myInfo; + + //private + + public GrChangeSignatureProcessor(Project project, GrChangeInfoImpl changeInfo) { super(project); + myInfo = changeInfo; } @Override protected UsageViewDescriptor createUsageViewDescriptor(UsageInfo[] usages) { - return null; //To change body of implemented methods use File | Settings | File Templates. + return new ChangeSignatureViewDescriptor(myInfo.getMethod()); } @NotNull @@ -48,12 +63,95 @@ public class GrChangeSignatureProcessor extends BaseRefactoringProcessor{ @Override protected void performRefactoring(UsageInfo[] usages) { - //To change body of implemented methods use File | Settings | File Templates. + changeMethod(); + } + + private void changeMethod() { + final PsiMethod method = myInfo.getMethod(); + if (myInfo.isChangeName()) { + method.setName(myInfo.getNewName()); + } + + if (myInfo.isChangeVisibility()) { + method.getModifierList().setModifierProperty(myInfo.getVisibilityModifier(), true); + } } @Override protected String getCommandName() { return ""; - //return RefactoringBundle.message("changing.signature.of.0", UsageViewUtil.getDescriptiveName(myChangeInfo.getMethod())); + //return RefactoringBundle.message("changing.signature.of.0", UsageViewUtil.getDescriptiveName(myInfo.getMethod())); + } + + + private MultiMap findConflicts(Ref refUsages) { + return new MultiMap();//todo + } + + @Override + protected boolean preprocessUsages(Ref refUsages) { + return showConflicts(findConflicts(refUsages)); + } + + static class GrChangeInfoImpl implements ChangeInfo { + private GrMethod myMethod; + private String myNewName; + private CanonicalTypes.Type myReturnType; + private String myVisibilityModifier; + private List myParameters; + private boolean myChangeParameters = false; + + public GrChangeInfoImpl(GrMethod method, + String visibilityModifier, + CanonicalTypes.Type returnType, + String newName, + List parameters) { + myMethod = method; + myVisibilityModifier = visibilityModifier; + myReturnType = returnType; + myParameters = parameters; + myNewName = newName; + + final int oldParameterCount = myMethod.getParameters().length; + if (oldParameterCount != myParameters.size()) { + myChangeParameters = true; + } + + for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) { + GrParameterInfo parameter = parameters.get(i); + if (parameter.getOldIndex() != i) { + myChangeParameters = true; + } + } + } + + @NotNull + public ParameterInfo[] getNewParameters() { + return myParameters.toArray(new GrParameterInfo[myParameters.size()]); + } + + public boolean isParameterSetOrOrderChanged() { + return myChangeParameters; + } + + public PsiMethod getMethod() { + return myMethod; + } + + public boolean isChangeVisibility() { + return !myMethod.getModifierList().hasModifierProperty(myVisibilityModifier); + } + + public boolean isChangeName() { + return !myMethod.getName().equals(myNewName); + } + + public String getNewName() { + return myNewName; + } + + public String getVisibilityModifier() { + return myVisibilityModifier; + } } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java index bdf0ff357c4f..127fea01d7ee 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java @@ -20,6 +20,7 @@ import com.intellij.psi.JavaPsiFacade; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiType; import com.intellij.psi.PsiTypeCodeFragment; +import com.intellij.refactoring.changeSignature.ParameterInfo; import org.jetbrains.plugins.groovy.debugger.fragments.GroovyCodeFragment; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; @@ -27,7 +28,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; /** * @author Maxim.Medvedev */ -public class GrParameterInfo { +public class GrParameterInfo implements ParameterInfo{ private GroovyCodeFragment myName; private GroovyCodeFragment myDefaultValue; private PsiTypeCodeFragment myType; @@ -56,11 +57,11 @@ public class GrParameterInfo { myDefaultInitializer = new GroovyCodeFragment(project, ""); } - public GroovyCodeFragment getName() { + public GroovyCodeFragment getNameFragment() { return myName; } - public GroovyCodeFragment getDefaultValue() { + public GroovyCodeFragment getDefaultValueFragment() { return myDefaultValue; } @@ -72,7 +73,15 @@ public class GrParameterInfo { return myDefaultInitializer; } - public int getPosition() { + public String getName() { + return myName.getText().trim(); + } + + public int getOldIndex() { return myPosition; } + + public String getDefaultValue() { + return myDefaultValue.getText().trim(); + } } From 3ccd6aca6ff67e0c96ccd1b27b66bd4b951b621f Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Wed, 17 Mar 2010 13:20:16 +0300 Subject: [PATCH 004/212] GrChangeSignature parameterTableModel --- .../changeSignature/GrChangeSignatureDialog.java | 6 +++--- .../changeSignature/GrChangeSignatureProcessor.java | 4 ++++ .../refactoring/changeSignature/GrParameterInfo.java | 11 +++++++++-- .../changeSignature/GrParameterTableModel.java | 11 +++++------ 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java index 22cf9c2333eb..220d82b3140a 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java @@ -226,7 +226,7 @@ public class GrChangeSignatureDialog extends RefactoringDialog { private static void generateParameterText(GrParameterInfo info, StringBuilder builder) { - final PsiTypeCodeFragment typeFragment = info.getType(); + final PsiTypeCodeFragment typeFragment = info.getTypeFragment(); builder.append(typeFragment != null ? typeFragment.getText().trim() : GrModifier.DEF).append(' '); final GroovyCodeFragment nameFragment = info.getNameFragment(); builder.append(nameFragment != null ? nameFragment.getText().trim() : ""); @@ -291,7 +291,7 @@ public class GrChangeSignatureDialog extends RefactoringDialog { } for (GrParameterInfo info : myParameterModel.getParameterInfos()) { - if (!checkType(info.getType())) { + if (!checkType(info.getTypeFragment())) { CommonRefactoringUtil .showErrorHint(myProject, null, "Type for parameter " + info.getName() + " is wrong", "Incorrect data", HelpID.CHANGE_SIGNATURE); return false; @@ -308,7 +308,7 @@ public class GrChangeSignatureDialog extends RefactoringDialog { return false; } catch (PsiTypeCodeFragment.NoTypeException e) { - return true; + return true; //Groovy accepts methods and parameters without explicit type } return true; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java index 0826dcf688e4..6fd842d9081f 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java @@ -19,6 +19,8 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Ref; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiMethod; +import com.intellij.psi.PsiReference; +import com.intellij.psi.search.searches.MethodReferencesSearch; import com.intellij.refactoring.BaseRefactoringProcessor; import com.intellij.refactoring.changeSignature.ChangeInfo; import com.intellij.refactoring.changeSignature.ChangeSignatureViewDescriptor; @@ -30,6 +32,7 @@ import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; +import java.util.Collection; import java.util.List; /** @@ -53,6 +56,7 @@ public class GrChangeSignatureProcessor extends BaseRefactoringProcessor { @NotNull @Override protected UsageInfo[] findUsages() { + final Collection collection = MethodReferencesSearch.search(myInfo.getMethod()).findAll(); return new UsageInfo[0]; //To change body of implemented methods use File | Settings | File Templates. } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java index 127fea01d7ee..781a625495da 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java @@ -28,7 +28,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; /** * @author Maxim.Medvedev */ -public class GrParameterInfo implements ParameterInfo{ +public class GrParameterInfo implements ParameterInfo { private GroovyCodeFragment myName; private GroovyCodeFragment myDefaultValue; private PsiTypeCodeFragment myType; @@ -43,10 +43,17 @@ public class GrParameterInfo implements ParameterInfo{ if (type != null) { myType = JavaPsiFacade.getElementFactory(project).createTypeCodeFragment(type.getCanonicalText(), parameter, true, true); } + else { + myType = JavaPsiFacade.getElementFactory(project).createTypeCodeFragment("", parameter, true, true); + } final GrExpression defaultInitializer = parameter.getDefaultInitializer(); if (defaultInitializer != null) { myDefaultInitializer = new GroovyCodeFragment(project, defaultInitializer.getText()); } + else { + myDefaultInitializer = new GroovyCodeFragment(project, ""); + } + myDefaultValue = new GroovyCodeFragment(project, ""); } public GrParameterInfo(Project project, PsiElement context) { @@ -65,7 +72,7 @@ public class GrParameterInfo implements ParameterInfo{ return myDefaultValue; } - public PsiTypeCodeFragment getType() { + public PsiTypeCodeFragment getTypeFragment() { return myType; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterTableModel.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterTableModel.java index 821c2c9ae415..14086babd758 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterTableModel.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterTableModel.java @@ -46,7 +46,7 @@ public class GrParameterTableModel extends AbstractTableModel implements RowEdit GrParameter parameter = parameters[i]; infos.add(new GrParameterInfo(parameter, i)); } - myProject=project; + myProject = project; } public void addRow() { @@ -82,13 +82,13 @@ public class GrParameterTableModel extends AbstractTableModel implements RowEdit final GrParameterInfo info = infos.get(rowIndex); switch (columnIndex) { case 0: - return info.getType(); + return info.getTypeFragment(); case 1: - return info.getName(); + return info.getNameFragment(); case 2: return info.getDefaultInitializer(); case 3: - return info.getDefaultValue(); + return info.getDefaultValueFragment(); default: throw new IllegalArgumentException(); } @@ -98,7 +98,6 @@ public class GrParameterTableModel extends AbstractTableModel implements RowEdit public void setValueAt(Object value, int rowIndex, int columnIndex) { if (rowIndex < 0 || rowIndex >= infos.size()) return; if (columnIndex < 0 || columnIndex > 3) return; - /*String s = value instanceof String ? (String)value : ""; s = s.trim(); final GrParameterInfo info = infos.get(rowIndex); @@ -142,7 +141,7 @@ public class GrParameterTableModel extends AbstractTableModel implements RowEdit case 3: return GroovyCodeFragment.class; default: - throw new IllegalArgumentException(); + throw new IllegalArgumentException(); } } From 1b1ef15a323c8432485bafa38e0c1119c77e9274 Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Sun, 4 Apr 2010 20:45:02 +0400 Subject: [PATCH 005/212] JavaChangeSignatureUsageProcessor --- .../ChangeSignatureProcessor.java | 371 ++------------ .../changeSignature/JavaChangeInfo.java | 40 ++ ...eInfoImpl.java => JavaChangeInfoImpl.java} | 72 ++- .../JavaChangeSignatureHandler.java | 2 +- .../JavaChangeSignatureUsageProcessor.java | 461 ++++++++++++++++++ .../changeSignature/JavaParameterInfo.java | 30 ++ .../changeSignature/ParameterInfoImpl.java | 2 +- .../changeSignature/ChangeInfo.java | 18 + .../ChangeSignatureUsageProcessor.java | 36 ++ .../src/META-INF/LangExtensionPoints.xml | 2 + .../GrChangeSignatureHandler.java | 8 +- .../GrChangeSignatureProcessor.java | 115 +++-- .../changeSignature/GrParameterInfo.java | 25 +- resources/src/META-INF/IdeaPlugin.xml | 5 +- 14 files changed, 798 insertions(+), 389 deletions(-) create mode 100644 java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfo.java rename java/java-impl/src/com/intellij/refactoring/changeSignature/{ChangeInfoImpl.java => JavaChangeInfoImpl.java} (82%) create mode 100644 java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java create mode 100644 java/java-impl/src/com/intellij/refactoring/changeSignature/JavaParameterInfo.java create mode 100644 platform/lang-api/src/com/intellij/refactoring/changeSignature/ChangeSignatureUsageProcessor.java diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java index 2c7a3c5f9e79..fef08e7f05df 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java @@ -26,28 +26,22 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Ref; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.codeStyle.VariableKind; -import com.intellij.psi.javadoc.PsiDocTagValue; import com.intellij.psi.scope.processor.VariablesProcessor; import com.intellij.psi.scope.util.PsiScopesUtil; -import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.search.searches.MethodReferencesSearch; -import com.intellij.psi.search.searches.OverridingMethodsSearch; -import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.util.*; -import com.intellij.psi.xml.XmlElement; import com.intellij.refactoring.BaseRefactoringProcessor; import com.intellij.refactoring.RefactoringBundle; -import com.intellij.refactoring.rename.JavaUnresolvableLocalCollisionDetector; -import com.intellij.refactoring.rename.RenameUtil; -import com.intellij.refactoring.rename.UnresolvableCollisionUsageInfo; +import com.intellij.refactoring.changeSignature.JavaChangeSignatureUsageProcessor.MyParameterUsageInfo; import com.intellij.refactoring.ui.ConflictsDialog; -import com.intellij.refactoring.util.*; +import com.intellij.refactoring.util.CanonicalTypes; +import com.intellij.refactoring.util.FieldConflictsResolver; +import com.intellij.refactoring.util.MoveRenameUsageInfo; +import com.intellij.refactoring.util.RefactoringUtil; import com.intellij.refactoring.util.usageInfo.DefaultConstructorImplicitUsageInfo; import com.intellij.refactoring.util.usageInfo.NoConstructorClassUsageInfo; import com.intellij.usageView.UsageInfo; @@ -66,12 +60,9 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor { private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.changeSignature.ChangeSignatureProcessor"); @Modifier private final String myNewVisibility; - private final ChangeInfoImpl myChangeInfo; + private final JavaChangeInfoImpl myChangeInfo; private final PsiManager myManager; private final PsiElementFactory myFactory; - private final boolean myGenerateDelegate; - private final Set myPropagateParametersMethods; - private final Set myPropagateExceptionsMethods; public ChangeSignatureProcessor(Project project, PsiMethod method, @@ -111,10 +102,11 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor { super(project); myManager = PsiManager.getInstance(project); myFactory = JavaPsiFacade.getInstance(myManager.getProject()).getElementFactory(); - myGenerateDelegate = generateDelegate; - myPropagateParametersMethods = propagateParametersMethods != null ? propagateParametersMethods : new HashSet(); - myPropagateExceptionsMethods = propagateExceptionsMethods != null ? propagateExceptionsMethods : new HashSet(); + Set myPropagateParametersMethods = + propagateParametersMethods != null ? propagateParametersMethods : new HashSet(); + Set myPropagateExceptionsMethods = + propagateExceptionsMethods != null ? propagateExceptionsMethods : new HashSet(); LOG.assertTrue(method.isValid()); if (newVisibility == null) { @@ -123,7 +115,7 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor { myNewVisibility = newVisibility; } - myChangeInfo = new ChangeInfoImpl(myNewVisibility, method, newName, newType, parameterInfo, thrownExceptions); + myChangeInfo = new JavaChangeInfoImpl(myNewVisibility, method, newName, newType, parameterInfo, thrownExceptions, generateDelegate, myPropagateParametersMethods, myPropagateExceptionsMethods); LOG.assertTrue(myChangeInfo.getMethod().isValid()); } @@ -133,200 +125,17 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor { @NotNull protected UsageInfo[] findUsages() { - ArrayList result = new ArrayList(); - final PsiMethod method = myChangeInfo.getMethod(); + List infos = new ArrayList(); - findSimpleUsages(method, result); - - final UsageInfo[] usageInfos = result.toArray(new UsageInfo[result.size()]); - return UsageViewUtil.removeDuplicatedUsages(usageInfos); - } - - private void findSimpleUsages(final PsiMethod method, final ArrayList result) { - PsiMethod[] overridingMethods = findSimpleUsagesWithoutParameters(method, result, true, true, true); - findUsagesInCallers (result); - - //Parameter name changes are not propagated - findParametersUsage(method, result, overridingMethods); - } - - private PsiMethod[] findSimpleUsagesWithoutParameters(final PsiMethod method, - final ArrayList result, - boolean isToModifyArgs, - boolean isToThrowExceptions, - boolean isOriginal) { - - GlobalSearchScope projectScope = GlobalSearchScope.projectScope(myProject); - PsiMethod[] overridingMethods = OverridingMethodsSearch.search(method, method.getUseScope(), true).toArray(PsiMethod.EMPTY_ARRAY); - - for (PsiMethod overridingMethod : overridingMethods) { - result.add(new OverriderUsageInfo(overridingMethod, method, isOriginal, isToModifyArgs, isToThrowExceptions)); + final ChangeSignatureUsageProcessor[] processors = ChangeSignatureUsageProcessor.EP_NAME.getExtensions(); + for (ChangeSignatureUsageProcessor processor : processors) { + infos.addAll(Arrays.asList(processor.findUsages(myChangeInfo))); } - - boolean needToChangeCalls = !myGenerateDelegate && (myChangeInfo.isNameChanged || myChangeInfo.isParameterSetOrOrderChanged || myChangeInfo.isExceptionSetOrOrderChanged || myChangeInfo.isVisibilityChanged/*for checking inaccessible*/); - if (needToChangeCalls) { - int parameterCount = method.getParameterList().getParametersCount(); - - PsiReference[] refs = MethodReferencesSearch.search(method, projectScope, true).toArray(PsiReference.EMPTY_ARRAY); - for (PsiReference ref : refs) { - PsiElement element = ref.getElement(); - boolean isToCatchExceptions = isToThrowExceptions && needToCatchExceptions(RefactoringUtil.getEnclosingMethod(element)); - if (!isToCatchExceptions) { - if (RefactoringUtil.isMethodUsage(element)) { - PsiExpressionList list = RefactoringUtil.getArgumentListByMethodReference(element); - if (!method.isVarArgs() && list.getExpressions().length != parameterCount) continue; - } - } - if (RefactoringUtil.isMethodUsage(element)) { - result.add(new MethodCallUsageInfo(element, isToModifyArgs, isToCatchExceptions)); - } - else if (element instanceof PsiDocTagValue) { - result.add(new UsageInfo(ref.getElement())); - } - else if (element instanceof PsiMethod && ((PsiMethod)element).isConstructor()) { - DefaultConstructorImplicitUsageInfo implicitUsageInfo = new DefaultConstructorImplicitUsageInfo((PsiMethod)element, - ((PsiMethod)element).getContainingClass(), method); - result.add(implicitUsageInfo); - } - else if(element instanceof PsiClass) { - LOG.assertTrue(method.isConstructor()); - final PsiClass psiClass = (PsiClass)element; - if (shouldPropagateToNonPhysicalMethod(method, result, psiClass, myPropagateParametersMethods)) continue; - if (shouldPropagateToNonPhysicalMethod(method, result, psiClass, myPropagateExceptionsMethods)) continue; - result.add(new NoConstructorClassUsageInfo(psiClass)); - } - else if (ref instanceof PsiCallReference) { - result.add(new CallReferenceUsageInfo((PsiCallReference) ref)); - } - else { - result.add(new MoveRenameUsageInfo(element, ref, method)); - } - } - - //if (method.isConstructor() && parameterCount == 0) { - // RefactoringUtil.visitImplicitConstructorUsages(method.getContainingClass(), - // new DefaultConstructorUsageCollector(result)); - //} - } - else if (myChangeInfo.isParameterTypesChanged) { - PsiReference[] refs = MethodReferencesSearch.search(method, projectScope, true).toArray(PsiReference.EMPTY_ARRAY); - for (PsiReference reference : refs) { - final PsiElement element = reference.getElement(); - if (element instanceof PsiDocTagValue) { - result.add(new UsageInfo(reference)); - } - else if (element instanceof XmlElement) { - result.add(new MoveRenameUsageInfo(reference, method)); - } - } - } - - // Conflicts - detectLocalsCollisionsInMethod(method, result, isOriginal); - for (final PsiMethod overridingMethod : overridingMethods) { - detectLocalsCollisionsInMethod(overridingMethod, result, isOriginal); - } - - return overridingMethods; - } - - private static boolean shouldPropagateToNonPhysicalMethod(PsiMethod method, ArrayList result, PsiClass containingClass, final Set propagateMethods) { - for (PsiMethod psiMethod : propagateMethods) { - if (!psiMethod.isPhysical() && Comparing.strEqual(psiMethod.getName(), containingClass.getName())) { - result.add(new DefaultConstructorImplicitUsageInfo(psiMethod, containingClass, method)); - return true; - } - } - return false; - } - - private void findUsagesInCallers(final ArrayList usages) { - for (PsiMethod caller : myPropagateParametersMethods) { - usages.add(new CallerUsageInfo(caller, true, myPropagateExceptionsMethods.contains(caller))); - } - for (PsiMethod caller : myPropagateExceptionsMethods) { - usages.add(new CallerUsageInfo(caller, myPropagateParametersMethods.contains(caller), true)); - } - Set merged = new HashSet(); - merged.addAll(myPropagateParametersMethods); - merged.addAll(myPropagateExceptionsMethods); - for (final PsiMethod method : merged) { - findSimpleUsagesWithoutParameters(method, usages, myPropagateParametersMethods.contains(method), - myPropagateExceptionsMethods.contains(method), false); - } - } - - private boolean needToChangeCalls() { - return myChangeInfo.isNameChanged || myChangeInfo.isParameterSetOrOrderChanged || myChangeInfo.isExceptionSetOrOrderChanged; + return infos.toArray(new UsageInfo[infos.size()]); } private boolean needToCatchExceptions(PsiMethod caller) { - return myChangeInfo.isExceptionSetOrOrderChanged && !myPropagateExceptionsMethods.contains(caller); - } - - private void detectLocalsCollisionsInMethod(final PsiMethod method, - final ArrayList result, - boolean isOriginal) { - final PsiParameter[] parameters = method.getParameterList().getParameters(); - final Set deletedOrRenamedParameters = new HashSet(); - if (isOriginal) { - deletedOrRenamedParameters.addAll(Arrays.asList(parameters)); - for (ParameterInfoImpl parameterInfo : myChangeInfo.newParms) { - if (parameterInfo.oldParameterIndex >= 0) { - final PsiParameter parameter = parameters[parameterInfo.oldParameterIndex]; - if (parameterInfo.getName().equals(parameter.getName())) { - deletedOrRenamedParameters.remove(parameter); - } - } - } - } - - for (ParameterInfoImpl parameterInfo : myChangeInfo.newParms) { - final int oldParameterIndex = parameterInfo.oldParameterIndex; - final String newName = parameterInfo.getName(); - if (oldParameterIndex >= 0) { - if (isOriginal) { //Name changes take place only in primary method - final PsiParameter parameter = parameters[oldParameterIndex]; - if (!newName.equals(parameter.getName())) { - JavaUnresolvableLocalCollisionDetector.visitLocalsCollisions(parameter, newName, method.getBody(), null, new JavaUnresolvableLocalCollisionDetector.CollidingVariableVisitor() { - public void visitCollidingElement(final PsiVariable collidingVariable) { - if (!deletedOrRenamedParameters.contains(collidingVariable)) { - result.add(new RenamedParameterCollidesWithLocalUsageInfo(parameter, collidingVariable, method)); - } - } - }); - } - } - } - else { - JavaUnresolvableLocalCollisionDetector.visitLocalsCollisions(method, newName, method.getBody(), null, new JavaUnresolvableLocalCollisionDetector.CollidingVariableVisitor() { - public void visitCollidingElement(PsiVariable collidingVariable) { - if (!deletedOrRenamedParameters.contains(collidingVariable)) { - result.add(new NewParameterCollidesWithLocalUsageInfo(collidingVariable, collidingVariable, method)); - } - } - }); - } - } - } - - private void findParametersUsage(final PsiMethod method, ArrayList result, PsiMethod[] overriders) { - PsiParameter[] parameters = method.getParameterList().getParameters(); - for (ParameterInfoImpl info : myChangeInfo.newParms) { - if (info.oldParameterIndex >= 0) { - PsiParameter parameter = parameters[info.oldParameterIndex]; - if (!info.getName().equals(parameter.getName())) { - addParameterUsages(parameter, result, info); - - for (PsiMethod overrider : overriders) { - PsiParameter parameter1 = overrider.getParameterList().getParameters()[info.oldParameterIndex]; - if (parameter.getName().equals(parameter1.getName())) { - addParameterUsages(parameter1, result, info); - } - } - } - } - } + return myChangeInfo.isExceptionSetOrOrderChanged && !myChangeInfo.propagateExceptionsMethods.contains(caller); } protected void refreshElements(PsiElement[] elements) { @@ -335,69 +144,29 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor { myChangeInfo.updateMethod((PsiMethod) elements[0]); } - private void addMethodConflicts(MultiMap conflicts) { - String newMethodName = myChangeInfo.newName; - - try { - PsiMethod prototype; - PsiManager manager = PsiManager.getInstance(myProject); - PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory(); - final PsiMethod method = myChangeInfo.getMethod(); - final CanonicalTypes.Type returnType = myChangeInfo.newReturnType; - if (returnType != null) { - prototype = factory.createMethod(newMethodName, returnType.getType(method, manager)); - } - else { - prototype = factory.createConstructor(); - prototype.setName(newMethodName); - } - ParameterInfoImpl[] parameters = myChangeInfo.newParms; - - - for (ParameterInfoImpl info : parameters) { - final PsiType parameterType = info.createType(method, manager); - PsiParameter param = factory.createParameter(info.getName(), parameterType); - prototype.getParameterList().add(param); - } - - ConflictsUtil.checkMethodConflicts( - method.getContainingClass(), - method, - prototype, conflicts); - } - catch (IncorrectOperationException e) { - LOG.error(e); - } - } - - protected boolean preprocessUsages(Ref refUsages) { MultiMap conflictDescriptions = new MultiMap(); - UsageInfo[] usagesIn = refUsages.get(); - addMethodConflicts(conflictDescriptions); - RenameUtil.addConflictDescriptions(usagesIn, conflictDescriptions); - Set usagesSet = new HashSet(Arrays.asList(usagesIn)); - RenameUtil.removeConflictUsages(usagesSet); - if (myChangeInfo.isVisibilityChanged) { - try { - addInaccessibilityDescriptions(usagesSet, conflictDescriptions); - } - catch (IncorrectOperationException e) { - LOG.error(e); + for (ChangeSignatureUsageProcessor usageProcessor : ChangeSignatureUsageProcessor.EP_NAME.getExtensions()) { + final MultiMap conflicts = usageProcessor.findConflicts(myChangeInfo, refUsages); + for (PsiElement key : conflicts.keySet()) { + Collection collection = conflictDescriptions.get(key); + collection.addAll(conflicts.get(key)); + conflictDescriptions.put(key, collection); } } + final Set usagesSet = new HashSet(Arrays.asList(refUsages.get())); if (myPrepareSuccessfulSwingThreadCallback != null && !conflictDescriptions.isEmpty()) { ConflictsDialog dialog = new ConflictsDialog(myProject, conflictDescriptions); dialog.show(); - if (!dialog.isOK()){ + if (!dialog.isOK()) { if (dialog.isShowConflicts()) prepareSuccessful(); return false; } } if (myChangeInfo.isReturnTypeChanged) { - askToRemoveCovariantOverriders (usagesSet); + askToRemoveCovariantOverriders(usagesSet); } refUsages.set(usagesSet.toArray(new UsageInfo[usagesSet.size()])); @@ -405,39 +174,6 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor { return true; } - private void addInaccessibilityDescriptions(Set usages, MultiMap conflictDescriptions) throws IncorrectOperationException { - PsiMethod method = myChangeInfo.getMethod(); - PsiModifierList modifierList = (PsiModifierList)method.getModifierList().copy(); - VisibilityUtil.setVisibility(modifierList, myNewVisibility); - - for (Iterator iterator = usages.iterator(); iterator.hasNext();) { - UsageInfo usageInfo = iterator.next(); - PsiElement element = usageInfo.getElement(); - if (element != null) { - if (element instanceof PsiReferenceExpression) { - PsiClass accessObjectClass = null; - PsiExpression qualifier = ((PsiReferenceExpression)element).getQualifierExpression(); - if (qualifier != null) { - accessObjectClass = (PsiClass)PsiUtil.getAccessObjectClass(qualifier).getElement(); - } - - if (!JavaPsiFacade.getInstance(element.getProject()).getResolveHelper() - .isAccessible(method, modifierList, element, accessObjectClass, null)) { - String message = - RefactoringBundle.message("0.with.1.visibility.is.not.accesible.from.2", - RefactoringUIUtil.getDescription(method, true), - myNewVisibility, - RefactoringUIUtil.getDescription(ConflictsUtil.getContainer(element), true)); - conflictDescriptions.putValue(method, message); - if (!needToChangeCalls()) { - iterator.remove(); - } - } - } - } - } - } - private void askToRemoveCovariantOverriders(Set usages) { if (PsiUtil.isLanguageLevel5OrHigher(myChangeInfo.getMethod())) { List covariantOverriderInfos = new ArrayList(); @@ -496,7 +232,7 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor { myChangeInfo.newTypeElement = myChangeInfo.newReturnType.getType(myChangeInfo.getMethod(), myManager); } - if (myGenerateDelegate) { + if (myChangeInfo.isGenerateDelegate) { generateDelegate(); } @@ -531,12 +267,12 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor { final DefaultConstructorImplicitUsageInfo defConstructorUsage = (DefaultConstructorImplicitUsageInfo)usage; PsiMethod constructor = defConstructorUsage.getConstructor(); if (!constructor.isPhysical()) { - final boolean toPropagate = myPropagateParametersMethods.remove(constructor); + final boolean toPropagate = myChangeInfo.propagateParametersMethods.remove(constructor); final PsiClass containingClass = defConstructorUsage.getContainingClass(); constructor = (PsiMethod)containingClass.add(constructor); PsiUtil.setModifierProperty(constructor, VisibilityUtil.getVisibilityModifier(containingClass.getModifierList()), true); if (toPropagate) { - myPropagateParametersMethods.add(constructor); + myChangeInfo.propagateParametersMethods.add(constructor); } } addSuperCall(constructor, defConstructorUsage.getBaseConstructor(),usages); @@ -708,7 +444,7 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor { } private void processMethodUsage(PsiElement ref, - ChangeInfoImpl changeInfo, + JavaChangeInfoImpl changeInfo, boolean toChangeArguments, boolean toCatchExceptions, PsiMethod callee, final UsageInfo[] usages) throws IncorrectOperationException { @@ -724,7 +460,7 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor { final PsiMethod caller = RefactoringUtil.getEnclosingMethod(ref); if (toChangeArguments) { final PsiExpressionList list = RefactoringUtil.getArgumentListByMethodReference(ref); - boolean toInsertDefaultValue = !myPropagateParametersMethods.contains(caller); + boolean toInsertDefaultValue = !myChangeInfo.propagateParametersMethods.contains(caller); if (toInsertDefaultValue && ref instanceof PsiReferenceExpression) { final PsiExpression qualifierExpression = ((PsiReferenceExpression) ref).getQualifierExpression(); if (qualifierExpression instanceof PsiSuperExpression && callerSignatureIsAboutToChangeToo(caller, usages)) { @@ -756,7 +492,7 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor { return callee.getThrowsList().getReferencedTypes(); //Callee method's throws list is already modified! } - private PsiClassType[] getPrimaryChangedExceptionInfo(ChangeInfoImpl changeInfo) throws IncorrectOperationException { + private PsiClassType[] getPrimaryChangedExceptionInfo(JavaChangeInfoImpl changeInfo) throws IncorrectOperationException { PsiClassType[] newExceptions = new PsiClassType[changeInfo.newExceptions.length]; for (int i = 0; i < newExceptions.length; i++) { newExceptions[i] = (PsiClassType)changeInfo.newExceptions[i].myType.getType(myChangeInfo.getMethod(), myManager); //context really does not matter here @@ -876,14 +612,14 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor { return true; } - private static int getNonVarargCount(ChangeInfoImpl changeInfo, PsiExpression[] args) { + private static int getNonVarargCount(JavaChangeInfoImpl changeInfo, PsiExpression[] args) { if (!changeInfo.wasVararg) return args.length; return changeInfo.oldParameterTypes.length - 1; } //This methods works equally well for primary usages as well as for propagated callers' usages private void fixActualArgumentsList(PsiExpressionList list, - ChangeInfoImpl changeInfo, + JavaChangeInfoImpl changeInfo, boolean toInsertDefaultValue) throws IncorrectOperationException { final PsiElementFactory factory = JavaPsiFacade.getInstance(list.getProject()).getElementFactory(); if (changeInfo.isParameterSetOrOrderChanged) { @@ -998,17 +734,6 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor { return callExpression != null ? info.getValue(callExpression) : factory.createExpressionFromText(info.defaultValue, list); } - private static void addParameterUsages(PsiParameter parameter, - ArrayList results, - ParameterInfoImpl info) { - PsiManager manager = parameter.getManager(); - GlobalSearchScope projectScope = GlobalSearchScope.projectScope(manager.getProject()); - for (PsiReference psiReference : ReferencesSearch.search(parameter, projectScope, false)) { - PsiElement parmRef = psiReference.getElement(); - UsageInfo usageInfo = new MyParameterUsageInfo(parmRef, parameter.getName(), info.getName()); - results.add(usageInfo); - } - } private void processCallerMethod(PsiMethod caller, PsiMethod baseMethod, @@ -1169,34 +894,6 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor { } } - private static class MyParameterUsageInfo extends UsageInfo { - final String oldParameterName; - final String newParameterName; - - public MyParameterUsageInfo(PsiElement element, String oldParameterName, String newParameterName) { - super(element); - this.oldParameterName = oldParameterName; - this.newParameterName = newParameterName; - } - } - - private static class RenamedParameterCollidesWithLocalUsageInfo extends UnresolvableCollisionUsageInfo { - private final PsiElement myCollidingElement; - private final PsiMethod myMethod; - - public RenamedParameterCollidesWithLocalUsageInfo(PsiParameter parameter, PsiElement collidingElement, PsiMethod method) { - super(parameter, collidingElement); - myCollidingElement = collidingElement; - myMethod = method; - } - - public String getDescription() { - return RefactoringBundle.message("there.is.already.a.0.in.the.1.it.will.conflict.with.the.renamed.parameter", - RefactoringUIUtil.getDescription(myCollidingElement, true), - RefactoringUIUtil.getDescription(myMethod, true)); - } - } - private void fixJavadocsForChangedMethod(PsiMethod method) throws IncorrectOperationException { final PsiParameter[] parameters = method.getParameterList().getParameters(); final ParameterInfoImpl[] newParms = myChangeInfo.newParms; diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfo.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfo.java new file mode 100644 index 000000000000..421e5b7b8fa4 --- /dev/null +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfo.java @@ -0,0 +1,40 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.refactoring.changeSignature; + +import com.intellij.psi.PsiMethod; +import com.intellij.refactoring.util.CanonicalTypes; +import org.jetbrains.annotations.NotNull; + +/** + * @author Maxim.Medvedev + */ +public interface JavaChangeInfo extends ChangeInfo { + boolean isVisibilityChanged(); + + boolean isExceptionSetChanged(); + + boolean isExceptionSetOrOrderChanged(); + + PsiMethod getMethod(); + + CanonicalTypes.Type getNewReturnType(); + + @NotNull + JavaParameterInfo[] getNewParameters(); + + String getNewVisibility(); +} diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeInfoImpl.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfoImpl.java similarity index 82% rename from java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeInfoImpl.java rename to java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfoImpl.java index 95db6722a643..f5411c48a927 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeInfoImpl.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfoImpl.java @@ -20,6 +20,8 @@ */ package com.intellij.refactoring.changeSignature; +import com.intellij.lang.Language; +import com.intellij.lang.StdLanguages; import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.*; import com.intellij.refactoring.util.CanonicalTypes; @@ -30,9 +32,10 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Set; -class ChangeInfoImpl implements ChangeInfo { - private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.changeSignature.ChangeInfoImpl"); +class JavaChangeInfoImpl implements JavaChangeInfo { + private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.changeSignature.JavaChangeInfoImpl"); final String newVisibility; private PsiMethod method; @@ -62,15 +65,22 @@ class ChangeInfoImpl implements ChangeInfo { PsiType newTypeElement; final PsiExpression[] defaultValues; + final boolean isGenerateDelegate; + final Set propagateParametersMethods; + final Set propagateExceptionsMethods; + /** * @param newExceptions null if not changed */ - public ChangeInfoImpl(@Modifier String newVisibility, + public JavaChangeInfoImpl(@Modifier String newVisibility, PsiMethod method, String newName, CanonicalTypes.Type newType, @NotNull ParameterInfoImpl[] newParms, - ThrownExceptionInfo[] newExceptions) { + ThrownExceptionInfo[] newExceptions, + boolean generateDelegate, + Set propagateParametersMethods, + Set propagateExceptionsMethods) { this.newVisibility = newVisibility; this.method = method; this.newName = newName; @@ -78,6 +88,10 @@ class ChangeInfoImpl implements ChangeInfo { this.newParms = newParms; wasVararg = method.isVarArgs(); + this.isGenerateDelegate =generateDelegate; + this.propagateExceptionsMethods=propagateExceptionsMethods; + this.propagateParametersMethods=propagateParametersMethods; + oldName = method.getName(); final PsiManager manager = method.getManager(); if (!method.isConstructor()){ @@ -178,10 +192,14 @@ class ChangeInfoImpl implements ChangeInfo { } @NotNull - public ParameterInfo[] getNewParameters() { + public JavaParameterInfo[] getNewParameters() { return newParms; } + public String getNewVisibility() { + return newVisibility; + } + public boolean isParameterSetOrOrderChanged() { return isParameterSetOrOrderChanged; } @@ -240,6 +258,10 @@ class ChangeInfoImpl implements ChangeInfo { return method; } + public CanonicalTypes.Type getNewReturnType() { + return newReturnType; + } + public void updateMethod(PsiMethod method) { this.method = method; } @@ -259,4 +281,44 @@ class ChangeInfoImpl implements ChangeInfo { if (defaultValues[i] != null) return defaultValues[i]; return newParms[i].getValue(expr); } + + public boolean isVisibilityChanged() { + return isVisibilityChanged; + } + + public boolean isNameChanged() { + return isNameChanged; + } + + public boolean isReturnTypeChanged() { + return isReturnTypeChanged; + } + + public String getNewName() { + return newName; + } + + public Language getLanguage() { + return StdLanguages.JAVA; + } + + public boolean isExceptionSetChanged() { + return isExceptionSetChanged; + } + + public boolean isExceptionSetOrOrderChanged() { + return isExceptionSetOrOrderChanged; + } + + public boolean isParameterNamesChanged() { + return isParameterNamesChanged; + } + + public boolean isParameterTypesChanged() { + return isParameterTypesChanged; + } + + public boolean isGenerateDelegate() { + return isGenerateDelegate; + } } diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureHandler.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureHandler.java index d8d683553901..0a40702708d5 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2010 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java new file mode 100644 index 000000000000..875a65a39d23 --- /dev/null +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java @@ -0,0 +1,461 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.refactoring.changeSignature; + +import com.intellij.lang.StdLanguages; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Ref; +import com.intellij.psi.*; +import com.intellij.psi.javadoc.PsiDocTagValue; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.search.searches.MethodReferencesSearch; +import com.intellij.psi.search.searches.OverridingMethodsSearch; +import com.intellij.psi.search.searches.ReferencesSearch; +import com.intellij.psi.util.PsiUtil; +import com.intellij.psi.xml.XmlElement; +import com.intellij.refactoring.RefactoringBundle; +import com.intellij.refactoring.rename.JavaUnresolvableLocalCollisionDetector; +import com.intellij.refactoring.rename.RenameUtil; +import com.intellij.refactoring.rename.UnresolvableCollisionUsageInfo; +import com.intellij.refactoring.util.*; +import com.intellij.refactoring.util.usageInfo.DefaultConstructorImplicitUsageInfo; +import com.intellij.refactoring.util.usageInfo.NoConstructorClassUsageInfo; +import com.intellij.usageView.UsageInfo; +import com.intellij.usageView.UsageViewUtil; +import com.intellij.util.IncorrectOperationException; +import com.intellij.util.VisibilityUtil; +import com.intellij.util.containers.HashSet; +import com.intellij.util.containers.MultiMap; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.Set; + +/** + * @author Maxim.Medvedev + */ +public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsageProcessor { + private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.changeSignature.JavaChangeSignatureUsageProcessor"); + + private static boolean isJavaUsage(UsageInfo info) { + final PsiElement element = info.getElement(); + if (element == null) return false; + return element.getLanguage() == StdLanguages.JAVA; + } + + public UsageInfo[] findUsages(ChangeInfo info) { + if (info instanceof JavaChangeInfo) { + return new UsageSearcher((JavaChangeInfo)info).findUsages(); + } + else { + return UsageInfo.EMPTY_ARRAY; + } + } + + public MultiMap findConflicts(ChangeInfo info, Ref refUsages) { + if (info instanceof JavaChangeInfo) { + return new ConflictSearcher((JavaChangeInfo)info).findConflicts(refUsages); + } + else { + return new MultiMap(); + } + } + + public boolean processUsage(ChangeInfo changeInfo, UsageInfo usageInfo) { + if (!isJavaUsage(usageInfo)) return false; + + return true; + } + + private static class UsageSearcher { + private final JavaChangeInfo myChangeInfo; + + private UsageSearcher(JavaChangeInfo changeInfo) { + this.myChangeInfo = changeInfo; + } + + public UsageInfo[] findUsages() { + ArrayList result = new ArrayList(); + final PsiElement element = myChangeInfo.getMethod(); + if (element instanceof PsiMethod) { + final PsiMethod method = (PsiMethod)element; + + findSimpleUsages(method, result); + + final UsageInfo[] usageInfos = result.toArray(new UsageInfo[result.size()]); + return UsageViewUtil.removeDuplicatedUsages(usageInfos); + } + return UsageInfo.EMPTY_ARRAY; + } + + + private void findSimpleUsages(final PsiMethod method, final ArrayList result) { + PsiMethod[] overridingMethods = findSimpleUsagesWithoutParameters(method, result, true, true, true); + findUsagesInCallers(result); + + //Parameter name changes are not propagated + findParametersUsage(method, result, overridingMethods); + } + + private void findUsagesInCallers(final ArrayList usages) { + if (myChangeInfo instanceof JavaChangeInfoImpl) { + JavaChangeInfoImpl changeInfo = (JavaChangeInfoImpl)myChangeInfo; + + for (PsiMethod caller : changeInfo.propagateParametersMethods) { + usages.add(new CallerUsageInfo(caller, true, changeInfo.propagateExceptionsMethods.contains(caller))); + } + for (PsiMethod caller : changeInfo.propagateExceptionsMethods) { + usages.add(new CallerUsageInfo(caller, changeInfo.propagateParametersMethods.contains(caller), true)); + } + Set merged = new HashSet(); + merged.addAll(changeInfo.propagateParametersMethods); + merged.addAll(changeInfo.propagateExceptionsMethods); + for (final PsiMethod method : merged) { + findSimpleUsagesWithoutParameters(method, usages, changeInfo.propagateParametersMethods.contains(method), + changeInfo.propagateExceptionsMethods.contains(method), false); + } + } + } + + private void detectLocalsCollisionsInMethod(final PsiMethod method, final ArrayList result, boolean isOriginal) { + if (myChangeInfo.getLanguage().equals(StdLanguages.JAVA)) { + final PsiParameter[] parameters = method.getParameterList().getParameters(); + final Set deletedOrRenamedParameters = new HashSet(); + if (isOriginal) { + deletedOrRenamedParameters.addAll(Arrays.asList(parameters)); + for (ParameterInfo parameterInfo : myChangeInfo.getNewParameters()) { + if (parameterInfo.getOldIndex() >= 0) { + final PsiParameter parameter = parameters[parameterInfo.getOldIndex()]; + if (parameterInfo.getName().equals(parameter.getName())) { + deletedOrRenamedParameters.remove(parameter); + } + } + } + } + + for (ParameterInfo parameterInfo : myChangeInfo.getNewParameters()) { + final int oldParameterIndex = parameterInfo.getOldIndex(); + final String newName = parameterInfo.getName(); + if (oldParameterIndex >= 0) { + if (isOriginal) { //Name changes take place only in primary method + final PsiParameter parameter = parameters[oldParameterIndex]; + if (!newName.equals(parameter.getName())) { + JavaUnresolvableLocalCollisionDetector.visitLocalsCollisions(parameter, newName, method.getBody(), null, + new JavaUnresolvableLocalCollisionDetector.CollidingVariableVisitor() { + public void visitCollidingElement(final PsiVariable collidingVariable) { + if (!deletedOrRenamedParameters + .contains(collidingVariable)) { + result.add( + new RenamedParameterCollidesWithLocalUsageInfo( + parameter, collidingVariable, method)); + } + } + }); + } + } + } + else { + JavaUnresolvableLocalCollisionDetector.visitLocalsCollisions(method, newName, method.getBody(), null, + new JavaUnresolvableLocalCollisionDetector.CollidingVariableVisitor() { + public void visitCollidingElement(PsiVariable collidingVariable) { + if (!deletedOrRenamedParameters.contains(collidingVariable)) { + result.add(new NewParameterCollidesWithLocalUsageInfo( + collidingVariable, collidingVariable, method)); + } + } + }); + } + } + } + } + + private void findParametersUsage(final PsiMethod method, ArrayList result, PsiMethod[] overriders) { + if (StdLanguages.JAVA.equals(myChangeInfo.getLanguage())) { + PsiParameter[] parameters = method.getParameterList().getParameters(); + for (ParameterInfo info : myChangeInfo.getNewParameters()) { + if (info.getOldIndex() >= 0) { + PsiParameter parameter = parameters[info.getOldIndex()]; + if (!info.getName().equals(parameter.getName())) { + addParameterUsages(parameter, result, info); + + for (PsiMethod overrider : overriders) { + PsiParameter parameter1 = overrider.getParameterList().getParameters()[info.getOldIndex()]; + if (parameter.getName().equals(parameter1.getName())) { + addParameterUsages(parameter1, result, info); + } + } + } + } + } + } + } + + private static boolean shouldPropagateToNonPhysicalMethod(PsiMethod method, + ArrayList result, + PsiClass containingClass, + final Set propagateMethods) { + for (PsiMethod psiMethod : propagateMethods) { + if (!psiMethod.isPhysical() && Comparing.strEqual(psiMethod.getName(), containingClass.getName())) { + result.add(new DefaultConstructorImplicitUsageInfo(psiMethod, containingClass, method)); + return true; + } + } + return false; + } + + private PsiMethod[] findSimpleUsagesWithoutParameters(final PsiMethod method, + final ArrayList result, + boolean isToModifyArgs, + boolean isToThrowExceptions, + boolean isOriginal) { + + GlobalSearchScope projectScope = GlobalSearchScope.projectScope(method.getProject()); + PsiMethod[] overridingMethods = OverridingMethodsSearch.search(method, method.getUseScope(), true).toArray(PsiMethod.EMPTY_ARRAY); + + for (PsiMethod overridingMethod : overridingMethods) { + result.add(new OverriderUsageInfo(overridingMethod, method, isOriginal, isToModifyArgs, isToThrowExceptions)); + } + + boolean needToChangeCalls = + !myChangeInfo.isGenerateDelegate() && (myChangeInfo.isNameChanged() || + myChangeInfo.isParameterSetOrOrderChanged() || + myChangeInfo.isExceptionSetOrOrderChanged() || + myChangeInfo.isVisibilityChanged()/*for checking inaccessible*/); + if (needToChangeCalls) { + int parameterCount = method.getParameterList().getParametersCount(); + + PsiReference[] refs = MethodReferencesSearch.search(method, projectScope, true).toArray(PsiReference.EMPTY_ARRAY); + for (PsiReference ref : refs) { + PsiElement element = ref.getElement(); + boolean isToCatchExceptions = isToThrowExceptions && needToCatchExceptions(RefactoringUtil.getEnclosingMethod(element)); + if (!isToCatchExceptions) { + if (RefactoringUtil.isMethodUsage(element)) { + PsiExpressionList list = RefactoringUtil.getArgumentListByMethodReference(element); + if (!method.isVarArgs() && list.getExpressions().length != parameterCount) continue; + } + } + if (RefactoringUtil.isMethodUsage(element)) { + result.add(new MethodCallUsageInfo(element, isToModifyArgs, isToCatchExceptions)); + } + else if (element instanceof PsiDocTagValue) { + result.add(new UsageInfo(ref.getElement())); + } + else if (element instanceof PsiMethod && ((PsiMethod)element).isConstructor()) { + DefaultConstructorImplicitUsageInfo implicitUsageInfo = + new DefaultConstructorImplicitUsageInfo((PsiMethod)element, ((PsiMethod)element).getContainingClass(), method); + result.add(implicitUsageInfo); + } + else if (element instanceof PsiClass) { + LOG.assertTrue(method.isConstructor()); + final PsiClass psiClass = (PsiClass)element; + if (!(myChangeInfo instanceof JavaChangeInfoImpl)) continue; + if (shouldPropagateToNonPhysicalMethod(method, result, psiClass, + ((JavaChangeInfoImpl)myChangeInfo).propagateParametersMethods)) { + continue; + } + if (shouldPropagateToNonPhysicalMethod(method, result, psiClass, + ((JavaChangeInfoImpl)myChangeInfo).propagateExceptionsMethods)) { + continue; + } + result.add(new NoConstructorClassUsageInfo(psiClass)); + } + else if (ref instanceof PsiCallReference) { + result.add(new CallReferenceUsageInfo((PsiCallReference)ref)); + } + else { + result.add(new MoveRenameUsageInfo(element, ref, method)); + } + } + + //if (method.isConstructor() && parameterCount == 0) { + // RefactoringUtil.visitImplicitConstructorUsages(method.getContainingClass(), + // new DefaultConstructorUsageCollector(result)); + //} + } + else if (myChangeInfo.isParameterTypesChanged()) { + PsiReference[] refs = MethodReferencesSearch.search(method, projectScope, true).toArray(PsiReference.EMPTY_ARRAY); + for (PsiReference reference : refs) { + final PsiElement element = reference.getElement(); + if (element instanceof PsiDocTagValue) { + result.add(new UsageInfo(reference)); + } + else if (element instanceof XmlElement) { + result.add(new MoveRenameUsageInfo(reference, method)); + } + } + } + + // Conflicts + detectLocalsCollisionsInMethod(method, result, isOriginal); + for (final PsiMethod overridingMethod : overridingMethods) { + detectLocalsCollisionsInMethod(overridingMethod, result, isOriginal); + } + + return overridingMethods; + } + + + private static void addParameterUsages(PsiParameter parameter, ArrayList results, ParameterInfo info) { + PsiManager manager = parameter.getManager(); + GlobalSearchScope projectScope = GlobalSearchScope.projectScope(manager.getProject()); + for (PsiReference psiReference : ReferencesSearch.search(parameter, projectScope, false)) { + PsiElement parmRef = psiReference.getElement(); + UsageInfo usageInfo = new MyParameterUsageInfo(parmRef, parameter.getName(), info.getName()); + results.add(usageInfo); + } + } + + private boolean needToCatchExceptions(PsiMethod caller) { + if (myChangeInfo instanceof JavaChangeInfoImpl) { + return myChangeInfo.isExceptionSetOrOrderChanged() && + !((JavaChangeInfoImpl)myChangeInfo).propagateExceptionsMethods.contains(caller); + } + else { + return myChangeInfo.isExceptionSetOrOrderChanged(); + } + } + + private static class RenamedParameterCollidesWithLocalUsageInfo extends UnresolvableCollisionUsageInfo { + private final PsiElement myCollidingElement; + private final PsiMethod myMethod; + + public RenamedParameterCollidesWithLocalUsageInfo(PsiParameter parameter, PsiElement collidingElement, PsiMethod method) { + super(parameter, collidingElement); + myCollidingElement = collidingElement; + myMethod = method; + } + + public String getDescription() { + return RefactoringBundle.message("there.is.already.a.0.in.the.1.it.will.conflict.with.the.renamed.parameter", + RefactoringUIUtil.getDescription(myCollidingElement, true), + RefactoringUIUtil.getDescription(myMethod, true)); + } + } + } + + private static class ConflictSearcher { + private final JavaChangeInfo myChangeInfo; + + private ConflictSearcher(JavaChangeInfo changeInfo) { + this.myChangeInfo = changeInfo; + } + + public MultiMap findConflicts(Ref refUsages) { + MultiMap conflictDescriptions = new MultiMap(); + addMethodConflicts(conflictDescriptions); + UsageInfo[] usagesIn = refUsages.get(); + RenameUtil.addConflictDescriptions(usagesIn, conflictDescriptions); + Set usagesSet = new HashSet(Arrays.asList(usagesIn)); + RenameUtil.removeConflictUsages(usagesSet); + if (myChangeInfo.isVisibilityChanged()) { + try { + addInaccessibilityDescriptions(usagesSet, conflictDescriptions); + } + catch (IncorrectOperationException e) { + LOG.error(e); + } + } + + return conflictDescriptions; + } + + private boolean needToChangeCalls() { + return myChangeInfo.isNameChanged() || myChangeInfo.isParameterSetOrOrderChanged() || myChangeInfo.isExceptionSetOrOrderChanged(); + } + + + private void addInaccessibilityDescriptions(Set usages, MultiMap conflictDescriptions) throws IncorrectOperationException { + PsiMethod method = myChangeInfo.getMethod(); + PsiModifierList modifierList = (PsiModifierList)method.getModifierList().copy(); + VisibilityUtil.setVisibility(modifierList, myChangeInfo.getNewVisibility()); + + for (Iterator iterator = usages.iterator(); iterator.hasNext();) { + UsageInfo usageInfo = iterator.next(); + PsiElement element = usageInfo.getElement(); + if (element != null) { + if (element instanceof PsiReferenceExpression) { + PsiClass accessObjectClass = null; + PsiExpression qualifier = ((PsiReferenceExpression)element).getQualifierExpression(); + if (qualifier != null) { + accessObjectClass = (PsiClass)PsiUtil.getAccessObjectClass(qualifier).getElement(); + } + + if (!JavaPsiFacade.getInstance(element.getProject()).getResolveHelper() + .isAccessible(method, modifierList, element, accessObjectClass, null)) { + String message = + RefactoringBundle.message("0.with.1.visibility.is.not.accesible.from.2", + RefactoringUIUtil.getDescription(method, true), + myChangeInfo.getNewVisibility(), + RefactoringUIUtil.getDescription(ConflictsUtil.getContainer(element), true)); + conflictDescriptions.putValue(method, message); + if (!needToChangeCalls()) { + iterator.remove(); + } + } + } + } + } + } + + + private void addMethodConflicts(MultiMap conflicts) { + String newMethodName = myChangeInfo.getNewName(); + if (!(myChangeInfo instanceof JavaChangeInfo)) { + return; + } + try { + PsiMethod prototype; + final PsiMethod method = myChangeInfo.getMethod(); + PsiManager manager = PsiManager.getInstance(method.getProject()); + PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory(); + final CanonicalTypes.Type returnType = myChangeInfo.getNewReturnType(); + if (returnType != null) { + prototype = factory.createMethod(newMethodName, returnType.getType(method, manager)); + } + else { + prototype = factory.createConstructor(); + prototype.setName(newMethodName); + } + JavaParameterInfo[] parameters = myChangeInfo.getNewParameters(); + + + for (JavaParameterInfo info : parameters) { + final PsiType parameterType = info.createType(method, manager); + PsiParameter param = factory.createParameter(info.getName(), parameterType); + prototype.getParameterList().add(param); + } + + ConflictsUtil.checkMethodConflicts(method.getContainingClass(), method, prototype, conflicts); + } + catch (IncorrectOperationException e) { + LOG.error(e); + } + } + } + + static class MyParameterUsageInfo extends UsageInfo { + final String oldParameterName; + final String newParameterName; + + public MyParameterUsageInfo(PsiElement element, String oldParameterName, String newParameterName) { + super(element); + this.oldParameterName = oldParameterName; + this.newParameterName = newParameterName; + } + } +} diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaParameterInfo.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaParameterInfo.java new file mode 100644 index 000000000000..18a41ad8ccc8 --- /dev/null +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaParameterInfo.java @@ -0,0 +1,30 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.refactoring.changeSignature; + +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiManager; +import com.intellij.psi.PsiType; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.Nullable; + +/** + * @author Maxim.Medvedev + */ +public interface JavaParameterInfo extends ParameterInfo { + @Nullable + PsiType createType(PsiElement context, final PsiManager manager) throws IncorrectOperationException; +} diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/ParameterInfoImpl.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/ParameterInfoImpl.java index 8139d1488039..7f8aad2f12d5 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/ParameterInfoImpl.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/ParameterInfoImpl.java @@ -30,7 +30,7 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; -public class ParameterInfoImpl implements ParameterInfo { +public class ParameterInfoImpl implements JavaParameterInfo { private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.changeSignature.ParameterInfoImpl"); public final int oldParameterIndex; boolean useAnySingleVariable; diff --git a/platform/lang-api/src/com/intellij/refactoring/changeSignature/ChangeInfo.java b/platform/lang-api/src/com/intellij/refactoring/changeSignature/ChangeInfo.java index f9c7a8b4f340..6e37873a3118 100644 --- a/platform/lang-api/src/com/intellij/refactoring/changeSignature/ChangeInfo.java +++ b/platform/lang-api/src/com/intellij/refactoring/changeSignature/ChangeInfo.java @@ -16,6 +16,8 @@ package com.intellij.refactoring.changeSignature; +import com.intellij.lang.Language; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; /** @@ -34,4 +36,20 @@ public interface ChangeInfo { ParameterInfo[] getNewParameters(); boolean isParameterSetOrOrderChanged(); + + boolean isParameterTypesChanged(); + + boolean isParameterNamesChanged(); + + boolean isGenerateDelegate(); + + boolean isNameChanged(); + + PsiElement getMethod(); + + boolean isReturnTypeChanged(); + + String getNewName(); + + Language getLanguage(); } diff --git a/platform/lang-api/src/com/intellij/refactoring/changeSignature/ChangeSignatureUsageProcessor.java b/platform/lang-api/src/com/intellij/refactoring/changeSignature/ChangeSignatureUsageProcessor.java new file mode 100644 index 000000000000..6602ea05d708 --- /dev/null +++ b/platform/lang-api/src/com/intellij/refactoring/changeSignature/ChangeSignatureUsageProcessor.java @@ -0,0 +1,36 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.refactoring.changeSignature; + +import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.openapi.util.Ref; +import com.intellij.psi.PsiElement; +import com.intellij.usageView.UsageInfo; +import com.intellij.util.containers.MultiMap; + +/** + * @author Maxim.Medvedev + */ +public interface ChangeSignatureUsageProcessor { + ExtensionPointName EP_NAME = + new ExtensionPointName("com.intellij.refactoring.changeSignatureUsageProcessor"); + + UsageInfo[] findUsages(ChangeInfo info); + + MultiMap findConflicts(ChangeInfo info, Ref refUsages); + + boolean processUsage(ChangeInfo changeInfo, UsageInfo usageInfo); +} diff --git a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml index 8008a656bb6c..c8deea026371 100644 --- a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml +++ b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml @@ -210,6 +210,8 @@ + diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureHandler.java index 7383624792f6..0ff6bf70226f 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureHandler.java @@ -15,7 +15,6 @@ */ package org.jetbrains.plugins.groovy.refactoring.changeSignature; -import com.intellij.codeInsight.TargetElementUtil; import com.intellij.ide.util.SuperMethodWarningUtil; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.actionSystem.LangDataKeys; @@ -23,7 +22,9 @@ import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.ScrollType; import com.intellij.openapi.project.Project; -import com.intellij.psi.*; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiMethod; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.HelpID; import com.intellij.refactoring.RefactoringBundle; @@ -40,7 +41,6 @@ import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle; * @author Maxim.Medvedev */ public class GrChangeSignatureHandler implements ChangeSignatureHandler { - public static final String REFACTORING_NAME = GroovyRefactoringBundle.message("changeSignature.refactoring.name"); public void invoke(@NotNull Project project, Editor editor, PsiFile file, DataContext dataContext) { editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE); @@ -81,8 +81,6 @@ public class GrChangeSignatureHandler implements ChangeSignatureHandler { if (!CommonRefactoringUtil.checkReadOnlyStatus(project, method)) return; - final PsiClass containingClass = method.getContainingClass(); - final PsiReference refExpr = editor != null ? TargetElementUtil.findReference(editor) : null; if (!(method instanceof GrMethod)) return; //todo final GrChangeSignatureDialog dialog = new GrChangeSignatureDialog(project, (GrMethod)method); dialog.show(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java index 6fd842d9081f..19143d2ad0c9 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java @@ -15,6 +15,7 @@ */ package org.jetbrains.plugins.groovy.refactoring.changeSignature; +import com.intellij.lang.Language; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Ref; import com.intellij.psi.PsiElement; @@ -22,17 +23,17 @@ import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiReference; import com.intellij.psi.search.searches.MethodReferencesSearch; import com.intellij.refactoring.BaseRefactoringProcessor; -import com.intellij.refactoring.changeSignature.ChangeInfo; import com.intellij.refactoring.changeSignature.ChangeSignatureViewDescriptor; -import com.intellij.refactoring.changeSignature.ParameterInfo; +import com.intellij.refactoring.changeSignature.JavaChangeInfo; +import com.intellij.refactoring.changeSignature.JavaParameterInfo; import com.intellij.refactoring.util.CanonicalTypes; import com.intellij.usageView.UsageInfo; import com.intellij.usageView.UsageViewDescriptor; import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.groovy.GroovyFileType; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; -import java.util.Collection; import java.util.List; /** @@ -56,8 +57,12 @@ public class GrChangeSignatureProcessor extends BaseRefactoringProcessor { @NotNull @Override protected UsageInfo[] findUsages() { - final Collection collection = MethodReferencesSearch.search(myInfo.getMethod()).findAll(); - return new UsageInfo[0]; //To change body of implemented methods use File | Settings | File Templates. + final PsiReference[] refs = MethodReferencesSearch.search(myInfo.getMethod()).toArray(PsiReference.EMPTY_ARRAY); + for (PsiReference ref : refs) { + + } + + return UsageInfo.EMPTY_ARRAY;//todo } @Override @@ -97,65 +102,109 @@ public class GrChangeSignatureProcessor extends BaseRefactoringProcessor { return showConflicts(findConflicts(refUsages)); } - static class GrChangeInfoImpl implements ChangeInfo { - private GrMethod myMethod; - private String myNewName; - private CanonicalTypes.Type myReturnType; - private String myVisibilityModifier; - private List myParameters; - private boolean myChangeParameters = false; + static class GrChangeInfoImpl implements JavaChangeInfo { + final GrMethod method; + final String newName; + final CanonicalTypes.Type returnType; + final String visibilityModifier; + final List parameters; + boolean changeParameters = false; public GrChangeInfoImpl(GrMethod method, - String visibilityModifier, - CanonicalTypes.Type returnType, - String newName, - List parameters) { - myMethod = method; - myVisibilityModifier = visibilityModifier; - myReturnType = returnType; - myParameters = parameters; - myNewName = newName; + String visibilityModifier, + CanonicalTypes.Type returnType, + String newName, + List parameters) { + this.method = method; + this.visibilityModifier = visibilityModifier; + this.returnType = returnType; + this.parameters = parameters; + this.newName = newName; - final int oldParameterCount = myMethod.getParameters().length; - if (oldParameterCount != myParameters.size()) { - myChangeParameters = true; + final int oldParameterCount = this.method.getParameters().length; + if (oldParameterCount != this.parameters.size()) { + changeParameters = true; } for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) { GrParameterInfo parameter = parameters.get(i); if (parameter.getOldIndex() != i) { - myChangeParameters = true; + changeParameters = true; } } } @NotNull - public ParameterInfo[] getNewParameters() { - return myParameters.toArray(new GrParameterInfo[myParameters.size()]); + public JavaParameterInfo[] getNewParameters() { + return parameters.toArray(new GrParameterInfo[parameters.size()]); + } + + public String getNewVisibility() { + return null;//todo } public boolean isParameterSetOrOrderChanged() { - return myChangeParameters; + return changeParameters; + } + + public boolean isParameterTypesChanged() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean isParameterNamesChanged() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean isGenerateDelegate() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean isNameChanged() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean isVisibilityChanged() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean isExceptionSetChanged() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean isExceptionSetOrOrderChanged() { + return false; //To change body of implemented methods use File | Settings | File Templates. } public PsiMethod getMethod() { - return myMethod; + return method; + } + + public boolean isReturnTypeChanged() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + public CanonicalTypes.Type getNewReturnType() { + return returnType; } public boolean isChangeVisibility() { - return !myMethod.getModifierList().hasModifierProperty(myVisibilityModifier); + return !method.getModifierList().hasModifierProperty(visibilityModifier); } public boolean isChangeName() { - return !myMethod.getName().equals(myNewName); + return !method.getName().equals(newName); } public String getNewName() { - return myNewName; + return newName; + } + + public Language getLanguage() { + return GroovyFileType.GROOVY_LANGUAGE; } public String getVisibilityModifier() { - return myVisibilityModifier; + return visibilityModifier; } } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java index 781a625495da..487234d6bd74 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java @@ -16,11 +16,10 @@ package org.jetbrains.plugins.groovy.refactoring.changeSignature; import com.intellij.openapi.project.Project; -import com.intellij.psi.JavaPsiFacade; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiType; -import com.intellij.psi.PsiTypeCodeFragment; -import com.intellij.refactoring.changeSignature.ParameterInfo; +import com.intellij.psi.*; +import com.intellij.refactoring.changeSignature.JavaParameterInfo; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.debugger.fragments.GroovyCodeFragment; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; @@ -28,7 +27,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; /** * @author Maxim.Medvedev */ -public class GrParameterInfo implements ParameterInfo { +public class GrParameterInfo implements JavaParameterInfo { private GroovyCodeFragment myName; private GroovyCodeFragment myDefaultValue; private PsiTypeCodeFragment myType; @@ -91,4 +90,18 @@ public class GrParameterInfo implements ParameterInfo { public String getDefaultValue() { return myDefaultValue.getText().trim(); } + + @Nullable + public PsiType createType(PsiElement context, final PsiManager manager) throws IncorrectOperationException { + try { + return myType.getType(); + } + catch (PsiTypeCodeFragment.TypeSyntaxException e) { + return null; + } + catch (PsiTypeCodeFragment.NoTypeException e) { + return null; + } + } + } diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index 868085e39c42..295b916a9e22 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -189,7 +189,7 @@ - + @@ -962,6 +962,9 @@ + + + Date: Wed, 14 Apr 2010 17:43:09 +0400 Subject: [PATCH 006/212] change signature: process usages for java --- .../ChangeSignatureProcessor.java | 682 +------------ .../changeSignature/JavaChangeInfo.java | 27 +- .../changeSignature/JavaChangeInfoImpl.java | 53 +- .../JavaChangeSignatureUsageProcessor.java | 952 +++++++++++++----- .../changeSignature/JavaParameterInfo.java | 11 +- .../changeSignature/UsageSearcher.java | 312 ++++++ .../ChangeSignatureUsageProcessor.java | 4 +- .../GrChangeSignatureProcessor.java | 44 + .../changeSignature/GrParameterInfo.java | 13 + 9 files changed, 1166 insertions(+), 932 deletions(-) create mode 100644 java/java-impl/src/com/intellij/refactoring/changeSignature/UsageSearcher.java diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java index fef08e7f05df..603adc22feae 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java @@ -20,7 +20,6 @@ */ package com.intellij.refactoring.changeSignature; -import com.intellij.codeInsight.ExceptionUtil; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; @@ -29,21 +28,11 @@ import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Ref; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleManager; -import com.intellij.psi.codeStyle.JavaCodeStyleManager; -import com.intellij.psi.codeStyle.VariableKind; -import com.intellij.psi.scope.processor.VariablesProcessor; -import com.intellij.psi.scope.util.PsiScopesUtil; import com.intellij.psi.util.*; import com.intellij.refactoring.BaseRefactoringProcessor; import com.intellij.refactoring.RefactoringBundle; -import com.intellij.refactoring.changeSignature.JavaChangeSignatureUsageProcessor.MyParameterUsageInfo; import com.intellij.refactoring.ui.ConflictsDialog; import com.intellij.refactoring.util.CanonicalTypes; -import com.intellij.refactoring.util.FieldConflictsResolver; -import com.intellij.refactoring.util.MoveRenameUsageInfo; -import com.intellij.refactoring.util.RefactoringUtil; -import com.intellij.refactoring.util.usageInfo.DefaultConstructorImplicitUsageInfo; -import com.intellij.refactoring.util.usageInfo.NoConstructorClassUsageInfo; import com.intellij.usageView.UsageInfo; import com.intellij.usageView.UsageViewDescriptor; import com.intellij.usageView.UsageViewUtil; @@ -59,10 +48,8 @@ import java.util.*; public class ChangeSignatureProcessor extends BaseRefactoringProcessor { private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.changeSignature.ChangeSignatureProcessor"); - @Modifier private final String myNewVisibility; private final JavaChangeInfoImpl myChangeInfo; private final PsiManager myManager; - private final PsiElementFactory myFactory; public ChangeSignatureProcessor(Project project, PsiMethod method, @@ -92,7 +79,7 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor { public ChangeSignatureProcessor(Project project, PsiMethod method, boolean generateDelegate, - String newVisibility, + @Modifier String newVisibility, String newName, CanonicalTypes.Type newType, @NotNull ParameterInfoImpl[] parameterInfo, @@ -101,7 +88,6 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor { Set propagateExceptionsMethods) { super(project); myManager = PsiManager.getInstance(project); - myFactory = JavaPsiFacade.getInstance(myManager.getProject()).getElementFactory(); Set myPropagateParametersMethods = propagateParametersMethods != null ? propagateParametersMethods : new HashSet(); @@ -110,12 +96,10 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor { LOG.assertTrue(method.isValid()); if (newVisibility == null) { - myNewVisibility = VisibilityUtil.getVisibilityModifier(method.getModifierList()); - } else { - myNewVisibility = newVisibility; - } + newVisibility = VisibilityUtil.getVisibilityModifier(method.getModifierList()); + } - myChangeInfo = new JavaChangeInfoImpl(myNewVisibility, method, newName, newType, parameterInfo, thrownExceptions, generateDelegate, myPropagateParametersMethods, myPropagateExceptionsMethods); + myChangeInfo = new JavaChangeInfoImpl(newVisibility, method, newName, newType, parameterInfo, thrownExceptions, generateDelegate, myPropagateParametersMethods, myPropagateExceptionsMethods); LOG.assertTrue(myChangeInfo.getMethod().isValid()); } @@ -134,9 +118,6 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor { return infos.toArray(new UsageInfo[infos.size()]); } - private boolean needToCatchExceptions(PsiMethod caller) { - return myChangeInfo.isExceptionSetOrOrderChanged && !myChangeInfo.propagateExceptionsMethods.contains(caller); - } protected void refreshElements(PsiElement[] elements) { boolean condition = elements.length == 1 && elements[0] instanceof PsiMethod; @@ -165,7 +146,7 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor { } } - if (myChangeInfo.isReturnTypeChanged) { + if (myChangeInfo.isReturnTypeChanged()) { askToRemoveCovariantOverriders(usagesSet); } @@ -215,151 +196,39 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor { } protected boolean isProcessCovariantOverriders() { - return Messages.showYesNoDialog(myProject, RefactoringBundle.message("do.you.want.to.process.overriding.methods.with.covariant.return.type"), - JavaChangeSignatureHandler.REFACTORING_NAME, Messages.getQuestionIcon()) - == DialogWrapper.OK_EXIT_CODE; + return Messages + .showYesNoDialog(myProject, RefactoringBundle.message("do.you.want.to.process.overriding.methods.with.covariant.return.type"), + JavaChangeSignatureHandler.REFACTORING_NAME, Messages.getQuestionIcon()) + == DialogWrapper.OK_EXIT_CODE; } protected void performRefactoring(UsageInfo[] usages) { - PsiElementFactory factory = JavaPsiFacade.getInstance(myManager.getProject()).getElementFactory(); - try { - if (myChangeInfo.isNameChanged) { - myChangeInfo.newNameIdentifier = factory.createIdentifier(myChangeInfo.newName); + final ChangeSignatureUsageProcessor[] processors = ChangeSignatureUsageProcessor.EP_NAME.getExtensions(); + + for (UsageInfo usage : usages) { + for (ChangeSignatureUsageProcessor processor : processors) { + if (processor.processUsage(myChangeInfo, usage, true, usages)) break; + } } - if (myChangeInfo.isReturnTypeChanged) { - myChangeInfo.newTypeElement = myChangeInfo.newReturnType.getType(myChangeInfo.getMethod(), myManager); - } - - if (myChangeInfo.isGenerateDelegate) { - generateDelegate(); + LOG.assertTrue(myChangeInfo.getMethod().isValid()); + for (ChangeSignatureUsageProcessor processor : processors) { + if (processor.processPrimaryMethod(myChangeInfo)) break; } for (UsageInfo usage : usages) { - if (usage instanceof CallerUsageInfo) { - final CallerUsageInfo callerUsageInfo = (CallerUsageInfo)usage; - processCallerMethod(callerUsageInfo.getMethod(), null, callerUsageInfo.isToInsertParameter(), - callerUsageInfo.isToInsertException()); - } - else if (usage instanceof OverriderUsageInfo) { - OverriderUsageInfo info = (OverriderUsageInfo)usage; - final PsiMethod method = info.getElement(); - final PsiMethod baseMethod = info.getBaseMethod(); - if (info.isOriginalOverrider()) { - processPrimaryMethod(method, baseMethod, false); - } - else { - processCallerMethod(method, baseMethod, info.isToInsertArgs(), info.isToCatchExceptions()); + for (ChangeSignatureUsageProcessor processor : processors) { + if (processor.processUsage(myChangeInfo, usage, false, usages)) { + break; } } } LOG.assertTrue(myChangeInfo.getMethod().isValid()); - processPrimaryMethod(myChangeInfo.getMethod(), null, true); - List postponedUsages = new ArrayList(); - - for (UsageInfo usage : usages) { - PsiElement element = usage.getElement(); - if (element == null) continue; - - if (usage instanceof DefaultConstructorImplicitUsageInfo) { - final DefaultConstructorImplicitUsageInfo defConstructorUsage = (DefaultConstructorImplicitUsageInfo)usage; - PsiMethod constructor = defConstructorUsage.getConstructor(); - if (!constructor.isPhysical()) { - final boolean toPropagate = myChangeInfo.propagateParametersMethods.remove(constructor); - final PsiClass containingClass = defConstructorUsage.getContainingClass(); - constructor = (PsiMethod)containingClass.add(constructor); - PsiUtil.setModifierProperty(constructor, VisibilityUtil.getVisibilityModifier(containingClass.getModifierList()), true); - if (toPropagate) { - myChangeInfo.propagateParametersMethods.add(constructor); - } - } - addSuperCall(constructor, defConstructorUsage.getBaseConstructor(),usages); - } - else if (usage instanceof NoConstructorClassUsageInfo) { - addDefaultConstructor(((NoConstructorClassUsageInfo)usage).getPsiClass(),usages); - } - else if (element instanceof PsiJavaCodeReferenceElement) { - if (usage instanceof MethodCallUsageInfo) { - final MethodCallUsageInfo methodCallInfo = (MethodCallUsageInfo)usage; - processMethodUsage(methodCallInfo.getElement(), myChangeInfo, methodCallInfo.isToChangeArguments(), - methodCallInfo.isToCatchExceptions(), methodCallInfo.getReferencedMethod(), usages); - } - else if (usage instanceof MyParameterUsageInfo) { - String newName = ((MyParameterUsageInfo)usage).newParameterName; - String oldName = ((MyParameterUsageInfo)usage).oldParameterName; - processParameterUsage((PsiReferenceExpression)element, oldName, newName); - } else { - postponedUsages.add(usage); - } - } - else if (usage instanceof CallReferenceUsageInfo) { - ((CallReferenceUsageInfo) usage).getReference().handleChangeSignature(myChangeInfo); - } - else if (element instanceof PsiEnumConstant) { - fixActualArgumentsList(((PsiEnumConstant)element).getArgumentList(), myChangeInfo, true); - } - else if (!(usage instanceof OverriderUsageInfo)) { - postponedUsages.add(usage); - } - } - - for (UsageInfo usageInfo : postponedUsages) { - PsiElement element = usageInfo.getElement(); - if (element == null) continue; - PsiReference reference = usageInfo instanceof MoveRenameUsageInfo ? - usageInfo.getReference() : - element.getReference(); - if (reference != null) { - PsiElement target = null; - if (usageInfo instanceof MyParameterUsageInfo) { - String newParameterName = ((MyParameterUsageInfo)usageInfo).newParameterName; - PsiParameter[] newParams = myChangeInfo.getMethod().getParameterList().getParameters(); - for (PsiParameter newParam : newParams) { - if (newParam.getName().equals(newParameterName)) { - target = newParam; - break; - } - } - } - else { - target = myChangeInfo.getMethod(); - } - if (target != null) { - reference.bindToElement(target); - } - } - } - - LOG.assertTrue(myChangeInfo.getMethod().isValid()); - } catch (IncorrectOperationException e) { - LOG.error(e); } - } - - private void generateDelegate() throws IncorrectOperationException { - final PsiMethod delegate = (PsiMethod)myChangeInfo.getMethod().copy(); - final PsiClass targetClass = myChangeInfo.getMethod().getContainingClass(); - LOG.assertTrue(!targetClass.isInterface()); - makeEmptyBody(myFactory, delegate); - final PsiCallExpression callExpression = addDelegatingCallTemplate(delegate, myChangeInfo.newName); - addDelegateArguments(callExpression); - targetClass.addBefore(delegate, myChangeInfo.getMethod()); - } - - private void addDelegateArguments(final PsiCallExpression callExpression) throws IncorrectOperationException { - final ParameterInfoImpl[] newParms = myChangeInfo.newParms; - for (int i = 0; i < newParms.length; i++) { - ParameterInfoImpl newParm = newParms[i]; - final PsiExpression actualArg; - if (newParm.oldParameterIndex >= 0) { - actualArg = myFactory.createExpressionFromText(myChangeInfo.oldParameterNames[newParm.oldParameterIndex], callExpression); - } - else { - actualArg = myChangeInfo.getValue(i, callExpression); - } - callExpression.getArgumentList().add(actualArg); + catch (IncorrectOperationException e) { + LOG.error(e); } } @@ -374,6 +243,7 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor { PsiUtil.setModifierProperty(delegate, PsiModifier.ABSTRACT, false); } + @Nullable public static PsiCallExpression addDelegatingCallTemplate(final PsiMethod delegate, final String newName) throws IncorrectOperationException { Project project = delegate.getProject(); PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory(); @@ -402,468 +272,11 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor { return callExpression; } - private void addDefaultConstructor(PsiClass aClass, final UsageInfo[] usages) throws IncorrectOperationException { - if (!(aClass instanceof PsiAnonymousClass)) { - PsiMethod defaultConstructor = myFactory.createMethodFromText(aClass.getName() + "(){}", aClass); - defaultConstructor = (PsiMethod) CodeStyleManager.getInstance(myProject).reformat(defaultConstructor); - defaultConstructor = (PsiMethod) aClass.add(defaultConstructor); - PsiUtil.setModifierProperty(defaultConstructor, VisibilityUtil.getVisibilityModifier(aClass.getModifierList()), true); - addSuperCall(defaultConstructor, null, usages); - } else { - final PsiElement parent = aClass.getParent(); - if (parent instanceof PsiNewExpression) { - final PsiExpressionList argumentList = ((PsiNewExpression) parent).getArgumentList(); - fixActualArgumentsList(argumentList, myChangeInfo, true); - } - } - } - - private void addSuperCall(PsiMethod constructor, PsiMethod callee, final UsageInfo[] usages) throws IncorrectOperationException { - PsiExpressionStatement superCall = (PsiExpressionStatement) myFactory.createStatementFromText("super();", constructor); - PsiCodeBlock body = constructor.getBody(); - assert body != null; - PsiStatement[] statements = body.getStatements(); - if (statements.length > 0) { - superCall = (PsiExpressionStatement) body.addBefore(superCall, statements[0]); - } else { - superCall = (PsiExpressionStatement) body.add(superCall); - } - PsiMethodCallExpression callExpression = (PsiMethodCallExpression) superCall.getExpression(); - processMethodUsage(callExpression.getMethodExpression(), myChangeInfo, true, false, callee, usages); - } - - private PsiParameter createNewParameter(ParameterInfoImpl newParm, - PsiSubstitutor substitutor) throws IncorrectOperationException { - final PsiElementFactory factory = JavaPsiFacade.getInstance(myProject).getElementFactory(); - final PsiType type = substitutor.substitute(newParm.createType(myChangeInfo.getMethod().getParameterList(), myManager)); - return factory.createParameter(newParm.getName(), type); - } - protected String getCommandName() { return RefactoringBundle.message("changing.signature.of.0", UsageViewUtil.getDescriptiveName(myChangeInfo.getMethod())); } - private void processMethodUsage(PsiElement ref, - JavaChangeInfoImpl changeInfo, - boolean toChangeArguments, - boolean toCatchExceptions, - PsiMethod callee, final UsageInfo[] usages) throws IncorrectOperationException { - if (changeInfo.isNameChanged) { - if (ref instanceof PsiJavaCodeReferenceElement) { - PsiElement last = ((PsiJavaCodeReferenceElement)ref).getReferenceNameElement(); - if (last instanceof PsiIdentifier && last.getText().equals(changeInfo.oldName)) { - last.replace(changeInfo.newNameIdentifier); - } - } - } - - final PsiMethod caller = RefactoringUtil.getEnclosingMethod(ref); - if (toChangeArguments) { - final PsiExpressionList list = RefactoringUtil.getArgumentListByMethodReference(ref); - boolean toInsertDefaultValue = !myChangeInfo.propagateParametersMethods.contains(caller); - if (toInsertDefaultValue && ref instanceof PsiReferenceExpression) { - final PsiExpression qualifierExpression = ((PsiReferenceExpression) ref).getQualifierExpression(); - if (qualifierExpression instanceof PsiSuperExpression && callerSignatureIsAboutToChangeToo(caller, usages)) { - toInsertDefaultValue = false; - } - } - - fixActualArgumentsList(list, changeInfo, toInsertDefaultValue); - } - - if (toCatchExceptions) { - if (!(ref instanceof PsiReferenceExpression && ((PsiReferenceExpression)ref).getQualifierExpression() instanceof PsiSuperExpression)) { - if (needToCatchExceptions(caller)) { - PsiClassType[] newExceptions = callee != null ? getCalleeChangedExceptionInfo(callee) : getPrimaryChangedExceptionInfo(changeInfo); - fixExceptions(ref, newExceptions); - } - } - } - } - - private static boolean callerSignatureIsAboutToChangeToo(final PsiMethod caller, final UsageInfo[] usages) { - for (UsageInfo usage : usages) { - if (usage instanceof MethodCallUsageInfo && MethodSignatureUtil.isSuperMethod(((MethodCallUsageInfo)usage).getReferencedMethod(), caller)) return true; - } - return false; - } - - private static PsiClassType[] getCalleeChangedExceptionInfo(final PsiMethod callee) { - return callee.getThrowsList().getReferencedTypes(); //Callee method's throws list is already modified! - } - - private PsiClassType[] getPrimaryChangedExceptionInfo(JavaChangeInfoImpl changeInfo) throws IncorrectOperationException { - PsiClassType[] newExceptions = new PsiClassType[changeInfo.newExceptions.length]; - for (int i = 0; i < newExceptions.length; i++) { - newExceptions[i] = (PsiClassType)changeInfo.newExceptions[i].myType.getType(myChangeInfo.getMethod(), myManager); //context really does not matter here - } - return newExceptions; - } - - private void fixExceptions(PsiElement ref, PsiClassType[] newExceptions) throws IncorrectOperationException { - //methods' throws lists are already modified, may use ExceptionUtil.collectUnhandledExceptions - newExceptions = filterCheckedExceptions(newExceptions); - - PsiElement context = PsiTreeUtil.getParentOfType(ref, PsiTryStatement.class, PsiMethod.class); - if (context instanceof PsiTryStatement) { - PsiTryStatement tryStatement = (PsiTryStatement)context; - PsiCodeBlock tryBlock = tryStatement.getTryBlock(); - - //Remove unused catches - Collection classes = ExceptionUtil.collectUnhandledExceptions(tryBlock, tryBlock); - PsiParameter[] catchParameters = tryStatement.getCatchBlockParameters(); - for (PsiParameter parameter : catchParameters) { - final PsiType caughtType = parameter.getType(); - - if (!(caughtType instanceof PsiClassType)) continue; - if (ExceptionUtil.isUncheckedExceptionOrSuperclass((PsiClassType)caughtType)) continue; - - if (!isCatchParameterRedundant((PsiClassType)caughtType, classes)) continue; - parameter.getParent().delete(); //delete catch section - } - - PsiClassType[] exceptionsToAdd = filterUnhandledExceptions(newExceptions, tryBlock); - addExceptions(exceptionsToAdd, tryStatement); - - adjustPossibleEmptyTryStatement(tryStatement); - } - else { - newExceptions = filterUnhandledExceptions(newExceptions, ref); - if (newExceptions.length > 0) { - //Add new try statement - PsiElementFactory elementFactory = JavaPsiFacade.getInstance(myManager.getProject()).getElementFactory(); - PsiTryStatement tryStatement = (PsiTryStatement)elementFactory.createStatementFromText("try {} catch (Exception e) {}", null); - PsiStatement anchor = PsiTreeUtil.getParentOfType(ref, PsiStatement.class); - LOG.assertTrue(anchor != null); - tryStatement.getTryBlock().add(anchor); - tryStatement = (PsiTryStatement)anchor.getParent().addAfter(tryStatement, anchor); - - addExceptions(newExceptions, tryStatement); - anchor.delete(); - tryStatement.getCatchSections()[0].delete(); //Delete dummy catch section - } - } - } - - private static PsiClassType[] filterCheckedExceptions(PsiClassType[] exceptions) { - List result = new ArrayList(); - for (PsiClassType exceptionType : exceptions) { - if (!ExceptionUtil.isUncheckedException(exceptionType)) result.add(exceptionType); - } - return result.toArray(new PsiClassType[result.size()]); - } - - private static void adjustPossibleEmptyTryStatement(PsiTryStatement tryStatement) throws IncorrectOperationException { - PsiCodeBlock tryBlock = tryStatement.getTryBlock(); - if (tryBlock != null) { - if (tryStatement.getCatchSections().length == 0 && - tryStatement.getFinallyBlock() == null) { - PsiElement firstBodyElement = tryBlock.getFirstBodyElement(); - if (firstBodyElement != null) { - tryStatement.getParent().addRangeAfter(firstBodyElement, tryBlock.getLastBodyElement(), tryStatement); - } - tryStatement.delete(); - } - } - } - - private static void addExceptions(PsiClassType[] exceptionsToAdd, PsiTryStatement tryStatement) throws IncorrectOperationException { - for (PsiClassType type : exceptionsToAdd) { - final JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(tryStatement.getProject()); - String name = styleManager.suggestVariableName(VariableKind.PARAMETER, null, null, type).names[0]; - name = styleManager.suggestUniqueVariableName(name, tryStatement, false); - - PsiCatchSection catchSection = - JavaPsiFacade.getInstance(tryStatement.getProject()).getElementFactory().createCatchSection(type, name, tryStatement); - tryStatement.add(catchSection); - } - } - - private void fixPrimaryThrowsLists(PsiMethod method, PsiClassType[] newExceptions) throws IncorrectOperationException { - PsiElementFactory elementFactory = JavaPsiFacade.getInstance(myManager.getProject()).getElementFactory(); - PsiJavaCodeReferenceElement[] refs = new PsiJavaCodeReferenceElement[newExceptions.length]; - for (int i = 0; i < refs.length; i++) { - refs[i] = elementFactory.createReferenceElementByType(newExceptions[i]); - } - PsiReferenceList throwsList = elementFactory.createReferenceList(refs); - - replaceThrowsList(method, throwsList); - } - - private void replaceThrowsList(PsiMethod method, PsiReferenceList throwsList) throws IncorrectOperationException { - PsiReferenceList methodThrowsList = (PsiReferenceList)method.getThrowsList().replace(throwsList); - methodThrowsList = (PsiReferenceList)JavaCodeStyleManager.getInstance(myProject).shortenClassReferences(methodThrowsList); - myManager.getCodeStyleManager().reformatRange(method, method.getParameterList().getTextRange().getEndOffset(), - methodThrowsList.getTextRange().getEndOffset()); - } - - private static PsiClassType[] filterUnhandledExceptions(PsiClassType[] exceptions, PsiElement place) { - List result = new ArrayList(); - for (PsiClassType exception : exceptions) { - if (!ExceptionUtil.isHandled(exception, place)) result.add(exception); - } - return result.toArray(new PsiClassType[result.size()]); - } - - private static boolean isCatchParameterRedundant (PsiClassType catchParamType, Collection thrownTypes) { - for (PsiType exceptionType : thrownTypes) { - if (exceptionType.isConvertibleFrom(catchParamType)) return false; - } - return true; - } - - private static int getNonVarargCount(JavaChangeInfoImpl changeInfo, PsiExpression[] args) { - if (!changeInfo.wasVararg) return args.length; - return changeInfo.oldParameterTypes.length - 1; - } - - //This methods works equally well for primary usages as well as for propagated callers' usages - private void fixActualArgumentsList(PsiExpressionList list, - JavaChangeInfoImpl changeInfo, - boolean toInsertDefaultValue) throws IncorrectOperationException { - final PsiElementFactory factory = JavaPsiFacade.getInstance(list.getProject()).getElementFactory(); - if (changeInfo.isParameterSetOrOrderChanged) { - if (changeInfo.isPropagationEnabled) { - final ParameterInfoImpl[] createdParmsInfo = changeInfo.getCreatedParmsInfoWithoutVarargs(); - for (ParameterInfoImpl info : createdParmsInfo) { - PsiExpression newArg; - if (toInsertDefaultValue) { - newArg = createDefaultValue(factory, info, list); - } - else { - newArg = factory.createExpressionFromText(info.getName(), list); - } - list.add(newArg); - } - } - else { - final PsiExpression[] args = list.getExpressions(); - final int nonVarargCount = getNonVarargCount(changeInfo, args); - final int varargCount = args.length - nonVarargCount; - PsiExpression[] newVarargInitializers = null; - - final int newArgsLength; - final int newNonVarargCount; - if (changeInfo.arrayToVarargs) { - newNonVarargCount = changeInfo.newParms.length - 1; - final ParameterInfoImpl lastNewParm = changeInfo.newParms[changeInfo.newParms.length - 1]; - final PsiExpression arrayToConvert = args[lastNewParm.oldParameterIndex]; - if (arrayToConvert instanceof PsiNewExpression) { - final PsiNewExpression expression = (PsiNewExpression)arrayToConvert; - final PsiArrayInitializerExpression arrayInitializer = expression.getArrayInitializer(); - if (arrayInitializer != null) { - newVarargInitializers = arrayInitializer.getInitializers(); - } - } - newArgsLength = newVarargInitializers == null ? changeInfo.newParms.length : newNonVarargCount + newVarargInitializers.length; - } - else if (changeInfo.retainsVarargs) { - newNonVarargCount = changeInfo.newParms.length - 1; - newArgsLength = newNonVarargCount + varargCount; - } - else if (changeInfo.obtainsVarags) { - newNonVarargCount = changeInfo.newParms.length - 1; - newArgsLength = newNonVarargCount; - } - else { - newNonVarargCount = changeInfo.newParms.length; - newArgsLength = changeInfo.newParms.length; - } - final PsiExpression[] newArgs = new PsiExpression[newArgsLength]; - for (int i = 0; i < newNonVarargCount; i++) { - newArgs [i] = createActualArgument(list, changeInfo.newParms [i], toInsertDefaultValue, args); - } - if (changeInfo.arrayToVarargs) { - if (newVarargInitializers == null) { - newArgs [newNonVarargCount] = createActualArgument(list, changeInfo.newParms [newNonVarargCount], toInsertDefaultValue, args); - } - else { - System.arraycopy(newVarargInitializers, 0, newArgs, newNonVarargCount, newVarargInitializers.length); - } - } - else { - final int newVarargCount = newArgsLength - newNonVarargCount; - LOG.assertTrue(newVarargCount == 0 || newVarargCount == varargCount); - System.arraycopy(args, nonVarargCount, newArgs, newNonVarargCount, newVarargCount); - } - ChangeSignatureUtil.synchronizeList(list, Arrays.asList(newArgs), ExpressionList.INSTANCE, changeInfo.toRemoveParm); - } - } - } - - private PsiExpression createActualArgument(final PsiExpressionList list, final ParameterInfoImpl info, final boolean toInsertDefaultValue, - final PsiExpression[] args) throws IncorrectOperationException { - final PsiElementFactory factory = JavaPsiFacade.getInstance(list.getProject()).getElementFactory(); - final int index = info.oldParameterIndex; - if (index >= 0) { - return args[index]; - } else { - if (toInsertDefaultValue) { - return createDefaultValue(factory, info, list); - } else { - return factory.createExpressionFromText(info.getName(), list); - } - } - } - - @Nullable - private PsiExpression createDefaultValue(final PsiElementFactory factory, final ParameterInfoImpl info, final PsiExpressionList list) - throws IncorrectOperationException { - if (info.useAnySingleVariable) { - final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(list.getProject()).getResolveHelper(); - final PsiType type = info.getTypeWrapper().getType(myChangeInfo.getMethod(), myManager); - final VariablesProcessor processor = new VariablesProcessor(false) { - protected boolean check(PsiVariable var, ResolveState state) { - if (var instanceof PsiField && !resolveHelper.isAccessible((PsiField)var, list, null)) return false; - final PsiType varType = state.get(PsiSubstitutor.KEY).substitute(var.getType()); - return type.isAssignableFrom(varType); - } - - public boolean execute(PsiElement pe, ResolveState state) { - super.execute(pe, state); - return size() < 2; - } - }; - PsiScopesUtil.treeWalkUp(processor, list, null); - if (processor.size() == 1) { - final PsiVariable result = processor.getResult(0); - return factory.createExpressionFromText(result.getName(), list); - } - } - final PsiCallExpression callExpression = PsiTreeUtil.getParentOfType(list, PsiCallExpression.class); - return callExpression != null ? info.getValue(callExpression) : factory.createExpressionFromText(info.defaultValue, list); - } - - - private void processCallerMethod(PsiMethod caller, - PsiMethod baseMethod, - boolean toInsertParams, - boolean toInsertThrows) throws IncorrectOperationException { - LOG.assertTrue(toInsertParams || toInsertThrows); - if (toInsertParams) { - List newParameters = new ArrayList(); - newParameters.addAll(Arrays.asList(caller.getParameterList().getParameters())); - final ParameterInfoImpl[] primaryNewParms = myChangeInfo.newParms; - PsiSubstitutor substitutor = baseMethod == null ? PsiSubstitutor.EMPTY : calculateSubstitutor(caller, baseMethod); - for (ParameterInfoImpl info : primaryNewParms) { - if (info.oldParameterIndex < 0) newParameters.add(createNewParameter(info, substitutor)); - } - PsiParameter[] arrayed = newParameters.toArray(new PsiParameter[newParameters.size()]); - boolean[] toRemoveParm = new boolean[arrayed.length]; - Arrays.fill(toRemoveParm, false); - resolveParameterVsFieldsConflicts(arrayed, caller, caller.getParameterList(), toRemoveParm); - } - - if (toInsertThrows) { - List newThrowns = new ArrayList(); - final PsiReferenceList throwsList = caller.getThrowsList(); - newThrowns.addAll(Arrays.asList(throwsList.getReferenceElements())); - final ThrownExceptionInfo[] primaryNewExns = myChangeInfo.newExceptions; - for (ThrownExceptionInfo thrownExceptionInfo : primaryNewExns) { - if (thrownExceptionInfo.oldIndex < 0) { - final PsiClassType type = (PsiClassType)thrownExceptionInfo.createType(caller, myManager); - final PsiJavaCodeReferenceElement ref = - JavaPsiFacade.getInstance(caller.getProject()).getElementFactory().createReferenceElementByType(type); - newThrowns.add(ref); - } - } - PsiJavaCodeReferenceElement[] arrayed = newThrowns.toArray(new PsiJavaCodeReferenceElement[newThrowns.size()]); - boolean[] toRemoveParm = new boolean[arrayed.length]; - Arrays.fill(toRemoveParm, false); - ChangeSignatureUtil.synchronizeList(throwsList, Arrays.asList(arrayed), ThrowsList.INSTANCE, toRemoveParm); - } - } - - private void processPrimaryMethod(PsiMethod method, - PsiMethod baseMethod, - boolean isOriginal) throws IncorrectOperationException { - PsiElementFactory factory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory(); - - if (myChangeInfo.isVisibilityChanged) { - PsiModifierList modifierList = method.getModifierList(); - final String highestVisibility = isOriginal ? - myNewVisibility : - VisibilityUtil.getHighestVisibility(myNewVisibility, VisibilityUtil.getVisibilityModifier(modifierList)); - VisibilityUtil.setVisibility(modifierList, highestVisibility); - } - - if (myChangeInfo.isNameChanged) { - String newName = baseMethod == null ? myChangeInfo.newName : - RefactoringUtil.suggestNewOverriderName(method.getName(), baseMethod.getName(), myChangeInfo.newName); - - if (newName != null && !newName.equals(method.getName())) { - final PsiIdentifier nameId = method.getNameIdentifier(); - assert nameId != null; - nameId.replace(JavaPsiFacade.getInstance(myManager.getProject()).getElementFactory().createIdentifier(newName)); - } - } - - final PsiSubstitutor substitutor = baseMethod == null ? PsiSubstitutor.EMPTY : calculateSubstitutor(method, baseMethod); - - if (myChangeInfo.isReturnTypeChanged) { - final PsiType returnType = substitutor.substitute(myChangeInfo.newTypeElement); - // don't modify return type for non-Java overriders (EJB) - if (method.getName().equals(myChangeInfo.newName)) { - final PsiTypeElement typeElement = method.getReturnTypeElement(); - if (typeElement != null) { - typeElement.replace(factory.createTypeElement(returnType)); - } - } - } - - PsiParameterList list = method.getParameterList(); - PsiParameter[] parameters = list.getParameters(); - - PsiParameter[] newParms = new PsiParameter[myChangeInfo.newParms.length]; - for (int i = 0; i < newParms.length; i++) { - ParameterInfoImpl info = myChangeInfo.newParms[i]; - int index = info.oldParameterIndex; - if (index >= 0) { - PsiParameter parameter = parameters[index]; - newParms[i] = parameter; - - String oldName = myChangeInfo.oldParameterNames[index]; - if (!oldName.equals(info.getName()) && oldName.equals(parameter.getName())) { - PsiIdentifier newIdentifier = factory.createIdentifier(info.getName()); - parameter.getNameIdentifier().replace(newIdentifier); - } - - String oldType = myChangeInfo.oldParameterTypes[index]; - if (!oldType.equals(info.getTypeText())) { - parameter.normalizeDeclaration(); - PsiType newType = substitutor.substitute(info.createType(myChangeInfo.getMethod().getParameterList(), myManager)); - - parameter.getTypeElement().replace(factory.createTypeElement(newType)); - } - } else { - newParms[i] = createNewParameter(info, substitutor); - } - } - - resolveParameterVsFieldsConflicts(newParms, method, list, myChangeInfo.toRemoveParm); - fixJavadocsForChangedMethod(method); - if (myChangeInfo.isExceptionSetOrOrderChanged) { - final PsiClassType[] newExceptions = getPrimaryChangedExceptionInfo(myChangeInfo); - fixPrimaryThrowsLists(method, newExceptions); - } - } - - private static void resolveParameterVsFieldsConflicts(final PsiParameter[] newParms, - final PsiMethod method, - final PsiParameterList list, - boolean[] toRemoveParm) throws IncorrectOperationException { - List conflictResolvers = new ArrayList(); - for (PsiParameter parameter : newParms) { - conflictResolvers.add(new FieldConflictsResolver(parameter.getName(), method.getBody())); - } - ChangeSignatureUtil.synchronizeList(list, Arrays.asList(newParms), ParameterList.INSTANCE, toRemoveParm); - JavaCodeStyleManager.getInstance(list.getProject()).shortenClassReferences(list); - for (FieldConflictsResolver fieldConflictsResolver : conflictResolvers) { - fieldConflictsResolver.fix(); - } - } - - private static PsiSubstitutor calculateSubstitutor(PsiMethod derivedMethod, PsiMethod baseMethod) { + public static PsiSubstitutor calculateSubstitutor(PsiMethod derivedMethod, PsiMethod baseMethod) { PsiSubstitutor substitutor; if (derivedMethod.getManager().areElementsEquivalent(derivedMethod, baseMethod)) { substitutor = PsiSubstitutor.EMPTY; @@ -883,51 +296,6 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor { return substitutor; } - private static void processParameterUsage(PsiReferenceExpression ref, String oldName, String newName) - throws IncorrectOperationException { - PsiElement last = ref.getReferenceNameElement(); - if (last instanceof PsiIdentifier && last.getText().equals(oldName)) { - PsiElementFactory factory = JavaPsiFacade.getInstance(ref.getProject()).getElementFactory(); - PsiIdentifier newNameIdentifier = factory.createIdentifier(newName); - last.replace(newNameIdentifier); - } - } - - private void fixJavadocsForChangedMethod(PsiMethod method) throws IncorrectOperationException { - final PsiParameter[] parameters = method.getParameterList().getParameters(); - final ParameterInfoImpl[] newParms = myChangeInfo.newParms; - LOG.assertTrue(parameters.length == newParms.length); - final Set newParameters = new HashSet(); - for (int i = 0; i < newParms.length; i++) { - ParameterInfoImpl newParm = newParms[i]; - if (newParm.oldParameterIndex < 0 || - !newParm.getName().equals(myChangeInfo.oldParameterNames[newParm.oldParameterIndex])) { - newParameters.add(parameters[i]); - } - } - RefactoringUtil.fixJavadocsForParams(method, newParameters); - } - - private static class ExpressionList implements ChangeSignatureUtil.ChildrenGenerator { - public static final ExpressionList INSTANCE = new ExpressionList(); - public List getChildren(PsiExpressionList psiExpressionList) { - return Arrays.asList(psiExpressionList.getExpressions()); - } - } - - private static class ParameterList implements ChangeSignatureUtil.ChildrenGenerator { - public static final ParameterList INSTANCE = new ParameterList(); - public List getChildren(PsiParameterList psiParameterList) { - return Arrays.asList(psiParameterList.getParameters()); - } - } - - private static class ThrowsList implements ChangeSignatureUtil.ChildrenGenerator { - public static final ThrowsList INSTANCE = new ThrowsList(); - public List getChildren(PsiReferenceList throwsList) { - return Arrays.asList(throwsList.getReferenceElements()); - } - } } diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfo.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfo.java index 421e5b7b8fa4..a4227e13d7f2 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfo.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfo.java @@ -15,7 +15,7 @@ */ package com.intellij.refactoring.changeSignature; -import com.intellij.psi.PsiMethod; +import com.intellij.psi.*; import com.intellij.refactoring.util.CanonicalTypes; import org.jetbrains.annotations.NotNull; @@ -36,5 +36,30 @@ public interface JavaChangeInfo extends ChangeInfo { @NotNull JavaParameterInfo[] getNewParameters(); + @Modifier String getNewVisibility(); + + @NotNull + String[] getOldParameterNames(); + + @NotNull + String[] getOldParameterTypes(); + + ThrownExceptionInfo[] getNewExceptions(); + + boolean isRetainsVarargs(); + + boolean isObtainsVarags(); + + boolean isArrayToVarargs(); + + PsiIdentifier getNewNameIdentifier(); + + String getOldName(); + + boolean wasVararg(); + + boolean[] toRemoveParm(); + + PsiExpression getValue(int i, PsiCallExpression callExpression); } diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfoImpl.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfoImpl.java index f5411c48a927..7c7cab0e6bb0 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfoImpl.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfoImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2010 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,6 +37,7 @@ import java.util.Set; class JavaChangeInfoImpl implements JavaChangeInfo { private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.changeSignature.JavaChangeInfoImpl"); + @Modifier final String newVisibility; private PsiMethod method; final String oldName; @@ -62,7 +63,7 @@ class JavaChangeInfoImpl implements JavaChangeInfo { final boolean obtainsVarags; final boolean arrayToVarargs; PsiIdentifier newNameIdentifier; - PsiType newTypeElement; +// PsiType newTypeElement; final PsiExpression[] defaultValues; final boolean isGenerateDelegate; @@ -189,6 +190,11 @@ class JavaChangeInfoImpl implements JavaChangeInfo { arrayToVarargs = false; } } + + if (isNameChanged) { + newNameIdentifier = factory.createIdentifier(newName); + } + } @NotNull @@ -196,6 +202,7 @@ class JavaChangeInfoImpl implements JavaChangeInfo { return newParms; } + @Modifier public String getNewVisibility() { return newVisibility; } @@ -321,4 +328,46 @@ class JavaChangeInfoImpl implements JavaChangeInfo { public boolean isGenerateDelegate() { return isGenerateDelegate; } + + @NotNull + public String[] getOldParameterNames() { + return oldParameterNames; + } + + @NotNull + public String[] getOldParameterTypes() { + return oldParameterTypes; + } + + public ThrownExceptionInfo[] getNewExceptions() { + return newExceptions; + } + + public boolean isRetainsVarargs() { + return retainsVarargs; + } + + public boolean isObtainsVarags() { + return obtainsVarags; + } + + public boolean isArrayToVarargs() { + return arrayToVarargs; + } + + public PsiIdentifier getNewNameIdentifier() { + return newNameIdentifier; + } + + public String getOldName() { + return oldName; + } + + public boolean wasVararg() { + return wasVararg; + } + + public boolean[] toRemoveParm() { + return toRemoveParm; + } } diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java index 875a65a39d23..bf734c040dec 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java @@ -15,36 +15,30 @@ */ package com.intellij.refactoring.changeSignature; +import com.intellij.codeInsight.ExceptionUtil; import com.intellij.lang.StdLanguages; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Ref; import com.intellij.psi.*; -import com.intellij.psi.javadoc.PsiDocTagValue; -import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.search.searches.MethodReferencesSearch; -import com.intellij.psi.search.searches.OverridingMethodsSearch; -import com.intellij.psi.search.searches.ReferencesSearch; -import com.intellij.psi.util.PsiUtil; -import com.intellij.psi.xml.XmlElement; +import com.intellij.psi.codeStyle.CodeStyleManager; +import com.intellij.psi.codeStyle.JavaCodeStyleManager; +import com.intellij.psi.codeStyle.VariableKind; +import com.intellij.psi.scope.processor.VariablesProcessor; +import com.intellij.psi.scope.util.PsiScopesUtil; +import com.intellij.psi.util.*; import com.intellij.refactoring.RefactoringBundle; -import com.intellij.refactoring.rename.JavaUnresolvableLocalCollisionDetector; import com.intellij.refactoring.rename.RenameUtil; -import com.intellij.refactoring.rename.UnresolvableCollisionUsageInfo; import com.intellij.refactoring.util.*; import com.intellij.refactoring.util.usageInfo.DefaultConstructorImplicitUsageInfo; import com.intellij.refactoring.util.usageInfo.NoConstructorClassUsageInfo; import com.intellij.usageView.UsageInfo; -import com.intellij.usageView.UsageViewUtil; import com.intellij.util.IncorrectOperationException; import com.intellij.util.VisibilityUtil; import com.intellij.util.containers.HashSet; import com.intellij.util.containers.MultiMap; +import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.Set; +import java.util.*; /** * @author Maxim.Medvedev @@ -76,275 +70,687 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr } } - public boolean processUsage(ChangeInfo changeInfo, UsageInfo usageInfo) { - if (!isJavaUsage(usageInfo)) return false; + public boolean processUsage(ChangeInfo changeInfo, UsageInfo usage, boolean beforeMethodChange, UsageInfo[] usages) { + if (!isJavaUsage(usage)) return false; + if (!(changeInfo instanceof JavaChangeInfo)) return false; + + if (beforeMethodChange) { + if (usage instanceof CallerUsageInfo) { + final CallerUsageInfo callerUsageInfo = (CallerUsageInfo)usage; + processCallerMethod((JavaChangeInfo)changeInfo, callerUsageInfo.getMethod(), null, callerUsageInfo.isToInsertParameter(), + callerUsageInfo.isToInsertException()); + return true; + } + else if (usage instanceof OverriderUsageInfo) { + OverriderUsageInfo info = (OverriderUsageInfo)usage; + final PsiMethod method = info.getElement(); + final PsiMethod baseMethod = info.getBaseMethod(); + if (info.isOriginalOverrider()) { + processPrimaryMethod((JavaChangeInfo)changeInfo, method, baseMethod, false); + } + else { + processCallerMethod((JavaChangeInfo)changeInfo, method, baseMethod, info.isToInsertArgs(), info.isToCatchExceptions()); + } + return true; + } + + } + else { + PsiElement element = usage.getElement(); + LOG.assertTrue(element != null); + + if (usage instanceof DefaultConstructorImplicitUsageInfo) { + final DefaultConstructorImplicitUsageInfo defConstructorUsage = (DefaultConstructorImplicitUsageInfo)usage; + PsiMethod constructor = defConstructorUsage.getConstructor(); + if (!constructor.isPhysical()) { + final boolean toPropagate = + ((JavaChangeInfoImpl)changeInfo).propagateParametersMethods.remove(constructor); //todo don't use explicit type cast + final PsiClass containingClass = defConstructorUsage.getContainingClass(); + constructor = (PsiMethod)containingClass.add(constructor); + PsiUtil.setModifierProperty(constructor, VisibilityUtil.getVisibilityModifier(containingClass.getModifierList()), true); + if (toPropagate) { + ((JavaChangeInfoImpl)changeInfo).propagateParametersMethods.add(constructor); //todo don't use explicit type cast + } + } + addSuperCall((JavaChangeInfo)changeInfo, constructor, defConstructorUsage.getBaseConstructor(), usages); + return true; + } + else if (usage instanceof NoConstructorClassUsageInfo) { + addDefaultConstructor(((JavaChangeInfo)changeInfo), ((NoConstructorClassUsageInfo)usage).getPsiClass(), usages); + return true; + } + else if (usage instanceof MethodCallUsageInfo) { + final MethodCallUsageInfo methodCallInfo = (MethodCallUsageInfo)usage; + processMethodUsage(methodCallInfo.getElement(), (JavaChangeInfo)changeInfo, methodCallInfo.isToChangeArguments(), + methodCallInfo.isToCatchExceptions(), methodCallInfo.getReferencedMethod(), usages); + return true; + } + else if (usage instanceof MyParameterUsageInfo) { + String newName = ((MyParameterUsageInfo)usage).newParameterName; + String oldName = ((MyParameterUsageInfo)usage).oldParameterName; + processParameterUsage((PsiReferenceExpression)element, oldName, newName); + return true; + } + else if (usage instanceof CallReferenceUsageInfo) { + ((CallReferenceUsageInfo)usage).getReference().handleChangeSignature(changeInfo); + return true; + } + else if (element instanceof PsiEnumConstant) { + fixActualArgumentsList(((PsiEnumConstant)element).getArgumentList(), (JavaChangeInfo)changeInfo, true); + return true; + } + else if (!(usage instanceof OverriderUsageInfo)) { + PsiReference reference = usage instanceof MoveRenameUsageInfo ? usage.getReference() : element.getReference(); + if (reference != null) { + PsiElement target = changeInfo.getMethod(); + if (target != null) { + reference.bindToElement(target); + } + } + } + } + return false; + } + + private static void processParameterUsage(PsiReferenceExpression ref, String oldName, String newName) + throws IncorrectOperationException { + + PsiElement last = ref.getReferenceNameElement(); + if (last instanceof PsiIdentifier && last.getText().equals(oldName)) { + PsiElementFactory factory = JavaPsiFacade.getInstance(ref.getProject()).getElementFactory(); + PsiIdentifier newNameIdentifier = factory.createIdentifier(newName); + last.replace(newNameIdentifier); + } + } + + + private static void addDefaultConstructor(JavaChangeInfo changeInfo, PsiClass aClass, final UsageInfo[] usages) + throws IncorrectOperationException { + if (!(aClass instanceof PsiAnonymousClass)) { + PsiElementFactory factory = JavaPsiFacade.getElementFactory(aClass.getProject()); + PsiMethod defaultConstructor = factory.createMethodFromText(aClass.getName() + "(){}", aClass); + defaultConstructor = (PsiMethod)CodeStyleManager.getInstance(aClass.getProject()).reformat(defaultConstructor); + defaultConstructor = (PsiMethod)aClass.add(defaultConstructor); + PsiUtil.setModifierProperty(defaultConstructor, VisibilityUtil.getVisibilityModifier(aClass.getModifierList()), true); + addSuperCall(changeInfo, defaultConstructor, null, usages); + } + else { + final PsiElement parent = aClass.getParent(); + if (parent instanceof PsiNewExpression) { + final PsiExpressionList argumentList = ((PsiNewExpression)parent).getArgumentList(); + fixActualArgumentsList(argumentList, changeInfo, true); + } + } + } + + private static void addSuperCall(JavaChangeInfo changeInfo, PsiMethod constructor, PsiMethod callee, final UsageInfo[] usages) + throws IncorrectOperationException { + final PsiElementFactory factory = JavaPsiFacade.getElementFactory(constructor.getProject()); + PsiExpressionStatement superCall = (PsiExpressionStatement)factory.createStatementFromText("super();", constructor); + PsiCodeBlock body = constructor.getBody(); + assert body != null; + PsiStatement[] statements = body.getStatements(); + if (statements.length > 0) { + superCall = (PsiExpressionStatement)body.addBefore(superCall, statements[0]); + } + else { + superCall = (PsiExpressionStatement)body.add(superCall); + } + PsiMethodCallExpression callExpression = (PsiMethodCallExpression)superCall.getExpression(); + processMethodUsage(callExpression.getMethodExpression(), changeInfo, true, false, callee, usages); + } + + private static void processMethodUsage(PsiElement ref, + JavaChangeInfo changeInfo, + boolean toChangeArguments, + boolean toCatchExceptions, + PsiMethod callee, final UsageInfo[] usages) throws IncorrectOperationException { + if (changeInfo.isNameChanged()) { + if (ref instanceof PsiJavaCodeReferenceElement) { + PsiElement last = ((PsiJavaCodeReferenceElement)ref).getReferenceNameElement(); + if (last instanceof PsiIdentifier && last.getText().equals(changeInfo.getOldName())) { + last.replace(changeInfo.getNewNameIdentifier()); + } + } + } + + final PsiMethod caller = RefactoringUtil.getEnclosingMethod(ref); + if (toChangeArguments) { + final PsiExpressionList list = RefactoringUtil.getArgumentListByMethodReference(ref); + boolean toInsertDefaultValue = !((JavaChangeInfoImpl)changeInfo).propagateParametersMethods.contains(caller); //todo + if (toInsertDefaultValue && ref instanceof PsiReferenceExpression) { + final PsiExpression qualifierExpression = ((PsiReferenceExpression)ref).getQualifierExpression(); + if (qualifierExpression instanceof PsiSuperExpression && callerSignatureIsAboutToChangeToo(caller, usages)) { + toInsertDefaultValue = false; + } + } + + fixActualArgumentsList(list, changeInfo, toInsertDefaultValue); + } + + if (toCatchExceptions) { + if (!(ref instanceof PsiReferenceExpression && + ((PsiReferenceExpression)ref).getQualifierExpression() instanceof PsiSuperExpression)) { + if (needToCatchExceptions(changeInfo, caller)) { + PsiClassType[] newExceptions = + callee != null ? getCalleeChangedExceptionInfo(callee) : getPrimaryChangedExceptionInfo(changeInfo); + fixExceptions(ref, newExceptions); + } + } + } + } + + private static boolean callerSignatureIsAboutToChangeToo(final PsiMethod caller, final UsageInfo[] usages) { + for (UsageInfo usage : usages) { + if (usage instanceof MethodCallUsageInfo && + MethodSignatureUtil.isSuperMethod(((MethodCallUsageInfo)usage).getReferencedMethod(), caller)) { + return true; + } + } + return false; + } + + private static PsiClassType[] getCalleeChangedExceptionInfo(final PsiMethod callee) { + return callee.getThrowsList().getReferencedTypes(); //Callee method's throws list is already modified! + } + + private static void fixExceptions(PsiElement ref, PsiClassType[] newExceptions) throws IncorrectOperationException { + //methods' throws lists are already modified, may use ExceptionUtil.collectUnhandledExceptions + newExceptions = filterCheckedExceptions(newExceptions); + + PsiElement context = PsiTreeUtil.getParentOfType(ref, PsiTryStatement.class, PsiMethod.class); + if (context instanceof PsiTryStatement) { + PsiTryStatement tryStatement = (PsiTryStatement)context; + PsiCodeBlock tryBlock = tryStatement.getTryBlock(); + + //Remove unused catches + Collection classes = ExceptionUtil.collectUnhandledExceptions(tryBlock, tryBlock); + PsiParameter[] catchParameters = tryStatement.getCatchBlockParameters(); + for (PsiParameter parameter : catchParameters) { + final PsiType caughtType = parameter.getType(); + + if (!(caughtType instanceof PsiClassType)) continue; + if (ExceptionUtil.isUncheckedExceptionOrSuperclass((PsiClassType)caughtType)) continue; + + if (!isCatchParameterRedundant((PsiClassType)caughtType, classes)) continue; + parameter.getParent().delete(); //delete catch section + } + + PsiClassType[] exceptionsToAdd = filterUnhandledExceptions(newExceptions, tryBlock); + addExceptions(exceptionsToAdd, tryStatement); + + adjustPossibleEmptyTryStatement(tryStatement); + } + else { + newExceptions = filterUnhandledExceptions(newExceptions, ref); + if (newExceptions.length > 0) { + //Add new try statement + PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(ref.getProject()); + PsiTryStatement tryStatement = (PsiTryStatement)elementFactory.createStatementFromText("try {} catch (Exception e) {}", null); + PsiStatement anchor = PsiTreeUtil.getParentOfType(ref, PsiStatement.class); + LOG.assertTrue(anchor != null); + tryStatement.getTryBlock().add(anchor); + tryStatement = (PsiTryStatement)anchor.getParent().addAfter(tryStatement, anchor); + + addExceptions(newExceptions, tryStatement); + anchor.delete(); + tryStatement.getCatchSections()[0].delete(); //Delete dummy catch section + } + } + } + + private static PsiClassType[] filterCheckedExceptions(PsiClassType[] exceptions) { + List result = new ArrayList(); + for (PsiClassType exceptionType : exceptions) { + if (!ExceptionUtil.isUncheckedException(exceptionType)) result.add(exceptionType); + } + return result.toArray(new PsiClassType[result.size()]); + } + + private static void adjustPossibleEmptyTryStatement(PsiTryStatement tryStatement) throws IncorrectOperationException { + PsiCodeBlock tryBlock = tryStatement.getTryBlock(); + if (tryBlock != null) { + if (tryStatement.getCatchSections().length == 0 && + tryStatement.getFinallyBlock() == null) { + PsiElement firstBodyElement = tryBlock.getFirstBodyElement(); + if (firstBodyElement != null) { + tryStatement.getParent().addRangeAfter(firstBodyElement, tryBlock.getLastBodyElement(), tryStatement); + } + tryStatement.delete(); + } + } + } + + private static void addExceptions(PsiClassType[] exceptionsToAdd, PsiTryStatement tryStatement) throws IncorrectOperationException { + for (PsiClassType type : exceptionsToAdd) { + final JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(tryStatement.getProject()); + String name = styleManager.suggestVariableName(VariableKind.PARAMETER, null, null, type).names[0]; + name = styleManager.suggestUniqueVariableName(name, tryStatement, false); + + PsiCatchSection catchSection = + JavaPsiFacade.getInstance(tryStatement.getProject()).getElementFactory().createCatchSection(type, name, tryStatement); + tryStatement.add(catchSection); + } + } + + private static PsiClassType[] filterUnhandledExceptions(PsiClassType[] exceptions, PsiElement place) { + List result = new ArrayList(); + for (PsiClassType exception : exceptions) { + if (!ExceptionUtil.isHandled(exception, place)) result.add(exception); + } + return result.toArray(new PsiClassType[result.size()]); + } + + private static boolean isCatchParameterRedundant(PsiClassType catchParamType, Collection thrownTypes) { + for (PsiType exceptionType : thrownTypes) { + if (exceptionType.isConvertibleFrom(catchParamType)) return false; + } return true; } - private static class UsageSearcher { - private final JavaChangeInfo myChangeInfo; - - private UsageSearcher(JavaChangeInfo changeInfo) { - this.myChangeInfo = changeInfo; - } - - public UsageInfo[] findUsages() { - ArrayList result = new ArrayList(); - final PsiElement element = myChangeInfo.getMethod(); - if (element instanceof PsiMethod) { - final PsiMethod method = (PsiMethod)element; - - findSimpleUsages(method, result); - - final UsageInfo[] usageInfos = result.toArray(new UsageInfo[result.size()]); - return UsageViewUtil.removeDuplicatedUsages(usageInfos); - } - return UsageInfo.EMPTY_ARRAY; - } - - - private void findSimpleUsages(final PsiMethod method, final ArrayList result) { - PsiMethod[] overridingMethods = findSimpleUsagesWithoutParameters(method, result, true, true, true); - findUsagesInCallers(result); - - //Parameter name changes are not propagated - findParametersUsage(method, result, overridingMethods); - } - - private void findUsagesInCallers(final ArrayList usages) { - if (myChangeInfo instanceof JavaChangeInfoImpl) { - JavaChangeInfoImpl changeInfo = (JavaChangeInfoImpl)myChangeInfo; - - for (PsiMethod caller : changeInfo.propagateParametersMethods) { - usages.add(new CallerUsageInfo(caller, true, changeInfo.propagateExceptionsMethods.contains(caller))); - } - for (PsiMethod caller : changeInfo.propagateExceptionsMethods) { - usages.add(new CallerUsageInfo(caller, changeInfo.propagateParametersMethods.contains(caller), true)); - } - Set merged = new HashSet(); - merged.addAll(changeInfo.propagateParametersMethods); - merged.addAll(changeInfo.propagateExceptionsMethods); - for (final PsiMethod method : merged) { - findSimpleUsagesWithoutParameters(method, usages, changeInfo.propagateParametersMethods.contains(method), - changeInfo.propagateExceptionsMethods.contains(method), false); - } - } - } - - private void detectLocalsCollisionsInMethod(final PsiMethod method, final ArrayList result, boolean isOriginal) { - if (myChangeInfo.getLanguage().equals(StdLanguages.JAVA)) { - final PsiParameter[] parameters = method.getParameterList().getParameters(); - final Set deletedOrRenamedParameters = new HashSet(); - if (isOriginal) { - deletedOrRenamedParameters.addAll(Arrays.asList(parameters)); - for (ParameterInfo parameterInfo : myChangeInfo.getNewParameters()) { - if (parameterInfo.getOldIndex() >= 0) { - final PsiParameter parameter = parameters[parameterInfo.getOldIndex()]; - if (parameterInfo.getName().equals(parameter.getName())) { - deletedOrRenamedParameters.remove(parameter); - } - } - } - } - - for (ParameterInfo parameterInfo : myChangeInfo.getNewParameters()) { - final int oldParameterIndex = parameterInfo.getOldIndex(); - final String newName = parameterInfo.getName(); - if (oldParameterIndex >= 0) { - if (isOriginal) { //Name changes take place only in primary method - final PsiParameter parameter = parameters[oldParameterIndex]; - if (!newName.equals(parameter.getName())) { - JavaUnresolvableLocalCollisionDetector.visitLocalsCollisions(parameter, newName, method.getBody(), null, - new JavaUnresolvableLocalCollisionDetector.CollidingVariableVisitor() { - public void visitCollidingElement(final PsiVariable collidingVariable) { - if (!deletedOrRenamedParameters - .contains(collidingVariable)) { - result.add( - new RenamedParameterCollidesWithLocalUsageInfo( - parameter, collidingVariable, method)); - } - } - }); - } - } + //This methods works equally well for primary usages as well as for propagated callers' usages + private static void fixActualArgumentsList(PsiExpressionList list, + JavaChangeInfo changeInfo, + boolean toInsertDefaultValue) throws IncorrectOperationException { + final PsiElementFactory factory = JavaPsiFacade.getInstance(list.getProject()).getElementFactory(); + if (changeInfo.isParameterSetOrOrderChanged()) { + if (((JavaChangeInfoImpl)changeInfo).isPropagationEnabled) { //todo + final ParameterInfoImpl[] createdParmsInfo = ((JavaChangeInfoImpl)changeInfo).getCreatedParmsInfoWithoutVarargs(); //todo + for (ParameterInfoImpl info : createdParmsInfo) { + PsiExpression newArg; + if (toInsertDefaultValue) { + newArg = createDefaultValue(changeInfo, factory, info, list); } else { - JavaUnresolvableLocalCollisionDetector.visitLocalsCollisions(method, newName, method.getBody(), null, - new JavaUnresolvableLocalCollisionDetector.CollidingVariableVisitor() { - public void visitCollidingElement(PsiVariable collidingVariable) { - if (!deletedOrRenamedParameters.contains(collidingVariable)) { - result.add(new NewParameterCollidesWithLocalUsageInfo( - collidingVariable, collidingVariable, method)); - } - } - }); + newArg = factory.createExpressionFromText(info.getName(), list); } + list.add(newArg); } } - } - - private void findParametersUsage(final PsiMethod method, ArrayList result, PsiMethod[] overriders) { - if (StdLanguages.JAVA.equals(myChangeInfo.getLanguage())) { - PsiParameter[] parameters = method.getParameterList().getParameters(); - for (ParameterInfo info : myChangeInfo.getNewParameters()) { - if (info.getOldIndex() >= 0) { - PsiParameter parameter = parameters[info.getOldIndex()]; - if (!info.getName().equals(parameter.getName())) { - addParameterUsages(parameter, result, info); - - for (PsiMethod overrider : overriders) { - PsiParameter parameter1 = overrider.getParameterList().getParameters()[info.getOldIndex()]; - if (parameter.getName().equals(parameter1.getName())) { - addParameterUsages(parameter1, result, info); - } - } - } - } - } - } - } - - private static boolean shouldPropagateToNonPhysicalMethod(PsiMethod method, - ArrayList result, - PsiClass containingClass, - final Set propagateMethods) { - for (PsiMethod psiMethod : propagateMethods) { - if (!psiMethod.isPhysical() && Comparing.strEqual(psiMethod.getName(), containingClass.getName())) { - result.add(new DefaultConstructorImplicitUsageInfo(psiMethod, containingClass, method)); - return true; - } - } - return false; - } - - private PsiMethod[] findSimpleUsagesWithoutParameters(final PsiMethod method, - final ArrayList result, - boolean isToModifyArgs, - boolean isToThrowExceptions, - boolean isOriginal) { - - GlobalSearchScope projectScope = GlobalSearchScope.projectScope(method.getProject()); - PsiMethod[] overridingMethods = OverridingMethodsSearch.search(method, method.getUseScope(), true).toArray(PsiMethod.EMPTY_ARRAY); - - for (PsiMethod overridingMethod : overridingMethods) { - result.add(new OverriderUsageInfo(overridingMethod, method, isOriginal, isToModifyArgs, isToThrowExceptions)); - } - - boolean needToChangeCalls = - !myChangeInfo.isGenerateDelegate() && (myChangeInfo.isNameChanged() || - myChangeInfo.isParameterSetOrOrderChanged() || - myChangeInfo.isExceptionSetOrOrderChanged() || - myChangeInfo.isVisibilityChanged()/*for checking inaccessible*/); - if (needToChangeCalls) { - int parameterCount = method.getParameterList().getParametersCount(); - - PsiReference[] refs = MethodReferencesSearch.search(method, projectScope, true).toArray(PsiReference.EMPTY_ARRAY); - for (PsiReference ref : refs) { - PsiElement element = ref.getElement(); - boolean isToCatchExceptions = isToThrowExceptions && needToCatchExceptions(RefactoringUtil.getEnclosingMethod(element)); - if (!isToCatchExceptions) { - if (RefactoringUtil.isMethodUsage(element)) { - PsiExpressionList list = RefactoringUtil.getArgumentListByMethodReference(element); - if (!method.isVarArgs() && list.getExpressions().length != parameterCount) continue; - } - } - if (RefactoringUtil.isMethodUsage(element)) { - result.add(new MethodCallUsageInfo(element, isToModifyArgs, isToCatchExceptions)); - } - else if (element instanceof PsiDocTagValue) { - result.add(new UsageInfo(ref.getElement())); - } - else if (element instanceof PsiMethod && ((PsiMethod)element).isConstructor()) { - DefaultConstructorImplicitUsageInfo implicitUsageInfo = - new DefaultConstructorImplicitUsageInfo((PsiMethod)element, ((PsiMethod)element).getContainingClass(), method); - result.add(implicitUsageInfo); - } - else if (element instanceof PsiClass) { - LOG.assertTrue(method.isConstructor()); - final PsiClass psiClass = (PsiClass)element; - if (!(myChangeInfo instanceof JavaChangeInfoImpl)) continue; - if (shouldPropagateToNonPhysicalMethod(method, result, psiClass, - ((JavaChangeInfoImpl)myChangeInfo).propagateParametersMethods)) { - continue; - } - if (shouldPropagateToNonPhysicalMethod(method, result, psiClass, - ((JavaChangeInfoImpl)myChangeInfo).propagateExceptionsMethods)) { - continue; - } - result.add(new NoConstructorClassUsageInfo(psiClass)); - } - else if (ref instanceof PsiCallReference) { - result.add(new CallReferenceUsageInfo((PsiCallReference)ref)); - } - else { - result.add(new MoveRenameUsageInfo(element, ref, method)); - } - } - - //if (method.isConstructor() && parameterCount == 0) { - // RefactoringUtil.visitImplicitConstructorUsages(method.getContainingClass(), - // new DefaultConstructorUsageCollector(result)); - //} - } - else if (myChangeInfo.isParameterTypesChanged()) { - PsiReference[] refs = MethodReferencesSearch.search(method, projectScope, true).toArray(PsiReference.EMPTY_ARRAY); - for (PsiReference reference : refs) { - final PsiElement element = reference.getElement(); - if (element instanceof PsiDocTagValue) { - result.add(new UsageInfo(reference)); - } - else if (element instanceof XmlElement) { - result.add(new MoveRenameUsageInfo(reference, method)); - } - } - } - - // Conflicts - detectLocalsCollisionsInMethod(method, result, isOriginal); - for (final PsiMethod overridingMethod : overridingMethods) { - detectLocalsCollisionsInMethod(overridingMethod, result, isOriginal); - } - - return overridingMethods; - } - - - private static void addParameterUsages(PsiParameter parameter, ArrayList results, ParameterInfo info) { - PsiManager manager = parameter.getManager(); - GlobalSearchScope projectScope = GlobalSearchScope.projectScope(manager.getProject()); - for (PsiReference psiReference : ReferencesSearch.search(parameter, projectScope, false)) { - PsiElement parmRef = psiReference.getElement(); - UsageInfo usageInfo = new MyParameterUsageInfo(parmRef, parameter.getName(), info.getName()); - results.add(usageInfo); - } - } - - private boolean needToCatchExceptions(PsiMethod caller) { - if (myChangeInfo instanceof JavaChangeInfoImpl) { - return myChangeInfo.isExceptionSetOrOrderChanged() && - !((JavaChangeInfoImpl)myChangeInfo).propagateExceptionsMethods.contains(caller); - } else { - return myChangeInfo.isExceptionSetOrOrderChanged(); + final PsiExpression[] args = list.getExpressions(); + final int nonVarargCount = getNonVarargCount(changeInfo, args); + final int varargCount = args.length - nonVarargCount; + PsiExpression[] newVarargInitializers = null; + + final int newArgsLength; + final int newNonVarargCount; + final JavaParameterInfo[] newParms = changeInfo.getNewParameters(); + if (changeInfo.isArrayToVarargs()) { + newNonVarargCount = newParms.length - 1; + final JavaParameterInfo lastNewParm = newParms[newParms.length - 1]; + final PsiExpression arrayToConvert = args[lastNewParm.getOldIndex()]; + if (arrayToConvert instanceof PsiNewExpression) { + final PsiNewExpression expression = (PsiNewExpression)arrayToConvert; + final PsiArrayInitializerExpression arrayInitializer = expression.getArrayInitializer(); + if (arrayInitializer != null) { + newVarargInitializers = arrayInitializer.getInitializers(); + } + } + newArgsLength = newVarargInitializers == null ? newParms.length : newNonVarargCount + newVarargInitializers.length; + } + else if (changeInfo.isRetainsVarargs()) { + newNonVarargCount = newParms.length - 1; + newArgsLength = newNonVarargCount + varargCount; + } + else if (changeInfo.isObtainsVarags()) { + newNonVarargCount = newParms.length - 1; + newArgsLength = newNonVarargCount; + } + else { + newNonVarargCount = newParms.length; + newArgsLength = newParms.length; + } + final PsiExpression[] newArgs = new PsiExpression[newArgsLength]; + final JavaParameterInfo[] newParameters = changeInfo.getNewParameters(); + for (int i = 0; i < newNonVarargCount; i++) { + newArgs[i] = createActualArgument(changeInfo, list, newParms[i], toInsertDefaultValue, args); + } + if (changeInfo.isArrayToVarargs()) { + if (newVarargInitializers == null) { + newArgs[newNonVarargCount] = + createActualArgument(changeInfo, list, newParameters[newNonVarargCount], toInsertDefaultValue, args); + } + else { + System.arraycopy(newVarargInitializers, 0, newArgs, newNonVarargCount, newVarargInitializers.length); + } + } + else { + final int newVarargCount = newArgsLength - newNonVarargCount; + LOG.assertTrue(newVarargCount == 0 || newVarargCount == varargCount); + System.arraycopy(args, nonVarargCount, newArgs, newNonVarargCount, newVarargCount); + } + ChangeSignatureUtil.synchronizeList(list, Arrays.asList(newArgs), ExpressionList.INSTANCE, changeInfo.toRemoveParm()); + } + } + } + + private static int getNonVarargCount(JavaChangeInfo changeInfo, PsiExpression[] args) { + if (!changeInfo.wasVararg()) return args.length; + return changeInfo.getOldParameterTypes().length - 1; + } + + + @Nullable + private static PsiExpression createActualArgument(JavaChangeInfo changeInfo, + final PsiExpressionList list, + final JavaParameterInfo info, + final boolean toInsertDefaultValue, + final PsiExpression[] args) throws IncorrectOperationException { + final PsiElementFactory factory = JavaPsiFacade.getInstance(list.getProject()).getElementFactory(); + final int index = info.getOldIndex(); + if (index >= 0) { + return args[index]; + } + else { + if (toInsertDefaultValue) { + return createDefaultValue(changeInfo, factory, info, list); + } + else { + return factory.createExpressionFromText(info.getName(), list); + } + } + } + + @Nullable + private static PsiExpression createDefaultValue(JavaChangeInfo changeInfo, + final PsiElementFactory factory, + final JavaParameterInfo info, + final PsiExpressionList list) + throws IncorrectOperationException { + if (((ParameterInfoImpl)info).isUseAnySingleVariable()) { //todo + final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(list.getProject()).getResolveHelper(); + final PsiType type = info.getTypeWrapper().getType(changeInfo.getMethod(), list.getManager()); + final VariablesProcessor processor = new VariablesProcessor(false) { + protected boolean check(PsiVariable var, ResolveState state) { + if (var instanceof PsiField && !resolveHelper.isAccessible((PsiField)var, list, null)) return false; + final PsiType varType = state.get(PsiSubstitutor.KEY).substitute(var.getType()); + return type.isAssignableFrom(varType); + } + + public boolean execute(PsiElement pe, ResolveState state) { + super.execute(pe, state); + return size() < 2; + } + }; + PsiScopesUtil.treeWalkUp(processor, list, null); + if (processor.size() == 1) { + final PsiVariable result = processor.getResult(0); + return factory.createExpressionFromText(result.getName(), list); + } + } + final PsiCallExpression callExpression = PsiTreeUtil.getParentOfType(list, PsiCallExpression.class); + return callExpression != null ? info.getValue(callExpression) : factory.createExpressionFromText(info.getDefaultValue(), list); + } + + + public boolean processPrimaryMethod(ChangeInfo changeInfo) { + if (!StdLanguages.JAVA.equals(changeInfo.getLanguage()) || !(changeInfo instanceof JavaChangeInfo)) return false; + final PsiElement element = changeInfo.getMethod(); + LOG.assertTrue(element instanceof PsiMethod); + if (changeInfo.isGenerateDelegate()) { + generateDelegate((JavaChangeInfo)changeInfo); + } + processPrimaryMethod((JavaChangeInfo)changeInfo, (PsiMethod)element, null, true); + return true; + } + private void generateDelegate(JavaChangeInfo changeInfo) throws IncorrectOperationException { + final PsiMethod delegate = (PsiMethod)changeInfo.getMethod().copy(); + final PsiClass targetClass = changeInfo.getMethod().getContainingClass(); + LOG.assertTrue(!targetClass.isInterface()); + PsiElementFactory factory = JavaPsiFacade.getElementFactory(targetClass.getProject()); + ChangeSignatureProcessor.makeEmptyBody(factory, delegate); + final PsiCallExpression callExpression = ChangeSignatureProcessor.addDelegatingCallTemplate(delegate, changeInfo.getNewName()); + addDelegateArguments(changeInfo, factory, callExpression); + targetClass.addBefore(delegate, changeInfo.getMethod()); + } + + + private static void addDelegateArguments(JavaChangeInfo changeInfo, PsiElementFactory factory, final PsiCallExpression callExpression) throws IncorrectOperationException { + final JavaParameterInfo[] newParms = changeInfo.getNewParameters(); + final String[] oldParameterNames = changeInfo.getOldParameterNames(); + for (int i = 0; i < newParms.length; i++) { + JavaParameterInfo newParm = newParms[i]; + final PsiExpression actualArg; + if (newParm.getOldIndex() >= 0) { + actualArg = factory.createExpressionFromText(oldParameterNames[newParm.getOldIndex()], callExpression); + } + else { + actualArg = changeInfo.getValue(i, callExpression); + } + callExpression.getArgumentList().add(actualArg); + } + } + + private static void processPrimaryMethod(JavaChangeInfo changeInfo, PsiMethod method, + PsiMethod baseMethod, + boolean isOriginal) throws IncorrectOperationException { + PsiElementFactory factory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory(); + + if (changeInfo.isVisibilityChanged()) { + PsiModifierList modifierList = method.getModifierList(); + final String highestVisibility = isOriginal ? + changeInfo.getNewVisibility() : + VisibilityUtil + .getHighestVisibility(changeInfo.getNewVisibility(), + VisibilityUtil.getVisibilityModifier(modifierList)); + VisibilityUtil.setVisibility(modifierList, highestVisibility); + } + + if (changeInfo.isNameChanged()) { + String newName = baseMethod == null ? changeInfo.getNewName() : + RefactoringUtil.suggestNewOverriderName(method.getName(), baseMethod.getName(), changeInfo.getNewName()); + + if (newName != null && !newName.equals(method.getName())) { + final PsiIdentifier nameId = method.getNameIdentifier(); + assert nameId != null; + nameId.replace(JavaPsiFacade.getInstance(method.getProject()).getElementFactory().createIdentifier(newName)); } } - private static class RenamedParameterCollidesWithLocalUsageInfo extends UnresolvableCollisionUsageInfo { - private final PsiElement myCollidingElement; - private final PsiMethod myMethod; + final PsiSubstitutor substitutor = baseMethod == null ? PsiSubstitutor.EMPTY : calculateSubstitutor(method, baseMethod); - public RenamedParameterCollidesWithLocalUsageInfo(PsiParameter parameter, PsiElement collidingElement, PsiMethod method) { - super(parameter, collidingElement); - myCollidingElement = collidingElement; - myMethod = method; + if (changeInfo.isReturnTypeChanged()) { + PsiType newTypeElement = changeInfo.getNewReturnType().getType(changeInfo.getMethod().getParameterList(), method.getManager()); + final PsiType returnType = substitutor.substitute(newTypeElement); + // don't modify return type for non-Java overriders (EJB) + if (method.getName().equals(changeInfo.getNewName())) { + final PsiTypeElement typeElement = method.getReturnTypeElement(); + if (typeElement != null) { + typeElement.replace(factory.createTypeElement(returnType)); + } } + } - public String getDescription() { - return RefactoringBundle.message("there.is.already.a.0.in.the.1.it.will.conflict.with.the.renamed.parameter", - RefactoringUIUtil.getDescription(myCollidingElement, true), - RefactoringUIUtil.getDescription(myMethod, true)); + PsiParameterList list = method.getParameterList(); + PsiParameter[] parameters = list.getParameters(); + + final JavaParameterInfo[] parameterInfos = changeInfo.getNewParameters(); + PsiParameter[] newParms = new PsiParameter[parameterInfos.length]; + final String[] oldParameterNames = changeInfo.getOldParameterNames(); + final String[] oldParameterTypes = changeInfo.getOldParameterTypes(); + for (int i = 0; i < newParms.length; i++) { + JavaParameterInfo info = parameterInfos[i]; + int index = info.getOldIndex(); + if (index >= 0) { + PsiParameter parameter = parameters[index]; + newParms[i] = parameter; + + String oldName = oldParameterNames[index]; + if (!oldName.equals(info.getName()) && oldName.equals(parameter.getName())) { + PsiIdentifier newIdentifier = factory.createIdentifier(info.getName()); + parameter.getNameIdentifier().replace(newIdentifier); + } + + String oldType = oldParameterTypes[index]; + if (!oldType.equals(info.getTypeText())) { + parameter.normalizeDeclaration(); + PsiType newType = substitutor.substitute(info.createType(changeInfo.getMethod().getParameterList(), method.getManager())); + + parameter.getTypeElement().replace(factory.createTypeElement(newType)); + } } + else { + newParms[i] = createNewParameter(changeInfo, info, substitutor); + } + } + + + resolveParameterVsFieldsConflicts(newParms, method, list, changeInfo.toRemoveParm()); + fixJavadocsForChangedMethod(method, changeInfo); + if (changeInfo.isExceptionSetOrOrderChanged()) { + final PsiClassType[] newExceptions = getPrimaryChangedExceptionInfo(changeInfo); + fixPrimaryThrowsLists(method, newExceptions); + } + } + + private static PsiClassType[] getPrimaryChangedExceptionInfo(JavaChangeInfo changeInfo) throws IncorrectOperationException { + final ThrownExceptionInfo[] newExceptionInfos = changeInfo.getNewExceptions(); + PsiClassType[] newExceptions = new PsiClassType[newExceptionInfos.length]; + final PsiMethod method = changeInfo.getMethod(); + for (int i = 0; i < newExceptions.length; i++) { + newExceptions[i] = + (PsiClassType)newExceptionInfos[i].myType.getType(method, method.getManager()); //context really does not matter here + } + return newExceptions; + } + + + private static void processCallerMethod(JavaChangeInfo changeInfo, PsiMethod caller, + PsiMethod baseMethod, + boolean toInsertParams, + boolean toInsertThrows) throws IncorrectOperationException { + LOG.assertTrue(toInsertParams || toInsertThrows); + if (toInsertParams) { + List newParameters = new ArrayList(); + newParameters.addAll(Arrays.asList(caller.getParameterList().getParameters())); + final JavaParameterInfo[] primaryNewParms = changeInfo.getNewParameters(); + PsiSubstitutor substitutor = baseMethod == null ? PsiSubstitutor.EMPTY : calculateSubstitutor(caller, baseMethod); + for (JavaParameterInfo info : primaryNewParms) { + if (info.getOldIndex() < 0) newParameters.add(createNewParameter(changeInfo, info, substitutor)); + } + PsiParameter[] arrayed = newParameters.toArray(new PsiParameter[newParameters.size()]); + boolean[] toRemoveParm = new boolean[arrayed.length]; + Arrays.fill(toRemoveParm, false); + resolveParameterVsFieldsConflicts(arrayed, caller, caller.getParameterList(), toRemoveParm); + } + + if (toInsertThrows) { + List newThrowns = new ArrayList(); + final PsiReferenceList throwsList = caller.getThrowsList(); + newThrowns.addAll(Arrays.asList(throwsList.getReferenceElements())); + final ThrownExceptionInfo[] primaryNewExns = changeInfo.getNewExceptions(); + for (ThrownExceptionInfo thrownExceptionInfo : primaryNewExns) { + if (thrownExceptionInfo.oldIndex < 0) { + final PsiClassType type = (PsiClassType)thrownExceptionInfo.createType(caller, caller.getManager()); + final PsiJavaCodeReferenceElement ref = + JavaPsiFacade.getInstance(caller.getProject()).getElementFactory().createReferenceElementByType(type); + newThrowns.add(ref); + } + } + PsiJavaCodeReferenceElement[] arrayed = newThrowns.toArray(new PsiJavaCodeReferenceElement[newThrowns.size()]); + boolean[] toRemoveParm = new boolean[arrayed.length]; + Arrays.fill(toRemoveParm, false); + ChangeSignatureUtil.synchronizeList(throwsList, Arrays.asList(arrayed), ThrowsList.INSTANCE, toRemoveParm); + } + } + + private static void fixPrimaryThrowsLists(PsiMethod method, PsiClassType[] newExceptions) throws IncorrectOperationException { + PsiElementFactory elementFactory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory(); + PsiJavaCodeReferenceElement[] refs = new PsiJavaCodeReferenceElement[newExceptions.length]; + for (int i = 0; i < refs.length; i++) { + refs[i] = elementFactory.createReferenceElementByType(newExceptions[i]); + } + PsiReferenceList throwsList = elementFactory.createReferenceList(refs); + + PsiReferenceList methodThrowsList = (PsiReferenceList)method.getThrowsList().replace(throwsList); + methodThrowsList = (PsiReferenceList)JavaCodeStyleManager.getInstance(method.getProject()).shortenClassReferences(methodThrowsList); + method.getManager().getCodeStyleManager().reformatRange(method, method.getParameterList().getTextRange().getEndOffset(), + methodThrowsList.getTextRange().getEndOffset()); + } + + private static void fixJavadocsForChangedMethod(PsiMethod method, JavaChangeInfo changeInfo) throws IncorrectOperationException { + final PsiParameter[] parameters = method.getParameterList().getParameters(); + final JavaParameterInfo[] newParms = changeInfo.getNewParameters(); + LOG.assertTrue(parameters.length == newParms.length); + final Set newParameters = new HashSet(); + final String[] oldParameterNames = changeInfo.getOldParameterNames(); + for (int i = 0; i < newParms.length; i++) { + JavaParameterInfo newParm = newParms[i]; + if (newParm.getOldIndex() < 0 || + !newParm.getName().equals(oldParameterNames[newParm.getOldIndex()])) { + newParameters.add(parameters[i]); + } + } + RefactoringUtil.fixJavadocsForParams(method, newParameters); + } + + private static PsiParameter createNewParameter(JavaChangeInfo changeInfo, JavaParameterInfo newParm, + PsiSubstitutor substitutor) throws IncorrectOperationException { + final PsiParameterList list = changeInfo.getMethod().getParameterList(); + final PsiElementFactory factory = JavaPsiFacade.getInstance(list.getProject()).getElementFactory(); + final PsiType type = substitutor.substitute(newParm.createType(list, list.getManager())); + return factory.createParameter(newParm.getName(), type); + } + + private static void resolveParameterVsFieldsConflicts(final PsiParameter[] newParms, + final PsiMethod method, + final PsiParameterList list, + boolean[] toRemoveParm) throws IncorrectOperationException { + List conflictResolvers = new ArrayList(); + for (PsiParameter parameter : newParms) { + conflictResolvers.add(new FieldConflictsResolver(parameter.getName(), method.getBody())); + } + ChangeSignatureUtil.synchronizeList(list, Arrays.asList(newParms), ParameterList.INSTANCE, toRemoveParm); + JavaCodeStyleManager.getInstance(list.getProject()).shortenClassReferences(list); + for (FieldConflictsResolver fieldConflictsResolver : conflictResolvers) { + fieldConflictsResolver.fix(); + } + } + + private static PsiSubstitutor calculateSubstitutor(PsiMethod derivedMethod, PsiMethod baseMethod) { + PsiSubstitutor substitutor; + if (derivedMethod.getManager().areElementsEquivalent(derivedMethod, baseMethod)) { + substitutor = PsiSubstitutor.EMPTY; + } + else { + final PsiClass baseClass = baseMethod.getContainingClass(); + final PsiClass derivedClass = derivedMethod.getContainingClass(); + if (baseClass != null && derivedClass != null && InheritanceUtil.isInheritorOrSelf(derivedClass, baseClass, true)) { + final PsiSubstitutor superClassSubstitutor = + TypeConversionUtil.getSuperClassSubstitutor(baseClass, derivedClass, PsiSubstitutor.EMPTY); + final MethodSignature superMethodSignature = baseMethod.getSignature(superClassSubstitutor); + final MethodSignature methodSignature = derivedMethod.getSignature(PsiSubstitutor.EMPTY); + final PsiSubstitutor superMethodSubstitutor = + MethodSignatureUtil.getSuperMethodSignatureSubstitutor(methodSignature, superMethodSignature); + substitutor = superMethodSubstitutor != null ? superMethodSubstitutor : superClassSubstitutor; + } + else { + substitutor = PsiSubstitutor.EMPTY; + } + } + return substitutor; + } + + private static boolean needToCatchExceptions(JavaChangeInfo changeInfo, PsiMethod caller) { + return changeInfo.isExceptionSetOrOrderChanged() && + !((JavaChangeInfoImpl)changeInfo).propagateExceptionsMethods.contains(caller); //todo + } + + private static class ParameterList implements ChangeSignatureUtil.ChildrenGenerator { + public static final ParameterList INSTANCE = new ParameterList(); + + public List getChildren(PsiParameterList psiParameterList) { + return Arrays.asList(psiParameterList.getParameters()); + } + } + + private static class ThrowsList implements ChangeSignatureUtil.ChildrenGenerator { + public static final ThrowsList INSTANCE = new ThrowsList(); + + public List getChildren(PsiReferenceList throwsList) { + return Arrays.asList(throwsList.getReferenceElements()); } } @@ -379,7 +785,8 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr } - private void addInaccessibilityDescriptions(Set usages, MultiMap conflictDescriptions) throws IncorrectOperationException { + private void addInaccessibilityDescriptions(Set usages, MultiMap conflictDescriptions) + throws IncorrectOperationException { PsiMethod method = myChangeInfo.getMethod(); PsiModifierList modifierList = (PsiModifierList)method.getModifierList().copy(); VisibilityUtil.setVisibility(modifierList, myChangeInfo.getNewVisibility()); @@ -458,4 +865,13 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr this.newParameterName = newParameterName; } } + + private static class ExpressionList implements ChangeSignatureUtil.ChildrenGenerator { + public static final ExpressionList INSTANCE = new ExpressionList(); + + public List getChildren(PsiExpressionList psiExpressionList) { + return Arrays.asList(psiExpressionList.getExpressions()); + } + } + } diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaParameterInfo.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaParameterInfo.java index 18a41ad8ccc8..e341c6d4d108 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaParameterInfo.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaParameterInfo.java @@ -15,9 +15,8 @@ */ package com.intellij.refactoring.changeSignature; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiManager; -import com.intellij.psi.PsiType; +import com.intellij.psi.*; +import com.intellij.refactoring.util.CanonicalTypes; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.Nullable; @@ -27,4 +26,10 @@ import org.jetbrains.annotations.Nullable; public interface JavaParameterInfo extends ParameterInfo { @Nullable PsiType createType(PsiElement context, final PsiManager manager) throws IncorrectOperationException; + + String getTypeText(); + + CanonicalTypes.Type getTypeWrapper(); + + PsiExpression getValue(PsiCallExpression callExpression); } diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/UsageSearcher.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/UsageSearcher.java new file mode 100644 index 000000000000..38cbbe0780a3 --- /dev/null +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/UsageSearcher.java @@ -0,0 +1,312 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.refactoring.changeSignature; + +import com.intellij.lang.StdLanguages; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.Comparing; +import com.intellij.psi.*; +import com.intellij.psi.javadoc.PsiDocTagValue; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.search.searches.MethodReferencesSearch; +import com.intellij.psi.search.searches.OverridingMethodsSearch; +import com.intellij.psi.search.searches.ReferencesSearch; +import com.intellij.psi.xml.XmlElement; +import com.intellij.refactoring.RefactoringBundle; +import com.intellij.refactoring.rename.JavaUnresolvableLocalCollisionDetector; +import com.intellij.refactoring.rename.UnresolvableCollisionUsageInfo; +import com.intellij.refactoring.util.MoveRenameUsageInfo; +import com.intellij.refactoring.util.RefactoringUIUtil; +import com.intellij.refactoring.util.RefactoringUtil; +import com.intellij.refactoring.util.usageInfo.DefaultConstructorImplicitUsageInfo; +import com.intellij.refactoring.util.usageInfo.NoConstructorClassUsageInfo; +import com.intellij.usageView.UsageInfo; +import com.intellij.usageView.UsageViewUtil; +import com.intellij.util.containers.HashSet; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Set; + +/** + * @author Maxim.Medvedev + */ +class UsageSearcher { + private final JavaChangeInfo myChangeInfo; + private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.changeSignature.UsageSearcher"); + + UsageSearcher(JavaChangeInfo changeInfo) { + this.myChangeInfo = changeInfo; + } + + public UsageInfo[] findUsages() { + ArrayList result = new ArrayList(); + final PsiElement element = myChangeInfo.getMethod(); + if (element instanceof PsiMethod) { + final PsiMethod method = (PsiMethod)element; + + findSimpleUsages(method, result); + + final UsageInfo[] usageInfos = result.toArray(new UsageInfo[result.size()]); + return UsageViewUtil.removeDuplicatedUsages(usageInfos); + } + return UsageInfo.EMPTY_ARRAY; + } + + + private void findSimpleUsages(final PsiMethod method, final ArrayList result) { + PsiMethod[] overridingMethods = findSimpleUsagesWithoutParameters(method, result, true, true, true); + findUsagesInCallers(result); + + //Parameter name changes are not propagated + findParametersUsage(method, result, overridingMethods); + } + + private void findUsagesInCallers(final ArrayList usages) { + if (myChangeInfo instanceof JavaChangeInfoImpl) { + JavaChangeInfoImpl changeInfo = (JavaChangeInfoImpl)myChangeInfo; + + for (PsiMethod caller : changeInfo.propagateParametersMethods) { + usages.add(new CallerUsageInfo(caller, true, changeInfo.propagateExceptionsMethods.contains(caller))); + } + for (PsiMethod caller : changeInfo.propagateExceptionsMethods) { + usages.add(new CallerUsageInfo(caller, changeInfo.propagateParametersMethods.contains(caller), true)); + } + Set merged = new HashSet(); + merged.addAll(changeInfo.propagateParametersMethods); + merged.addAll(changeInfo.propagateExceptionsMethods); + for (final PsiMethod method : merged) { + findSimpleUsagesWithoutParameters(method, usages, changeInfo.propagateParametersMethods.contains(method), + changeInfo.propagateExceptionsMethods.contains(method), false); + } + } + } + + private void detectLocalsCollisionsInMethod(final PsiMethod method, final ArrayList result, boolean isOriginal) { + if (myChangeInfo.getLanguage().equals(StdLanguages.JAVA)) { + final PsiParameter[] parameters = method.getParameterList().getParameters(); + final Set deletedOrRenamedParameters = new HashSet(); + if (isOriginal) { + deletedOrRenamedParameters.addAll(Arrays.asList(parameters)); + for (ParameterInfo parameterInfo : myChangeInfo.getNewParameters()) { + if (parameterInfo.getOldIndex() >= 0) { + final PsiParameter parameter = parameters[parameterInfo.getOldIndex()]; + if (parameterInfo.getName().equals(parameter.getName())) { + deletedOrRenamedParameters.remove(parameter); + } + } + } + } + + for (ParameterInfo parameterInfo : myChangeInfo.getNewParameters()) { + final int oldParameterIndex = parameterInfo.getOldIndex(); + final String newName = parameterInfo.getName(); + if (oldParameterIndex >= 0) { + if (isOriginal) { //Name changes take place only in primary method + final PsiParameter parameter = parameters[oldParameterIndex]; + if (!newName.equals(parameter.getName())) { + JavaUnresolvableLocalCollisionDetector.visitLocalsCollisions(parameter, newName, method.getBody(), null, + new JavaUnresolvableLocalCollisionDetector.CollidingVariableVisitor() { + public void visitCollidingElement(final PsiVariable collidingVariable) { + if (!deletedOrRenamedParameters + .contains(collidingVariable)) { + result.add( + new RenamedParameterCollidesWithLocalUsageInfo( + parameter, collidingVariable, method)); + } + } + }); + } + } + } + else { + JavaUnresolvableLocalCollisionDetector.visitLocalsCollisions(method, newName, method.getBody(), null, + new JavaUnresolvableLocalCollisionDetector.CollidingVariableVisitor() { + public void visitCollidingElement(PsiVariable collidingVariable) { + if (!deletedOrRenamedParameters.contains(collidingVariable)) { + result.add(new NewParameterCollidesWithLocalUsageInfo( + collidingVariable, collidingVariable, method)); + } + } + }); + } + } + } + } + + private void findParametersUsage(final PsiMethod method, ArrayList result, PsiMethod[] overriders) { + if (StdLanguages.JAVA.equals(myChangeInfo.getLanguage())) { + PsiParameter[] parameters = method.getParameterList().getParameters(); + for (ParameterInfo info : myChangeInfo.getNewParameters()) { + if (info.getOldIndex() >= 0) { + PsiParameter parameter = parameters[info.getOldIndex()]; + if (!info.getName().equals(parameter.getName())) { + addParameterUsages(parameter, result, info); + + for (PsiMethod overrider : overriders) { + PsiParameter parameter1 = overrider.getParameterList().getParameters()[info.getOldIndex()]; + if (parameter.getName().equals(parameter1.getName())) { + addParameterUsages(parameter1, result, info); + } + } + } + } + } + } + } + + private static boolean shouldPropagateToNonPhysicalMethod(PsiMethod method, + ArrayList result, + PsiClass containingClass, + final Set propagateMethods) { + for (PsiMethod psiMethod : propagateMethods) { + if (!psiMethod.isPhysical() && Comparing.strEqual(psiMethod.getName(), containingClass.getName())) { + result.add(new DefaultConstructorImplicitUsageInfo(psiMethod, containingClass, method)); + return true; + } + } + return false; + } + + private PsiMethod[] findSimpleUsagesWithoutParameters(final PsiMethod method, + final ArrayList result, + boolean isToModifyArgs, + boolean isToThrowExceptions, + boolean isOriginal) { + + GlobalSearchScope projectScope = GlobalSearchScope.projectScope(method.getProject()); + PsiMethod[] overridingMethods = OverridingMethodsSearch.search(method, method.getUseScope(), true).toArray(PsiMethod.EMPTY_ARRAY); + + for (PsiMethod overridingMethod : overridingMethods) { + result.add(new OverriderUsageInfo(overridingMethod, method, isOriginal, isToModifyArgs, isToThrowExceptions)); + } + + boolean needToChangeCalls = + !myChangeInfo.isGenerateDelegate() && (myChangeInfo.isNameChanged() || + myChangeInfo.isParameterSetOrOrderChanged() || + myChangeInfo.isExceptionSetOrOrderChanged() || + myChangeInfo.isVisibilityChanged()/*for checking inaccessible*/); + if (needToChangeCalls) { + int parameterCount = method.getParameterList().getParametersCount(); + + PsiReference[] refs = MethodReferencesSearch.search(method, projectScope, true).toArray(PsiReference.EMPTY_ARRAY); + for (PsiReference ref : refs) { + PsiElement element = ref.getElement(); + boolean isToCatchExceptions = isToThrowExceptions && needToCatchExceptions(RefactoringUtil.getEnclosingMethod(element)); + if (!isToCatchExceptions) { + if (RefactoringUtil.isMethodUsage(element)) { + PsiExpressionList list = RefactoringUtil.getArgumentListByMethodReference(element); + if (!method.isVarArgs() && list.getExpressions().length != parameterCount) continue; + } + } + if (RefactoringUtil.isMethodUsage(element)) { + result.add(new MethodCallUsageInfo(element, isToModifyArgs, isToCatchExceptions)); + } + else if (element instanceof PsiDocTagValue) { + result.add(new UsageInfo(ref.getElement())); + } + else if (element instanceof PsiMethod && ((PsiMethod)element).isConstructor()) { + DefaultConstructorImplicitUsageInfo implicitUsageInfo = + new DefaultConstructorImplicitUsageInfo((PsiMethod)element, ((PsiMethod)element).getContainingClass(), method); + result.add(implicitUsageInfo); + } + else if (element instanceof PsiClass) { + LOG.assertTrue(method.isConstructor()); + final PsiClass psiClass = (PsiClass)element; + if (!(myChangeInfo instanceof JavaChangeInfoImpl)) continue; + if (shouldPropagateToNonPhysicalMethod(method, result, psiClass, + ((JavaChangeInfoImpl)myChangeInfo).propagateParametersMethods)) { + continue; + } + if (shouldPropagateToNonPhysicalMethod(method, result, psiClass, + ((JavaChangeInfoImpl)myChangeInfo).propagateExceptionsMethods)) { + continue; + } + result.add(new NoConstructorClassUsageInfo(psiClass)); + } + else if (ref instanceof PsiCallReference) { + result.add(new CallReferenceUsageInfo((PsiCallReference)ref)); + } + else { + result.add(new MoveRenameUsageInfo(element, ref, method)); + } + } + + //if (method.isConstructor() && parameterCount == 0) { + // RefactoringUtil.visitImplicitConstructorUsages(method.getContainingClass(), + // new DefaultConstructorUsageCollector(result)); + //} + } + else if (myChangeInfo.isParameterTypesChanged()) { + PsiReference[] refs = MethodReferencesSearch.search(method, projectScope, true).toArray(PsiReference.EMPTY_ARRAY); + for (PsiReference reference : refs) { + final PsiElement element = reference.getElement(); + if (element instanceof PsiDocTagValue) { + result.add(new UsageInfo(reference)); + } + else if (element instanceof XmlElement) { + result.add(new MoveRenameUsageInfo(reference, method)); + } + } + } + + // Conflicts + detectLocalsCollisionsInMethod(method, result, isOriginal); + for (final PsiMethod overridingMethod : overridingMethods) { + detectLocalsCollisionsInMethod(overridingMethod, result, isOriginal); + } + + return overridingMethods; + } + + + private static void addParameterUsages(PsiParameter parameter, ArrayList results, ParameterInfo info) { + PsiManager manager = parameter.getManager(); + GlobalSearchScope projectScope = GlobalSearchScope.projectScope(manager.getProject()); + for (PsiReference psiReference : ReferencesSearch.search(parameter, projectScope, false)) { + PsiElement parmRef = psiReference.getElement(); + UsageInfo usageInfo = new JavaChangeSignatureUsageProcessor.MyParameterUsageInfo(parmRef, parameter.getName(), info.getName()); + results.add(usageInfo); + } + } + + private boolean needToCatchExceptions(PsiMethod caller) { + if (myChangeInfo instanceof JavaChangeInfoImpl) { + return myChangeInfo.isExceptionSetOrOrderChanged() && + !((JavaChangeInfoImpl)myChangeInfo).propagateExceptionsMethods.contains(caller); + } + else { + return myChangeInfo.isExceptionSetOrOrderChanged(); + } + } + + private static class RenamedParameterCollidesWithLocalUsageInfo extends UnresolvableCollisionUsageInfo { + private final PsiElement myCollidingElement; + private final PsiMethod myMethod; + + public RenamedParameterCollidesWithLocalUsageInfo(PsiParameter parameter, PsiElement collidingElement, PsiMethod method) { + super(parameter, collidingElement); + myCollidingElement = collidingElement; + myMethod = method; + } + + public String getDescription() { + return RefactoringBundle.message("there.is.already.a.0.in.the.1.it.will.conflict.with.the.renamed.parameter", + RefactoringUIUtil.getDescription(myCollidingElement, true), + RefactoringUIUtil.getDescription(myMethod, true)); + } + } +} diff --git a/platform/lang-api/src/com/intellij/refactoring/changeSignature/ChangeSignatureUsageProcessor.java b/platform/lang-api/src/com/intellij/refactoring/changeSignature/ChangeSignatureUsageProcessor.java index 6602ea05d708..3857afd60dda 100644 --- a/platform/lang-api/src/com/intellij/refactoring/changeSignature/ChangeSignatureUsageProcessor.java +++ b/platform/lang-api/src/com/intellij/refactoring/changeSignature/ChangeSignatureUsageProcessor.java @@ -32,5 +32,7 @@ public interface ChangeSignatureUsageProcessor { MultiMap findConflicts(ChangeInfo info, Ref refUsages); - boolean processUsage(ChangeInfo changeInfo, UsageInfo usageInfo); + boolean processUsage(ChangeInfo changeInfo, UsageInfo usageInfo, boolean beforeMethodChange, UsageInfo[] usages); + + boolean processPrimaryMethod(ChangeInfo changeInfo); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java index 19143d2ad0c9..c49871851d44 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java @@ -19,6 +19,7 @@ import com.intellij.lang.Language; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Ref; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiIdentifier; import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiReference; import com.intellij.psi.search.searches.MethodReferencesSearch; @@ -26,6 +27,7 @@ import com.intellij.refactoring.BaseRefactoringProcessor; import com.intellij.refactoring.changeSignature.ChangeSignatureViewDescriptor; import com.intellij.refactoring.changeSignature.JavaChangeInfo; import com.intellij.refactoring.changeSignature.JavaParameterInfo; +import com.intellij.refactoring.changeSignature.ThrownExceptionInfo; import com.intellij.refactoring.util.CanonicalTypes; import com.intellij.usageView.UsageInfo; import com.intellij.usageView.UsageViewDescriptor; @@ -206,5 +208,47 @@ public class GrChangeSignatureProcessor extends BaseRefactoringProcessor { public String getVisibilityModifier() { return visibilityModifier; } + + @NotNull + public String[] getOldParameterNames() { + return new String[0]; //To change body of implemented methods use File | Settings | File Templates. + } + + @NotNull + public String[] getOldParameterTypes() { + return new String[0]; //To change body of implemented methods use File | Settings | File Templates. + } + + public ThrownExceptionInfo[] getNewExceptions() { + return new ThrownExceptionInfo[0]; //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean isRetainsVarargs() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean isObtainsVarags() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean isArrayToVarargs() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + public PsiIdentifier getNewNameIdentifier() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + public String getOldName() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean wasVararg() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean[] toRemoveParm() { + return new boolean[0]; //To change body of implemented methods use File | Settings | File Templates. + } } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java index 487234d6bd74..e0703e325c4f 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java @@ -18,6 +18,7 @@ package org.jetbrains.plugins.groovy.refactoring.changeSignature; import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.refactoring.changeSignature.JavaParameterInfo; +import com.intellij.refactoring.util.CanonicalTypes; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.debugger.fragments.GroovyCodeFragment; @@ -104,4 +105,16 @@ public class GrParameterInfo implements JavaParameterInfo { } } + + public String getTypeText() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + public CanonicalTypes.Type getTypeWrapper() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + public PsiExpression getValue(PsiCallExpression callExpression) { + return null; //To change body of implemented methods use File | Settings | File Templates. + } } From 828cb69421dc9440d20a2f25e75dbd4566b8d156 Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Thu, 15 Apr 2010 13:57:07 +0400 Subject: [PATCH 007/212] Groovy ChangeSignature usageSearch initial --- .../ChangeSignatureParameterUsageInfo.java | 33 ++ .../ChangeSignatureProcessor.java | 1 + .../JavaChangeSignatureUsageProcessor.java | 20 +- .../changeSignature/UsageSearcher.java | 83 ++--- .../lang/psi/GroovyPsiElementFactory.java | 2 + .../psi/impl/GroovyPsiElementFactoryImpl.java | 6 + .../GrChageSignatureUsageSearcher.java | 309 ++++++++++++++++++ .../GrChangeSignatureProcessor.java | 43 ++- .../GrChangeSignatureUsageProcessor.java | 48 +++ .../GrMethodCallUsageInfo.java | 81 +++++ .../GrUnresolvableLocalCollisionDetector.java | 105 ++++++ 11 files changed, 660 insertions(+), 71 deletions(-) create mode 100644 java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureParameterUsageInfo.java create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChageSignatureUsageSearcher.java create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodCallUsageInfo.java create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrUnresolvableLocalCollisionDetector.java diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureParameterUsageInfo.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureParameterUsageInfo.java new file mode 100644 index 000000000000..15cf7f0e0702 --- /dev/null +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureParameterUsageInfo.java @@ -0,0 +1,33 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.refactoring.changeSignature; + +import com.intellij.psi.PsiElement; +import com.intellij.usageView.UsageInfo; + +/** +* @author Maxim.Medvedev +*/ +public class ChangeSignatureParameterUsageInfo extends UsageInfo { + final String oldParameterName; + final String newParameterName; + + public ChangeSignatureParameterUsageInfo(PsiElement element, String oldParameterName, String newParameterName) { + super(element); + this.oldParameterName = oldParameterName; + this.newParameterName = newParameterName; + } +} diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java index 603adc22feae..e351932529dc 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java @@ -131,6 +131,7 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor { final MultiMap conflicts = usageProcessor.findConflicts(myChangeInfo, refUsages); for (PsiElement key : conflicts.keySet()) { Collection collection = conflictDescriptions.get(key); + if (collection.size() == 0) collection = new HashSet(); collection.addAll(conflicts.get(key)); conflictDescriptions.put(key, collection); } diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java index bf734c040dec..2136a0f7c5f3 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java @@ -126,9 +126,9 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr methodCallInfo.isToCatchExceptions(), methodCallInfo.getReferencedMethod(), usages); return true; } - else if (usage instanceof MyParameterUsageInfo) { - String newName = ((MyParameterUsageInfo)usage).newParameterName; - String oldName = ((MyParameterUsageInfo)usage).oldParameterName; + else if (usage instanceof ChangeSignatureParameterUsageInfo) { + String newName = ((ChangeSignatureParameterUsageInfo)usage).newParameterName; + String oldName = ((ChangeSignatureParameterUsageInfo)usage).oldParameterName; processParameterUsage((PsiReferenceExpression)element, oldName, newName); return true; } @@ -495,7 +495,8 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr processPrimaryMethod((JavaChangeInfo)changeInfo, (PsiMethod)element, null, true); return true; } - private void generateDelegate(JavaChangeInfo changeInfo) throws IncorrectOperationException { + + private static void generateDelegate(JavaChangeInfo changeInfo) throws IncorrectOperationException { final PsiMethod delegate = (PsiMethod)changeInfo.getMethod().copy(); final PsiClass targetClass = changeInfo.getMethod().getContainingClass(); LOG.assertTrue(!targetClass.isInterface()); @@ -855,17 +856,6 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr } } - static class MyParameterUsageInfo extends UsageInfo { - final String oldParameterName; - final String newParameterName; - - public MyParameterUsageInfo(PsiElement element, String oldParameterName, String newParameterName) { - super(element); - this.oldParameterName = oldParameterName; - this.newParameterName = newParameterName; - } - } - private static class ExpressionList implements ChangeSignatureUtil.ChildrenGenerator { public static final ExpressionList INSTANCE = new ExpressionList(); diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/UsageSearcher.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/UsageSearcher.java index 38cbbe0780a3..4902403dad1f 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/UsageSearcher.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/UsageSearcher.java @@ -96,53 +96,53 @@ class UsageSearcher { } private void detectLocalsCollisionsInMethod(final PsiMethod method, final ArrayList result, boolean isOriginal) { - if (myChangeInfo.getLanguage().equals(StdLanguages.JAVA)) { - final PsiParameter[] parameters = method.getParameterList().getParameters(); - final Set deletedOrRenamedParameters = new HashSet(); - if (isOriginal) { - deletedOrRenamedParameters.addAll(Arrays.asList(parameters)); - for (ParameterInfo parameterInfo : myChangeInfo.getNewParameters()) { - if (parameterInfo.getOldIndex() >= 0) { - final PsiParameter parameter = parameters[parameterInfo.getOldIndex()]; - if (parameterInfo.getName().equals(parameter.getName())) { - deletedOrRenamedParameters.remove(parameter); - } + if (!StdLanguages.JAVA.equals(method.getLanguage())) return; + + final PsiParameter[] parameters = method.getParameterList().getParameters(); + final Set deletedOrRenamedParameters = new HashSet(); + if (isOriginal) { + deletedOrRenamedParameters.addAll(Arrays.asList(parameters)); + for (ParameterInfo parameterInfo : myChangeInfo.getNewParameters()) { + if (parameterInfo.getOldIndex() >= 0) { + final PsiParameter parameter = parameters[parameterInfo.getOldIndex()]; + if (parameterInfo.getName().equals(parameter.getName())) { + deletedOrRenamedParameters.remove(parameter); } } } + } - for (ParameterInfo parameterInfo : myChangeInfo.getNewParameters()) { - final int oldParameterIndex = parameterInfo.getOldIndex(); - final String newName = parameterInfo.getName(); - if (oldParameterIndex >= 0) { - if (isOriginal) { //Name changes take place only in primary method - final PsiParameter parameter = parameters[oldParameterIndex]; - if (!newName.equals(parameter.getName())) { - JavaUnresolvableLocalCollisionDetector.visitLocalsCollisions(parameter, newName, method.getBody(), null, - new JavaUnresolvableLocalCollisionDetector.CollidingVariableVisitor() { - public void visitCollidingElement(final PsiVariable collidingVariable) { - if (!deletedOrRenamedParameters - .contains(collidingVariable)) { - result.add( - new RenamedParameterCollidesWithLocalUsageInfo( - parameter, collidingVariable, method)); - } + for (ParameterInfo parameterInfo : myChangeInfo.getNewParameters()) { + final int oldParameterIndex = parameterInfo.getOldIndex(); + final String newName = parameterInfo.getName(); + if (oldParameterIndex >= 0) { + if (isOriginal) { //Name changes take place only in primary method + final PsiParameter parameter = parameters[oldParameterIndex]; + if (!newName.equals(parameter.getName())) { + JavaUnresolvableLocalCollisionDetector.visitLocalsCollisions(parameter, newName, method.getBody(), null, + new JavaUnresolvableLocalCollisionDetector.CollidingVariableVisitor() { + public void visitCollidingElement(final PsiVariable collidingVariable) { + if (!deletedOrRenamedParameters + .contains(collidingVariable)) { + result.add( + new RenamedParameterCollidesWithLocalUsageInfo( + parameter, collidingVariable, method)); } - }); - } + } + }); } } - else { - JavaUnresolvableLocalCollisionDetector.visitLocalsCollisions(method, newName, method.getBody(), null, - new JavaUnresolvableLocalCollisionDetector.CollidingVariableVisitor() { - public void visitCollidingElement(PsiVariable collidingVariable) { - if (!deletedOrRenamedParameters.contains(collidingVariable)) { - result.add(new NewParameterCollidesWithLocalUsageInfo( - collidingVariable, collidingVariable, method)); - } + } + else { + JavaUnresolvableLocalCollisionDetector.visitLocalsCollisions(method, newName, method.getBody(), null, + new JavaUnresolvableLocalCollisionDetector.CollidingVariableVisitor() { + public void visitCollidingElement(PsiVariable collidingVariable) { + if (!deletedOrRenamedParameters.contains(collidingVariable)) { + result.add(new NewParameterCollidesWithLocalUsageInfo( + collidingVariable, collidingVariable, method)); } - }); - } + } + }); } } } @@ -205,6 +205,9 @@ class UsageSearcher { PsiReference[] refs = MethodReferencesSearch.search(method, projectScope, true).toArray(PsiReference.EMPTY_ARRAY); for (PsiReference ref : refs) { PsiElement element = ref.getElement(); + + if (!StdLanguages.JAVA.equals(element.getLanguage())) continue; + boolean isToCatchExceptions = isToThrowExceptions && needToCatchExceptions(RefactoringUtil.getEnclosingMethod(element)); if (!isToCatchExceptions) { if (RefactoringUtil.isMethodUsage(element)) { @@ -278,7 +281,7 @@ class UsageSearcher { GlobalSearchScope projectScope = GlobalSearchScope.projectScope(manager.getProject()); for (PsiReference psiReference : ReferencesSearch.search(parameter, projectScope, false)) { PsiElement parmRef = psiReference.getElement(); - UsageInfo usageInfo = new JavaChangeSignatureUsageProcessor.MyParameterUsageInfo(parmRef, parameter.getName(), info.getName()); + UsageInfo usageInfo = new ChangeSignatureParameterUsageInfo(parmRef, parameter.getName(), info.getName()); results.add(usageInfo); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyPsiElementFactory.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyPsiElementFactory.java index 4b6c600d5a28..005a21100e03 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyPsiElementFactory.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyPsiElementFactory.java @@ -84,6 +84,8 @@ public abstract class GroovyPsiElementFactory { public abstract GrReferenceExpression createReferenceExpressionFromText(String exprText); + public abstract GrReferenceExpression createReferenceExpressionFromText(String idText, PsiElement context) ; + public abstract GrCodeReferenceElement createReferenceElementFromText(String refName); public abstract GrExpression createExpressionFromText(String exprText); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java index 2b7e14dd29f8..a0adb7c0d796 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java @@ -108,6 +108,12 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory { return (GrReferenceExpression) ((GroovyFileBase) file).getTopStatements()[0]; } + public GrReferenceExpression createReferenceExpressionFromText(String idText, PsiElement context) { + PsiFile file = createGroovyFile(idText, false, context); + return (GrReferenceExpression) ((GroovyFileBase) file).getTopStatements()[0]; + } + + public GrExpression createExpressionFromText(String text) { GroovyFileImpl file = (GroovyFileImpl) createGroovyFile(text); assert file.getTopStatements()[0] instanceof GrExpression; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChageSignatureUsageSearcher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChageSignatureUsageSearcher.java new file mode 100644 index 000000000000..860f000f17a7 --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChageSignatureUsageSearcher.java @@ -0,0 +1,309 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.groovy.refactoring.changeSignature; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.psi.*; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.search.searches.MethodReferencesSearch; +import com.intellij.psi.search.searches.OverridingMethodsSearch; +import com.intellij.psi.search.searches.ReferencesSearch; +import com.intellij.refactoring.RefactoringBundle; +import com.intellij.refactoring.changeSignature.*; +import com.intellij.refactoring.rename.UnresolvableCollisionUsageInfo; +import com.intellij.refactoring.util.MoveRenameUsageInfo; +import com.intellij.refactoring.util.RefactoringUIUtil; +import com.intellij.refactoring.util.RefactoringUtil; +import com.intellij.refactoring.util.usageInfo.DefaultConstructorImplicitUsageInfo; +import com.intellij.refactoring.util.usageInfo.NoConstructorClassUsageInfo; +import com.intellij.usageView.UsageInfo; +import com.intellij.usageView.UsageViewUtil; +import com.intellij.util.containers.HashSet; +import org.jetbrains.plugins.groovy.GroovyFileType; +import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocTagValueToken; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousClassDefinition; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; +import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Set; + +/** + * @author Maxim.Medvedev + */ +class GrChageSignatureUsageSearcher { + private final JavaChangeInfo myChangeInfo; + private static final Logger LOG = + Logger.getInstance("org.jetbrains.plugins.groovy.refactoring.changeSignature.GrChageSignatureUsageSearcher"); + + GrChageSignatureUsageSearcher(JavaChangeInfo changeInfo) { + this.myChangeInfo = changeInfo; + } + + public UsageInfo[] findUsages() { + ArrayList result = new ArrayList(); + final PsiElement element = myChangeInfo.getMethod(); + if (element instanceof PsiMethod) { + final PsiMethod method = (PsiMethod)element; + + findSimpleUsages(method, result); + + final UsageInfo[] usageInfos = result.toArray(new UsageInfo[result.size()]); + return UsageViewUtil.removeDuplicatedUsages(usageInfos); + } + return UsageInfo.EMPTY_ARRAY; + } + + + private void findSimpleUsages(final PsiMethod method, final ArrayList result) { + PsiMethod[] overridingMethods = findSimpleUsagesWithoutParameters(method, result, true, true, true); + //findUsagesInCallers(result); todo + + //Parameter name changes are not propagated + findParametersUsage(method, result, overridingMethods); + } + + /* todo + private void findUsagesInCallers(final ArrayList usages) { + if (myChangeInfo instanceof JavaChangeInfoImpl) { + JavaChangeInfoImpl changeInfo = (JavaChangeInfoImpl)myChangeInfo; + + for (PsiMethod caller : changeInfo.propagateParametersMethods) { + usages.add(new CallerUsageInfo(caller, true, changeInfo.propagateExceptionsMethods.contains(caller))); + } + for (PsiMethod caller : changeInfo.propagateExceptionsMethods) { + usages.add(new CallerUsageInfo(caller, changeInfo.propagateParametersMethods.contains(caller), true)); + } + Set merged = new HashSet(); + merged.addAll(changeInfo.propagateParametersMethods); + merged.addAll(changeInfo.propagateExceptionsMethods); + for (final PsiMethod method : merged) { + findSimpleUsagesWithoutParameters(method, usages, changeInfo.propagateParametersMethods.contains(method), + changeInfo.propagateExceptionsMethods.contains(method), false); + } + } + } + */ + + private void detectLocalsCollisionsInMethod(final GrMethod method, final ArrayList result, boolean isOriginal) { + if (!GroovyFileType.GROOVY_LANGUAGE.equals(method.getLanguage())) return; + + final PsiParameter[] parameters = method.getParameterList().getParameters(); + final Set deletedOrRenamedParameters = new HashSet(); + if (isOriginal) { + deletedOrRenamedParameters.addAll(Arrays.asList(parameters)); + for (ParameterInfo parameterInfo : myChangeInfo.getNewParameters()) { + if (parameterInfo.getOldIndex() >= 0) { + final PsiParameter parameter = parameters[parameterInfo.getOldIndex()]; + if (parameterInfo.getName().equals(parameter.getName())) { + deletedOrRenamedParameters.remove(parameter); + } + } + } + } + + for (ParameterInfo parameterInfo : myChangeInfo.getNewParameters()) { + final int oldParameterIndex = parameterInfo.getOldIndex(); + final String newName = parameterInfo.getName(); + if (oldParameterIndex >= 0) { + if (isOriginal) { //Name changes take place only in primary method + final PsiParameter parameter = parameters[oldParameterIndex]; + if (!newName.equals(parameter.getName())) { + final GrUnresolvableLocalCollisionDetector.CollidingVariableVisitor collidingVariableVisitor = + new GrUnresolvableLocalCollisionDetector.CollidingVariableVisitor() { + public void visitCollidingVariable(final PsiVariable collidingVariable) { + if (!deletedOrRenamedParameters.contains(collidingVariable)) { + result.add(new RenamedParameterCollidesWithLocalUsageInfo(parameter, collidingVariable, method)); + } + } + }; + GrUnresolvableLocalCollisionDetector.visitLocalsCollisions(parameter, newName, method.getBlock(), collidingVariableVisitor); + } + } + } + else { + final GrUnresolvableLocalCollisionDetector.CollidingVariableVisitor variableVisitor = + new GrUnresolvableLocalCollisionDetector.CollidingVariableVisitor() { + public void visitCollidingVariable(PsiVariable collidingVariable) { + if (!deletedOrRenamedParameters.contains(collidingVariable)) { + result.add(new NewParameterCollidesWithLocalUsageInfo(collidingVariable, collidingVariable, method)); + } + } + }; + GrUnresolvableLocalCollisionDetector.visitLocalsCollisions(method, newName, method.getBlock(), variableVisitor); + } + } + } + + private void findParametersUsage(final PsiMethod method, ArrayList result, PsiMethod[] overriders) { + if (!GroovyFileType.GROOVY_LANGUAGE.equals(method.getLanguage())) return; + + PsiParameter[] parameters = method.getParameterList().getParameters(); + for (ParameterInfo info : myChangeInfo.getNewParameters()) { + if (info.getOldIndex() >= 0) { + PsiParameter parameter = parameters[info.getOldIndex()]; + if (!info.getName().equals(parameter.getName())) { + addParameterUsages(parameter, result, info); + + for (PsiMethod overrider : overriders) { + if (!GroovyFileType.GROOVY_LANGUAGE.equals(overrider.getLanguage())) continue; + PsiParameter parameter1 = overrider.getParameterList().getParameters()[info.getOldIndex()]; + if (parameter.getName().equals(parameter1.getName())) { + addParameterUsages(parameter1, result, info); + } + } + } + } + } + } + + private PsiMethod[] findSimpleUsagesWithoutParameters(final PsiMethod method, + final ArrayList result, + boolean isToModifyArgs, + boolean isToThrowExceptions, + boolean isOriginal) { + + GlobalSearchScope projectScope = GlobalSearchScope.projectScope(method.getProject()); + PsiMethod[] overridingMethods = OverridingMethodsSearch.search(method, method.getUseScope(), true).toArray(PsiMethod.EMPTY_ARRAY); + + for (PsiMethod overridingMethod : overridingMethods) { + if (GroovyFileType.GROOVY_LANGUAGE.equals(overridingMethod.getLanguage())) { + result.add(new OverriderUsageInfo(overridingMethod, method, isOriginal, isToModifyArgs, isToThrowExceptions)); + } + } + + boolean needToChangeCalls = + !myChangeInfo.isGenerateDelegate() && (myChangeInfo.isNameChanged() || + myChangeInfo.isParameterSetOrOrderChanged() || + myChangeInfo.isExceptionSetOrOrderChanged() || + myChangeInfo.isVisibilityChanged()/*for checking inaccessible*/); + if (needToChangeCalls) { + PsiReference[] refs = MethodReferencesSearch.search(method, projectScope, true).toArray(PsiReference.EMPTY_ARRAY); + for (PsiReference ref : refs) { + PsiElement element = ref.getElement(); + + if (!GroovyFileType.GROOVY_LANGUAGE.equals(element.getLanguage())) continue; + + boolean isToCatchExceptions = isToThrowExceptions && needToCatchExceptions(RefactoringUtil.getEnclosingMethod(element)); + //todo check for applicability of arguments to method + if (isMethodUsage(element)) { + result.add(new GrMethodCallUsageInfo(element, isToModifyArgs, isToCatchExceptions)); + } + else if (element instanceof GrDocTagValueToken) { + result.add(new UsageInfo(ref.getElement())); + } + else if (element instanceof GrMethod && ((GrMethod)element).isConstructor()) { + DefaultConstructorImplicitUsageInfo implicitUsageInfo = + new DefaultConstructorImplicitUsageInfo((GrMethod)element, ((GrMethod)element).getContainingClass(), method); + result.add(implicitUsageInfo); + } + else if (element instanceof PsiClass) { + LOG.assertTrue(method.isConstructor()); + final PsiClass psiClass = (PsiClass)element; + /*if (!(myChangeInfo instanceof JavaChangeInfoImpl)) continue; todo propagate methods + if (shouldPropagateToNonPhysicalMethod(method, result, psiClass, + ((JavaChangeInfoImpl)myChangeInfo).propagateParametersMethods)) { + continue; + } + if (shouldPropagateToNonPhysicalMethod(method, result, psiClass, + ((JavaChangeInfoImpl)myChangeInfo).propagateExceptionsMethods)) { + continue; + }*/ + result.add(new NoConstructorClassUsageInfo(psiClass)); + } + else if (ref instanceof PsiCallReference) { + result.add(new CallReferenceUsageInfo((PsiCallReference)ref)); + } + else { + result.add(new MoveRenameUsageInfo(element, ref, method)); + } + } + } + else if (myChangeInfo.isParameterTypesChanged()) { + PsiReference[] refs = MethodReferencesSearch.search(method, projectScope, true).toArray(PsiReference.EMPTY_ARRAY); + for (PsiReference reference : refs) { + final PsiElement element = reference.getElement(); + if (element instanceof GrDocTagValueToken) { + result.add(new UsageInfo(reference)); + } + } + } + + // Conflicts + if (method instanceof GrMethod) { + detectLocalsCollisionsInMethod((GrMethod)method, result, isOriginal); + } + for (final PsiMethod overridingMethod : overridingMethods) { + if (overridingMethod instanceof GrMethod) { + detectLocalsCollisionsInMethod((GrMethod)overridingMethod, result, isOriginal); + } + } + + return overridingMethods; + } + + private static void addParameterUsages(PsiParameter parameter, ArrayList results, ParameterInfo info) { + PsiManager manager = parameter.getManager(); + GlobalSearchScope projectScope = GlobalSearchScope.projectScope(manager.getProject()); + for (PsiReference psiReference : ReferencesSearch.search(parameter, projectScope, false)) { + PsiElement parmRef = psiReference.getElement(); + UsageInfo usageInfo = new ChangeSignatureParameterUsageInfo(parmRef, parameter.getName(), info.getName()); + results.add(usageInfo); + } + } + + private boolean needToCatchExceptions(PsiMethod caller) { + /*if (myChangeInfo instanceof JavaChangeInfoImpl) { //todo propagate methods + return myChangeInfo.isExceptionSetOrOrderChanged() && + !((JavaChangeInfoImpl)myChangeInfo).propagateExceptionsMethods.contains(caller); + } + else {*/ + return myChangeInfo.isExceptionSetOrOrderChanged(); + } + + private static class RenamedParameterCollidesWithLocalUsageInfo extends UnresolvableCollisionUsageInfo { + private final PsiElement myCollidingElement; + private final PsiMethod myMethod; + + public RenamedParameterCollidesWithLocalUsageInfo(PsiParameter parameter, PsiElement collidingElement, PsiMethod method) { + super(parameter, collidingElement); + myCollidingElement = collidingElement; + myMethod = method; + } + + public String getDescription() { + return RefactoringBundle.message("there.is.already.a.0.in.the.1.it.will.conflict.with.the.renamed.parameter", + RefactoringUIUtil.getDescription(myCollidingElement, true), + RefactoringUIUtil.getDescription(myMethod, true)); + } + } + + static boolean isMethodUsage(PsiElement element) { + if (element instanceof GrEnumConstant) return true; + if (!(element instanceof GrCodeReferenceElement)) return false; + PsiElement parent = element.getParent(); + if (parent instanceof GrCall) { + return true; + } + else if (parent instanceof GrAnonymousClassDefinition) { + return element.equals(((GrAnonymousClassDefinition)parent).getBaseClassReferenceGroovy()); + } + return false; + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java index c49871851d44..63642ebfd6c0 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java @@ -16,12 +16,10 @@ package org.jetbrains.plugins.groovy.refactoring.changeSignature; import com.intellij.lang.Language; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Ref; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiIdentifier; -import com.intellij.psi.PsiMethod; -import com.intellij.psi.PsiReference; +import com.intellij.psi.*; import com.intellij.psi.search.searches.MethodReferencesSearch; import com.intellij.refactoring.BaseRefactoringProcessor; import com.intellij.refactoring.changeSignature.ChangeSignatureViewDescriptor; @@ -42,24 +40,25 @@ import java.util.List; * @author Maxim.Medvedev */ public class GrChangeSignatureProcessor extends BaseRefactoringProcessor { - private final GrChangeInfoImpl myInfo; + public static final Logger LOG = Logger.getInstance("#org.jetbrains.plugins.groovy.refactoring.changeSignature.GrChangeSignatureProcessor"); + private final GrChangeInfoImpl myChangeInfo; //private public GrChangeSignatureProcessor(Project project, GrChangeInfoImpl changeInfo) { super(project); - myInfo = changeInfo; + myChangeInfo = changeInfo; } @Override protected UsageViewDescriptor createUsageViewDescriptor(UsageInfo[] usages) { - return new ChangeSignatureViewDescriptor(myInfo.getMethod()); + return new ChangeSignatureViewDescriptor(myChangeInfo.getMethod()); } @NotNull @Override protected UsageInfo[] findUsages() { - final PsiReference[] refs = MethodReferencesSearch.search(myInfo.getMethod()).toArray(PsiReference.EMPTY_ARRAY); + final PsiReference[] refs = MethodReferencesSearch.search(myChangeInfo.getMethod()).toArray(PsiReference.EMPTY_ARRAY); for (PsiReference ref : refs) { } @@ -69,7 +68,9 @@ public class GrChangeSignatureProcessor extends BaseRefactoringProcessor { @Override protected void refreshElements(PsiElement[] elements) { - //To change body of implemented methods use File | Settings | File Templates. + boolean condition = elements.length == 1 && elements[0] instanceof PsiMethod; + LOG.assertTrue(condition); + myChangeInfo.updateMethod((PsiMethod) elements[0]); } @Override @@ -78,20 +79,20 @@ public class GrChangeSignatureProcessor extends BaseRefactoringProcessor { } private void changeMethod() { - final PsiMethod method = myInfo.getMethod(); - if (myInfo.isChangeName()) { - method.setName(myInfo.getNewName()); + final PsiMethod method = myChangeInfo.getMethod(); + if (myChangeInfo.isChangeName()) { + method.setName(myChangeInfo.getNewName()); } - if (myInfo.isChangeVisibility()) { - method.getModifierList().setModifierProperty(myInfo.getVisibilityModifier(), true); + if (myChangeInfo.isChangeVisibility()) { + method.getModifierList().setModifierProperty(myChangeInfo.getVisibilityModifier(), true); } } @Override protected String getCommandName() { return ""; - //return RefactoringBundle.message("changing.signature.of.0", UsageViewUtil.getDescriptiveName(myInfo.getMethod())); + //return RefactoringBundle.message("changing.signature.of.0", UsageViewUtil.getDescriptiveName(myChangeInfo.getMethod())); } @@ -105,7 +106,7 @@ public class GrChangeSignatureProcessor extends BaseRefactoringProcessor { } static class GrChangeInfoImpl implements JavaChangeInfo { - final GrMethod method; + GrMethod method; final String newName; final CanonicalTypes.Type returnType; final String visibilityModifier; @@ -250,5 +251,15 @@ public class GrChangeSignatureProcessor extends BaseRefactoringProcessor { public boolean[] toRemoveParm() { return new boolean[0]; //To change body of implemented methods use File | Settings | File Templates. } + + public PsiExpression getValue(int i, PsiCallExpression callExpression) { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + public void updateMethod(PsiMethod psiMethod) { + if (psiMethod instanceof GrMethod) { + method = (GrMethod)psiMethod; + } + } } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java new file mode 100644 index 000000000000..387cd3c97aaa --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.groovy.refactoring.changeSignature; + +import com.intellij.openapi.util.Ref; +import com.intellij.psi.PsiElement; +import com.intellij.refactoring.changeSignature.ChangeInfo; +import com.intellij.refactoring.changeSignature.ChangeSignatureUsageProcessor; +import com.intellij.refactoring.changeSignature.JavaChangeInfo; +import com.intellij.usageView.UsageInfo; +import com.intellij.util.containers.MultiMap; + +/** + * @author Maxim.Medvedev + */ +public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProcessor { + public UsageInfo[] findUsages(ChangeInfo info) { + if (info instanceof JavaChangeInfo) { + return new GrChageSignatureUsageSearcher((JavaChangeInfo)info).findUsages(); + } + return UsageInfo.EMPTY_ARRAY; + } + + public MultiMap findConflicts(ChangeInfo info, Ref refUsages) { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean processUsage(ChangeInfo changeInfo, UsageInfo usageInfo, boolean beforeMethodChange, UsageInfo[] usages) { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean processPrimaryMethod(ChangeInfo changeInfo) { + return false; //To change body of implemented methods use File | Settings | File Templates. + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodCallUsageInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodCallUsageInfo.java new file mode 100644 index 000000000000..084ed8209197 --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodCallUsageInfo.java @@ -0,0 +1,81 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.groovy.refactoring.changeSignature; + +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiMethod; +import com.intellij.psi.PsiNewExpression; +import com.intellij.usageView.UsageInfo; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrConstructorInvocation; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrApplicationStatement; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrCallExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant; + +/** + * @author Maxim.Medvedev + */ +public class GrMethodCallUsageInfo extends UsageInfo { + private final boolean myToChangeArguments; + private final boolean myToCatchExceptions; + private final PsiMethod myReferencedMethod; + + public boolean isToCatchExceptions() { + return myToCatchExceptions; + } + + public boolean isToChangeArguments() { + return myToChangeArguments; + } + + public GrMethodCallUsageInfo(PsiElement element, boolean isToChangeArguments, boolean isToCatchExceptions) { + super(element); + myToChangeArguments = isToChangeArguments; + myToCatchExceptions = isToCatchExceptions; + myReferencedMethod = resolveMethod(element); + } + + @Nullable + private static PsiMethod resolveMethod(final PsiElement ref) { + if (ref instanceof GrEnumConstant) return ((GrEnumConstant)ref).resolveConstructor(); + PsiElement parent = ref.getParent(); + if (parent instanceof GrCallExpression) { + return ((GrCallExpression)parent).resolveMethod(); + } + else if (parent instanceof GrApplicationStatement) { + final GrExpression expression = ((GrApplicationStatement)parent).getFunExpression(); + if (expression instanceof GrReferenceExpression) { + final PsiElement element = ((GrReferenceExpression)expression).resolve(); + if (element instanceof PsiMethod) { + return (PsiMethod)element; + } + } + } + else if (parent instanceof GrConstructorInvocation) { + return ((PsiNewExpression)parent.getParent()).resolveConstructor(); + } + + return null; + } + + public PsiMethod getReferencedMethod() { + return myReferencedMethod; + } + + +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrUnresolvableLocalCollisionDetector.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrUnresolvableLocalCollisionDetector.java new file mode 100644 index 000000000000..9d0a1ec23b14 --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrUnresolvableLocalCollisionDetector.java @@ -0,0 +1,105 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.groovy.refactoring.changeSignature; + +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiMethod; +import com.intellij.psi.PsiVariable; +import com.intellij.psi.util.PsiTreeUtil; +import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; +import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; +import org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor; +import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; + +/** + * @author Maxim.Medvedev + */ +public class GrUnresolvableLocalCollisionDetector { + private GrUnresolvableLocalCollisionDetector() { + } + + public static void visitLocalsCollisions(PsiElement element, + final String newName, + GroovyPsiElement place, + final CollidingVariableVisitor visitor) { + visitDownstreamCollisions(newName, place, visitor); + visitUpstreamCollisions(element, newName, place, visitor); + } + + private static void visitUpstreamCollisions(PsiElement element, + String newName, + GroovyPsiElement place, + CollidingVariableVisitor visitor) { + final GrReferenceExpression refExpr = + GroovyPsiElementFactory.getInstance(place.getProject()).createReferenceExpressionFromText(newName, place); + final GroovyResolveResult[] results = refExpr.multiResolve(false); + for (GroovyResolveResult result : results) { + final PsiElement resolved = result.getElement(); + if (resolved instanceof GrParameter || (resolved instanceof GrVariable && !(resolved instanceof GrField))) { + final PsiElement parent = PsiTreeUtil.findCommonParent(resolved, element); + if (parent != null) { + PsiElement current = element; + while (current != null && current != parent) { + if (current instanceof PsiMethod || current instanceof PsiClass || current instanceof GrClosableBlock) { + return; + } + current = current.getParent(); + } + } + + if (!place.getManager().areElementsEquivalent(element, resolved)) { + visitor.visitCollidingVariable((PsiVariable)resolved); + } + } + } + } + + private static void visitDownstreamCollisions(final String newName, GroovyPsiElement place, final CollidingVariableVisitor visitor) { + place.accept(new GroovyRecursiveElementVisitor() { + @Override + public void visitVariableDeclaration(GrVariableDeclaration variableDeclaration) { + final GrVariable[] variables = variableDeclaration.getVariables(); + for (GrVariable variable : variables) { + if (variable.getName().equals(newName)) { + visitor.visitCollidingVariable(variable); + } + } + } + + @Override + public void visitMethod(GrMethod method) {} + + @Override + public void visitClosure(GrClosableBlock closure) {} + + @Override + public void visitTypeDefinition(GrTypeDefinition typeDefinition) {} + }); + } + + interface CollidingVariableVisitor { + void visitCollidingVariable(PsiVariable variable); + } +} From 80e4f489d128c9ee4860119134d73a242cb64607 Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Thu, 22 Apr 2010 14:15:33 +0400 Subject: [PATCH 008/212] GrChangeInfo --- .../JavaChangeSignatureUsageProcessor.java | 2 +- ... => JavaChangeSignatureUsageSearcher.java} | 12 +- .../changeSignature/JavaParameterInfo.java | 2 + .../changeSignature/GrChangeInfoImpl.java | 278 ++++++++++++++++++ .../GrChangeSignatureDialog.java | 8 +- .../GrChangeSignatureProcessor.java | 171 +---------- .../changeSignature/GrParameterInfo.java | 4 + 7 files changed, 297 insertions(+), 180 deletions(-) rename java/java-impl/src/com/intellij/refactoring/changeSignature/{UsageSearcher.java => JavaChangeSignatureUsageSearcher.java} (98%) create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeInfoImpl.java diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java index 2136a0f7c5f3..d8a3ae5ffa3a 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java @@ -54,7 +54,7 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr public UsageInfo[] findUsages(ChangeInfo info) { if (info instanceof JavaChangeInfo) { - return new UsageSearcher((JavaChangeInfo)info).findUsages(); + return new JavaChangeSignatureUsageSearcher((JavaChangeInfo)info).findUsages(); } else { return UsageInfo.EMPTY_ARRAY; diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/UsageSearcher.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageSearcher.java similarity index 98% rename from java/java-impl/src/com/intellij/refactoring/changeSignature/UsageSearcher.java rename to java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageSearcher.java index 4902403dad1f..29fb2cba1594 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/UsageSearcher.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageSearcher.java @@ -44,11 +44,11 @@ import java.util.Set; /** * @author Maxim.Medvedev */ -class UsageSearcher { +class JavaChangeSignatureUsageSearcher { private final JavaChangeInfo myChangeInfo; - private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.changeSignature.UsageSearcher"); + private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.changeSignature.JavaChangeSignatureUsageSearcher"); - UsageSearcher(JavaChangeInfo changeInfo) { + JavaChangeSignatureUsageSearcher(JavaChangeInfo changeInfo) { this.myChangeInfo = changeInfo; } @@ -97,7 +97,7 @@ class UsageSearcher { private void detectLocalsCollisionsInMethod(final PsiMethod method, final ArrayList result, boolean isOriginal) { if (!StdLanguages.JAVA.equals(method.getLanguage())) return; - + final PsiParameter[] parameters = method.getParameterList().getParameters(); final Set deletedOrRenamedParameters = new HashSet(); if (isOriginal) { @@ -206,8 +206,6 @@ class UsageSearcher { for (PsiReference ref : refs) { PsiElement element = ref.getElement(); - if (!StdLanguages.JAVA.equals(element.getLanguage())) continue; - boolean isToCatchExceptions = isToThrowExceptions && needToCatchExceptions(RefactoringUtil.getEnclosingMethod(element)); if (!isToCatchExceptions) { if (RefactoringUtil.isMethodUsage(element)) { @@ -219,7 +217,7 @@ class UsageSearcher { result.add(new MethodCallUsageInfo(element, isToModifyArgs, isToCatchExceptions)); } else if (element instanceof PsiDocTagValue) { - result.add(new UsageInfo(ref.getElement())); + result.add(new UsageInfo(element)); } else if (element instanceof PsiMethod && ((PsiMethod)element).isConstructor()) { DefaultConstructorImplicitUsageInfo implicitUsageInfo = diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaParameterInfo.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaParameterInfo.java index e341c6d4d108..d03bd999c3a5 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaParameterInfo.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaParameterInfo.java @@ -32,4 +32,6 @@ public interface JavaParameterInfo extends ParameterInfo { CanonicalTypes.Type getTypeWrapper(); PsiExpression getValue(PsiCallExpression callExpression); + + boolean isVarargType(); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeInfoImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeInfoImpl.java new file mode 100644 index 000000000000..02a6264a7f66 --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeInfoImpl.java @@ -0,0 +1,278 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.groovy.refactoring.changeSignature; + +import com.intellij.lang.Language; +import com.intellij.psi.*; +import com.intellij.refactoring.changeSignature.JavaChangeInfo; +import com.intellij.refactoring.changeSignature.JavaParameterInfo; +import com.intellij.refactoring.changeSignature.ThrownExceptionInfo; +import com.intellij.refactoring.util.CanonicalTypes; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.groovy.GroovyFileType; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; + +import java.util.List; + +/** + * @author Maxim.Medvedev + */ +class GrChangeInfoImpl implements JavaChangeInfo { + GrMethod method; + final String newName; + final CanonicalTypes.Type returnType; + final String visibilityModifier; + final List parameters; + boolean changeParameters = false; + private boolean myIsParameterTypesChanged = false; + private boolean myIsParameterNamesChanged = false; + private boolean myIsNameChanged = false; + private boolean myIsVisibilityChanged = false; + private boolean myIsReturnTypeChanged = false; + private boolean myIsRetainVarargs; + private boolean myIsArrayToVarargs; + private boolean myIsObtainVarargs; + private boolean myWasVarargs; + private String myOldName; + private PsiIdentifier myNewNameIdentifier; + private PsiExpression[] defaultValues; + + public GrChangeInfoImpl(GrMethod method, + String visibilityModifier, + CanonicalTypes.Type returnType, + String newName, + List parameters) { + this.method = method; + this.visibilityModifier = visibilityModifier; + this.returnType = returnType; + this.parameters = parameters; + this.newName = newName; + myOldName = method.getName(); + + if (!method.getName().equals(newName)) { + myIsNameChanged = true; + } + + myIsVisibilityChanged = !method.hasModifierProperty(visibilityModifier); + + if (!method.isConstructor()) { + PsiType oldReturnType = method.getReturnType(); + try { + PsiType newReturnType = returnType.getType(method, getMethod().getManager()); + if ((oldReturnType == null && newReturnType != null) || (oldReturnType != null && !oldReturnType.equals(newReturnType))) { + myIsReturnTypeChanged = true; + } + } + catch (IncorrectOperationException e) { + myIsReturnTypeChanged = true; + } + } + + GrParameter[] params = method.getParameters(); + final int oldParameterCount = this.method.getParameters().length; + if (oldParameterCount != this.parameters.size()) { + changeParameters = true; + } + else { + for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) { + GrParameterInfo parameter = parameters.get(i); + if (parameter.getOldIndex() != i) { + changeParameters = true; + break; + } + if (!params[i].getName().equals(parameter.getName())) { + myIsParameterNamesChanged = true; + } + try { + PsiType type = parameter.createType(method, method.getManager()); + PsiType oldType = params[i].getType(); + if (!oldType.equals(type)) { + myIsParameterTypesChanged = true; + } + } + catch (IncorrectOperationException e) { + myIsParameterTypesChanged = true; + } + } + } + + myWasVarargs = method.isVarArgs(); + if (parameters.size()==0) { + myIsObtainVarargs=false; + myIsRetainVarargs=false; + myIsArrayToVarargs=false; + } else { + GrParameterInfo lastNewParam = parameters.get(parameters.size() - 1); + myIsObtainVarargs= lastNewParam.isVarargType(); + myIsRetainVarargs = lastNewParam.getOldIndex() >= 0 && myIsObtainVarargs; + if (myIsRetainVarargs) { + final PsiType oldTypeForVararg = params[lastNewParam.getOldIndex()].getType(); + myIsArrayToVarargs = (oldTypeForVararg instanceof PsiArrayType && !(oldTypeForVararg instanceof PsiEllipsisType)); + } + else { + myIsArrayToVarargs = false; + } + } + + if (myIsNameChanged) { + myNewNameIdentifier = JavaPsiFacade.getElementFactory(getMethod().getProject()).createIdentifier(newName); + } + + PsiElementFactory factory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory(); + defaultValues = new PsiExpression[parameters.size()]; + for(int i = 0; i < parameters.size(); i++){ + JavaParameterInfo info = parameters.get(i); + if (info.getOldIndex() < 0 && !info.isVarargType()){ + if (info.getDefaultValue() == null) continue; + try{ + defaultValues[i] = factory.createExpressionFromText(info.getDefaultValue(), method); + } + catch(IncorrectOperationException e){ +// LOG.error(e); + } + } + } + } + + @NotNull + public JavaParameterInfo[] getNewParameters() { + return parameters.toArray(new GrParameterInfo[parameters.size()]); + } + + @Modifier + public String getNewVisibility() { + return visibilityModifier; + } + + public boolean isParameterSetOrOrderChanged() { + return changeParameters; + } + + public boolean isParameterTypesChanged() { + return myIsParameterTypesChanged; + } + + public boolean isParameterNamesChanged() { + return myIsParameterNamesChanged; + } + + public boolean isGenerateDelegate() { + return false; + } + + public boolean isNameChanged() { + return myIsNameChanged; + } + + public boolean isVisibilityChanged() { + return myIsVisibilityChanged; + } + + public boolean isExceptionSetChanged() { + return false; + } + + public boolean isExceptionSetOrOrderChanged() { + return false; + } + + public PsiMethod getMethod() { + return method; + } + + public boolean isReturnTypeChanged() { + return myIsReturnTypeChanged; + } + + public CanonicalTypes.Type getNewReturnType() { + return returnType; + } + + public boolean isChangeVisibility() { + return !method.getModifierList().hasModifierProperty(visibilityModifier); + } + + public boolean isChangeName() { + return !method.getName().equals(newName); + } + + public String getNewName() { + return newName; + } + + public Language getLanguage() { + return GroovyFileType.GROOVY_LANGUAGE; + } + + public String getVisibilityModifier() { + return visibilityModifier; + } + + @NotNull + public String[] getOldParameterNames() { + return new String[0]; //To change body of implemented methods use File | Settings | File Templates. + } + + @NotNull + public String[] getOldParameterTypes() { + return new String[0]; //To change body of implemented methods use File | Settings | File Templates. + } + + public ThrownExceptionInfo[] getNewExceptions() { + return new ThrownExceptionInfo[0]; //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean isRetainsVarargs() { + return myIsRetainVarargs; + } + + public boolean isObtainsVarags() { + return myIsObtainVarargs; + } + + public boolean isArrayToVarargs() { + return myIsArrayToVarargs; + } + + public PsiIdentifier getNewNameIdentifier() { + return myNewNameIdentifier; + } + + public String getOldName() { + return myOldName; + } + + public boolean wasVararg() { + return myWasVarargs; + } + + public boolean[] toRemoveParm() { + return new boolean[0]; //To change body of implemented methods use File | Settings | File Templates. + } + + public PsiExpression getValue(int i, PsiCallExpression callExpression) { + if (defaultValues[i] != null) return defaultValues[i]; + return parameters.get(i).getValue(callExpression); + } + + public void updateMethod(PsiMethod psiMethod) { + if (psiMethod instanceof GrMethod) { + method = (GrMethod)psiMethod; + } + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java index 220d82b3140a..f2c56e828ff9 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java @@ -269,10 +269,10 @@ public class GrChangeSignatureDialog extends RefactoringDialog { String newName = getNewName(); final List parameterInfos = myParameterModel.getParameterInfos(); - invokeRefactoring(new GrChangeSignatureProcessor(myProject, new GrChangeSignatureProcessor.GrChangeInfoImpl(myMethod, modifier, - CanonicalTypes.createTypeWrapper( - returnType), newName, - parameterInfos))); + invokeRefactoring(new GrChangeSignatureProcessor(myProject, new GrChangeInfoImpl(myMethod, modifier, + CanonicalTypes.createTypeWrapper( + returnType), newName, + parameterInfos))); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java index 63642ebfd6c0..f10e1a342efb 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java @@ -15,26 +15,19 @@ */ package org.jetbrains.plugins.groovy.refactoring.changeSignature; -import com.intellij.lang.Language; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Ref; -import com.intellij.psi.*; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiMethod; +import com.intellij.psi.PsiReference; import com.intellij.psi.search.searches.MethodReferencesSearch; import com.intellij.refactoring.BaseRefactoringProcessor; import com.intellij.refactoring.changeSignature.ChangeSignatureViewDescriptor; -import com.intellij.refactoring.changeSignature.JavaChangeInfo; -import com.intellij.refactoring.changeSignature.JavaParameterInfo; -import com.intellij.refactoring.changeSignature.ThrownExceptionInfo; -import com.intellij.refactoring.util.CanonicalTypes; import com.intellij.usageView.UsageInfo; import com.intellij.usageView.UsageViewDescriptor; import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.groovy.GroovyFileType; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; - -import java.util.List; /** * @author Maxim.Medvedev @@ -104,162 +97,4 @@ public class GrChangeSignatureProcessor extends BaseRefactoringProcessor { protected boolean preprocessUsages(Ref refUsages) { return showConflicts(findConflicts(refUsages)); } - - static class GrChangeInfoImpl implements JavaChangeInfo { - GrMethod method; - final String newName; - final CanonicalTypes.Type returnType; - final String visibilityModifier; - final List parameters; - boolean changeParameters = false; - - public GrChangeInfoImpl(GrMethod method, - String visibilityModifier, - CanonicalTypes.Type returnType, - String newName, - List parameters) { - this.method = method; - this.visibilityModifier = visibilityModifier; - this.returnType = returnType; - this.parameters = parameters; - this.newName = newName; - - final int oldParameterCount = this.method.getParameters().length; - if (oldParameterCount != this.parameters.size()) { - changeParameters = true; - } - - for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) { - GrParameterInfo parameter = parameters.get(i); - if (parameter.getOldIndex() != i) { - changeParameters = true; - } - } - } - - @NotNull - public JavaParameterInfo[] getNewParameters() { - return parameters.toArray(new GrParameterInfo[parameters.size()]); - } - - public String getNewVisibility() { - return null;//todo - } - - public boolean isParameterSetOrOrderChanged() { - return changeParameters; - } - - public boolean isParameterTypesChanged() { - return false; //To change body of implemented methods use File | Settings | File Templates. - } - - public boolean isParameterNamesChanged() { - return false; //To change body of implemented methods use File | Settings | File Templates. - } - - public boolean isGenerateDelegate() { - return false; //To change body of implemented methods use File | Settings | File Templates. - } - - public boolean isNameChanged() { - return false; //To change body of implemented methods use File | Settings | File Templates. - } - - public boolean isVisibilityChanged() { - return false; //To change body of implemented methods use File | Settings | File Templates. - } - - public boolean isExceptionSetChanged() { - return false; //To change body of implemented methods use File | Settings | File Templates. - } - - public boolean isExceptionSetOrOrderChanged() { - return false; //To change body of implemented methods use File | Settings | File Templates. - } - - public PsiMethod getMethod() { - return method; - } - - public boolean isReturnTypeChanged() { - return false; //To change body of implemented methods use File | Settings | File Templates. - } - - public CanonicalTypes.Type getNewReturnType() { - return returnType; - } - - public boolean isChangeVisibility() { - return !method.getModifierList().hasModifierProperty(visibilityModifier); - } - - public boolean isChangeName() { - return !method.getName().equals(newName); - } - - public String getNewName() { - return newName; - } - - public Language getLanguage() { - return GroovyFileType.GROOVY_LANGUAGE; - } - - public String getVisibilityModifier() { - return visibilityModifier; - } - - @NotNull - public String[] getOldParameterNames() { - return new String[0]; //To change body of implemented methods use File | Settings | File Templates. - } - - @NotNull - public String[] getOldParameterTypes() { - return new String[0]; //To change body of implemented methods use File | Settings | File Templates. - } - - public ThrownExceptionInfo[] getNewExceptions() { - return new ThrownExceptionInfo[0]; //To change body of implemented methods use File | Settings | File Templates. - } - - public boolean isRetainsVarargs() { - return false; //To change body of implemented methods use File | Settings | File Templates. - } - - public boolean isObtainsVarags() { - return false; //To change body of implemented methods use File | Settings | File Templates. - } - - public boolean isArrayToVarargs() { - return false; //To change body of implemented methods use File | Settings | File Templates. - } - - public PsiIdentifier getNewNameIdentifier() { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - - public String getOldName() { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - - public boolean wasVararg() { - return false; //To change body of implemented methods use File | Settings | File Templates. - } - - public boolean[] toRemoveParm() { - return new boolean[0]; //To change body of implemented methods use File | Settings | File Templates. - } - - public PsiExpression getValue(int i, PsiCallExpression callExpression) { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - - public void updateMethod(PsiMethod psiMethod) { - if (psiMethod instanceof GrMethod) { - method = (GrMethod)psiMethod; - } - } - } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java index e0703e325c4f..be14f96539fe 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java @@ -117,4 +117,8 @@ public class GrParameterInfo implements JavaParameterInfo { public PsiExpression getValue(PsiCallExpression callExpression) { return null; //To change body of implemented methods use File | Settings | File Templates. } + + public boolean isVarargType() { + return getTypeText().endsWith("..."); + } } From 7ee374a0661ff9715d0335dad7dfd7cf343fab6e Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Thu, 22 Apr 2010 16:38:34 +0400 Subject: [PATCH 009/212] grChangeSignatureConflictSearcher --- .../GrChangeSignatureConflictSearcher.java | 162 ++++++++++++++++++ .../GrChangeSignatureUsageProcessor.java | 7 +- 2 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureConflictSearcher.java diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureConflictSearcher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureConflictSearcher.java new file mode 100644 index 000000000000..9ff813bd6336 --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureConflictSearcher.java @@ -0,0 +1,162 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.groovy.refactoring.changeSignature; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.Ref; +import com.intellij.psi.*; +import com.intellij.refactoring.RefactoringBundle; +import com.intellij.refactoring.changeSignature.JavaChangeInfo; +import com.intellij.refactoring.changeSignature.JavaParameterInfo; +import com.intellij.refactoring.rename.RenameUtil; +import com.intellij.refactoring.util.CanonicalTypes; +import com.intellij.refactoring.util.ConflictsUtil; +import com.intellij.refactoring.util.RefactoringUIUtil; +import com.intellij.usageView.UsageInfo; +import com.intellij.util.ArrayUtil; +import com.intellij.util.IncorrectOperationException; +import com.intellij.util.VisibilityUtil; +import com.intellij.util.containers.HashSet; +import com.intellij.util.containers.MultiMap; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.GroovyFileType; +import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; +import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrConstructorInvocation; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; + +import java.util.Arrays; +import java.util.Iterator; +import java.util.Set; + +/** +* @author Maxim.Medvedev +*/ +class GrChangeSignatureConflictSearcher { + private static final Logger LOG = + Logger.getInstance("#org.jetbrains.plugins.groovy.refactoring.changeSignature.GrChangeSignatureConflictSearcher"); + private final JavaChangeInfo myChangeInfo; + + GrChangeSignatureConflictSearcher(JavaChangeInfo changeInfo) { + this.myChangeInfo = changeInfo; + } + + public MultiMap findConflicts(Ref refUsages) { + MultiMap conflictDescriptions = new MultiMap(); + addMethodConflicts(conflictDescriptions); + UsageInfo[] usagesIn = refUsages.get(); + RenameUtil.addConflictDescriptions(usagesIn, conflictDescriptions); + Set usagesSet = new HashSet(Arrays.asList(usagesIn)); + RenameUtil.removeConflictUsages(usagesSet); + if (myChangeInfo.isVisibilityChanged()) { + try { + addInaccessibilityDescriptions(usagesSet, conflictDescriptions); + } + catch (IncorrectOperationException e) { + LOG.error(e); + } + } + + return conflictDescriptions; + } + + private boolean needToChangeCalls() { + return myChangeInfo.isNameChanged() || myChangeInfo.isParameterSetOrOrderChanged() || myChangeInfo.isExceptionSetOrOrderChanged(); + } + + + private void addInaccessibilityDescriptions(Set usages, MultiMap conflictDescriptions) + throws IncorrectOperationException { + PsiMethod method = myChangeInfo.getMethod(); + PsiModifierList modifierList = (PsiModifierList)method.getModifierList().copy(); + VisibilityUtil.setVisibility(modifierList, myChangeInfo.getNewVisibility()); + + for (Iterator iterator = usages.iterator(); iterator.hasNext();) { + UsageInfo usageInfo = iterator.next(); + PsiElement element = usageInfo.getElement(); + if (element != null) { + if (element instanceof GrReferenceExpression) { + PsiClass accessObjectClass = null; + GrExpression qualifier = ((GrReferenceExpression)element).getQualifierExpression(); + if (qualifier != null) { + accessObjectClass = getAccessObjectClass(qualifier); + } + + if (!JavaPsiFacade.getInstance(element.getProject()).getResolveHelper() + .isAccessible(method, modifierList, element, accessObjectClass, null)) { + String message = + RefactoringBundle.message("0.with.1.visibility.is.not.accesible.from.2", + RefactoringUIUtil.getDescription(method, true), + myChangeInfo.getNewVisibility(), + RefactoringUIUtil.getDescription(ConflictsUtil.getContainer(element), true)); + conflictDescriptions.putValue(method, message); + if (!needToChangeCalls()) { + iterator.remove(); + } + } + } + } + } + } + + @Nullable + private static PsiClass getAccessObjectClass(GrExpression expression) { + if (expression instanceof GrConstructorInvocation) return null; + PsiType type = expression.getType(); + if (type instanceof PsiClassType) { + return ((PsiClassType)type).resolveGenerics().getElement(); + } + if (type == null && expression instanceof PsiReferenceExpression) { + JavaResolveResult resolveResult = ((PsiReferenceExpression)expression).advancedResolve(false); + if (resolveResult.getElement() instanceof PsiClass) { + return (PsiClass)resolveResult.getElement(); + } + } + return null; + } + + + private void addMethodConflicts(MultiMap conflicts) { + String newMethodName = myChangeInfo.getNewName(); + try { + PsiMethod prototype; + final PsiMethod method = myChangeInfo.getMethod(); + if (!GroovyFileType.GROOVY_LANGUAGE.equals(method.getLanguage())) return; + PsiManager manager = PsiManager.getInstance(method.getProject()); + GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(manager.getProject()); + final CanonicalTypes.Type returnType = myChangeInfo.getNewReturnType(); + if (returnType != null) { + prototype = factory.createMethodFromText("", newMethodName, returnType.getTypeText(), ArrayUtil.EMPTY_STRING_ARRAY); + } + else { + prototype = factory.createConstructorFromText(newMethodName, ArrayUtil.EMPTY_STRING_ARRAY, ArrayUtil.EMPTY_STRING_ARRAY, ""); + } + JavaParameterInfo[] parameters = myChangeInfo.getNewParameters(); + + + for (JavaParameterInfo info : parameters) { + PsiParameter param = factory.createParameter(info.getName(), info.getTypeText(), (GroovyPsiElement)method); + prototype.getParameterList().add(param); + } + + ConflictsUtil.checkMethodConflicts(method.getContainingClass(), method, prototype, conflicts); + } + catch (IncorrectOperationException e) { + LOG.error(e); + } + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java index 387cd3c97aaa..316aa8ca934b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java @@ -35,7 +35,12 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc } public MultiMap findConflicts(ChangeInfo info, Ref refUsages) { - return null; //To change body of implemented methods use File | Settings | File Templates. + if (info instanceof JavaChangeInfo) { + return new GrChangeSignatureConflictSearcher((JavaChangeInfo)info).findConflicts(refUsages); + } + else { + return new MultiMap(); + } } public boolean processUsage(ChangeInfo changeInfo, UsageInfo usageInfo, boolean beforeMethodChange, UsageInfo[] usages) { From 9a5770b6127ed8d17f9d62db90db59ef10a5da73 Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Fri, 23 Apr 2010 10:32:41 +0400 Subject: [PATCH 010/212] improved searching of method duplicates --- .../plugins/groovy/GroovyBundle.properties | 1 + .../groovy/annotator/GroovyAnnotator.java | 47 ++++++------ .../GroovyParameterInfoHandler.java | 16 ++-- .../psi/api/types/GrClosureParameter.java | 3 - .../psi/api/types/GrClosureSignature.java | 3 + .../groovy/lang/psi/impl/GrClosureType.java | 1 + .../impl/types/GrClosureParameterImpl.java | 15 +--- .../impl/types/GrClosureSignatureImpl.java | 13 ++-- .../{ => types}/GrClosureSignatureUtil.java | 74 +++++++++++++++++-- .../plugins/groovy/lang/psi/util/PsiUtil.java | 2 +- .../groovy/lang/GroovyHighlightingTest.java | 2 + .../highlighting/MethodDuplicates.groovy | 9 +++ 12 files changed, 124 insertions(+), 62 deletions(-) rename plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/{ => types}/GrClosureSignatureUtil.java (80%) create mode 100644 plugins/groovy/testdata/highlighting/MethodDuplicates.groovy diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties index fb9defa85f29..e21c42b9f823 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties @@ -335,3 +335,4 @@ property.name.expected=Property name expected add.method.body=Add method body wildcards.are.not.allowed.in.extends.list=A super type may not specify a wildcard type method.doesnot.override.super=Method does not override method from its superclass +method.duplicate={0} is already defined diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java index 32ab9945900d..5e91f438a33a 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java @@ -33,13 +33,13 @@ import com.intellij.psi.*; import com.intellij.psi.infos.CandidateInfo; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.searches.SuperMethodsSearch; +import com.intellij.psi.util.MethodSignature; import com.intellij.psi.util.MethodSignatureBackedByPsiMethod; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.ArrayUtil; import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.MultiMap; import gnu.trove.THashSet; -import gnu.trove.TObjectHashingStrategy; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.GroovyBundle; @@ -49,7 +49,6 @@ import org.jetbrains.plugins.groovy.annotator.intentions.dynamic.DynamicProperty import org.jetbrains.plugins.groovy.codeInspection.GroovyImportsTracker; import org.jetbrains.plugins.groovy.config.GroovyConfigUtils; import org.jetbrains.plugins.groovy.highlighter.DefaultHighlighter; -import org.jetbrains.plugins.groovy.intentions.utils.DuplicatesUtil; import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.*; import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; import org.jetbrains.plugins.groovy.lang.lexer.TokenSets; @@ -83,6 +82,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.util.GrVariableDeclarationOwner import org.jetbrains.plugins.groovy.lang.psi.impl.GrClosureType; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass; +import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil; import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil; @@ -953,34 +953,33 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator { } private static void checkDuplicateMethod(GrMethod[] methods, AnnotationHolder holder) { - final Map> map = DuplicatesUtil.factorDuplicates(methods, new TObjectHashingStrategy() { - public int computeHashCode(GrMethod method) { - return method.getSignature(PsiSubstitutor.EMPTY).hashCode(); - } - - public boolean equals(GrMethod method1, GrMethod method2) { - return method1.getSignature(PsiSubstitutor.EMPTY).equals(method2.getSignature(PsiSubstitutor.EMPTY)); - } - }); + Map> map = GrClosureSignatureUtil.findMethodSignatures(methods); processMethodDuplicates(map, holder); } - protected static void processMethodDuplicates(Map> map, AnnotationHolder holder) { - HashSet duplicateMethodsWarning = new HashSet(); - HashSet duplicateMethodsErrors = new HashSet(); - - DuplicatesUtil.collectMethodDuplicates(map, duplicateMethodsWarning, duplicateMethodsErrors); - - for (GrMethod duplicateMethod : duplicateMethodsErrors) { - holder.createErrorAnnotation(duplicateMethod.getNameIdentifierGroovy(), - GroovyBundle.message("repetitive.method.name.signature.and.return.type")); - } - - for (GrMethod duplicateMethod : duplicateMethodsWarning) { - holder.createWarningAnnotation(duplicateMethod.getNameIdentifierGroovy(), GroovyBundle.message("repetitive.method.name.signature")); + protected static void processMethodDuplicates(Map> map, AnnotationHolder holder) { + for (MethodSignature signature : map.keySet()) { + List methods = map.get(signature); + if (methods.size() > 1) { + String signaturePresentation = getSignaturePresentation(signature); + for (GrMethod method : methods) { + holder.createErrorAnnotation(method.getNameIdentifierGroovy(), GroovyBundle.message("method.duplicate", signaturePresentation)); + } + } } } + private static String getSignaturePresentation(MethodSignature signature) { + StringBuilder builder = new StringBuilder(); + builder.append(signature.getName()).append('('); + PsiType[] types = signature.getParameterTypes(); + for (PsiType type : types) { + builder.append(type.getPresentableText()).append(", "); + } + if (types.length > 0) builder.delete(builder.length() - 2, builder.length()); + builder.append(")"); + return builder.toString(); + } private static void checkTypeDefinition(AnnotationHolder holder, GrTypeDefinition typeDefinition) { final GroovyConfigUtils configUtils = GroovyConfigUtils.getInstance(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parameterInfo/GroovyParameterInfoHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parameterInfo/GroovyParameterInfoHandler.java index 32740d1cd782..0382bb84c211 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parameterInfo/GroovyParameterInfoHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parameterInfo/GroovyParameterInfoHandler.java @@ -328,18 +328,16 @@ public class GroovyParameterInfoHandler implements ParameterInfoHandler 0) { for (int i = 0; i < parameters.length; i++) { if (i > 0) buffer.append(", "); - final String name = parameters[i].getName(); final PsiType psiType = parameters[i].getType(); - if (name == null) { - buffer.append(psiType == null ? "null" : psiType.getPresentableText()); + if (psiType == null) { + buffer.append("def"); } else { - String typeText = psiType == null ? "def" : psiType.getPresentableText(); - buffer.append(typeText).append(' ').append(name); - final GrExpression initializer = parameters[i].getDefaultInitializer(); - if (initializer != null) { - buffer.append(" = ").append(initializer.getText()); - } + buffer.append(psiType.getPresentableText()); + } + final GrExpression initializer = parameters[i].getDefaultInitializer(); + if (initializer != null) { + buffer.append(" = ").append(initializer.getText()); } } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/types/GrClosureParameter.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/types/GrClosureParameter.java index 70e763cfdc44..17c8a2d0b33c 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/types/GrClosureParameter.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/types/GrClosureParameter.java @@ -35,7 +35,4 @@ public interface GrClosureParameter { GrExpression getDefaultInitializer(); boolean isValid(); - - @Nullable - String getName(); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/types/GrClosureSignature.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/types/GrClosureSignature.java index ada0d0f01584..38bc577b0b62 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/types/GrClosureSignature.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/types/GrClosureSignature.java @@ -15,6 +15,7 @@ */ package org.jetbrains.plugins.groovy.lang.psi.api.types; +import com.intellij.psi.PsiSubstitutor; import com.intellij.psi.PsiType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -23,6 +24,8 @@ import org.jetbrains.annotations.Nullable; * @author Maxim.Medvedev */ public interface GrClosureSignature { + @NotNull PsiSubstitutor getSubstitutor(); + @NotNull GrClosureParameter[] getParameters(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrClosureType.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrClosureType.java index d48a6502f629..09f696369190 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrClosureType.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrClosureType.java @@ -26,6 +26,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureParameter; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature; +import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil; /** * @author ven diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureParameterImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureParameterImpl.java index 1f858715a3a2..39ee2d7315cf 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureParameterImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureParameterImpl.java @@ -29,12 +29,10 @@ import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureParameter; */ public class GrClosureParameterImpl implements GrClosureParameter { @Nullable final PsiType myType; - @Nullable final String myName=null; final boolean myOptional; @Nullable final GrExpression myDefaultInitializer; - public GrClosureParameterImpl(/*String name,*/ PsiType type, boolean optional, GrExpression defaultInitializer) { -// myName = name; + public GrClosureParameterImpl(PsiType type, boolean optional, GrExpression defaultInitializer) { myType = type; myOptional = optional; if (myOptional) { @@ -45,16 +43,12 @@ public class GrClosureParameterImpl implements GrClosureParameter { } } - public GrClosureParameterImpl(@Nullable PsiType type) { - this(/*null,*/ type, false, null); - } - public GrClosureParameterImpl(PsiParameter parameter) { this(parameter, PsiSubstitutor.EMPTY); } public GrClosureParameterImpl(PsiParameter parameter, PsiSubstitutor substitutor) { - this(/*parameter.getName(), */substitutor.substitute(parameter.getType()), + this(substitutor.substitute(parameter.getType()), parameter instanceof GrParameter ? ((GrParameter)parameter).isOptional() : false, parameter instanceof GrParameter ? ((GrParameter)parameter).getDefaultInitializer() : null); } @@ -78,11 +72,6 @@ public class GrClosureParameterImpl implements GrClosureParameter { return (myType == null || myType.isValid()) && (myDefaultInitializer == null || myDefaultInitializer.isValid()); } - @Nullable - public String getName() { - return myName; - } - @Override public boolean equals(Object obj) { if (obj instanceof GrClosureParameter) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureSignatureImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureSignatureImpl.java index 0bd43b1b2b8d..e90e1c37eeaa 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureSignatureImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureSignatureImpl.java @@ -32,6 +32,7 @@ public class GrClosureSignatureImpl implements GrClosureSignature { private final boolean myIsVarargs; @Nullable private final PsiType myReturnType; @NotNull private final GrClosureParameter[] myParameters; + @NotNull private PsiSubstitutor mySubstitutor; public GrClosureSignatureImpl(@NotNull PsiParameter[] parameters, @Nullable PsiType returnType, @NotNull PsiSubstitutor substitutor) { myReturnType = substitutor.substitute(returnType); @@ -46,16 +47,13 @@ public class GrClosureSignatureImpl implements GrClosureSignature { else { myIsVarargs = false; } + mySubstitutor = substitutor; } public GrClosureSignatureImpl(PsiParameter[] parameters, PsiType returnType) { this(parameters, returnType, PsiSubstitutor.EMPTY); } - public GrClosureSignatureImpl(PsiParameter[] parameters) { - this(parameters, null); - } - public GrClosureSignatureImpl(@NotNull GrClosableBlock block) { this(block.getAllParameters(), block.getReturnType()); } @@ -68,7 +66,7 @@ public class GrClosureSignatureImpl implements GrClosureSignature { this(method.getParameterList().getParameters(), PsiUtil.getSmartReturnType(method), substitutor); } - private GrClosureSignatureImpl(@NotNull GrClosureParameter[] params, @Nullable PsiType returnType, boolean isVarArgs) { + GrClosureSignatureImpl(@NotNull GrClosureParameter[] params, @Nullable PsiType returnType, boolean isVarArgs) { myParameters = params; myReturnType = returnType; myIsVarargs = isVarArgs; @@ -85,6 +83,11 @@ public class GrClosureSignatureImpl implements GrClosureSignature { return myReturnType; } + @NotNull + public PsiSubstitutor getSubstitutor() { + return mySubstitutor; + } + @NotNull public GrClosureParameter[] getParameters() { GrClosureParameter[] result = new GrClosureParameter[myParameters.length]; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrClosureSignatureUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureSignatureUtil.java similarity index 80% rename from plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrClosureSignatureUtil.java rename to plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureSignatureUtil.java index 79510b570cd9..f8788f325e39 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrClosureSignatureUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureSignatureUtil.java @@ -13,25 +13,27 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.plugins.groovy.lang.psi.impl; +package org.jetbrains.plugins.groovy.lang.psi.impl.types; +import com.intellij.openapi.util.Pair; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.util.MethodSignature; +import com.intellij.psi.util.MethodSignatureUtil; +import gnu.trove.THashMap; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList; import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureParameter; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature; +import org.jetbrains.plugins.groovy.lang.psi.impl.GrTupleType; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; -import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureImpl; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; +import java.util.*; /** * @author Maxim.Medvedev @@ -70,7 +72,7 @@ public class GrClosureSignatureUtil { } private static boolean isApplicable(GrClosureSignature signature, PsiType[] args, PsiManager manager, GlobalSearchScope scope) { - GrClosureParameter[] params = signature.getParameters(); + GrClosureParameter[] params = signature.getParameters(); if (args.length > params.length && !signature.isVarargs()) return false; int optional = getOptionalParamCount(signature, false); int notOptional = params.length - optional; @@ -344,4 +346,62 @@ public class GrClosureSignatureUtil { return copy; } } + + + public static List generateAllSignaturesForMethod(GrMethod method, PsiSubstitutor substitutor) { + GrClosureSignature signature = createSignature(method, substitutor); + String name = method.getName(); + GrClosureParameter[] params = signature.getParameters(); + PsiTypeParameter[] typeParameters = method.getTypeParameters(); + + ArrayList newParams = new ArrayList(params.length); + ArrayList opts = new ArrayList(params.length); + ArrayList optInds = new ArrayList(params.length); + + for (int i = 0; i < params.length; i++) { + if (params[i].isOptional()) { + opts.add(params[i]); + optInds.add(i); + } + else { + newParams.add(params[i].getType()); + } + } + + List result = new ArrayList(opts.size() + 1); + result.add(generateSignature(name, newParams, typeParameters, substitutor)); + for (int i = 0; i < opts.size(); i++) { + newParams.add(optInds.get(i), opts.get(i).getType()); + result.add(generateSignature(name, newParams, typeParameters, substitutor)); + } + return result; + } + + public static Map> findMethodSignatures(GrMethod[] methods) { + List> signatures = new ArrayList>(); + for (GrMethod method : methods) { + List current = generateAllSignaturesForMethod(method, PsiSubstitutor.EMPTY); + for (MethodSignature signature : current) { + signatures.add(new Pair(signature, method)); + } + } + + THashMap> map = new THashMap>(); + for (Pair pair : signatures) { + List list = map.get(pair.first); + if (list == null) { + list = new ArrayList(); + map.put(pair.first, list); + } + list.add(pair.second); + } + return map; + } + + private static MethodSignature generateSignature(String name, + List paramTypes, + PsiTypeParameter[] typeParameters, + PsiSubstitutor substitutor) { + return MethodSignatureUtil.createMethodSignature(name, paramTypes.toArray(new PsiType[paramTypes.size()]), typeParameters, substitutor); + } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java index 3d8b97b7594e..7fda1a07e520 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java @@ -64,11 +64,11 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMe import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement; -import org.jetbrains.plugins.groovy.lang.psi.impl.GrClosureSignatureUtil; import org.jetbrains.plugins.groovy.lang.psi.impl.GrClosureType; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass; import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.JavaIdentifier; +import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil; import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil; import org.jetbrains.plugins.groovy.lang.resolve.processors.MethodResolverProcessor; diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.java index bd357303a96b..b78fd9708100 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.java @@ -238,4 +238,6 @@ public class GroovyHighlightingTest extends LightCodeInsightFixtureTestCase { public void testOverrideAnnotation() throws Exception {doTest();} public void testClosureCallWithTupleTypeArgument() throws Exception {doTest();} + + public void testMethodDuplicates() throws Exception {doTest();} } \ No newline at end of file diff --git a/plugins/groovy/testdata/highlighting/MethodDuplicates.groovy b/plugins/groovy/testdata/highlighting/MethodDuplicates.groovy new file mode 100644 index 000000000000..039707c2629e --- /dev/null +++ b/plugins/groovy/testdata/highlighting/MethodDuplicates.groovy @@ -0,0 +1,9 @@ +def foo(String s = "a", int i, double y = 4) { + +} + +def foo(int i, double y) {} + +def foo(String s, int i) {} + +def foo(String s, double y){} \ No newline at end of file From 63662c28a75f3a22e701e20a3a1b34d874ab5e91 Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Tue, 27 Apr 2010 15:37:11 +0400 Subject: [PATCH 011/212] GroovyChangeSignatureUsageProcessor --- .../ChangeMethodSignatureFromUsageFix.java | 2 +- plugins/groovy/src/META-INF/plugin.xml | 1 + .../plugins/groovy/GroovyBundle.properties | 2 +- .../groovy/annotator/GroovyAnnotator.java | 28 ++---- .../documentation/GroovyPresentationUtil.java | 13 +++ .../arguments/GrArgumentLabelImpl.java | 3 +- .../psi/impl/synthetic/GroovyScriptClass.java | 11 ++- .../impl/types/GrClosureSignatureUtil.java | 44 ++++----- .../plugins/groovy/lang/psi/util/PsiUtil.java | 5 +- .../GroovyRefactoringBundle.properties | 3 + .../GrChangeSignatureConflictSearcher.java | 15 ++- .../GrChangeSignatureDialog.java | 12 ++- .../GrChangeSignatureProcessor.java | 42 +++++++-- .../GrChangeSignatureUsageProcessor.java | 91 +++++++++++++++++- .../changeSignature/GrMethodConflictUtil.java | 94 +++++++++++++++++++ .../changeSignature/GrParameterInfo.java | 16 +++- 16 files changed, 300 insertions(+), 82 deletions(-) create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodConflictUtil.java diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeMethodSignatureFromUsageFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeMethodSignatureFromUsageFix.java index f66231688ff9..f63c6fdff819 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeMethodSignatureFromUsageFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeMethodSignatureFromUsageFix.java @@ -95,7 +95,7 @@ public class ChangeMethodSignatureFromUsageFix implements IntentionAction { String result = ""; try { for (ParameterInfoImpl info : infos) { - PsiType type = info.getTypeWrapper().getType(context, context.getManager()); + PsiType type = info.createType(context, context.getManager()); if (result.length() != 0) { result += ", "; } diff --git a/plugins/groovy/src/META-INF/plugin.xml b/plugins/groovy/src/META-INF/plugin.xml index 4896b89518a7..db910b0b7dc6 100644 --- a/plugins/groovy/src/META-INF/plugin.xml +++ b/plugins/groovy/src/META-INF/plugin.xml @@ -66,6 +66,7 @@ + diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties index e21c42b9f823..e66396ab806a 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties @@ -335,4 +335,4 @@ property.name.expected=Property name expected add.method.body=Add method body wildcards.are.not.allowed.in.extends.list=A super type may not specify a wildcard type method.doesnot.override.super=Method does not override method from its superclass -method.duplicate={0} is already defined +method.duplicate=Method with signature {0} is already defined in the class ''{1}'' diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java index 5e91f438a33a..9372b283591f 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java @@ -33,6 +33,7 @@ import com.intellij.psi.*; import com.intellij.psi.infos.CandidateInfo; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.searches.SuperMethodsSearch; +import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.MethodSignature; import com.intellij.psi.util.MethodSignatureBackedByPsiMethod; import com.intellij.psi.util.PsiTreeUtil; @@ -49,6 +50,7 @@ import org.jetbrains.plugins.groovy.annotator.intentions.dynamic.DynamicProperty import org.jetbrains.plugins.groovy.codeInspection.GroovyImportsTracker; import org.jetbrains.plugins.groovy.config.GroovyConfigUtils; import org.jetbrains.plugins.groovy.highlighter.DefaultHighlighter; +import org.jetbrains.plugins.groovy.lang.documentation.GroovyPresentationUtil; import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.*; import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; import org.jetbrains.plugins.groovy.lang.lexer.TokenSets; @@ -453,7 +455,7 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator { if (argumentTypes == null || argumentTypes.length == 0 || (argumentTypes.length == 1 && - PsiUtil.createMapType(newExpression.getManager(), newExpression.getResolveScope()).isAssignableFrom(argumentTypes[0]))) { + InheritanceUtil.isInheritor(argumentTypes[0], CommonClassNames.JAVA_UTIL_MAP))) { checkDefaultMapConstructor(myHolder, argList, element); } else { @@ -953,34 +955,22 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator { } private static void checkDuplicateMethod(GrMethod[] methods, AnnotationHolder holder) { - Map> map = GrClosureSignatureUtil.findMethodSignatures(methods); + MultiMap map = GrClosureSignatureUtil.findMethodSignatures(methods); processMethodDuplicates(map, holder); } - protected static void processMethodDuplicates(Map> map, AnnotationHolder holder) { + protected static void processMethodDuplicates(MultiMap map, AnnotationHolder holder) { for (MethodSignature signature : map.keySet()) { - List methods = map.get(signature); + Collection methods = map.get(signature); if (methods.size() > 1) { - String signaturePresentation = getSignaturePresentation(signature); - for (GrMethod method : methods) { - holder.createErrorAnnotation(method.getNameIdentifierGroovy(), GroovyBundle.message("method.duplicate", signaturePresentation)); + String signaturePresentation = GroovyPresentationUtil.getSignaturePresentation(signature); + for (PsiMethod method : methods) { + holder.createErrorAnnotation(method.getNameIdentifier(), GroovyBundle.message("method.duplicate", signaturePresentation, method.getContainingClass().getName())); } } } } - private static String getSignaturePresentation(MethodSignature signature) { - StringBuilder builder = new StringBuilder(); - builder.append(signature.getName()).append('('); - PsiType[] types = signature.getParameterTypes(); - for (PsiType type : types) { - builder.append(type.getPresentableText()).append(", "); - } - if (types.length > 0) builder.delete(builder.length() - 2, builder.length()); - builder.append(")"); - return builder.toString(); - } - private static void checkTypeDefinition(AnnotationHolder holder, GrTypeDefinition typeDefinition) { final GroovyConfigUtils configUtils = GroovyConfigUtils.getInstance(); if (typeDefinition.isAnnotationType()) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/documentation/GroovyPresentationUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/documentation/GroovyPresentationUtil.java index 0e54114fb85e..f1077df5aa0b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/documentation/GroovyPresentationUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/documentation/GroovyPresentationUtil.java @@ -20,6 +20,7 @@ import com.intellij.psi.PsiReference; import com.intellij.psi.PsiSubstitutor; import com.intellij.psi.PsiType; import com.intellij.psi.search.searches.ReferencesSearch; +import com.intellij.psi.util.MethodSignature; import com.intellij.util.ArrayUtil; import com.intellij.util.Processor; import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement; @@ -91,4 +92,16 @@ public class GroovyPresentationUtil { return builder.toString(); } } + + public static String getSignaturePresentation(MethodSignature signature) { + StringBuilder builder = new StringBuilder(); + builder.append(signature.getName()).append('('); + PsiType[] types = signature.getParameterTypes(); + for (PsiType type : types) { + builder.append(type.getPresentableText()).append(", "); + } + if (types.length > 0) builder.delete(builder.length() - 2, builder.length()); + builder.append(")"); + return builder.toString(); + } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/arguments/GrArgumentLabelImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/arguments/GrArgumentLabelImpl.java index 3586c29fcc36..2be7c9b5213a 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/arguments/GrArgumentLabelImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/arguments/GrArgumentLabelImpl.java @@ -21,6 +21,7 @@ import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry; import com.intellij.psi.impl.source.resolve.reference.impl.PsiMultiReference; +import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PropertyUtil; import com.intellij.util.ArrayUtil; import com.intellij.util.IncorrectOperationException; @@ -95,7 +96,7 @@ public class GrArgumentLabelImpl extends GroovyPsiElementImpl implements GrArgum if (resolvedMethod != null) { final PsiParameter[] parameters = resolvedMethod.getParameterList().getParameters(); if (parameters.length > 0) { - if (PsiUtil.createMapType(resolvedMethod.getManager(), resolvedMethod.getResolveScope()).isAssignableFrom(parameters[0].getType())) { + if (InheritanceUtil.isInheritor(parameters[0].getType(), CommonClassNames.JAVA_UTIL_MAP)) { //call with named argument, not setting property return null; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GroovyScriptClass.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GroovyScriptClass.java index 2bfb2b289f1f..37fb3f58a480 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GroovyScriptClass.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GroovyScriptClass.java @@ -22,6 +22,7 @@ import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; import com.intellij.psi.impl.InheritanceImplUtil; +import com.intellij.psi.impl.PsiClassImplUtil; import com.intellij.psi.impl.light.LightElement; import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.psi.scope.BaseScopeProcessor; @@ -215,12 +216,12 @@ public class GroovyScriptClass extends LightElement implements GrMemberOwner, Sy @NotNull public PsiField[] getAllFields() { - return PsiField.EMPTY_ARRAY; + return PsiClassImplUtil.getAllFields(this); } @NotNull public PsiMethod[] getAllMethods() { - return getMethods(); //todo + return PsiClassImplUtil.getAllMethods(this); } @NotNull @@ -233,17 +234,17 @@ public class GroovyScriptClass extends LightElement implements GrMemberOwner, Sy } public PsiMethod findMethodBySignature(PsiMethod patternMethod, boolean checkBases) { - return null; + return PsiClassImplUtil.findMethodBySignature(this, patternMethod, checkBases); } @NotNull public PsiMethod[] findMethodsBySignature(PsiMethod patternMethod, boolean checkBases) { - return PsiMethod.EMPTY_ARRAY; + return PsiClassImplUtil.findMethodsBySignature(this, patternMethod, checkBases); } @NotNull public PsiMethod[] findMethodsByName(String name, boolean checkBases) { - return PsiMethod.EMPTY_ARRAY; + return PsiClassImplUtil.findMethodsByName(this, name, checkBases); } @NotNull diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureSignatureUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureSignatureUtil.java index f8788f325e39..f51857ce6d14 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureSignatureUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureSignatureUtil.java @@ -18,9 +18,11 @@ package org.jetbrains.plugins.groovy.lang.psi.impl.types; import com.intellij.openapi.util.Pair; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.MethodSignature; import com.intellij.psi.util.MethodSignatureUtil; -import gnu.trove.THashMap; +import com.intellij.util.containers.MultiMap; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList; import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument; @@ -31,7 +33,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureParameter; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature; import org.jetbrains.plugins.groovy.lang.psi.impl.GrTupleType; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; -import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import java.util.*; @@ -191,8 +192,8 @@ public class GrClosureSignatureUtil { * @return null if signature can not be applied to this argumentList */ @Nullable - public static List[] mapParametersToArguments(GrClosureSignature signature, - GrArgumentList list, + public static List[] mapParametersToArguments(@NotNull GrClosureSignature signature, + @NotNull GrArgumentList list, PsiManager manager, GlobalSearchScope scope) { @@ -206,7 +207,7 @@ public class GrClosureSignatureUtil { } @Nullable - private static List[] map(GrClosureSignature signature, GrArgumentList list, PsiManager manager, GlobalSearchScope scope) { + private static List[] map(@NotNull GrClosureSignature signature, @NotNull GrArgumentList list, PsiManager manager, GlobalSearchScope scope) { final GrExpression[] args = list.getExpressionArguments(); final GrNamedArgument[] namedArgs = list.getNamedArguments(); boolean hasNamedArgs = namedArgs.length > 0; @@ -220,8 +221,7 @@ public class GrClosureSignatureUtil { if (hasNamedArgs) { if (paramLength == 0) return null; PsiType type = params[0].getType(); - PsiClassType mapType = PsiUtil.createMapType(manager, scope); - if (TypesUtil.isAssignable(mapType, type, manager, scope)) { + if (InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_UTIL_MAP)) { paramLength--; map[0] = Arrays.asList(namedArgs); } @@ -287,8 +287,7 @@ public class GrClosureSignatureUtil { if (hasNamedArgs) { if (params.length == 0) return null; PsiType type = params[0].getType(); - PsiClassType mapType = PsiUtil.createMapType(manager, scope); - if (TypesUtil.isAssignable(mapType, type, manager, scope)) { + if (InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_UTIL_MAP)) { map[0] = Arrays.asList(namedArgs); } else { @@ -377,23 +376,24 @@ public class GrClosureSignatureUtil { return result; } - public static Map> findMethodSignatures(GrMethod[] methods) { - List> signatures = new ArrayList>(); - for (GrMethod method : methods) { - List current = generateAllSignaturesForMethod(method, PsiSubstitutor.EMPTY); + public static MultiMap findMethodSignatures(PsiMethod[] methods) { + List> signatures = new ArrayList>(); + for (PsiMethod method : methods) { + List current; + if (method instanceof GrMethod) { + current = generateAllSignaturesForMethod((GrMethod)method, PsiSubstitutor.EMPTY); + } + else { + current = Collections.singletonList(method.getSignature(PsiSubstitutor.EMPTY)); + } for (MethodSignature signature : current) { - signatures.add(new Pair(signature, method)); + signatures.add(new Pair(signature, method)); } } - THashMap> map = new THashMap>(); - for (Pair pair : signatures) { - List list = map.get(pair.first); - if (list == null) { - list = new ArrayList(); - map.put(pair.first, list); - } - list.add(pair.second); + MultiMap map = new MultiMap(); + for (Pair pair : signatures) { + map.putValue(pair.first, pair.second); } return map; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java index 7fda1a07e520..eae83b497e5b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java @@ -129,10 +129,7 @@ public class PsiUtil { //check for default constructor if (method.isConstructor() && method.getParameterList().getParametersCount() == 0 && argumentTypes.length == 1) { - final PsiType type = argumentTypes[0]; - final PsiClassType mapType = JavaPsiFacade.getElementFactory(method.getProject()) - .createTypeByFQClassName(CommonClassNames.JAVA_UTIL_MAP, method.getResolveScope()); - return TypesUtil.isAssignable(mapType, type, method.getManager(), method.getResolveScope()); + return InheritanceUtil.isInheritor(argumentTypes[0], CommonClassNames.JAVA_UTIL_MAP); } LOG.assertTrue(signature != null); return GrClosureSignatureUtil.isSignatureApplicable(signature, argumentTypes, method.getManager(), method.getResolveScope()); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties index eb617f3e9cb6..c8e8f0e18434 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties @@ -105,3 +105,6 @@ column.name.type=Type column.name.name=Name column.name.default.initializer=Default initializer column.name.default.value=Default value\ +method.duplicate=Method with signature {0} is already defined in {1} +replace.setter.for.property=The default setter for property ''{0}'' will be overwritten +replace.getter.for.property=The default getter for property ''{0}'' will be overwritten \ No newline at end of file diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureConflictSearcher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureConflictSearcher.java index 9ff813bd6336..e440db12582d 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureConflictSearcher.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureConflictSearcher.java @@ -32,20 +32,20 @@ import com.intellij.util.VisibilityUtil; import com.intellij.util.containers.HashSet; import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.groovy.GroovyFileType; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrConstructorInvocation; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import java.util.Arrays; import java.util.Iterator; import java.util.Set; /** -* @author Maxim.Medvedev -*/ + * @author Maxim.Medvedev + */ class GrChangeSignatureConflictSearcher { private static final Logger LOG = Logger.getInstance("#org.jetbrains.plugins.groovy.refactoring.changeSignature.GrChangeSignatureConflictSearcher"); @@ -78,7 +78,6 @@ class GrChangeSignatureConflictSearcher { return myChangeInfo.isNameChanged() || myChangeInfo.isParameterSetOrOrderChanged() || myChangeInfo.isExceptionSetOrOrderChanged(); } - private void addInaccessibilityDescriptions(Set usages, MultiMap conflictDescriptions) throws IncorrectOperationException { PsiMethod method = myChangeInfo.getMethod(); @@ -131,14 +130,14 @@ class GrChangeSignatureConflictSearcher { private void addMethodConflicts(MultiMap conflicts) { - String newMethodName = myChangeInfo.getNewName(); try { - PsiMethod prototype; + GrMethod prototype; final PsiMethod method = myChangeInfo.getMethod(); - if (!GroovyFileType.GROOVY_LANGUAGE.equals(method.getLanguage())) return; + if (!(method instanceof GrMethod)) return; PsiManager manager = PsiManager.getInstance(method.getProject()); GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(manager.getProject()); final CanonicalTypes.Type returnType = myChangeInfo.getNewReturnType(); + String newMethodName = myChangeInfo.getNewName(); if (returnType != null) { prototype = factory.createMethodFromText("", newMethodName, returnType.getTypeText(), ArrayUtil.EMPTY_STRING_ARRAY); } @@ -147,13 +146,13 @@ class GrChangeSignatureConflictSearcher { } JavaParameterInfo[] parameters = myChangeInfo.getNewParameters(); - for (JavaParameterInfo info : parameters) { PsiParameter param = factory.createParameter(info.getName(), info.getTypeText(), (GroovyPsiElement)method); prototype.getParameterList().add(param); } ConflictsUtil.checkMethodConflicts(method.getContainingClass(), method, prototype, conflicts); + GrMethodConflictUtil.checkMethodConflicts(method.getContainingClass(), prototype, ((GrMethod)method), conflicts); } catch (IncorrectOperationException e) { LOG.error(e); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java index f2c56e828ff9..2be7860396f5 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java @@ -18,10 +18,8 @@ package org.jetbrains.plugins.groovy.refactoring.changeSignature; import com.intellij.openapi.editor.Document; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.psi.JavaPsiFacade; -import com.intellij.psi.PsiDocumentManager; -import com.intellij.psi.PsiType; -import com.intellij.psi.PsiTypeCodeFragment; +import com.intellij.psi.*; +import com.intellij.psi.search.GlobalSearchScope; import com.intellij.refactoring.HelpID; import com.intellij.refactoring.ui.CodeFragmentTableCellEditor; import com.intellij.refactoring.ui.CodeFragmentTableCellRenderer; @@ -261,11 +259,15 @@ public class GrChangeSignatureDialog extends RefactoringDialog { returnType = myReturnTypeCodeFragment.getType(); } catch (PsiTypeCodeFragment.TypeSyntaxException e) { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } catch (PsiTypeCodeFragment.NoTypeException e) { returnType = PsiType.NULL; } + if (returnType == PsiType.NULL) { + returnType = JavaPsiFacade.getElementFactory(myProject) + .createTypeByFQClassName(CommonClassNames.JAVA_LANG_OBJECT, GlobalSearchScope.allScope(myProject)); + } + //todo show warnings String newName = getNewName(); final List parameterInfos = myParameterModel.getParameterInfos(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java index f10e1a342efb..66acdb5c03a1 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java @@ -20,20 +20,26 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Ref; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiMethod; -import com.intellij.psi.PsiReference; -import com.intellij.psi.search.searches.MethodReferencesSearch; import com.intellij.refactoring.BaseRefactoringProcessor; +import com.intellij.refactoring.changeSignature.ChangeSignatureUsageProcessor; import com.intellij.refactoring.changeSignature.ChangeSignatureViewDescriptor; import com.intellij.usageView.UsageInfo; import com.intellij.usageView.UsageViewDescriptor; +import com.intellij.util.containers.HashSet; import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.NotNull; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + /** * @author Maxim.Medvedev */ public class GrChangeSignatureProcessor extends BaseRefactoringProcessor { - public static final Logger LOG = Logger.getInstance("#org.jetbrains.plugins.groovy.refactoring.changeSignature.GrChangeSignatureProcessor"); + public static final Logger LOG = + Logger.getInstance("#org.jetbrains.plugins.groovy.refactoring.changeSignature.GrChangeSignatureProcessor"); private final GrChangeInfoImpl myChangeInfo; //private @@ -51,24 +57,31 @@ public class GrChangeSignatureProcessor extends BaseRefactoringProcessor { @NotNull @Override protected UsageInfo[] findUsages() { - final PsiReference[] refs = MethodReferencesSearch.search(myChangeInfo.getMethod()).toArray(PsiReference.EMPTY_ARRAY); - for (PsiReference ref : refs) { + List infos = new ArrayList(); + final ChangeSignatureUsageProcessor[] processors = ChangeSignatureUsageProcessor.EP_NAME.getExtensions(); + for (ChangeSignatureUsageProcessor processor : processors) { + infos.addAll(Arrays.asList(processor.findUsages(myChangeInfo))); } - - return UsageInfo.EMPTY_ARRAY;//todo + return infos.toArray(new UsageInfo[infos.size()]); } @Override protected void refreshElements(PsiElement[] elements) { boolean condition = elements.length == 1 && elements[0] instanceof PsiMethod; LOG.assertTrue(condition); - myChangeInfo.updateMethod((PsiMethod) elements[0]); + myChangeInfo.updateMethod((PsiMethod)elements[0]); } @Override protected void performRefactoring(UsageInfo[] usages) { changeMethod(); + for (UsageInfo usage : usages) { + + for (ChangeSignatureUsageProcessor processor : GrChangeSignatureUsageProcessor.EP_NAME.getExtensions()) { + if (processor.processUsage(myChangeInfo, usage, false, usages)) break; + } + } } private void changeMethod() { @@ -95,6 +108,17 @@ public class GrChangeSignatureProcessor extends BaseRefactoringProcessor { @Override protected boolean preprocessUsages(Ref refUsages) { - return showConflicts(findConflicts(refUsages)); + MultiMap conflictDescriptions = new MultiMap(); + for (ChangeSignatureUsageProcessor usageProcessor : ChangeSignatureUsageProcessor.EP_NAME.getExtensions()) { + final MultiMap conflicts = usageProcessor.findConflicts(myChangeInfo, refUsages); + for (PsiElement key : conflicts.keySet()) { + Collection collection = conflictDescriptions.get(key); + if (collection.size() == 0) collection = new HashSet(); + collection.addAll(conflicts.get(key)); + conflictDescriptions.put(key, collection); + } + } + + return showConflicts(conflictDescriptions); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java index 316aa8ca934b..da261bdbec40 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java @@ -17,11 +17,21 @@ package org.jetbrains.plugins.groovy.refactoring.changeSignature; import com.intellij.openapi.util.Ref; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiMethod; import com.intellij.refactoring.changeSignature.ChangeInfo; import com.intellij.refactoring.changeSignature.ChangeSignatureUsageProcessor; import com.intellij.refactoring.changeSignature.JavaChangeInfo; +import com.intellij.refactoring.changeSignature.JavaParameterInfo; import com.intellij.usageView.UsageInfo; import com.intellij.util.containers.MultiMap; +import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall; +import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement; +import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil; + +import java.util.List; /** * @author Maxim.Medvedev @@ -43,11 +53,84 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc } } - public boolean processUsage(ChangeInfo changeInfo, UsageInfo usageInfo, boolean beforeMethodChange, UsageInfo[] usages) { - return false; //To change body of implemented methods use File | Settings | File Templates. + public boolean processPrimaryMethod(ChangeInfo changeInfo) { + return false; } - public boolean processPrimaryMethod(ChangeInfo changeInfo) { - return false; //To change body of implemented methods use File | Settings | File Templates. + public boolean processUsage(ChangeInfo changeInfo, UsageInfo usageInfo, boolean beforeMethodChange, UsageInfo[] usages) { + if (!(changeInfo instanceof JavaChangeInfo)) return false; + PsiElement element = usageInfo.getElement(); + if (element == null) return false; + + if (usageInfo instanceof GrMethodCallUsageInfo) { + processMethodUsage(element, ((JavaChangeInfo)changeInfo), ((GrMethodCallUsageInfo)usageInfo).isToChangeArguments(), + ((GrMethodCallUsageInfo)usageInfo).isToCatchExceptions(), ((JavaChangeInfo)changeInfo).getMethod()); + GrCall call = (GrCall)element; + GrArgumentList argumentList = call.getArgumentList(); + return true; + } + return false; + } + + private static void processMethodUsage(PsiElement element, + JavaChangeInfo changeInfo, + boolean toChangeArguments, + boolean toCatchExceptions, + PsiMethod method) { + if (changeInfo.isNameChanged()) { + if (element instanceof GrCodeReferenceElement) { + ((GrCodeReferenceElement)element).bindToElement(method); + } + } + if (toChangeArguments) { + JavaParameterInfo[] parameters = changeInfo.getNewParameters(); + GrArgumentList argumentList = ((GrCall)element.getParent()).getArgumentList(); + if (argumentList == null) return; + List[] map = GrClosureSignatureUtil + .mapParametersToArguments(GrClosureSignatureUtil.createSignature(method), argumentList, element.getManager(), + method.getResolveScope()); + + if (map == null) return; + PsiElement child = argumentList.getFirstChild(); + if (child != null) { + argumentList.deleteChildRange(child, argumentList.getLastChild()); + } + + GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(element.getProject()); + for (int i = 0; i < parameters.length; i++) { + JavaParameterInfo parameter = parameters[i]; + int index = parameter.getOldIndex(); + if (index >= 0) { + List arguments = map[index]; + if (arguments.size() == 1) { + PsiElement arg = arguments.iterator().next(); + if (i > 0 && arg instanceof GrNamedArgument) { + arg = factory.createExpressionFromText("[" + arg.getText() + "]"); + } + argumentList.add(arg); + } + else if (arguments.size() > 1) { + if (i == 0 && arguments.iterator().next() instanceof GrNamedArgument || + i == parameters.length - 1 && parameter.isVarargType()) { + for (PsiElement argument : arguments) { + argumentList.add(argument); + } + } + else { + StringBuilder argText = new StringBuilder(); + argText.append("["); + for (PsiElement argument : arguments) { + argText.append(argument.getText()).append(", "); + } + argText.replace(argText.length() - 2, argText.length(), "]"); + argumentList.add(factory.createExpressionFromText(argText.toString())); + } + } + else if (i < parameters.length - 1) { + argumentList.add(factory.createExpressionFromText("[]")); + } + } + } + } } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodConflictUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodConflictUtil.java new file mode 100644 index 000000000000..5246e227649f --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodConflictUtil.java @@ -0,0 +1,94 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.groovy.refactoring.changeSignature; + +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiMethod; +import com.intellij.psi.PsiSubstitutor; +import com.intellij.psi.util.MethodSignature; +import com.intellij.refactoring.util.RefactoringUIUtil; +import com.intellij.util.containers.MultiMap; +import org.jetbrains.plugins.groovy.lang.documentation.GroovyPresentationUtil; +import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; +import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil; +import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils; +import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle; + +import java.util.List; + +/** + * @author Maxim.Medvedev + */ +public class GrMethodConflictUtil { + private GrMethodConflictUtil() { + } + + public static void checkMethodConflicts(PsiClass clazz, + GrMethod prototype, + GrMethod refactoredMethod, + final MultiMap conflicts) { + checkForSignatureOverload(clazz, prototype, refactoredMethod, conflicts); + checkForAccessorOverloading(clazz, prototype, conflicts); + } + + private static void checkForSignatureOverload(PsiClass clazz, + GrMethod prototype, + GrMethod refactoredMethod, + MultiMap conflicts) { + String newName = prototype.getName(); + PsiMethod[] methods = clazz.findMethodsByName(newName, false); + MultiMap signatures = GrClosureSignatureUtil.findMethodSignatures(methods); + List prototypeSignatures = GrClosureSignatureUtil.generateAllSignaturesForMethod(prototype, PsiSubstitutor.EMPTY); + + for (MethodSignature prototypeSignature : prototypeSignatures) { + for (PsiMethod method : signatures.get(prototypeSignature)) { + if (method != refactoredMethod) { + String signaturePresentation = GroovyPresentationUtil.getSignaturePresentation(prototypeSignature); + conflicts.putValue(method, GroovyRefactoringBundle.message("method.duplicate", signaturePresentation, + RefactoringUIUtil.getDescription(clazz, false))); + break; + } + } + } + } + + private static void checkForAccessorOverloading(PsiClass clazz, + GrMethod prototype, + MultiMap conflicts) { + if (GroovyPropertyUtils.isSimplePropertySetter(prototype)) { + String propertyName = GroovyPropertyUtils.getPropertyNameBySetter(prototype); + PsiMethod setter = + GroovyPropertyUtils.findPropertySetter(clazz, propertyName, prototype.hasModifierProperty( + GrModifier.STATIC), false); + if (setter instanceof GrAccessorMethod) { + conflicts.putValue(setter, GroovyRefactoringBundle.message("replace.setter.for.property", propertyName)); + } + } + else if (GroovyPropertyUtils.isSimplePropertyGetter(prototype)) { + boolean isStatic = prototype.hasModifierProperty( + GrModifier.STATIC); + String propertyName = GroovyPropertyUtils.getPropertyNameByGetter(prototype); + PsiMethod getter = + GroovyPropertyUtils.findPropertyGetter(clazz, propertyName, isStatic, false); + if (getter instanceof GrAccessorMethod) { + conflicts.putValue(getter, GroovyRefactoringBundle.message("replace.getter.for.property", propertyName)); + } + } + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java index be14f96539fe..9d38f89e9786 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java @@ -34,6 +34,7 @@ public class GrParameterInfo implements JavaParameterInfo { private PsiTypeCodeFragment myType; private GroovyCodeFragment myDefaultInitializer; private final int myPosition; + private CanonicalTypes.Type myTypeWrapper; public GrParameterInfo(GrParameter parameter, int position) { myPosition = position; @@ -107,15 +108,24 @@ public class GrParameterInfo implements JavaParameterInfo { public String getTypeText() { - return null; //To change body of implemented methods use File | Settings | File Templates. + if (getTypeWrapper() != null) { + return getTypeWrapper().getTypeText(); + } + else { + return ""; + } } public CanonicalTypes.Type getTypeWrapper() { - return null; //To change body of implemented methods use File | Settings | File Templates. + if (myTypeWrapper == null) { + myTypeWrapper = CanonicalTypes.createTypeWrapper(createType(myType.getContext(), myType.getManager())); + } + return myTypeWrapper; } public PsiExpression getValue(PsiCallExpression callExpression) { - return null; //To change body of implemented methods use File | Settings | File Templates. + return JavaPsiFacade.getInstance(callExpression.getProject()).getElementFactory() + .createExpressionFromText(myDefaultValue.getText(), callExpression); } public boolean isVarargType() { From b5e1e6a3e1e135cc0c7892d283f46ffc19c82428 Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Sat, 1 May 2010 19:30:24 +0400 Subject: [PATCH 012/212] changeSignature. first tests --- plugins/groovy/src/META-INF/plugin.xml | 2 +- .../plugins/groovy/GroovyBundle.properties | 2 +- .../groovy/annotator/GroovyAnnotator.java | 9 +- .../ConvertParameterToMapEntryIntention.java | 2 +- .../lang/psi/GroovyPsiElementFactory.java | 9 +- .../statements/arguments/GrArgumentList.java | 11 +- .../statements/params/GrParameterList.java | 5 - .../psi/impl/GroovyPsiElementFactoryImpl.java | 22 +- .../impl/statements/GrVariableBaseImpl.java | 4 +- .../arguments/GrArgumentListImpl.java | 109 +++---- .../params/GrParameterListImpl.java | 37 +-- .../impl/types/GrClosureSignatureUtil.java | 52 ++-- .../plugins/groovy/lang/psi/util/PsiUtil.java | 26 +- .../GroovyRefactoringBundle.properties | 2 +- .../GrChageSignatureUsageSearcher.java | 27 +- .../changeSignature/GrChangeInfoImpl.java | 2 +- .../GrChangeSignatureDialog.form | 4 +- .../GrChangeSignatureDialog.java | 17 +- .../GrChangeSignatureProcessor.java | 42 ++- .../GrChangeSignatureUsageProcessor.java | 174 ++++++++--- .../GrMethodCallUsageInfo.java | 13 +- .../changeSignature/GrParameterInfo.java | 24 +- .../GrParameterTableModel.java | 2 +- .../changeSignature/ChangeSignatureTest.java | 280 ++++++++++++++++++ .../highlighting/MethodDuplicates.groovy | 19 +- .../ChangeVisibilityAndName.groovy | 3 + .../ChangeVisibilityAndName_after.groovy | 3 + .../InsertOptionalParameter.groovy | 3 + .../InsertOptionalParameter_after.groovy | 3 + .../changeSignature/InsertParameter.groovy | 3 + .../InsertParameter_after.groovy | 3 + .../MoveNamedParameters.groovy | 3 + .../MoveNamedParameters_after.groovy | 3 + .../MoveVarArgParameters.groovy | 3 + .../MoveVarArgParameters_after.groovy | 3 + .../NamedParametersOrder1.groovy | 4 + .../NamedParametersOrder1_after.groovy | 4 + .../NamedParametersOrder2.groovy | 3 + .../NamedParametersOrder2_after.groovy | 3 + .../NamedParametersOrder3.groovy | 4 + .../NamedParametersOrder3_after.groovy | 4 + .../NamedParametersRemove.groovy | 3 + .../NamedParametersRemove_after.groovy | 3 + .../changeSignature/OneNewParameter.groovy | 3 + .../OneNewParameter_after.groovy | 3 + .../changeSignature/RemoveParameter.groovy | 3 + .../RemoveParameter_after.groovy | 3 + resources/src/META-INF/IdeaPlugin.xml | 2 +- 48 files changed, 754 insertions(+), 214 deletions(-) create mode 100644 plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/ChangeVisibilityAndName.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/ChangeVisibilityAndName_after.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/InsertOptionalParameter.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/InsertOptionalParameter_after.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/InsertParameter.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/InsertParameter_after.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/MoveNamedParameters.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/MoveNamedParameters_after.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/MoveVarArgParameters.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/MoveVarArgParameters_after.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/NamedParametersOrder1.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/NamedParametersOrder1_after.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/NamedParametersOrder2.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/NamedParametersOrder2_after.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/NamedParametersOrder3.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/NamedParametersOrder3_after.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/NamedParametersRemove.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/NamedParametersRemove_after.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/OneNewParameter.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/OneNewParameter_after.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/RemoveParameter.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/RemoveParameter_after.groovy diff --git a/plugins/groovy/src/META-INF/plugin.xml b/plugins/groovy/src/META-INF/plugin.xml index 0eceb9c68bf3..8fc265d497d9 100644 --- a/plugins/groovy/src/META-INF/plugin.xml +++ b/plugins/groovy/src/META-INF/plugin.xml @@ -66,7 +66,7 @@ - + diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties index e66396ab806a..4f2e1a91b881 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties @@ -335,4 +335,4 @@ property.name.expected=Property name expected add.method.body=Add method body wildcards.are.not.allowed.in.extends.list=A super type may not specify a wildcard type method.doesnot.override.super=Method does not override method from its superclass -method.duplicate=Method with signature {0} is already defined in the class ''{1}'' +method.duplicate=Method with signature {0} is already defined in the class ''{1}'' diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java index 9372b283591f..485055cc628d 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java @@ -92,7 +92,10 @@ import org.jetbrains.plugins.groovy.lang.resolve.processors.PropertyResolverProc import org.jetbrains.plugins.groovy.overrideImplement.GroovyOverrideImplementUtil; import org.jetbrains.plugins.groovy.overrideImplement.quickFix.ImplementMethodsQuickFix; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Set; /** * @author ven @@ -1225,7 +1228,7 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator { private static void highlightInapplicableMethodUsage(GroovyResolveResult methodResolveResult, PsiElement place, AnnotationHolder holder, PsiMethod method, PsiType[] argumentTypes) { - PsiElement elementToHighlight = PsiUtil.getArgumentsElement(place); + PsiElement elementToHighlight = PsiUtil.getArgumentsList(place); if (elementToHighlight == null) { elementToHighlight = place; } @@ -1357,7 +1360,7 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator { final String typesString = buildArgTypesList(argumentTypes); String message = GroovyBundle.message("cannot.apply.method.or.closure", variable.getName(), typesString); - PsiElement elementToHighlight = PsiUtil.getArgumentsElement(place); + PsiElement elementToHighlight = PsiUtil.getArgumentsList(place); if (elementToHighlight == null) elementToHighlight = place; holder.createWarningAnnotation(elementToHighlight, message); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/parameterToEntry/ConvertParameterToMapEntryIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/parameterToEntry/ConvertParameterToMapEntryIntention.java index 4952796b0223..a9ee6b700a15 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/parameterToEntry/ConvertParameterToMapEntryIntention.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/parameterToEntry/ConvertParameterToMapEntryIntention.java @@ -201,7 +201,7 @@ public class ConvertParameterToMapEntryIntention extends Intention { } //Eliminate obsolete parameter from parameter list - list.removeParameter(param); + param.delete(); //Remove old arguments from occurrences diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyPsiElementFactory.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyPsiElementFactory.java index 005a21100e03..0c5ecb253d81 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyPsiElementFactory.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyPsiElementFactory.java @@ -106,7 +106,14 @@ public abstract class GroovyPsiElementFactory { public abstract GrClosableBlock createClosureFromText(String s) throws IncorrectOperationException; - public abstract GrParameter createParameter(String name, @Nullable String typeText, GroovyPsiElement context) throws IncorrectOperationException; + public GrParameter createParameter(String name, @Nullable String typeText, GroovyPsiElement context) throws IncorrectOperationException { + return createParameter(name, typeText, null, context); + } + + public abstract GrParameter createParameter(String name, + @Nullable String typeText, + String initializer, + GroovyPsiElement context) throws IncorrectOperationException; public abstract GrCodeReferenceElement createTypeOrPackageReference(String qName); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/arguments/GrArgumentList.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/arguments/GrArgumentList.java index 52634cbd83f7..76f67f31345e 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/arguments/GrArgumentList.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/arguments/GrArgumentList.java @@ -16,12 +16,12 @@ package org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments; +import com.intellij.psi.PsiElement; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.annotations.NotNull; -import com.intellij.util.IncorrectOperationException; -import com.intellij.psi.PsiElement; /** * @author ilyas @@ -48,5 +48,4 @@ public interface GrArgumentList extends GroovyPsiElement { GrExpression removeArgument(int argNumber); GrNamedArgument addNamedArgument(GrNamedArgument namedArgument); - -} +} \ No newline at end of file diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/params/GrParameterList.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/params/GrParameterList.java index 9faab910c527..851220f8a72e 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/params/GrParameterList.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/params/GrParameterList.java @@ -16,10 +16,8 @@ package org.jetbrains.plugins.groovy.lang.psi.api.statements.params; -import com.intellij.psi.PsiElement; import com.intellij.psi.PsiParameterList; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; /** @@ -32,9 +30,6 @@ public interface GrParameterList extends GroovyPsiElement, PsiParameterList { void addParameterToEnd(GrParameter parameter); - @Nullable - PsiElement removeParameter(GrParameter parameter); - void addParameterToHead(GrParameter parameter); int getParameterNumber(GrParameter parameter); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java index a0adb7c0d796..afe92a1243fe 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java @@ -236,20 +236,26 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory { return createDummyFile(s, false); } - public GrParameter createParameter(String name, @Nullable String typeText, GroovyPsiElement context) throws IncorrectOperationException { - String fileText; + public GrParameter createParameter(String name, @Nullable String typeText, @Nullable String initializer, GroovyPsiElement context) + throws IncorrectOperationException { + StringBuilder fileText = new StringBuilder(); + fileText.append("def foo("); if (typeText != null) { - fileText = "def foo(" + typeText + " " + name + ") {}"; - } else { - fileText = "def foo(" + name + ") {}"; + fileText.append(typeText).append(" "); } - GroovyFileImpl groovyFile = createDummyFile(fileText); + fileText.append(name); + if (initializer != null && initializer.length() > 0) { + fileText.append(" = ").append(initializer); + } + fileText.append("){}"); + GroovyFileImpl groovyFile = createDummyFile(fileText.toString()); groovyFile.setContext(context); ASTNode node = groovyFile.getFirstChild().getNode(); - if (node.getElementType() != GroovyElementTypes.METHOD_DEFINITION) + if (node.getElementType() != GroovyElementTypes.METHOD_DEFINITION) { throw new IncorrectOperationException("Invalid all text"); - return ((GrMethod) node.getPsi()).getParameters()[0]; + } + return ((GrMethod)node.getPsi()).getParameters()[0]; } public GrCodeReferenceElement createTypeOrPackageReference(String qName) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableBaseImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableBaseImpl.java index 6ad5628f787d..8e81d5f7cb0a 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableBaseImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrVariableBaseImpl.java @@ -92,9 +92,9 @@ public abstract class GrVariableBaseImpl extends GroovyBa PsiElement next = PsiUtil.getNextNonSpace(this); ASTNode parentNode = parent.getNode(); assert parentNode != null; - parentNode.removeChild(getNode()); + super.delete(); if (prev != null && prev.getNode() != null && prev.getNode().getElementType() == GroovyTokenTypes.mCOMMA) { - parentNode.removeChild(prev.getNode()); + prev.delete(); } else if (next instanceof LeafPsiElement && next.getNode() != null && next.getNode().getElementType() == GroovyTokenTypes.mCOMMA) { next.delete(); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/arguments/GrArgumentListImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/arguments/GrArgumentListImpl.java index bf685ac284ac..1e38bfc5e137 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/arguments/GrArgumentListImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/arguments/GrArgumentListImpl.java @@ -18,14 +18,12 @@ package org.jetbrains.plugins.groovy.lang.psi.impl.statements.arguments; import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiWhiteSpace; import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.impl.source.tree.TreeUtil; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; -import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mCOMMA; import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor; import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList; import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument; @@ -33,6 +31,8 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpres import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiElementImpl; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; +import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mCOMMA; + /** * @author ilyas */ @@ -104,34 +104,12 @@ public class GrArgumentListImpl extends GroovyPsiElementImpl implements GrArgume @Nullable public GrExpression removeArgument(final int argNumber) { - for (int i = 0; i < getExpressionArguments().length; i++) { - GrExpression expression = getExpressionArguments()[i]; - if (i == argNumber) { - final ASTNode exprNode = expression.getNode(); - final PsiElement prevElem = PsiUtil.getPrevNonSpace(expression); - final PsiElement nextElem = PsiUtil.getNextNonSpace(expression); - getNode().removeChild(exprNode); - if (nextElem != null && nextElem.getNode() != null && (nextElem.getNode().getElementType() == mCOMMA)) { - final PsiElement n = nextElem.getNextSibling(); - getNode().removeChild(nextElem.getNode()); - if (n != null && n instanceof PsiWhiteSpace) { - getNode().removeChild(n.getNode()); - } - } else if (prevElem != null) { - final ASTNode prev = prevElem.getNode(); - if (prev != null && prev.getElementType() == mCOMMA) { - final PsiElement p = prevElem.getPrevSibling(); - getNode().removeChild(prev); - getNode().removeChild(prevElem.getNode()); - if (p != null && p instanceof PsiWhiteSpace) { - getNode().removeChild(p.getNode()); - } - } - } - return expression; - } - } - return null; + GrExpression[] arguments = getExpressionArguments(); + if (argNumber < 0 || arguments.length <= argNumber) return null; + + GrExpression expression = arguments[argNumber]; + expression.delete(); + return expression; } public GrNamedArgument addNamedArgument(final GrNamedArgument namedArgument) { @@ -143,20 +121,23 @@ public class GrArgumentListImpl extends GroovyPsiElementImpl implements GrArgume final int exprCount = args.length; if (namedCount > 0) { anchor = namedArguments[namedCount - 1]; - } else if (exprCount > 0) { + } + else if (exprCount > 0) { anchor = args[exprCount - 1]; } if (anchor != null) { anchor = PsiUtil.getNextNonSpace(anchor); - } else { + } + else { anchor = getRightParen(); } if (anchor != null) { final ASTNode astNode = anchor.getNode(); getNode().addChild(newNode, astNode); - } else { + } + else { getNode().addChild(newNode); } @@ -166,35 +147,61 @@ public class GrArgumentListImpl extends GroovyPsiElementImpl implements GrArgume return namedArgument; } + @Override + public PsiElement addBefore(@NotNull PsiElement element, PsiElement anchor) throws IncorrectOperationException { + if (element instanceof GrNamedArgument || element instanceof GrExpression) { + if (anchor == null) anchor=getLastChild(); + if (anchor == null) { + return super.addBefore(element, anchor); + } + else { + anchor = anchor.getPrevSibling(); + } + while (anchor != null && !(anchor instanceof GrExpression) && !(anchor instanceof GrNamedArgument)) { + anchor = anchor.getPrevSibling(); + } + return addAfter(element, anchor); + } + return super.addBefore(element, anchor); + } + @Override public PsiElement addAfter(@NotNull PsiElement element, PsiElement anchor) throws IncorrectOperationException { - GrExpression[] params = getExpressionArguments(); - final ASTNode astNode = getNode(); + if (element instanceof GrExpression || element instanceof GrNamedArgument) { + GrExpression[] params = getExpressionArguments(); - if (anchor == null) anchor = getLeftParen(); + if (anchor == null) anchor = getLeftParen(); - PsiElement result; - if (params.length == 0) { + PsiElement result; result = super.addAfter(element, anchor); - } - else { - result = super.addAfter(element, anchor); - astNode.addLeaf(mCOMMA, ",", result.getNode()); - } + if (params.length != 0) { + final ASTNode astNode = getNode(); + if (anchor == getLeftParen()) { + astNode.addLeaf(mCOMMA, ",", result.getNextSibling().getNode()); + } + else { + astNode.addLeaf(mCOMMA, ",", result.getNode()); + } + } - CodeStyleManager.getInstance(getManager().getProject()).reformat(this); - return result; + CodeStyleManager.getInstance(getManager().getProject()).reformat(this); + return result; + } + return super.addAfter(element, anchor); } public void deleteChildInternal(@NotNull ASTNode child) { - ASTNode next = TreeUtil.skipElements(child.getTreeNext(), GroovyTokenTypes.WHITE_SPACES_OR_COMMENTS); - if (next != null && next.getElementType() == mCOMMA) { - deleteChildInternal(next); - } - else { + PsiElement element = child.getPsi(); + if (element instanceof GrExpression || element instanceof GrNamedArgument) { ASTNode prev = TreeUtil.skipElementsBack(child.getTreePrev(), GroovyTokenTypes.WHITE_SPACES_OR_COMMENTS); if (prev != null && prev.getElementType() == mCOMMA) { - deleteChildInternal(prev); + super.deleteChildInternal(prev); + } + else { + ASTNode next = TreeUtil.skipElements(child.getTreeNext(), GroovyTokenTypes.WHITE_SPACES_OR_COMMENTS); + if (next != null && next.getElementType() == mCOMMA) { + deleteChildInternal(next); + } } } super.deleteChildInternal(child); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/params/GrParameterListImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/params/GrParameterListImpl.java index e2d5d72ac588..40f1e1f805ce 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/params/GrParameterListImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/params/GrParameterListImpl.java @@ -20,16 +20,13 @@ import com.intellij.lang.ASTNode; import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiParameter; -import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.impl.PsiImplUtil; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterList; import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiElementImpl; -import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mCOMMA; @@ -103,40 +100,24 @@ public class GrParameterListImpl extends GroovyPsiElementImpl implements GrParam return -1; } - @Nullable - public PsiElement removeParameter(final GrParameter toRemove) { - final ASTNode astNode = getNode(); - for (GrParameter param : getParameters()) { - if (param == toRemove) { - final ASTNode paramNode = param.getNode(); - assert paramNode != null; - PsiElement prevSibling = PsiUtil.getPrevNonSpace(param); - astNode.removeChild(paramNode); - if (prevSibling != null) { - final ASTNode prev = prevSibling.getNode(); - if (prev != null && prev.getElementType() == mCOMMA) { - astNode.removeChild(prev); - } - } - return toRemove; - } - } - return null; - } - @Override public PsiElement addAfter(@NotNull PsiElement element, PsiElement anchor) throws IncorrectOperationException { GrParameter[] params = getParameters(); - final ASTNode astNode = getNode(); if (params.length == 0) { - astNode.addChild(element.getNode()); + add(element); } else { - astNode.addLeaf(mCOMMA, ",", (element = super.addAfter(element, anchor)).getNode()); + element = super.addAfter(element, anchor); + final ASTNode astNode = getNode(); + if (anchor != null) { + astNode.addLeaf(mCOMMA, ",", element.getNode()); + } + else { + astNode.addLeaf(mCOMMA, ",", element.getNextSibling().getNode()); + } } - CodeStyleManager.getInstance(getManager().getProject()).reformat(this); return element; } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureSignatureUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureSignatureUtil.java index f51857ce6d14..30c6d14b7217 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureSignatureUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureSignatureUtil.java @@ -34,7 +34,10 @@ import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature; import org.jetbrains.plugins.groovy.lang.psi.impl.GrTupleType; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; /** * @author Maxim.Medvedev @@ -184,6 +187,15 @@ public class GrClosureSignatureUtil { return count; } + public static class ArgInfo { + public List args; + public final boolean isMultiArg; + + public ArgInfo(List args, boolean multiArg) { + this.args = args; + isMultiArg = multiArg; + } + } /** * Returns array of lists which contain psiElements mapped to parameters * @@ -192,12 +204,12 @@ public class GrClosureSignatureUtil { * @return null if signature can not be applied to this argumentList */ @Nullable - public static List[] mapParametersToArguments(@NotNull GrClosureSignature signature, + public static ArgInfo[] mapParametersToArguments(@NotNull GrClosureSignature signature, @NotNull GrArgumentList list, PsiManager manager, GlobalSearchScope scope) { - List[] map = map(signature, list, manager, scope); + ArgInfo[] map = map(signature, list, manager, scope); if (map != null) return map; if (signature.isVarargs()) { @@ -207,7 +219,7 @@ public class GrClosureSignatureUtil { } @Nullable - private static List[] map(@NotNull GrClosureSignature signature, @NotNull GrArgumentList list, PsiManager manager, GlobalSearchScope scope) { + private static ArgInfo[] map(@NotNull GrClosureSignature signature, @NotNull GrArgumentList list, PsiManager manager, GlobalSearchScope scope) { final GrExpression[] args = list.getExpressionArguments(); final GrNamedArgument[] namedArgs = list.getNamedArguments(); boolean hasNamedArgs = namedArgs.length > 0; @@ -215,7 +227,7 @@ public class GrClosureSignatureUtil { GrClosureParameter[] params = signature.getParameters(); - List[] map = new List[params.length]; + ArgInfo[] map = new ArgInfo[params.length]; int paramLength = params.length; if (hasNamedArgs) { @@ -223,7 +235,7 @@ public class GrClosureSignatureUtil { PsiType type = params[0].getType(); if (InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_UTIL_MAP)) { paramLength--; - map[0] = Arrays.asList(namedArgs); + map[0] = new ArgInfo(Arrays.asList(namedArgs), true); } else { return null; @@ -240,18 +252,20 @@ public class GrClosureSignatureUtil { optional = args.length - notOptional; if (hasNamedArgs) curParam++; for (int curArg = 0; curArg < args.length; curArg++, curParam++) { - while (optional == 0 && curParam < paramLength && params[curParam].isOptional()) { + while (optional == 0 && curParam < params.length && params[curParam].isOptional()) { + map[curParam] = new ArgInfo(Collections.emptyList(), false); curParam++; } - if (curParam == paramLength) return null; + if (curParam == params.length) return null; if (params[curParam].isOptional()) optional--; if (TypesUtil.isAssignableByMethodCallConversion(params[curParam].getType(), args[curArg].getType(), manager, scope)) { - map[curParam] = Collections.singletonList(args[curArg]); + map[curParam] = new ArgInfo(Collections.singletonList(args[curArg]), false); } else { return null; } } + for (; curParam < params.length; curParam++) map[curParam] = new ArgInfo(Collections.emptyList(), false); return map; } @@ -281,14 +295,14 @@ public class GrClosureSignatureUtil { } @Nullable - public List[] map() { + public ArgInfo[] map() { boolean hasNamedArgs = namedArgs.length > 0; - List[] map = new List[params.length]; + ArgInfo[] map = new ArgInfo[params.length]; if (hasNamedArgs) { if (params.length == 0) return null; PsiType type = params[0].getType(); if (InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_UTIL_MAP)) { - map[0] = Arrays.asList(namedArgs); + map[0] = new ArgInfo(Arrays.asList(namedArgs), true); } else { return null; @@ -303,7 +317,7 @@ public class GrClosureSignatureUtil { } @Nullable - private List[] mapInternal(int curParam, int curArg, boolean skipOptionals, int notOptional, List[] map) { + private ArgInfo[] mapInternal(int curParam, int curArg, boolean skipOptionals, int notOptional, ArgInfo[] map) { if (notOptional > args.length - curArg) return null; if (notOptional == args.length - curArg) skipOptionals = true; @@ -316,31 +330,31 @@ public class GrClosureSignatureUtil { if (params[curParam].isOptional()) { if (TypesUtil.isAssignable(params[curParam].getType(), types[curArg], manager, scope)) { - List[] copy = mapInternal(curParam + 1, curArg + 1, false, notOptional, copyMap(map)); + ArgInfo[] copy = mapInternal(curParam + 1, curArg + 1, false, notOptional, copyMap(map)); if (copy != null) return copy; } skipOptionals = true; } else { if (!TypesUtil.isAssignableByMethodCallConversion(params[curParam].getType(), types[curArg], manager, scope)) return null; - map[curParam] = Collections.singletonList(args[curArg]); + map[curParam] = new ArgInfo(Collections.singletonList(args[curArg]), false); notOptional--; curArg++; curParam++; } } - map[paramLength] = new ArrayList(args.length - curArg); + map[paramLength] = new ArgInfo(new ArrayList(args.length - curArg), true); for (; curArg < args.length; curArg++) { if (!TypesUtil.isAssignableByMethodCallConversion(vararg, types[curArg], manager, scope)) return null; - map[paramLength].add(args[curArg]); + map[paramLength].args.add(args[curArg]); } return map; } - private static List[] copyMap(List[] map) { - List[] copy = new List[map.length]; + private static ArgInfo[] copyMap(ArgInfo[] map) { + ArgInfo[] copy = new ArgInfo[map.length]; System.arraycopy(map, 0, copy, 0, map.length); return copy; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java index eae83b497e5b..a4f0001101d4 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java @@ -147,14 +147,13 @@ public class PsiUtil { } @Nullable - public static GroovyPsiElement getArgumentsElement(PsiElement methodRef) { + public static GrArgumentList getArgumentsList(PsiElement methodRef) { PsiElement parent = methodRef.getParent(); - if (parent instanceof GrMethodCallExpression) { - return ((GrMethodCallExpression)parent).getArgumentList(); - } else if (parent instanceof GrApplicationStatement) { - return ((GrApplicationStatement)parent).getArgumentList(); - } else if (parent instanceof GrNewExpression) { - return ((GrNewExpression)parent).getArgumentList(); + if (parent instanceof GrCall) { + return ((GrCall)parent).getArgumentList(); + } + if (parent instanceof GrAnonymousClassDefinition) { + return ((GrAnonymousClassDefinition)parent).getArgumentListGroovy(); } return null; } @@ -751,4 +750,17 @@ public class PsiUtil { return method.getReturnType(); } } + + public static boolean isMethodUsage(PsiElement element) { + if (element instanceof GrEnumConstant) return true; + if (!(element instanceof GrReferenceElement)) return false; + PsiElement parent = element.getParent(); + if (parent instanceof GrCall) { + return true; + } + else if (parent instanceof GrAnonymousClassDefinition) { + return element.equals(((GrAnonymousClassDefinition)parent).getBaseClassReferenceGroovy()); + } + return false; + } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties index c8e8f0e18434..fc06305f3201 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties @@ -104,7 +104,7 @@ changeSignature.refactoring.name=Change Signature column.name.type=Type column.name.name=Name column.name.default.initializer=Default initializer -column.name.default.value=Default value\ +column.name.default.value=Default value method.duplicate=Method with signature {0} is already defined in {1} replace.setter.for.property=The default setter for property ''{0}'' will be overwritten replace.getter.for.property=The default getter for property ''{0}'' will be overwritten \ No newline at end of file diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChageSignatureUsageSearcher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChageSignatureUsageSearcher.java index 860f000f17a7..824e733fd6f4 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChageSignatureUsageSearcher.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChageSignatureUsageSearcher.java @@ -34,11 +34,10 @@ import com.intellij.usageView.UsageViewUtil; import com.intellij.util.containers.HashSet; import org.jetbrains.plugins.groovy.GroovyFileType; import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocTagValueToken; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousClassDefinition; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; -import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement; +import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature; +import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil; +import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import java.util.ArrayList; import java.util.Arrays; @@ -202,8 +201,12 @@ class GrChageSignatureUsageSearcher { boolean isToCatchExceptions = isToThrowExceptions && needToCatchExceptions(RefactoringUtil.getEnclosingMethod(element)); //todo check for applicability of arguments to method - if (isMethodUsage(element)) { - result.add(new GrMethodCallUsageInfo(element, isToModifyArgs, isToCatchExceptions)); + if (PsiUtil.isMethodUsage(element)) { + GrClosureSignature signature = GrClosureSignatureUtil.createSignature(method); + GrClosureSignatureUtil.ArgInfo[] map = GrClosureSignatureUtil + .mapParametersToArguments(signature, PsiUtil.getArgumentsList(element), method.getManager(), method.getResolveScope()); + result.add( + new GrMethodCallUsageInfo(element, GrClosureSignatureUtil.createSignature(method), isToModifyArgs, isToCatchExceptions, map)); } else if (element instanceof GrDocTagValueToken) { result.add(new UsageInfo(ref.getElement())); @@ -294,16 +297,4 @@ class GrChageSignatureUsageSearcher { } } - static boolean isMethodUsage(PsiElement element) { - if (element instanceof GrEnumConstant) return true; - if (!(element instanceof GrCodeReferenceElement)) return false; - PsiElement parent = element.getParent(); - if (parent instanceof GrCall) { - return true; - } - else if (parent instanceof GrAnonymousClassDefinition) { - return element.equals(((GrAnonymousClassDefinition)parent).getBaseClassReferenceGroovy()); - } - return false; - } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeInfoImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeInfoImpl.java index 02a6264a7f66..9d5713fc666c 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeInfoImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeInfoImpl.java @@ -191,7 +191,7 @@ class GrChangeInfoImpl implements JavaChangeInfo { return false; } - public PsiMethod getMethod() { + public GrMethod getMethod() { return method; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.form b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.form index 9036d53d1a4a..88b9a50ad584 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.form +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.form @@ -91,14 +91,14 @@ - + - + diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java index 2be7860396f5..0b5e71420422 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java @@ -28,7 +28,7 @@ import com.intellij.refactoring.util.CanonicalTypes; import com.intellij.refactoring.util.CommonRefactoringUtil; import com.intellij.ui.EditorTextField; import com.intellij.ui.TableUtil; -import com.intellij.util.ui.Table; +import com.intellij.ui.table.JBTable; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.debugger.fragments.GroovyCodeFragment; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; @@ -55,7 +55,7 @@ public class GrChangeSignatureDialog extends RefactoringDialog { private JRadioButton myProtectedRadioButton; private JRadioButton myPrivateRadioButton; private JPanel myParametersPanel; - private Table myParameterTable; + private JBTable myParameterTable; private JButton myAddButton; private JButton myRemoveButton; private JButton myMoveUpButton; @@ -80,9 +80,12 @@ public class GrChangeSignatureDialog extends RefactoringDialog { myAddButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int selectedColumn = myParameterTable.getSelectedColumn(); + if (selectedColumn < 0) selectedColumn = 0; myParameterModel.addRow(); myParameterTable.setRowSelectionInterval(myParameterModel.getRowCount() - 1, myParameterModel.getRowCount() - 1); myParameterTable.setColumnSelectionInterval(selectedColumn, selectedColumn); + updateSignature(); + myParameterTable.requestFocus(); } }); myRemoveButton.addActionListener(new ActionListener() { @@ -96,6 +99,8 @@ public class GrChangeSignatureDialog extends RefactoringDialog { if (myParameterModel.getRowCount() == 0) return; myParameterTable.setRowSelectionInterval(selectedRow, selectedRow); myParameterTable.setColumnSelectionInterval(selectedColumn, selectedColumn); + updateSignature(); + myParameterTable.requestFocus(); } }); @@ -106,6 +111,8 @@ public class GrChangeSignatureDialog extends RefactoringDialog { myParameterModel.exchangeRows(selectedRow, selectedRow - 1); myParameterTable.setRowSelectionInterval(selectedRow - 1, selectedRow - 1); myParameterTable.setColumnSelectionInterval(selectedColumn, selectedColumn); + updateSignature(); + myParameterTable.requestFocus(); } }); @@ -116,6 +123,8 @@ public class GrChangeSignatureDialog extends RefactoringDialog { myParameterModel.exchangeRows(selectedRow, selectedRow + 1); myParameterTable.setRowSelectionInterval(selectedRow + 1, selectedRow + 1); myParameterTable.setColumnSelectionInterval(selectedColumn, selectedColumn); + updateSignature(); + myParameterTable.requestFocus(); } }); } @@ -157,7 +166,7 @@ public class GrChangeSignatureDialog extends RefactoringDialog { private void createParametersModel() { myParameterModel = new GrParameterTableModel(myMethod, this, myProject); - myParameterTable = new Table(myParameterModel); + myParameterTable = new JBTable(myParameterModel); myParameterTable.setCellSelectionEnabled(true); myParameterTable.getColumnModel().getColumn(0).setCellRenderer(new CodeFragmentTableCellRenderer(myProject)); @@ -228,7 +237,7 @@ public class GrChangeSignatureDialog extends RefactoringDialog { builder.append(typeFragment != null ? typeFragment.getText().trim() : GrModifier.DEF).append(' '); final GroovyCodeFragment nameFragment = info.getNameFragment(); builder.append(nameFragment != null ? nameFragment.getText().trim() : ""); - final GroovyCodeFragment defaultInitializer = info.getDefaultInitializer(); + final GroovyCodeFragment defaultInitializer = info.getDefaultInitializerFragment(); final String defaultInitializerText = defaultInitializer != null ? defaultInitializer.getText().trim() : ""; if (defaultInitializerText.length() > 0) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java index 66acdb5c03a1..56505ce2ef75 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java @@ -23,16 +23,15 @@ import com.intellij.psi.PsiMethod; import com.intellij.refactoring.BaseRefactoringProcessor; import com.intellij.refactoring.changeSignature.ChangeSignatureUsageProcessor; import com.intellij.refactoring.changeSignature.ChangeSignatureViewDescriptor; +import com.intellij.refactoring.util.MoveRenameUsageInfo; import com.intellij.usageView.UsageInfo; import com.intellij.usageView.UsageViewDescriptor; import com.intellij.util.containers.HashSet; import com.intellij.util.containers.MultiMap; +import com.intellij.util.containers.hash.HashMap; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; +import java.util.*; /** * @author Maxim.Medvedev @@ -63,9 +62,32 @@ public class GrChangeSignatureProcessor extends BaseRefactoringProcessor { for (ChangeSignatureUsageProcessor processor : processors) { infos.addAll(Arrays.asList(processor.findUsages(myChangeInfo))); } + + infos = filterUsages(infos); return infos.toArray(new UsageInfo[infos.size()]); } + private static List filterUsages(List infos) { + Map moveRenameInfos = new HashMap(); + Set usedElements = new com.intellij.util.containers.hash.HashSet(); + + List result = new ArrayList(infos.size() / 2); + for (UsageInfo info : infos) { + PsiElement element = info.getElement(); + if (info instanceof MoveRenameUsageInfo) { + if (usedElements.contains(element)) continue; + moveRenameInfos.put(element, (MoveRenameUsageInfo)info); + } + else { + moveRenameInfos.remove(element); + usedElements.add(element); + result.add(info); + } + } + result.addAll(moveRenameInfos.values()); + return result; + } + @Override protected void refreshElements(PsiElement[] elements) { boolean condition = elements.length == 1 && elements[0] instanceof PsiMethod; @@ -77,21 +99,15 @@ public class GrChangeSignatureProcessor extends BaseRefactoringProcessor { protected void performRefactoring(UsageInfo[] usages) { changeMethod(); for (UsageInfo usage : usages) { - - for (ChangeSignatureUsageProcessor processor : GrChangeSignatureUsageProcessor.EP_NAME.getExtensions()) { + for (ChangeSignatureUsageProcessor processor : ChangeSignatureUsageProcessor.EP_NAME.getExtensions()) { if (processor.processUsage(myChangeInfo, usage, false, usages)) break; } } } private void changeMethod() { - final PsiMethod method = myChangeInfo.getMethod(); - if (myChangeInfo.isChangeName()) { - method.setName(myChangeInfo.getNewName()); - } - - if (myChangeInfo.isChangeVisibility()) { - method.getModifierList().setModifierProperty(myChangeInfo.getVisibilityModifier(), true); + for (ChangeSignatureUsageProcessor processor : ChangeSignatureUsageProcessor.EP_NAME.getExtensions()) { + if (processor.processPrimaryMethod(myChangeInfo)) break; } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java index da261bdbec40..01168bebae00 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java @@ -15,28 +15,42 @@ */ package org.jetbrains.plugins.groovy.refactoring.changeSignature; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Ref; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiMethod; +import com.intellij.psi.codeStyle.CodeStyleManager; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.changeSignature.ChangeInfo; import com.intellij.refactoring.changeSignature.ChangeSignatureUsageProcessor; import com.intellij.refactoring.changeSignature.JavaChangeInfo; import com.intellij.refactoring.changeSignature.JavaParameterInfo; import com.intellij.usageView.UsageInfo; +import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.MultiMap; +import com.intellij.util.containers.hash.HashSet; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList; import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall; -import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterList; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil; import java.util.List; +import java.util.Set; /** * @author Maxim.Medvedev */ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProcessor { + private static final Logger LOG = + Logger.getInstance("#org.jetbrains.plugins.groovy.refactoring.changeSignature.GrChangeSignatureUsageProcessor"); + public UsageInfo[] findUsages(ChangeInfo info) { if (info instanceof JavaChangeInfo) { return new GrChageSignatureUsageSearcher((JavaChangeInfo)info).findUsages(); @@ -54,19 +68,65 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc } public boolean processPrimaryMethod(ChangeInfo changeInfo) { - return false; + if (!(changeInfo instanceof GrChangeInfoImpl)) return false; + + GrChangeInfoImpl grInfo = (GrChangeInfoImpl)changeInfo; + GrMethod method = grInfo.getMethod(); + + if (grInfo.isChangeName()) { + method.setName(grInfo.getNewName()); + } + + if (grInfo.isVisibilityChanged()) { + method.getModifierList().setModifierProperty(grInfo.getVisibilityModifier(), true); + } + + if (grInfo.isParameterSetOrOrderChanged()) { + JavaParameterInfo[] newParameters = grInfo.getNewParameters(); + GrParameterList parameterList = method.getParameterList(); + GrParameter[] oldParameters = parameterList.getParameters(); + + + PsiElement anchor = null; + GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(method.getProject()); + + for (JavaParameterInfo newParameter : newParameters) { + int index = newParameter.getOldIndex(); + if (index < 0) { + GrParameter grParameter = + factory.createParameter(newParameter.getName(), newParameter.getTypeText(), getInitializer(newParameter), parameterList); + anchor = parameterList.addAfter(grParameter, anchor); + } + else { + GrParameter grParameter = oldParameters[index]; + anchor = parameterList.addAfter(grParameter, anchor); + } + } + + for (GrParameter oldParameter : oldParameters) { + oldParameter.delete(); + } + CodeStyleManager.getInstance(parameterList.getProject()).reformat(parameterList); + } + return true; + } + + @Nullable + private static String getInitializer(JavaParameterInfo newParameter) { + if (newParameter instanceof GrParameterInfo) return ((GrParameterInfo)newParameter).getDefaultInitializer(); + return null; } public boolean processUsage(ChangeInfo changeInfo, UsageInfo usageInfo, boolean beforeMethodChange, UsageInfo[] usages) { if (!(changeInfo instanceof JavaChangeInfo)) return false; + PsiElement element = usageInfo.getElement(); if (element == null) return false; if (usageInfo instanceof GrMethodCallUsageInfo) { processMethodUsage(element, ((JavaChangeInfo)changeInfo), ((GrMethodCallUsageInfo)usageInfo).isToChangeArguments(), - ((GrMethodCallUsageInfo)usageInfo).isToCatchExceptions(), ((JavaChangeInfo)changeInfo).getMethod()); - GrCall call = (GrCall)element; - GrArgumentList argumentList = call.getArgumentList(); + ((GrMethodCallUsageInfo)usageInfo).isToCatchExceptions(), + ((JavaChangeInfo)changeInfo).getMethod(), ((GrMethodCallUsageInfo)usageInfo).getMapToArguments()); return true; } return false; @@ -76,61 +136,107 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc JavaChangeInfo changeInfo, boolean toChangeArguments, boolean toCatchExceptions, - PsiMethod method) { + PsiMethod method, GrClosureSignatureUtil.ArgInfo[] map) { + if (map == null) return; if (changeInfo.isNameChanged()) { - if (element instanceof GrCodeReferenceElement) { - ((GrCodeReferenceElement)element).bindToElement(method); + if (element instanceof GrReferenceElement) { + element = ((GrReferenceElement)element).bindToElement(method); } } if (toChangeArguments) { JavaParameterInfo[] parameters = changeInfo.getNewParameters(); GrArgumentList argumentList = ((GrCall)element.getParent()).getArgumentList(); if (argumentList == null) return; - List[] map = GrClosureSignatureUtil - .mapParametersToArguments(GrClosureSignatureUtil.createSignature(method), argumentList, element.getManager(), - method.getResolveScope()); + Set argsToDelete = new HashSet(map.length * 2); + for (GrClosureSignatureUtil.ArgInfo argInfo : map) { + argsToDelete.addAll(argInfo.args); + } - if (map == null) return; - PsiElement child = argumentList.getFirstChild(); - if (child != null) { - argumentList.deleteChildRange(child, argumentList.getLastChild()); + for (JavaParameterInfo parameter : parameters) { + int index = parameter.getOldIndex(); + if (index >= 0) { + argsToDelete.removeAll(map[index].args); + } + } + + for (PsiElement arg : argsToDelete) { + arg.delete(); } GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(element.getProject()); + + boolean skipOptionals = false; + PsiElement anchor = null; for (int i = 0; i < parameters.length; i++) { JavaParameterInfo parameter = parameters[i]; int index = parameter.getOldIndex(); if (index >= 0) { - List arguments = map[index]; - if (arguments.size() == 1) { - PsiElement arg = arguments.iterator().next(); - if (i > 0 && arg instanceof GrNamedArgument) { - arg = factory.createExpressionFromText("[" + arg.getText() + "]"); - } - argumentList.add(arg); - } - else if (arguments.size() > 1) { - if (i == 0 && arguments.iterator().next() instanceof GrNamedArgument || - i == parameters.length - 1 && parameter.isVarargType()) { - for (PsiElement argument : arguments) { - argumentList.add(argument); - } - } - else { + GrClosureSignatureUtil.ArgInfo argInfo = map[index]; + List arguments = argInfo.args; + if (argInfo.isMultiArg) { //arguments for Map and varArg + if ((i != 0 || !(arguments.size() > 0 && arguments.iterator().next() instanceof GrNamedArgument)) && + (i != parameters.length - 1 || !parameter.isVarargType())) { StringBuilder argText = new StringBuilder(); argText.append("["); for (PsiElement argument : arguments) { argText.append(argument.getText()).append(", "); + argument.delete(); } argText.replace(argText.length() - 2, argText.length(), "]"); - argumentList.add(factory.createExpressionFromText(argText.toString())); + if (!(arguments.size() > 0 && arguments.iterator().next() instanceof GrNamedArgument)) { + argText.append(" as ").append(parameter.getTypeText()); + } + anchor = argumentList.addAfter(factory.createExpressionFromText(argText.toString()), anchor); } } - else if (i < parameters.length - 1) { - argumentList.add(factory.createExpressionFromText("[]")); + else { //arguments for simple parameters + if (arguments.size() == 1) { //arg exists + PsiElement arg = arguments.iterator().next(); + PsiElement curArg = getNextArg(anchor, argumentList); + if (curArg == arg) { + anchor = arg; + } + else { + anchor = argumentList.addBefore(arg, anchor); + } + } + else { //arg is skipped. Parameter is optional + skipOptionals = true; + } } } + else { + if (skipOptionals && isParameterOptional(parameter)) continue; + GrExpression fromText = null; + try { + fromText = factory.createExpressionFromText(parameter.getDefaultValue()); + } + catch (IncorrectOperationException e) { + LOG.error(e.getMessage()); + } + anchor = argumentList.addBefore(fromText, getNextArg(anchor, argumentList)); + } } + + CodeStyleManager.getInstance(argumentList.getProject()).reformat(argumentList); } } + + @Nullable + private static PsiElement getNextArg(PsiElement anchor, GrArgumentList argumentList) { + if (anchor == null) { + anchor = argumentList.getFirstChild(); + if (anchor == null) return null; + if (anchor instanceof GrExpression) return anchor; + } + return PsiTreeUtil.getNextSiblingOfType(anchor, GrExpression.class); + } + + private static boolean wasParameterOptional(JavaParameterInfo parameterInfo) { + return parameterInfo instanceof GrParameterInfo && ((GrParameterInfo)parameterInfo).wasOptional(); + } + + private static boolean isParameterOptional(JavaParameterInfo parameterInfo) { + return parameterInfo instanceof GrParameterInfo && ((GrParameterInfo)parameterInfo).isOptional(); + } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodCallUsageInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodCallUsageInfo.java index 084ed8209197..b077913edf33 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodCallUsageInfo.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodCallUsageInfo.java @@ -26,6 +26,8 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpres import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrCallExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant; +import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature; +import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil; /** * @author Maxim.Medvedev @@ -34,6 +36,7 @@ public class GrMethodCallUsageInfo extends UsageInfo { private final boolean myToChangeArguments; private final boolean myToCatchExceptions; private final PsiMethod myReferencedMethod; + private GrClosureSignatureUtil.ArgInfo[] myMapToArguments; public boolean isToCatchExceptions() { return myToCatchExceptions; @@ -43,10 +46,14 @@ public class GrMethodCallUsageInfo extends UsageInfo { return myToChangeArguments; } - public GrMethodCallUsageInfo(PsiElement element, boolean isToChangeArguments, boolean isToCatchExceptions) { + public GrMethodCallUsageInfo(PsiElement element, + GrClosureSignature oldSignature, + boolean isToChangeArguments, + boolean isToCatchExceptions, GrClosureSignatureUtil.ArgInfo[] mapToArguments) { super(element); myToChangeArguments = isToChangeArguments; myToCatchExceptions = isToCatchExceptions; + myMapToArguments = mapToArguments; myReferencedMethod = resolveMethod(element); } @@ -77,5 +84,7 @@ public class GrMethodCallUsageInfo extends UsageInfo { return myReferencedMethod; } - + public GrClosureSignatureUtil.ArgInfo[] getMapToArguments() { + return myMapToArguments; + } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java index 9d38f89e9786..e0aba02b1f50 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java @@ -35,6 +35,8 @@ public class GrParameterInfo implements JavaParameterInfo { private GroovyCodeFragment myDefaultInitializer; private final int myPosition; private CanonicalTypes.Type myTypeWrapper; + private boolean myWasOptional = false; + private boolean myWasVarArg = false; public GrParameterInfo(GrParameter parameter, int position) { myPosition = position; @@ -43,6 +45,7 @@ public class GrParameterInfo implements JavaParameterInfo { final PsiType type = parameter.getDeclaredType(); if (type != null) { myType = JavaPsiFacade.getElementFactory(project).createTypeCodeFragment(type.getCanonicalText(), parameter, true, true); + myWasVarArg = myType instanceof PsiArrayType; } else { myType = JavaPsiFacade.getElementFactory(project).createTypeCodeFragment("", parameter, true, true); @@ -55,6 +58,7 @@ public class GrParameterInfo implements JavaParameterInfo { myDefaultInitializer = new GroovyCodeFragment(project, ""); } myDefaultValue = new GroovyCodeFragment(project, ""); + myWasOptional = parameter.isOptional(); } public GrParameterInfo(Project project, PsiElement context) { @@ -77,7 +81,7 @@ public class GrParameterInfo implements JavaParameterInfo { return myType; } - public GroovyCodeFragment getDefaultInitializer() { + public GroovyCodeFragment getDefaultInitializerFragment() { return myDefaultInitializer; } @@ -129,6 +133,22 @@ public class GrParameterInfo implements JavaParameterInfo { } public boolean isVarargType() { - return getTypeText().endsWith("..."); + return getTypeText().endsWith("...") || getTypeText().endsWith("[]"); + } + + public boolean wasOptional() { + return myWasOptional; + } + + public boolean isOptional() { + return getDefaultInitializer().length() > 0; + } + + public String getDefaultInitializer() { + return myDefaultInitializer.getText().trim(); + } + + public boolean wasWasVarArg() { + return myWasVarArg; } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterTableModel.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterTableModel.java index 14086babd758..ccaa2e22ad20 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterTableModel.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterTableModel.java @@ -86,7 +86,7 @@ public class GrParameterTableModel extends AbstractTableModel implements RowEdit case 1: return info.getNameFragment(); case 2: - return info.getDefaultInitializer(); + return info.getDefaultInitializerFragment(); case 3: return info.getDefaultValueFragment(); default: diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java new file mode 100644 index 000000000000..bd492ab44a41 --- /dev/null +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java @@ -0,0 +1,280 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.groovy.refactoring.changeSignature; + +import com.intellij.codeInsight.TargetElementUtilBase; +import com.intellij.psi.*; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.refactoring.changeSignature.ThrownExceptionInfo; +import com.intellij.refactoring.util.CanonicalTypes; +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; +import org.jetbrains.plugins.groovy.util.TestUtils; + +import java.util.Arrays; + +/** + * @author Maxim.Medvedev + */ +public class ChangeSignatureTest extends LightCodeInsightFixtureTestCase { + + @Override + protected String getBasePath() { + return TestUtils.getTestDataPath() + "refactoring/changeSignature/"; + } + + public void testOneNewParameter() throws Exception { + doTest(null, new GrParameterInfo[]{ + new SimpleInfo("p", -1, "\"5\"", null, createType(CommonClassNames.JAVA_LANG_STRING)) + }); + } + + public void testRemoveParameter() throws Exception { + doTest(null, new GrParameterInfo[0]); + } + + public void testInsertParameter() throws Exception { + doTest(null, new GrParameterInfo[]{ + new SimpleInfo(0), + new SimpleInfo("p", -1, "5", "-3", createType("int")), + new SimpleInfo(1) + }); + } + + public void testInsertOptionalParameter() throws Exception { + doTest(null, new GrParameterInfo[]{ + new SimpleInfo(0), + new SimpleInfo(1), + new SimpleInfo("p", -1, "5", "-3", createType("int")) + }); + } + + public void testNamedParametersRemove() throws Exception { + doTest(null, new GrParameterInfo[]{ + new SimpleInfo(1), + new SimpleInfo(2) + }); + } + + public void testNamedParametersOrder1() throws Exception { + doTest(null, new GrParameterInfo[] { + new SimpleInfo(0), + new SimpleInfo(2) + }); + } + + public void testNamedParametersOrder2() throws Exception { + doTest(null, new GrParameterInfo[]{ + new SimpleInfo(0), + new SimpleInfo("p", -1, "5", null, createType("int")), + new SimpleInfo(2), + }); + } + + public void testNamedParametersOrder3() throws Exception { + doTest(null, new GrParameterInfo[] { + new SimpleInfo(0), + new SimpleInfo(2), + new SimpleInfo("p", -1, "5", null, createType("int")), + }); + } + + public void testMoveNamedParameters() throws Exception { + doTest(null, new GrParameterInfo[] { + new SimpleInfo(1), + new SimpleInfo(0) + }); + } + + public void testMoveVarArgParameters() throws Exception { + doTest(null, new GrParameterInfo[] { + new SimpleInfo(1), + new SimpleInfo(0) + }); + } + + public void testChangeVisibilityAndName() throws Exception { + doTest("protected", "newName", null, new GrParameterInfo[]{new SimpleInfo(0)}, new ThrownExceptionInfo[0], false); + } + + private PsiType createType(String typeText) { + return JavaPsiFacade.getElementFactory(getProject()).createTypeByFQClassName(typeText, GlobalSearchScope.allScope(getProject())); + } + + + private void doTest(String newReturnType, GrParameterInfo[] parameterInfos) throws Exception { + doTest("public", null, newReturnType, parameterInfos, new ThrownExceptionInfo[0], false); + } + + private void doTest(String newReturnType, GrParameterInfo[] parameterInfos, final boolean generateDelegate) throws Exception { + doTest("public", null, newReturnType, parameterInfos, new ThrownExceptionInfo[0], generateDelegate); + } + + private void doTest(String newVisibility, + String newName, + String newReturnType, + GrParameterInfo[] parameterInfo, + ThrownExceptionInfo[] exceptionInfo, + final boolean generateDelegate) throws Exception { + doTest(newVisibility, newName, newReturnType, new SimpleParameterGen(parameterInfo), new SimpleExceptionsGen(exceptionInfo), + generateDelegate); + } + + private void doTest(String newVisibility, String newName, @NonNls String newReturnType, GenParams gen, final boolean generateDelegate) + throws Exception { + doTest(newVisibility, newName, newReturnType, gen, new SimpleExceptionsGen(), generateDelegate); + } + + private void doTest(String newVisibility, + String newName, + String newReturnType, + GenParams genParams, + GenExceptions genExceptions, + final boolean generateDelegate) throws Exception { + myFixture.configureByFile(getTestName(false) + ".groovy"); + final PsiElement targetElement = + TargetElementUtilBase.findTargetElement(myFixture.getEditor(), TargetElementUtilBase.ELEMENT_NAME_ACCEPTED); + assertTrue(" is not on method name", targetElement instanceof GrMethod); + GrMethod method = (GrMethod)targetElement; + final PsiElementFactory factory = JavaPsiFacade.getInstance(getProject()).getElementFactory(); + PsiType newType = newReturnType != null ? factory.createTypeFromText(newReturnType, method) : method.getReturnType(); + GrChangeInfoImpl changeInfo = + new GrChangeInfoImpl(method, newVisibility, CanonicalTypes.createTypeWrapper(newType), newName != null ? newName : method.getName(), + Arrays.asList(genParams.genParams(method))); + new GrChangeSignatureProcessor(getProject(), changeInfo).run(); + myFixture.checkResultByFile(getTestName(false) + "_after.groovy"); + } + + + private interface GenParams { + GrParameterInfo[] genParams(GrMethod method) throws IncorrectOperationException; + } + + private static class SimpleParameterGen implements GenParams { + private final GrParameterInfo[] myInfos; + + private SimpleParameterGen(GrParameterInfo[] infos) { + myInfos = infos; + } + + public GrParameterInfo[] genParams(GrMethod method) { + GrParameter[] params = method.getParameterList().getParameters(); + for (int i = 0, myInfosLength = myInfos.length; i < myInfosLength; i++) { + int oldIndex = myInfos[i].getOldIndex(); + if (oldIndex > -1) { + myInfos[i] = new GrParameterInfo(params[oldIndex], oldIndex); + } + } + return myInfos; + } + } + + private interface GenExceptions { + ThrownExceptionInfo[] genExceptions(PsiMethod method) throws IncorrectOperationException; + } + + private static class SimpleExceptionsGen implements GenExceptions { + private final ThrownExceptionInfo[] myInfos; + + public SimpleExceptionsGen() { + myInfos = new ThrownExceptionInfo[0]; + } + + private SimpleExceptionsGen(ThrownExceptionInfo[] infos) { + myInfos = infos; + } + + public ThrownExceptionInfo[] genExceptions(PsiMethod method) { + for (ThrownExceptionInfo info : myInfos) { + info.updateFromMethod(method); + } + return myInfos; + } + } + + class SimpleInfo extends GrParameterInfo { + int myOldIndex; + String myNewName; + String myDefaultValue; + String myDefaultInitializer; + CanonicalTypes.Type myTypeWrapper; + + SimpleInfo(int oldIndex) { + this(null, oldIndex); + } + + SimpleInfo(String newName, int oldIndex) { + this(newName, oldIndex, "", null, null); + } + + SimpleInfo( + String newName, + int oldIndex, + String defaultValue, + String defaultInitializer, + PsiType type) { + super(myFixture.getProject(), myFixture.getFile()); + myOldIndex = oldIndex; + myNewName = newName; + myDefaultValue = defaultValue; + if (type == null) { + myTypeWrapper = null; + } + else { + myTypeWrapper = CanonicalTypes.createTypeWrapper(type); + } + myDefaultInitializer = defaultInitializer; + } + + @Override + public int getOldIndex() { + return myOldIndex; + } + + @Override + public String getName() { + return myNewName; + } + + @Override + public String getDefaultValue() { + return myDefaultValue; + } + + @Override + public CanonicalTypes.Type getTypeWrapper() { + return myTypeWrapper; + } + + @Override + public String getTypeText() { + return myTypeWrapper.getTypeText(); + } + + @Override + public PsiType createType(PsiElement context, PsiManager manager) throws IncorrectOperationException { + return myTypeWrapper.getType(context, manager); + } + + @Override + public String getDefaultInitializer() { + return myDefaultInitializer; + } + } +} diff --git a/plugins/groovy/testdata/highlighting/MethodDuplicates.groovy b/plugins/groovy/testdata/highlighting/MethodDuplicates.groovy index d093d9a2a4d8..e54573402ae0 100644 --- a/plugins/groovy/testdata/highlighting/MethodDuplicates.groovy +++ b/plugins/groovy/testdata/highlighting/MethodDuplicates.groovy @@ -1,9 +1,24 @@ -def foo(String s = "a", int i, double y = 4) { +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +def foo(String s = "a", int i, double y = 4) { } def foo(int i, double y) {} -def foo(String s, int i) {} +def foo(String s, int i) {} def foo(String s, double y){} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/ChangeVisibilityAndName.groovy b/plugins/groovy/testdata/refactoring/changeSignature/ChangeVisibilityAndName.groovy new file mode 100644 index 000000000000..3d7ee438b074 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/ChangeVisibilityAndName.groovy @@ -0,0 +1,3 @@ +def foo(String s) {} + +foo("a") \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/ChangeVisibilityAndName_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/ChangeVisibilityAndName_after.groovy new file mode 100644 index 000000000000..ba13bb6986ce --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/ChangeVisibilityAndName_after.groovy @@ -0,0 +1,3 @@ +def protected newName(String s) {} + +newName("a") \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/InsertOptionalParameter.groovy b/plugins/groovy/testdata/refactoring/changeSignature/InsertOptionalParameter.groovy new file mode 100644 index 000000000000..8d6a085df8d3 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/InsertOptionalParameter.groovy @@ -0,0 +1,3 @@ +def foo(String s, double x = 5){} + +print foo("s"); \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/InsertOptionalParameter_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/InsertOptionalParameter_after.groovy new file mode 100644 index 000000000000..06a10e26b3ab --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/InsertOptionalParameter_after.groovy @@ -0,0 +1,3 @@ +def foo(String s, double x = 5, int p = -3){} + +print foo("s"); \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/InsertParameter.groovy b/plugins/groovy/testdata/refactoring/changeSignature/InsertParameter.groovy new file mode 100644 index 000000000000..9f4ec033c2f6 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/InsertParameter.groovy @@ -0,0 +1,3 @@ +def foo(String s, double x) {} + +print foo("3", 4) \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/InsertParameter_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/InsertParameter_after.groovy new file mode 100644 index 000000000000..b4c428064a03 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/InsertParameter_after.groovy @@ -0,0 +1,3 @@ +def foo(String s, int p = -3, double x) {} + +print foo("3", 5, 4) \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/MoveNamedParameters.groovy b/plugins/groovy/testdata/refactoring/changeSignature/MoveNamedParameters.groovy new file mode 100644 index 000000000000..9e798c992884 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/MoveNamedParameters.groovy @@ -0,0 +1,3 @@ +def foo(Map map, String s) {} + +foo(2: "y", "a", x: "d", y: "c") \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/MoveNamedParameters_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/MoveNamedParameters_after.groovy new file mode 100644 index 000000000000..a1ad43b53461 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/MoveNamedParameters_after.groovy @@ -0,0 +1,3 @@ +def foo(String s, Map map) {} + +foo("a", [2: "y", x: "d", y: "c"]) \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/MoveVarArgParameters.groovy b/plugins/groovy/testdata/refactoring/changeSignature/MoveVarArgParameters.groovy new file mode 100644 index 000000000000..1b9feb37d300 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/MoveVarArgParameters.groovy @@ -0,0 +1,3 @@ +def foo(String s, String[] args) {} + +foo("a", "b", "c") \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/MoveVarArgParameters_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/MoveVarArgParameters_after.groovy new file mode 100644 index 000000000000..d34406f1958f --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/MoveVarArgParameters_after.groovy @@ -0,0 +1,3 @@ +def foo(String[] args, String s) {} + +foo(["b", "c"] as String[], "a") \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/NamedParametersOrder1.groovy b/plugins/groovy/testdata/refactoring/changeSignature/NamedParametersOrder1.groovy new file mode 100644 index 000000000000..a7feff59fb20 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/NamedParametersOrder1.groovy @@ -0,0 +1,4 @@ +def foo(Map map, String s, double y) {} + +print foo(a: 4, "", b: 5, 6d, 56:78, (1+2):4) + diff --git a/plugins/groovy/testdata/refactoring/changeSignature/NamedParametersOrder1_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/NamedParametersOrder1_after.groovy new file mode 100644 index 000000000000..259a018515b9 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/NamedParametersOrder1_after.groovy @@ -0,0 +1,4 @@ +def foo(Map map, double y) {} + +print foo(a: 4, b: 5, 6d, 56: 78, (1 + 2): 4) + diff --git a/plugins/groovy/testdata/refactoring/changeSignature/NamedParametersOrder2.groovy b/plugins/groovy/testdata/refactoring/changeSignature/NamedParametersOrder2.groovy new file mode 100644 index 000000000000..632d5a39f2ad --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/NamedParametersOrder2.groovy @@ -0,0 +1,3 @@ +def foo(Map map, String s, double y) {} + +print foo(a: 4, "", b: 5, 6d, 56:78, (1+2):4) \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/NamedParametersOrder2_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/NamedParametersOrder2_after.groovy new file mode 100644 index 000000000000..36f1bc19adff --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/NamedParametersOrder2_after.groovy @@ -0,0 +1,3 @@ +def foo(Map map, int p, double y) {} + +print foo(a: 4, b: 5, 5, 6d, 56: 78, (1 + 2): 4) \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/NamedParametersOrder3.groovy b/plugins/groovy/testdata/refactoring/changeSignature/NamedParametersOrder3.groovy new file mode 100644 index 000000000000..a7feff59fb20 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/NamedParametersOrder3.groovy @@ -0,0 +1,4 @@ +def foo(Map map, String s, double y) {} + +print foo(a: 4, "", b: 5, 6d, 56:78, (1+2):4) + diff --git a/plugins/groovy/testdata/refactoring/changeSignature/NamedParametersOrder3_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/NamedParametersOrder3_after.groovy new file mode 100644 index 000000000000..8deb4abddf70 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/NamedParametersOrder3_after.groovy @@ -0,0 +1,4 @@ +def foo(Map map, double y, int p) {} + +print foo(a: 4, b: 5, 6d, 56: 78, (1 + 2): 4, 5) + diff --git a/plugins/groovy/testdata/refactoring/changeSignature/NamedParametersRemove.groovy b/plugins/groovy/testdata/refactoring/changeSignature/NamedParametersRemove.groovy new file mode 100644 index 000000000000..9a548528fff2 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/NamedParametersRemove.groovy @@ -0,0 +1,3 @@ +def foo(Map map, String s, double y) {} + +print foo(a: 4, "", b: 5, 6d, 56:78, (1+2):4) diff --git a/plugins/groovy/testdata/refactoring/changeSignature/NamedParametersRemove_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/NamedParametersRemove_after.groovy new file mode 100644 index 000000000000..7f3e60a4fed8 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/NamedParametersRemove_after.groovy @@ -0,0 +1,3 @@ +def foo(String s, double y) {} + +print foo("", 6d) diff --git a/plugins/groovy/testdata/refactoring/changeSignature/OneNewParameter.groovy b/plugins/groovy/testdata/refactoring/changeSignature/OneNewParameter.groovy new file mode 100644 index 000000000000..e44ef0de709c --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/OneNewParameter.groovy @@ -0,0 +1,3 @@ +def foo() {} + +print foo() \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/OneNewParameter_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/OneNewParameter_after.groovy new file mode 100644 index 000000000000..6f01c1f1a37c --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/OneNewParameter_after.groovy @@ -0,0 +1,3 @@ +def foo(String p) {} + +print foo("5") \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/RemoveParameter.groovy b/plugins/groovy/testdata/refactoring/changeSignature/RemoveParameter.groovy new file mode 100644 index 000000000000..6ae1d6867c77 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/RemoveParameter.groovy @@ -0,0 +1,3 @@ +def foo(String s){} + +print foo("4") diff --git a/plugins/groovy/testdata/refactoring/changeSignature/RemoveParameter_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/RemoveParameter_after.groovy new file mode 100644 index 000000000000..80c312166f37 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/RemoveParameter_after.groovy @@ -0,0 +1,3 @@ +def foo(){} + +print foo() diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index e3979a9f6edf..7fa3a206b8c5 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -960,7 +960,7 @@ - + From 83fd6dbbcc8ae1bea8f7518a491afaa2e55122ef Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Sun, 2 May 2010 15:37:56 +0400 Subject: [PATCH 013/212] formatting for added elements to PSI --- .../impl/statements/blocks/GrBlockImpl.java | 11 +++---- .../typedef/GrTypeDefinitionImpl.java | 15 +++++----- .../refactoring/extractMethod/clos_em.test | 10 +++---- .../refactoring/extractMethod/enum1.test | 16 +++++----- .../refactoring/extractMethod/inter4.test | 30 +++++++++---------- .../refactoring/extractMethod/meth_em1.test | 18 +++++------ .../refactoring/extractMethod/meth_em2.test | 14 ++++----- .../refactoring/extractMethod/meth_em3.test | 12 ++++---- .../refactoring/extractMethod/output1.test | 24 +++++++-------- .../refactoring/extractMethod/ret1.test | 16 +++++----- .../refactoring/extractMethod/ret2.test | 26 ++++++++-------- .../refactoring/extractMethod/ret3.test | 26 ++++++++-------- .../refactoring/extractMethod/ret4.test | 18 +++++------ .../refactoring/extractMethod/ven1.test | 22 +++++++------- .../refactoring/extractMethod/ven2.test | 22 +++++++------- .../refactoring/extractMethod/ven3.test | 22 +++++++------- 16 files changed, 151 insertions(+), 151 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrBlockImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrBlockImpl.java index e35d332bdab7..1275b629019c 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrBlockImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrBlockImpl.java @@ -87,7 +87,6 @@ public abstract class GrBlockImpl extends GroovyPsiElementImpl implements GrCode } public GrStatement addStatementBefore(@NotNull GrStatement element, GrStatement anchor) throws IncorrectOperationException { - if (anchor == null && getRBrace() == null) { throw new IncorrectOperationException(); } @@ -98,14 +97,16 @@ public abstract class GrBlockImpl extends GroovyPsiElementImpl implements GrCode ASTNode elemNode = element.copy().getNode(); assert elemNode != null; - final ASTNode anchorNode = anchor != null ? anchor.getNode() : getRBrace().getNode(); - getNode().addChild(elemNode, anchorNode); + PsiElement actualAnchor = anchor == null ? getRBrace() : anchor; + final ASTNode anchorNode = actualAnchor.getNode(); + element = (GrStatement)addBefore(element, actualAnchor); if (mayUseNewLinesAsSeparators()) { getNode().addLeaf(GroovyTokenTypes.mNLS, "\n", anchorNode); - } else { + } + else { getNode().addLeaf(GroovyTokenTypes.mSEMI, ";", anchorNode); } - return (GrStatement) elemNode.getPsi(); + return element; } @Nullable diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionImpl.java index 1afc8edce8df..22fb8db578ea 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionImpl.java @@ -659,7 +659,6 @@ public abstract class GrTypeDefinitionImpl extends GroovyBaseElementImpl - println (x + y) - foo(x, y) + int x, int y -> + println (x + y) + foo(x, y) } ----- def foo = { - int x, int y -> - testMethod(x, y) + int x, int y -> + testMethod(x, y) } private def testMethod(int x, int y) { diff --git a/plugins/groovy/testdata/groovy/refactoring/extractMethod/enum1.test b/plugins/groovy/testdata/groovy/refactoring/extractMethod/enum1.test index 36240b1f5ea6..b2c7e43fa309 100644 --- a/plugins/groovy/testdata/groovy/refactoring/extractMethod/enum1.test +++ b/plugins/groovy/testdata/groovy/refactoring/extractMethod/enum1.test @@ -1,17 +1,17 @@ enum E { - A, B, C; + A, B, C; - def r(){ - def e = C - } + def r(){ + def e = C + } } ----- enum E { - A, B, C; + A, B, C; - def r(){ - testMethod() - } + def r(){ + testMethod() + } private def testMethod() { def e = C diff --git a/plugins/groovy/testdata/groovy/refactoring/extractMethod/inter4.test b/plugins/groovy/testdata/groovy/refactoring/extractMethod/inter4.test index 0b435ca3de58..5497a83d84ed 100644 --- a/plugins/groovy/testdata/groovy/refactoring/extractMethod/inter4.test +++ b/plugins/groovy/testdata/groovy/refactoring/extractMethod/inter4.test @@ -1,25 +1,25 @@ def i = 6 while (true) { - println "preved" - i = 42 - if (i > 0) { - break; - } else { - cl = { continue; } - cl.call() - } + println "preved" + i = 42 + if (i > 0) { + break; + } else { + cl = { continue; } + cl.call() + } } println i ----- def i = 6 while (true) { - println "preved" - i = 42 - if (i > 0) { - break; - } else { - testMethod() - } + println "preved" + i = 42 + if (i > 0) { + break; + } else { + testMethod() + } } private def testMethod() { diff --git a/plugins/groovy/testdata/groovy/refactoring/extractMethod/meth_em1.test b/plugins/groovy/testdata/groovy/refactoring/extractMethod/meth_em1.test index 0b9e43ca91a0..ada54735d166 100644 --- a/plugins/groovy/testdata/groovy/refactoring/extractMethod/meth_em1.test +++ b/plugins/groovy/testdata/groovy/refactoring/extractMethod/meth_em1.test @@ -1,16 +1,16 @@ protected static def getGeneratedFileNames(String name, int boo) { - def names = new ArrayList() - foo = null - println (names.toString() + boo + name) - println (names + foo) - names + def names = new ArrayList() + foo = null + println (names.toString() + boo + name) + println (names + foo) + names } ----- protected static def getGeneratedFileNames(String name, int boo) { - def names = new ArrayList() - foo = null - testMethod(names, boo, name, foo) - names + def names = new ArrayList() + foo = null + testMethod(names, boo, name, foo) + names } private static def testMethod(ArrayList names, int boo, String name, foo) { diff --git a/plugins/groovy/testdata/groovy/refactoring/extractMethod/meth_em2.test b/plugins/groovy/testdata/groovy/refactoring/extractMethod/meth_em2.test index 4de30238f64e..881ffa18fd87 100644 --- a/plugins/groovy/testdata/groovy/refactoring/extractMethod/meth_em2.test +++ b/plugins/groovy/testdata/groovy/refactoring/extractMethod/meth_em2.test @@ -1,14 +1,14 @@ protected static def getGeneratedFileNames(String name, int boo) { - def names = new ArrayList() - foo = null - println (names.toString() + boo + name) - println (names + foo) - names + def names = new ArrayList() + foo = null + println (names.toString() + boo + name) + println (names + foo) + names } ----- protected static def getGeneratedFileNames(String name, int boo) { - def names = new ArrayList() - testMethod(names, boo, name) + def names = new ArrayList() + testMethod(names, boo, name) } private static ArrayList testMethod(ArrayList names, int boo, String name) { diff --git a/plugins/groovy/testdata/groovy/refactoring/extractMethod/meth_em3.test b/plugins/groovy/testdata/groovy/refactoring/extractMethod/meth_em3.test index 5675730c17b0..fb8b1c5ded99 100644 --- a/plugins/groovy/testdata/groovy/refactoring/extractMethod/meth_em3.test +++ b/plugins/groovy/testdata/groovy/refactoring/extractMethod/meth_em3.test @@ -1,13 +1,13 @@ protected static def getGeneratedFileNames(String name, int boo) { - def names - names = new ArrayList() - names + def names + names = new ArrayList() + names } ----- protected static def getGeneratedFileNames(String name, int boo) { - def names - names = testMethod() - names + def names + names = testMethod() + names } private static ArrayList testMethod() { diff --git a/plugins/groovy/testdata/groovy/refactoring/extractMethod/output1.test b/plugins/groovy/testdata/groovy/refactoring/extractMethod/output1.test index c11c3f02af91..4c8dbdf53611 100644 --- a/plugins/groovy/testdata/groovy/refactoring/extractMethod/output1.test +++ b/plugins/groovy/testdata/groovy/refactoring/extractMethod/output1.test @@ -1,26 +1,26 @@ class S { - def r() { - Closure sin = {x -> Math.sin(x)} + def r() { + Closure sin = {x -> Math.sin(x)} - 10.times { - x -> sin x - } - + 10.times { + x -> sin x } + + } } ----- class S { - def r() { - Closure sin = testMethod() + def r() { + Closure sin = testMethod() - 10.times { - x -> sin x - } - + 10.times { + x -> sin x } + } + private Closure testMethod() { Closure sin = {x -> Math.sin(x)} return sin diff --git a/plugins/groovy/testdata/groovy/refactoring/extractMethod/ret1.test b/plugins/groovy/testdata/groovy/refactoring/extractMethod/ret1.test index 2948942a0a68..497d1a0d82a6 100644 --- a/plugins/groovy/testdata/groovy/refactoring/extractMethod/ret1.test +++ b/plugins/groovy/testdata/groovy/refactoring/extractMethod/ret1.test @@ -1,15 +1,15 @@ static def foo(int i, int j, int k) { - def v - println(i + j - k) - v = 42 - return v + j + def v + println(i + j - k) + v = 42 + return v + j } ----- static def foo(int i, int j, int k) { - def v - println(i + j - k) - v = 42 - return testMethod(v, j) + def v + println(i + j - k) + v = 42 + return testMethod(v, j) } private static def testMethod(int v, int j) { diff --git a/plugins/groovy/testdata/groovy/refactoring/extractMethod/ret2.test b/plugins/groovy/testdata/groovy/refactoring/extractMethod/ret2.test index 0788fb098d7e..ffaa39fd6fd0 100644 --- a/plugins/groovy/testdata/groovy/refactoring/extractMethod/ret2.test +++ b/plugins/groovy/testdata/groovy/refactoring/extractMethod/ret2.test @@ -1,20 +1,20 @@ static def foo(int i, int j, int k) { - def v - println(i + j - k) - v = 42 - if (i > 42) { - println("preved!") - return v + i - } else { - return v + j - } + def v + println(i + j - k) + v = 42 + if (i > 42) { + println("preved!") + return v + i + } else { + return v + j + } } ------ static def foo(int i, int j, int k) { - def v - println(i + j - k) - v = 42 - return testMethod(i, v, j) + def v + println(i + j - k) + v = 42 + return testMethod(i, v, j) } private static def testMethod(int i, int v, int j) { diff --git a/plugins/groovy/testdata/groovy/refactoring/extractMethod/ret3.test b/plugins/groovy/testdata/groovy/refactoring/extractMethod/ret3.test index 0609f5865b72..b37df98f011d 100644 --- a/plugins/groovy/testdata/groovy/refactoring/extractMethod/ret3.test +++ b/plugins/groovy/testdata/groovy/refactoring/extractMethod/ret3.test @@ -1,20 +1,20 @@ static def foo(int i, int j, int k) { - def v - println(i + j - k) - v = 42 - if (i > 42) { - println("preved!") - } else { - return v + j - } - return 239 + def v + println(i + j - k) + v = 42 + if (i > 42) { + println("preved!") + } else { + return v + j + } + return 239 } ----- static def foo(int i, int j, int k) { - def v - println(i + j - k) - v = 42 - return testMethod(i, v, j) + def v + println(i + j - k) + v = 42 + return testMethod(i, v, j) } private static def testMethod(int i, int v, int j) { diff --git a/plugins/groovy/testdata/groovy/refactoring/extractMethod/ret4.test b/plugins/groovy/testdata/groovy/refactoring/extractMethod/ret4.test index 1d35d0a99396..994296d9db63 100644 --- a/plugins/groovy/testdata/groovy/refactoring/extractMethod/ret4.test +++ b/plugins/groovy/testdata/groovy/refactoring/extractMethod/ret4.test @@ -1,13 +1,13 @@ static def foo(int i, int j, int k) { - def v - println(i + j - k) - v = 42 - if (i > 42) { - println("preved!") - } else { - return v + j - } - return v + def v + println(i + j - k) + v = 42 + if (i > 42) { + println("preved!") + } else { + return v + j + } + return v } ----- FAILED: Refactoring is not supported when return statement interrupts the execution flow \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/refactoring/extractMethod/ven1.test b/plugins/groovy/testdata/groovy/refactoring/extractMethod/ven1.test index b7be7ba3c519..5d329a13b3f6 100644 --- a/plugins/groovy/testdata/groovy/refactoring/extractMethod/ven1.test +++ b/plugins/groovy/testdata/groovy/refactoring/extractMethod/ven1.test @@ -1,20 +1,20 @@ protected static def getGeneratedFileNames() { - def foo = 0 - while (true) { - println(foo) - foo = "" - } + def foo = 0 + while (true) { + println(foo) + foo = "" + } - int t = foo + int t = foo } ----- protected static def getGeneratedFileNames() { - def foo = 0 - while (true) { - foo = testMethod(foo) - } + def foo = 0 + while (true) { + foo = testMethod(foo) + } - int t = foo + int t = foo } private static String testMethod(Serializable foo) { diff --git a/plugins/groovy/testdata/groovy/refactoring/extractMethod/ven2.test b/plugins/groovy/testdata/groovy/refactoring/extractMethod/ven2.test index debd462f07da..abc71079d1e6 100644 --- a/plugins/groovy/testdata/groovy/refactoring/extractMethod/ven2.test +++ b/plugins/groovy/testdata/groovy/refactoring/extractMethod/ven2.test @@ -1,20 +1,20 @@ protected static def getGeneratedFileNames() { - foo = 0 - while (true) { - println(foo) - foo = "" - } + foo = 0 + while (true) { + println(foo) + foo = "" + } - int t = foo + int t = foo } ----- protected static def getGeneratedFileNames() { - foo = 0 - while (true) { - foo = testMethod(foo) - } + foo = 0 + while (true) { + foo = testMethod(foo) + } - int t = foo + int t = foo } private static String testMethod(Serializable foo) { diff --git a/plugins/groovy/testdata/groovy/refactoring/extractMethod/ven3.test b/plugins/groovy/testdata/groovy/refactoring/extractMethod/ven3.test index debd462f07da..abc71079d1e6 100644 --- a/plugins/groovy/testdata/groovy/refactoring/extractMethod/ven3.test +++ b/plugins/groovy/testdata/groovy/refactoring/extractMethod/ven3.test @@ -1,20 +1,20 @@ protected static def getGeneratedFileNames() { - foo = 0 - while (true) { - println(foo) - foo = "" - } + foo = 0 + while (true) { + println(foo) + foo = "" + } - int t = foo + int t = foo } ----- protected static def getGeneratedFileNames() { - foo = 0 - while (true) { - foo = testMethod(foo) - } + foo = 0 + while (true) { + foo = testMethod(foo) + } - int t = foo + int t = foo } private static String testMethod(Serializable foo) { From eea795801df18f15ade338330231c2c2bfeca69f Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Mon, 3 May 2010 15:44:48 +0400 Subject: [PATCH 014/212] correct cases for Groovy ChangeSignature --- .../ChangeSignatureParameterUsageInfo.java | 4 +- .../JavaChangeSignatureUsageSearcher.java | 29 ++- .../psi/impl/GrDocMemberReferenceImpl.java | 41 +++- .../psi/impl/GrDocMethodReferenceImpl.java | 31 +++ .../lang/psi/GroovyPsiElementFactory.java | 9 + .../statements/typedef/members/GrMethod.java | 3 + .../psi/impl/GroovyPsiElementFactoryImpl.java | 31 ++- .../modifiers/GrModifierListImpl.java | 1 + .../impl/statements/blocks/GrBlockImpl.java | 6 + .../typedef/GrTypeDefinitionImpl.java | 8 + .../typedef/members/GrMethodBaseImpl.java | 29 +++ .../impl/types/GrClosureSignatureUtil.java | 2 + .../GrChageSignatureUsageSearcher.java | 9 + .../changeSignature/GrChangeInfoImpl.java | 15 +- .../GrChangeSignatureConflictSearcher.java | 2 +- .../GrChangeSignatureDialog.form | 52 ++--- .../GrChangeSignatureDialog.java | 28 ++- .../GrChangeSignatureProcessor.java | 5 + .../GrChangeSignatureUsageProcessor.java | 221 ++++++++++++++---- .../changeSignature/GrParameterInfo.java | 23 +- .../changeSignature/ChangeSignatureTest.java | 98 +++++++- .../changeSignature/AddReturnType.groovy | 3 + .../AddReturnType_after.groovy | 3 + .../AnonymousClassUsage.groovy | 9 + .../AnonymousClassUsage_after.groovy | 9 + .../ChangeParameterType.groovy | 1 + .../ChangeParameterType_after.groovy | 1 + .../changeSignature/ChangeReturnType.groovy | 3 + .../ChangeReturnType_after.groovy | 3 + .../GroovyDocReferences.groovy | 9 + .../GroovyDocReferences_after.groovy | 9 + .../ImplicitConstructorForClass.groovy | 7 + .../ImplicitConstructorForClass_after.groovy | 10 + .../ImplicitConstructorInConstructor.groovy | 7 + ...licitConstructorInConstructor_after.groovy | 9 + .../changeSignature/Overriders.groovy | 11 + .../changeSignature/Overriders_after.groovy | 11 + .../changeSignature/ParameterRename.groovy | 15 ++ .../ParameterRename_after.groovy | 15 ++ .../changeSignature/RemoveReturnType.groovy | 3 + .../RemoveReturnType_after.groovy | 3 + 41 files changed, 659 insertions(+), 129 deletions(-) create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/AddReturnType.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/AddReturnType_after.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/AnonymousClassUsage.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/AnonymousClassUsage_after.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/ChangeParameterType.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/ChangeParameterType_after.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/ChangeReturnType.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/ChangeReturnType_after.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/GroovyDocReferences.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/GroovyDocReferences_after.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorForClass.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorForClass_after.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorInConstructor.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorInConstructor_after.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/Overriders.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/Overriders_after.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/ParameterRename.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/ParameterRename_after.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/RemoveReturnType.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/RemoveReturnType_after.groovy diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureParameterUsageInfo.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureParameterUsageInfo.java index 15cf7f0e0702..b98b104a373f 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureParameterUsageInfo.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureParameterUsageInfo.java @@ -22,8 +22,8 @@ import com.intellij.usageView.UsageInfo; * @author Maxim.Medvedev */ public class ChangeSignatureParameterUsageInfo extends UsageInfo { - final String oldParameterName; - final String newParameterName; + public final String oldParameterName; + public final String newParameterName; public ChangeSignatureParameterUsageInfo(PsiElement element, String oldParameterName, String newParameterName) { super(element); diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageSearcher.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageSearcher.java index 29fb2cba1594..00eef0ce427b 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageSearcher.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageSearcher.java @@ -220,23 +220,28 @@ class JavaChangeSignatureUsageSearcher { result.add(new UsageInfo(element)); } else if (element instanceof PsiMethod && ((PsiMethod)element).isConstructor()) { - DefaultConstructorImplicitUsageInfo implicitUsageInfo = - new DefaultConstructorImplicitUsageInfo((PsiMethod)element, ((PsiMethod)element).getContainingClass(), method); - result.add(implicitUsageInfo); + if (StdLanguages.JAVA.equals(element.getLanguage())) { + DefaultConstructorImplicitUsageInfo implicitUsageInfo = + new DefaultConstructorImplicitUsageInfo((PsiMethod)element, ((PsiMethod)element).getContainingClass(), method); + result.add(implicitUsageInfo); + } } else if (element instanceof PsiClass) { LOG.assertTrue(method.isConstructor()); final PsiClass psiClass = (PsiClass)element; - if (!(myChangeInfo instanceof JavaChangeInfoImpl)) continue; - if (shouldPropagateToNonPhysicalMethod(method, result, psiClass, - ((JavaChangeInfoImpl)myChangeInfo).propagateParametersMethods)) { - continue; + if (StdLanguages.JAVA.equals(psiClass.getLanguage())) { + if (myChangeInfo instanceof JavaChangeInfoImpl) { + if (shouldPropagateToNonPhysicalMethod(method, result, psiClass, + ((JavaChangeInfoImpl)myChangeInfo).propagateParametersMethods)) { + continue; + } + if (shouldPropagateToNonPhysicalMethod(method, result, psiClass, + ((JavaChangeInfoImpl)myChangeInfo).propagateExceptionsMethods)) { + continue; + } + } + result.add(new NoConstructorClassUsageInfo(psiClass)); } - if (shouldPropagateToNonPhysicalMethod(method, result, psiClass, - ((JavaChangeInfoImpl)myChangeInfo).propagateExceptionsMethods)) { - continue; - } - result.add(new NoConstructorClassUsageInfo(psiClass)); } else if (ref instanceof PsiCallReference) { result.add(new CallReferenceUsageInfo((PsiCallReference)ref)); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/groovydoc/psi/impl/GrDocMemberReferenceImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/groovydoc/psi/impl/GrDocMemberReferenceImpl.java index 3016d4fd81e0..0c56173622b3 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/groovydoc/psi/impl/GrDocMemberReferenceImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/groovydoc/psi/impl/GrDocMemberReferenceImpl.java @@ -16,8 +16,8 @@ package org.jetbrains.plugins.groovy.lang.groovydoc.psi.impl; -import com.intellij.codeInsight.lookup.LookupItem; import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.codeInsight.lookup.LookupItem; import com.intellij.lang.ASTNode; import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; @@ -56,8 +56,47 @@ public abstract class GrDocMemberReferenceImpl extends GroovyDocPsiElementImpl i return getManager().areElementsEquivalent(element, resolve()); } + @Nullable public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException { if (isReferenceTo(element)) return this; + + if (element instanceof PsiClass) { + GrDocReferenceElement holder = getReferenceHolder(); + if (holder != null) { + return replace(holder.getReferenceElement().bindToElement(element).getParent()); + } + GrDocReferenceElement ref = + GroovyPsiElementFactory.getInstance(getProject()).createDocReferenceElementFromFQN(((PsiClass)element).getQualifiedName()); + return replace(ref); + } + else if (element instanceof PsiMember) { + PsiClass clazz = ((PsiMember)element).getContainingClass(); + if (clazz == null) return null; + String qName = clazz.getQualifiedName(); + String memberRefText; + if (element instanceof PsiField) { + memberRefText = ((PsiField)element).getName(); + } + else if (element instanceof PsiMethod) { + PsiParameterList list = ((PsiMethod)element).getParameterList(); + StringBuilder builder = new StringBuilder(); + builder.append(((PsiMethod)element).getName()).append("("); + PsiParameter[] params = list.getParameters(); + for (int i = 0; i < params.length; i++) { + PsiParameter parameter = params[i]; + PsiType type = parameter.getType(); + if (i > 0) builder.append(", "); + builder.append(type.getPresentableText()); + } + builder.append(")"); + memberRefText = builder.toString(); + } + else { + return null; + } + GrDocMemberReference ref = GroovyPsiElementFactory.getInstance(getProject()).createDocMemberReferenceFromText(qName, memberRefText); + return replace(ref); + } return null; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/groovydoc/psi/impl/GrDocMethodReferenceImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/groovydoc/psi/impl/GrDocMethodReferenceImpl.java index b9647abd6c39..c9ca6bbf2eb5 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/groovydoc/psi/impl/GrDocMethodReferenceImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/groovydoc/psi/impl/GrDocMethodReferenceImpl.java @@ -55,6 +55,37 @@ public class GrDocMethodReferenceImpl extends GrDocMemberReferenceImpl implement return child; } + @Override + public PsiElement resolve() { + String name = getReferenceName(); + GrDocReferenceElement holder = getReferenceHolder(); + PsiElement resolved; + if (holder != null) { + GrCodeReferenceElement referenceElement = holder.getReferenceElement(); + resolved = referenceElement != null ? referenceElement.resolve() : null; + } else { + resolved = getEnclosingClass(this); + } + if (resolved instanceof PsiClass) { + PsiType[] parameterTypes = getParameterList().getParameterTypes(); + PsiType thisType = JavaPsiFacade.getInstance(getProject()).getElementFactory().createType((PsiClass)resolved, PsiSubstitutor.EMPTY); + + MethodResolverProcessor processor = new MethodResolverProcessor(name, this, false, thisType, parameterTypes, PsiType.EMPTY_ARRAY); + resolved.processDeclarations(processor, ResolveState.initial(), resolved, this); + if (processor.hasApplicableCandidates()) { + return processor.getCandidates()[0].getElement(); + } + + MethodResolverProcessor constructorProcessor = + new MethodResolverProcessor(name, this, true, thisType, parameterTypes, PsiType.EMPTY_ARRAY); + resolved.processDeclarations(constructorProcessor, ResolveState.initial(), resolved, this); + if (constructorProcessor.hasApplicableCandidates()) { + return constructorProcessor.getCandidates()[0].getElement(); + } + } + return null; + } + protected ResolveResult[] multiResolveImpl() { String name = getReferenceName(); GrDocReferenceElement holder = getReferenceHolder(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyPsiElementFactory.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyPsiElementFactory.java index 0c5ecb253d81..61054ce72d58 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyPsiElementFactory.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyPsiElementFactory.java @@ -24,9 +24,12 @@ import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocComment; +import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocMemberReference; +import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocReferenceElement; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrLabel; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrBlockStatement; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrConstructorInvocation; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration; import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList; @@ -102,6 +105,10 @@ public abstract class GroovyPsiElementFactory { public abstract PsiElement createDocMemberReferenceNameFromText(String idText); + public abstract GrDocMemberReference createDocMemberReferenceFromText(String className, String text); + + public abstract GrDocReferenceElement createDocReferenceElementFromFQN(String qName); + public abstract GrTopStatement createTopElementFromText(String text); public abstract GrClosableBlock createClosureFromText(String s) throws IncorrectOperationException; @@ -151,4 +158,6 @@ public abstract class GroovyPsiElementFactory { public abstract GrLabel createLabel(@NotNull String name); public abstract GrDocComment createDocCommentFromText(String text) ; + + public abstract GrConstructorInvocation createConstructorInvocation(String text); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/typedef/members/GrMethod.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/typedef/members/GrMethod.java index c8d74d081e67..20f8675df8ae 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/typedef/members/GrMethod.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/typedef/members/GrMethod.java @@ -65,6 +65,9 @@ public interface GrMethod extends GrMembersDeclaration, GrNamedElement, PsiMetho @Nullable PsiType getReturnType(); + @Nullable + GrTypeElement setReturnType(@Nullable PsiType newReturnType); + @NotNull @NonNls String getName(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java index afe92a1243fe..71c5f8acddc0 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java @@ -29,6 +29,7 @@ import org.jetbrains.plugins.groovy.GroovyFileType; import org.jetbrains.plugins.groovy.annotator.intentions.QuickfixUtil; import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocComment; import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocMemberReference; +import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocReferenceElement; import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocTag; import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes; import org.jetbrains.plugins.groovy.lang.psi.*; @@ -46,6 +47,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrClassDefin import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrEnumTypeDefinition; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinitionBody; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrConstructor; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.GrTopStatement; @@ -87,14 +89,27 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory { } public PsiElement createDocMemberReferenceNameFromText(String idText) { - PsiFile file = createGroovyFile("/** @see A#" + idText + " */"); + GrDocMemberReference reference = createDocMemberReferenceFromText("Foo", idText); + assert reference != null : "DocMemberReference ponts to null"; + return reference.getReferenceNameElement(); + } + + public GrDocMemberReference createDocMemberReferenceFromText(String className, String text) { + PsiFile file = createGroovyFile("/** @see " + className + "#" + text + " */"); PsiElement element = file.getFirstChild(); assert element instanceof GrDocComment; GrDocTag tag = PsiTreeUtil.getChildOfType(element, GrDocTag.class); assert tag != null : "Doc tag points to null"; - GrDocMemberReference reference = PsiTreeUtil.getChildOfType(tag, GrDocMemberReference.class); - assert reference != null : "DocMemberReference ponts to null"; - return reference.getReferenceNameElement(); + return PsiTreeUtil.getChildOfType(tag, GrDocMemberReference.class); + } + + public GrDocReferenceElement createDocReferenceElementFromFQN(String qName) { + PsiFile file = createGroovyFile("/** @see " + qName + " */"); + PsiElement element = file.getFirstChild(); + assert element instanceof GrDocComment; + GrDocTag tag = PsiTreeUtil.getChildOfType(element, GrDocTag.class); + assert tag != null : "Doc tag points to null"; + return PsiTreeUtil.getChildOfType(tag, GrDocReferenceElement.class); } public GrCodeReferenceElement createReferenceElementFromText(String refName) { @@ -242,6 +257,8 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory { fileText.append("def foo("); if (typeText != null) { fileText.append(typeText).append(" "); + } else { + fileText.append("def "); } fileText.append(name); if (initializer != null && initializer.length() > 0) { @@ -542,4 +559,10 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory { builder.append(" def foo(){}"); return (GrDocComment)createGroovyFile(text+"def foo(){}").getFirstChild(); } + + @Override + public GrConstructorInvocation createConstructorInvocation(String text) { + GroovyFile file = (GroovyFile)createGroovyFile("class Foo{ def Foo(){" + text + "}}"); + return ((GrConstructor)file.getClasses()[0].getConstructors()[0]).getChainingConstructorInvocation(); + } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/modifiers/GrModifierListImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/modifiers/GrModifierListImpl.java index efe439228134..4e5986dcf369 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/modifiers/GrModifierListImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/modifiers/GrModifierListImpl.java @@ -170,6 +170,7 @@ public class GrModifierListImpl extends GroovyBaseElementImpl extends GroovyBaseEl } } + @Nullable + public GrTypeElement setReturnType(@Nullable PsiType newReturnType) { + GrTypeElement typeElement = getReturnTypeElementGroovy(); + if (newReturnType == null) { + if (typeElement != null) typeElement.delete(); + return null; + } + GrTypeElement newTypeElement = GroovyPsiElementFactory.getInstance(getProject()).createTypeElement(newReturnType); + if (typeElement == null) { + GrModifierList list = getModifierList(); + newTypeElement = (GrTypeElement)addAfter(newTypeElement, list); + } + else { + newTypeElement= (GrTypeElement)typeElement.replace(newTypeElement); + } + + newTypeElement.accept(new GroovyRecursiveElementVisitor() { + @Override + public void visitCodeReferenceElement(GrCodeReferenceElement refElement) { + super.visitCodeReferenceElement(refElement); + PsiUtil.shortenReference(refElement); + } + }); + return newTypeElement; + } + @Override public Icon getIcon(int flags) { RowIcon baseIcon = createLayeredIcon(GroovyIcons.METHOD, ElementPresentationUtil.getFlags(this, false)); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureSignatureUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureSignatureUtil.java index 30c6d14b7217..7582e9798de4 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureSignatureUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureSignatureUtil.java @@ -188,6 +188,8 @@ public class GrClosureSignatureUtil { } public static class ArgInfo { + public static final ArgInfo[] EMPTY_ARRAY = new ArgInfo[0]; + public List args; public final boolean isMultiArg; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChageSignatureUsageSearcher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChageSignatureUsageSearcher.java index 824e733fd6f4..25f1c0748118 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChageSignatureUsageSearcher.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChageSignatureUsageSearcher.java @@ -34,6 +34,7 @@ import com.intellij.usageView.UsageViewUtil; import com.intellij.util.containers.HashSet; import org.jetbrains.plugins.groovy.GroovyFileType; import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocTagValueToken; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousClassDefinition; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature; import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil; @@ -219,6 +220,14 @@ class GrChageSignatureUsageSearcher { else if (element instanceof PsiClass) { LOG.assertTrue(method.isConstructor()); final PsiClass psiClass = (PsiClass)element; + if (psiClass instanceof GrAnonymousClassDefinition) { + GrClosureSignature signature = GrClosureSignatureUtil.createSignature(method); + GrClosureSignatureUtil.ArgInfo[] map = GrClosureSignatureUtil + .mapParametersToArguments(signature, PsiUtil.getArgumentsList(element), method.getManager(), method.getResolveScope()); + result.add( + new GrMethodCallUsageInfo(element, GrClosureSignatureUtil.createSignature(method), isToModifyArgs, isToCatchExceptions, map)); + continue; + } /*if (!(myChangeInfo instanceof JavaChangeInfoImpl)) continue; todo propagate methods if (shouldPropagateToNonPhysicalMethod(method, result, psiClass, ((JavaChangeInfoImpl)myChangeInfo).propagateParametersMethods)) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeInfoImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeInfoImpl.java index 9d5713fc666c..88fe621425fd 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeInfoImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeInfoImpl.java @@ -23,6 +23,7 @@ import com.intellij.refactoring.changeSignature.ThrownExceptionInfo; import com.intellij.refactoring.util.CanonicalTypes; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.GroovyFileType; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; @@ -35,7 +36,7 @@ import java.util.List; class GrChangeInfoImpl implements JavaChangeInfo { GrMethod method; final String newName; - final CanonicalTypes.Type returnType; + @Nullable final CanonicalTypes.Type returnType; final String visibilityModifier; final List parameters; boolean changeParameters = false; @@ -54,7 +55,7 @@ class GrChangeInfoImpl implements JavaChangeInfo { public GrChangeInfoImpl(GrMethod method, String visibilityModifier, - CanonicalTypes.Type returnType, + @Nullable CanonicalTypes.Type returnType, String newName, List parameters) { this.method = method; @@ -73,7 +74,7 @@ class GrChangeInfoImpl implements JavaChangeInfo { if (!method.isConstructor()) { PsiType oldReturnType = method.getReturnType(); try { - PsiType newReturnType = returnType.getType(method, getMethod().getManager()); + PsiType newReturnType = returnType == null ? null : returnType.getType(method, getMethod().getManager()); if ((oldReturnType == null && newReturnType != null) || (oldReturnType != null && !oldReturnType.equals(newReturnType))) { myIsReturnTypeChanged = true; } @@ -207,10 +208,6 @@ class GrChangeInfoImpl implements JavaChangeInfo { return !method.getModifierList().hasModifierProperty(visibilityModifier); } - public boolean isChangeName() { - return !method.getName().equals(newName); - } - public String getNewName() { return newName; } @@ -219,10 +216,6 @@ class GrChangeInfoImpl implements JavaChangeInfo { return GroovyFileType.GROOVY_LANGUAGE; } - public String getVisibilityModifier() { - return visibilityModifier; - } - @NotNull public String[] getOldParameterNames() { return new String[0]; //To change body of implemented methods use File | Settings | File Templates. diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureConflictSearcher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureConflictSearcher.java index e440db12582d..3ed5c47b3a3d 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureConflictSearcher.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureConflictSearcher.java @@ -142,7 +142,7 @@ class GrChangeSignatureConflictSearcher { prototype = factory.createMethodFromText("", newMethodName, returnType.getTypeText(), ArrayUtil.EMPTY_STRING_ARRAY); } else { - prototype = factory.createConstructorFromText(newMethodName, ArrayUtil.EMPTY_STRING_ARRAY, ArrayUtil.EMPTY_STRING_ARRAY, ""); + prototype = factory.createConstructorFromText(newMethodName, ArrayUtil.EMPTY_STRING_ARRAY, ArrayUtil.EMPTY_STRING_ARRAY, "{}"); } JavaParameterInfo[] parameters = myChangeInfo.getNewParameters(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.form b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.form index 88b9a50ad584..1f3ca694ae7a 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.form +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.form @@ -10,20 +10,20 @@ - + - + - + - + @@ -57,7 +57,7 @@ - + @@ -65,7 +65,7 @@ - + @@ -73,7 +73,7 @@ - + @@ -81,7 +81,7 @@ - + @@ -116,28 +116,12 @@ - + - - - - - - - - - - - - - - - - - + @@ -145,6 +129,22 @@ + + + + + + + + + + + + + + + + diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java index 0b5e71420422..0b6ba62205f1 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java @@ -18,8 +18,10 @@ package org.jetbrains.plugins.groovy.refactoring.changeSignature; import com.intellij.openapi.editor.Document; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.psi.*; -import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.JavaPsiFacade; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiType; +import com.intellij.psi.PsiTypeCodeFragment; import com.intellij.refactoring.HelpID; import com.intellij.refactoring.ui.CodeFragmentTableCellEditor; import com.intellij.refactoring.ui.CodeFragmentTableCellRenderer; @@ -62,6 +64,8 @@ public class GrChangeSignatureDialog extends RefactoringDialog { private JButton myMoveDownButton; private JPanel contentPane; private JLabel mySignatureLabel; + private JLabel myNameLabel; + private JLabel myReturnTypeLabel; private GrParameterTableModel myParameterModel; private GrMethod myMethod; // private Project myProject; @@ -162,6 +166,9 @@ public class GrChangeSignatureDialog extends RefactoringDialog { if (element != null) { myReturnTypeField.setText(element.getText()); } + + myReturnTypeLabel.setLabelFor(myReturnTypeField); + myNameLabel.setLabelFor(myNameField); } private void createParametersModel() { @@ -270,18 +277,14 @@ public class GrChangeSignatureDialog extends RefactoringDialog { catch (PsiTypeCodeFragment.TypeSyntaxException e) { } catch (PsiTypeCodeFragment.NoTypeException e) { - returnType = PsiType.NULL; } - if (returnType == PsiType.NULL) { - returnType = JavaPsiFacade.getElementFactory(myProject) - .createTypeByFQClassName(CommonClassNames.JAVA_LANG_OBJECT, GlobalSearchScope.allScope(myProject)); - } - //todo show warnings String newName = getNewName(); final List parameterInfos = myParameterModel.getParameterInfos(); invokeRefactoring(new GrChangeSignatureProcessor(myProject, new GrChangeInfoImpl(myMethod, modifier, - CanonicalTypes.createTypeWrapper( + returnType == null + ? null + : CanonicalTypes.createTypeWrapper( returnType), newName, parameterInfos))); @@ -299,6 +302,7 @@ public class GrChangeSignatureDialog extends RefactoringDialog { if (!checkType(myReturnTypeCodeFragment)) { CommonRefactoringUtil.showErrorHint(myProject, null, "Return type is wrong", "Incorrect data", HelpID.CHANGE_SIGNATURE); + return false; } for (GrParameterInfo info : myParameterModel.getParameterInfos()) { @@ -307,6 +311,12 @@ public class GrChangeSignatureDialog extends RefactoringDialog { .showErrorHint(myProject, null, "Type for parameter " + info.getName() + " is wrong", "Incorrect data", HelpID.CHANGE_SIGNATURE); return false; } + String defaultValue = info.getDefaultValue(); + if (info.getOldIndex() < 0 && (defaultValue == null || defaultValue.trim().length() == 0)) { + CommonRefactoringUtil.showErrorHint(myProject, null, "Specify default value for parameter " + info.getName(), "Incorrect data", + HelpID.CHANGE_SIGNATURE); + return false; + } } return true; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java index 56505ce2ef75..83be6dbb8122 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java @@ -97,6 +97,11 @@ public class GrChangeSignatureProcessor extends BaseRefactoringProcessor { @Override protected void performRefactoring(UsageInfo[] usages) { + for (UsageInfo usage : usages) { + for (ChangeSignatureUsageProcessor processor : ChangeSignatureUsageProcessor.EP_NAME.getExtensions()) { + if (processor.processUsage(myChangeInfo, usage, true, usages)) break; + } + } changeMethod(); for (UsageInfo usage : usages) { for (ChangeSignatureUsageProcessor processor : ChangeSignatureUsageProcessor.EP_NAME.getExtensions()) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java index 01168bebae00..61918afac0f1 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java @@ -19,28 +19,43 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Ref; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiMethod; +import com.intellij.psi.PsiReference; +import com.intellij.psi.PsiType; import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.refactoring.changeSignature.ChangeInfo; -import com.intellij.refactoring.changeSignature.ChangeSignatureUsageProcessor; -import com.intellij.refactoring.changeSignature.JavaChangeInfo; -import com.intellij.refactoring.changeSignature.JavaParameterInfo; +import com.intellij.refactoring.changeSignature.*; +import com.intellij.refactoring.util.CanonicalTypes; +import com.intellij.refactoring.util.RefactoringUtil; +import com.intellij.refactoring.util.usageInfo.DefaultConstructorImplicitUsageInfo; +import com.intellij.refactoring.util.usageInfo.NoConstructorClassUsageInfo; import com.intellij.usageView.UsageInfo; +import com.intellij.util.ArrayUtil; import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.MultiMap; import com.intellij.util.containers.hash.HashSet; import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.GroovyFileType; import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; +import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier; +import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrConstructorInvocation; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList; import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterList; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrConstructor; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; +import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement; import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil; +import java.util.Arrays; import java.util.List; import java.util.Set; @@ -73,44 +88,92 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc GrChangeInfoImpl grInfo = (GrChangeInfoImpl)changeInfo; GrMethod method = grInfo.getMethod(); - if (grInfo.isChangeName()) { - method.setName(grInfo.getNewName()); - } - - if (grInfo.isVisibilityChanged()) { - method.getModifierList().setModifierProperty(grInfo.getVisibilityModifier(), true); + return processPrimaryMethodInner(grInfo, method, null); + } + + private static boolean processPrimaryMethodInner(JavaChangeInfo changeInfo, GrMethod method, PsiMethod baseMethod) { + if (changeInfo.isNameChanged()) { + String newName = baseMethod == null ? changeInfo.getNewName() : + RefactoringUtil.suggestNewOverriderName(method.getName(), baseMethod.getName(), changeInfo.getNewName()); + if (newName != null && !newName.equals(method.getName())) { + method.setName(changeInfo.getNewName()); + } } - if (grInfo.isParameterSetOrOrderChanged()) { - JavaParameterInfo[] newParameters = grInfo.getNewParameters(); - GrParameterList parameterList = method.getParameterList(); - GrParameter[] oldParameters = parameterList.getParameters(); + if (changeInfo.isVisibilityChanged()) { + method.getModifierList().setModifierProperty(changeInfo.getNewVisibility(), true); + } + if (changeInfo.isReturnTypeChanged()) { + CanonicalTypes.Type newReturnType = changeInfo.getNewReturnType(); + GrTypeElement element = method.getReturnTypeElementGroovy(); + if (newReturnType == null) { + if (element != null) { + element.delete(); + GrModifierList modifierList = method.getModifierList(); + if (modifierList.getModifiers().length == 0) { + modifierList.setModifierProperty(GrModifier.DEF, true); + } + } + } else { + PsiType type = newReturnType.getType(method.getParameterList(), method.getManager()); + method.setReturnType(type); + } + } - PsiElement anchor = null; - GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(method.getProject()); + JavaParameterInfo[] newParameters = changeInfo.getNewParameters(); + final GrParameterList parameterList = method.getParameterList(); + GrParameter[] oldParameters = parameterList.getParameters(); - for (JavaParameterInfo newParameter : newParameters) { - int index = newParameter.getOldIndex(); - if (index < 0) { - GrParameter grParameter = - factory.createParameter(newParameter.getName(), newParameter.getTypeText(), getInitializer(newParameter), parameterList); - anchor = parameterList.addAfter(grParameter, anchor); + Set toRemove = new HashSet(oldParameters.length); + toRemove.addAll(Arrays.asList(oldParameters)); + + GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(method.getProject()); + GrParameter anchor = null; + for (JavaParameterInfo newParameter : newParameters) { + /* + int index = newParameter.getOldIndex(); + if (index < 0) { + */ + String typeText; + if (newParameter instanceof GrParameterInfo && ((GrParameterInfo)newParameter).hasNoType()) { + typeText = null; } else { - GrParameter grParameter = oldParameters[index]; - anchor = parameterList.addAfter(grParameter, anchor); + typeText = newParameter.getTypeText(); } - } - - for (GrParameter oldParameter : oldParameters) { - oldParameter.delete(); - } - CodeStyleManager.getInstance(parameterList.getProject()).reformat(parameterList); + GrParameter grParameter = + factory.createParameter(newParameter.getName(), typeText, getInitializer(newParameter), parameterList); + anchor = (GrParameter)parameterList.addAfter(grParameter, anchor); +/* } + else { + GrParameter grParameter = oldParameters[index]; + if (grParameter != getNextOfType(parameterList, anchor, GrParameter.class)) { + anchor = (GrParameter)parameterList.addAfter(grParameter, anchor); + } + else { + anchor = grParameter; + toRemove.remove(grParameter); + } + if (anchor.getName() != newParameter.getName()) { + anchor.setName(newParameter.getName()); + } + }*/ } + + for (GrParameter oldParameter : toRemove) { + oldParameter.delete(); + } + CodeStyleManager.getInstance(parameterList.getProject()).reformat(parameterList); + return true; } + @Nullable + private static Type getNextOfType(List parameterList, PsiElement current, Class type) { + return current != null ? PsiTreeUtil.getNextSiblingOfType(current, type) : PsiTreeUtil.getChildOfType(parameterList, type); + } + @Nullable private static String getInitializer(JavaParameterInfo newParameter) { if (newParameter instanceof GrParameterInfo) return ((GrParameterInfo)newParameter).getDefaultInitializer(); @@ -122,25 +185,95 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc PsiElement element = usageInfo.getElement(); if (element == null) return false; + if (!GroovyFileType.GROOVY_LANGUAGE.equals(element.getLanguage())) return false; - if (usageInfo instanceof GrMethodCallUsageInfo) { - processMethodUsage(element, ((JavaChangeInfo)changeInfo), ((GrMethodCallUsageInfo)usageInfo).isToChangeArguments(), - ((GrMethodCallUsageInfo)usageInfo).isToCatchExceptions(), - ((JavaChangeInfo)changeInfo).getMethod(), ((GrMethodCallUsageInfo)usageInfo).getMapToArguments()); - return true; + if (beforeMethodChange) { + if (usageInfo instanceof OverriderUsageInfo) { + processPrimaryMethodInner(((JavaChangeInfo)changeInfo), (GrMethod)((OverriderUsageInfo)usageInfo).getElement(), + ((OverriderUsageInfo)usageInfo).getBaseMethod()); + } + } + else { + if (usageInfo instanceof GrMethodCallUsageInfo) { + processMethodUsage(element, ((JavaChangeInfo)changeInfo), ((GrMethodCallUsageInfo)usageInfo).isToChangeArguments(), + ((GrMethodCallUsageInfo)usageInfo).isToCatchExceptions(), + ((GrMethodCallUsageInfo)usageInfo).getMapToArguments()); + return true; + } + else if (usageInfo instanceof DefaultConstructorImplicitUsageInfo) { + processConstructor( + (GrMethod)((DefaultConstructorImplicitUsageInfo)usageInfo).getConstructor(), + (JavaChangeInfo)changeInfo); + return true; + } + else if (usageInfo instanceof NoConstructorClassUsageInfo) { + processClassUsage((GrTypeDefinition)((NoConstructorClassUsageInfo)usageInfo).getPsiClass(), ((JavaChangeInfo)changeInfo)); + return true; + } + else if (usageInfo instanceof ChangeSignatureParameterUsageInfo) { + String newName = ((ChangeSignatureParameterUsageInfo)usageInfo).newParameterName; + String oldName = ((ChangeSignatureParameterUsageInfo)usageInfo).oldParameterName; + processParameterUsage((PsiReference)element, oldName, newName); + return true; + } + else { + PsiReference ref = element.getReference(); + if (ref != null && changeInfo.getMethod() != null) { + ref.bindToElement(changeInfo.getMethod()); + return true; + } + } } return false; } + private static void processParameterUsage(PsiReference ref, String oldName, String newName) + throws IncorrectOperationException { + ref.handleElementRename(newName); + } + + private static void processClassUsage(GrTypeDefinition psiClass, JavaChangeInfo changeInfo) { + String name = psiClass.getName(); + + GrConstructor constructor = ((GrConstructor)GroovyPsiElementFactory.getInstance(psiClass.getProject()) + .createConstructorFromText(name, ArrayUtil.EMPTY_STRING_ARRAY, ArrayUtil.EMPTY_STRING_ARRAY, "{}")); + + GrModifierList list = constructor.getModifierList(); + if (psiClass.hasModifierProperty(GrModifier.PRIVATE)) list.setModifierProperty(GrModifier.PRIVATE, true); + if (psiClass.hasModifierProperty(GrModifier.PROTECTED)) list.setModifierProperty(GrModifier.PROTECTED, true); + if (!list.hasExplicitVisibilityModifiers()) { + list.setModifierProperty(GrModifier.DEF, true); + } + + constructor = psiClass.addMemberDeclaration(constructor, null); + + processConstructor(constructor, changeInfo); + } + + private static void processConstructor(GrMethod constructor, JavaChangeInfo changeInfo) { + GrOpenBlock block = constructor.getBlock(); + GrConstructorInvocation invocation = + GroovyPsiElementFactory.getInstance(constructor.getProject()).createConstructorInvocation("super()"); + invocation = (GrConstructorInvocation)block.addStatementBefore(invocation, getFirstStatement(block)); + processMethodUsage(invocation.getThisOrSuperKeyword(), changeInfo, true, true, GrClosureSignatureUtil.ArgInfo.EMPTY_ARRAY); + } + + @Nullable + private static GrStatement getFirstStatement(GrCodeBlock block) { + GrStatement[] statements = block.getStatements(); + if (statements.length == 0) return null; + return statements[0]; + } + private static void processMethodUsage(PsiElement element, JavaChangeInfo changeInfo, boolean toChangeArguments, boolean toCatchExceptions, - PsiMethod method, GrClosureSignatureUtil.ArgInfo[] map) { + GrClosureSignatureUtil.ArgInfo[] map) { if (map == null) return; if (changeInfo.isNameChanged()) { if (element instanceof GrReferenceElement) { - element = ((GrReferenceElement)element).bindToElement(method); + element = ((GrReferenceElement)element).handleElementRename(changeInfo.getNewName()); } } if (toChangeArguments) { @@ -192,7 +325,7 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc else { //arguments for simple parameters if (arguments.size() == 1) { //arg exists PsiElement arg = arguments.iterator().next(); - PsiElement curArg = getNextArg(anchor, argumentList); + PsiElement curArg = getNextOfType(argumentList, anchor, GrExpression.class); if (curArg == arg) { anchor = arg; } @@ -214,7 +347,7 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc catch (IncorrectOperationException e) { LOG.error(e.getMessage()); } - anchor = argumentList.addBefore(fromText, getNextArg(anchor, argumentList)); + anchor = argumentList.addBefore(fromText, getNextOfType(argumentList, anchor, GrExpression.class)); } } @@ -222,16 +355,6 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc } } - @Nullable - private static PsiElement getNextArg(PsiElement anchor, GrArgumentList argumentList) { - if (anchor == null) { - anchor = argumentList.getFirstChild(); - if (anchor == null) return null; - if (anchor instanceof GrExpression) return anchor; - } - return PsiTreeUtil.getNextSiblingOfType(anchor, GrExpression.class); - } - private static boolean wasParameterOptional(JavaParameterInfo parameterInfo) { return parameterInfo instanceof GrParameterInfo && ((GrParameterInfo)parameterInfo).wasOptional(); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java index e0aba02b1f50..68d45dc5e76f 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java @@ -17,6 +17,7 @@ package org.jetbrains.plugins.groovy.refactoring.changeSignature; import com.intellij.openapi.project.Project; import com.intellij.psi.*; +import com.intellij.psi.search.GlobalSearchScope; import com.intellij.refactoring.changeSignature.JavaParameterInfo; import com.intellij.refactoring.util.CanonicalTypes; import com.intellij.util.IncorrectOperationException; @@ -106,23 +107,27 @@ public class GrParameterInfo implements JavaParameterInfo { return null; } catch (PsiTypeCodeFragment.NoTypeException e) { - return null; + return JavaPsiFacade.getElementFactory(manager.getProject()) + .createTypeByFQClassName(CommonClassNames.JAVA_LANG_OBJECT, GlobalSearchScope.allScope(manager.getProject())); } } public String getTypeText() { - if (getTypeWrapper() != null) { - return getTypeWrapper().getTypeText(); - } - else { - return ""; + CanonicalTypes.Type type = getTypeWrapper(); + if (type != null) { + return type.getTypeText(); } + return ""; } + @Nullable public CanonicalTypes.Type getTypeWrapper() { if (myTypeWrapper == null) { - myTypeWrapper = CanonicalTypes.createTypeWrapper(createType(myType.getContext(), myType.getManager())); + PsiType type = createType(myType.getContext(), myType.getManager()); + if (type != null) { + myTypeWrapper = CanonicalTypes.createTypeWrapper(type); + } } return myTypeWrapper; } @@ -151,4 +156,8 @@ public class GrParameterInfo implements JavaParameterInfo { public boolean wasWasVarArg() { return myWasVarArg; } + + public boolean hasNoType() { + return myType.getText().trim().length() == 0; + } } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java index bd492ab44a41..69b7d2d874ab 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java @@ -52,7 +52,7 @@ public class ChangeSignatureTest extends LightCodeInsightFixtureTestCase { public void testInsertParameter() throws Exception { doTest(null, new GrParameterInfo[]{ new SimpleInfo(0), - new SimpleInfo("p", -1, "5", "-3", createType("int")), + new SimpleInfo("p", -1, "5", "-3", PsiType.INT), new SimpleInfo(1) }); } @@ -61,7 +61,7 @@ public class ChangeSignatureTest extends LightCodeInsightFixtureTestCase { doTest(null, new GrParameterInfo[]{ new SimpleInfo(0), new SimpleInfo(1), - new SimpleInfo("p", -1, "5", "-3", createType("int")) + new SimpleInfo("p", -1, "5", "-3", PsiType.INT) }); } @@ -82,7 +82,7 @@ public class ChangeSignatureTest extends LightCodeInsightFixtureTestCase { public void testNamedParametersOrder2() throws Exception { doTest(null, new GrParameterInfo[]{ new SimpleInfo(0), - new SimpleInfo("p", -1, "5", null, createType("int")), + new SimpleInfo("p", -1, "5", null, PsiType.INT), new SimpleInfo(2), }); } @@ -91,7 +91,7 @@ public class ChangeSignatureTest extends LightCodeInsightFixtureTestCase { doTest(null, new GrParameterInfo[] { new SimpleInfo(0), new SimpleInfo(2), - new SimpleInfo("p", -1, "5", null, createType("int")), + new SimpleInfo("p", -1, "5", null, PsiType.INT), }); } @@ -113,6 +113,59 @@ public class ChangeSignatureTest extends LightCodeInsightFixtureTestCase { doTest("protected", "newName", null, new GrParameterInfo[]{new SimpleInfo(0)}, new ThrownExceptionInfo[0], false); } + public void testImplicitConstructorInConstructor() throws Exception { + doTest(null, new GrParameterInfo[]{ + new SimpleInfo("p", -1, "5", null, PsiType.INT) + }); + } + + public void testImplicitConstructorForClass() throws Exception { + doTest(null, new GrParameterInfo[]{ + new SimpleInfo("p", -1, "5", null, PsiType.INT) + }); + } + + public void testAnonymousClassUsage() throws Exception { + doTest(null, new GrParameterInfo[]{ + new SimpleInfo("p", -1, "5", null, PsiType.INT) + }); + } + + public void testGroovyDocReferences() throws Exception { + doTest(null, new GrParameterInfo[] { + new SimpleInfo(0), + new SimpleInfo(2) + }); + } + + public void testOverriders() throws Exception { + doTest("public", "bar", null, new GrParameterInfo[]{ + new SimpleInfo(0) + }, new ThrownExceptionInfo[0], false); + } + + public void testParameterRename() throws Exception { + doTest(null, new GrParameterInfo[]{ + new SimpleInfo("newP", 0) + }); + } + + public void testAddReturnType() throws Exception { + doTest("int", new GrParameterInfo[]{new SimpleInfo(0)}); + } + + public void testChangeReturnType() throws Exception { + doTest("int", new GrParameterInfo[]{new SimpleInfo(0)}); + } + + public void testRemoveReturnType() throws Exception { + doTest("", new GrParameterInfo[]{new SimpleInfo(0)}); + } + + public void testChangeParameterType() throws Exception { + doTest("", new GrParameterInfo[]{new SimpleInfo("p", 0, null, null, PsiType.INT)}); + } + private PsiType createType(String typeText) { return JavaPsiFacade.getElementFactory(getProject()).createTypeByFQClassName(typeText, GlobalSearchScope.allScope(getProject())); } @@ -153,9 +206,19 @@ public class ChangeSignatureTest extends LightCodeInsightFixtureTestCase { assertTrue(" is not on method name", targetElement instanceof GrMethod); GrMethod method = (GrMethod)targetElement; final PsiElementFactory factory = JavaPsiFacade.getInstance(getProject()).getElementFactory(); - PsiType newType = newReturnType != null ? factory.createTypeFromText(newReturnType, method) : method.getReturnType(); + PsiType newType; + if (newReturnType == null) { + newType = method.getReturnType(); + } + else if (newReturnType.length() == 0) { + newType = null; + } + else { + newType = factory.createTypeFromText(newReturnType, method); + } GrChangeInfoImpl changeInfo = - new GrChangeInfoImpl(method, newVisibility, CanonicalTypes.createTypeWrapper(newType), newName != null ? newName : method.getName(), + new GrChangeInfoImpl(method, newVisibility, newType != null ? CanonicalTypes.createTypeWrapper(newType) : null, + newName != null ? newName : method.getName(), Arrays.asList(genParams.genParams(method))); new GrChangeSignatureProcessor(getProject(), changeInfo).run(); myFixture.checkResultByFile(getTestName(false) + "_after.groovy"); @@ -178,7 +241,23 @@ public class ChangeSignatureTest extends LightCodeInsightFixtureTestCase { for (int i = 0, myInfosLength = myInfos.length; i < myInfosLength; i++) { int oldIndex = myInfos[i].getOldIndex(); if (oldIndex > -1) { - myInfos[i] = new GrParameterInfo(params[oldIndex], oldIndex); + final String name = myInfos[i].getName(); + final CanonicalTypes.Type wrapper = myInfos[i].getTypeWrapper(); + myInfos[i] = new GrParameterInfo(params[oldIndex], oldIndex) { + @Override + public String getName() { + if (name != null) return name; + return super.getName(); + } + + @Override + public CanonicalTypes.Type getTypeWrapper() { + if (wrapper != null) { + return wrapper; + } + return super.getTypeWrapper(); + } + }; } } return myInfos; @@ -276,5 +355,10 @@ public class ChangeSignatureTest extends LightCodeInsightFixtureTestCase { public String getDefaultInitializer() { return myDefaultInitializer; } + + @Override + public boolean hasNoType() { + return myTypeWrapper == null; + } } } diff --git a/plugins/groovy/testdata/refactoring/changeSignature/AddReturnType.groovy b/plugins/groovy/testdata/refactoring/changeSignature/AddReturnType.groovy new file mode 100644 index 000000000000..5ed6f269cfdf --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/AddReturnType.groovy @@ -0,0 +1,3 @@ +class Foo { + def foo(String s){} +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/AddReturnType_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/AddReturnType_after.groovy new file mode 100644 index 000000000000..f1e098a69e01 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/AddReturnType_after.groovy @@ -0,0 +1,3 @@ +class Foo { + def int foo(String s){} +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/AnonymousClassUsage.groovy b/plugins/groovy/testdata/refactoring/changeSignature/AnonymousClassUsage.groovy new file mode 100644 index 000000000000..5ce4ba9b6e31 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/AnonymousClassUsage.groovy @@ -0,0 +1,9 @@ +class Foo { + def Foo(){} +} + +new Foo() { + def String toString() { + return super.toString(); + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/AnonymousClassUsage_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/AnonymousClassUsage_after.groovy new file mode 100644 index 000000000000..5c0dea5ed9b4 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/AnonymousClassUsage_after.groovy @@ -0,0 +1,9 @@ +class Foo { + def Foo(int p){} +} + +new Foo(5) { + def String toString() { + return super.toString(); + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/ChangeParameterType.groovy b/plugins/groovy/testdata/refactoring/changeSignature/ChangeParameterType.groovy new file mode 100644 index 000000000000..2a364da4ff75 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/ChangeParameterType.groovy @@ -0,0 +1 @@ +def foo(String s) {} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/ChangeParameterType_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/ChangeParameterType_after.groovy new file mode 100644 index 000000000000..26b2495a146e --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/ChangeParameterType_after.groovy @@ -0,0 +1 @@ +def foo(int p) {} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/ChangeReturnType.groovy b/plugins/groovy/testdata/refactoring/changeSignature/ChangeReturnType.groovy new file mode 100644 index 000000000000..5abf67ca64eb --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/ChangeReturnType.groovy @@ -0,0 +1,3 @@ +class Foo { + String foo(int x) {} +} diff --git a/plugins/groovy/testdata/refactoring/changeSignature/ChangeReturnType_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/ChangeReturnType_after.groovy new file mode 100644 index 000000000000..3b5dc737e1e3 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/ChangeReturnType_after.groovy @@ -0,0 +1,3 @@ +class Foo { + int foo(int x) {} +} diff --git a/plugins/groovy/testdata/refactoring/changeSignature/GroovyDocReferences.groovy b/plugins/groovy/testdata/refactoring/changeSignature/GroovyDocReferences.groovy new file mode 100644 index 000000000000..422e1863ec2b --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/GroovyDocReferences.groovy @@ -0,0 +1,9 @@ +class Foo { + /** + * @see Foo#foo(String, double, ArrayList) + */ + + def foo(String a, double y, ArrayList list) { + + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/GroovyDocReferences_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/GroovyDocReferences_after.groovy new file mode 100644 index 000000000000..cf7e0f57e419 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/GroovyDocReferences_after.groovy @@ -0,0 +1,9 @@ +class Foo { + /** + * @see Foo#foo(String, ArrayList) + */ + + def foo(String a, ArrayList list) { + + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorForClass.groovy b/plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorForClass.groovy new file mode 100644 index 000000000000..bfa6fd29a0c7 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorForClass.groovy @@ -0,0 +1,7 @@ +class Foo { + def Foo() {} +} + +class Bar extends Foo { + def get() {return "a"} +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorForClass_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorForClass_after.groovy new file mode 100644 index 000000000000..3c3b24fb2e98 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorForClass_after.groovy @@ -0,0 +1,10 @@ +class Foo { + def Foo(int p) {} +} + +class Bar extends Foo { +def Bar(){ +super(5) +} + def get() {return "a"} +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorInConstructor.groovy b/plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorInConstructor.groovy new file mode 100644 index 000000000000..ea0c86ff980f --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorInConstructor.groovy @@ -0,0 +1,7 @@ +class Foo { + def Foo() {} +} + +class Bar extends Foo { + def Bar() {} +} diff --git a/plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorInConstructor_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorInConstructor_after.groovy new file mode 100644 index 000000000000..01d4f34b9f7c --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorInConstructor_after.groovy @@ -0,0 +1,9 @@ +class Foo { + def Foo(int p) {} +} + +class Bar extends Foo { + def Bar() { +super(5) +} +} diff --git a/plugins/groovy/testdata/refactoring/changeSignature/Overriders.groovy b/plugins/groovy/testdata/refactoring/changeSignature/Overriders.groovy new file mode 100644 index 000000000000..54dad04cb9a5 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/Overriders.groovy @@ -0,0 +1,11 @@ +class Foo { + def foo(String s, double x) {} +} + +class Bar extends Foo { + def foo(String s, double x) {} +} + +class Baz extends Bar { + def foo(String s, double x) {} +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/Overriders_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/Overriders_after.groovy new file mode 100644 index 000000000000..bfa39caf276a --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/Overriders_after.groovy @@ -0,0 +1,11 @@ +class Foo { + def bar(String s) {} +} + +class Bar extends Foo { + def bar(String s) {} +} + +class Baz extends Bar { + def bar(String s) {} +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/ParameterRename.groovy b/plugins/groovy/testdata/refactoring/changeSignature/ParameterRename.groovy new file mode 100644 index 000000000000..384ab41e93ce --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/ParameterRename.groovy @@ -0,0 +1,15 @@ +class Foo { + def foo(String p) { + p = 5; + print p; + return p.substring(2) + } +} + +class Bar extends Foo { + def foo(String p) { + p = 5; + print p; + return p.substring(2) + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/ParameterRename_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/ParameterRename_after.groovy new file mode 100644 index 000000000000..c4d0bb8b13d1 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/ParameterRename_after.groovy @@ -0,0 +1,15 @@ +class Foo { + def foo(String newP) { + newP = 5; + print newP; + return newP.substring(2) + } +} + +class Bar extends Foo { + def foo(String newP) { + newP = 5; + print newP; + return newP.substring(2) + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/RemoveReturnType.groovy b/plugins/groovy/testdata/refactoring/changeSignature/RemoveReturnType.groovy new file mode 100644 index 000000000000..1a699d67c385 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/RemoveReturnType.groovy @@ -0,0 +1,3 @@ +class Foo { + String foo(int x){} +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/RemoveReturnType_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/RemoveReturnType_after.groovy new file mode 100644 index 000000000000..b1c67a419488 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/RemoveReturnType_after.groovy @@ -0,0 +1,3 @@ +class Foo { + def foo(int x){} +} \ No newline at end of file From 298b36095ec67e5c6e49af6f0962859ddfb78d49 Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Thu, 6 May 2010 14:22:18 +0400 Subject: [PATCH 015/212] groovy change signature dialog improvements --- .../GroovyRefactoringBundle.properties | 7 +++- .../GrChangeSignatureDialog.form | 4 +- .../GrChangeSignatureDialog.java | 42 ++++++++++--------- .../GrParameterTableModel.java | 17 ++------ 4 files changed, 33 insertions(+), 37 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties index fc06305f3201..10e8d5f43930 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties @@ -107,4 +107,9 @@ column.name.default.initializer=Default initializer column.name.default.value=Default value method.duplicate=Method with signature {0} is already defined in {1} replace.setter.for.property=The default setter for property ''{0}'' will be overwritten -replace.getter.for.property=The default getter for property ''{0}'' will be overwritten \ No newline at end of file +replace.getter.for.property=The default getter for property ''{0}'' will be overwritten +name.is.wrong=Name ''{0}'' is incorrect +incorrect.data=Incorrect data +return.type.is.wrong=Return type is wrong +type.for.parameter.is.incorrect=Type for parameter ''{0}'' is incorrect +specify.default.value=Specify default value for parameter ''{0}'' \ No newline at end of file diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.form b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.form index 1f3ca694ae7a..848e85b8f768 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.form +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.form @@ -10,7 +10,7 @@ - + @@ -18,7 +18,7 @@ - + diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java index 0b6ba62205f1..9540f6c3ce97 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java @@ -33,7 +33,6 @@ import com.intellij.ui.TableUtil; import com.intellij.ui.table.JBTable; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.debugger.fragments.GroovyCodeFragment; -import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement; @@ -47,6 +46,8 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.List; +import static org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle.message; + /** * @author Maxim.Medvedev */ @@ -166,8 +167,11 @@ public class GrChangeSignatureDialog extends RefactoringDialog { if (element != null) { myReturnTypeField.setText(element.getText()); } - + + myReturnTypeLabel = new JLabel(); myReturnTypeLabel.setLabelFor(myReturnTypeField); + + myNameLabel = new JLabel(); myNameLabel.setLabelFor(myNameField); } @@ -241,7 +245,9 @@ public class GrChangeSignatureDialog extends RefactoringDialog { private static void generateParameterText(GrParameterInfo info, StringBuilder builder) { final PsiTypeCodeFragment typeFragment = info.getTypeFragment(); - builder.append(typeFragment != null ? typeFragment.getText().trim() : GrModifier.DEF).append(' '); + String typeText = typeFragment != null ? typeFragment.getText().trim() : GrModifier.DEF; + if (typeText.length() == 0) typeText = GrModifier.DEF; + builder.append(typeText).append(' '); final GroovyCodeFragment nameFragment = info.getNameFragment(); builder.append(nameFragment != null ? nameFragment.getText().trim() : ""); final GroovyCodeFragment defaultInitializer = info.getDefaultInitializerFragment(); @@ -295,25 +301,32 @@ public class GrChangeSignatureDialog extends RefactoringDialog { } private boolean validateInputData() { - if (!checkName()) { - CommonRefactoringUtil.showErrorHint(myProject, null, "Name is wrong", "Incorrect data", HelpID.CHANGE_SIGNATURE); + if (!StringUtil.isJavaIdentifier(getNewName())) { + CommonRefactoringUtil + .showErrorHint(myProject, null, message("name.is.wrong", getNewName()), message("incorrect.data"), HelpID.CHANGE_SIGNATURE); return false; } if (!checkType(myReturnTypeCodeFragment)) { - CommonRefactoringUtil.showErrorHint(myProject, null, "Return type is wrong", "Incorrect data", HelpID.CHANGE_SIGNATURE); + CommonRefactoringUtil + .showErrorHint(myProject, null, message("return.type.is.wrong"), message("incorrect.data"), HelpID.CHANGE_SIGNATURE); return false; } for (GrParameterInfo info : myParameterModel.getParameterInfos()) { + if (!StringUtil.isJavaIdentifier(info.getName())) { + CommonRefactoringUtil + .showErrorHint(myProject, null, message("name.is.wrong", info.getName()), message("incorrect.data"), HelpID.CHANGE_SIGNATURE); + } if (!checkType(info.getTypeFragment())) { CommonRefactoringUtil - .showErrorHint(myProject, null, "Type for parameter " + info.getName() + " is wrong", "Incorrect data", HelpID.CHANGE_SIGNATURE); + .showErrorHint(myProject, null, message("type.for.parameter.is.incorrect", info.getName()), message("incorrect.data"), + HelpID.CHANGE_SIGNATURE); return false; } String defaultValue = info.getDefaultValue(); if (info.getOldIndex() < 0 && (defaultValue == null || defaultValue.trim().length() == 0)) { - CommonRefactoringUtil.showErrorHint(myProject, null, "Specify default value for parameter " + info.getName(), "Incorrect data", + CommonRefactoringUtil.showErrorHint(myProject, null, message("specify.default.value", info.getName()), message("incorrect.data"), HelpID.CHANGE_SIGNATURE); return false; } @@ -321,7 +334,7 @@ public class GrChangeSignatureDialog extends RefactoringDialog { return true; } - private boolean checkType(PsiTypeCodeFragment typeCodeFragment) { + private static boolean checkType(PsiTypeCodeFragment typeCodeFragment) { try { typeCodeFragment.getType(); } @@ -334,15 +347,4 @@ public class GrChangeSignatureDialog extends RefactoringDialog { return true; } - private boolean checkName() { - final String newName = getNewName(); - if (StringUtil.isJavaIdentifier(newName)) return true; - try { - GroovyPsiElementFactory.getInstance(myProject).createMethodFromText("def " + newName + "(){}"); - } - catch (Throwable e) { - return false; - } - return true; - } } \ No newline at end of file diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterTableModel.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterTableModel.java index ccaa2e22ad20..ee6287c3afc2 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterTableModel.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterTableModel.java @@ -98,19 +98,6 @@ public class GrParameterTableModel extends AbstractTableModel implements RowEdit public void setValueAt(Object value, int rowIndex, int columnIndex) { if (rowIndex < 0 || rowIndex >= infos.size()) return; if (columnIndex < 0 || columnIndex > 3) return; - /*String s = value instanceof String ? (String)value : ""; - s = s.trim(); - final GrParameterInfo info = infos.get(rowIndex); - switch (columnIndex) { - case 0: - info.setType(s); - case 1: - info.setName(s); - case 2: - info.setDefaultInitializer(s); - case 3: - info.setDefaultValue(s); - }*/ fireTableCellUpdated(rowIndex, columnIndex); } @@ -147,7 +134,9 @@ public class GrParameterTableModel extends AbstractTableModel implements RowEdit @Override public boolean isCellEditable(int rowIndex, int columnIndex) { - return true; + if (columnIndex < 3) return true; + GrParameterInfo info = infos.get(rowIndex); + return info.getOldIndex() < 0; } public List getParameterInfos() { From 675ac58ca39841dbbb064a5cbc254d933ace91f3 Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Fri, 14 May 2010 15:12:09 +0400 Subject: [PATCH 016/212] find conflicts & generate delegate --- .../ChangeSignatureProcessor.java | 1 + .../JavaChangeSignatureUsageProcessor.java | 15 +- .../JavaChangeSignatureUsageSearcher.java | 39 ++-- .../typedef/members/GrMethodBaseImpl.java | 3 + .../psi/impl/synthetic/GroovyScriptClass.java | 10 + .../GroovyRefactoringBundle.properties | 8 +- .../GrChageSignatureUsageSearcher.java | 8 +- .../changeSignature/GrChangeInfoImpl.java | 27 +-- .../GrChangeSignatureConflictSearcher.java | 2 +- .../GrChangeSignatureDialog.form | 184 +++++++++--------- .../GrChangeSignatureDialog.java | 105 +++------- .../GrChangeSignatureProcessor.java | 32 ++- .../GrChangeSignatureUsageProcessor.java | 71 +++++-- .../changeSignature/GrMethodConflictUtil.java | 80 ++++++-- .../changeSignature/TableWithButtons.form | 73 +++++++ .../changeSignature/TableWithButtons.java | 121 ++++++++++++ .../changeSignature/ChangeSignatureTest.java | 21 +- .../changeSignature/GenerateDelegate.groovy | 9 + .../GenerateDelegate_after.groovy | 13 ++ 19 files changed, 547 insertions(+), 275 deletions(-) create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/TableWithButtons.form create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/TableWithButtons.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/GenerateDelegate.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/GenerateDelegate_after.groovy diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java index 2b624ad14c11..e83f00598218 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java @@ -139,6 +139,7 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor { } final UsageInfo[] usagesIn = refUsages.get(); + RenameUtil.addConflictDescriptions(usagesIn, conflictDescriptions); Set usagesSet = new HashSet(Arrays.asList(usagesIn)); RenameUtil.removeConflictUsages(usagesSet); if (myPrepareSuccessfulSwingThreadCallback != null && !conflictDescriptions.isEmpty()) { diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java index d8a3ae5ffa3a..845ff02d9e59 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java @@ -531,11 +531,10 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr if (changeInfo.isVisibilityChanged()) { PsiModifierList modifierList = method.getModifierList(); - final String highestVisibility = isOriginal ? - changeInfo.getNewVisibility() : - VisibilityUtil - .getHighestVisibility(changeInfo.getNewVisibility(), - VisibilityUtil.getVisibilityModifier(modifierList)); + final String highestVisibility = isOriginal + ? changeInfo.getNewVisibility() + : VisibilityUtil.getHighestVisibility(changeInfo.getNewVisibility(), + VisibilityUtil.getVisibilityModifier(modifierList)); VisibilityUtil.setVisibility(modifierList, highestVisibility); } @@ -765,9 +764,7 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr public MultiMap findConflicts(Ref refUsages) { MultiMap conflictDescriptions = new MultiMap(); addMethodConflicts(conflictDescriptions); - UsageInfo[] usagesIn = refUsages.get(); - RenameUtil.addConflictDescriptions(usagesIn, conflictDescriptions); - Set usagesSet = new HashSet(Arrays.asList(usagesIn)); + Set usagesSet = new HashSet(Arrays.asList(refUsages.get())); RenameUtil.removeConflictUsages(usagesSet); if (myChangeInfo.isVisibilityChanged()) { try { @@ -795,7 +792,7 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr for (Iterator iterator = usages.iterator(); iterator.hasNext();) { UsageInfo usageInfo = iterator.next(); PsiElement element = usageInfo.getElement(); - if (element != null) { + if (element != null && StdLanguages.JAVA.equals(element.getLanguage())) { if (element instanceof PsiReferenceExpression) { PsiClass accessObjectClass = null; PsiExpression qualifier = ((PsiReferenceExpression)element).getQualifierExpression(); diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageSearcher.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageSearcher.java index 00eef0ce427b..a6965af58299 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageSearcher.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageSearcher.java @@ -119,30 +119,29 @@ class JavaChangeSignatureUsageSearcher { if (isOriginal) { //Name changes take place only in primary method final PsiParameter parameter = parameters[oldParameterIndex]; if (!newName.equals(parameter.getName())) { - JavaUnresolvableLocalCollisionDetector.visitLocalsCollisions(parameter, newName, method.getBody(), null, - new JavaUnresolvableLocalCollisionDetector.CollidingVariableVisitor() { - public void visitCollidingElement(final PsiVariable collidingVariable) { - if (!deletedOrRenamedParameters - .contains(collidingVariable)) { - result.add( - new RenamedParameterCollidesWithLocalUsageInfo( - parameter, collidingVariable, method)); - } - } - }); + JavaUnresolvableLocalCollisionDetector.visitLocalsCollisions( + parameter, newName, method.getBody(), null, + new JavaUnresolvableLocalCollisionDetector.CollidingVariableVisitor() { + public void visitCollidingElement(final PsiVariable collidingVariable) { + if (!deletedOrRenamedParameters.contains(collidingVariable)) { + result.add(new RenamedParameterCollidesWithLocalUsageInfo(parameter, collidingVariable, method)); + } + } + }); } } } else { - JavaUnresolvableLocalCollisionDetector.visitLocalsCollisions(method, newName, method.getBody(), null, - new JavaUnresolvableLocalCollisionDetector.CollidingVariableVisitor() { - public void visitCollidingElement(PsiVariable collidingVariable) { - if (!deletedOrRenamedParameters.contains(collidingVariable)) { - result.add(new NewParameterCollidesWithLocalUsageInfo( - collidingVariable, collidingVariable, method)); - } - } - }); + JavaUnresolvableLocalCollisionDetector.visitLocalsCollisions( + method, newName, method.getBody(), null, + new JavaUnresolvableLocalCollisionDetector.CollidingVariableVisitor() { + public void visitCollidingElement(PsiVariable collidingVariable) { + if (!deletedOrRenamedParameters.contains(collidingVariable)) { + result.add(new NewParameterCollidesWithLocalUsageInfo( + collidingVariable, collidingVariable, method)); + } + } + }); } } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodBaseImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodBaseImpl.java index 84da9a1320ab..b8190ba6850d 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodBaseImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodBaseImpl.java @@ -32,6 +32,7 @@ import com.intellij.psi.util.MethodSignature; import com.intellij.psi.util.MethodSignatureBackedByPsiMethod; import com.intellij.psi.util.TypeConversionUtil; import com.intellij.ui.RowIcon; +import com.intellij.util.ArrayUtil; import com.intellij.util.Function; import com.intellij.util.IncorrectOperationException; import com.intellij.util.NullableFunction; @@ -393,6 +394,8 @@ public abstract class GrMethodBaseImpl extends GroovyBaseEl @Nullable public PsiMethod findDeepestSuperMethod() { + final PsiMethod[] methods = findDeepestSuperMethods(); + if (methods.length > 0) return methods[0]; return null; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GroovyScriptClass.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GroovyScriptClass.java index 37fb3f58a480..4334774acdc0 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GroovyScriptClass.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GroovyScriptClass.java @@ -125,6 +125,16 @@ public class GroovyScriptClass extends LightElement implements GrMemberOwner, Sy return myFile.add(element); } + @Override + public PsiElement addAfter(@NotNull PsiElement element, PsiElement anchor) throws IncorrectOperationException { + return myFile.addAfter(element, anchor); + } + + @Override + public PsiElement addBefore(@NotNull PsiElement element, PsiElement anchor) throws IncorrectOperationException { + return myFile.addBefore(element, anchor); + } + public PsiReferenceList getExtendsList() { return null; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties index 10e8d5f43930..8355088fcbc6 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties @@ -100,6 +100,10 @@ introduce.parameter.title=Introduce Parameter groovy.does.not.support.inner.classes.but.it.is.used.in.parameter.initializer=Groovy does not support inner classes but it is used in parameter initializer. groovy.does.not.support.anonymous.classes.but.it.is.used.in.parameter.initializer=Groovy does not support anonymous classes but it is used in parameter initializer. error.wrong.caret.position.method.name=The caret should be positioned at the name of the method to be refactored. + +######################################################################################################################## +# Change signature +######################################################################################################################## changeSignature.refactoring.name=Change Signature column.name.type=Type column.name.name=Name @@ -112,4 +116,6 @@ name.is.wrong=Name ''{0}'' is incorrect incorrect.data=Incorrect data return.type.is.wrong=Return type is wrong type.for.parameter.is.incorrect=Type for parameter ''{0}'' is incorrect -specify.default.value=Specify default value for parameter ''{0}'' \ No newline at end of file +specify.default.value=Specify default value for parameter ''{0}'' +changing.signature.of.0=Changing signature of {0} +refactored.method.will.cover.closure.property=Refactored method will override closure property ''{0}'' in {1} \ No newline at end of file diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChageSignatureUsageSearcher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChageSignatureUsageSearcher.java index 25f1c0748118..072f880bdadc 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChageSignatureUsageSearcher.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChageSignatureUsageSearcher.java @@ -203,11 +203,11 @@ class GrChageSignatureUsageSearcher { boolean isToCatchExceptions = isToThrowExceptions && needToCatchExceptions(RefactoringUtil.getEnclosingMethod(element)); //todo check for applicability of arguments to method if (PsiUtil.isMethodUsage(element)) { - GrClosureSignature signature = GrClosureSignatureUtil.createSignature(method); + GrClosureSignature signature = GrClosureSignatureUtil.createSignature(method, PsiSubstitutor.EMPTY); GrClosureSignatureUtil.ArgInfo[] map = GrClosureSignatureUtil .mapParametersToArguments(signature, PsiUtil.getArgumentsList(element), method.getManager(), method.getResolveScope()); result.add( - new GrMethodCallUsageInfo(element, GrClosureSignatureUtil.createSignature(method), isToModifyArgs, isToCatchExceptions, map)); + new GrMethodCallUsageInfo(element, GrClosureSignatureUtil.createSignature(method, PsiSubstitutor.EMPTY), isToModifyArgs, isToCatchExceptions, map)); } else if (element instanceof GrDocTagValueToken) { result.add(new UsageInfo(ref.getElement())); @@ -221,11 +221,11 @@ class GrChageSignatureUsageSearcher { LOG.assertTrue(method.isConstructor()); final PsiClass psiClass = (PsiClass)element; if (psiClass instanceof GrAnonymousClassDefinition) { - GrClosureSignature signature = GrClosureSignatureUtil.createSignature(method); + GrClosureSignature signature = GrClosureSignatureUtil.createSignature(method, PsiSubstitutor.EMPTY); GrClosureSignatureUtil.ArgInfo[] map = GrClosureSignatureUtil .mapParametersToArguments(signature, PsiUtil.getArgumentsList(element), method.getManager(), method.getResolveScope()); result.add( - new GrMethodCallUsageInfo(element, GrClosureSignatureUtil.createSignature(method), isToModifyArgs, isToCatchExceptions, map)); + new GrMethodCallUsageInfo(element, GrClosureSignatureUtil.createSignature(method, PsiSubstitutor.EMPTY), isToModifyArgs, isToCatchExceptions, map)); continue; } /*if (!(myChangeInfo instanceof JavaChangeInfoImpl)) continue; todo propagate methods diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeInfoImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeInfoImpl.java index 88fe621425fd..db653ca5cabb 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeInfoImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeInfoImpl.java @@ -52,17 +52,19 @@ class GrChangeInfoImpl implements JavaChangeInfo { private String myOldName; private PsiIdentifier myNewNameIdentifier; private PsiExpression[] defaultValues; + private boolean myDelegate; public GrChangeInfoImpl(GrMethod method, String visibilityModifier, @Nullable CanonicalTypes.Type returnType, String newName, - List parameters) { + List parameters, boolean generateDelegate) { this.method = method; this.visibilityModifier = visibilityModifier; this.returnType = returnType; this.parameters = parameters; this.newName = newName; + myDelegate = generateDelegate; myOldName = method.getName(); if (!method.getName().equals(newName)) { @@ -113,13 +115,14 @@ class GrChangeInfoImpl implements JavaChangeInfo { } myWasVarargs = method.isVarArgs(); - if (parameters.size()==0) { - myIsObtainVarargs=false; - myIsRetainVarargs=false; - myIsArrayToVarargs=false; - } else { + if (parameters.size() == 0) { + myIsObtainVarargs = false; + myIsRetainVarargs = false; + myIsArrayToVarargs = false; + } + else { GrParameterInfo lastNewParam = parameters.get(parameters.size() - 1); - myIsObtainVarargs= lastNewParam.isVarargType(); + myIsObtainVarargs = lastNewParam.isVarargType(); myIsRetainVarargs = lastNewParam.getOldIndex() >= 0 && myIsObtainVarargs; if (myIsRetainVarargs) { final PsiType oldTypeForVararg = params[lastNewParam.getOldIndex()].getType(); @@ -136,14 +139,14 @@ class GrChangeInfoImpl implements JavaChangeInfo { PsiElementFactory factory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory(); defaultValues = new PsiExpression[parameters.size()]; - for(int i = 0; i < parameters.size(); i++){ + for (int i = 0; i < parameters.size(); i++) { JavaParameterInfo info = parameters.get(i); - if (info.getOldIndex() < 0 && !info.isVarargType()){ + if (info.getOldIndex() < 0 && !info.isVarargType()) { if (info.getDefaultValue() == null) continue; - try{ + try { defaultValues[i] = factory.createExpressionFromText(info.getDefaultValue(), method); } - catch(IncorrectOperationException e){ + catch (IncorrectOperationException e) { // LOG.error(e); } } @@ -173,7 +176,7 @@ class GrChangeInfoImpl implements JavaChangeInfo { } public boolean isGenerateDelegate() { - return false; + return myDelegate; } public boolean isNameChanged() { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureConflictSearcher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureConflictSearcher.java index 3ed5c47b3a3d..1ebefc2c49b1 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureConflictSearcher.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureConflictSearcher.java @@ -152,7 +152,7 @@ class GrChangeSignatureConflictSearcher { } ConflictsUtil.checkMethodConflicts(method.getContainingClass(), method, prototype, conflicts); - GrMethodConflictUtil.checkMethodConflicts(method.getContainingClass(), prototype, ((GrMethod)method), conflicts); + GrMethodConflictUtil.checkMethodConflicts(method.getContainingClass(), prototype, ((GrMethod)method), conflicts, true); } catch (IncorrectOperationException e) { LOG.error(e); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.form b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.form index 848e85b8f768..e60e6f42e45d 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.form +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.form @@ -1,9 +1,9 @@
- + - + @@ -12,7 +12,7 @@ - + @@ -20,7 +20,7 @@ - + @@ -29,13 +29,12 @@ - + - - + @@ -43,68 +42,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -149,39 +87,93 @@ - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -190,5 +182,9 @@ + + + + diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java index 9540f6c3ce97..9a8411ac35de 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java @@ -40,10 +40,7 @@ import org.jetbrains.plugins.groovy.refactoring.ui.GrCodeFragmentTableCellEditor import org.jetbrains.plugins.groovy.refactoring.ui.GrCodeFragmentTableCellRenderer; import javax.swing.*; -import javax.swing.event.TableModelEvent; -import javax.swing.event.TableModelListener; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; +import java.awt.*; import java.util.List; import static org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle.message; @@ -59,17 +56,14 @@ public class GrChangeSignatureDialog extends RefactoringDialog { private JRadioButton myPrivateRadioButton; private JPanel myParametersPanel; private JBTable myParameterTable; - private JButton myAddButton; - private JButton myRemoveButton; - private JButton myMoveUpButton; - private JButton myMoveDownButton; private JPanel contentPane; private JLabel mySignatureLabel; private JLabel myNameLabel; private JLabel myReturnTypeLabel; + private JRadioButton myModifyRadioButton; + private JRadioButton myDelegateRadioButton; private GrParameterTableModel myParameterModel; private GrMethod myMethod; -// private Project myProject; private PsiTypeCodeFragment myReturnTypeCodeFragment; private GroovyCodeFragment myNameCodeFragment; @@ -77,63 +71,11 @@ public class GrChangeSignatureDialog extends RefactoringDialog { super(project, true); myMethod = method; init(); - configureParameterButtons(); + createParametersPanel(); + createExceptionsPanel(); updateSignature(); } - private void configureParameterButtons() { - myAddButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - int selectedColumn = myParameterTable.getSelectedColumn(); - if (selectedColumn < 0) selectedColumn = 0; - myParameterModel.addRow(); - myParameterTable.setRowSelectionInterval(myParameterModel.getRowCount() - 1, myParameterModel.getRowCount() - 1); - myParameterTable.setColumnSelectionInterval(selectedColumn, selectedColumn); - updateSignature(); - myParameterTable.requestFocus(); - } - }); - myRemoveButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - int selectedRow = myParameterTable.getSelectedRow(); - int selectedColumn = myParameterTable.getSelectedColumn(); - - myParameterModel.removeRow(myParameterTable.getSelectedRow()); - - if (selectedRow == myParameterModel.getRowCount()) selectedRow--; - if (myParameterModel.getRowCount() == 0) return; - myParameterTable.setRowSelectionInterval(selectedRow, selectedRow); - myParameterTable.setColumnSelectionInterval(selectedColumn, selectedColumn); - updateSignature(); - myParameterTable.requestFocus(); - } - }); - - myMoveUpButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - final int selectedRow = myParameterTable.getSelectedRow(); - int selectedColumn = myParameterTable.getSelectedColumn(); - myParameterModel.exchangeRows(selectedRow, selectedRow - 1); - myParameterTable.setRowSelectionInterval(selectedRow - 1, selectedRow - 1); - myParameterTable.setColumnSelectionInterval(selectedColumn, selectedColumn); - updateSignature(); - myParameterTable.requestFocus(); - } - }); - - myMoveDownButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - final int selectedRow = myParameterTable.getSelectedRow(); - int selectedColumn = myParameterTable.getSelectedColumn(); - myParameterModel.exchangeRows(selectedRow, selectedRow + 1); - myParameterTable.setRowSelectionInterval(selectedRow + 1, selectedRow + 1); - myParameterTable.setColumnSelectionInterval(selectedColumn, selectedColumn); - updateSignature(); - myParameterTable.requestFocus(); - } - }); - } - protected void init() { super.init(); } @@ -150,7 +92,6 @@ public class GrChangeSignatureDialog extends RefactoringDialog { private void createUIComponents() { createNameAndReturnTypeEditors(); - createParametersModel(); } private void createNameAndReturnTypeEditors() { @@ -175,9 +116,16 @@ public class GrChangeSignatureDialog extends RefactoringDialog { myNameLabel.setLabelFor(myNameField); } - private void createParametersModel() { + private void createParametersPanel() { myParameterModel = new GrParameterTableModel(myMethod, this, myProject); - myParameterTable = new JBTable(myParameterModel); + TableWithButtons parameterTable = new TableWithButtons(myParameterModel) { + @Override + protected void update() { + updateSignature(); + } + }; + + myParameterTable = parameterTable.getTable(); myParameterTable.setCellSelectionEnabled(true); myParameterTable.getColumnModel().getColumn(0).setCellRenderer(new CodeFragmentTableCellRenderer(myProject)); @@ -190,26 +138,17 @@ public class GrChangeSignatureDialog extends RefactoringDialog { myParameterTable.getColumnModel().getColumn(2).setCellEditor(new GrCodeFragmentTableCellEditor(myProject)); myParameterTable.getColumnModel().getColumn(3).setCellEditor(new GrCodeFragmentTableCellEditor(myProject)); - if (myParameterTable.getRowCount() > 0) { - myParameterTable.setRowSelectionInterval(0, 0); - myParameterTable.setColumnSelectionInterval(0, 0); - } - - myParameterModel.addTableModelListener(new TableModelListener() { - public void tableChanged(TableModelEvent e) { - updateSignature(); - } - }); + myParameterTable.setRowSelectionInterval(0, 0); + myParameterTable.setColumnSelectionInterval(0, 0); + myParametersPanel.add(parameterTable.getPanel(), BorderLayout.CENTER); } - private void updateSignature() { - final int selectedRow = myParameterTable.getSelectedRow(); - final int rowCount = myParameterModel.getRowCount(); - myMoveUpButton.setEnabled(selectedRow > 0); - myMoveDownButton.setEnabled(selectedRow + 1 < rowCount && rowCount > 1); - myRemoveButton.setEnabled(rowCount > 0); + private void createExceptionsPanel() { + } + + private void updateSignature() { mySignatureLabel.setText(generateSignatureText()); } @@ -292,7 +231,7 @@ public class GrChangeSignatureDialog extends RefactoringDialog { ? null : CanonicalTypes.createTypeWrapper( returnType), newName, - parameterInfos))); + parameterInfos, myDelegateRadioButton.isSelected()))); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java index 83be6dbb8122..b18e4fafe209 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java @@ -23,13 +23,17 @@ import com.intellij.psi.PsiMethod; import com.intellij.refactoring.BaseRefactoringProcessor; import com.intellij.refactoring.changeSignature.ChangeSignatureUsageProcessor; import com.intellij.refactoring.changeSignature.ChangeSignatureViewDescriptor; +import com.intellij.refactoring.rename.RenameUtil; +import com.intellij.refactoring.ui.ConflictsDialog; import com.intellij.refactoring.util.MoveRenameUsageInfo; import com.intellij.usageView.UsageInfo; import com.intellij.usageView.UsageViewDescriptor; +import com.intellij.usageView.UsageViewUtil; import com.intellij.util.containers.HashSet; import com.intellij.util.containers.MultiMap; import com.intellij.util.containers.hash.HashMap; import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle; import java.util.*; @@ -118,13 +122,7 @@ public class GrChangeSignatureProcessor extends BaseRefactoringProcessor { @Override protected String getCommandName() { - return ""; - //return RefactoringBundle.message("changing.signature.of.0", UsageViewUtil.getDescriptiveName(myChangeInfo.getMethod())); - } - - - private MultiMap findConflicts(Ref refUsages) { - return new MultiMap();//todo + return GroovyRefactoringBundle.message("changing.signature.of.0", UsageViewUtil.getDescriptiveName(myChangeInfo.getMethod())); } @Override @@ -140,6 +138,24 @@ public class GrChangeSignatureProcessor extends BaseRefactoringProcessor { } } - return showConflicts(conflictDescriptions); + final UsageInfo[] usagesIn = refUsages.get(); + RenameUtil.addConflictDescriptions(usagesIn, conflictDescriptions); + Set usagesSet = new HashSet(Arrays.asList(usagesIn)); + RenameUtil.removeConflictUsages(usagesSet); + if (!conflictDescriptions.isEmpty()) { + ConflictsDialog dialog = new ConflictsDialog(myProject, conflictDescriptions, new Runnable() { + public void run() { + execute(usagesIn); + } + }); + dialog.show(); + if (!dialog.isOK()) { + if (dialog.isShowConflicts()) prepareSuccessful(); + return false; + } + } + refUsages.set(usagesSet.toArray(new UsageInfo[usagesSet.size()])); + prepareSuccessful(); + return true; } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java index 61918afac0f1..7f3be3fcc0ed 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java @@ -17,10 +17,8 @@ package org.jetbrains.plugins.groovy.refactoring.changeSignature; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Ref; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiMethod; -import com.intellij.psi.PsiReference; -import com.intellij.psi.PsiType; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.changeSignature.*; @@ -87,10 +85,48 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc GrChangeInfoImpl grInfo = (GrChangeInfoImpl)changeInfo; GrMethod method = grInfo.getMethod(); + if (grInfo.isGenerateDelegate()) { + return generateDelegate(grInfo); + } return processPrimaryMethodInner(grInfo, method, null); } + private static boolean generateDelegate(GrChangeInfoImpl grInfo) { + final GrMethod method = grInfo.getMethod(); + final PsiClass psiClass = method.getContainingClass(); + GrMethod newMethod = (GrMethod)method.copy(); + newMethod = (GrMethod)psiClass.addAfter(newMethod, method); + StringBuffer buffer = new StringBuffer(); + buffer.append("\n"); + if (!PsiType.VOID.equals(method.getReturnType())) { + buffer.append("return "); + } + buffer.append(method.getName()).append("("); + + final GrParameter[] oldParameters = method.getParameterList().getParameters(); + final JavaParameterInfo[] parameters = grInfo.getNewParameters(); + + String[] params = new String[parameters.length]; + for (int i = 0; i < parameters.length; i++) { + JavaParameterInfo parameter = parameters[i]; + final int oldIndex = parameter.getOldIndex(); + if (oldIndex >= 0) { + params[i] = oldParameters[oldIndex].getName(); + } + else { + params[i] = parameter.getDefaultValue(); + } + } + buffer.append(StringUtil.join(params, ",")); + buffer.append(");"); + + final GrCodeBlock codeBlock = GroovyPsiElementFactory.getInstance(method.getProject()).createMethodBodyFromText(buffer.toString()); + newMethod.setBlock(codeBlock); + CodeStyleManager.getInstance(method.getProject()).reformat(newMethod); + return processPrimaryMethodInner(grInfo, method, null); + } + private static boolean processPrimaryMethodInner(JavaChangeInfo changeInfo, GrMethod method, PsiMethod baseMethod) { if (changeInfo.isNameChanged()) { String newName = baseMethod == null ? changeInfo.getNewName() : @@ -115,7 +151,8 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc modifierList.setModifierProperty(GrModifier.DEF, true); } } - } else { + } + else { PsiType type = newReturnType.getType(method.getParameterList(), method.getManager()); method.setReturnType(type); } @@ -135,16 +172,16 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc int index = newParameter.getOldIndex(); if (index < 0) { */ - String typeText; - if (newParameter instanceof GrParameterInfo && ((GrParameterInfo)newParameter).hasNoType()) { - typeText = null; - } - else { - typeText = newParameter.getTypeText(); - } - GrParameter grParameter = - factory.createParameter(newParameter.getName(), typeText, getInitializer(newParameter), parameterList); - anchor = (GrParameter)parameterList.addAfter(grParameter, anchor); + String typeText; + if (newParameter instanceof GrParameterInfo && ((GrParameterInfo)newParameter).hasNoType()) { + typeText = null; + } + else { + typeText = newParameter.getTypeText(); + } + GrParameter grParameter = + factory.createParameter(newParameter.getName(), typeText, getInitializer(newParameter), parameterList); + anchor = (GrParameter)parameterList.addAfter(grParameter, anchor); /* } else { GrParameter grParameter = oldParameters[index]; @@ -170,7 +207,9 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc } @Nullable - private static Type getNextOfType(List parameterList, PsiElement current, Class type) { + private static Type getNextOfType(List parameterList, + PsiElement current, + Class type) { return current != null ? PsiTreeUtil.getNextSiblingOfType(current, type) : PsiTreeUtil.getChildOfType(parameterList, type); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodConflictUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodConflictUtil.java index 5246e227649f..28deeeb2f766 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodConflictUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodConflictUtil.java @@ -15,10 +15,7 @@ */ package org.jetbrains.plugins.groovy.refactoring.changeSignature; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiMethod; -import com.intellij.psi.PsiSubstitutor; +import com.intellij.psi.*; import com.intellij.psi.util.MethodSignature; import com.intellij.refactoring.util.RefactoringUIUtil; import com.intellij.util.containers.MultiMap; @@ -26,6 +23,10 @@ import org.jetbrains.plugins.groovy.lang.documentation.GroovyPresentationUtil; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; +import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureParameter; +import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature; +import org.jetbrains.plugins.groovy.lang.psi.impl.GrClosureType; +import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil; import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils; import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle; @@ -42,20 +43,66 @@ public class GrMethodConflictUtil { public static void checkMethodConflicts(PsiClass clazz, GrMethod prototype, GrMethod refactoredMethod, - final MultiMap conflicts) { - checkForSignatureOverload(clazz, prototype, refactoredMethod, conflicts); + final MultiMap conflicts, boolean excludeJavaConflicts) { + List prototypeSignatures = GrClosureSignatureUtil.generateAllSignaturesForMethod(prototype, PsiSubstitutor.EMPTY); + checkForClosurePropertySignatrureOverload(clazz, prototype, refactoredMethod, conflicts, prototypeSignatures); + checkForMethodSignatureOverload(clazz, prototype, refactoredMethod, conflicts, excludeJavaConflicts, prototypeSignatures); + checkForAccessorOverloading(clazz, prototype, conflicts); } - private static void checkForSignatureOverload(PsiClass clazz, - GrMethod prototype, - GrMethod refactoredMethod, - MultiMap conflicts) { + private static void checkForClosurePropertySignatrureOverload(PsiClass clazz, + GrMethod prototype, + GrMethod refactoredMethod, + MultiMap conflicts, + List prototypeSignatures) { + final boolean isStatic = prototype.hasModifierProperty(GrModifier.STATIC); + final String name = prototype.getName(); + if (!GroovyPropertyUtils.isProperty(clazz, name, isStatic)) return; + + final PsiMethod getter = GroovyPropertyUtils.findPropertyGetter(clazz, name, isStatic, true); + + final PsiType returnType; + if (getter instanceof GrMethod) { + returnType = ((GrMethod)getter).getInferredReturnType(); + } + else if (getter instanceof GrAccessorMethod) { + returnType = ((GrAccessorMethod)getter).getInferredReturnType(); + } + else { + return; + } + if (!(returnType instanceof GrClosureType)) return; + + final GrClosureSignature signature = ((GrClosureType)returnType).getSignature(); + + NextSignature: + for (MethodSignature prototypeSignature : prototypeSignatures) { + final GrClosureParameter[] params = signature.getParameters(); + final PsiType[] types = prototypeSignature.getParameterTypes(); + if (types.length != params.length) continue; + for (int i = 0; i < types.length; i++) { + if (!TypesUtil.isAssignableByMethodCallConversion(types[i], params[i].getType(), refactoredMethod.getParameterList())) { + continue NextSignature; + } + } + conflicts.putValue(getter, GroovyRefactoringBundle.message("refactored.method.will.cover.closure.property", name, RefactoringUIUtil.getDescription(getter.getContainingClass(), false))); + } + } + + private static void checkForMethodSignatureOverload(PsiClass clazz, + GrMethod prototype, + GrMethod refactoredMethod, + MultiMap conflicts, + boolean excludeJavaConflicts, + List prototypeSignatures) { + if (excludeJavaConflicts) { + prototypeSignatures.remove(prototype.getSignature(PsiSubstitutor.EMPTY)); + } + String newName = prototype.getName(); PsiMethod[] methods = clazz.findMethodsByName(newName, false); MultiMap signatures = GrClosureSignatureUtil.findMethodSignatures(methods); - List prototypeSignatures = GrClosureSignatureUtil.generateAllSignaturesForMethod(prototype, PsiSubstitutor.EMPTY); - for (MethodSignature prototypeSignature : prototypeSignatures) { for (PsiMethod method : signatures.get(prototypeSignature)) { if (method != refactoredMethod) { @@ -74,18 +121,15 @@ public class GrMethodConflictUtil { if (GroovyPropertyUtils.isSimplePropertySetter(prototype)) { String propertyName = GroovyPropertyUtils.getPropertyNameBySetter(prototype); PsiMethod setter = - GroovyPropertyUtils.findPropertySetter(clazz, propertyName, prototype.hasModifierProperty( - GrModifier.STATIC), false); + GroovyPropertyUtils.findPropertySetter(clazz, propertyName, prototype.hasModifierProperty(GrModifier.STATIC), false); if (setter instanceof GrAccessorMethod) { conflicts.putValue(setter, GroovyRefactoringBundle.message("replace.setter.for.property", propertyName)); } } else if (GroovyPropertyUtils.isSimplePropertyGetter(prototype)) { - boolean isStatic = prototype.hasModifierProperty( - GrModifier.STATIC); + boolean isStatic = prototype.hasModifierProperty(GrModifier.STATIC); String propertyName = GroovyPropertyUtils.getPropertyNameByGetter(prototype); - PsiMethod getter = - GroovyPropertyUtils.findPropertyGetter(clazz, propertyName, isStatic, false); + PsiMethod getter = GroovyPropertyUtils.findPropertyGetter(clazz, propertyName, isStatic, false); if (getter instanceof GrAccessorMethod) { conflicts.putValue(getter, GroovyRefactoringBundle.message("replace.getter.for.property", propertyName)); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/TableWithButtons.form b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/TableWithButtons.form new file mode 100644 index 000000000000..f19c2b2bcfc7 --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/TableWithButtons.form @@ -0,0 +1,73 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/TableWithButtons.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/TableWithButtons.java new file mode 100644 index 000000000000..8467d6788b89 --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/TableWithButtons.java @@ -0,0 +1,121 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.groovy.refactoring.changeSignature; + +import com.intellij.ui.RowEditableTableModel; +import com.intellij.ui.table.JBTable; + +import javax.swing.*; +import javax.swing.event.TableModelEvent; +import javax.swing.event.TableModelListener; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * @author Maxim.Medvedev + */ +public abstract class TableWithButtons { + public TableWithButtons(RowEditableTableModel model) { + myModel = model; + myAddButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + int selectedColumn = myTable.getSelectedColumn(); + if (selectedColumn < 0) selectedColumn = 0; + myModel.addRow(); + myTable.setRowSelectionInterval(myModel.getRowCount() - 1, myModel.getRowCount() - 1); + myTable.setColumnSelectionInterval(selectedColumn, selectedColumn); + innerUpdate(); + myTable.requestFocus(); + } + }); + myRemoveButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + int selectedRow = myTable.getSelectedRow(); + int selectedColumn = myTable.getSelectedColumn(); + + myModel.removeRow(myTable.getSelectedRow()); + + if (selectedRow == myModel.getRowCount()) selectedRow--; + if (myModel.getRowCount() == 0) return; + myTable.setRowSelectionInterval(selectedRow, selectedRow); + myTable.setColumnSelectionInterval(selectedColumn, selectedColumn); + innerUpdate(); + myTable.requestFocus(); + } + }); + myMoveUpButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + final int selectedRow = myTable.getSelectedRow(); + int selectedColumn = myTable.getSelectedColumn(); + myModel.exchangeRows(selectedRow, selectedRow - 1); + myTable.setRowSelectionInterval(selectedRow - 1, selectedRow - 1); + myTable.setColumnSelectionInterval(selectedColumn, selectedColumn); + innerUpdate(); + myTable.requestFocus(); + } + }); + myMoveDownButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + final int selectedRow = myTable.getSelectedRow(); + int selectedColumn = myTable.getSelectedColumn(); + myModel.exchangeRows(selectedRow, selectedRow + 1); + myTable.setRowSelectionInterval(selectedRow + 1, selectedRow + 1); + myTable.setColumnSelectionInterval(selectedColumn, selectedColumn); + innerUpdate(); + myTable.requestFocus(); + } + }); + + myModel.addTableModelListener(new TableModelListener() { + public void tableChanged(TableModelEvent e) { + innerUpdate(); + } + }); + } + + private RowEditableTableModel myModel; + + private JPanel myPanel; + private JButton myAddButton; + private JButton myRemoveButton; + private JButton myMoveUpButton; + private JButton myMoveDownButton; + private JBTable myTable; + + private void createUIComponents() { + myTable = new JBTable(myModel); + } + + private void innerUpdate() { + final int selectedRow = myTable.getSelectedRow(); + final int rowCount = myModel.getRowCount(); + myMoveUpButton.setEnabled(selectedRow > 0); + myMoveDownButton.setEnabled(selectedRow + 1 < rowCount && rowCount > 1); + myRemoveButton.setEnabled(rowCount > 0); + update(); + } + + protected abstract void update(); + + public JBTable getTable() { + return myTable; + } + + public JPanel getPanel() { + return myPanel; + } +} diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java index 69b7d2d874ab..4403d56ff963 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java @@ -73,7 +73,7 @@ public class ChangeSignatureTest extends LightCodeInsightFixtureTestCase { } public void testNamedParametersOrder1() throws Exception { - doTest(null, new GrParameterInfo[] { + doTest(null, new GrParameterInfo[]{ new SimpleInfo(0), new SimpleInfo(2) }); @@ -86,9 +86,9 @@ public class ChangeSignatureTest extends LightCodeInsightFixtureTestCase { new SimpleInfo(2), }); } - + public void testNamedParametersOrder3() throws Exception { - doTest(null, new GrParameterInfo[] { + doTest(null, new GrParameterInfo[]{ new SimpleInfo(0), new SimpleInfo(2), new SimpleInfo("p", -1, "5", null, PsiType.INT), @@ -96,14 +96,14 @@ public class ChangeSignatureTest extends LightCodeInsightFixtureTestCase { } public void testMoveNamedParameters() throws Exception { - doTest(null, new GrParameterInfo[] { + doTest(null, new GrParameterInfo[]{ new SimpleInfo(1), new SimpleInfo(0) }); } public void testMoveVarArgParameters() throws Exception { - doTest(null, new GrParameterInfo[] { + doTest(null, new GrParameterInfo[]{ new SimpleInfo(1), new SimpleInfo(0) }); @@ -132,7 +132,7 @@ public class ChangeSignatureTest extends LightCodeInsightFixtureTestCase { } public void testGroovyDocReferences() throws Exception { - doTest(null, new GrParameterInfo[] { + doTest(null, new GrParameterInfo[]{ new SimpleInfo(0), new SimpleInfo(2) }); @@ -165,7 +165,11 @@ public class ChangeSignatureTest extends LightCodeInsightFixtureTestCase { public void testChangeParameterType() throws Exception { doTest("", new GrParameterInfo[]{new SimpleInfo("p", 0, null, null, PsiType.INT)}); } - + + public void testGenerateDelegate() throws Exception { + doTest("", new GrParameterInfo[]{new SimpleInfo(0), new SimpleInfo("p", -1, "2", "2", PsiType.INT)}, true); + } + private PsiType createType(String typeText) { return JavaPsiFacade.getElementFactory(getProject()).createTypeByFQClassName(typeText, GlobalSearchScope.allScope(getProject())); } @@ -218,8 +222,7 @@ public class ChangeSignatureTest extends LightCodeInsightFixtureTestCase { } GrChangeInfoImpl changeInfo = new GrChangeInfoImpl(method, newVisibility, newType != null ? CanonicalTypes.createTypeWrapper(newType) : null, - newName != null ? newName : method.getName(), - Arrays.asList(genParams.genParams(method))); + newName != null ? newName : method.getName(), Arrays.asList(genParams.genParams(method)), generateDelegate); new GrChangeSignatureProcessor(getProject(), changeInfo).run(); myFixture.checkResultByFile(getTestName(false) + "_after.groovy"); } diff --git a/plugins/groovy/testdata/refactoring/changeSignature/GenerateDelegate.groovy b/plugins/groovy/testdata/refactoring/changeSignature/GenerateDelegate.groovy new file mode 100644 index 000000000000..1537c83e6d1f --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/GenerateDelegate.groovy @@ -0,0 +1,9 @@ +class X { + def foo(String s) { + print s; + } + + def main() { + foo("a") + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/GenerateDelegate_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/GenerateDelegate_after.groovy new file mode 100644 index 000000000000..f235e864152d --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/GenerateDelegate_after.groovy @@ -0,0 +1,13 @@ +class X { + def foo(String s, int p = 2) { + print s; + } + + def foo(String s) { + return foo(s, 2); + } + + def main() { + foo("a") + } +} \ No newline at end of file From 0fe654cd9a75f8cb92ace7f1d10e7ccf0816bc80 Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Sat, 15 May 2010 21:30:25 +0400 Subject: [PATCH 017/212] exception info for groovy --- .../ChangeSignatureDialog.java | 2 +- .../changeSignature/ExceptionsTableModel.java | 26 +-- .../changeSignature/JavaChangeInfoImpl.java | 6 +- .../JavaChangeSignatureUsageProcessor.java | 8 +- .../JavaThrownExceptionInfo.java | 68 ++++++ .../changeSignature/ThrownExceptionInfo.java | 54 +---- .../ChangeSignaturePropagationTest.java | 5 +- .../refactoring/ChangeSignatureTest.java | 9 +- .../lang/psi/GroovyPsiElementFactory.java | 11 +- .../api/statements/GrTryCatchStatement.java | 9 +- .../psi/impl/GroovyPsiElementFactoryImpl.java | 38 +++- .../statements/GrTryCatchStatementImpl.java | 10 + .../impl/statements/blocks/GrBlockImpl.java | 11 +- .../typedef/GrTypeDefinitionImpl.java | 12 +- .../DefaultGroovyVariableNameValidator.java | 72 +++++++ .../refactoring/GroovyNameSuggestionUtil.java | 48 ++++- .../GroovyRefactoringBundle.properties | 5 +- .../changeSignature/GrChangeInfoImpl.java | 36 +++- .../GrChangeSignatureDialog.form | 62 ++++-- .../GrChangeSignatureDialog.java | 198 +++++++++++++----- .../GrChangeSignatureUsageProcessor.java | 145 +++++++++++-- .../changeSignature/TableWithButtons.java | 1 + ...troduceParameterMethodUsagesProcessor.java | 2 +- .../changeSignature/ChangeSignatureTest.java | 28 ++- .../groovy/refactoring/rename/ClosureIt.test | 2 +- .../groovy/surround/statements/closure1.test | 3 +- .../groovy/surround/statements/closure2.test | 3 +- .../groovy/surround/statements/closure3.test | 3 +- .../changeSignature/AddException.groovy | 3 + .../changeSignature/AddException_after.groovy | 3 + .../ExceptionCaughtInUsage.groovy | 8 + .../ExceptionCaughtInUsage_after.groovy | 11 + .../ExceptionInClosableBlock.groovy | 5 + .../ExceptionInClosableBlock_after.groovy | 8 + .../ImplicitConstructorForClass_after.groovy | 5 +- .../ImplicitDefaultConstructorAfter.groovy | 1 - 36 files changed, 704 insertions(+), 217 deletions(-) create mode 100644 java/java-impl/src/com/intellij/refactoring/changeSignature/JavaThrownExceptionInfo.java create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/DefaultGroovyVariableNameValidator.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/AddException.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/AddException_after.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/ExceptionCaughtInUsage.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/ExceptionCaughtInUsage_after.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/ExceptionInClosableBlock.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/ExceptionInClosableBlock_after.groovy diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureDialog.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureDialog.java index ebcb3b4c41f3..bea5505e1410 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureDialog.java @@ -457,7 +457,7 @@ public class ChangeSignatureDialog extends RefactoringDialog { final PsiClassType[] types = myMethod.getThrowsList().getReferencedTypes(); if (thrownExceptions.length <= types.length) return false; for (int i = 0; i < types.length; i++) { - if (thrownExceptions[i].oldIndex != i) return false; + if (thrownExceptions[i].getOldIndex() != i) return false; } return true; } diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/ExceptionsTableModel.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/ExceptionsTableModel.java index 820fcf4ca97d..535909cf7ae6 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/ExceptionsTableModel.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/ExceptionsTableModel.java @@ -29,7 +29,7 @@ import java.util.List; /** * @author ven */ -class ExceptionsTableModel extends AbstractTableModel implements RowEditableTableModel { +public class ExceptionsTableModel extends AbstractTableModel implements RowEditableTableModel { private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.changeSignature.ParameterTableModel"); private List myTypeCodeFraments; @@ -45,7 +45,7 @@ class ExceptionsTableModel extends AbstractTableModel implements RowEditableTabl } public void addRow() { - myExceptionInfos.add(new ThrownExceptionInfo()); + myExceptionInfos.add(new JavaThrownExceptionInfo()); myTypeCodeFraments.add(createParameterTypeCodeFragment("", myContext)); fireTableRowsInserted(myTypeCodeFraments.size() - 1, myTypeCodeFraments.size() - 1); } @@ -102,22 +102,6 @@ class ExceptionsTableModel extends AbstractTableModel implements RowEditableTabl } } - PsiType getTypeByRow(int row) { - Object typeValueAt = getValueAt(row, 0); - LOG.assertTrue(typeValueAt instanceof PsiTypeCodeFragment); - PsiType type; - try { - type = ((PsiTypeCodeFragment)typeValueAt).getType(); - } - catch (PsiTypeCodeFragment.TypeSyntaxException e1) { - type = null; - } - catch (PsiTypeCodeFragment.NoTypeException e1) { - type = null; - } - return type; - } - public void setTypeInfos(PsiMethod method) { PsiClassType[] referencedTypes = method.getThrowsList().getReferencedTypes(); myTypeCodeFraments = new ArrayList(referencedTypes.length); @@ -127,17 +111,17 @@ class ExceptionsTableModel extends AbstractTableModel implements RowEditableTabl final PsiTypeCodeFragment typeCodeFragment = createParameterTypeCodeFragment(typeWrapper.getTypeText(), method.getThrowsList()); typeWrapper.addImportsTo(typeCodeFragment); myTypeCodeFraments.add(typeCodeFragment); - myExceptionInfos.add(new ThrownExceptionInfo(i, referencedTypes[i])); + myExceptionInfos.add(new JavaThrownExceptionInfo(i, referencedTypes[i])); } } - PsiTypeCodeFragment createParameterTypeCodeFragment(final String typeText, PsiElement context) { + public PsiTypeCodeFragment createParameterTypeCodeFragment(final String typeText, PsiElement context) { return JavaPsiFacade.getInstance(myContext.getProject()).getElementFactory().createTypeCodeFragment( typeText, context, false, true, true ); } - PsiTypeCodeFragment[] getTypeCodeFragments() { + public PsiTypeCodeFragment[] getTypeCodeFragments() { return myTypeCodeFraments.toArray(new PsiTypeCodeFragment[myTypeCodeFraments.size()]); } diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfoImpl.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfoImpl.java index 7c7cab0e6bb0..1172acbb6282 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfoImpl.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfoImpl.java @@ -221,7 +221,7 @@ class JavaChangeInfoImpl implements JavaChangeInfo { if (!isExceptionSetChanged) { for (int i = 0; i < newExceptions.length; i++) { try { - if (newExceptions[i].oldIndex < 0 || !types[i].equals(newExceptions[i].myType.getType(method, method.getManager()))) { + if (newExceptions[i].getOldIndex() < 0 || !types[i].equals(newExceptions[i].createType(method, method.getManager()))) { isExceptionSetChanged = true; break; } @@ -229,7 +229,7 @@ class JavaChangeInfoImpl implements JavaChangeInfo { catch (IncorrectOperationException e) { isExceptionSetChanged = true; } - if (newExceptions[i].oldIndex != i) isExceptionSetOrOrderChanged = true; + if (newExceptions[i].getOldIndex() != i) isExceptionSetOrOrderChanged = true; } } @@ -256,7 +256,7 @@ class JavaChangeInfoImpl implements JavaChangeInfo { PsiClassType[] types = method.getThrowsList().getReferencedTypes(); ThrownExceptionInfo[] result = new ThrownExceptionInfo[types.length]; for (int i = 0; i < result.length; i++) { - result[i] = new ThrownExceptionInfo(i, types[i]); + result[i] = new JavaThrownExceptionInfo(i, types[i]); } return result; } diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java index 845ff02d9e59..f89dc9418a14 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java @@ -490,8 +490,8 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr final PsiElement element = changeInfo.getMethod(); LOG.assertTrue(element instanceof PsiMethod); if (changeInfo.isGenerateDelegate()) { - generateDelegate((JavaChangeInfo)changeInfo); - } + generateDelegate((JavaChangeInfo)changeInfo); + } processPrimaryMethod((JavaChangeInfo)changeInfo, (PsiMethod)element, null, true); return true; } @@ -611,7 +611,7 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr final PsiMethod method = changeInfo.getMethod(); for (int i = 0; i < newExceptions.length; i++) { newExceptions[i] = - (PsiClassType)newExceptionInfos[i].myType.getType(method, method.getManager()); //context really does not matter here + (PsiClassType)newExceptionInfos[i].createType(method, method.getManager()); //context really does not matter here } return newExceptions; } @@ -642,7 +642,7 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr newThrowns.addAll(Arrays.asList(throwsList.getReferenceElements())); final ThrownExceptionInfo[] primaryNewExns = changeInfo.getNewExceptions(); for (ThrownExceptionInfo thrownExceptionInfo : primaryNewExns) { - if (thrownExceptionInfo.oldIndex < 0) { + if (thrownExceptionInfo.getOldIndex() < 0) { final PsiClassType type = (PsiClassType)thrownExceptionInfo.createType(caller, caller.getManager()); final PsiJavaCodeReferenceElement ref = JavaPsiFacade.getInstance(caller.getProject()).getElementFactory().createReferenceElementByType(type); diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaThrownExceptionInfo.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaThrownExceptionInfo.java new file mode 100644 index 000000000000..9e2d86d3a28e --- /dev/null +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaThrownExceptionInfo.java @@ -0,0 +1,68 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.refactoring.changeSignature; + +import com.intellij.psi.*; +import com.intellij.refactoring.util.CanonicalTypes; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.Nullable; + +/** + * @author Maxim.Medvedev + */ +public class JavaThrownExceptionInfo implements ThrownExceptionInfo { + private final int oldIndex; + private CanonicalTypes.Type myType; + + public JavaThrownExceptionInfo() { + oldIndex = -1; + } + + public JavaThrownExceptionInfo(int oldIndex) { + this.oldIndex = oldIndex; + } + + public JavaThrownExceptionInfo(int oldIndex, PsiClassType type) { + this.oldIndex = oldIndex; + setType(type); + } + + public void setType(PsiClassType type) { + myType = CanonicalTypes.createTypeWrapper(type); + } + + @Nullable + public PsiType createType(PsiElement context, final PsiManager manager) throws IncorrectOperationException { + if (myType != null) { + return myType.getType(context, manager); + } + else { + return null; + } + } + + public void updateFromMethod(PsiMethod method) { + if (myType != null) return; + PsiClassType[] types = method.getThrowsList().getReferencedTypes(); + if (oldIndex >= 0) { + setType(types[oldIndex]); + } + } + + public int getOldIndex() { + return oldIndex; + } +} diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/ThrownExceptionInfo.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/ThrownExceptionInfo.java index 0f55dd0dc486..f17178789a3f 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/ThrownExceptionInfo.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/ThrownExceptionInfo.java @@ -16,59 +16,19 @@ package com.intellij.refactoring.changeSignature; import com.intellij.psi.*; -import com.intellij.refactoring.util.CanonicalTypes; import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.Nullable; /** * @author ven */ -public class ThrownExceptionInfo { - int oldIndex; - CanonicalTypes.Type myType; +public interface ThrownExceptionInfo { + void setType(PsiClassType type); - public ThrownExceptionInfo() { - oldIndex = -1; - } + @Nullable + PsiType createType(PsiElement context, final PsiManager manager) throws IncorrectOperationException; - public ThrownExceptionInfo(int oldIndex) { - this.oldIndex = oldIndex; - } + void updateFromMethod(PsiMethod method); - public ThrownExceptionInfo(int oldIndex, PsiClassType type) { - this.oldIndex = oldIndex; - setType(type); - } - - public void setType(PsiClassType type) { - myType = CanonicalTypes.createTypeWrapper(type); - } - - public PsiType createType(PsiElement context, final PsiManager manager) throws IncorrectOperationException { - if (myType != null) { - return myType.getType(context, manager); - } else { - return null; - } - } - - String getTypeText() { - if (myType != null) { - return myType.getTypeText(); - } - else { - return ""; - } - } - - public void updateFromMethod(PsiMethod method) { - if (myType != null) return; - PsiClassType[] types = method.getThrowsList().getReferencedTypes(); - if (oldIndex >= 0) { - setType(types[oldIndex]); - } - } - - public int getOldIndex() { - return oldIndex; - } + int getOldIndex(); } diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignaturePropagationTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignaturePropagationTest.java index 65f1245cb276..9338fe4d2685 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignaturePropagationTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignaturePropagationTest.java @@ -7,6 +7,7 @@ import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.searches.ClassInheritorsSearch; import com.intellij.psi.search.searches.MethodReferencesSearch; import com.intellij.refactoring.changeSignature.ChangeSignatureProcessor; +import com.intellij.refactoring.changeSignature.JavaThrownExceptionInfo; import com.intellij.refactoring.changeSignature.ParameterInfoImpl; import com.intellij.refactoring.changeSignature.ThrownExceptionInfo; import com.intellij.refactoring.util.CanonicalTypes; @@ -101,7 +102,7 @@ public class ChangeSignaturePropagationTest extends LightCodeInsightTestCase { private void exceptionPropagationTest(final PsiMethod method, final Set methodsToPropagateExceptions) throws Exception { PsiClassType newExceptionType = JavaPsiFacade.getElementFactory(getProject()).createTypeByFQClassName("java.lang.Exception", GlobalSearchScope.allScope(getProject())); - final ThrownExceptionInfo[] newExceptions = new ThrownExceptionInfo[]{new ThrownExceptionInfo(-1, newExceptionType)}; + final ThrownExceptionInfo[] newExceptions = new ThrownExceptionInfo[]{new JavaThrownExceptionInfo(-1, newExceptionType)}; doTest(new ParameterInfoImpl[0], newExceptions, null, methodsToPropagateExceptions, method); } @@ -149,7 +150,7 @@ public class ChangeSignaturePropagationTest extends LightCodeInsightTestCase { final PsiClassType[] exceptions = method.getThrowsList().getReferencedTypes(); ThrownExceptionInfo[] result = new ThrownExceptionInfo[exceptions.length + newExceptions.length]; for (int i = 0; i < exceptions.length; i++) { - result[i] = new ThrownExceptionInfo(i); + result[i] = new JavaThrownExceptionInfo(i); } System.arraycopy(newExceptions, 0, result, exceptions.length, newExceptions.length); return result; diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTest.java index 8fa39d06946a..2e3118b5532f 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTest.java @@ -4,6 +4,7 @@ import com.intellij.JavaTestUtil; import com.intellij.codeInsight.TargetElementUtilBase; import com.intellij.psi.*; import com.intellij.refactoring.changeSignature.ChangeSignatureProcessor; +import com.intellij.refactoring.changeSignature.JavaThrownExceptionInfo; import com.intellij.refactoring.changeSignature.ParameterInfoImpl; import com.intellij.refactoring.changeSignature.ThrownExceptionInfo; import com.intellij.testFramework.LightCodeInsightTestCase; @@ -152,7 +153,7 @@ public class ChangeSignatureTest extends LightCodeInsightTestCase { public void testReorderExceptions() throws Exception { doTest(null, null, null, new SimpleParameterGen(new ParameterInfoImpl[0]), - new SimpleExceptionsGen(new ThrownExceptionInfo[]{new ThrownExceptionInfo(1), new ThrownExceptionInfo(0)}), + new SimpleExceptionsGen(new ThrownExceptionInfo[]{new JavaThrownExceptionInfo(1), new JavaThrownExceptionInfo(0)}), false); } @@ -161,7 +162,7 @@ public class ChangeSignatureTest extends LightCodeInsightTestCase { new GenExceptions() { public ThrownExceptionInfo[] genExceptions(PsiMethod method) { return new ThrownExceptionInfo[] { - new ThrownExceptionInfo(-1, JavaPsiFacade.getInstance(method.getProject()).getElementFactory().createTypeByFQClassName("java.lang.Exception", method.getResolveScope())) + new JavaThrownExceptionInfo(-1, JavaPsiFacade.getInstance(method.getProject()).getElementFactory().createTypeByFQClassName("java.lang.Exception", method.getResolveScope())) }; } }, @@ -173,7 +174,7 @@ public class ChangeSignatureTest extends LightCodeInsightTestCase { new GenExceptions() { public ThrownExceptionInfo[] genExceptions(PsiMethod method) { return new ThrownExceptionInfo[] { - new ThrownExceptionInfo(-1, JavaPsiFacade.getInstance(method.getProject()).getElementFactory().createTypeByFQClassName("java.lang.RuntimeException", method.getResolveScope())) + new JavaThrownExceptionInfo(-1, JavaPsiFacade.getInstance(method.getProject()).getElementFactory().createTypeByFQClassName("java.lang.RuntimeException", method.getResolveScope())) }; } }, @@ -185,7 +186,7 @@ public class ChangeSignatureTest extends LightCodeInsightTestCase { new GenExceptions() { public ThrownExceptionInfo[] genExceptions(PsiMethod method) { return new ThrownExceptionInfo[] { - new ThrownExceptionInfo(-1, JavaPsiFacade.getInstance(method.getProject()).getElementFactory().createTypeByFQClassName("java.lang.Exception", method.getResolveScope())) + new JavaThrownExceptionInfo(-1, JavaPsiFacade.getInstance(method.getProject()).getElementFactory().createTypeByFQClassName("java.lang.Exception", method.getResolveScope())) }; } }, diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyPsiElementFactory.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyPsiElementFactory.java index 61054ce72d58..7916fede4bb9 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyPsiElementFactory.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyPsiElementFactory.java @@ -18,7 +18,9 @@ package org.jetbrains.plugins.groovy.lang.psi; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiClassType; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiReferenceList; import com.intellij.psi.PsiType; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; @@ -28,10 +30,7 @@ import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocMemberReference; import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocReferenceElement; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrLabel; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrBlockStatement; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrConstructorInvocation; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.*; import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList; import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; @@ -160,4 +159,8 @@ public abstract class GroovyPsiElementFactory { public abstract GrDocComment createDocCommentFromText(String text) ; public abstract GrConstructorInvocation createConstructorInvocation(String text); + + public abstract PsiReferenceList createThrownList(PsiClassType[] exceptionTypes); + + public abstract GrCatchClause createCatchClause(PsiClassType type, String parameterName); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/GrTryCatchStatement.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/GrTryCatchStatement.java index e24a85d8d11d..1d935e3afdbf 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/GrTryCatchStatement.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/GrTryCatchStatement.java @@ -16,6 +16,7 @@ package org.jetbrains.plugins.groovy.lang.psi.api.statements; +import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock; import org.jetbrains.annotations.Nullable; @@ -25,12 +26,12 @@ import org.jetbrains.annotations.Nullable; */ public interface GrTryCatchStatement extends GroovyPsiElement, GrStatement { - public GrOpenBlock getTryBlock(); + GrOpenBlock getTryBlock(); - public GrCatchClause[] getCatchClauses(); + GrCatchClause[] getCatchClauses(); @Nullable - public GrFinallyClause getFinallyClause(); - + GrFinallyClause getFinallyClause(); + GrCatchClause addCatchClause(@NotNull GrCatchClause clause, @Nullable GrCatchClause anchorBefore); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java index 71c5f8acddc0..9e64b7cce206 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java @@ -18,6 +18,7 @@ package org.jetbrains.plugins.groovy.lang.psi.impl; import com.intellij.lang.ASTNode; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.search.ProjectScope; import com.intellij.psi.util.PsiTreeUtil; @@ -539,18 +540,18 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory { List res = new ArrayList(); final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(myProject); - for (int i = 0; i < paramTypes.length; i++) { - String paramType = paramTypes[i]; - + for (String paramType : paramTypes) { try { psiType = factory.createTypeElement(paramType).getType(); - } catch (IncorrectOperationException e) { + } + catch (IncorrectOperationException e) { psiType = PsiType.getJavaLangObject(PsiManager.getInstance(myProject), ProjectScope.getAllScope(myProject)); } res.add(psiType); } - return createMethodFromText(modifier, name, type, paramTypes, QuickfixUtil.getMethodArgumentsNames(myProject, res.toArray(PsiType.EMPTY_ARRAY)), null); + return createMethodFromText(modifier, name, type, paramTypes, + QuickfixUtil.getMethodArgumentsNames(myProject, res.toArray(new PsiType[res.size()])), null); } public GrDocComment createDocCommentFromText(String text) { @@ -565,4 +566,31 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory { GroovyFile file = (GroovyFile)createGroovyFile("class Foo{ def Foo(){" + text + "}}"); return ((GrConstructor)file.getClasses()[0].getConstructors()[0]).getChainingConstructorInvocation(); } + + @Override + public PsiReferenceList createThrownList(PsiClassType[] exceptionTypes) { + if (exceptionTypes.length == 0) { + return createMethodFromText("def foo(){}").getThrowsList(); + } + String[] types = new String[exceptionTypes.length]; + for (int i = 0; i < types.length; i++) { + types[i] = exceptionTypes[i].getCanonicalText(); + } + final String end = StringUtil.join(types, ","); + return createMethodFromText("def foo() throws " + end + "{}").getThrowsList(); + } + + @Override + public GrCatchClause createCatchClause(PsiClassType type, String parameterName) { + StringBuffer buffer = new StringBuffer("try{} catch("); + if (type == null) { + buffer.append("Throwable "); + } + else { + buffer.append(type.getCanonicalText()).append(" "); + } + buffer.append(parameterName).append("){\n}"); + final GrTryCatchStatement statement = (GrTryCatchStatement)createStatementFromText(buffer.toString()); + return statement.getCatchClauses()[0]; + } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrTryCatchStatementImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrTryCatchStatementImpl.java index 39b2166aba10..019fb3dbdd02 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrTryCatchStatementImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrTryCatchStatementImpl.java @@ -17,7 +17,9 @@ package org.jetbrains.plugins.groovy.lang.psi.impl.statements; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrCatchClause; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrFinallyClause; @@ -52,4 +54,12 @@ public class GrTryCatchStatementImpl extends GroovyPsiElementImpl implements GrT public GrFinallyClause getFinallyClause() { return findChildByClass(GrFinallyClause.class); } + + public GrCatchClause addCatchClause(@NotNull GrCatchClause clause, @Nullable GrCatchClause anchorBefore) { + PsiElement anchor = anchorBefore; + if (anchor == null) { + anchor = getTryBlock(); + } + return (GrCatchClause)addAfter(clause, anchor); + } } \ No newline at end of file diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrBlockImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrBlockImpl.java index 5a1a43d34727..f76c7bed8901 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrBlockImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrBlockImpl.java @@ -30,6 +30,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrString; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterList; import org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction; import org.jetbrains.plugins.groovy.lang.psi.controlFlow.impl.ControlFlowBuilder; import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiElementImpl; @@ -100,7 +101,10 @@ public abstract class GrBlockImpl extends GroovyPsiElementImpl implements GrCode PsiElement actualAnchor = anchor == null ? getRBrace() : anchor; if (mayUseNewLinesAsSeparators()) { PsiElement prev = actualAnchor.getPrevSibling(); - if (!GroovyTokenTypes.mNLS.equals(prev.getNode().getElementType())) { + if (prev instanceof GrParameterList && prev.getTextLength() == 0 && prev.getPrevSibling() != null) { + prev = prev.getPrevSibling(); + } + if (!isNls(prev)) { getNode().addLeaf(GroovyTokenTypes.mNLS, "\n", actualAnchor.getNode()); } } @@ -114,6 +118,11 @@ public abstract class GrBlockImpl extends GroovyPsiElementImpl implements GrCode } return element; } + private static boolean isNls(PsiElement element) { + if (!GroovyTokenTypes.WHITE_SPACES_SET.contains(element.getNode().getElementType())) return false; + String text = element.getText(); + return text.contains("\n") || text.contains("\r"); + } @Nullable public PsiElement getLBrace() { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionImpl.java index 3f9e89d6fccd..68d1dc80d232 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrTypeDefinitionImpl.java @@ -665,14 +665,6 @@ public abstract class GrTypeDefinitionImpl extends GroovyBaseElementImpl mySet = new HashSet(); + + public DefaultGroovyVariableNameValidator(PsiElement context) { + this(context, Collections.emptyList()); + } + + public DefaultGroovyVariableNameValidator(PsiElement context, Collection restrictedNames) { + myContext = context; + mySet.addAll(restrictedNames); + PropertyResolverProcessor processor = new PropertyResolverProcessor(null, myContext); + ResolveUtil.treeWalkUp(myContext, processor, true); + final GroovyResolveResult[] results = processor.getCandidates(); + for (GroovyResolveResult result : results) { + final PsiElement element = result.getElement(); + if (element instanceof PsiNamedElement) { + mySet.add(((PsiNamedElement)element).getName()); + } + } + } + + public String validateName(String name, boolean increaseNumber) { + if (!mySet.contains(name)) return name; + if (increaseNumber) { + int i = 1; + //noinspection StatementWithEmptyBody + for (; mySet.contains(name + i); i++) ; + return name + i; + } + else { + return ""; + } + } + + public Project getProject() { + return myContext.getProject(); + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyNameSuggestionUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyNameSuggestionUtil.java index 5e4b22685a3d..80235309bdad 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyNameSuggestionUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyNameSuggestionUtil.java @@ -20,10 +20,12 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; +import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PsiTypesUtil; import com.intellij.psi.util.TypeConversionUtil; import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrSuperReferenceExpression; @@ -40,22 +42,16 @@ public class GroovyNameSuggestionUtil { public static final Logger LOG = Logger.getInstance("org.jetbrains.plugins.groovy.refactoring.GroovyNameSuggestionUtil"); + private GroovyNameSuggestionUtil() { + } + public static String[] suggestVariableNames(GrExpression expr, NameValidator validator) { ArrayList possibleNames = new ArrayList(); PsiType type = expr.getType(); generateNameByExpr(expr, possibleNames, validator); if (type != null && !PsiType.VOID.equals(type)) { - String unboxed = PsiTypesUtil.unboxIfPossible(type.getCanonicalText()); - if (unboxed != null && !unboxed.equals(type.getCanonicalText())) { - String name = generateNameForBuiltInType(unboxed); - name = validator.validateName(name, true); - if (GroovyNamesUtil.isIdentifier(name)) { - possibleNames.add(name); - } - } else { - generateByType(expr.getType(), possibleNames, validator); - } + generateVariableNameByTypeInner(type, possibleNames,validator); } while (possibleNames.contains("")) { possibleNames.remove(""); @@ -66,6 +62,25 @@ public class GroovyNameSuggestionUtil { return ArrayUtil.toStringArray(possibleNames); } + public static String[] suggestVariableNameByType(PsiType type, NameValidator validator) { + ArrayList possibleNames=new ArrayList(); + generateVariableNameByTypeInner(type, possibleNames, validator); + return possibleNames.toArray(new String[possibleNames.size()]); + } + + private static void generateVariableNameByTypeInner(PsiType type, ArrayList possibleNames, NameValidator validator) { + String unboxed = PsiTypesUtil.unboxIfPossible(type.getCanonicalText()); + if (unboxed != null && !unboxed.equals(type.getCanonicalText())) { + String name = generateNameForBuiltInType(unboxed); + name = validator.validateName(name, true); + if (GroovyNamesUtil.isIdentifier(name)) { + possibleNames.add(name); + } + } + else { + generateByType(type, possibleNames, validator); + } + } private static void generateNameByExpr(GrExpression expr, ArrayList possibleNames, NameValidator validator) { if (expr instanceof GrThisReferenceExpression) { @@ -95,6 +110,7 @@ public class GroovyNameSuggestionUtil { String typeName = type.getPresentableText(); generateNamesForCollectionType(type, possibleNames, validator); generateNamesForArrayType(type, possibleNames, validator); + generateNamesForExceptions(type, possibleNames, validator); typeName = cleanTypeName(typeName); if (typeName.equals("String")) { possibleNames.add(validator.validateName("s", true)); @@ -110,6 +126,15 @@ public class GroovyNameSuggestionUtil { } } + private static void generateNamesForExceptions(PsiType type, ArrayList possibleNames, NameValidator validator) { + if (InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_LANG_ERROR)) { + possibleNames.add(validator.validateName("error", true)); + } + else if (InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_LANG_EXCEPTION)) { + possibleNames.add(validator.validateName("e", true)); + } + } + private static void generateNamesForArrayType(PsiType type, ArrayList possibleNames, NameValidator validator) { int arrayDim = type.getArrayDimensions(); if (arrayDim == 0) return; @@ -195,6 +220,7 @@ public class GroovyNameSuggestionUtil { return str.substring(0, 1).toUpperCase() + str.substring(1); } + @Nullable private static PsiType getCollectionComponentType(PsiType type, Project project) { if (!(type instanceof PsiClassType)) return null; PsiClassType classType = (PsiClassType) type; @@ -202,7 +228,7 @@ public class GroovyNameSuggestionUtil { PsiClass clazz = result.getElement(); if (clazz == null) return null; JavaPsiFacade facade = JavaPsiFacade.getInstance(project); - PsiClass collectionClass = facade.findClass("java.util.Collection", ((PsiClassType) type).getResolveScope()); + @SuppressWarnings({"ConstantConditions"}) PsiClass collectionClass = facade.findClass("java.util.Collection", type.getResolveScope()); if (collectionClass == null || collectionClass.getTypeParameters().length != 1) return null; PsiSubstitutor substitutor = TypeConversionUtil.getClassSubstitutor(collectionClass, clazz, result.getSubstitutor()); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties index 8355088fcbc6..14896bb29c93 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties @@ -118,4 +118,7 @@ return.type.is.wrong=Return type is wrong type.for.parameter.is.incorrect=Type for parameter ''{0}'' is incorrect specify.default.value=Specify default value for parameter ''{0}'' changing.signature.of.0=Changing signature of {0} -refactored.method.will.cover.closure.property=Refactored method will override closure property ''{0}'' in {1} \ No newline at end of file +refactored.method.will.cover.closure.property=Refactored method will override closure property ''{0}'' in {1} +changeSignature.not.throwable.type=Wrong type: ''{0}'' for exception, should extend java.lang.Throwable +changeSignature.wrong.type.for.exception=Wrong type: ''{0}'' for exception +changeSignature.no.type.for.exception=Specify a type for exception \ No newline at end of file diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeInfoImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeInfoImpl.java index db653ca5cabb..5d1807048090 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeInfoImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeInfoImpl.java @@ -53,12 +53,15 @@ class GrChangeInfoImpl implements JavaChangeInfo { private PsiIdentifier myNewNameIdentifier; private PsiExpression[] defaultValues; private boolean myDelegate; + private ThrownExceptionInfo[] myThrownExceptions; + private boolean myExceptionSetChanged; + private boolean myExceptionSetOrOrderChanged; public GrChangeInfoImpl(GrMethod method, String visibilityModifier, @Nullable CanonicalTypes.Type returnType, String newName, - List parameters, boolean generateDelegate) { + List parameters, ThrownExceptionInfo[] exceptions, boolean generateDelegate) { this.method = method; this.visibilityModifier = visibilityModifier; this.returnType = returnType; @@ -151,6 +154,27 @@ class GrChangeInfoImpl implements JavaChangeInfo { } } } + + myThrownExceptions = exceptions; + final PsiClassType[] thrownTypes = method.getThrowsList().getReferencedTypes(); + if (thrownTypes.length != myThrownExceptions.length) { + myExceptionSetChanged = true; + myExceptionSetOrOrderChanged = true; + } + else { + myExceptionSetChanged = false; + for (int i = 0; i < myThrownExceptions.length; i++) { + ThrownExceptionInfo info = myThrownExceptions[i]; + if (info.getOldIndex() < 0) { + myExceptionSetChanged = true; + myExceptionSetOrOrderChanged = true; + break; + } + else if (info.getOldIndex() != i) { + myExceptionSetOrOrderChanged = true; + } + } + } } @NotNull @@ -188,11 +212,11 @@ class GrChangeInfoImpl implements JavaChangeInfo { } public boolean isExceptionSetChanged() { - return false; + return myExceptionSetChanged; } public boolean isExceptionSetOrOrderChanged() { - return false; + return myExceptionSetOrOrderChanged; } public GrMethod getMethod() { @@ -207,10 +231,6 @@ class GrChangeInfoImpl implements JavaChangeInfo { return returnType; } - public boolean isChangeVisibility() { - return !method.getModifierList().hasModifierProperty(visibilityModifier); - } - public String getNewName() { return newName; } @@ -230,7 +250,7 @@ class GrChangeInfoImpl implements JavaChangeInfo { } public ThrownExceptionInfo[] getNewExceptions() { - return new ThrownExceptionInfo[0]; //To change body of implemented methods use File | Settings | File Templates. + return myThrownExceptions; } public boolean isRetainsVarargs() { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.form b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.form index e60e6f42e45d..415ac736259c 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.form +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.form @@ -34,7 +34,7 @@ - + @@ -42,7 +42,26 @@ - + + + + + + + + + + + + + + + + + + + + @@ -140,7 +159,7 @@ - + @@ -148,29 +167,44 @@ - + - + + + - + - - - - - - - + - + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java index 9a8411ac35de..fc51098f2d6e 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java @@ -18,29 +18,37 @@ package org.jetbrains.plugins.groovy.refactoring.changeSignature; import com.intellij.openapi.editor.Document; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.psi.JavaPsiFacade; -import com.intellij.psi.PsiDocumentManager; -import com.intellij.psi.PsiType; -import com.intellij.psi.PsiTypeCodeFragment; +import com.intellij.psi.*; import com.intellij.refactoring.HelpID; +import com.intellij.refactoring.changeSignature.ExceptionsTableModel; +import com.intellij.refactoring.changeSignature.ThrownExceptionInfo; import com.intellij.refactoring.ui.CodeFragmentTableCellEditor; import com.intellij.refactoring.ui.CodeFragmentTableCellRenderer; import com.intellij.refactoring.ui.RefactoringDialog; import com.intellij.refactoring.util.CanonicalTypes; import com.intellij.refactoring.util.CommonRefactoringUtil; +import com.intellij.ui.EditableRowTable; import com.intellij.ui.EditorTextField; import com.intellij.ui.TableUtil; import com.intellij.ui.table.JBTable; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.debugger.fragments.GroovyCodeFragment; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement; +import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle; import org.jetbrains.plugins.groovy.refactoring.ui.GrCodeFragmentTableCellEditor; import org.jetbrains.plugins.groovy.refactoring.ui.GrCodeFragmentTableCellRenderer; import javax.swing.*; +import javax.swing.event.TableModelEvent; +import javax.swing.event.TableModelListener; +import javax.swing.table.TableColumnModel; import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.util.List; import static org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle.message; @@ -54,26 +62,36 @@ public class GrChangeSignatureDialog extends RefactoringDialog { private JRadioButton myPublicRadioButton; private JRadioButton myProtectedRadioButton; private JRadioButton myPrivateRadioButton; - private JPanel myParametersPanel; private JBTable myParameterTable; private JPanel contentPane; - private JLabel mySignatureLabel; + private JTextArea mySignatureLabel; private JLabel myNameLabel; private JLabel myReturnTypeLabel; - private JRadioButton myModifyRadioButton; + @SuppressWarnings({"UnusedDeclaration"}) private JRadioButton myModifyRadioButton; private JRadioButton myDelegateRadioButton; + @SuppressWarnings({"UnusedDeclaration"}) private JPanel myParameterButtonPanel; + private JBTable myExceptionsTable; + @SuppressWarnings({"UnusedDeclaration"}) private JPanel myExceptionsButtonPanel; private GrParameterTableModel myParameterModel; private GrMethod myMethod; private PsiTypeCodeFragment myReturnTypeCodeFragment; private GroovyCodeFragment myNameCodeFragment; + private ExceptionsTableModel myExceptionTableModel; + private static final String INDENT = " "; public GrChangeSignatureDialog(@NotNull Project project, GrMethod method) { super(project, true); myMethod = method; init(); - createParametersPanel(); - createExceptionsPanel(); updateSignature(); + ActionListener listener = new ActionListener() { + public void actionPerformed(ActionEvent e) { + updateSignature(); + } + }; + myPublicRadioButton.addActionListener(listener); + myPrivateRadioButton.addActionListener(listener); + myProtectedRadioButton.addActionListener(listener); } protected void init() { @@ -92,6 +110,8 @@ public class GrChangeSignatureDialog extends RefactoringDialog { private void createUIComponents() { createNameAndReturnTypeEditors(); + createParametersPanel(); + createExceptionsPanel(); } private void createNameAndReturnTypeEditors() { @@ -118,33 +138,55 @@ public class GrChangeSignatureDialog extends RefactoringDialog { private void createParametersPanel() { myParameterModel = new GrParameterTableModel(myMethod, this, myProject); - TableWithButtons parameterTable = new TableWithButtons(myParameterModel) { - @Override - protected void update() { + myParameterModel.addTableModelListener(new TableModelListener() { + public void tableChanged(TableModelEvent e) { updateSignature(); } - }; + }); + myParameterTable = new JBTable(myParameterModel); + myParameterTable.setPreferredScrollableViewportSize(new Dimension(550, myParameterTable.getRowHeight() * 8)); + + myParameterButtonPanel = EditableRowTable.createButtonsTable(myParameterTable, myParameterModel, true); - myParameterTable = parameterTable.getTable(); myParameterTable.setCellSelectionEnabled(true); + final TableColumnModel columnModel = myParameterTable.getColumnModel(); + columnModel.getColumn(0).setCellRenderer(new CodeFragmentTableCellRenderer(myProject)); + columnModel.getColumn(1).setCellRenderer(new GrCodeFragmentTableCellRenderer(myProject)); + columnModel.getColumn(2).setCellRenderer(new GrCodeFragmentTableCellRenderer(myProject)); + columnModel.getColumn(3).setCellRenderer(new GrCodeFragmentTableCellRenderer(myProject)); - myParameterTable.getColumnModel().getColumn(0).setCellRenderer(new CodeFragmentTableCellRenderer(myProject)); - myParameterTable.getColumnModel().getColumn(1).setCellRenderer(new GrCodeFragmentTableCellRenderer(myProject)); - myParameterTable.getColumnModel().getColumn(2).setCellRenderer(new GrCodeFragmentTableCellRenderer(myProject)); - myParameterTable.getColumnModel().getColumn(3).setCellRenderer(new GrCodeFragmentTableCellRenderer(myProject)); + columnModel.getColumn(0).setCellEditor(new CodeFragmentTableCellEditor(myProject)); + columnModel.getColumn(1).setCellEditor(new GrCodeFragmentTableCellEditor(myProject)); + columnModel.getColumn(2).setCellEditor(new GrCodeFragmentTableCellEditor(myProject)); + columnModel.getColumn(3).setCellEditor(new GrCodeFragmentTableCellEditor(myProject)); - myParameterTable.getColumnModel().getColumn(0).setCellEditor(new CodeFragmentTableCellEditor(myProject)); - myParameterTable.getColumnModel().getColumn(1).setCellEditor(new GrCodeFragmentTableCellEditor(myProject)); - myParameterTable.getColumnModel().getColumn(2).setCellEditor(new GrCodeFragmentTableCellEditor(myProject)); - myParameterTable.getColumnModel().getColumn(3).setCellEditor(new GrCodeFragmentTableCellEditor(myProject)); - - myParameterTable.setRowSelectionInterval(0, 0); - myParameterTable.setColumnSelectionInterval(0, 0); - - myParametersPanel.add(parameterTable.getPanel(), BorderLayout.CENTER); + if (myParameterModel.getRowCount() > 0) { + myParameterTable.setRowSelectionInterval(0, 0); + myParameterTable.setColumnSelectionInterval(0, 0); + } } private void createExceptionsPanel() { + myExceptionTableModel = new ExceptionsTableModel(myMethod); + myExceptionTableModel.setTypeInfos(myMethod); + myExceptionTableModel.addTableModelListener(new TableModelListener() { + public void tableChanged(TableModelEvent e) { + updateSignature(); + } + }); + myExceptionsTable = new JBTable(myExceptionTableModel); + myExceptionsTable.setPreferredScrollableViewportSize(new Dimension(200, myExceptionsTable.getRowHeight() * 8)); + + myExceptionsButtonPanel = EditableRowTable.createButtonsTable(myExceptionsTable, myExceptionTableModel, false); + + myExceptionsTable.getColumnModel().getColumn(0).setCellRenderer(new CodeFragmentTableCellRenderer(myProject)); + myExceptionsTable.getColumnModel().getColumn(0).setCellEditor(new CodeFragmentTableCellEditor(myProject)); + + if (myExceptionTableModel.getRowCount() > 0) { + myExceptionsTable.setRowSelectionInterval(0, 0); + myExceptionsTable.setColumnSelectionInterval(0, 0); + } + } @@ -168,21 +210,37 @@ public class GrChangeSignatureDialog extends RefactoringDialog { } builder.append(type).append(' '); builder.append(name).append('('); - final List infos = myParameterModel.getParameterInfos(); - for (int i = 0, infosSize = infos.size() - 1; i < infosSize; i++) { - generateParameterText(infos.get(i), builder); - builder.append(", "); - } - if (infos.size() > 0) { - generateParameterText(infos.get(infos.size() - 1), builder); - } + final List infos = myParameterModel.getParameterInfos(); + if (infos.size() > 0) { + final List paramsText = ContainerUtil.map(infos, new Function() { + public String fun(GrParameterInfo grParameterInfo) { + return generateParameterText(grParameterInfo); + } + }); + builder.append("\n").append(INDENT); + builder.append(StringUtil.join(paramsText, ",\n" + INDENT)); + builder.append('\n'); + } builder.append(')'); + + final PsiTypeCodeFragment[] exceptions = myExceptionTableModel.getTypeCodeFragments(); + if (exceptions.length > 0) { + builder.append("\nthrows\n"); + final List exceptionNames = ContainerUtil.map(exceptions, new Function() { + public String fun(PsiTypeCodeFragment fragment) { + return fragment.getText(); + } + }); + + builder.append(INDENT).append(StringUtil.join(exceptionNames, ",\n" + INDENT)); + } return builder.toString(); } - private static void generateParameterText(GrParameterInfo info, StringBuilder builder) { + private static String generateParameterText(GrParameterInfo info) { + StringBuilder builder = new StringBuilder(); final PsiTypeCodeFragment typeFragment = info.getTypeFragment(); String typeText = typeFragment != null ? typeFragment.getText().trim() : GrModifier.DEF; if (typeText.length() == 0) typeText = GrModifier.DEF; @@ -195,6 +253,7 @@ public class GrChangeSignatureDialog extends RefactoringDialog { if (defaultInitializerText.length() > 0) { builder.append(" = ").append(defaultInitializerText); } + return builder.toString(); } @Override @@ -219,19 +278,19 @@ public class GrChangeSignatureDialog extends RefactoringDialog { try { returnType = myReturnTypeCodeFragment.getType(); } - catch (PsiTypeCodeFragment.TypeSyntaxException e) { + catch (PsiTypeCodeFragment.TypeSyntaxException ignored) { } - catch (PsiTypeCodeFragment.NoTypeException e) { + catch (PsiTypeCodeFragment.NoTypeException ignored) { } String newName = getNewName(); final List parameterInfos = myParameterModel.getParameterInfos(); - invokeRefactoring(new GrChangeSignatureProcessor(myProject, new GrChangeInfoImpl(myMethod, modifier, - returnType == null - ? null - : CanonicalTypes.createTypeWrapper( - returnType), newName, - parameterInfos, myDelegateRadioButton.isSelected()))); + + final ThrownExceptionInfo[] exceptionInfos = myExceptionTableModel.getThrownExceptions(); + invokeRefactoring(new GrChangeSignatureProcessor( + myProject, + new GrChangeInfoImpl(myMethod, modifier, returnType == null ? null : CanonicalTypes.createTypeWrapper(returnType), newName, + parameterInfos, exceptionInfos, myDelegateRadioButton.isSelected()))); } @@ -239,37 +298,66 @@ public class GrChangeSignatureDialog extends RefactoringDialog { return myNameField.getText().trim(); } + private void showErrorHint(String hint) { + CommonRefactoringUtil.showErrorHint(myProject, null, hint, GroovyRefactoringBundle.message("incorrect.data"), HelpID.CHANGE_SIGNATURE); + } + private boolean validateInputData() { if (!StringUtil.isJavaIdentifier(getNewName())) { - CommonRefactoringUtil - .showErrorHint(myProject, null, message("name.is.wrong", getNewName()), message("incorrect.data"), HelpID.CHANGE_SIGNATURE); + showErrorHint(message("name.is.wrong", getNewName())); return false; } if (!checkType(myReturnTypeCodeFragment)) { - CommonRefactoringUtil - .showErrorHint(myProject, null, message("return.type.is.wrong"), message("incorrect.data"), HelpID.CHANGE_SIGNATURE); + showErrorHint(message("return.type.is.wrong")); return false; } for (GrParameterInfo info : myParameterModel.getParameterInfos()) { if (!StringUtil.isJavaIdentifier(info.getName())) { - CommonRefactoringUtil - .showErrorHint(myProject, null, message("name.is.wrong", info.getName()), message("incorrect.data"), HelpID.CHANGE_SIGNATURE); + showErrorHint(message("name.is.wrong", info.getName())); } if (!checkType(info.getTypeFragment())) { - CommonRefactoringUtil - .showErrorHint(myProject, null, message("type.for.parameter.is.incorrect", info.getName()), message("incorrect.data"), - HelpID.CHANGE_SIGNATURE); + showErrorHint(message("type.for.parameter.is.incorrect", info.getName())); return false; } String defaultValue = info.getDefaultValue(); if (info.getOldIndex() < 0 && (defaultValue == null || defaultValue.trim().length() == 0)) { - CommonRefactoringUtil.showErrorHint(myProject, null, message("specify.default.value", info.getName()), message("incorrect.data"), - HelpID.CHANGE_SIGNATURE); + showErrorHint(message("specify.default.value", info.getName())); return false; } } + + ThrownExceptionInfo[] exceptionInfos = myExceptionTableModel.getThrownExceptions(); + PsiTypeCodeFragment[] typeCodeFragments = myExceptionTableModel.getTypeCodeFragments(); + for (int i = 0; i < exceptionInfos.length; i++) { + ThrownExceptionInfo exceptionInfo = exceptionInfos[i]; + PsiTypeCodeFragment typeCodeFragment = typeCodeFragments[i]; + try { + PsiType type = typeCodeFragment.getType(); + if (!(type instanceof PsiClassType)) { + showErrorHint(GroovyRefactoringBundle.message("changeSignature.wrong.type.for.exception", typeCodeFragment.getText())); + return false; + } + + PsiClassType throwable = JavaPsiFacade.getInstance(myMethod.getProject()).getElementFactory() + .createTypeByFQClassName("java.lang.Throwable", type.getResolveScope()); + if (!throwable.isAssignableFrom(type)) { + showErrorHint(GroovyRefactoringBundle.message("changeSignature.not.throwable.type", typeCodeFragment.getText())); + return false; + } + exceptionInfo.setType((PsiClassType)type); + } + catch (PsiTypeCodeFragment.TypeSyntaxException e) { + showErrorHint(GroovyRefactoringBundle.message("changeSignature.wrong.type.for.exception", typeCodeFragment.getText())); + return false; + } + catch (PsiTypeCodeFragment.NoTypeException e) { + showErrorHint(GroovyRefactoringBundle.message("changeSignature.no.type.for.exception")); + return false; + } + } + return true; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java index 7f3be3fcc0ed..96ae931c38ab 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java @@ -16,6 +16,7 @@ package org.jetbrains.plugins.groovy.refactoring.changeSignature; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; @@ -28,19 +29,25 @@ import com.intellij.refactoring.util.usageInfo.DefaultConstructorImplicitUsageIn import com.intellij.refactoring.util.usageInfo.NoConstructorClassUsageInfo; import com.intellij.usageView.UsageInfo; import com.intellij.util.ArrayUtil; +import com.intellij.util.Function; import com.intellij.util.IncorrectOperationException; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; import com.intellij.util.containers.hash.HashSet; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.GroovyFileType; import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement; +import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrCatchClause; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrConstructorInvocation; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrTryCatchStatement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList; import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall; @@ -51,7 +58,11 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefini import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrConstructor; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement; +import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil; +import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; +import org.jetbrains.plugins.groovy.refactoring.DefaultGroovyVariableNameValidator; +import org.jetbrains.plugins.groovy.refactoring.GroovyNameSuggestionUtil; import java.util.Arrays; import java.util.List; @@ -120,7 +131,7 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc } buffer.append(StringUtil.join(params, ",")); buffer.append(");"); - + final GrCodeBlock codeBlock = GroovyPsiElementFactory.getInstance(method.getProject()).createMethodBodyFromText(buffer.toString()); newMethod.setBlock(codeBlock); CodeStyleManager.getInstance(method.getProject()).reformat(newMethod); @@ -203,6 +214,19 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc } CodeStyleManager.getInstance(parameterList.getProject()).reformat(parameterList); + if (changeInfo.isExceptionSetOrOrderChanged()) { + final ThrownExceptionInfo[] infos = changeInfo.getNewExceptions(); + PsiClassType[] exceptionTypes = new PsiClassType[infos.length]; + for (int i = 0; i < infos.length; i++) { + ThrownExceptionInfo info = infos[i]; + exceptionTypes[i] = (PsiClassType)info.createType(method, method.getManager()); + } + + PsiReferenceList thrownList = GroovyPsiElementFactory.getInstance(method.getProject()).createThrownList(exceptionTypes); + thrownList = (PsiReferenceList)method.getThrowsList().replace(thrownList); + PsiUtil.shortenReferences((GroovyPsiElement)thrownList); + CodeStyleManager.getInstance(method.getProject()).reformat(method.getThrowsList()); + } return true; } @@ -251,8 +275,7 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc } else if (usageInfo instanceof ChangeSignatureParameterUsageInfo) { String newName = ((ChangeSignatureParameterUsageInfo)usageInfo).newParameterName; - String oldName = ((ChangeSignatureParameterUsageInfo)usageInfo).oldParameterName; - processParameterUsage((PsiReference)element, oldName, newName); + ((PsiReference)element).handleElementRename(newName); return true; } else { @@ -266,11 +289,6 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc return false; } - private static void processParameterUsage(PsiReference ref, String oldName, String newName) - throws IncorrectOperationException { - ref.handleElementRename(newName); - } - private static void processClassUsage(GrTypeDefinition psiClass, JavaChangeInfo changeInfo) { String name = psiClass.getName(); @@ -284,7 +302,7 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc list.setModifierProperty(GrModifier.DEF, true); } - constructor = psiClass.addMemberDeclaration(constructor, null); + constructor = (GrConstructor)psiClass.add(constructor); processConstructor(constructor, changeInfo); } @@ -294,7 +312,9 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc GrConstructorInvocation invocation = GroovyPsiElementFactory.getInstance(constructor.getProject()).createConstructorInvocation("super()"); invocation = (GrConstructorInvocation)block.addStatementBefore(invocation, getFirstStatement(block)); - processMethodUsage(invocation.getThisOrSuperKeyword(), changeInfo, true, true, GrClosureSignatureUtil.ArgInfo.EMPTY_ARRAY); + processMethodUsage(invocation.getThisOrSuperKeyword(), changeInfo, + changeInfo.isParameterSetOrOrderChanged() || changeInfo.isParameterNamesChanged(), + changeInfo.isExceptionSetChanged(), GrClosureSignatureUtil.ArgInfo.EMPTY_ARRAY); } @Nullable @@ -392,10 +412,111 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc CodeStyleManager.getInstance(argumentList.getProject()).reformat(argumentList); } + + if (toCatchExceptions) { + final ThrownExceptionInfo[] exceptionInfos = changeInfo.getNewExceptions(); + PsiClassType[] exceptions = getExceptions(exceptionInfos, element, element.getManager()); + fixExceptions(element, exceptions); + } } - private static boolean wasParameterOptional(JavaParameterInfo parameterInfo) { - return parameterInfo instanceof GrParameterInfo && ((GrParameterInfo)parameterInfo).wasOptional(); + private static void fixExceptions(PsiElement element, PsiClassType[] exceptions) { + if (exceptions.length == 0) return; + final GroovyPsiElement context = + PsiTreeUtil.getParentOfType(element, GrTryCatchStatement.class, GrClosableBlock.class, GrMethod.class); + if (context instanceof GrClosableBlock) { + element = generateTryCatch(element, exceptions); + } + else if (context instanceof GrMethod) { + final PsiClassType[] referencedTypes = ((GrMethod)context).getThrowsList().getReferencedTypes(); + final List psiClassTypes = filterOutExceptions(exceptions, context, referencedTypes); + element = generateTryCatch(element, psiClassTypes.toArray(new PsiClassType[psiClassTypes.size()])); + } + else if (context instanceof GrTryCatchStatement) { + final GrCatchClause[] catchClauses = ((GrTryCatchStatement)context).getCatchClauses(); + List referencedTypes = ContainerUtil.map(catchClauses, new Function() { + @Nullable + public PsiClassType fun(GrCatchClause grCatchClause) { + final GrParameter grParameter = grCatchClause.getParameter(); + final PsiType type = grParameter != null ? grParameter.getType() : null; + if (type instanceof PsiClassType) { + return (PsiClassType)type; + } + else { + return null; + } + } + }); + + referencedTypes = ContainerUtil.skipNulls(referencedTypes); + final List psiClassTypes = + filterOutExceptions(exceptions, context, referencedTypes.toArray(new PsiClassType[referencedTypes.size()])); + + element = fixCatchBlock((GrTryCatchStatement)context, psiClassTypes.toArray(new PsiClassType[psiClassTypes.size()])); + } + + // CodeStyleManager.getInstance(element.getProject()).reformat(element); + } + + private static PsiElement generateTryCatch(PsiElement element, PsiClassType[] exceptions) { + if (exceptions.length == 0) return element; + GrTryCatchStatement tryCatch = + (GrTryCatchStatement)GroovyPsiElementFactory.getInstance(element.getProject()).createStatementFromText("try{} catch (Exception e){}"); + final GrStatement statement = PsiTreeUtil.getParentOfType(element, GrStatement.class); + assert statement != null; + tryCatch.getTryBlock().addStatementBefore(statement, null); + tryCatch = (GrTryCatchStatement)statement.replace(tryCatch); + tryCatch.getCatchClauses()[0].delete(); + fixCatchBlock(tryCatch, exceptions); + return tryCatch; + } + + private static PsiElement fixCatchBlock(GrTryCatchStatement tryCatch, PsiClassType[] exceptions) { + if (exceptions.length == 0) return tryCatch; + final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(tryCatch.getProject()); + + final GrCatchClause[] clauses = tryCatch.getCatchClauses(); + List restricted = ContainerUtil.map(clauses, new Function() { + @Nullable + public String fun(GrCatchClause grCatchClause) { + final GrParameter grParameter = grCatchClause.getParameter(); + return grParameter != null ? grParameter.getName() : null; + } + }); + + restricted = ContainerUtil.skipNulls(restricted); + final DefaultGroovyVariableNameValidator nameValidator = new DefaultGroovyVariableNameValidator(tryCatch, restricted); + + GrCatchClause anchor = clauses.length == 0 ? null : clauses[clauses.length - 1]; + for (PsiClassType type : exceptions) { + final String[] names = GroovyNameSuggestionUtil.suggestVariableNameByType(type, nameValidator); + final GrCatchClause catchClause = factory.createCatchClause(type, names[0]); + anchor = tryCatch.addCatchClause(catchClause, anchor); + PsiUtil.shortenReferences(anchor); + } + return tryCatch; + } + + private static List filterOutExceptions(PsiClassType[] exceptions, + final GroovyPsiElement context, + final PsiClassType[] referencedTypes) { + return ContainerUtil.findAll(exceptions, new Condition() { + public boolean value(PsiClassType o) { + for (PsiClassType type : referencedTypes) { + if (TypesUtil.isAssignable(type, o, context.getManager(), context.getResolveScope(), false)) return false; + } + return true; + } + }); + } + + private static PsiClassType[] getExceptions(ThrownExceptionInfo[] infos, final PsiElement context, final PsiManager manager) { + return ContainerUtil.map(infos, new Function() { + @Nullable + public PsiClassType fun(ThrownExceptionInfo thrownExceptionInfo) { + return (PsiClassType)thrownExceptionInfo.createType(context, manager); + } + }, new PsiClassType[infos.length]); } private static boolean isParameterOptional(JavaParameterInfo parameterInfo) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/TableWithButtons.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/TableWithButtons.java index 8467d6788b89..cdbbcf5c6a63 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/TableWithButtons.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/TableWithButtons.java @@ -98,6 +98,7 @@ public abstract class TableWithButtons { private void createUIComponents() { myTable = new JBTable(myModel); + myTable.setPreferredScrollableViewportSize(new Dimension(450, myTable.getRowHeight() * 8)); } private void innerUpdate() { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduceParameter/java2groovy/GroovyIntroduceParameterMethodUsagesProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduceParameter/java2groovy/GroovyIntroduceParameterMethodUsagesProcessor.java index 6c7adedba5e1..ca2233050602 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduceParameter/java2groovy/GroovyIntroduceParameterMethodUsagesProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduceParameter/java2groovy/GroovyIntroduceParameterMethodUsagesProcessor.java @@ -241,7 +241,7 @@ public class GroovyIntroduceParameterMethodUsagesProcessor implements IntroduceP constructor = (GrMethod)aClass.add(constructor); PsiUtil.setModifierProperty(constructor, VisibilityUtil.getVisibilityModifier(aClass.getModifierList()), true); processAddSuperCall(data, new UsageInfo(constructor), usages); - constructor = (GrMethod)CodeStyleManager.getInstance(data.getProject()).reformat(constructor); +// constructor = (GrMethod)CodeStyleManager.getInstance(data.getProject()).reformat(constructor); return false; } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java index 4403d56ff963..bdad2c827bec 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java @@ -18,6 +18,7 @@ package org.jetbrains.plugins.groovy.refactoring.changeSignature; import com.intellij.codeInsight.TargetElementUtilBase; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.refactoring.changeSignature.JavaThrownExceptionInfo; import com.intellij.refactoring.changeSignature.ThrownExceptionInfo; import com.intellij.refactoring.util.CanonicalTypes; import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; @@ -170,6 +171,30 @@ public class ChangeSignatureTest extends LightCodeInsightFixtureTestCase { doTest("", new GrParameterInfo[]{new SimpleInfo(0), new SimpleInfo("p", -1, "2", "2", PsiType.INT)}, true); } + public void testAddException() throws Exception { + doTest("public", null, "", + new GrParameterInfo[]{new SimpleInfo(0)}, + new ThrownExceptionInfo[]{new JavaThrownExceptionInfo(-1, (PsiClassType)createType("java.io.IOException"))}, + false + ); + } + + public void testExceptionCaughtInUsage() throws Exception { + doTest("public", null, "", + new GrParameterInfo[]{new SimpleInfo(0)}, + new ThrownExceptionInfo[]{new JavaThrownExceptionInfo(-1, (PsiClassType)createType("java.io.IOException"))}, + false + ); + } + + public void testExceptionInClosableBlock() throws Exception { + doTest("public", null, "", + new GrParameterInfo[]{new SimpleInfo(0)}, + new ThrownExceptionInfo[]{new JavaThrownExceptionInfo(-1, (PsiClassType)createType("java.io.IOException"))}, + false + ); + } + private PsiType createType(String typeText) { return JavaPsiFacade.getElementFactory(getProject()).createTypeByFQClassName(typeText, GlobalSearchScope.allScope(getProject())); } @@ -222,7 +247,8 @@ public class ChangeSignatureTest extends LightCodeInsightFixtureTestCase { } GrChangeInfoImpl changeInfo = new GrChangeInfoImpl(method, newVisibility, newType != null ? CanonicalTypes.createTypeWrapper(newType) : null, - newName != null ? newName : method.getName(), Arrays.asList(genParams.genParams(method)), generateDelegate); + newName != null ? newName : method.getName(), Arrays.asList(genParams.genParams(method)), + genExceptions.genExceptions(method), generateDelegate); new GrChangeSignatureProcessor(getProject(), changeInfo).run(); myFixture.checkResultByFile(getTestName(false) + "_after.groovy"); } diff --git a/plugins/groovy/testdata/groovy/refactoring/rename/ClosureIt.test b/plugins/groovy/testdata/groovy/refactoring/rename/ClosureIt.test index cb24d7ac9e26..5da844e827d9 100644 --- a/plugins/groovy/testdata/groovy/refactoring/rename/ClosureIt.test +++ b/plugins/groovy/testdata/groovy/refactoring/rename/ClosureIt.test @@ -3,6 +3,6 @@ def c = { } ----- def c = { - newName -> + def newName -> newName } \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/surround/statements/closure1.test b/plugins/groovy/testdata/groovy/surround/statements/closure1.test index 2c7e8c4ec8c2..4ac11bcae44e 100644 --- a/plugins/groovy/testdata/groovy/surround/statements/closure1.test +++ b/plugins/groovy/testdata/groovy/surround/statements/closure1.test @@ -1,4 +1,5 @@ return a = b ----- -{-> return a = b +{-> + return a = b }.call() diff --git a/plugins/groovy/testdata/groovy/surround/statements/closure2.test b/plugins/groovy/testdata/groovy/surround/statements/closure2.test index 4a20a6cabf0c..f5e350491f7d 100644 --- a/plugins/groovy/testdata/groovy/surround/statements/closure2.test +++ b/plugins/groovy/testdata/groovy/surround/statements/closure2.test @@ -9,7 +9,8 @@ def call() { a() ----- def a() { - {-> owner.call() + {-> + owner.call() }.call() } diff --git a/plugins/groovy/testdata/groovy/surround/statements/closure3.test b/plugins/groovy/testdata/groovy/surround/statements/closure3.test index 9affb7498f39..f32d51fe08d5 100644 --- a/plugins/groovy/testdata/groovy/surround/statements/closure3.test +++ b/plugins/groovy/testdata/groovy/surround/statements/closure3.test @@ -3,6 +3,7 @@ } ----- { - {-> owner.call 0 + {-> + owner.call 0 }.call() } \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/AddException.groovy b/plugins/groovy/testdata/refactoring/changeSignature/AddException.groovy new file mode 100644 index 000000000000..9e3d7e1f87b1 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/AddException.groovy @@ -0,0 +1,3 @@ +def foo(String s) { + print s; +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/AddException_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/AddException_after.groovy new file mode 100644 index 000000000000..7076c87091ad --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/AddException_after.groovy @@ -0,0 +1,3 @@ +def foo(String s) throws IOException{ + print s; +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/ExceptionCaughtInUsage.groovy b/plugins/groovy/testdata/refactoring/changeSignature/ExceptionCaughtInUsage.groovy new file mode 100644 index 000000000000..4a363a2f05a3 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/ExceptionCaughtInUsage.groovy @@ -0,0 +1,8 @@ +def foo(String s) { + +} + +def bar() { + foo("") +} + diff --git a/plugins/groovy/testdata/refactoring/changeSignature/ExceptionCaughtInUsage_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/ExceptionCaughtInUsage_after.groovy new file mode 100644 index 000000000000..11e39836bd31 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/ExceptionCaughtInUsage_after.groovy @@ -0,0 +1,11 @@ +def foo(String s) throws IOException{ + +} + +def bar() { + try{ +foo("") +}catch(IOException e){ +} +} + diff --git a/plugins/groovy/testdata/refactoring/changeSignature/ExceptionInClosableBlock.groovy b/plugins/groovy/testdata/refactoring/changeSignature/ExceptionInClosableBlock.groovy new file mode 100644 index 000000000000..dcd5e0d1ce46 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/ExceptionInClosableBlock.groovy @@ -0,0 +1,5 @@ +def foo(String s){} + +new Object().each { + foo("") +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/ExceptionInClosableBlock_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/ExceptionInClosableBlock_after.groovy new file mode 100644 index 000000000000..3066c2f95128 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/ExceptionInClosableBlock_after.groovy @@ -0,0 +1,8 @@ +def foo(String s) throws IOException{} + +new Object().each { + try{ +foo("") +}catch(IOException e){ +} +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorForClass_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorForClass_after.groovy index 3c3b24fb2e98..2201865c9400 100644 --- a/plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorForClass_after.groovy +++ b/plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorForClass_after.groovy @@ -3,8 +3,7 @@ class Foo { } class Bar extends Foo { -def Bar(){ + def Bar(){ super(5) -} - def get() {return "a"} +}def get() {return "a"} } \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/introduceParameter/implicitDefaultConstructor/ImplicitDefaultConstructorAfter.groovy b/plugins/groovy/testdata/refactoring/introduceParameter/implicitDefaultConstructor/ImplicitDefaultConstructorAfter.groovy index 19c1e90323eb..71c2f34d1813 100644 --- a/plugins/groovy/testdata/refactoring/introduceParameter/implicitDefaultConstructor/ImplicitDefaultConstructorAfter.groovy +++ b/plugins/groovy/testdata/refactoring/introduceParameter/implicitDefaultConstructor/ImplicitDefaultConstructorAfter.groovy @@ -1,7 +1,6 @@ class B extends A { def B() { super(27) - } } From 5879d42caec81fa2ced19e3c8e0424ba717eb733 Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Sun, 23 May 2010 19:01:40 +0400 Subject: [PATCH 018/212] infrastructure for tests --- .../changeSignature/GrParameterInfo.java | 12 +- .../changeSignature/ChangeSignatureTest.java | 247 ++++++++---------- 2 files changed, 115 insertions(+), 144 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java index 68d45dc5e76f..5d47ba7c138a 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java @@ -36,8 +36,6 @@ public class GrParameterInfo implements JavaParameterInfo { private GroovyCodeFragment myDefaultInitializer; private final int myPosition; private CanonicalTypes.Type myTypeWrapper; - private boolean myWasOptional = false; - private boolean myWasVarArg = false; public GrParameterInfo(GrParameter parameter, int position) { myPosition = position; @@ -46,7 +44,6 @@ public class GrParameterInfo implements JavaParameterInfo { final PsiType type = parameter.getDeclaredType(); if (type != null) { myType = JavaPsiFacade.getElementFactory(project).createTypeCodeFragment(type.getCanonicalText(), parameter, true, true); - myWasVarArg = myType instanceof PsiArrayType; } else { myType = JavaPsiFacade.getElementFactory(project).createTypeCodeFragment("", parameter, true, true); @@ -59,7 +56,6 @@ public class GrParameterInfo implements JavaParameterInfo { myDefaultInitializer = new GroovyCodeFragment(project, ""); } myDefaultValue = new GroovyCodeFragment(project, ""); - myWasOptional = parameter.isOptional(); } public GrParameterInfo(Project project, PsiElement context) { @@ -141,8 +137,8 @@ public class GrParameterInfo implements JavaParameterInfo { return getTypeText().endsWith("...") || getTypeText().endsWith("[]"); } - public boolean wasOptional() { - return myWasOptional; + public boolean isUseAnySingleVariable() { + return false; } public boolean isOptional() { @@ -153,10 +149,6 @@ public class GrParameterInfo implements JavaParameterInfo { return myDefaultInitializer.getText().trim(); } - public boolean wasWasVarArg() { - return myWasVarArg; - } - public boolean hasNoType() { return myType.getText().trim().length() == 0; } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java index bdad2c827bec..e4f1f105a85c 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java @@ -16,6 +16,9 @@ package org.jetbrains.plugins.groovy.refactoring.changeSignature; import com.intellij.codeInsight.TargetElementUtilBase; +import com.intellij.openapi.application.Result; +import com.intellij.openapi.application.WriteAction; +import com.intellij.openapi.editor.Document; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.refactoring.changeSignature.JavaThrownExceptionInfo; @@ -23,7 +26,6 @@ import com.intellij.refactoring.changeSignature.ThrownExceptionInfo; import com.intellij.refactoring.util.CanonicalTypes; import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; import com.intellij.util.IncorrectOperationException; -import org.jetbrains.annotations.NonNls; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.util.TestUtils; @@ -41,158 +43,157 @@ public class ChangeSignatureTest extends LightCodeInsightFixtureTestCase { } public void testOneNewParameter() throws Exception { - doTest(null, new GrParameterInfo[]{ - new SimpleInfo("p", -1, "\"5\"", null, createType(CommonClassNames.JAVA_LANG_STRING)) - }); + doTest(null, new SimpleInfo[]{ + new SimpleInfo("p", -1, "\"5\"", null, createType(CommonClassNames.JAVA_LANG_STRING))}); } public void testRemoveParameter() throws Exception { - doTest(null, new GrParameterInfo[0]); + doTest(null, new SimpleInfo[0]); } public void testInsertParameter() throws Exception { - doTest(null, new GrParameterInfo[]{ + doTest(null, new SimpleInfo[]{ new SimpleInfo(0), new SimpleInfo("p", -1, "5", "-3", PsiType.INT), new SimpleInfo(1) - }); + }); } public void testInsertOptionalParameter() throws Exception { - doTest(null, new GrParameterInfo[]{ + doTest(null, new SimpleInfo[]{ new SimpleInfo(0), new SimpleInfo(1), new SimpleInfo("p", -1, "5", "-3", PsiType.INT) - }); + }); } public void testNamedParametersRemove() throws Exception { - doTest(null, new GrParameterInfo[]{ + doTest(null, new SimpleInfo[]{ new SimpleInfo(1), new SimpleInfo(2) - }); + }); } public void testNamedParametersOrder1() throws Exception { - doTest(null, new GrParameterInfo[]{ + doTest(null, new SimpleInfo[]{ new SimpleInfo(0), new SimpleInfo(2) - }); + }); } public void testNamedParametersOrder2() throws Exception { - doTest(null, new GrParameterInfo[]{ + doTest(null, new SimpleInfo[]{ new SimpleInfo(0), new SimpleInfo("p", -1, "5", null, PsiType.INT), new SimpleInfo(2), - }); + }); } public void testNamedParametersOrder3() throws Exception { - doTest(null, new GrParameterInfo[]{ + doTest(null, new SimpleInfo[]{ new SimpleInfo(0), new SimpleInfo(2), new SimpleInfo("p", -1, "5", null, PsiType.INT), - }); + }); } public void testMoveNamedParameters() throws Exception { - doTest(null, new GrParameterInfo[]{ + doTest(null, new SimpleInfo[]{ new SimpleInfo(1), new SimpleInfo(0) - }); + }); } public void testMoveVarArgParameters() throws Exception { - doTest(null, new GrParameterInfo[]{ + doTest(null, new SimpleInfo[]{ new SimpleInfo(1), new SimpleInfo(0) - }); + }); } public void testChangeVisibilityAndName() throws Exception { - doTest("protected", "newName", null, new GrParameterInfo[]{new SimpleInfo(0)}, new ThrownExceptionInfo[0], false); + doTest("protected", "newName", null, new SimpleInfo[]{new SimpleInfo(0)}, new ThrownExceptionInfo[0], false); } public void testImplicitConstructorInConstructor() throws Exception { - doTest(null, new GrParameterInfo[]{ + doTest(null, new SimpleInfo[]{ new SimpleInfo("p", -1, "5", null, PsiType.INT) - }); + }); } public void testImplicitConstructorForClass() throws Exception { - doTest(null, new GrParameterInfo[]{ + doTest(null, new SimpleInfo[]{ new SimpleInfo("p", -1, "5", null, PsiType.INT) - }); + }); } public void testAnonymousClassUsage() throws Exception { - doTest(null, new GrParameterInfo[]{ + doTest(null, new SimpleInfo[]{ new SimpleInfo("p", -1, "5", null, PsiType.INT) - }); + }); } public void testGroovyDocReferences() throws Exception { - doTest(null, new GrParameterInfo[]{ + doTest(null, new SimpleInfo[]{ new SimpleInfo(0), new SimpleInfo(2) - }); + }); } public void testOverriders() throws Exception { - doTest("public", "bar", null, new GrParameterInfo[]{ + doTest("public", "bar", null, new SimpleInfo[]{ new SimpleInfo(0) - }, new ThrownExceptionInfo[0], false); + }, new ThrownExceptionInfo[0], false); } public void testParameterRename() throws Exception { - doTest(null, new GrParameterInfo[]{ + doTest(null, new SimpleInfo[]{ new SimpleInfo("newP", 0) - }); + }); } public void testAddReturnType() throws Exception { - doTest("int", new GrParameterInfo[]{new SimpleInfo(0)}); + doTest("int", new SimpleInfo[]{new SimpleInfo(0)}); } public void testChangeReturnType() throws Exception { - doTest("int", new GrParameterInfo[]{new SimpleInfo(0)}); + doTest("int", new SimpleInfo[]{new SimpleInfo(0)}); } public void testRemoveReturnType() throws Exception { - doTest("", new GrParameterInfo[]{new SimpleInfo(0)}); + doTest("", new SimpleInfo[]{new SimpleInfo(0)}); } public void testChangeParameterType() throws Exception { - doTest("", new GrParameterInfo[]{new SimpleInfo("p", 0, null, null, PsiType.INT)}); + doTest("", new SimpleInfo[]{new SimpleInfo("p", 0, null, null, PsiType.INT)}); } public void testGenerateDelegate() throws Exception { - doTest("", new GrParameterInfo[]{new SimpleInfo(0), new SimpleInfo("p", -1, "2", "2", PsiType.INT)}, true); + doTest("", new SimpleInfo[]{new SimpleInfo(0), new SimpleInfo("p", -1, "2", "2", PsiType.INT)}, true); } public void testAddException() throws Exception { doTest("public", null, "", - new GrParameterInfo[]{new SimpleInfo(0)}, + new SimpleInfo[]{new SimpleInfo(0)}, new ThrownExceptionInfo[]{new JavaThrownExceptionInfo(-1, (PsiClassType)createType("java.io.IOException"))}, false - ); + ); } public void testExceptionCaughtInUsage() throws Exception { doTest("public", null, "", - new GrParameterInfo[]{new SimpleInfo(0)}, + new SimpleInfo[]{new SimpleInfo(0)}, new ThrownExceptionInfo[]{new JavaThrownExceptionInfo(-1, (PsiClassType)createType("java.io.IOException"))}, false - ); + ); } public void testExceptionInClosableBlock() throws Exception { doTest("public", null, "", - new GrParameterInfo[]{new SimpleInfo(0)}, + new SimpleInfo[]{new SimpleInfo(0)}, new ThrownExceptionInfo[]{new JavaThrownExceptionInfo(-1, (PsiClassType)createType("java.io.IOException"))}, false - ); + ); } private PsiType createType(String typeText) { @@ -200,36 +201,51 @@ public class ChangeSignatureTest extends LightCodeInsightFixtureTestCase { } - private void doTest(String newReturnType, GrParameterInfo[] parameterInfos) throws Exception { + private void doTest(String newReturnType, SimpleInfo[] parameterInfos) throws Exception { doTest("public", null, newReturnType, parameterInfos, new ThrownExceptionInfo[0], false); } - private void doTest(String newReturnType, GrParameterInfo[] parameterInfos, final boolean generateDelegate) throws Exception { + private void doTest(String newReturnType, SimpleInfo[] parameterInfos, final boolean generateDelegate) throws Exception { doTest("public", null, newReturnType, parameterInfos, new ThrownExceptionInfo[0], generateDelegate); } private void doTest(String newVisibility, String newName, String newReturnType, - GrParameterInfo[] parameterInfo, + SimpleInfo[] parameterInfo, ThrownExceptionInfo[] exceptionInfo, final boolean generateDelegate) throws Exception { - doTest(newVisibility, newName, newReturnType, new SimpleParameterGen(parameterInfo), new SimpleExceptionsGen(exceptionInfo), + doTestForGroovy(newVisibility, newName, newReturnType, new SimpleParameterGen(parameterInfo), new SimpleExceptionsGen(exceptionInfo), generateDelegate); } - private void doTest(String newVisibility, String newName, @NonNls String newReturnType, GenParams gen, final boolean generateDelegate) - throws Exception { - doTest(newVisibility, newName, newReturnType, gen, new SimpleExceptionsGen(), generateDelegate); - } - - private void doTest(String newVisibility, + private void doTestForGroovy(String newVisibility, String newName, String newReturnType, GenParams genParams, GenExceptions genExceptions, final boolean generateDelegate) throws Exception { myFixture.configureByFile(getTestName(false) + ".groovy"); + executeRefactoring(newVisibility, newName, newReturnType, genParams, genExceptions, generateDelegate); + myFixture.checkResultByFile(getTestName(false) + "_after.groovy"); + } + + private void doTestForJava(String newVisibility, + String newName, + String newReturnType, + GenParams genParams, + GenExceptions genExceptions, + final boolean generateDelegate) throws Exception { + myFixture.configureByFiles(getTestName(false) + ".groovy", getTestName(false)+".java"); + executeRefactoring(newVisibility, newName, newReturnType, genParams, genExceptions, generateDelegate); + myFixture.checkResultByFile(getTestName(false) + "_after.java"); + } + + private void executeRefactoring(String newVisibility, + String newName, + String newReturnType, + GenParams genParams, + GenExceptions genExceptions, boolean generateDelegate) { final PsiElement targetElement = TargetElementUtilBase.findTargetElement(myFixture.getEditor(), TargetElementUtilBase.ELEMENT_NAME_ACCEPTED); assertTrue(" is not on method name", targetElement instanceof GrMethod); @@ -250,7 +266,6 @@ public class ChangeSignatureTest extends LightCodeInsightFixtureTestCase { newName != null ? newName : method.getName(), Arrays.asList(genParams.genParams(method)), genExceptions.genExceptions(method), generateDelegate); new GrChangeSignatureProcessor(getProject(), changeInfo).run(); - myFixture.checkResultByFile(getTestName(false) + "_after.groovy"); } @@ -258,38 +273,53 @@ public class ChangeSignatureTest extends LightCodeInsightFixtureTestCase { GrParameterInfo[] genParams(GrMethod method) throws IncorrectOperationException; } - private static class SimpleParameterGen implements GenParams { - private final GrParameterInfo[] myInfos; + private class SimpleParameterGen implements GenParams { + private final SimpleInfo[] myInfos; - private SimpleParameterGen(GrParameterInfo[] infos) { + private SimpleParameterGen(SimpleInfo[] infos) { myInfos = infos; } public GrParameterInfo[] genParams(GrMethod method) { GrParameter[] params = method.getParameterList().getParameters(); - for (int i = 0, myInfosLength = myInfos.length; i < myInfosLength; i++) { - int oldIndex = myInfos[i].getOldIndex(); + GrParameterInfo[] result=new GrParameterInfo[myInfos.length]; + for (int i = 0; i < myInfos.length; i++) { + final SimpleInfo sim = myInfos[i]; + int oldIndex = sim.myOldIndex; + final GrParameterInfo info; if (oldIndex > -1) { - final String name = myInfos[i].getName(); - final CanonicalTypes.Type wrapper = myInfos[i].getTypeWrapper(); - myInfos[i] = new GrParameterInfo(params[oldIndex], oldIndex) { - @Override - public String getName() { - if (name != null) return name; - return super.getName(); - } - - @Override - public CanonicalTypes.Type getTypeWrapper() { - if (wrapper != null) { - return wrapper; - } - return super.getTypeWrapper(); - } - }; + info = new GrParameterInfo(params[oldIndex], oldIndex); } + else { + info = new GrParameterInfo(getProject(), method); + } + if (sim.myNewName != null) { + setText(info.getNameFragment(), sim.myNewName); + } + if (sim.myType != null) { + setText(info.getTypeFragment(), sim.myType.getCanonicalText()); + } + if (sim.myDefaultInitializer != null) { + setText(info.getDefaultInitializerFragment(), sim.myDefaultInitializer); + } + if (sim.myDefaultValue != null) { + setText(info.getDefaultValueFragment(), sim.myDefaultValue); + } + result[i] = info; } - return myInfos; + return result; + } + + private void setText(final PsiCodeFragment codeFragment, final String newText) { + new WriteAction() { + @Override + protected void run(Result result) throws Throwable { + final PsiDocumentManager docManager = PsiDocumentManager.getInstance(getProject()); + final Document document = docManager.getDocument(codeFragment); + document.setText(newText); + docManager.commitDocument(document); + } + }.execute(); } } @@ -316,12 +346,12 @@ public class ChangeSignatureTest extends LightCodeInsightFixtureTestCase { } } - class SimpleInfo extends GrParameterInfo { + static class SimpleInfo { int myOldIndex; String myNewName; String myDefaultValue; String myDefaultInitializer; - CanonicalTypes.Type myTypeWrapper; + private PsiType myType; SimpleInfo(int oldIndex) { this(null, oldIndex); @@ -331,63 +361,12 @@ public class ChangeSignatureTest extends LightCodeInsightFixtureTestCase { this(newName, oldIndex, "", null, null); } - SimpleInfo( - String newName, - int oldIndex, - String defaultValue, - String defaultInitializer, - PsiType type) { - super(myFixture.getProject(), myFixture.getFile()); + SimpleInfo(String newName, int oldIndex, String defaultValue, String defaultInitializer, PsiType type) { myOldIndex = oldIndex; myNewName = newName; myDefaultValue = defaultValue; - if (type == null) { - myTypeWrapper = null; - } - else { - myTypeWrapper = CanonicalTypes.createTypeWrapper(type); - } myDefaultInitializer = defaultInitializer; - } - - @Override - public int getOldIndex() { - return myOldIndex; - } - - @Override - public String getName() { - return myNewName; - } - - @Override - public String getDefaultValue() { - return myDefaultValue; - } - - @Override - public CanonicalTypes.Type getTypeWrapper() { - return myTypeWrapper; - } - - @Override - public String getTypeText() { - return myTypeWrapper.getTypeText(); - } - - @Override - public PsiType createType(PsiElement context, PsiManager manager) throws IncorrectOperationException { - return myTypeWrapper.getType(context, manager); - } - - @Override - public String getDefaultInitializer() { - return myDefaultInitializer; - } - - @Override - public boolean hasNoType() { - return myTypeWrapper == null; + myType = type; } } } From 9fa3c7dc51e086a2b71e6ece5e64f6dd59ae279c Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Wed, 26 May 2010 14:19:28 +0400 Subject: [PATCH 019/212] tests --- .../ChangeSignatureForJavaTest.java | 295 ++++++++++++++++++ .../changeSignature/ChangeSignatureTest.java | 230 +++----------- .../ChangeSignatureTestCase.java | 172 ++++++++++ .../changeSignature/AddException.java | 5 + .../changeSignature/AddException_after.groovy | 2 +- .../changeSignature/AddException_after.java | 7 + .../changeSignature/AnonymousClassUsage.java | 7 + .../AnonymousClassUsage_after.java | 7 + .../ChangeVisibilityAndName.java | 5 + .../ChangeVisibilityAndName_after.java | 5 + .../changeSignature/EnumConstructor.groovy | 6 + .../EnumConstructor_after.groovy | 6 + .../ImplicitConstructorForClass.java | 3 + .../ImplicitConstructorForClass_after.groovy | 8 +- .../ImplicitConstructorForClass_after.java | 4 + .../ImplicitConstructorInConstructor.java | 5 + ...licitConstructorInConstructor_after.groovy | 4 +- ...mplicitConstructorInConstructor_after.java | 5 + .../InsertParameter_after.java | 5 + .../changeSignature/InseterParameter.java | 5 + .../changeSignature/MoveVarArgParameters.java | 5 + .../MoveVarArgParameters_after.java | 5 + .../changeSignature/OneNewParameter.java | 5 + .../OneNewParameter_after.java | 5 + .../changeSignature/Overriders.java | 7 + .../changeSignature/Overriders_after.java | 7 + .../changeSignature/RemoveParameter.java | 5 + .../RemoveParameter_after.java | 5 + .../AddException.groovy | 2 + .../changeSignatureForJava/AddException.java | 23 ++ .../AddException_after.groovy | 6 + .../AddException_after.java | 27 ++ .../AddRuntimeException.java | 8 + .../AddRuntimeException_after.java | 8 + .../AlreadyHandled.java | 8 + .../AlreadyHandled_after.java | 8 + .../CovariantReturnType.java | 19 ++ .../CovariantReturnType_after.java | 19 ++ .../DefaultConstructor.groovy | 5 + .../DefaultConstructor.java | 11 + .../DefaultConstructor_after.groovy | 6 + .../DefaultConstructor_after.java | 12 + .../EnumConstructor.java | 7 + .../EnumConstructor_after.java | 7 + .../GenerateDelegate.groovy | 11 + .../GenerateDelegate.java | 16 + .../GenerateDelegateDefaultConstructor.groovy | 10 + .../GenerateDelegateDefaultConstructor.java | 15 + ...ateDelegateDefaultConstructor_after.groovy | 10 + ...erateDelegateDefaultConstructor_after.java | 19 ++ .../GenerateDelegate_after.groovy | 11 + .../GenerateDelegate_after.java | 20 ++ .../GenericTypes.groovy | 3 + .../changeSignatureForJava/GenericTypes.java | 22 ++ .../GenericTypesInOldParameters.java | 26 ++ .../GenericTypesInOldParameters_after.java | 26 ++ .../GenericTypes_after.groovy | 3 + .../GenericTypes_after.java | 22 ++ ...eParameterWithDefaultValueInHierarchy.java | 9 + ...eterWithDefaultValueInHierarchy_after.java | 9 + .../ParameterReorder.groovy | 5 + .../ParameterReorder.java | 26 ++ .../ParameterReorder_after.groovy | 5 + .../ParameterReorder_after.java | 26 ++ .../ReorderExceptions.java | 34 ++ .../ReorderExceptions_after.java | 32 ++ .../ReorderWithVarargs.java | 7 + .../ReorderWithVarargs2.java | 9 + .../ReorderWithVarargs2_after.java | 9 + .../ReorderWithVarargs_after.java | 7 + .../changeSignatureForJava/Simple.groovy | 5 + .../changeSignatureForJava/Simple.java | 7 + .../Simple_after.groovy | 5 + .../changeSignatureForJava/Simple_after.java | 7 + .../TypeParametersInMethod.java | 9 + .../TypeParametersInMethod_after.java | 9 + .../UseAnyVariable.java | 14 + .../UseAnyVariable_after.java | 14 + .../changeSignatureForJava/Varargs1.java | 10 + .../Varargs1_after.java | 10 + 80 files changed, 1298 insertions(+), 190 deletions(-) create mode 100644 plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureForJavaTest.java create mode 100644 plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTestCase.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/AddException.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/AddException_after.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/AnonymousClassUsage.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/AnonymousClassUsage_after.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/ChangeVisibilityAndName.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/ChangeVisibilityAndName_after.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/EnumConstructor.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/EnumConstructor_after.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorForClass.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorForClass_after.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorInConstructor.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorInConstructor_after.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/InsertParameter_after.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/InseterParameter.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/MoveVarArgParameters.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/MoveVarArgParameters_after.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/OneNewParameter.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/OneNewParameter_after.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/Overriders.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/Overriders_after.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/RemoveParameter.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/RemoveParameter_after.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/AddException.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/AddException.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/AddException_after.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/AddException_after.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/AddRuntimeException.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/AddRuntimeException_after.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/AlreadyHandled.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/AlreadyHandled_after.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/CovariantReturnType.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/CovariantReturnType_after.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/DefaultConstructor.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/DefaultConstructor.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/DefaultConstructor_after.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/DefaultConstructor_after.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/EnumConstructor.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/EnumConstructor_after.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/GenerateDelegate.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/GenerateDelegate.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/GenerateDelegateDefaultConstructor.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/GenerateDelegateDefaultConstructor.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/GenerateDelegateDefaultConstructor_after.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/GenerateDelegateDefaultConstructor_after.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/GenerateDelegate_after.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/GenerateDelegate_after.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/GenericTypes.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/GenericTypes.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/GenericTypesInOldParameters.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/GenericTypesInOldParameters_after.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/GenericTypes_after.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/GenericTypes_after.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/IntroduceParameterWithDefaultValueInHierarchy.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/IntroduceParameterWithDefaultValueInHierarchy_after.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/ParameterReorder.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/ParameterReorder.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/ParameterReorder_after.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/ParameterReorder_after.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderExceptions.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderExceptions_after.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderWithVarargs.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderWithVarargs2.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderWithVarargs2_after.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderWithVarargs_after.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/Simple.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/Simple.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/Simple_after.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/Simple_after.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/TypeParametersInMethod.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/TypeParametersInMethod_after.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/UseAnyVariable.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/UseAnyVariable_after.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/Varargs1.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/Varargs1_after.java diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureForJavaTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureForJavaTest.java new file mode 100644 index 000000000000..ac619531f787 --- /dev/null +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureForJavaTest.java @@ -0,0 +1,295 @@ +package org.jetbrains.plugins.groovy.refactoring.changeSignature; + +import com.intellij.codeInsight.TargetElementUtilBase; +import com.intellij.psi.*; +import com.intellij.refactoring.changeSignature.ChangeSignatureProcessor; +import com.intellij.refactoring.changeSignature.JavaThrownExceptionInfo; +import com.intellij.refactoring.changeSignature.ParameterInfoImpl; +import com.intellij.refactoring.changeSignature.ThrownExceptionInfo; +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.plugins.groovy.util.TestUtils; + +import java.io.File; + +/** + * @author Maxim.Medvedev + */ +public class ChangeSignatureForJavaTest extends LightCodeInsightFixtureTestCase { + public void testSimple() throws Exception { + doTest(null, null, null, new ParameterInfoImpl[0], new ThrownExceptionInfo[0], false); + } + + public void testParameterReorder() throws Exception { + doTest(null, new ParameterInfoImpl[]{new ParameterInfoImpl(1), new ParameterInfoImpl(0)}, false); + } + + public void testGenericTypes() throws Exception { + doTest(null, null, "T", new GenParams() { + public ParameterInfoImpl[] genParams(PsiMethod method) throws IncorrectOperationException { + final PsiElementFactory factory = JavaPsiFacade.getInstance(getProject()).getElementFactory(); + return new ParameterInfoImpl[]{ + new ParameterInfoImpl(-1, "x", factory.createTypeFromText("T", method.getParameterList()), "null"), + new ParameterInfoImpl(-1, "y", factory.createTypeFromText("C", method.getParameterList()), "null") + }; + } + }, false); + } + + public void testGenericTypesInOldParameters() throws Exception { + doTest(null, null, null, new GenParams() { + public ParameterInfoImpl[] genParams(PsiMethod method) throws IncorrectOperationException { + final PsiElementFactory factory = JavaPsiFacade.getInstance(getProject()).getElementFactory(); + return new ParameterInfoImpl[] { + new ParameterInfoImpl(0, "t", factory.createTypeFromText("T", method), null) + }; + } + }, false); + } + + public void testTypeParametersInMethod() throws Exception { + doTest(null, null, null, new GenParams() { + public ParameterInfoImpl[] genParams(PsiMethod method) throws IncorrectOperationException { + final PsiElementFactory factory = JavaPsiFacade.getInstance(getProject()).getElementFactory(); + return new ParameterInfoImpl[]{ + new ParameterInfoImpl(-1, "t", factory.createTypeFromText("T", method.getParameterList()), "null"), + new ParameterInfoImpl(-1, "u", factory.createTypeFromText("U", method.getParameterList()), "null"), + new ParameterInfoImpl(-1, "cu", factory.createTypeFromText("C", method.getParameterList()), "null") + }; + } + }, false); + } + + public void testDefaultConstructor() throws Exception { + doTest(null, + new ParameterInfoImpl[] { + new ParameterInfoImpl(-1, "j", PsiType.INT, "27") + }, false); + } + + public void testGenerateDelegate() throws Exception { + doTest(null, + new ParameterInfoImpl[] { + new ParameterInfoImpl(-1, "i", PsiType.INT, "27") + }, true); + } + + /*public void testGenerateDelegateForAbstract() throws Exception { + doTest(null, + new ParameterInfoImpl[] { + new ParameterInfoImpl(-1, "i", PsiType.INT, "27") + }, true); + } + + public void testGenerateDelegateWithReturn() throws Exception { + doTest(null, + new ParameterInfoImpl[] { + new ParameterInfoImpl(-1, "i", PsiType.INT, "27") + }, true); + } + + public void testGenerateDelegateWithParametersReordering() throws Exception { + doTest(null, + new ParameterInfoImpl[] { + new ParameterInfoImpl(1), + new ParameterInfoImpl(-1, "c", PsiType.CHAR, "'a'"), + new ParameterInfoImpl(0, "j", PsiType.INT) + }, true); + } + + public void testGenerateDelegateConstructor() throws Exception { + doTest(null, new ParameterInfoImpl[0], true); + } + */ + + public void testGenerateDelegateDefaultConstructor() throws Exception { + doTest(null, new ParameterInfoImpl[] { + new ParameterInfoImpl(-1, "i", PsiType.INT, "27") + }, true); + } + + /* + public void testSCR40895() throws Exception { + doTest(null, new ParameterInfoImpl[] { + new ParameterInfoImpl(0, "y", PsiType.INT), + new ParameterInfoImpl(1, "b", PsiType.BOOLEAN) + }, false); + } + + + public void testSuperCallFromOtherMethod() throws Exception { + doTest(null, new ParameterInfoImpl[] { + new ParameterInfoImpl(-1, "nnn", PsiType.INT, "-222"), + }, false); + } + */ + + //todo? + public void testUseAnyVariable() throws Exception { + doTest(null, null, null, new GenParams() { + public ParameterInfoImpl[] genParams(PsiMethod method) throws IncorrectOperationException { + final PsiElementFactory factory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory(); + return new ParameterInfoImpl[] { + new ParameterInfoImpl(-1, "l", factory.createTypeFromText("List", method), "null", true) + }; + } + }, false); + } + + /* + public void testRemoveVarargParameter() throws Exception { + doTest(null, null, null, new ParameterInfoImpl[]{new ParameterInfoImpl(0)}, new ThrownExceptionInfo[0], false); + } + */ + + public void testEnumConstructor() throws Exception { + doTest(null, new ParameterInfoImpl[] { + new ParameterInfoImpl(-1, "i", PsiType.INT, "10") + }, false); + } + + public void testVarargs1() throws Exception { + doTest(null, new ParameterInfoImpl[] { + new ParameterInfoImpl(-1, "b", PsiType.BOOLEAN, "true"), + new ParameterInfoImpl(0) + }, false); + } + + public void testCovariantReturnType() throws Exception { + doTest("java.lang.Runnable", new ParameterInfoImpl[0], false); + } + + public void testReorderExceptions() throws Exception { + doTest(null, null, null, new SimpleParameterGen(new ParameterInfoImpl[0]), + new SimpleExceptionsGen(new ThrownExceptionInfo[]{new JavaThrownExceptionInfo(1), new JavaThrownExceptionInfo(0)}), + false); + } + + public void testAlreadyHandled() throws Exception { + doTest(null, null, null, new SimpleParameterGen(new ParameterInfoImpl[0]), + new GenExceptions() { + public ThrownExceptionInfo[] genExceptions(PsiMethod method) { + return new ThrownExceptionInfo[] { + new JavaThrownExceptionInfo(-1, JavaPsiFacade.getInstance(method.getProject()).getElementFactory().createTypeByFQClassName("java.lang.Exception", method.getResolveScope())) + }; + } + }, + false); + } + + public void testAddRuntimeException() throws Exception { + doTest(null, null, null, new SimpleParameterGen(new ParameterInfoImpl[0]), + new GenExceptions() { + public ThrownExceptionInfo[] genExceptions(PsiMethod method) { + return new ThrownExceptionInfo[] { + new JavaThrownExceptionInfo(-1, JavaPsiFacade.getInstance(method.getProject()).getElementFactory().createTypeByFQClassName("java.lang.RuntimeException", method.getResolveScope())) + }; + } + }, + false); + } + + public void testAddException() throws Exception { + doTest(null, null, null, new SimpleParameterGen(new ParameterInfoImpl[0]), + new GenExceptions() { + public ThrownExceptionInfo[] genExceptions(PsiMethod method) { + return new ThrownExceptionInfo[] { + new JavaThrownExceptionInfo(-1, JavaPsiFacade.getInstance(method.getProject()).getElementFactory().createTypeByFQClassName("java.lang.Exception", method.getResolveScope())) + }; + } + }, + false); + } + + //todo + public void testReorderWithVarargs() throws Exception { // IDEADEV-26977 + final PsiElementFactory factory = JavaPsiFacade.getInstance(getProject()).getElementFactory(); + doTest(null, new ParameterInfoImpl[] { + new ParameterInfoImpl(1), + new ParameterInfoImpl(0, "s", factory.createTypeFromText("java.lang.String...", myFixture.getFile())) + }, false); + } + + public void testIntroduceParameterWithDefaultValueInHierarchy() throws Exception { + doTest(null, new ParameterInfoImpl[]{new ParameterInfoImpl(-1, "i", PsiType.INT, "0")}, false); + } + + private void doTest(String newReturnType, ParameterInfoImpl[] parameterInfos, final boolean generateDelegate) throws Exception { + doTest(null, null, newReturnType, parameterInfos, new ThrownExceptionInfo[0], generateDelegate); + } + + private void doTest(String newVisibility, + String newName, + String newReturnType, + ParameterInfoImpl[] parameterInfo, + ThrownExceptionInfo[] exceptionInfo, + final boolean generateDelegate) throws Exception { + doTest(newVisibility, newName, newReturnType, new SimpleParameterGen(parameterInfo), new SimpleExceptionsGen(exceptionInfo), generateDelegate); + } + + private void doTest(String newVisibility, String newName, @NonNls String newReturnType, GenParams gen, final boolean generateDelegate) throws Exception { + doTest(newVisibility, newName, newReturnType, gen, new SimpleExceptionsGen(), generateDelegate); + } + + private void doTest(String newVisibility, String newName, String newReturnType, GenParams genParams, GenExceptions genExceptions, final boolean generateDelegate) throws Exception { + myFixture.configureByFile(getTestName(false) +".groovy"); + myFixture.configureByFile(getTestName(false) + ".java"); + final PsiElement targetElement = TargetElementUtilBase.findTargetElement(myFixture.getEditor(), TargetElementUtilBase.ELEMENT_NAME_ACCEPTED); + assertTrue(" is not on method name", targetElement instanceof PsiMethod); + PsiMethod method = (PsiMethod) targetElement; + final PsiElementFactory factory = JavaPsiFacade.getInstance(getProject()).getElementFactory(); + PsiType newType = newReturnType != null ? factory.createTypeFromText(newReturnType, method) : method.getReturnType(); + new ChangeSignatureProcessor(getProject(), method, generateDelegate, newVisibility, + newName != null ? newName : method.getName(), + newType, genParams.genParams(method), genExceptions.genExceptions(method)).run(); + myFixture.checkResultByFile(getTestName(false) + ".groovy", getTestName(false) + "_after.groovy", true); + } + + private interface GenParams { + ParameterInfoImpl[] genParams(PsiMethod method) throws IncorrectOperationException; + } + + private static class SimpleParameterGen implements GenParams { + private final ParameterInfoImpl[] myInfos; + + private SimpleParameterGen(ParameterInfoImpl[] infos) { + myInfos = infos; + } + + public ParameterInfoImpl[] genParams(PsiMethod method) { + for (ParameterInfoImpl info : myInfos) { + info.updateFromMethod(method); + } + return myInfos; + } + } + + private interface GenExceptions { + ThrownExceptionInfo[] genExceptions(PsiMethod method) throws IncorrectOperationException; + } + + private static class SimpleExceptionsGen implements GenExceptions { + private final ThrownExceptionInfo[] myInfos; + + public SimpleExceptionsGen() { + myInfos = new ThrownExceptionInfo[0]; + } + + private SimpleExceptionsGen(ThrownExceptionInfo[] infos) { + myInfos = infos; + } + + public ThrownExceptionInfo[] genExceptions(PsiMethod method) { + for (ThrownExceptionInfo info : myInfos) { + info.updateFromMethod(method); + } + return myInfos; + } + } + + @Override + protected String getBasePath() { + return TestUtils.getTestDataPath() + "/refactoring/changeSignatureForJava/"; + } +} diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java index e4f1f105a85c..ee67f97e36fa 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java @@ -15,27 +15,18 @@ */ package org.jetbrains.plugins.groovy.refactoring.changeSignature; -import com.intellij.codeInsight.TargetElementUtilBase; -import com.intellij.openapi.application.Result; -import com.intellij.openapi.application.WriteAction; -import com.intellij.openapi.editor.Document; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.refactoring.changeSignature.JavaThrownExceptionInfo; import com.intellij.refactoring.changeSignature.ThrownExceptionInfo; -import com.intellij.refactoring.util.CanonicalTypes; -import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; -import com.intellij.util.IncorrectOperationException; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.util.TestUtils; -import java.util.Arrays; +import java.io.File; /** * @author Maxim.Medvedev */ -public class ChangeSignatureTest extends LightCodeInsightFixtureTestCase { +public class ChangeSignatureTest extends ChangeSignatureTestCase { @Override protected String getBasePath() { @@ -43,16 +34,16 @@ public class ChangeSignatureTest extends LightCodeInsightFixtureTestCase { } public void testOneNewParameter() throws Exception { - doTest(null, new SimpleInfo[]{ + doTest(new SimpleInfo[]{ new SimpleInfo("p", -1, "\"5\"", null, createType(CommonClassNames.JAVA_LANG_STRING))}); } public void testRemoveParameter() throws Exception { - doTest(null, new SimpleInfo[0]); + doTest(new SimpleInfo[0]); } public void testInsertParameter() throws Exception { - doTest(null, new SimpleInfo[]{ + doTest(new SimpleInfo[]{ new SimpleInfo(0), new SimpleInfo("p", -1, "5", "-3", PsiType.INT), new SimpleInfo(1) @@ -60,7 +51,7 @@ public class ChangeSignatureTest extends LightCodeInsightFixtureTestCase { } public void testInsertOptionalParameter() throws Exception { - doTest(null, new SimpleInfo[]{ + doTest(new SimpleInfo[]{ new SimpleInfo(0), new SimpleInfo(1), new SimpleInfo("p", -1, "5", "-3", PsiType.INT) @@ -68,21 +59,21 @@ public class ChangeSignatureTest extends LightCodeInsightFixtureTestCase { } public void testNamedParametersRemove() throws Exception { - doTest(null, new SimpleInfo[]{ + doTest(new SimpleInfo[]{ new SimpleInfo(1), new SimpleInfo(2) }); } public void testNamedParametersOrder1() throws Exception { - doTest(null, new SimpleInfo[]{ + doTest(new SimpleInfo[]{ new SimpleInfo(0), new SimpleInfo(2) }); } - public void testNamedParametersOrder2() throws Exception { - doTest(null, new SimpleInfo[]{ + /*public void testNamedParametersOrder2() throws Exception { + doTest(new SimpleInfo[]{ new SimpleInfo(0), new SimpleInfo("p", -1, "5", null, PsiType.INT), new SimpleInfo(2), @@ -90,22 +81,22 @@ public class ChangeSignatureTest extends LightCodeInsightFixtureTestCase { } public void testNamedParametersOrder3() throws Exception { - doTest(null, new SimpleInfo[]{ + doTest(new SimpleInfo[]{ new SimpleInfo(0), new SimpleInfo(2), new SimpleInfo("p", -1, "5", null, PsiType.INT), }); - } + }*/ public void testMoveNamedParameters() throws Exception { - doTest(null, new SimpleInfo[]{ + doTest(new SimpleInfo[]{ new SimpleInfo(1), new SimpleInfo(0) }); } public void testMoveVarArgParameters() throws Exception { - doTest(null, new SimpleInfo[]{ + doTest(new SimpleInfo[]{ new SimpleInfo(1), new SimpleInfo(0) }); @@ -116,40 +107,36 @@ public class ChangeSignatureTest extends LightCodeInsightFixtureTestCase { } public void testImplicitConstructorInConstructor() throws Exception { - doTest(null, new SimpleInfo[]{ + doTest(new SimpleInfo[]{ new SimpleInfo("p", -1, "5", null, PsiType.INT) }); } public void testImplicitConstructorForClass() throws Exception { - doTest(null, new SimpleInfo[]{ + doTest(new SimpleInfo[]{ new SimpleInfo("p", -1, "5", null, PsiType.INT) }); } public void testAnonymousClassUsage() throws Exception { - doTest(null, new SimpleInfo[]{ + doTest(new SimpleInfo[]{ new SimpleInfo("p", -1, "5", null, PsiType.INT) }); } public void testGroovyDocReferences() throws Exception { - doTest(null, new SimpleInfo[]{ + doTest(new SimpleInfo[]{ new SimpleInfo(0), new SimpleInfo(2) }); } public void testOverriders() throws Exception { - doTest("public", "bar", null, new SimpleInfo[]{ - new SimpleInfo(0) - }, new ThrownExceptionInfo[0], false); + doTest("public", "bar", null, new SimpleInfo[]{new SimpleInfo(0)}, new ThrownExceptionInfo[0], false); } public void testParameterRename() throws Exception { - doTest(null, new SimpleInfo[]{ - new SimpleInfo("newP", 0) - }); + doTest(new SimpleInfo[]{new SimpleInfo("newP", 0)}); } public void testAddReturnType() throws Exception { @@ -196,11 +183,27 @@ public class ChangeSignatureTest extends LightCodeInsightFixtureTestCase { ); } + public void testGenerateDelegateForConstructor() { + //todo + } + + public void testGenerateDelegateForAbstract() { + //todo + } + + public void testEnumConstructor() throws Exception { + doTest(new SimpleInfo[]{new SimpleInfo("a", -1, "2", null, PsiType.INT)}); + } + private PsiType createType(String typeText) { return JavaPsiFacade.getElementFactory(getProject()).createTypeByFQClassName(typeText, GlobalSearchScope.allScope(getProject())); } + private void doTest(SimpleInfo[] parameterInfos) throws Exception { + doTest("public", null, null, parameterInfos, new ThrownExceptionInfo[0], false); + } + private void doTest(String newReturnType, SimpleInfo[] parameterInfos) throws Exception { doTest("public", null, newReturnType, parameterInfos, new ThrownExceptionInfo[0], false); } @@ -215,158 +218,17 @@ public class ChangeSignatureTest extends LightCodeInsightFixtureTestCase { SimpleInfo[] parameterInfo, ThrownExceptionInfo[] exceptionInfo, final boolean generateDelegate) throws Exception { - doTestForGroovy(newVisibility, newName, newReturnType, new SimpleParameterGen(parameterInfo), new SimpleExceptionsGen(exceptionInfo), - generateDelegate); - } - - private void doTestForGroovy(String newVisibility, - String newName, - String newReturnType, - GenParams genParams, - GenExceptions genExceptions, - final boolean generateDelegate) throws Exception { + final File javaSrc = new File(getTestDataPath() + "/" + getTestName(false) + ".java"); + if (javaSrc.exists()) { + myFixture.copyFileToProject(getTestName(false) + ".java"); + } myFixture.configureByFile(getTestName(false) + ".groovy"); - executeRefactoring(newVisibility, newName, newReturnType, genParams, genExceptions, generateDelegate); - myFixture.checkResultByFile(getTestName(false) + "_after.groovy"); - } - - private void doTestForJava(String newVisibility, - String newName, - String newReturnType, - GenParams genParams, - GenExceptions genExceptions, - final boolean generateDelegate) throws Exception { - myFixture.configureByFiles(getTestName(false) + ".groovy", getTestName(false)+".java"); - executeRefactoring(newVisibility, newName, newReturnType, genParams, genExceptions, generateDelegate); - myFixture.checkResultByFile(getTestName(false) + "_after.java"); - } - - private void executeRefactoring(String newVisibility, - String newName, - String newReturnType, - GenParams genParams, - GenExceptions genExceptions, boolean generateDelegate) { - final PsiElement targetElement = - TargetElementUtilBase.findTargetElement(myFixture.getEditor(), TargetElementUtilBase.ELEMENT_NAME_ACCEPTED); - assertTrue(" is not on method name", targetElement instanceof GrMethod); - GrMethod method = (GrMethod)targetElement; - final PsiElementFactory factory = JavaPsiFacade.getInstance(getProject()).getElementFactory(); - PsiType newType; - if (newReturnType == null) { - newType = method.getReturnType(); - } - else if (newReturnType.length() == 0) { - newType = null; - } - else { - newType = factory.createTypeFromText(newReturnType, method); - } - GrChangeInfoImpl changeInfo = - new GrChangeInfoImpl(method, newVisibility, newType != null ? CanonicalTypes.createTypeWrapper(newType) : null, - newName != null ? newName : method.getName(), Arrays.asList(genParams.genParams(method)), - genExceptions.genExceptions(method), generateDelegate); - new GrChangeSignatureProcessor(getProject(), changeInfo).run(); - } - - - private interface GenParams { - GrParameterInfo[] genParams(GrMethod method) throws IncorrectOperationException; - } - - private class SimpleParameterGen implements GenParams { - private final SimpleInfo[] myInfos; - - private SimpleParameterGen(SimpleInfo[] infos) { - myInfos = infos; - } - - public GrParameterInfo[] genParams(GrMethod method) { - GrParameter[] params = method.getParameterList().getParameters(); - GrParameterInfo[] result=new GrParameterInfo[myInfos.length]; - for (int i = 0; i < myInfos.length; i++) { - final SimpleInfo sim = myInfos[i]; - int oldIndex = sim.myOldIndex; - final GrParameterInfo info; - if (oldIndex > -1) { - info = new GrParameterInfo(params[oldIndex], oldIndex); - } - else { - info = new GrParameterInfo(getProject(), method); - } - if (sim.myNewName != null) { - setText(info.getNameFragment(), sim.myNewName); - } - if (sim.myType != null) { - setText(info.getTypeFragment(), sim.myType.getCanonicalText()); - } - if (sim.myDefaultInitializer != null) { - setText(info.getDefaultInitializerFragment(), sim.myDefaultInitializer); - } - if (sim.myDefaultValue != null) { - setText(info.getDefaultValueFragment(), sim.myDefaultValue); - } - result[i] = info; - } - return result; - } - - private void setText(final PsiCodeFragment codeFragment, final String newText) { - new WriteAction() { - @Override - protected void run(Result result) throws Throwable { - final PsiDocumentManager docManager = PsiDocumentManager.getInstance(getProject()); - final Document document = docManager.getDocument(codeFragment); - document.setText(newText); - docManager.commitDocument(document); - } - }.execute(); - } - } - - private interface GenExceptions { - ThrownExceptionInfo[] genExceptions(PsiMethod method) throws IncorrectOperationException; - } - - private static class SimpleExceptionsGen implements GenExceptions { - private final ThrownExceptionInfo[] myInfos; - - public SimpleExceptionsGen() { - myInfos = new ThrownExceptionInfo[0]; - } - - private SimpleExceptionsGen(ThrownExceptionInfo[] infos) { - myInfos = infos; - } - - public ThrownExceptionInfo[] genExceptions(PsiMethod method) { - for (ThrownExceptionInfo info : myInfos) { - info.updateFromMethod(method); - } - return myInfos; - } - } - - static class SimpleInfo { - int myOldIndex; - String myNewName; - String myDefaultValue; - String myDefaultInitializer; - private PsiType myType; - - SimpleInfo(int oldIndex) { - this(null, oldIndex); - } - - SimpleInfo(String newName, int oldIndex) { - this(newName, oldIndex, "", null, null); - } - - SimpleInfo(String newName, int oldIndex, String defaultValue, String defaultInitializer, PsiType type) { - myOldIndex = oldIndex; - myNewName = newName; - myDefaultValue = defaultValue; - myDefaultInitializer = defaultInitializer; - myType = type; + executeRefactoring(newVisibility, newName, newReturnType, new SimpleParameterGen(parameterInfo, getProject()), + new SimpleExceptionsGen(exceptionInfo), generateDelegate); + if (javaSrc.exists()) { + System.out.println(getTestName(false)); + myFixture.checkResultByFile(getTestName(false) + ".java", getTestName(false) + "_after.java", true); } + myFixture.checkResultByFile(getTestName(false) + ".groovy", getTestName(false) + "_after.groovy", true); } } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTestCase.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTestCase.java new file mode 100644 index 000000000000..fc9a22d75d60 --- /dev/null +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTestCase.java @@ -0,0 +1,172 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.groovy.refactoring.changeSignature; + +import com.intellij.codeInsight.TargetElementUtilBase; +import com.intellij.openapi.application.Result; +import com.intellij.openapi.application.WriteAction; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.project.Project; +import com.intellij.psi.*; +import com.intellij.refactoring.changeSignature.ThrownExceptionInfo; +import com.intellij.refactoring.util.CanonicalTypes; +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; + +import java.util.Arrays; + +/** + * @author Maxim.Medvedev + */ +public abstract class ChangeSignatureTestCase extends LightCodeInsightFixtureTestCase { + void executeRefactoring(String newVisibility, + String newName, + String newReturnType, + GenParams genParams, + GenExceptions genExceptions, boolean generateDelegate) { + final PsiElement targetElement = + TargetElementUtilBase.findTargetElement(myFixture.getEditor(), TargetElementUtilBase.ELEMENT_NAME_ACCEPTED); + assertTrue(" is not on method name", targetElement instanceof GrMethod); + GrMethod method = (GrMethod)targetElement; + final PsiElementFactory factory = JavaPsiFacade.getInstance(getProject()).getElementFactory(); + PsiType newType; + if (newReturnType == null) { + if (method.getReturnTypeElement() == null) { + newType = null; + } + else { + newType = method.getReturnType(); + } + } + else if (newReturnType.length() == 0) { + newType = null; + } + else { + newType = factory.createTypeFromText(newReturnType, method); + } + GrChangeInfoImpl changeInfo = + new GrChangeInfoImpl(method, newVisibility, newType != null ? CanonicalTypes.createTypeWrapper(newType) : null, + newName != null ? newName : method.getName(), Arrays.asList(genParams.genParams(method)), + genExceptions.genExceptions(method), generateDelegate); + new GrChangeSignatureProcessor(getProject(), changeInfo).run(); + } + + + interface GenParams { + GrParameterInfo[] genParams(GrMethod method) throws IncorrectOperationException; + } + + static class SimpleParameterGen implements GenParams { + private final SimpleInfo[] myInfos; + private Project myProject; + + public SimpleParameterGen(SimpleInfo[] infos, Project project) { + myInfos = infos; + myProject = project; + } + + public GrParameterInfo[] genParams(GrMethod method) { + GrParameter[] params = method.getParameterList().getParameters(); + GrParameterInfo[] result = new GrParameterInfo[myInfos.length]; + for (int i = 0; i < myInfos.length; i++) { + final SimpleInfo sim = myInfos[i]; + int oldIndex = sim.myOldIndex; + final GrParameterInfo info; + if (oldIndex > -1) { + info = new GrParameterInfo(params[oldIndex], oldIndex); + } + else { + info = new GrParameterInfo(myProject, method); + } + if (sim.myNewName != null) { + setText(info.getNameFragment(), sim.myNewName); + } + if (sim.myType != null) { + setText(info.getTypeFragment(), sim.myType.getCanonicalText()); + } + if (sim.myDefaultInitializer != null) { + setText(info.getDefaultInitializerFragment(), sim.myDefaultInitializer); + } + if (sim.myDefaultValue != null) { + setText(info.getDefaultValueFragment(), sim.myDefaultValue); + } + result[i] = info; + } + return result; + } + + private void setText(final PsiCodeFragment codeFragment, final String newText) { + new WriteAction() { + @Override + protected void run(Result result) throws Throwable { + final PsiDocumentManager docManager = PsiDocumentManager.getInstance(myProject); + final Document document = docManager.getDocument(codeFragment); + document.setText(newText); + docManager.commitDocument(document); + } + }.execute(); + } + } + + interface GenExceptions { + ThrownExceptionInfo[] genExceptions(PsiMethod method) throws IncorrectOperationException; + } + + static class SimpleExceptionsGen implements GenExceptions { + private final ThrownExceptionInfo[] myInfos; + + public SimpleExceptionsGen() { + myInfos = new ThrownExceptionInfo[0]; + } + + public SimpleExceptionsGen(ThrownExceptionInfo[] infos) { + myInfos = infos; + } + + public ThrownExceptionInfo[] genExceptions(PsiMethod method) { + for (ThrownExceptionInfo info : myInfos) { + info.updateFromMethod(method); + } + return myInfos; + } + } + + static class SimpleInfo { + int myOldIndex; + String myNewName; + String myDefaultValue; + String myDefaultInitializer; + private PsiType myType; + + SimpleInfo(int oldIndex) { + this(null, oldIndex); + } + + SimpleInfo(String newName, int oldIndex) { + this(newName, oldIndex, "", null, null); + } + + SimpleInfo(String newName, int oldIndex, String defaultValue, String defaultInitializer, PsiType type) { + myOldIndex = oldIndex; + myNewName = newName; + myDefaultValue = defaultValue; + myDefaultInitializer = defaultInitializer; + myType = type; + } + } +} diff --git a/plugins/groovy/testdata/refactoring/changeSignature/AddException.java b/plugins/groovy/testdata/refactoring/changeSignature/AddException.java new file mode 100644 index 000000000000..8eebbafa3860 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/AddException.java @@ -0,0 +1,5 @@ +class Foo { + public static void main(String[] args) { + new AddException().foo(); + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/AddException_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/AddException_after.groovy index 7076c87091ad..827115db95ec 100644 --- a/plugins/groovy/testdata/refactoring/changeSignature/AddException_after.groovy +++ b/plugins/groovy/testdata/refactoring/changeSignature/AddException_after.groovy @@ -1,3 +1,3 @@ -def foo(String s) throws IOException{ +def foo(String s) throws IOException { print s; } \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/AddException_after.java b/plugins/groovy/testdata/refactoring/changeSignature/AddException_after.java new file mode 100644 index 000000000000..e3a0b27716f4 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/AddException_after.java @@ -0,0 +1,7 @@ +class Foo { + public static void main(String[] args) { + try {new AddException().foo();} catch (java.io.IOException e) { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. +} + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/AnonymousClassUsage.java b/plugins/groovy/testdata/refactoring/changeSignature/AnonymousClassUsage.java new file mode 100644 index 000000000000..f9c9f76ea941 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/AnonymousClassUsage.java @@ -0,0 +1,7 @@ +class X { + public static void main(String[] args) { + new Foo() { + public String toString(){return "";} + } + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/AnonymousClassUsage_after.java b/plugins/groovy/testdata/refactoring/changeSignature/AnonymousClassUsage_after.java new file mode 100644 index 000000000000..baba62e2aa91 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/AnonymousClassUsage_after.java @@ -0,0 +1,7 @@ +class X { + public static void main(String[] args) { + new Foo(5) { + public String toString(){return "";} + } + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/ChangeVisibilityAndName.java b/plugins/groovy/testdata/refactoring/changeSignature/ChangeVisibilityAndName.java new file mode 100644 index 000000000000..462ab8fb759d --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/ChangeVisibilityAndName.java @@ -0,0 +1,5 @@ +class Foo { + public static void main(String[] args) { + new ChangeVisibilityAndName().foo("a"); + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/ChangeVisibilityAndName_after.java b/plugins/groovy/testdata/refactoring/changeSignature/ChangeVisibilityAndName_after.java new file mode 100644 index 000000000000..4391b5fe446c --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/ChangeVisibilityAndName_after.java @@ -0,0 +1,5 @@ +class Foo { + public static void main(String[] args) { + new ChangeVisibilityAndName().newName("a"); + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/EnumConstructor.groovy b/plugins/groovy/testdata/refactoring/changeSignature/EnumConstructor.groovy new file mode 100644 index 000000000000..e8dbf699ac04 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/EnumConstructor.groovy @@ -0,0 +1,6 @@ +enum E{ + x, y + def E() { + + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/EnumConstructor_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/EnumConstructor_after.groovy new file mode 100644 index 000000000000..17f3c2e91170 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/EnumConstructor_after.groovy @@ -0,0 +1,6 @@ +enum E{ + x(2), y(2) + def E(int a) { + + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorForClass.java b/plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorForClass.java new file mode 100644 index 000000000000..9601cc28a985 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorForClass.java @@ -0,0 +1,3 @@ +class Z extends Foo { + +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorForClass_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorForClass_after.groovy index 2201865c9400..112864597a23 100644 --- a/plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorForClass_after.groovy +++ b/plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorForClass_after.groovy @@ -3,7 +3,9 @@ class Foo { } class Bar extends Foo { - def Bar(){ -super(5) -}def get() {return "a"} + def Bar() { + super(5) + } + + def get() {return "a"} } \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorForClass_after.java b/plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorForClass_after.java new file mode 100644 index 000000000000..53d30b904aee --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorForClass_after.java @@ -0,0 +1,4 @@ +class Z extends Foo { + +Z() { +super(5);}} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorInConstructor.java b/plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorInConstructor.java new file mode 100644 index 000000000000..b38117dc8516 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorInConstructor.java @@ -0,0 +1,5 @@ +class Z extends Foo{ + Z(){ + + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorInConstructor_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorInConstructor_after.groovy index 01d4f34b9f7c..438f38d16d5d 100644 --- a/plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorInConstructor_after.groovy +++ b/plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorInConstructor_after.groovy @@ -4,6 +4,6 @@ class Foo { class Bar extends Foo { def Bar() { -super(5) -} + super(5) + } } diff --git a/plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorInConstructor_after.java b/plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorInConstructor_after.java new file mode 100644 index 000000000000..626d723a82c9 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/ImplicitConstructorInConstructor_after.java @@ -0,0 +1,5 @@ +class Z extends Foo{ + Z(){ + + super(5);} +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/InsertParameter_after.java b/plugins/groovy/testdata/refactoring/changeSignature/InsertParameter_after.java new file mode 100644 index 000000000000..ce895198e7fa --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/InsertParameter_after.java @@ -0,0 +1,5 @@ +class Foo { + public static void main(String[] args) { + new InsertParameter().foo("3", 5, 4) + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/InseterParameter.java b/plugins/groovy/testdata/refactoring/changeSignature/InseterParameter.java new file mode 100644 index 000000000000..b3979abc69cb --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/InseterParameter.java @@ -0,0 +1,5 @@ +class Foo { + public static void main(String[] args) { + new InsertParameter().foo("3", 4); + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/MoveVarArgParameters.java b/plugins/groovy/testdata/refactoring/changeSignature/MoveVarArgParameters.java new file mode 100644 index 000000000000..e9eda05eaa9f --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/MoveVarArgParameters.java @@ -0,0 +1,5 @@ +class Foo { + public static void main(String[] args) { + new MoveVarArgParameters().foo("a", "b", "c") + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/MoveVarArgParameters_after.java b/plugins/groovy/testdata/refactoring/changeSignature/MoveVarArgParameters_after.java new file mode 100644 index 000000000000..3c8a30ae9d82 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/MoveVarArgParameters_after.java @@ -0,0 +1,5 @@ +class Foo { + public static void main(String[] args) { + new MoveVarArgParameters().foo(new String[]{"b", "c"}, "a") + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/OneNewParameter.java b/plugins/groovy/testdata/refactoring/changeSignature/OneNewParameter.java new file mode 100644 index 000000000000..5616b6fb4e73 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/OneNewParameter.java @@ -0,0 +1,5 @@ +class Foo { + public static void main(String[] args) { + new OneNewParameter().foo(); + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/OneNewParameter_after.java b/plugins/groovy/testdata/refactoring/changeSignature/OneNewParameter_after.java new file mode 100644 index 000000000000..8d6a34cfe0d2 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/OneNewParameter_after.java @@ -0,0 +1,5 @@ +class Foo { + public static void main(String[] args) { + new OneNewParameter().foo("5"); + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/Overriders.java b/plugins/groovy/testdata/refactoring/changeSignature/Overriders.java new file mode 100644 index 000000000000..ce7049ec6044 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/Overriders.java @@ -0,0 +1,7 @@ +class Z extends Foo { + void foo(String s, double x) {} +} + +class ZZ extends Z { + void foo(String s, double x) {} +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/Overriders_after.java b/plugins/groovy/testdata/refactoring/changeSignature/Overriders_after.java new file mode 100644 index 000000000000..dd39708dd2c1 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/Overriders_after.java @@ -0,0 +1,7 @@ +class Z extends Foo { + void bar(String s) {} +} + +class ZZ extends Z { + void bar(String s) {} +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/RemoveParameter.java b/plugins/groovy/testdata/refactoring/changeSignature/RemoveParameter.java new file mode 100644 index 000000000000..d982e6691800 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/RemoveParameter.java @@ -0,0 +1,5 @@ +class Foo { + public static void main(String[] args) { + new RemoveParameter().foo(); + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/RemoveParameter_after.java b/plugins/groovy/testdata/refactoring/changeSignature/RemoveParameter_after.java new file mode 100644 index 000000000000..d982e6691800 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/RemoveParameter_after.java @@ -0,0 +1,5 @@ +class Foo { + public static void main(String[] args) { + new RemoveParameter().foo(); + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/AddException.groovy b/plugins/groovy/testdata/refactoring/changeSignatureForJava/AddException.groovy new file mode 100644 index 000000000000..81580628d5e4 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/AddException.groovy @@ -0,0 +1,2 @@ +def test=new Test() +test.foo() \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/AddException.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/AddException.java new file mode 100644 index 000000000000..a0b725d5e578 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/AddException.java @@ -0,0 +1,23 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +class Test { + void foo () { + } + + void bar () { + foo(); + } +} diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/AddException_after.groovy b/plugins/groovy/testdata/refactoring/changeSignatureForJava/AddException_after.groovy new file mode 100644 index 000000000000..ecc0322fcf7b --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/AddException_after.groovy @@ -0,0 +1,6 @@ +def test=new Test() +try{ + test.foo(); +} catch (Exception e) { + +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/AddException_after.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/AddException_after.java new file mode 100644 index 000000000000..b1d2cff2a894 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/AddException_after.java @@ -0,0 +1,27 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +class Test { + void foo () throws Exception { + } + + void bar () { + try { + foo(); + } catch (Exception e) { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } + } +} diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/AddRuntimeException.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/AddRuntimeException.java new file mode 100644 index 000000000000..cf59542ef50c --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/AddRuntimeException.java @@ -0,0 +1,8 @@ +class Test { + void foo () { + } + + void bar () { + foo(); + } +} diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/AddRuntimeException_after.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/AddRuntimeException_after.java new file mode 100644 index 000000000000..7ec846065761 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/AddRuntimeException_after.java @@ -0,0 +1,8 @@ +class Test { + void foo () throws RuntimeException { + } + + void bar () { + foo(); + } +} diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/AlreadyHandled.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/AlreadyHandled.java new file mode 100644 index 000000000000..43ecdda106a2 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/AlreadyHandled.java @@ -0,0 +1,8 @@ +class Test { + void foo () { + } + + void bar () throws Exception { + foo(); + } +} diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/AlreadyHandled_after.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/AlreadyHandled_after.java new file mode 100644 index 000000000000..e2f1a754e0f2 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/AlreadyHandled_after.java @@ -0,0 +1,8 @@ +class Test { + void foo () throws Exception { + } + + void bar () throws Exception { + foo(); + } +} diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/CovariantReturnType.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/CovariantReturnType.java new file mode 100644 index 000000000000..4498755a3cbf --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/CovariantReturnType.java @@ -0,0 +1,19 @@ +import java.util.*; + +class A { + List method() { } +} + +class Q implements List, Runnable { +} + +class Z implements List { +} + +class B extends A { + Q method() { } +} + +class C extends A { + Z method() { } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/CovariantReturnType_after.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/CovariantReturnType_after.java new file mode 100644 index 000000000000..289fc99a63b8 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/CovariantReturnType_after.java @@ -0,0 +1,19 @@ +import java.util.*; + +class A { + Runnable method() { } +} + +class Q implements List, Runnable { +} + +class Z implements List { +} + +class B extends A { + Q method() { } +} + +class C extends A { + Runnable method() { } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/DefaultConstructor.groovy b/plugins/groovy/testdata/refactoring/changeSignatureForJava/DefaultConstructor.groovy new file mode 100644 index 000000000000..2829ff318234 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/DefaultConstructor.groovy @@ -0,0 +1,5 @@ +class A extends C { + def A(int k) { + int b = k; + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/DefaultConstructor.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/DefaultConstructor.java new file mode 100644 index 000000000000..e3306bd1fbae --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/DefaultConstructor.java @@ -0,0 +1,11 @@ +class C { + C() { + } +} + +class C1 extends C { + int i; + C1(int i, int k) { + this.i = i; + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/DefaultConstructor_after.groovy b/plugins/groovy/testdata/refactoring/changeSignatureForJava/DefaultConstructor_after.groovy new file mode 100644 index 000000000000..6c55fc0f04a7 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/DefaultConstructor_after.groovy @@ -0,0 +1,6 @@ +class A extends C { + def A(int k) { + super(27) +int b = k; + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/DefaultConstructor_after.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/DefaultConstructor_after.java new file mode 100644 index 000000000000..5acc86c650cc --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/DefaultConstructor_after.java @@ -0,0 +1,12 @@ +class C { + C(int j) { + } +} + +class C1 extends C { + int i; + C1(int i, int k) { + super(27); + this.i = i; + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/EnumConstructor.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/EnumConstructor.java new file mode 100644 index 000000000000..5047f3326b9f --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/EnumConstructor.java @@ -0,0 +1,7 @@ +enum En { + A {}, + B {}, + C; + + En() { } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/EnumConstructor_after.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/EnumConstructor_after.java new file mode 100644 index 000000000000..96ec0ca3fdee --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/EnumConstructor_after.java @@ -0,0 +1,7 @@ +enum En { + A(10) {}, + B(10) {}, + C(10); + + En(int i) { } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenerateDelegate.groovy b/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenerateDelegate.groovy new file mode 100644 index 000000000000..8a0f3666506f --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenerateDelegate.groovy @@ -0,0 +1,11 @@ +class C2 extends C { + void method() { + } +} + +class Usage { + { + new C().method(); + new C2().method(); + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenerateDelegate.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenerateDelegate.java new file mode 100644 index 000000000000..48b3e4b82c19 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenerateDelegate.java @@ -0,0 +1,16 @@ +class C { + void method() { + } +} + +class C1 extends C { + void method() { + } +} + +class Usage { + { + new C().method(); + new C1().method(); + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenerateDelegateDefaultConstructor.groovy b/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenerateDelegateDefaultConstructor.groovy new file mode 100644 index 000000000000..8200621d3253 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenerateDelegateDefaultConstructor.groovy @@ -0,0 +1,10 @@ +public class C2 extends C { + public C2(String s) { + } +} + +class Usage { + { + C c = new C(); + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenerateDelegateDefaultConstructor.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenerateDelegateDefaultConstructor.java new file mode 100644 index 000000000000..2c160ef3c242 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenerateDelegateDefaultConstructor.java @@ -0,0 +1,15 @@ +public class C { + public C() { + } +} + +public class C1 extends C { + public C1(String s) { + } +} + +class Usage { + { + C c = new C(); + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenerateDelegateDefaultConstructor_after.groovy b/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenerateDelegateDefaultConstructor_after.groovy new file mode 100644 index 000000000000..8200621d3253 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenerateDelegateDefaultConstructor_after.groovy @@ -0,0 +1,10 @@ +public class C2 extends C { + public C2(String s) { + } +} + +class Usage { + { + C c = new C(); + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenerateDelegateDefaultConstructor_after.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenerateDelegateDefaultConstructor_after.java new file mode 100644 index 000000000000..7352b816a1b1 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenerateDelegateDefaultConstructor_after.java @@ -0,0 +1,19 @@ +public class C { + public C() { + this(27); + } + + public C(int i) { + } +} + +public class C1 extends C { + public C1(String s) { + } +} + +class Usage { + { + C c = new C(); + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenerateDelegate_after.groovy b/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenerateDelegate_after.groovy new file mode 100644 index 000000000000..af1b39e36849 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenerateDelegate_after.groovy @@ -0,0 +1,11 @@ +class C2 extends C { + void method(int i) { + } +} + +class Usage { + { + new C().method(); + new C2().method(); + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenerateDelegate_after.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenerateDelegate_after.java new file mode 100644 index 000000000000..a8fba68f4a6a --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenerateDelegate_after.java @@ -0,0 +1,20 @@ +class C { + void method() { + method(27); + } + + void method(int i) { + } +} + +class C1 extends C { + void method(int i) { + } +} + +class Usage { + { + new C().method(); + new C1().method(); + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenericTypes.groovy b/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenericTypes.groovy new file mode 100644 index 000000000000..0ddc832cd1cc --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenericTypes.groovy @@ -0,0 +1,3 @@ +class C2 extends C { + void method(); +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenericTypes.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenericTypes.java new file mode 100644 index 000000000000..a66c5c74f5c2 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenericTypes.java @@ -0,0 +1,22 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +class C { + void method(); +} + +class C1 extends C { + void method(); +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenericTypesInOldParameters.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenericTypesInOldParameters.java new file mode 100644 index 000000000000..96ef7a9a4118 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenericTypesInOldParameters.java @@ -0,0 +1,26 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +class C { + void put(Object o) { + System.out.println(o); + } +} + +class CString extends C { + void put(Object o) { + System.out.println(o+"Text"); + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenericTypesInOldParameters_after.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenericTypesInOldParameters_after.java new file mode 100644 index 000000000000..67b736c22cbd --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenericTypesInOldParameters_after.java @@ -0,0 +1,26 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +class C { + void put(T t) { + System.out.println(t); + } +} + +class CString extends C { + void put(String t) { + System.out.println(t +"Text"); + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenericTypes_after.groovy b/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenericTypes_after.groovy new file mode 100644 index 000000000000..a29527c35326 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenericTypes_after.groovy @@ -0,0 +1,3 @@ +class C2 extends C { + String method(String x, C y); +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenericTypes_after.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenericTypes_after.java new file mode 100644 index 000000000000..446ab9e42e1a --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenericTypes_after.java @@ -0,0 +1,22 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +class C { + T method(T x, C y); +} + +class C1 extends C { + String method(String x, C y); +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/IntroduceParameterWithDefaultValueInHierarchy.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/IntroduceParameterWithDefaultValueInHierarchy.java new file mode 100644 index 000000000000..b332ce73eadd --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/IntroduceParameterWithDefaultValueInHierarchy.java @@ -0,0 +1,9 @@ +class Foo { + void foo(){} + + class A extends Foo { + void foo(){ + super.foo(); + } + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/IntroduceParameterWithDefaultValueInHierarchy_after.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/IntroduceParameterWithDefaultValueInHierarchy_after.java new file mode 100644 index 000000000000..08cf46f1074f --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/IntroduceParameterWithDefaultValueInHierarchy_after.java @@ -0,0 +1,9 @@ +class Foo { + void foo(int i){} + + class A extends Foo { + void foo(int i){ + super.foo(i); + } + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/ParameterReorder.groovy b/plugins/groovy/testdata/refactoring/changeSignatureForJava/ParameterReorder.groovy new file mode 100644 index 000000000000..f0f53b8a00dc --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/ParameterReorder.groovy @@ -0,0 +1,5 @@ +class Foo extends A { + int method(int i, int j) {} +} + +new A().method(1, 2); \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/ParameterReorder.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/ParameterReorder.java new file mode 100644 index 000000000000..8cfd2b08085c --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/ParameterReorder.java @@ -0,0 +1,26 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +class A { + public int method(int i, int j) { + return i - j; + } +} + +class B extends A { + public void method(int j, int i) { + return i - j; + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/ParameterReorder_after.groovy b/plugins/groovy/testdata/refactoring/changeSignatureForJava/ParameterReorder_after.groovy new file mode 100644 index 000000000000..28e7eb72fc6d --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/ParameterReorder_after.groovy @@ -0,0 +1,5 @@ +class Foo extends A { + int method(int j, int i) {} +} + +new A().method(2, 1); \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/ParameterReorder_after.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/ParameterReorder_after.java new file mode 100644 index 000000000000..217a7dda19c0 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/ParameterReorder_after.java @@ -0,0 +1,26 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +class A { + public int method(int j, int i) { + return i - j; + } +} + +class B extends A { + public void method(int i, int j) { + return i - j; + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderExceptions.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderExceptions.java new file mode 100644 index 000000000000..d492b54f2269 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderExceptions.java @@ -0,0 +1,34 @@ +class MyException extends Exception{ +} + +class MyException1 extends Exception{ +} + +class Test { + void foo () throws MyException, + MyException1 { + } + + void bar () { + try { + foo(); + } + catch (MyException e) {} + catch (MyException1 myException1) {} + } +} + +class Derived extends Test { + void foo() throws MyException, + MyException1 { + + } + + void bar () { + try { + foo(); + } + catch (MyException e) {} + catch (MyException1 myException1) {} + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderExceptions_after.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderExceptions_after.java new file mode 100644 index 000000000000..c91abcebbad7 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderExceptions_after.java @@ -0,0 +1,32 @@ +class MyException extends Exception{ +} + +class MyException1 extends Exception{ +} + +class Test { + void foo () throws MyException1, MyException { + } + + void bar () { + try { + foo(); + } + catch (MyException e) {} + catch (MyException1 myException1) {} + } +} + +class Derived extends Test { + void foo() throws MyException1, MyException { + + } + + void bar () { + try { + foo(); + } + catch (MyException e) {} + catch (MyException1 myException1) {} + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderWithVarargs.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderWithVarargs.java new file mode 100644 index 000000000000..41002940ffb2 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderWithVarargs.java @@ -0,0 +1,7 @@ +class Test { + void foo(String[] s, int a) {} + + { + foo(new String[]{"a", "bbb"}, 1); + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderWithVarargs2.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderWithVarargs2.java new file mode 100644 index 000000000000..d0ead6cee4f1 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderWithVarargs2.java @@ -0,0 +1,9 @@ +class Test { + static final String[] strs = new String[] { "a" }; + + void foo(String[] s, int a) {} + + { + foo(strs, 1); + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderWithVarargs2_after.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderWithVarargs2_after.java new file mode 100644 index 000000000000..5107af29b8ba --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderWithVarargs2_after.java @@ -0,0 +1,9 @@ +class Test { + static final String[] strs = new String[] { "a" }; + + void foo(int a, String... s) {} + + { + foo(1, strs); + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderWithVarargs_after.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderWithVarargs_after.java new file mode 100644 index 000000000000..f17d806b135a --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderWithVarargs_after.java @@ -0,0 +1,7 @@ +class Test { + void foo(int a, String... s) {} + + { + foo(1, "a", "bbb"); + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/Simple.groovy b/plugins/groovy/testdata/refactoring/changeSignatureForJava/Simple.groovy new file mode 100644 index 000000000000..bc4e935ff4ba --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/Simple.groovy @@ -0,0 +1,5 @@ +class C extends A { + void method(int i) { + + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/Simple.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/Simple.java new file mode 100644 index 000000000000..7c644e4eac70 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/Simple.java @@ -0,0 +1,7 @@ +class A { + void method(int i); +} + +class B extends A { + void method(int k); +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/Simple_after.groovy b/plugins/groovy/testdata/refactoring/changeSignatureForJava/Simple_after.groovy new file mode 100644 index 000000000000..a3dc3749db17 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/Simple_after.groovy @@ -0,0 +1,5 @@ +class C extends A { + void method() { + + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/Simple_after.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/Simple_after.java new file mode 100644 index 000000000000..231247a4b9d0 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/Simple_after.java @@ -0,0 +1,7 @@ +class A { + void method(); +} + +class B extends A { + void method(); +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/TypeParametersInMethod.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/TypeParametersInMethod.java new file mode 100644 index 000000000000..d91d98d3f0c0 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/TypeParametersInMethod.java @@ -0,0 +1,9 @@ +class C { + protected U method(){ + } +} + +class C1 extends C { + protected V method(){ + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/TypeParametersInMethod_after.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/TypeParametersInMethod_after.java new file mode 100644 index 000000000000..0a59f0145ec1 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/TypeParametersInMethod_after.java @@ -0,0 +1,9 @@ +class C { + protected U method(T t, U u, C cu){ + } +} + +class C1 extends C { + protected V method(String t, V u, C cu){ + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/UseAnyVariable.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/UseAnyVariable.java new file mode 100644 index 000000000000..b86284eaeb85 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/UseAnyVariable.java @@ -0,0 +1,14 @@ +import java.util.List; + +class C { + void method() { + } +} + +class Usage { + List myList; + { + C c = new C(); + c.method(); + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/UseAnyVariable_after.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/UseAnyVariable_after.java new file mode 100644 index 000000000000..a2b6f44b9a8c --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/UseAnyVariable_after.java @@ -0,0 +1,14 @@ +import java.util.List; + +class C { + void method(List l) { + } +} + +class Usage { + List myList; + { + C c = new C(); + c.method(myList); + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/Varargs1.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/Varargs1.java new file mode 100644 index 000000000000..b26fd25bf974 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/Varargs1.java @@ -0,0 +1,10 @@ +class C { + void method(int... args) { + } + + { + method(1,2); + method(1,2,3); + method(); + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/Varargs1_after.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/Varargs1_after.java new file mode 100644 index 000000000000..4241d7bb4b69 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/Varargs1_after.java @@ -0,0 +1,10 @@ +class C { + void method(boolean b, int... args) { + } + + { + method(true, 1,2); + method(true, 1,2,3); + method(true); + } +} \ No newline at end of file From 4411b639fb2264e4038a812430cf426d0f330609 Mon Sep 17 00:00:00 2001 From: Kirill Kalishev Date: Fri, 28 May 2010 18:08:46 +0400 Subject: [PATCH 020/212] TreeUi: revalidation of element --- .../util/treeView/AbstractTreeStructure.java | 4 ++ .../ide/util/treeView/AbstractTreeUi.java | 25 ++++++++- .../treeView/AbstractTreeBuilderTest.java | 24 +++++++- .../ide/util/treeView/BaseTreeTestCase.java | 9 +++ .../ide/util/treeView/TreeUiTest.java | 55 ++++++++++++++++--- 5 files changed, 106 insertions(+), 11 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeStructure.java b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeStructure.java index f383b43b6b86..4612aa83211c 100644 --- a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeStructure.java +++ b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeStructure.java @@ -39,4 +39,8 @@ public abstract class AbstractTreeStructure { return false; } + public Object revalidateElement(Object element) { + return element; + } + } \ No newline at end of file diff --git a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java index a02f6ec482da..77ecd1f686f1 100644 --- a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java +++ b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java @@ -3447,16 +3447,37 @@ public class AbstractTreeUi { final boolean deferred, final boolean canBeCentered, final boolean scrollToVisible, - boolean canSmartExpand) { + final boolean canSmartExpand) { final Runnable _onDone = new Runnable() { public void run() { if (!checkDeferred(deferred, onDone)) return; - selectVisible(element, onDone, addToSelection, canBeCentered, scrollToVisible); + + checkPathAndMaybeRevalidate(element, new Runnable() { + public void run() { + selectVisible(element, onDone, addToSelection, canBeCentered, scrollToVisible); + } + }, true, false, canSmartExpand); } }; _expand(element, _onDone, true, false, canSmartExpand); } + private void checkPathAndMaybeRevalidate(Object element, Runnable onDone, boolean parentsOnly, boolean checkIfInStructure, boolean canSmartExpand) { + boolean toRevalidate = getNodeForElement(element, false) == null && isInStructure(element); + if (!toRevalidate) { + runDone(onDone); + return; + } + + Object actualElement = getTreeStructure().revalidateElement(element); + if (actualElement == null) { + runDone(onDone); + return; + } + + _expand(actualElement, onDone, parentsOnly, checkIfInStructure, canSmartExpand); + } + public void scrollSelectionToVisible(@Nullable Runnable onDone, boolean shouldBeCentered) { int[] rows = myTree.getSelectionRows(); if (rows == null || rows.length == 0) { diff --git a/platform/platform-impl/testSrc/com/intellij/ide/util/treeView/AbstractTreeBuilderTest.java b/platform/platform-impl/testSrc/com/intellij/ide/util/treeView/AbstractTreeBuilderTest.java index 2b004f1e228d..a94f57214b68 100644 --- a/platform/platform-impl/testSrc/com/intellij/ide/util/treeView/AbstractTreeBuilderTest.java +++ b/platform/platform-impl/testSrc/com/intellij/ide/util/treeView/AbstractTreeBuilderTest.java @@ -108,6 +108,7 @@ abstract class AbstractTreeBuilderTest extends BaseTreeTestCase myChild2Parent = new HashMap(); private final Map myElement2Node = new HashMap(); private final Set myLeaves = new HashSet(); + private Revalidator myRevalidator; public Object getRootElement() { return myRoot.myElement; @@ -464,7 +472,8 @@ abstract class AbstractTreeBuilderTest extends BaseTreeTestCase extends FlyIdeaTestCase { public static class NodeElement extends ComparableObject.Impl implements Comparable{ final String myName; + private NodeElement myForcedParent; public NodeElement(String name) { super(name); @@ -461,6 +462,14 @@ abstract class BaseTreeTestCase extends FlyIdeaTestCase { public int compareTo(NodeElement o) { return myName.compareTo(o.myName); } + + public NodeElement getForcedParent() { + return myForcedParent; + } + + public void setForcedParent(NodeElement forcedParent) { + myForcedParent = forcedParent; + } } } diff --git a/platform/platform-impl/testSrc/com/intellij/ide/util/treeView/TreeUiTest.java b/platform/platform-impl/testSrc/com/intellij/ide/util/treeView/TreeUiTest.java index c5ed81422547..3a44ccd3c1fa 100644 --- a/platform/platform-impl/testSrc/com/intellij/ide/util/treeView/TreeUiTest.java +++ b/platform/platform-impl/testSrc/com/intellij/ide/util/treeView/TreeUiTest.java @@ -1013,7 +1013,7 @@ public class TreeUiTest extends AbstractTreeBuilderTest { public void onElementAction(String action, Object element) { if (wasInterrupted[0]) { if (myCancelRequest == null) { - myCancelRequest = new AssertionError("Not supposed to be update after interruption request: action=" + action + " element=" + element); + myCancelRequest = new AssertionError("Not supposed to be update after interruption request: action=" + action + " element=" + element + " interruptAction=" + interruptAction + " interruptElement=" + interruptElement); } } else { if (element.equals(interruptElement) && action.equals(interruptAction)) { @@ -1411,6 +1411,50 @@ public class TreeUiTest extends AbstractTreeBuilderTest { doTestSelectionOnDelete(true); } + public void testRevalidateStructure() throws Exception { + final NodeElement com = new NodeElement("com"); + final NodeElement actionSystem = new NodeElement("actionSystem"); + actionSystem.setForcedParent(com); + + doAndWaitForBuilder(new Runnable() { + public void run() { + myRoot.addChild(com).addChild(actionSystem); + getBuilder().getUi().activate(true); + } + }); + + select(actionSystem, false); + + assertTree("-/\n" + + " -com\n" + + " [actionSystem]\n"); + + + removeFromParentButKeepRef(actionSystem); + + final NodeElement newActionSystem = new NodeElement("actionSystem"); + + myStructure.getNodeFor(com).addChild("intellij").addChild("openapi").addChild(newActionSystem); + + assertSame(com, myStructure.getParentElement(actionSystem)); + assertNotSame(com, newActionSystem); + assertEquals(new NodeElement("openapi"), myStructure.getParentElement(newActionSystem)); + + myStructure.setRevalidator(new Revalidator() { + public NodeElement revalidate(NodeElement element) { + return element == actionSystem ? newActionSystem : null; + } + }); + + updateFromRoot(); + + assertTree("-/\n" + + " -com\n" + + " -intellij\n" + + " -openapi\n" + + " [actionSystem]\n"); + } + private void doTestSelectionOnDelete(boolean keepRef) throws Exception { myComparator.setDelegate(new NodeDescriptor.NodeComparator() { public int compare(NodeDescriptor o1, NodeDescriptor o2) { @@ -1702,13 +1746,8 @@ public class TreeUiTest extends AbstractTreeBuilderTest { } @Override - public void testCancelUpdate() throws Exception { - super.testCancelUpdate(); - } - - @Override - public void testThrowingProcessCancelledInterruptsUpdate() throws Exception { - super.testThrowingProcessCancelledInterruptsUpdate(); + public void testRevalidateStructure() throws Exception { + super.testRevalidateStructure(); } } From 1bd7b6591d3a598da1f47073c393ff7f3d2948f4 Mon Sep 17 00:00:00 2001 From: Kirill Kalishev Date: Fri, 28 May 2010 18:11:14 +0400 Subject: [PATCH 021/212] app icon tiny fix --- platform/platform-impl/src/com/intellij/ui/AppIcon.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ui/AppIcon.java b/platform/platform-impl/src/com/intellij/ui/AppIcon.java index 33e51d08c00b..cfd003fb6d90 100644 --- a/platform/platform-impl/src/com/intellij/ui/AppIcon.java +++ b/platform/platform-impl/src/com/intellij/ui/AppIcon.java @@ -130,8 +130,8 @@ public abstract class AppIcon { @Override public void applicationActivated(IdeFrame ideFrame) { hideProgress(myCurrentProcessId); - setOkBadge(false); - setErrorBadge(null); + _setOkBadge(false); + _setTextBadge(null); } }; app.addApplicationListener(myAppListener); From 4d706d696086c9636d3b06c50f2a4d01c8c82d74 Mon Sep 17 00:00:00 2001 From: Kirill Kalishev Date: Fri, 28 May 2010 20:21:03 +0400 Subject: [PATCH 022/212] attempt to commite bg loading interruption tests --- .../src/com/intellij/openapi/util/SimpleTimer.java | 4 ++++ .../com/intellij/ide/util/treeView/TreeUiTest.java | 11 ++++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/util/SimpleTimer.java b/platform/platform-api/src/com/intellij/openapi/util/SimpleTimer.java index 4569932702ef..c04d74b0a3e1 100644 --- a/platform/platform-api/src/com/intellij/openapi/util/SimpleTimer.java +++ b/platform/platform-api/src/com/intellij/openapi/util/SimpleTimer.java @@ -16,6 +16,7 @@ package com.intellij.openapi.util; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.progress.ProcessCanceledException; import org.jetbrains.annotations.NonNls; import java.util.*; @@ -134,6 +135,9 @@ public class SimpleTimer { try { each.run(); } + catch (ProcessCanceledException e) { + throw e; + } catch (Throwable e) { LOG.error(e); } diff --git a/platform/platform-impl/testSrc/com/intellij/ide/util/treeView/TreeUiTest.java b/platform/platform-impl/testSrc/com/intellij/ide/util/treeView/TreeUiTest.java index 3a44ccd3c1fa..5dfc46e85e55 100644 --- a/platform/platform-impl/testSrc/com/intellij/ide/util/treeView/TreeUiTest.java +++ b/platform/platform-impl/testSrc/com/intellij/ide/util/treeView/TreeUiTest.java @@ -3,10 +3,7 @@ package com.intellij.ide.util.treeView; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.Progressive; -import com.intellij.openapi.util.ActionCallback; -import com.intellij.openapi.util.Condition; -import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.util.Ref; +import com.intellij.openapi.util.*; import com.intellij.util.Time; import com.intellij.util.WaitFor; import junit.framework.TestSuite; @@ -1441,8 +1438,8 @@ public class TreeUiTest extends AbstractTreeBuilderTest { assertEquals(new NodeElement("openapi"), myStructure.getParentElement(newActionSystem)); myStructure.setRevalidator(new Revalidator() { - public NodeElement revalidate(NodeElement element) { - return element == actionSystem ? newActionSystem : null; + public AsyncResult revalidate(NodeElement element) { + return element == actionSystem ? new AsyncResult.Done(newActionSystem) : null; } }); @@ -1730,7 +1727,7 @@ public class TreeUiTest extends AbstractTreeBuilderTest { buildAction.run(); - boolean released = new WaitFor(5000) { + boolean released = new WaitFor(60000) { @Override protected boolean condition() { return getBuilder().getUi() == null; From 72401ebaae804b86522ff13316981f4721b4894b Mon Sep 17 00:00:00 2001 From: Kirill Kalishev Date: Fri, 28 May 2010 20:23:08 +0400 Subject: [PATCH 023/212] revalidation of elements in TreeUi and BaseProjectTreeBuilder --- .../projectView/BaseProjectTreeBuilder.java | 11 +++- .../util/treeView/AbstractTreeStructure.java | 59 ++++++++++++++++++- .../ide/util/treeView/AbstractTreeUi.java | 22 ++++--- .../treeView/AbstractTreeBuilderTest.java | 5 +- .../ide/util/treeView/BaseTreeTestCase.java | 8 ++- 5 files changed, 91 insertions(+), 14 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/BaseProjectTreeBuilder.java b/platform/lang-impl/src/com/intellij/ide/projectView/BaseProjectTreeBuilder.java index 62c157186e1d..006410ff9375 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/BaseProjectTreeBuilder.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/BaseProjectTreeBuilder.java @@ -52,10 +52,19 @@ public abstract class BaseProjectTreeBuilder extends AbstractTreeBuilder { DefaultTreeModel treeModel, AbstractTreeStructure treeStructure, Comparator comparator) { - super(tree, treeModel, treeStructure, comparator); + init(tree, treeModel, new AbstractTreeStructure.Delegate(treeStructure) { + @Override + public AsyncResult revalidateElement(Object element) { + return _revalidateElement(element); + } + }, comparator, DEFAULT_UPDATE_INACTIVE); myProject = project; } + private AsyncResult _revalidateElement(Object element) { + return new AsyncResult.Done(element); + } + protected boolean isAlwaysShowPlus(NodeDescriptor nodeDescriptor) { return ((AbstractTreeNode)nodeDescriptor).isAlwaysShowPlus(); } diff --git a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeStructure.java b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeStructure.java index 4612aa83211c..bff7c077e2ac 100644 --- a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeStructure.java +++ b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeStructure.java @@ -16,6 +16,7 @@ package com.intellij.ide.util.treeView; +import com.intellij.openapi.util.AsyncResult; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -39,8 +40,62 @@ public abstract class AbstractTreeStructure { return false; } - public Object revalidateElement(Object element) { - return element; + public AsyncResult revalidateElement(Object element) { + return new AsyncResult.Done(element); + } + + public static class Delegate extends AbstractTreeStructure { + private AbstractTreeStructure myDelegee; + + public Delegate(AbstractTreeStructure delegee) { + myDelegee = delegee; + } + + @Override + public Object getRootElement() { + return myDelegee.getRootElement(); + } + + @Override + public Object[] getChildElements(Object element) { + return myDelegee.getChildElements(element); + } + + @Override + public Object getParentElement(Object element) { + return myDelegee.getParentElement(element); + } + + @NotNull + @Override + public NodeDescriptor createDescriptor(Object element, NodeDescriptor parentDescriptor) { + return myDelegee.createDescriptor(element, parentDescriptor); + } + + @Override + public void commit() { + myDelegee.commit(); + } + + @Override + public boolean hasSomethingToCommit() { + return myDelegee.hasSomethingToCommit(); + } + + @Override + public boolean isToBuildChildrenInBackground(Object element) { + return myDelegee.isToBuildChildrenInBackground(element); + } + + @Override + public boolean isAlwaysLeaf(Object element) { + return myDelegee.isAlwaysLeaf(element); + } + + @Override + public AsyncResult revalidateElement(Object element) { + return myDelegee.revalidateElement(element); + } } } \ No newline at end of file diff --git a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java index 77ecd1f686f1..adbb791565a0 100644 --- a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java +++ b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java @@ -3462,20 +3462,26 @@ public class AbstractTreeUi { _expand(element, _onDone, true, false, canSmartExpand); } - private void checkPathAndMaybeRevalidate(Object element, Runnable onDone, boolean parentsOnly, boolean checkIfInStructure, boolean canSmartExpand) { + private void checkPathAndMaybeRevalidate(Object element, final Runnable onDone, final boolean parentsOnly, final boolean checkIfInStructure, final boolean canSmartExpand) { boolean toRevalidate = getNodeForElement(element, false) == null && isInStructure(element); if (!toRevalidate) { runDone(onDone); return; } - Object actualElement = getTreeStructure().revalidateElement(element); - if (actualElement == null) { - runDone(onDone); - return; - } - - _expand(actualElement, onDone, parentsOnly, checkIfInStructure, canSmartExpand); + getTreeStructure().revalidateElement(element).doWhenDone(new AsyncResult.Handler() { + public void run(final Object o) { + invokeLaterIfNeeded(new Runnable() { + public void run() { + _expand(o, onDone, parentsOnly, checkIfInStructure, canSmartExpand); + } + }); + } + }).doWhenRejected(new Runnable() { + public void run() { + runDone(onDone); + } + }); } public void scrollSelectionToVisible(@Nullable Runnable onDone, boolean shouldBeCentered) { diff --git a/platform/platform-impl/testSrc/com/intellij/ide/util/treeView/AbstractTreeBuilderTest.java b/platform/platform-impl/testSrc/com/intellij/ide/util/treeView/AbstractTreeBuilderTest.java index a94f57214b68..2721428b3bdc 100644 --- a/platform/platform-impl/testSrc/com/intellij/ide/util/treeView/AbstractTreeBuilderTest.java +++ b/platform/platform-impl/testSrc/com/intellij/ide/util/treeView/AbstractTreeBuilderTest.java @@ -1,5 +1,6 @@ package com.intellij.ide.util.treeView; +import com.intellij.openapi.util.AsyncResult; import com.intellij.openapi.util.Condition; import com.intellij.testFramework.PlatformTestUtil; import com.intellij.ui.treeStructure.Tree; @@ -525,7 +526,7 @@ abstract class AbstractTreeBuilderTest extends BaseTreeTestCase revalidateElement(Object element) { return myRevalidator != null ? myRevalidator.revalidate((NodeElement)element) : super.revalidateElement(element); } @@ -535,7 +536,7 @@ abstract class AbstractTreeBuilderTest extends BaseTreeTestCase revalidate(NodeElement element); } class MyBuilder extends BaseTreeBuilder { diff --git a/platform/platform-impl/testSrc/com/intellij/ide/util/treeView/BaseTreeTestCase.java b/platform/platform-impl/testSrc/com/intellij/ide/util/treeView/BaseTreeTestCase.java index 9e55f0858cdf..9b53c5a35611 100644 --- a/platform/platform-impl/testSrc/com/intellij/ide/util/treeView/BaseTreeTestCase.java +++ b/platform/platform-impl/testSrc/com/intellij/ide/util/treeView/BaseTreeTestCase.java @@ -226,7 +226,13 @@ abstract class BaseTreeTestCase extends FlyIdeaTestCase { } void _runBackgroundLoading(Runnable runnable) { - SimpleTimer.getInstance().setUp(runnable, getChildrenLoadingDelay()); + try { + Thread.currentThread().sleep(getChildrenLoadingDelay()); + runnable.run(); + } + catch (InterruptedException e) { + throw new RuntimeException(e); + } } From abc2d6a6e1b56d8fce3ef1d28fec1026a7abd7f7 Mon Sep 17 00:00:00 2001 From: Kirill Kalishev Date: Fri, 28 May 2010 20:26:18 +0400 Subject: [PATCH 024/212] PackagesTreeStructureTest.testPackageView fix --- .../src/com/intellij/ide/util/treeView/AbstractTreeUi.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java index adbb791565a0..cd7d9eedd2de 100644 --- a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java +++ b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java @@ -3127,8 +3127,10 @@ public class AbstractTreeUi { } myTreeModel.nodeStructureChanged(parentNode); - while (expanded.hasMoreElements()) { - expandSilently(expanded.nextElement()); + if (expanded != null) { + while (expanded.hasMoreElements()) { + expandSilently(expanded.nextElement()); + } } if (selected != null) { From 01f41c167800381ec569a7560510830bfcd0fb67 Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Sat, 29 May 2010 13:40:10 +0400 Subject: [PATCH 025/212] integration with java --- .../ChangeSignatureProcessor.java | 5 +- .../JavaChangeSignatureUsageProcessor.java | 3 +- .../dynamic/elements/DMethodElement.java | 2 +- .../lang/psi/GroovyPsiElementFactory.java | 20 ++- .../psi/impl/GroovyPsiElementFactoryImpl.java | 43 +++-- .../GrChageSignatureUsageSearcher.java | 28 +++- .../GrChangeSignatureConflictSearcher.java | 4 +- .../GrChangeSignatureDialog.form | 2 +- .../GrChangeSignatureDialog.java | 6 + .../GrChangeSignatureUsageProcessor.java | 152 ++++++++++++------ .../ChangeSignatureForJavaTest.java | 22 +-- .../changeSignature/ChangeSignatureTest.java | 18 ++- .../ExceptionCaughtInUsage_after.groovy | 1 + .../ExceptionInClosableBlock_after.groovy | 1 + .../GenerateDelegateForAbstract.groovy | 9 ++ .../GenerateDelegateForAbstract_after.groovy | 13 ++ .../GenerateDelegateForConstructor.groovy | 11 ++ ...enerateDelegateForConstructor_after.groovy | 15 ++ .../changeSignature/MoveArrayToTheEnd.groovy | 3 + .../MoveArrayToTheEnd_after.groovy | 3 + .../changeSignature/TypeParameters.groovy | 7 + .../TypeParameters_after.groovy | 7 + .../AddException_after.groovy | 6 +- .../CovariantReturnType.groovy | 7 + .../CovariantReturnType_after.groovy | 7 + .../EnumConstructor.java | 7 - .../EnumConstructor_after.java | 7 - .../GenericTypesInOldParameters.groovy | 5 + .../GenericTypesInOldParameters_after.groovy | 5 + ...eParameterWithDefaultValueInHierarchy.java | 9 -- ...eterWithDefaultValueInHierarchy_after.java | 9 -- .../ReorderExceptions.groovy | 20 +++ .../ReorderExceptions_after.groovy | 19 +++ .../ReorderWithVarargs.java | 7 - .../ReorderWithVarargs_after.java | 7 - .../TypeParametersInMethod.groovy | 4 + .../TypeParametersInMethod_after.groovy | 4 + .../changeSignatureForJava/Varargs1.groovy | 3 + .../Varargs1_after.groovy | 3 + 39 files changed, 365 insertions(+), 139 deletions(-) create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/GenerateDelegateForAbstract.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/GenerateDelegateForAbstract_after.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/GenerateDelegateForConstructor.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/GenerateDelegateForConstructor_after.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/MoveArrayToTheEnd.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/MoveArrayToTheEnd_after.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/TypeParameters.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/TypeParameters_after.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/CovariantReturnType.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/CovariantReturnType_after.groovy delete mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/EnumConstructor.java delete mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/EnumConstructor_after.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/GenericTypesInOldParameters.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/GenericTypesInOldParameters_after.groovy delete mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/IntroduceParameterWithDefaultValueInHierarchy.java delete mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/IntroduceParameterWithDefaultValueInHierarchy_after.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderExceptions.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderExceptions_after.groovy delete mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderWithVarargs.java delete mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderWithVarargs_after.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/TypeParametersInMethod.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/TypeParametersInMethod_after.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/Varargs1.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignatureForJava/Varargs1_after.groovy diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java index e83f00598218..c543d4ee7b8b 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java @@ -206,9 +206,8 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor { protected boolean isProcessCovariantOverriders() { return Messages - .showYesNoDialog(myProject, RefactoringBundle.message("do.you.want.to.process.overriding.methods.with.covariant.return.type"), - JavaChangeSignatureHandler.REFACTORING_NAME, Messages.getQuestionIcon()) - == DialogWrapper.OK_EXIT_CODE; + .showYesNoDialog(myProject, RefactoringBundle.message("do.you.want.to.process.overriding.methods.with.covariant.return.type"), + JavaChangeSignatureHandler.REFACTORING_NAME, Messages.getQuestionIcon()) == DialogWrapper.OK_EXIT_CODE; } protected void performRefactoring(UsageInfo[] usages) { diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java index a176578ec659..56985374bbc5 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java @@ -403,14 +403,13 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr newArgsLength = newParms.length; } final PsiExpression[] newArgs = new PsiExpression[newArgsLength]; - final JavaParameterInfo[] newParameters = changeInfo.getNewParameters(); for (int i = 0; i < newNonVarargCount; i++) { newArgs[i] = createActualArgument(changeInfo, list, newParms[i], toInsertDefaultValue, args); } if (changeInfo.isArrayToVarargs()) { if (newVarargInitializers == null) { newArgs[newNonVarargCount] = - createActualArgument(changeInfo, list, newParameters[newNonVarargCount], toInsertDefaultValue, args); + createActualArgument(changeInfo, list, newParms[newNonVarargCount], toInsertDefaultValue, args); } else { System.arraycopy(newVarargInitializers, 0, newArgs, newNonVarargCount, newVarargInitializers.length); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/dynamic/elements/DMethodElement.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/dynamic/elements/DMethodElement.java index ade4225f7475..2b07b647b2cf 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/dynamic/elements/DMethodElement.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/dynamic/elements/DMethodElement.java @@ -72,7 +72,7 @@ public class DMethodElement extends DItemElement { final String[] argumentsTypes = QuickfixUtil.getArgumentsTypes(myPairs); final GrMethod method = GroovyPsiElementFactory.getInstance(manager.getProject()) - .createMethodFromText(staticModifier, getName(), type, argumentsTypes); + .createMethodFromText(staticModifier, getName(), type, argumentsTypes, null); myImplicitMethod = new GrDynamicImplicitMethod(manager, method, containingClassName) { @Override diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyPsiElementFactory.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyPsiElementFactory.java index 7916fede4bb9..2750f6bf0aae 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyPsiElementFactory.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyPsiElementFactory.java @@ -144,15 +144,27 @@ public abstract class GroovyPsiElementFactory { public abstract PsiElement createDotToken(String newDot); - public abstract GrMethod createMethodFromText(String methodText); + public abstract GrMethod createMethodFromText(String methodText, PsiElement context); + + public GrMethod createMethodFromText(String methodText) { + return createMethodFromText(methodText, null); + } public abstract GrAnnotation createAnnotationFromText(String annoText); public abstract GroovyFile createGroovyFile(String text, boolean isPhisical, PsiElement context); - public abstract GrMethod createMethodFromText(String modifier, String name, String type, String[] paramTypes); + public abstract GrMethod createMethodFromText(String modifier, String name, String type, String[] paramTypes, PsiElement context); - public abstract GrMethod createConstructorFromText(@NotNull String constructorName, String[] paramTypes, String[] paramNames, String body); + public abstract GrMethod createConstructorFromText(@NotNull String constructorName, + String[] paramTypes, + String[] paramNames, + String body, + PsiElement context); + + public GrMethod createConstructorFromText(@NotNull String constructorName, String[] paramTypes, String[] paramNames, String body) { + return createConstructorFromText(constructorName, paramTypes, paramNames, body, null); + } public abstract GrLabel createLabel(@NotNull String name); @@ -163,4 +175,6 @@ public abstract class GroovyPsiElementFactory { public abstract PsiReferenceList createThrownList(PsiClassType[] exceptionTypes); public abstract GrCatchClause createCatchClause(PsiClassType type, String parameterName); + + public abstract GrArgumentList createArgumentList(); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java index 1fe8fc9b9241..5605528578de 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java @@ -355,10 +355,15 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory { return createReferenceExpressionFromText("a" + newDot + "b").getDotToken(); } - public GrConstructorImpl createConstructorFromText(@NotNull String constructorName, @Nullable String[] paramTypes, String[] paramNames, String body) { - final GrMethod method = createMethodFromText(null, constructorName, null, paramTypes, paramNames, body); + public GrConstructorImpl createConstructorFromText(@NotNull String constructorName, + @Nullable String[] paramTypes, + String[] paramNames, + String body, + PsiElement context) { + final GrMethod method = createMethodFromText(null, constructorName, null, paramTypes, paramNames, body, context); - GroovyFileBase file = createDummyFile("class " + constructorName + "{" + method.getText() + "}"); + GroovyFileImpl file = createDummyFile("class " + constructorName + "{" + method.getText() + "}"); + file.setContext(context); GrTopLevelDefintion defintion = file.getTopLevelDefinitions()[0]; assert defintion != null && defintion instanceof GrClassDefinition; final PsiMethod constructor = ((GrClassDefinition) defintion).getMethods()[0]; @@ -374,8 +379,11 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory { return ((GrLabeledStatement)definition).getLabel(); } - public GrMethod createMethodFromText(@NotNull String methodText) { - GroovyFileBase file = createDummyFile(methodText); + public GrMethod createMethodFromText(@NotNull String methodText, PsiElement context) { + GroovyFileImpl file = createDummyFile(methodText); + if (context != null) { + file.setContext(context); + } try { GrTopLevelDefintion defintion = file.getTopLevelDefinitions()[0]; assert defintion != null && defintion instanceof GrMethod; @@ -388,7 +396,7 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory { @Override public GrAnnotation createAnnotationFromText(String annoText) { - return createMethodFromText(annoText + " void foo() {}").getModifierList().getAnnotations()[0]; + return createMethodFromText(annoText + " void foo() {}", null).getModifierList().getAnnotations()[0]; } public PsiFile createGroovyFile(String idText) { @@ -500,7 +508,13 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory { } - private GrMethod createMethodFromText(String modifier, String name, String type, @Nullable String[] paramTypes, @NotNull String[] paramNames, String body) { + private GrMethod createMethodFromText(String modifier, + String name, + String type, + @Nullable String[] paramTypes, + @NotNull String[] paramNames, + String body, + PsiElement context) { StringBuilder builder = new StringBuilder(); if (modifier != null){ @@ -537,10 +551,10 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory { builder.append("}"); } - return createMethodFromText(builder.toString()); + return createMethodFromText(builder.toString(), context); } - public GrMethod createMethodFromText(String modifier, String name, @Nullable String type, String[] paramTypes) { + public GrMethod createMethodFromText(String modifier, String name, @Nullable String type, String[] paramTypes, PsiElement context) { PsiType psiType; List res = new ArrayList(); final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(myProject); @@ -556,7 +570,7 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory { } return createMethodFromText(modifier, name, type, paramTypes, - QuickfixUtil.getMethodArgumentsNames(myProject, res.toArray(new PsiType[res.size()])), null); + QuickfixUtil.getMethodArgumentsNames(myProject, res.toArray(new PsiType[res.size()])), null, context); } public GrDocComment createDocCommentFromText(String text) { @@ -575,14 +589,14 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory { @Override public PsiReferenceList createThrownList(PsiClassType[] exceptionTypes) { if (exceptionTypes.length == 0) { - return createMethodFromText("def foo(){}").getThrowsList(); + return createMethodFromText("def foo(){}", null).getThrowsList(); } String[] types = new String[exceptionTypes.length]; for (int i = 0; i < types.length; i++) { types[i] = exceptionTypes[i].getCanonicalText(); } final String end = StringUtil.join(types, ","); - return createMethodFromText("def foo() throws " + end + "{}").getThrowsList(); + return createMethodFromText("def foo() throws " + end + "{}", null).getThrowsList(); } @Override @@ -598,4 +612,9 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory { final GrTryCatchStatement statement = (GrTryCatchStatement)createStatementFromText(buffer.toString()); return statement.getCatchClauses()[0]; } + + @Override + public GrArgumentList createArgumentList() { + return ((GrCall)createExpressionFromText("foo()")).getArgumentList(); + } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChageSignatureUsageSearcher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChageSignatureUsageSearcher.java index 072f880bdadc..448b63129244 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChageSignatureUsageSearcher.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChageSignatureUsageSearcher.java @@ -34,7 +34,10 @@ import com.intellij.usageView.UsageViewUtil; import com.intellij.util.containers.HashSet; import org.jetbrains.plugins.groovy.GroovyFileType; import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocTagValueToken; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousClassDefinition; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature; import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil; @@ -146,7 +149,10 @@ class GrChageSignatureUsageSearcher { } } }; - GrUnresolvableLocalCollisionDetector.visitLocalsCollisions(method, newName, method.getBlock(), variableVisitor); + final GrOpenBlock block = method.getBlock(); + if (block != null) { + GrUnresolvableLocalCollisionDetector.visitLocalsCollisions(method, newName, block, variableVisitor); + } } } } @@ -204,10 +210,22 @@ class GrChageSignatureUsageSearcher { //todo check for applicability of arguments to method if (PsiUtil.isMethodUsage(element)) { GrClosureSignature signature = GrClosureSignatureUtil.createSignature(method, PsiSubstitutor.EMPTY); - GrClosureSignatureUtil.ArgInfo[] map = GrClosureSignatureUtil - .mapParametersToArguments(signature, PsiUtil.getArgumentsList(element), method.getManager(), method.getResolveScope()); - result.add( - new GrMethodCallUsageInfo(element, GrClosureSignatureUtil.createSignature(method, PsiSubstitutor.EMPTY), isToModifyArgs, isToCatchExceptions, map)); + final GrArgumentList argList = PsiUtil.getArgumentsList(element); + //enum constant may not have argList + if (argList == null) { + if (element instanceof GrEnumConstant) { + result.add( + new GrMethodCallUsageInfo(element, GrClosureSignatureUtil.createSignature(method, PsiSubstitutor.EMPTY), isToModifyArgs, + isToCatchExceptions, new GrClosureSignatureUtil.ArgInfo[0])); + } + } + else { + GrClosureSignatureUtil.ArgInfo[] map = + GrClosureSignatureUtil.mapParametersToArguments(signature, argList, method.getManager(), method.getResolveScope()); + result.add( + new GrMethodCallUsageInfo(element, GrClosureSignatureUtil.createSignature(method, PsiSubstitutor.EMPTY), isToModifyArgs, + isToCatchExceptions, map)); + } } else if (element instanceof GrDocTagValueToken) { result.add(new UsageInfo(ref.getElement())); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureConflictSearcher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureConflictSearcher.java index 1ebefc2c49b1..27acb2f08c76 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureConflictSearcher.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureConflictSearcher.java @@ -139,10 +139,10 @@ class GrChangeSignatureConflictSearcher { final CanonicalTypes.Type returnType = myChangeInfo.getNewReturnType(); String newMethodName = myChangeInfo.getNewName(); if (returnType != null) { - prototype = factory.createMethodFromText("", newMethodName, returnType.getTypeText(), ArrayUtil.EMPTY_STRING_ARRAY); + prototype = factory.createMethodFromText("", newMethodName, returnType.getTypeText(), ArrayUtil.EMPTY_STRING_ARRAY, method); } else { - prototype = factory.createConstructorFromText(newMethodName, ArrayUtil.EMPTY_STRING_ARRAY, ArrayUtil.EMPTY_STRING_ARRAY, "{}"); + prototype = factory.createConstructorFromText(newMethodName, ArrayUtil.EMPTY_STRING_ARRAY, ArrayUtil.EMPTY_STRING_ARRAY, "{}", method); } JavaParameterInfo[] parameters = myChangeInfo.getNewParameters(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.form b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.form index 415ac736259c..fafc8c3bbab0 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.form +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.form @@ -116,7 +116,7 @@ - + diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java index fc51098f2d6e..36a09576add5 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java @@ -72,6 +72,7 @@ public class GrChangeSignatureDialog extends RefactoringDialog { @SuppressWarnings({"UnusedDeclaration"}) private JPanel myParameterButtonPanel; private JBTable myExceptionsTable; @SuppressWarnings({"UnusedDeclaration"}) private JPanel myExceptionsButtonPanel; + private JPanel myDelegatePanel; private GrParameterTableModel myParameterModel; private GrMethod myMethod; private PsiTypeCodeFragment myReturnTypeCodeFragment; @@ -96,6 +97,11 @@ public class GrChangeSignatureDialog extends RefactoringDialog { protected void init() { super.init(); + final PsiClass psiClass = myMethod.getContainingClass(); + if (psiClass == null) return; + if (psiClass.isInterface()) { + myDelegatePanel.setVisible(false); + } } private void stopEditing() { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java index 83fdc3b00eb1..979a99994e26 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java @@ -21,7 +21,7 @@ import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleManager; -import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.*; import com.intellij.refactoring.changeSignature.*; import com.intellij.refactoring.util.CanonicalTypes; import com.intellij.refactoring.util.RefactoringUtil; @@ -37,8 +37,10 @@ import com.intellij.util.containers.hash.HashSet; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.GroovyFileType; import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement; +import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; +import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrCatchClause; @@ -50,12 +52,12 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArg import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterList; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrConstructor; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; @@ -110,10 +112,28 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc newMethod = (GrMethod)psiClass.addAfter(newMethod, method); StringBuffer buffer = new StringBuffer(); buffer.append("\n"); - if (!PsiType.VOID.equals(method.getReturnType())) { - buffer.append("return "); + if (method.isConstructor()) { + buffer.append("this"); } - buffer.append(method.getName()).append("("); + else { + if (!PsiType.VOID.equals(method.getReturnType())) { + buffer.append("return "); + } + buffer.append(method.getName()); + } + + generateParametersForDelegateCall(grInfo, method, buffer); + + final GrCodeBlock codeBlock = GroovyPsiElementFactory.getInstance(method.getProject()).createMethodBodyFromText(buffer.toString()); + newMethod.setBlock(codeBlock); + newMethod.getModifierList().setModifierProperty(GrModifier.ABSTRACT, false); + + CodeStyleManager.getInstance(method.getProject()).reformat(newMethod); + return processPrimaryMethodInner(grInfo, method, null); + } + + private static void generateParametersForDelegateCall(GrChangeInfoImpl grInfo, GrMethod method, StringBuffer buffer) { + buffer.append("("); final GrParameter[] oldParameters = method.getParameterList().getParameters(); final JavaParameterInfo[] parameters = grInfo.getNewParameters(); @@ -131,11 +151,6 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc } buffer.append(StringUtil.join(params, ",")); buffer.append(");"); - - final GrCodeBlock codeBlock = GroovyPsiElementFactory.getInstance(method.getProject()).createMethodBodyFromText(buffer.toString()); - newMethod.setBlock(codeBlock); - CodeStyleManager.getInstance(method.getProject()).reformat(newMethod); - return processPrimaryMethodInner(grInfo, method, null); } private static boolean processPrimaryMethodInner(JavaChangeInfo changeInfo, GrMethod method, PsiMethod baseMethod) { @@ -151,6 +166,9 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc method.getModifierList().setModifierProperty(changeInfo.getNewVisibility(), true); } + PsiSubstitutor substitutor = baseMethod != null ? calculateSubstitutor(method, baseMethod) : PsiSubstitutor.EMPTY; + + final PsiMethod context = changeInfo.getMethod(); if (changeInfo.isReturnTypeChanged()) { CanonicalTypes.Type newReturnType = changeInfo.getNewReturnType(); GrTypeElement element = method.getReturnTypeElementGroovy(); @@ -164,8 +182,11 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc } } else { - PsiType type = newReturnType.getType(method.getParameterList(), method.getManager()); - method.setReturnType(type); + PsiType type = newReturnType.getType(context, method.getManager()); + final PsiType oldReturnType = method.getReturnType(); + if (!TypesUtil.isAssignable(type, oldReturnType, context.getManager(), context.getResolveScope())) { //todo ask for replace covariant type + method.setReturnType(substitutor.substitute(type)); + } } } @@ -179,39 +200,24 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(method.getProject()); GrParameter anchor = null; for (JavaParameterInfo newParameter : newParameters) { - /* - int index = newParameter.getOldIndex(); - if (index < 0) { - */ - String typeText; + PsiType type; if (newParameter instanceof GrParameterInfo && ((GrParameterInfo)newParameter).hasNoType()) { - typeText = null; + type = null; } else { - typeText = newParameter.getTypeText(); + type = substitutor.substitute(newParameter.createType(context, method.getManager())); } - GrParameter grParameter = - factory.createParameter(newParameter.getName(), typeText, getInitializer(newParameter), parameterList); + + GrParameter grParameter = factory + .createParameter(newParameter.getName(), type == null ? null : type.getCanonicalText(), getInitializer(newParameter), + parameterList); anchor = (GrParameter)parameterList.addAfter(grParameter, anchor); -/* } - else { - GrParameter grParameter = oldParameters[index]; - if (grParameter != getNextOfType(parameterList, anchor, GrParameter.class)) { - anchor = (GrParameter)parameterList.addAfter(grParameter, anchor); - } - else { - anchor = grParameter; - toRemove.remove(grParameter); - } - if (anchor.getName() != newParameter.getName()) { - anchor.setName(newParameter.getName()); - } - }*/ } for (GrParameter oldParameter : toRemove) { oldParameter.delete(); } + PsiUtil.shortenReferences(parameterList); CodeStyleManager.getInstance(parameterList.getProject()).reformat(parameterList); if (changeInfo.isExceptionSetOrOrderChanged()) { @@ -230,6 +236,31 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc return true; } + private static PsiSubstitutor calculateSubstitutor(PsiMethod derivedMethod, PsiMethod baseMethod) { + PsiSubstitutor substitutor; + if (derivedMethod.getManager().areElementsEquivalent(derivedMethod, baseMethod)) { + substitutor = PsiSubstitutor.EMPTY; + } + else { + final PsiClass baseClass = baseMethod.getContainingClass(); + final PsiClass derivedClass = derivedMethod.getContainingClass(); + if (baseClass != null && derivedClass != null && InheritanceUtil.isInheritorOrSelf(derivedClass, baseClass, true)) { + final PsiSubstitutor superClassSubstitutor = + TypeConversionUtil.getSuperClassSubstitutor(baseClass, derivedClass, PsiSubstitutor.EMPTY); + final MethodSignature superMethodSignature = baseMethod.getSignature(superClassSubstitutor); + final MethodSignature methodSignature = derivedMethod.getSignature(PsiSubstitutor.EMPTY); + final PsiSubstitutor superMethodSubstitutor = + MethodSignatureUtil.getSuperMethodSignatureSubstitutor(methodSignature, superMethodSignature); + substitutor = superMethodSubstitutor != null ? superMethodSubstitutor : superClassSubstitutor; + } + else { + substitutor = PsiSubstitutor.EMPTY; + } + } + return substitutor; + } + + @Nullable private static Type getNextOfType(List parameterList, PsiElement current, @@ -293,7 +324,7 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc String name = psiClass.getName(); GrConstructor constructor = ((GrConstructor)GroovyPsiElementFactory.getInstance(psiClass.getProject()) - .createConstructorFromText(name, ArrayUtil.EMPTY_STRING_ARRAY, ArrayUtil.EMPTY_STRING_ARRAY, "{}")); + .createConstructorFromText(name, ArrayUtil.EMPTY_STRING_ARRAY, ArrayUtil.EMPTY_STRING_ARRAY, "{}", null)); GrModifierList list = constructor.getModifierList(); if (psiClass.hasModifierProperty(GrModifier.PRIVATE)) list.setModifierProperty(GrModifier.PRIVATE, true); @@ -337,8 +368,17 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc } if (toChangeArguments) { JavaParameterInfo[] parameters = changeInfo.getNewParameters(); - GrArgumentList argumentList = ((GrCall)element.getParent()).getArgumentList(); - if (argumentList == null) return; + GrArgumentList argumentList = PsiUtil.getArgumentsList(element); + GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(element.getProject()); + if (argumentList == null) { + if (element instanceof GrEnumConstant) { + argumentList = factory.createArgumentList(); + argumentList = (GrArgumentList)element.add(argumentList); + } + else { + return; + } + } Set argsToDelete = new HashSet(map.length * 2); for (GrClosureSignatureUtil.ArgInfo argInfo : map) { argsToDelete.addAll(argInfo.args); @@ -355,7 +395,6 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc arg.delete(); } - GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(element.getProject()); boolean skipOptionals = false; PsiElement anchor = null; //PsiTreeUtil.getChildOfAnyType(argumentList, GrExpression.class, GrNamedArgument.class); @@ -384,14 +423,29 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc else { //arguments for simple parameters if (arguments.size() == 1) { //arg exists PsiElement arg = arguments.iterator().next(); + if (i == parameters.length - 1 && parameter.isVarargType()) { + if (arg instanceof GrSafeCastExpression) { + PsiElement expr = ((GrSafeCastExpression)arg).getOperand(); + if (expr instanceof GrListOrMap && !((GrListOrMap)expr).isMap()) { + final PsiElement copy = expr.copy(); + PsiElement[] newVarargs = ((GrListOrMap)copy).getInitializers(); + for (PsiElement vararg : newVarargs) { + anchor = argumentList.addAfter(vararg, anchor); + } + arg.delete(); + continue; + } + } + } + PsiElement curArg = getNextOfType(argumentList, anchor, GrExpression.class); if (curArg == arg) { anchor = arg; } else { final PsiElement copy = arg.copy(); - arg.delete(); anchor = argumentList.addAfter(copy, anchor); + arg.delete(); } } else { //arg is skipped. Parameter is optional @@ -425,15 +479,18 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc private static void fixExceptions(PsiElement element, PsiClassType[] exceptions) { if (exceptions.length == 0) return; final GroovyPsiElement context = - PsiTreeUtil.getParentOfType(element, GrTryCatchStatement.class, GrClosableBlock.class, GrMethod.class); + PsiTreeUtil.getParentOfType(element, GrTryCatchStatement.class, GrClosableBlock.class, GrMethod.class, GroovyFile.class); if (context instanceof GrClosableBlock) { element = generateTryCatch(element, exceptions); } else if (context instanceof GrMethod) { - final PsiClassType[] referencedTypes = ((GrMethod)context).getThrowsList().getReferencedTypes(); - final List psiClassTypes = filterOutExceptions(exceptions, context, referencedTypes); + final PsiClassType[] handledExceptions = ((GrMethod)context).getThrowsList().getReferencedTypes(); + final List psiClassTypes = filterOutExceptions(exceptions, context, handledExceptions); element = generateTryCatch(element, psiClassTypes.toArray(new PsiClassType[psiClassTypes.size()])); } + else if (context instanceof GroovyFile) { + element = generateTryCatch(element, exceptions); + } else if (context instanceof GrTryCatchStatement) { final GrCatchClause[] catchClauses = ((GrTryCatchStatement)context).getCatchClauses(); List referencedTypes = ContainerUtil.map(catchClauses, new Function() { @@ -493,6 +550,8 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc for (PsiClassType type : exceptions) { final String[] names = GroovyNameSuggestionUtil.suggestVariableNameByType(type, nameValidator); final GrCatchClause catchClause = factory.createCatchClause(type, names[0]); + final GrStatement printStackTrace = factory.createStatementFromText(names[0] + ".printStackTrace()"); + catchClause.getBody().addStatementBefore(printStackTrace, null); anchor = tryCatch.addCatchClause(catchClause, anchor); PsiUtil.shortenReferences(anchor); } @@ -501,10 +560,11 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc private static List filterOutExceptions(PsiClassType[] exceptions, final GroovyPsiElement context, - final PsiClassType[] referencedTypes) { + final PsiClassType[] handledExceptions) { return ContainerUtil.findAll(exceptions, new Condition() { public boolean value(PsiClassType o) { - for (PsiClassType type : referencedTypes) { + if (!InheritanceUtil.isInheritor(o, CommonClassNames.JAVA_LANG_EXCEPTION)) return false; + for (PsiClassType type : handledExceptions) { if (TypesUtil.isAssignable(type, o, context.getManager(), context.getResolveScope(), false)) return false; } return true; diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureForJavaTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureForJavaTest.java index ac619531f787..3a7ee3b4c5e7 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureForJavaTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureForJavaTest.java @@ -11,8 +11,6 @@ import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NonNls; import org.jetbrains.plugins.groovy.util.TestUtils; -import java.io.File; - /** * @author Maxim.Medvedev */ @@ -125,7 +123,7 @@ public class ChangeSignatureForJavaTest extends LightCodeInsightFixtureTestCase } */ - //todo? + /*//todo? public void testUseAnyVariable() throws Exception { doTest(null, null, null, new GenParams() { public ParameterInfoImpl[] genParams(PsiMethod method) throws IncorrectOperationException { @@ -135,20 +133,21 @@ public class ChangeSignatureForJavaTest extends LightCodeInsightFixtureTestCase }; } }, false); - } + }*/ /* public void testRemoveVarargParameter() throws Exception { doTest(null, null, null, new ParameterInfoImpl[]{new ParameterInfoImpl(0)}, new ThrownExceptionInfo[0], false); } - */ + public void testEnumConstructor() throws Exception { doTest(null, new ParameterInfoImpl[] { new ParameterInfoImpl(-1, "i", PsiType.INT, "10") }, false); } - + */ + public void testVarargs1() throws Exception { doTest(null, new ParameterInfoImpl[] { new ParameterInfoImpl(-1, "b", PsiType.BOOLEAN, "true"), @@ -166,6 +165,7 @@ public class ChangeSignatureForJavaTest extends LightCodeInsightFixtureTestCase false); } + /* public void testAlreadyHandled() throws Exception { doTest(null, null, null, new SimpleParameterGen(new ParameterInfoImpl[0]), new GenExceptions() { @@ -176,8 +176,9 @@ public class ChangeSignatureForJavaTest extends LightCodeInsightFixtureTestCase } }, false); - } + }*/ + /* public void testAddRuntimeException() throws Exception { doTest(null, null, null, new SimpleParameterGen(new ParameterInfoImpl[0]), new GenExceptions() { @@ -189,6 +190,7 @@ public class ChangeSignatureForJavaTest extends LightCodeInsightFixtureTestCase }, false); } + */ public void testAddException() throws Exception { doTest(null, null, null, new SimpleParameterGen(new ParameterInfoImpl[0]), @@ -202,6 +204,7 @@ public class ChangeSignatureForJavaTest extends LightCodeInsightFixtureTestCase false); } + /* //todo public void testReorderWithVarargs() throws Exception { // IDEADEV-26977 final PsiElementFactory factory = JavaPsiFacade.getInstance(getProject()).getElementFactory(); @@ -210,10 +213,7 @@ public class ChangeSignatureForJavaTest extends LightCodeInsightFixtureTestCase new ParameterInfoImpl(0, "s", factory.createTypeFromText("java.lang.String...", myFixture.getFile())) }, false); } - - public void testIntroduceParameterWithDefaultValueInHierarchy() throws Exception { - doTest(null, new ParameterInfoImpl[]{new ParameterInfoImpl(-1, "i", PsiType.INT, "0")}, false); - } + */ private void doTest(String newReturnType, ParameterInfoImpl[] parameterInfos, final boolean generateDelegate) throws Exception { doTest(null, null, newReturnType, parameterInfos, new ThrownExceptionInfo[0], generateDelegate); diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java index ee67f97e36fa..c384a1ea8066 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java @@ -183,18 +183,28 @@ public class ChangeSignatureTest extends ChangeSignatureTestCase { ); } - public void testGenerateDelegateForConstructor() { - //todo + public void testGenerateDelegateForConstructor() throws Exception { + doTest("public", "Foo", null, new SimpleInfo[]{new SimpleInfo(0), new SimpleInfo("a", -1, "5", null, PsiType.INT)}, + new ThrownExceptionInfo[0], true); } - public void testGenerateDelegateForAbstract() { - //todo + public void testGenerateDelegateForAbstract() throws Exception { + doTest("public", "foo", null, new SimpleInfo[]{new SimpleInfo(0), new SimpleInfo("a", -1, "5", null, PsiType.INT)}, + new ThrownExceptionInfo[0], true); + } + + public void testTypeParameters() throws Exception { + doTest(new SimpleInfo[]{new SimpleInfo("list", -1, "null", null, createType("java.util.List")), new SimpleInfo(0)}); } public void testEnumConstructor() throws Exception { doTest(new SimpleInfo[]{new SimpleInfo("a", -1, "2", null, PsiType.INT)}); } + public void testMoveArrayToTheEnd() throws Exception { + doTest(new SimpleInfo[] {new SimpleInfo(1), new SimpleInfo(0)}); + } + private PsiType createType(String typeText) { return JavaPsiFacade.getElementFactory(getProject()).createTypeByFQClassName(typeText, GlobalSearchScope.allScope(getProject())); } diff --git a/plugins/groovy/testdata/refactoring/changeSignature/ExceptionCaughtInUsage_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/ExceptionCaughtInUsage_after.groovy index 11e39836bd31..e5cd8cd3337c 100644 --- a/plugins/groovy/testdata/refactoring/changeSignature/ExceptionCaughtInUsage_after.groovy +++ b/plugins/groovy/testdata/refactoring/changeSignature/ExceptionCaughtInUsage_after.groovy @@ -6,6 +6,7 @@ def bar() { try{ foo("") }catch(IOException e){ +e.printStackTrace() } } diff --git a/plugins/groovy/testdata/refactoring/changeSignature/ExceptionInClosableBlock_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/ExceptionInClosableBlock_after.groovy index 3066c2f95128..a845f80f5b6d 100644 --- a/plugins/groovy/testdata/refactoring/changeSignature/ExceptionInClosableBlock_after.groovy +++ b/plugins/groovy/testdata/refactoring/changeSignature/ExceptionInClosableBlock_after.groovy @@ -4,5 +4,6 @@ new Object().each { try{ foo("") }catch(IOException e){ +e.printStackTrace() } } \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/GenerateDelegateForAbstract.groovy b/plugins/groovy/testdata/refactoring/changeSignature/GenerateDelegateForAbstract.groovy new file mode 100644 index 000000000000..bf106aa67632 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/GenerateDelegateForAbstract.groovy @@ -0,0 +1,9 @@ +abstract class X { + abstract def foo(String s) +} + +class Y extends X { + def foo(String s) { + + } +} diff --git a/plugins/groovy/testdata/refactoring/changeSignature/GenerateDelegateForAbstract_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/GenerateDelegateForAbstract_after.groovy new file mode 100644 index 000000000000..4041b066da34 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/GenerateDelegateForAbstract_after.groovy @@ -0,0 +1,13 @@ +abstract class X { + abstract def foo(String s, int a) + + def foo(String s) { + return foo(s, 5); + } +} + +class Y extends X { + def foo(String s, int a) { + + } +} diff --git a/plugins/groovy/testdata/refactoring/changeSignature/GenerateDelegateForConstructor.groovy b/plugins/groovy/testdata/refactoring/changeSignature/GenerateDelegateForConstructor.groovy new file mode 100644 index 000000000000..44f384176b4c --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/GenerateDelegateForConstructor.groovy @@ -0,0 +1,11 @@ +class Foo { + def Foo(String s) { + + } + + def Foo() { + this("a") + + print new Foo("b"); + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/GenerateDelegateForConstructor_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/GenerateDelegateForConstructor_after.groovy new file mode 100644 index 000000000000..ce77fd68ae76 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/GenerateDelegateForConstructor_after.groovy @@ -0,0 +1,15 @@ +class Foo { + def Foo(String s, int a) { + + } + + def Foo(String s) { + this(s, 5); + } + + def Foo() { + this("a") + + print new Foo("b"); + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/MoveArrayToTheEnd.groovy b/plugins/groovy/testdata/refactoring/changeSignature/MoveArrayToTheEnd.groovy new file mode 100644 index 000000000000..b5277bb46364 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/MoveArrayToTheEnd.groovy @@ -0,0 +1,3 @@ +def foo(String[] ss, int i) {} + +foo(["1", "2"] as String[], 1); \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/MoveArrayToTheEnd_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/MoveArrayToTheEnd_after.groovy new file mode 100644 index 000000000000..835321f2016b --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/MoveArrayToTheEnd_after.groovy @@ -0,0 +1,3 @@ +def foo(int i, String[] ss) {} + +foo(1, "1", "2"); \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/TypeParameters.groovy b/plugins/groovy/testdata/refactoring/changeSignature/TypeParameters.groovy new file mode 100644 index 000000000000..6390801ece42 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/TypeParameters.groovy @@ -0,0 +1,7 @@ +class X { + def foo(T t) {} +} + +class Y extends X { + def foo(String t){} +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/TypeParameters_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/TypeParameters_after.groovy new file mode 100644 index 000000000000..c6789677af49 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/TypeParameters_after.groovy @@ -0,0 +1,7 @@ +class X { + def foo(List list, T t) {} +} + +class Y extends X { + def foo(List list, String t){} +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/AddException_after.groovy b/plugins/groovy/testdata/refactoring/changeSignatureForJava/AddException_after.groovy index ecc0322fcf7b..d23d7f384c7c 100644 --- a/plugins/groovy/testdata/refactoring/changeSignatureForJava/AddException_after.groovy +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/AddException_after.groovy @@ -1,6 +1,6 @@ def test=new Test() try{ - test.foo(); -} catch (Exception e) { - +test.foo() +}catch(Exception e){ +e.printStackTrace() } \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/CovariantReturnType.groovy b/plugins/groovy/testdata/refactoring/changeSignatureForJava/CovariantReturnType.groovy new file mode 100644 index 000000000000..116753525822 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/CovariantReturnType.groovy @@ -0,0 +1,7 @@ +class B1 extends A { + Q method() { } +} + +class C1 extends A { + Z method() { } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/CovariantReturnType_after.groovy b/plugins/groovy/testdata/refactoring/changeSignatureForJava/CovariantReturnType_after.groovy new file mode 100644 index 000000000000..47aad4679fcb --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/CovariantReturnType_after.groovy @@ -0,0 +1,7 @@ +class B1 extends A { + Q method() { } +} + +class C1 extends A { + Runnable method() { } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/EnumConstructor.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/EnumConstructor.java deleted file mode 100644 index 5047f3326b9f..000000000000 --- a/plugins/groovy/testdata/refactoring/changeSignatureForJava/EnumConstructor.java +++ /dev/null @@ -1,7 +0,0 @@ -enum En { - A {}, - B {}, - C; - - En() { } -} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/EnumConstructor_after.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/EnumConstructor_after.java deleted file mode 100644 index 96ec0ca3fdee..000000000000 --- a/plugins/groovy/testdata/refactoring/changeSignatureForJava/EnumConstructor_after.java +++ /dev/null @@ -1,7 +0,0 @@ -enum En { - A(10) {}, - B(10) {}, - C(10); - - En(int i) { } -} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenericTypesInOldParameters.groovy b/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenericTypesInOldParameters.groovy new file mode 100644 index 000000000000..25c195abd9c6 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenericTypesInOldParameters.groovy @@ -0,0 +1,5 @@ +class CString1 extends C { + void put(Object o) { + System.out.println(o+"Text"); + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenericTypesInOldParameters_after.groovy b/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenericTypesInOldParameters_after.groovy new file mode 100644 index 000000000000..81f7b4a44f2e --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/GenericTypesInOldParameters_after.groovy @@ -0,0 +1,5 @@ +class CString1 extends C { + void put(String t) { + System.out.println(t+"Text"); + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/IntroduceParameterWithDefaultValueInHierarchy.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/IntroduceParameterWithDefaultValueInHierarchy.java deleted file mode 100644 index b332ce73eadd..000000000000 --- a/plugins/groovy/testdata/refactoring/changeSignatureForJava/IntroduceParameterWithDefaultValueInHierarchy.java +++ /dev/null @@ -1,9 +0,0 @@ -class Foo { - void foo(){} - - class A extends Foo { - void foo(){ - super.foo(); - } - } -} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/IntroduceParameterWithDefaultValueInHierarchy_after.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/IntroduceParameterWithDefaultValueInHierarchy_after.java deleted file mode 100644 index 08cf46f1074f..000000000000 --- a/plugins/groovy/testdata/refactoring/changeSignatureForJava/IntroduceParameterWithDefaultValueInHierarchy_after.java +++ /dev/null @@ -1,9 +0,0 @@ -class Foo { - void foo(int i){} - - class A extends Foo { - void foo(int i){ - super.foo(i); - } - } -} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderExceptions.groovy b/plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderExceptions.groovy new file mode 100644 index 000000000000..dfcc9155ee89 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderExceptions.groovy @@ -0,0 +1,20 @@ +class Derived1 extends Test { + void foo() throws MyException, + MyException1 { + + } + + void bar () { + try { + foo(); + } + catch (MyException e) {} + catch (MyException1 myException1) {} + } +} + +try { + new Test().foo(); +} +catch (MyException e) {} +catch (MyException1 myException1) {} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderExceptions_after.groovy b/plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderExceptions_after.groovy new file mode 100644 index 000000000000..5e5ecbd0fd98 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderExceptions_after.groovy @@ -0,0 +1,19 @@ +class Derived1 extends Test { + void foo() throws MyException1, MyException { + + } + + void bar () { + try { + Test.foo(); + } + catch (MyException e) {} + catch (MyException1 myException1) {} + } +} + +try { + new Test().foo(); +} +catch (MyException e) {} +catch (MyException1 myException1) {} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderWithVarargs.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderWithVarargs.java deleted file mode 100644 index 41002940ffb2..000000000000 --- a/plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderWithVarargs.java +++ /dev/null @@ -1,7 +0,0 @@ -class Test { - void foo(String[] s, int a) {} - - { - foo(new String[]{"a", "bbb"}, 1); - } -} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderWithVarargs_after.java b/plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderWithVarargs_after.java deleted file mode 100644 index f17d806b135a..000000000000 --- a/plugins/groovy/testdata/refactoring/changeSignatureForJava/ReorderWithVarargs_after.java +++ /dev/null @@ -1,7 +0,0 @@ -class Test { - void foo(int a, String... s) {} - - { - foo(1, "a", "bbb"); - } -} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/TypeParametersInMethod.groovy b/plugins/groovy/testdata/refactoring/changeSignatureForJava/TypeParametersInMethod.groovy new file mode 100644 index 000000000000..e8da3e9ca506 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/TypeParametersInMethod.groovy @@ -0,0 +1,4 @@ +class C2 extends C { + protected V method(){ + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/TypeParametersInMethod_after.groovy b/plugins/groovy/testdata/refactoring/changeSignatureForJava/TypeParametersInMethod_after.groovy new file mode 100644 index 000000000000..60e39c9db15c --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/TypeParametersInMethod_after.groovy @@ -0,0 +1,4 @@ +class C2 extends C { + protected V method(String t, V u, C cu){ + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/Varargs1.groovy b/plugins/groovy/testdata/refactoring/changeSignatureForJava/Varargs1.groovy new file mode 100644 index 000000000000..5daac734b897 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/Varargs1.groovy @@ -0,0 +1,3 @@ +new C().method() +new C().method(1) +new C().method(1, 2) \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignatureForJava/Varargs1_after.groovy b/plugins/groovy/testdata/refactoring/changeSignatureForJava/Varargs1_after.groovy new file mode 100644 index 000000000000..7c3ca4e8aaad --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignatureForJava/Varargs1_after.groovy @@ -0,0 +1,3 @@ +new C().method(true) +new C().method(true, 1) +new C().method(true, 1, 2) \ No newline at end of file From 9b56725bd0a433eb3d1b633ad4d53d8c645b27e4 Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Sun, 30 May 2010 17:28:36 +0400 Subject: [PATCH 026/212] fixes & tests --- .../JavaChangeSignatureUsageProcessor.java | 49 ++++++-- .../changeSignature/MethodCallUsageInfo.java | 17 ++- .../ReplaceVarargWithArray.java | 14 +++ .../ReplaceVarargWithArray_after.java | 14 +++ .../refactoring/ChangeSignatureTest.java | 12 ++ .../statements/params/GrParameterImpl.java | 20 ++-- .../GrChageSignatureUsageSearcher.java | 23 +--- .../GrChangeSignatureDialog.java | 29 +++-- .../GrChangeSignatureUsageProcessor.java | 25 ++-- .../GrMethodCallUsageInfo.java | 42 ++++--- .../changeSignature/GrParameterInfo.java | 100 +++++++--------- .../GrParameterTableModel.java | 16 +-- .../changeSignature/GrTableParameterInfo.java | 110 ++++++++++++++++++ .../changeSignature/ChangeSignatureTest.java | 13 ++- .../ChangeSignatureTestCase.java | 56 ++++----- .../MoveVarArgParameters.groovy | 2 +- .../MoveVarArgParameters_after.groovy | 2 +- .../MoveVarArgParameters_after.java | 2 +- .../ReplaceVarargWithArray.groovy | 14 +++ .../ReplaceVarargWithArray_after.groovy | 14 +++ 20 files changed, 401 insertions(+), 173 deletions(-) create mode 100644 java/java-tests/testData/refactoring/changeSignature/ReplaceVarargWithArray.java create mode 100644 java/java-tests/testData/refactoring/changeSignature/ReplaceVarargWithArray_after.java create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrTableParameterInfo.java create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/ReplaceVarargWithArray.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/ReplaceVarargWithArray_after.groovy diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java index 56985374bbc5..08ea1f00f740 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java @@ -19,6 +19,7 @@ import com.intellij.codeInsight.ExceptionUtil; import com.intellij.lang.StdLanguages; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Ref; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.codeStyle.JavaCodeStyleManager; @@ -123,7 +124,7 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr else if (usage instanceof MethodCallUsageInfo) { final MethodCallUsageInfo methodCallInfo = (MethodCallUsageInfo)usage; processMethodUsage(methodCallInfo.getElement(), (JavaChangeInfo)changeInfo, methodCallInfo.isToChangeArguments(), - methodCallInfo.isToCatchExceptions(), methodCallInfo.getReferencedMethod(), usages); + methodCallInfo.isToCatchExceptions(), methodCallInfo.getReferencedMethod(), methodCallInfo.getSubstitutor(), usages); return true; } else if (usage instanceof ChangeSignatureParameterUsageInfo) { @@ -137,7 +138,7 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr return true; } else if (element instanceof PsiEnumConstant) { - fixActualArgumentsList(((PsiEnumConstant)element).getArgumentList(), (JavaChangeInfo)changeInfo, true); + fixActualArgumentsList(((PsiEnumConstant)element).getArgumentList(), (JavaChangeInfo)changeInfo, true, PsiSubstitutor.EMPTY); return true; } else if (!(usage instanceof OverriderUsageInfo)) { @@ -179,7 +180,9 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr final PsiElement parent = aClass.getParent(); if (parent instanceof PsiNewExpression) { final PsiExpressionList argumentList = ((PsiNewExpression)parent).getArgumentList(); - fixActualArgumentsList(argumentList, changeInfo, true); + final PsiClass baseClass = changeInfo.getMethod().getContainingClass(); + final PsiSubstitutor substitutor = TypeConversionUtil.getSuperClassSubstitutor(baseClass, aClass, PsiSubstitutor.EMPTY); + fixActualArgumentsList(argumentList, changeInfo, true, substitutor); } } } @@ -198,14 +201,17 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr superCall = (PsiExpressionStatement)body.add(superCall); } PsiMethodCallExpression callExpression = (PsiMethodCallExpression)superCall.getExpression(); - processMethodUsage(callExpression.getMethodExpression(), changeInfo, true, false, callee, usages); + final PsiClass aClass = constructor.getContainingClass(); + final PsiClass baseClass = changeInfo.getMethod().getContainingClass(); + final PsiSubstitutor substitutor = TypeConversionUtil.getSuperClassSubstitutor(baseClass, aClass, PsiSubstitutor.EMPTY); + processMethodUsage(callExpression.getMethodExpression(), changeInfo, true, false, callee, substitutor, usages); } private static void processMethodUsage(PsiElement ref, JavaChangeInfo changeInfo, boolean toChangeArguments, boolean toCatchExceptions, - PsiMethod callee, final UsageInfo[] usages) throws IncorrectOperationException { + PsiMethod callee, PsiSubstitutor subsitutor, final UsageInfo[] usages) throws IncorrectOperationException { if (changeInfo.isNameChanged()) { if (ref instanceof PsiJavaCodeReferenceElement) { PsiElement last = ((PsiJavaCodeReferenceElement)ref).getReferenceNameElement(); @@ -226,7 +232,7 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr } } - fixActualArgumentsList(list, changeInfo, toInsertDefaultValue); + fixActualArgumentsList(list, changeInfo, toInsertDefaultValue, subsitutor); } if (toCatchExceptions) { @@ -352,7 +358,7 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr //This methods works equally well for primary usages as well as for propagated callers' usages private static void fixActualArgumentsList(PsiExpressionList list, JavaChangeInfo changeInfo, - boolean toInsertDefaultValue) throws IncorrectOperationException { + boolean toInsertDefaultValue, PsiSubstitutor substitutor) throws IncorrectOperationException { final PsiElementFactory factory = JavaPsiFacade.getInstance(list.getProject()).getElementFactory(); if (changeInfo.isParameterSetOrOrderChanged()) { if (changeInfo instanceof JavaChangeInfoImpl && ((JavaChangeInfoImpl)changeInfo).isPropagationEnabled) { @@ -402,8 +408,31 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr newNonVarargCount = newParms.length; newArgsLength = newParms.length; } + + String[] oldVarargs = null; + if (changeInfo.wasVararg() && !changeInfo.isRetainsVarargs()) { + oldVarargs = new String[varargCount]; + for (int i = nonVarargCount; i < args.length; i++) { + oldVarargs[i - nonVarargCount] = args[i].getText(); + } + } + final PsiExpression[] newArgs = new PsiExpression[newArgsLength]; for (int i = 0; i < newNonVarargCount; i++) { + if (newParms[i].getOldIndex() == nonVarargCount && oldVarargs != null) { + PsiType type = newParms[i].createType(changeInfo.getMethod(), list.getManager()); + if (type instanceof PsiArrayType) { + type = substitutor.substitute(type); + type = TypeConversionUtil.erasure(type); + String typeText = type.getCanonicalText(); + if (type instanceof PsiEllipsisType) { + typeText = typeText.replace("...", "[]"); + } + String text = "new " + typeText + "{" + StringUtil.join(oldVarargs, ",") + "}"; + newArgs[i] = factory.createExpressionFromText(text, changeInfo.getMethod()); + continue; + } + } newArgs[i] = createActualArgument(changeInfo, list, newParms[i], toInsertDefaultValue, args); } if (changeInfo.isArrayToVarargs()) { @@ -839,7 +868,11 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr for (JavaParameterInfo info : parameters) { - final PsiType parameterType = info.createType(method, manager); + PsiType parameterType = info.createType(method, manager); + if (parameterType == null) { + parameterType = + JavaPsiFacade.getElementFactory(method.getProject()).createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, method); + } PsiParameter param = factory.createParameter(info.getName(), parameterType); prototype.getParameterList().add(param); } diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/MethodCallUsageInfo.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/MethodCallUsageInfo.java index 616ec7f5c32e..62068a0977ba 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/MethodCallUsageInfo.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/MethodCallUsageInfo.java @@ -27,6 +27,7 @@ public class MethodCallUsageInfo extends UsageInfo { private final boolean myToChangeArguments; private final boolean myToCatchExceptions; private final PsiMethod myReferencedMethod; + private final PsiSubstitutor mySubstitutor; public boolean isToCatchExceptions() { return myToCatchExceptions; @@ -40,17 +41,19 @@ public class MethodCallUsageInfo extends UsageInfo { super(ref); myToChangeArguments = isToChangeArguments; myToCatchExceptions = isToCatchExceptions; - myReferencedMethod = resolveMethod(ref); + final JavaResolveResult resolveResult = resolveMethod(ref); + myReferencedMethod = (PsiMethod)resolveResult.getElement(); + mySubstitutor = resolveResult.getSubstitutor(); } - private static PsiMethod resolveMethod(final PsiElement ref) { - if (ref instanceof PsiEnumConstant) return ((PsiEnumConstant)ref).resolveConstructor(); + private static JavaResolveResult resolveMethod(final PsiElement ref) { + if (ref instanceof PsiEnumConstant) return ((PsiEnumConstant)ref).resolveMethodGenerics(); PsiElement parent = ref.getParent(); if (parent instanceof PsiCall) { - return ((PsiCall)parent).resolveMethod(); + return ((PsiCall)parent).resolveMethodGenerics(); } else if (parent instanceof PsiAnonymousClass) { - return ((PsiNewExpression)parent.getParent()).resolveConstructor(); + return ((PsiNewExpression)parent.getParent()).resolveMethodGenerics(); } LOG.error("Unknown reference"); @@ -60,4 +63,8 @@ public class MethodCallUsageInfo extends UsageInfo { public PsiMethod getReferencedMethod() { return myReferencedMethod; } + + public PsiSubstitutor getSubstitutor() { + return mySubstitutor; + } } diff --git a/java/java-tests/testData/refactoring/changeSignature/ReplaceVarargWithArray.java b/java/java-tests/testData/refactoring/changeSignature/ReplaceVarargWithArray.java new file mode 100644 index 000000000000..20f9b40c633f --- /dev/null +++ b/java/java-tests/testData/refactoring/changeSignature/ReplaceVarargWithArray.java @@ -0,0 +1,14 @@ +class List {} + +class Base { + void foo(String s, List... l) {} +} + +class Inheritor extends Base { + void foo(String s, List... l) {} + + { + new Inheritor().foo("a", new List()); + } +} + diff --git a/java/java-tests/testData/refactoring/changeSignature/ReplaceVarargWithArray_after.java b/java/java-tests/testData/refactoring/changeSignature/ReplaceVarargWithArray_after.java new file mode 100644 index 000000000000..e2a0388bf7ec --- /dev/null +++ b/java/java-tests/testData/refactoring/changeSignature/ReplaceVarargWithArray_after.java @@ -0,0 +1,14 @@ +class List {} + +class Base { + void foo(List[] l, String s) {} +} + +class Inheritor extends Base { + void foo(List[] l, String s) {} + + { + new Inheritor().foo(new List[]{new List()}, "a"); + } +} + diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTest.java index 00238154d697..f6525766f150 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTest.java @@ -210,6 +210,18 @@ public class ChangeSignatureTest extends LightCodeInsightTestCase { doTest(null, new ParameterInfoImpl[] {new ParameterInfoImpl(1), new ParameterInfoImpl(0)}, false); } + public void testReplaceVarargWithArray() throws Exception { + doTest(null, null, null, new GenParams() { + public ParameterInfoImpl[] genParams(PsiMethod method) throws IncorrectOperationException { + final PsiElementFactory factory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory(); + return new ParameterInfoImpl[] { + new ParameterInfoImpl(1, "l", factory.createTypeFromText("List[]", method.getParameterList()), "null", false), + new ParameterInfoImpl(0, "s", factory.createTypeFromText("String", method.getParameterList())) + }; + } + }, false); + } + private void doTest(String newReturnType, ParameterInfoImpl[] parameterInfos, final boolean generateDelegate) throws Exception { doTest(null, null, newReturnType, parameterInfos, new ThrownExceptionInfo[0], generateDelegate); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/params/GrParameterImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/params/GrParameterImpl.java index cb47e248809a..7a347fe253ec 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/params/GrParameterImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/params/GrParameterImpl.java @@ -96,22 +96,24 @@ public class GrParameterImpl extends GrVariableImpl implements GrParameter { } - @NotNull - public PsiType getType() { - /*PsiType type = getTypeGroovy(); - if (type == null) type = super.getType();*/ - PsiType type = super.getType(); + @Override + public PsiType getDeclaredType() { + final PsiType type = super.getDeclaredType(); if (isVarArgs()) { return new PsiEllipsisType(type); } - else if (isMainMethodFirstUntypedParameter()) { + return type; + } + + @NotNull + public PsiType getType() { + PsiType type = super.getType(); + if (isMainMethodFirstUntypedParameter()) { PsiClassType stringType = JavaPsiFacade.getInstance(getProject()).getElementFactory().createTypeByFQClassName("java.lang.String", getResolveScope()); return stringType.createArrayType(); } - else { - return type; - } + return type; } private boolean isMainMethodFirstUntypedParameter() { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChageSignatureUsageSearcher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChageSignatureUsageSearcher.java index 448b63129244..01a4d03ea1f6 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChageSignatureUsageSearcher.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChageSignatureUsageSearcher.java @@ -39,8 +39,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousClassDefinition; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; -import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature; -import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import java.util.ArrayList; @@ -207,24 +205,16 @@ class GrChageSignatureUsageSearcher { if (!GroovyFileType.GROOVY_LANGUAGE.equals(element.getLanguage())) continue; boolean isToCatchExceptions = isToThrowExceptions && needToCatchExceptions(RefactoringUtil.getEnclosingMethod(element)); - //todo check for applicability of arguments to method if (PsiUtil.isMethodUsage(element)) { - GrClosureSignature signature = GrClosureSignatureUtil.createSignature(method, PsiSubstitutor.EMPTY); final GrArgumentList argList = PsiUtil.getArgumentsList(element); //enum constant may not have argList if (argList == null) { if (element instanceof GrEnumConstant) { - result.add( - new GrMethodCallUsageInfo(element, GrClosureSignatureUtil.createSignature(method, PsiSubstitutor.EMPTY), isToModifyArgs, - isToCatchExceptions, new GrClosureSignatureUtil.ArgInfo[0])); + result.add(new GrMethodCallUsageInfo(element, isToModifyArgs, isToCatchExceptions)); } } else { - GrClosureSignatureUtil.ArgInfo[] map = - GrClosureSignatureUtil.mapParametersToArguments(signature, argList, method.getManager(), method.getResolveScope()); - result.add( - new GrMethodCallUsageInfo(element, GrClosureSignatureUtil.createSignature(method, PsiSubstitutor.EMPTY), isToModifyArgs, - isToCatchExceptions, map)); + result.add(new GrMethodCallUsageInfo(element, isToModifyArgs,isToCatchExceptions)); } } else if (element instanceof GrDocTagValueToken) { @@ -239,11 +229,7 @@ class GrChageSignatureUsageSearcher { LOG.assertTrue(method.isConstructor()); final PsiClass psiClass = (PsiClass)element; if (psiClass instanceof GrAnonymousClassDefinition) { - GrClosureSignature signature = GrClosureSignatureUtil.createSignature(method, PsiSubstitutor.EMPTY); - GrClosureSignatureUtil.ArgInfo[] map = GrClosureSignatureUtil - .mapParametersToArguments(signature, PsiUtil.getArgumentsList(element), method.getManager(), method.getResolveScope()); - result.add( - new GrMethodCallUsageInfo(element, GrClosureSignatureUtil.createSignature(method, PsiSubstitutor.EMPTY), isToModifyArgs, isToCatchExceptions, map)); + result.add(new GrMethodCallUsageInfo(element, isToModifyArgs, isToCatchExceptions)); continue; } /*if (!(myChangeInfo instanceof JavaChangeInfoImpl)) continue; todo propagate methods @@ -296,6 +282,9 @@ class GrChageSignatureUsageSearcher { UsageInfo usageInfo = new ChangeSignatureParameterUsageInfo(parmRef, parameter.getName(), info.getName()); results.add(usageInfo); } + if (info.getName() != parameter.getName()) { + + } } private boolean needToCatchExceptions(PsiMethod caller) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java index 36a09576add5..a395ba7e7e53 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java @@ -217,10 +217,10 @@ public class GrChangeSignatureDialog extends RefactoringDialog { builder.append(type).append(' '); builder.append(name).append('('); - final List infos = myParameterModel.getParameterInfos(); + final List infos = myParameterModel.getParameterInfos(); if (infos.size() > 0) { - final List paramsText = ContainerUtil.map(infos, new Function() { - public String fun(GrParameterInfo grParameterInfo) { + final List paramsText = ContainerUtil.map(infos, new Function() { + public String fun(GrTableParameterInfo grParameterInfo) { return generateParameterText(grParameterInfo); } }); @@ -245,7 +245,7 @@ public class GrChangeSignatureDialog extends RefactoringDialog { } - private static String generateParameterText(GrParameterInfo info) { + private static String generateParameterText(GrTableParameterInfo info) { StringBuilder builder = new StringBuilder(); final PsiTypeCodeFragment typeFragment = info.getTypeFragment(); String typeText = typeFragment != null ? typeFragment.getText().trim() : GrModifier.DEF; @@ -290,14 +290,19 @@ public class GrChangeSignatureDialog extends RefactoringDialog { } String newName = getNewName(); - final List parameterInfos = myParameterModel.getParameterInfos(); - + final List tableParameterInfos = myParameterModel.getParameterInfos(); + final List parameterInfos = ContainerUtil.map(tableParameterInfos, new Function() { + public GrParameterInfo fun(GrTableParameterInfo info) { + return info.generateParameterInfo(); + } + }); final ThrownExceptionInfo[] exceptionInfos = myExceptionTableModel.getThrownExceptions(); - invokeRefactoring(new GrChangeSignatureProcessor( - myProject, - new GrChangeInfoImpl(myMethod, modifier, returnType == null ? null : CanonicalTypes.createTypeWrapper(returnType), newName, - parameterInfos, exceptionInfos, myDelegateRadioButton.isSelected()))); - + invokeRefactoring(new GrChangeSignatureProcessor(myProject, new GrChangeInfoImpl(myMethod, modifier, returnType == null + ? null + : CanonicalTypes + .createTypeWrapper(returnType), + newName, parameterInfos, exceptionInfos, + myDelegateRadioButton.isSelected()))); } private String getNewName() { @@ -319,7 +324,7 @@ public class GrChangeSignatureDialog extends RefactoringDialog { return false; } - for (GrParameterInfo info : myParameterModel.getParameterInfos()) { + for (GrTableParameterInfo info : myParameterModel.getParameterInfos()) { if (!StringUtil.isJavaIdentifier(info.getName())) { showErrorHint(message("name.is.wrong", info.getName())); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java index 979a99994e26..dc01b03df1b5 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java @@ -52,7 +52,8 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArg import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrSafeCastExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterList; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; @@ -291,7 +292,7 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc if (usageInfo instanceof GrMethodCallUsageInfo) { processMethodUsage(element, ((JavaChangeInfo)changeInfo), ((GrMethodCallUsageInfo)usageInfo).isToChangeArguments(), ((GrMethodCallUsageInfo)usageInfo).isToCatchExceptions(), - ((GrMethodCallUsageInfo)usageInfo).getMapToArguments()); + ((GrMethodCallUsageInfo)usageInfo).getMapToArguments(), ((GrMethodCallUsageInfo)usageInfo).getSubstitutor()); return true; } else if (usageInfo instanceof DefaultConstructorImplicitUsageInfo) { @@ -334,18 +335,21 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc } constructor = (GrConstructor)psiClass.add(constructor); - processConstructor(constructor, changeInfo); } private static void processConstructor(GrMethod constructor, JavaChangeInfo changeInfo) { + final PsiClass containingClass = constructor.getContainingClass(); + final PsiClass baseClass = changeInfo.getMethod().getContainingClass(); + final PsiSubstitutor substitutor = TypeConversionUtil.getSuperClassSubstitutor(baseClass, containingClass, PsiSubstitutor.EMPTY); + GrOpenBlock block = constructor.getBlock(); GrConstructorInvocation invocation = GroovyPsiElementFactory.getInstance(constructor.getProject()).createConstructorInvocation("super()"); invocation = (GrConstructorInvocation)block.addStatementBefore(invocation, getFirstStatement(block)); processMethodUsage(invocation.getThisOrSuperKeyword(), changeInfo, changeInfo.isParameterSetOrOrderChanged() || changeInfo.isParameterNamesChanged(), - changeInfo.isExceptionSetChanged(), GrClosureSignatureUtil.ArgInfo.EMPTY_ARRAY); + changeInfo.isExceptionSetChanged(), GrClosureSignatureUtil.ArgInfo.EMPTY_ARRAY, substitutor); } @Nullable @@ -359,7 +363,7 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc JavaChangeInfo changeInfo, boolean toChangeArguments, boolean toCatchExceptions, - GrClosureSignatureUtil.ArgInfo[] map) { + GrClosureSignatureUtil.ArgInfo[] map, PsiSubstitutor substitutor) { if (map == null) return; if (changeInfo.isNameChanged()) { if (element instanceof GrReferenceElement) { @@ -414,10 +418,17 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc argument.delete(); } argText.replace(argText.length() - 2, argText.length(), "]"); - if (!(arguments.size() > 0 && arguments.iterator().next() instanceof GrNamedArgument)) { - argText.append(" as ").append(parameter.getTypeText()); + PsiType type = parameter.createType(changeInfo.getMethod().getParameterList(), argumentList.getManager()); + if (type instanceof PsiArrayType) { + type = substitutor.substitute(type); + String typeText = type.getCanonicalText(); + if (type instanceof PsiEllipsisType) { + typeText = typeText.replace("...", "[]"); + } + argText.append(" as ").append(typeText); } anchor = argumentList.addAfter(factory.createExpressionFromText(argText.toString()), anchor); + PsiUtil.shortenReferences((GroovyPsiElement)anchor); } } else { //arguments for simple parameters diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodCallUsageInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodCallUsageInfo.java index b077913edf33..a92476e6e3c1 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodCallUsageInfo.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodCallUsageInfo.java @@ -17,10 +17,12 @@ package org.jetbrains.plugins.groovy.refactoring.changeSignature; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiMethod; -import com.intellij.psi.PsiNewExpression; +import com.intellij.psi.PsiSubstitutor; import com.intellij.usageView.UsageInfo; import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrConstructorInvocation; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrApplicationStatement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; @@ -28,6 +30,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrC import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature; import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil; +import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; /** * @author Maxim.Medvedev @@ -37,6 +40,7 @@ public class GrMethodCallUsageInfo extends UsageInfo { private final boolean myToCatchExceptions; private final PsiMethod myReferencedMethod; private GrClosureSignatureUtil.ArgInfo[] myMapToArguments; + private PsiSubstitutor mySubstitutor; public boolean isToCatchExceptions() { return myToCatchExceptions; @@ -46,35 +50,39 @@ public class GrMethodCallUsageInfo extends UsageInfo { return myToChangeArguments; } - public GrMethodCallUsageInfo(PsiElement element, - GrClosureSignature oldSignature, - boolean isToChangeArguments, - boolean isToCatchExceptions, GrClosureSignatureUtil.ArgInfo[] mapToArguments) { + public GrMethodCallUsageInfo(PsiElement element, boolean isToChangeArguments, boolean isToCatchExceptions) { super(element); myToChangeArguments = isToChangeArguments; myToCatchExceptions = isToCatchExceptions; - myMapToArguments = mapToArguments; - myReferencedMethod = resolveMethod(element); + final GroovyResolveResult resolveResult = resolveMethod(element); + myReferencedMethod = (PsiMethod)resolveResult.getElement(); + mySubstitutor = resolveResult.getSubstitutor(); + final GrArgumentList list = PsiUtil.getArgumentsList(element); + if (list == null) { + myMapToArguments = GrClosureSignatureUtil.ArgInfo.EMPTY_ARRAY; + } + else { + final GrClosureSignature signature = GrClosureSignatureUtil.createSignature(myReferencedMethod, mySubstitutor); + myMapToArguments = + GrClosureSignatureUtil.mapParametersToArguments(signature, list, element.getManager(), myReferencedMethod.getResolveScope()); + } } @Nullable - private static PsiMethod resolveMethod(final PsiElement ref) { - if (ref instanceof GrEnumConstant) return ((GrEnumConstant)ref).resolveConstructor(); + private static GroovyResolveResult resolveMethod(final PsiElement ref) { + if (ref instanceof GrEnumConstant) return ((GrEnumConstant)ref).resolveConstructorGenerics(); PsiElement parent = ref.getParent(); if (parent instanceof GrCallExpression) { - return ((GrCallExpression)parent).resolveMethod(); + return ((GrCallExpression)parent).getMethodVariants()[0]; } else if (parent instanceof GrApplicationStatement) { final GrExpression expression = ((GrApplicationStatement)parent).getFunExpression(); if (expression instanceof GrReferenceExpression) { - final PsiElement element = ((GrReferenceExpression)expression).resolve(); - if (element instanceof PsiMethod) { - return (PsiMethod)element; - } + return ((GrReferenceExpression)expression).advancedResolve(); } } else if (parent instanceof GrConstructorInvocation) { - return ((PsiNewExpression)parent.getParent()).resolveConstructor(); + return ((GrConstructorInvocation)parent).resolveConstructorGenerics(); } return null; @@ -87,4 +95,8 @@ public class GrMethodCallUsageInfo extends UsageInfo { public GrClosureSignatureUtil.ArgInfo[] getMapToArguments() { return myMapToArguments; } + + public PsiSubstitutor getSubstitutor() { + return mySubstitutor; + } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java index 5d47ba7c138a..77f9f4544090 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterInfo.java @@ -17,12 +17,11 @@ package org.jetbrains.plugins.groovy.refactoring.changeSignature; import com.intellij.openapi.project.Project; import com.intellij.psi.*; -import com.intellij.psi.search.GlobalSearchScope; import com.intellij.refactoring.changeSignature.JavaParameterInfo; import com.intellij.refactoring.util.CanonicalTypes; import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.groovy.debugger.fragments.GroovyCodeFragment; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; @@ -30,60 +29,52 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; * @author Maxim.Medvedev */ public class GrParameterInfo implements JavaParameterInfo { - private GroovyCodeFragment myName; - private GroovyCodeFragment myDefaultValue; - private PsiTypeCodeFragment myType; - private GroovyCodeFragment myDefaultInitializer; + private String myName; + private final String myDefaultValue; + private final String myDefaultInitializer; private final int myPosition; private CanonicalTypes.Type myTypeWrapper; public GrParameterInfo(GrParameter parameter, int position) { myPosition = position; final Project project = parameter.getProject(); - myName = new GroovyCodeFragment(project, parameter.getName()); + myName = parameter.getName(); final PsiType type = parameter.getDeclaredType(); if (type != null) { - myType = JavaPsiFacade.getElementFactory(project).createTypeCodeFragment(type.getCanonicalText(), parameter, true, true); + myTypeWrapper = CanonicalTypes.createTypeWrapper(type); } else { - myType = JavaPsiFacade.getElementFactory(project).createTypeCodeFragment("", parameter, true, true); + myTypeWrapper = null; } final GrExpression defaultInitializer = parameter.getDefaultInitializer(); if (defaultInitializer != null) { - myDefaultInitializer = new GroovyCodeFragment(project, defaultInitializer.getText()); + myDefaultInitializer = defaultInitializer.getText(); } else { - myDefaultInitializer = new GroovyCodeFragment(project, ""); + myDefaultInitializer = ""; } - myDefaultValue = new GroovyCodeFragment(project, ""); + myDefaultValue = ""; } - public GrParameterInfo(Project project, PsiElement context) { - this.myPosition = -1; - myName = new GroovyCodeFragment(project, ""); - myDefaultValue = new GroovyCodeFragment(project, ""); - myType = JavaPsiFacade.getElementFactory(project).createTypeCodeFragment("", context, true, true); - myDefaultInitializer = new GroovyCodeFragment(project, ""); - } - - public GroovyCodeFragment getNameFragment() { - return myName; - } - - public GroovyCodeFragment getDefaultValueFragment() { - return myDefaultValue; - } - - public PsiTypeCodeFragment getTypeFragment() { - return myType; - } - - public GroovyCodeFragment getDefaultInitializerFragment() { - return myDefaultInitializer; + public GrParameterInfo(@NotNull String name, + @Nullable String defaultValue, + @Nullable String defaultInitializer, + @Nullable PsiType type, + int position) { + myName = name; + myDefaultValue = defaultValue; + myDefaultInitializer = defaultInitializer; + myPosition = position; + if (type != null) { + myTypeWrapper = CanonicalTypes.createTypeWrapper(type); + } + else { + myTypeWrapper = null; + } } public String getName() { - return myName.getText().trim(); + return myName; } public int getOldIndex() { @@ -91,46 +82,30 @@ public class GrParameterInfo implements JavaParameterInfo { } public String getDefaultValue() { - return myDefaultValue.getText().trim(); + return myDefaultValue; } @Nullable public PsiType createType(PsiElement context, final PsiManager manager) throws IncorrectOperationException { - try { - return myType.getType(); - } - catch (PsiTypeCodeFragment.TypeSyntaxException e) { - return null; - } - catch (PsiTypeCodeFragment.NoTypeException e) { - return JavaPsiFacade.getElementFactory(manager.getProject()) - .createTypeByFQClassName(CommonClassNames.JAVA_LANG_OBJECT, GlobalSearchScope.allScope(manager.getProject())); - } + if (myTypeWrapper == null) return null; + return myTypeWrapper.getType(context, manager); } - public String getTypeText() { - CanonicalTypes.Type type = getTypeWrapper(); - if (type != null) { - return type.getTypeText(); + if (myTypeWrapper != null) { + return myTypeWrapper.getTypeText(); } return ""; } @Nullable public CanonicalTypes.Type getTypeWrapper() { - if (myTypeWrapper == null) { - PsiType type = createType(myType.getContext(), myType.getManager()); - if (type != null) { - myTypeWrapper = CanonicalTypes.createTypeWrapper(type); - } - } return myTypeWrapper; } public PsiExpression getValue(PsiCallExpression callExpression) { return JavaPsiFacade.getInstance(callExpression.getProject()).getElementFactory() - .createExpressionFromText(myDefaultValue.getText(), callExpression); + .createExpressionFromText(myDefaultValue, callExpression); } public boolean isVarargType() { @@ -146,10 +121,17 @@ public class GrParameterInfo implements JavaParameterInfo { } public String getDefaultInitializer() { - return myDefaultInitializer.getText().trim(); + return myDefaultInitializer; } public boolean hasNoType() { - return myType.getText().trim().length() == 0; + return getTypeText().length() == 0; + } + + /** + * for testing only + */ + public void setName(String newName) { + myName = newName; } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterTableModel.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterTableModel.java index ee6287c3afc2..81a4c9d08865 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterTableModel.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterTableModel.java @@ -32,7 +32,7 @@ import java.util.List; * @author Maxim.Medvedev */ public class GrParameterTableModel extends AbstractTableModel implements RowEditableTableModel { - private final List infos; + private final List infos; private final GrMethod myMethod; private final GrChangeSignatureDialog myDialog; private final Project myProject; @@ -41,17 +41,17 @@ public class GrParameterTableModel extends AbstractTableModel implements RowEdit myMethod = method; myDialog = dialog; final GrParameter[] parameters = myMethod.getParameters(); - infos = new ArrayList(parameters.length); + infos = new ArrayList(parameters.length); for (int i = 0; i < parameters.length; i++) { GrParameter parameter = parameters[i]; - infos.add(new GrParameterInfo(parameter, i)); + infos.add(new GrTableParameterInfo(parameter, i)); } myProject = project; } public void addRow() { final int row = infos.size(); - infos.add(new GrParameterInfo(myProject, myMethod)); + infos.add(new GrTableParameterInfo(myProject, myMethod)); fireTableRowsInserted(row, row); } @@ -61,7 +61,7 @@ public class GrParameterTableModel extends AbstractTableModel implements RowEdit } public void exchangeRows(int index1, int index2) { - final GrParameterInfo info = infos.get(index1); + final GrTableParameterInfo info = infos.get(index1); infos.set(index1, infos.get(index2)); infos.set(index2, info); fireTableRowsUpdated(Math.min(index1, index2), Math.max(index1, index2)); @@ -79,7 +79,7 @@ public class GrParameterTableModel extends AbstractTableModel implements RowEdit @Nullable public Object getValueAt(int rowIndex, int columnIndex) { if (rowIndex < 0 || rowIndex >= infos.size()) return null; - final GrParameterInfo info = infos.get(rowIndex); + final GrTableParameterInfo info = infos.get(rowIndex); switch (columnIndex) { case 0: return info.getTypeFragment(); @@ -135,11 +135,11 @@ public class GrParameterTableModel extends AbstractTableModel implements RowEdit @Override public boolean isCellEditable(int rowIndex, int columnIndex) { if (columnIndex < 3) return true; - GrParameterInfo info = infos.get(rowIndex); + GrTableParameterInfo info = infos.get(rowIndex); return info.getOldIndex() < 0; } - public List getParameterInfos() { + public List getParameterInfos() { return infos; } } \ No newline at end of file diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrTableParameterInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrTableParameterInfo.java new file mode 100644 index 000000000000..ff5d2fe96b43 --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrTableParameterInfo.java @@ -0,0 +1,110 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.groovy.refactoring.changeSignature; + +import com.intellij.openapi.project.Project; +import com.intellij.psi.JavaPsiFacade; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiType; +import com.intellij.psi.PsiTypeCodeFragment; +import org.jetbrains.plugins.groovy.debugger.fragments.GroovyCodeFragment; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; + +/** + * @author Maxim.Medvedev + */ +public class GrTableParameterInfo { + private GroovyCodeFragment myName; + private GroovyCodeFragment myDefaultValue; + private PsiTypeCodeFragment myType; + private GroovyCodeFragment myDefaultInitializer; + private final int myPosition; + + public GrTableParameterInfo(GrParameter parameter, int position) { + myPosition = position; + final Project project = parameter.getProject(); + myName = new GroovyCodeFragment(project, parameter.getName()); + final PsiType type = parameter.getDeclaredType(); + if (type != null) { + String typeText = type.getCanonicalText(); + if (typeText == null) typeText = type.getPresentableText(); + myType = JavaPsiFacade.getElementFactory(project).createTypeCodeFragment(typeText, parameter, true, true, true); + } + else { + myType = JavaPsiFacade.getElementFactory(project).createTypeCodeFragment("", parameter, true, true, true); + } + final GrExpression defaultInitializer = parameter.getDefaultInitializer(); + if (defaultInitializer != null) { + myDefaultInitializer = new GroovyCodeFragment(project, defaultInitializer.getText()); + } + else { + myDefaultInitializer = new GroovyCodeFragment(project, ""); + } + myDefaultValue = new GroovyCodeFragment(project, ""); + } + + public GrTableParameterInfo(Project project, PsiElement context) { + this.myPosition = -1; + myName = new GroovyCodeFragment(project, ""); + myDefaultValue = new GroovyCodeFragment(project, ""); + myType = JavaPsiFacade.getElementFactory(project).createTypeCodeFragment("", context, true, true); + myDefaultInitializer = new GroovyCodeFragment(project, ""); + } + + public GroovyCodeFragment getNameFragment() { + return myName; + } + + public GroovyCodeFragment getDefaultValueFragment() { + return myDefaultValue; + } + + public PsiTypeCodeFragment getTypeFragment() { + return myType; + } + + public GroovyCodeFragment getDefaultInitializerFragment() { + return myDefaultInitializer; + } + + public String getName() { + return myName.getText().trim(); + } + + public int getOldIndex() { + return myPosition; + } + + public String getDefaultValue() { + return myDefaultValue.getText().trim(); + } + + public GrParameterInfo generateParameterInfo() { + String defaultInitializer = myDefaultInitializer.getText().trim(); + PsiType type; + try { + type = myType.getType(); + } + catch (PsiTypeCodeFragment.TypeSyntaxException e) { + type = null; + } + catch (PsiTypeCodeFragment.NoTypeException e) { + type = null; + } + return new GrParameterInfo(getName(), getDefaultValue(), defaultInitializer, type, myPosition); + } +} diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java index c384a1ea8066..746ef3c2b8e4 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java @@ -15,7 +15,10 @@ */ package org.jetbrains.plugins.groovy.refactoring.changeSignature; -import com.intellij.psi.*; +import com.intellij.psi.CommonClassNames; +import com.intellij.psi.JavaPsiFacade; +import com.intellij.psi.PsiClassType; +import com.intellij.psi.PsiType; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.refactoring.changeSignature.JavaThrownExceptionInfo; import com.intellij.refactoring.changeSignature.ThrownExceptionInfo; @@ -35,7 +38,7 @@ public class ChangeSignatureTest extends ChangeSignatureTestCase { public void testOneNewParameter() throws Exception { doTest(new SimpleInfo[]{ - new SimpleInfo("p", -1, "\"5\"", null, createType(CommonClassNames.JAVA_LANG_STRING))}); + new SimpleInfo("p", -1, "\"5\"", null, CommonClassNames.JAVA_LANG_STRING)}); } public void testRemoveParameter() throws Exception { @@ -194,7 +197,7 @@ public class ChangeSignatureTest extends ChangeSignatureTestCase { } public void testTypeParameters() throws Exception { - doTest(new SimpleInfo[]{new SimpleInfo("list", -1, "null", null, createType("java.util.List")), new SimpleInfo(0)}); + doTest(new SimpleInfo[]{new SimpleInfo("list", -1, "null", null, "java.util.List"), new SimpleInfo(0)}); } public void testEnumConstructor() throws Exception { @@ -205,6 +208,10 @@ public class ChangeSignatureTest extends ChangeSignatureTestCase { doTest(new SimpleInfo[] {new SimpleInfo(1), new SimpleInfo(0)}); } + public void testReplaceVarargWithArray() throws Exception { + doTest(new SimpleInfo[]{new SimpleInfo("l", 1, null, null, "List[]"), new SimpleInfo(0)}); + } + private PsiType createType(String typeText) { return JavaPsiFacade.getElementFactory(getProject()).createTypeByFQClassName(typeText, GlobalSearchScope.allScope(getProject())); } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTestCase.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTestCase.java index fc9a22d75d60..bb342d1d5c93 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTestCase.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTestCase.java @@ -16,15 +16,13 @@ package org.jetbrains.plugins.groovy.refactoring.changeSignature; import com.intellij.codeInsight.TargetElementUtilBase; -import com.intellij.openapi.application.Result; -import com.intellij.openapi.application.WriteAction; -import com.intellij.openapi.editor.Document; import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.refactoring.changeSignature.ThrownExceptionInfo; import com.intellij.refactoring.util.CanonicalTypes; import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; import com.intellij.util.IncorrectOperationException; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; @@ -84,43 +82,43 @@ public abstract class ChangeSignatureTestCase extends LightCodeInsightFixtureTes GrParameter[] params = method.getParameterList().getParameters(); GrParameterInfo[] result = new GrParameterInfo[myInfos.length]; for (int i = 0; i < myInfos.length; i++) { + final SimpleInfo sim = myInfos[i]; int oldIndex = sim.myOldIndex; + final GrParameterInfo info; + String name = null; + String defInitializer = null; + PsiType type = null; + String defValue = null; if (oldIndex > -1) { - info = new GrParameterInfo(params[oldIndex], oldIndex); - } - else { - info = new GrParameterInfo(myProject, method); + final GrParameter p = params[oldIndex]; + name = p.getName(); + final GrExpression initializer = p.getDefaultInitializer(); + defInitializer = initializer != null ? initializer.getText() : null; + type = p.getDeclaredType(); } + if (sim.myNewName != null) { - setText(info.getNameFragment(), sim.myNewName); + name = sim.myNewName; } - if (sim.myType != null) { - setText(info.getTypeFragment(), sim.myType.getCanonicalText()); + if (sim.myType != null && sim.myType.length() > 0) { + type = JavaPsiFacade.getElementFactory(myProject).createTypeFromText(sim.myType, method); } if (sim.myDefaultInitializer != null) { - setText(info.getDefaultInitializerFragment(), sim.myDefaultInitializer); + defInitializer = sim.myDefaultInitializer; } if (sim.myDefaultValue != null) { - setText(info.getDefaultValueFragment(), sim.myDefaultValue); + defValue = sim.myDefaultValue; } + + assert (oldIndex < 0 && defValue != null) || oldIndex >= 0; + assert name != null; + info = new GrParameterInfo(name, defValue, defInitializer, type, oldIndex); result[i] = info; } return result; } - - private void setText(final PsiCodeFragment codeFragment, final String newText) { - new WriteAction() { - @Override - protected void run(Result result) throws Throwable { - final PsiDocumentManager docManager = PsiDocumentManager.getInstance(myProject); - final Document document = docManager.getDocument(codeFragment); - document.setText(newText); - docManager.commitDocument(document); - } - }.execute(); - } } interface GenExceptions { @@ -151,22 +149,26 @@ public abstract class ChangeSignatureTestCase extends LightCodeInsightFixtureTes String myNewName; String myDefaultValue; String myDefaultInitializer; - private PsiType myType; + private String myType; SimpleInfo(int oldIndex) { this(null, oldIndex); } SimpleInfo(String newName, int oldIndex) { - this(newName, oldIndex, "", null, null); + this(newName, oldIndex, "", null, ""); } - SimpleInfo(String newName, int oldIndex, String defaultValue, String defaultInitializer, PsiType type) { + SimpleInfo(String newName, int oldIndex, String defaultValue, String defaultInitializer, String type) { myOldIndex = oldIndex; myNewName = newName; myDefaultValue = defaultValue; myDefaultInitializer = defaultInitializer; myType = type; } + + SimpleInfo(String newName, int oldIndex, String defaultValue, String defaultInitializer, PsiType type) { + this(newName, oldIndex, defaultValue, defaultInitializer, type.getCanonicalText()); + } } } diff --git a/plugins/groovy/testdata/refactoring/changeSignature/MoveVarArgParameters.groovy b/plugins/groovy/testdata/refactoring/changeSignature/MoveVarArgParameters.groovy index 1b9feb37d300..3c4bcbe90285 100644 --- a/plugins/groovy/testdata/refactoring/changeSignature/MoveVarArgParameters.groovy +++ b/plugins/groovy/testdata/refactoring/changeSignature/MoveVarArgParameters.groovy @@ -1,3 +1,3 @@ -def foo(String s, String[] args) {} +def foo(String s, String... args) {} foo("a", "b", "c") \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/MoveVarArgParameters_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/MoveVarArgParameters_after.groovy index d34406f1958f..9a4978f320ed 100644 --- a/plugins/groovy/testdata/refactoring/changeSignature/MoveVarArgParameters_after.groovy +++ b/plugins/groovy/testdata/refactoring/changeSignature/MoveVarArgParameters_after.groovy @@ -1,3 +1,3 @@ -def foo(String[] args, String s) {} +def foo(String... args, String s) {} foo(["b", "c"] as String[], "a") \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/MoveVarArgParameters_after.java b/plugins/groovy/testdata/refactoring/changeSignature/MoveVarArgParameters_after.java index 3c8a30ae9d82..682ce050f6a7 100644 --- a/plugins/groovy/testdata/refactoring/changeSignature/MoveVarArgParameters_after.java +++ b/plugins/groovy/testdata/refactoring/changeSignature/MoveVarArgParameters_after.java @@ -1,5 +1,5 @@ class Foo { public static void main(String[] args) { - new MoveVarArgParameters().foo(new String[]{"b", "c"}, "a") + new MoveVarArgParameters().foo(new String[]{"b","c"},"a" ) } } \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/ReplaceVarargWithArray.groovy b/plugins/groovy/testdata/refactoring/changeSignature/ReplaceVarargWithArray.groovy new file mode 100644 index 000000000000..d47669e10e5a --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/ReplaceVarargWithArray.groovy @@ -0,0 +1,14 @@ +class List {} + +class Base { + void foo(String s, List... l) {} +} + +class Inheritor extends Base { + void foo(String s, List... l) {} + + { + new Inheritor().foo("a", new ArrayList()); + } +} + diff --git a/plugins/groovy/testdata/refactoring/changeSignature/ReplaceVarargWithArray_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/ReplaceVarargWithArray_after.groovy new file mode 100644 index 000000000000..be83d989534c --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/ReplaceVarargWithArray_after.groovy @@ -0,0 +1,14 @@ +class List {} + +class Base { + void foo(List[] l, String s) {} +} + +class Inheritor extends Base { + void foo(List[] l, String s) {} + + { + new Inheritor().foo([new List()] as List[], "a"); + } +} + From aecbce3f7762c5c14587cb5eb4b341039a05893c Mon Sep 17 00:00:00 2001 From: Kirill Kalishev Date: Mon, 31 May 2010 14:32:03 +0400 Subject: [PATCH 027/212] IDEA-53847 Project view state is not preserved (including currently selected item) if Compact Empty Middle Packages option is changed --- .../projectView/BaseProjectTreeBuilder.java | 127 +++++++++++++----- 1 file changed, 95 insertions(+), 32 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/BaseProjectTreeBuilder.java b/platform/lang-impl/src/com/intellij/ide/projectView/BaseProjectTreeBuilder.java index 006410ff9375..ad1f4fd571c4 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/BaseProjectTreeBuilder.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/BaseProjectTreeBuilder.java @@ -25,24 +25,22 @@ import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.Progressive; import com.intellij.openapi.progress.util.StatusBarProgress; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.ActionCallback; -import com.intellij.openapi.util.AsyncResult; -import com.intellij.openapi.util.Condition; -import com.intellij.openapi.util.Conditions; +import com.intellij.openapi.util.*; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.psi.PsiDirectory; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiFileSystemItem; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; +import java.util.*; public abstract class BaseProjectTreeBuilder extends AbstractTreeBuilder { protected final Project myProject; @@ -62,7 +60,42 @@ public abstract class BaseProjectTreeBuilder extends AbstractTreeBuilder { } private AsyncResult _revalidateElement(Object element) { - return new AsyncResult.Done(element); + final AsyncResult result = new AsyncResult(); + + if (element instanceof AbstractTreeNode) { + AbstractTreeNode node = (AbstractTreeNode)element; + final Object value = node.getValue(); + VirtualFile vFile = null; + if (value instanceof PsiFileSystemItem) { + vFile = ((PsiFileSystemItem)value).getVirtualFile(); + } else if (value instanceof PsiElement) { + PsiFile psiFile = ((PsiElement)value).getContainingFile(); + if (psiFile != null) { + vFile = psiFile.getVirtualFile(); + } + } + final ActionCallback cb = new ActionCallback(); + + final VirtualFile finalVFile = vFile; + batch(new Progressive() { + public void run(@NotNull ProgressIndicator indicator) { + final Ref target = new Ref(); + _select(value, finalVFile, false, Conditions.alwaysTrue(), cb, indicator, target); + cb.doWhenDone(new Runnable() { + public void run() { + result.setDone(target.get()); + } + }).doWhenRejected(new Runnable() { + public void run() { + result.setRejected(); + } + }); + } + }); + } else { + result.setRejected(); + } + return result; } protected boolean isAlwaysShowPlus(NodeDescriptor nodeDescriptor) { @@ -141,7 +174,7 @@ public abstract class BaseProjectTreeBuilder extends AbstractTreeBuilder { public void run() { batch(new Progressive() { public void run(@NotNull ProgressIndicator indicator) { - _select(element, file, requestFocus, nonStopCondition, result, indicator); + _select(element, file, requestFocus, nonStopCondition, result, indicator, null); } }); } @@ -157,12 +190,13 @@ public abstract class BaseProjectTreeBuilder extends AbstractTreeBuilder { final boolean requestFocus, final Condition nonStopCondition, final ActionCallback result, - ProgressIndicator indicator) { + ProgressIndicator indicator, + @Nullable final Ref virtualSelectTarget) { AbstractTreeNode alreadySelected = alreadySelectedNode(element); final Runnable onDone = new Runnable() { public void run() { - if (requestFocus) { + if (requestFocus && virtualSelectTarget == null) { IdeFocusManager.getInstance(myProject).requestFocus(getTree(), true); } @@ -178,7 +212,7 @@ public abstract class BaseProjectTreeBuilder extends AbstractTreeBuilder { }; if (alreadySelected == null) { - expandPathTo(file, (AbstractTreeNode)getTreeStructure().getRootElement(), element, condition, indicator) + expandPathTo(file, (AbstractTreeNode)getTreeStructure().getRootElement(), element, condition, indicator, virtualSelectTarget) .doWhenDone(new AsyncResult.Handler() { public void run(AbstractTreeNode node) { select(node, onDone); @@ -219,15 +253,21 @@ public abstract class BaseProjectTreeBuilder extends AbstractTreeBuilder { final AbstractTreeNode root, final Object element, final Condition nonStopCondition, - final ProgressIndicator indicator) { + final ProgressIndicator indicator, + @Nullable final Ref target) { final AsyncResult async = new AsyncResult(); if (root.canRepresent(element)) { - expand(root, new Runnable() { - public void run() { - async.setDone(root); - } - }); + if (target == null) { + expand(root, new Runnable() { + public void run() { + async.setDone(root); + } + }); + } else { + target.set(root); + async.setDone(root); + } return async; } @@ -237,27 +277,50 @@ public abstract class BaseProjectTreeBuilder extends AbstractTreeBuilder { } - expand(root, new Runnable() { - public void run() { - indicator.checkCanceled(); + if (target == null) { + expand(root, new Runnable() { + public void run() { + indicator.checkCanceled(); + final DefaultMutableTreeNode rootNode = getNodeForElement(root); + if (rootNode != null) { + final List kids = collectChildren(rootNode); + expandChild(kids, 0, nonStopCondition, file, element, async, indicator, target); + } + else { + async.setRejected(); + } + } + }); + } else { + if (indicator.isCanceled()) { + async.setRejected(); + } else { final DefaultMutableTreeNode rootNode = getNodeForElement(root); - if (rootNode != null) { - final List kids = collectChildren(rootNode); - expandChild(kids, 0, nonStopCondition, file, element, async, indicator); - } - else { - async.setRejected(); + final ArrayList kids = new ArrayList(); + if (rootNode != null && getTree().isExpanded(new TreePath(rootNode.getPath()))) { + kids.addAll(collectChildren(rootNode)); + } else { + List list = Arrays.asList(getTreeStructure().getChildElements(root)); + for (Object each : list) { + kids.add((AbstractTreeNode)each); + } } + + yield(new Runnable() { + public void run() { + expandChild(kids, 0, nonStopCondition, file, element, async, indicator, target); + } + }); } - }); + } return async; } private void expandChild(final List kids, final int i, final Condition nonStopCondition, final VirtualFile file, final Object element, - final AsyncResult async, final ProgressIndicator indicator) { + final AsyncResult async, final ProgressIndicator indicator, final Ref virtualSelectTarget) { if (i >= kids.size()) { async.setRejected(); @@ -272,7 +335,7 @@ public abstract class BaseProjectTreeBuilder extends AbstractTreeBuilder { } if (nonStopCondition.value(eachKid)) { - expandPathTo(file, eachKid, element, nonStopCondition, indicator).doWhenDone(new AsyncResult.Handler() { + expandPathTo(file, eachKid, element, nonStopCondition, indicator, virtualSelectTarget).doWhenDone(new AsyncResult.Handler() { public void run(AbstractTreeNode abstractTreeNode) { indicator.checkCanceled(); @@ -282,10 +345,10 @@ public abstract class BaseProjectTreeBuilder extends AbstractTreeBuilder { public void run() { indicator.checkCanceled(); - if (nodeWasCollapsed[0]) { + if (nodeWasCollapsed[0] && virtualSelectTarget == null) { collapseChildren(eachKid, null); } - expandChild(kids, i + 1, nonStopCondition, file, element, async, indicator); + expandChild(kids, i + 1, nonStopCondition, file, element, async, indicator, virtualSelectTarget); } }); } else { From ae62b9ef94607133c8f1910cadd612dd4a4b7d84 Mon Sep 17 00:00:00 2001 From: Kirill Kalishev Date: Mon, 31 May 2010 15:35:16 +0400 Subject: [PATCH 028/212] project view scrolling fix - 1 --- .../ide/projectView/BaseProjectTreeBuilder.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/BaseProjectTreeBuilder.java b/platform/lang-impl/src/com/intellij/ide/projectView/BaseProjectTreeBuilder.java index ad1f4fd571c4..ae4abf72fef1 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/BaseProjectTreeBuilder.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/BaseProjectTreeBuilder.java @@ -215,12 +215,20 @@ public abstract class BaseProjectTreeBuilder extends AbstractTreeBuilder { expandPathTo(file, (AbstractTreeNode)getTreeStructure().getRootElement(), element, condition, indicator, virtualSelectTarget) .doWhenDone(new AsyncResult.Handler() { public void run(AbstractTreeNode node) { - select(node, onDone); + if (virtualSelectTarget == null) { + select(node, onDone); + } else if (onDone != null) { + onDone.run(); + } } }).notifyWhenRejected(result); } else { - select(alreadySelected, onDone); + if (virtualSelectTarget == null) { + select(alreadySelected, onDone); + } else if (onDone != null) { + onDone.run(); + } } } From e94405d911c4e44adc4cf2a0892da2642925bf0b Mon Sep 17 00:00:00 2001 From: Kirill Kalishev Date: Mon, 31 May 2010 15:56:40 +0400 Subject: [PATCH 029/212] tree holds size while updating to avoid viewport flickering --- .../ide/util/treeView/AbstractTreeUi.java | 14 ++++++++++++ .../com/intellij/ui/treeStructure/Tree.java | 22 +++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java index cd7d9eedd2de..49f18c1d7528 100644 --- a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java +++ b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java @@ -271,6 +271,13 @@ public class AbstractTreeUi { } } + private void setHoldSize(boolean holdSize) { + if (myTree instanceof com.intellij.ui.treeStructure.Tree) { + final com.intellij.ui.treeStructure.Tree tree = (Tree)myTree; + tree.setHoldSize(holdSize); + } + } + private void cleanUpAll() { final long now = System.currentTimeMillis(); final AbstractTreeUi[] uis = ourUi2Countdown.keySet().toArray(new AbstractTreeUi[ourUi2Countdown.size()]); @@ -962,7 +969,10 @@ public class AbstractTreeUi { } final void updateSubtreeNow(TreeUpdatePass pass, boolean canSmartExpand) { + + maybeSetBusyAndScheduleWaiterForReady(true); + setHoldSize(true); boolean consumed = initRootNodeNowIfNeeded(pass); if (consumed) return; @@ -1804,6 +1814,8 @@ public class AbstractTreeUi { } } + setHoldSize(false); + if (myTree.isShowing()) { if (getBuilder().isToEnsureSelectionOnFocusGained() && Registry.is("ide.tree.ensureSelectionOnFocusGained")) { TreeUtil.ensureSelection(myTree); @@ -3526,6 +3538,7 @@ public class AbstractTreeUi { } if (Registry.is("ide.tree.autoscrollToVCenter") && canBeCentered) { + setHoldSize(false); runDone(new Runnable() { public void run() { TreeUtil.showRowCentered(myTree, row, false, scroll).doWhenDone(new Runnable() { @@ -3537,6 +3550,7 @@ public class AbstractTreeUi { }); } else { + setHoldSize(false); TreeUtil.showAndSelect(myTree, row - 2, row + 2, row, -1, addToSelection, scroll).doWhenDone(new Runnable() { public void run() { runDone(onDone); diff --git a/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java b/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java index 04fa252ddfdc..cdc6be22ccb1 100644 --- a/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java +++ b/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java @@ -47,6 +47,8 @@ public class Tree extends JTree implements ComponentWithEmptyText, Autoscroll, Q private boolean myBusy; private Rectangle myLastVisibleRec; + private Dimension myHoldSize; + public Tree() { initTree_(); } @@ -539,4 +541,24 @@ public class Tree extends JTree implements ComponentWithEmptyText, Autoscroll, Q public void reshape(int x, int y, int w, int h) { super.reshape(x, y, w, h); } + + public void setHoldSize(boolean hold) { + if (hold && myHoldSize == null) { + myHoldSize = getPreferredSize(); + } else if (!hold && myHoldSize != null) { + myHoldSize = null; + revalidate(); + } + } + + public Dimension getPreferredSize() { + Dimension size = super.getPreferredSize(); + + if (myHoldSize != null) { + size.width = Math.max(size.width, myHoldSize.width); + size.height = Math.max(size.height, myHoldSize.height); + } + + return size; + } } \ No newline at end of file From 009a9f5b77f6c797d4b7fb45da7cb33fdebd40f5 Mon Sep 17 00:00:00 2001 From: Kirill Kalishev Date: Mon, 31 May 2010 16:22:14 +0400 Subject: [PATCH 030/212] tree busy icon - click to cancel updating --- .../intellij/ide/util/treeView/AbstractTreeUi.java | 9 +++++++-- .../src/com/intellij/ui/treeStructure/Tree.java | 12 ++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java index 49f18c1d7528..8d6d33e9c7f5 100644 --- a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java +++ b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java @@ -2082,8 +2082,13 @@ public class AbstractTreeUi { resetToReadyNow(); done.setDone(); } else { - requestCancel(); - getReady(this).notify(done); + if (isIdle() && hasPendingWork()) { + resetToReadyNow(); + done.setDone(); + } else { + requestCancel(); + getReady(this).notify(done); + } } maybeReady(); diff --git a/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java b/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java index cdc6be22ccb1..3989ac967ec8 100644 --- a/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java +++ b/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java @@ -186,14 +186,26 @@ public class Tree extends JTree implements ComponentWithEmptyText, Autoscroll, Q myBusyIcon.setOpaque(false); myBusyIcon.setPaintPassiveIcon(false); add(myBusyIcon); + myBusyIcon.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + if (!UIUtil.isActionClick(e)) return; + AbstractTreeBuilder builder = AbstractTreeBuilder.getBuilderFor(Tree.this); + if (builder != null) { + builder.cancelUpdate(); + } + } + }); } } if (myBusyIcon != null) { if (myBusy) { myBusyIcon.resume(); + myBusyIcon.setToolTipText("Update is in progress. Click to cancel"); } else { myBusyIcon.suspend(); + myBusyIcon.setToolTipText(null); SwingUtilities.invokeLater(new Runnable() { public void run() { if (myBusyIcon != null) { From b85dd68c8b7dbd9364709bd943122a6d5b9cf49b Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Mon, 31 May 2010 17:46:42 +0400 Subject: [PATCH 031/212] [Mercurial] Large merge of the hg4idea-luciad fork. --- .../org/zmlx/hg4idea/HgVcsMessages.properties | 54 ++- plugins/hg4idea/resources/python/filemerge.py | 38 ++ .../hg4idea/resources/python/prompthooks.py | 112 +++++ plugins/hg4idea/src/META-INF/plugin.xml | 110 +++-- .../org/zmlx/hg4idea/HgContentRevision.java | 18 +- .../hg4idea/HgCurrentBranchStatusUpdater.java | 42 +- .../src/org/zmlx/hg4idea/HgErrorHandler.java | 33 ++ .../zmlx/hg4idea/HgExecutableValidator.java | 29 +- .../src/org/zmlx/hg4idea/HgFileRevision.java | 91 ++-- .../org/zmlx/hg4idea/HgIdeConfigurable.java | 22 +- .../zmlx/hg4idea/HgIncomingStatusUpdater.java | 36 +- .../zmlx/hg4idea/HgOutgoingStatusUpdater.java | 39 +- .../zmlx/hg4idea/HgProjectConfigurable.java | 16 +- .../org/zmlx/hg4idea/HgRevisionNumber.java | 50 +- .../hg4idea/src/org/zmlx/hg4idea/HgUtil.java | 161 +++++++ .../hg4idea/src/org/zmlx/hg4idea/HgVcs.java | 138 ++++-- .../zmlx/hg4idea/HgVirtualFileListener.java | 297 +++++++----- .../hg4idea/action/HgAbstractFilesAction.java | 32 +- .../action/HgAbstractGlobalAction.java | 31 +- .../zmlx/hg4idea/action/HgMarkResolved.java | 20 +- .../zmlx/hg4idea/action/HgMercurialMenu.java | 13 +- .../zmlx/hg4idea/action/HgMqRebaseAction.java | 32 +- .../action/HgRunConflictResolverAction.java | 59 +-- .../zmlx/hg4idea/command/HgCatCommand.java | 84 +++- .../hg4idea/command/HgChangesetsCommand.java | 80 ++++ .../zmlx/hg4idea/command/HgCloneCommand.java | 41 ++ .../command/HgCommandAuthenticator.java | 96 ++++ .../zmlx/hg4idea/command/HgCommandResult.java | 29 +- .../hg4idea/command/HgCommandService.java | 192 ++++++-- .../zmlx/hg4idea/command/HgCommitCommand.java | 37 +- .../zmlx/hg4idea/command/HgHeadsCommand.java | 53 +-- .../hg4idea/command/HgIdentifyCommand.java | 32 ++ .../hg4idea/command/HgIncomingCommand.java | 17 +- .../zmlx/hg4idea/command/HgLogCommand.java | 29 +- .../zmlx/hg4idea/command/HgMergeCommand.java | 13 +- .../hg4idea/command/HgOutgoingCommand.java | 17 +- .../hg4idea/command/HgParentsCommand.java | 39 ++ .../zmlx/hg4idea/command/HgPullCommand.java | 38 +- .../zmlx/hg4idea/command/HgPushCommand.java | 38 +- .../hg4idea/command/HgResolveCommand.java | 114 ++++- .../zmlx/hg4idea/command/HgRevertCommand.java | 30 +- .../hg4idea/command/HgRevisionsCommand.java | 168 +++---- .../zmlx/hg4idea/command/HgStatusCommand.java | 51 +- ...TrackFileNamesAccrossRevisionsCommand.java | 146 ++++++ .../hg4idea/command/HgVersionCommand.java | 8 +- .../HgWorkingCopyRevisionsCommand.java | 63 +-- .../zmlx/hg4idea/command/ShellCommand.java | 10 +- .../zmlx/hg4idea/command/SocketServer.java | 93 ++++ .../HgCachingCommitedChangesProvider.java | 229 ++++----- .../hg4idea/provider/HgChangeProvider.java | 321 +++++++------ .../hg4idea/provider/HgCheckoutProvider.java | 80 ++++ .../provider/HgCommitedChangeList.java | 43 +- .../HgCurrentBinaryContentRevision.java | 37 +- .../provider/HgCurrentContentRevision.java | 63 +-- .../HgCurrentContentRevisionFactory.java | 40 -- .../zmlx/hg4idea/provider/HgDiffProvider.java | 24 +- .../hg4idea/provider/HgHistoryProvider.java | 106 +++-- .../provider/HgRollbackEnvironment.java | 39 +- .../provider/annotate/HgAnnotation.java | 30 +- .../annotate/HgAnnotationProvider.java | 21 +- .../provider/commit/HgCheckinEnvironment.java | 165 +++++-- .../provider/commit/HgCommitSession.java | 30 +- .../provider/update/HgConflictResolver.java | 103 ++-- .../hg4idea/provider/update/HgHeadMerger.java | 79 ++-- .../update/HgIntegrateEnvironment.java | 60 +-- .../provider/update/HgRegularUpdater.java | 268 +++++++++-- .../provider/update/HgUpdateEnvironment.java | 81 +++- .../hg4idea/provider/update/HgUpdater.java | 50 +- .../provider/update/HgUpdaterFactory.java | 14 +- .../org/zmlx/hg4idea/ui/HgCloneDialog.form | 84 ++++ .../org/zmlx/hg4idea/ui/HgCloneDialog.java | 446 ++++++++++++++++++ .../hg4idea/ui/HgConfigurationIdePanel.form | 2 +- .../hg4idea/ui/HgConfigurationIdePanel.java | 88 +++- .../hg4idea/ui/HgCurrentBranchStatus.java | 29 +- .../zmlx/hg4idea/ui/HgIntegrateDialog.form | 35 +- .../zmlx/hg4idea/ui/HgIntegrateDialog.java | 143 ++---- .../hg4idea/ui/HgSetExecutableDialog.form | 20 +- .../hg4idea/ui/HgSetExecutableDialog.java | 95 +++- .../org/zmlx/hg4idea/ui/HgUpdateDialog.form | 59 +++ .../org/zmlx/hg4idea/ui/HgUpdateDialog.java | 120 +++++ .../org/zmlx/hg4idea/AbstractHgTestCase.java | 105 +++++ .../org/zmlx/hg4idea/HgAddTestCase.java | 9 +- .../org/zmlx/hg4idea/HgCatTestCase.java | 57 +++ .../org/zmlx/hg4idea/HgCopyTestCase.java | 26 +- .../org/zmlx/hg4idea/HgDeleteTestCase.java | 24 +- .../zmlx/hg4idea/HgFromClonedTestCase.java | 82 ++++ .../org/zmlx/hg4idea/HgLogTestCase.java | 36 ++ .../org/zmlx/hg4idea/HgMoveTestCase.java | 20 +- .../org/zmlx/hg4idea/HgRenameTestCase.java | 34 +- .../hg4idea/HgResolveConflictTestCase.java | 62 +++ .../org/zmlx/hg4idea/HgRevertTestCase.java | 47 ++ .../testSrc/org/zmlx/hg4idea/HgTestCase.java | 71 ++- .../org/zmlx/hg4idea/HgUpdateTestCase.java | 283 +++++++++++ 93 files changed, 4959 insertions(+), 1892 deletions(-) create mode 100644 plugins/hg4idea/resources/python/filemerge.py create mode 100644 plugins/hg4idea/resources/python/prompthooks.py create mode 100644 plugins/hg4idea/src/org/zmlx/hg4idea/HgErrorHandler.java create mode 100644 plugins/hg4idea/src/org/zmlx/hg4idea/HgUtil.java create mode 100644 plugins/hg4idea/src/org/zmlx/hg4idea/command/HgChangesetsCommand.java create mode 100644 plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCloneCommand.java create mode 100644 plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCommandAuthenticator.java create mode 100644 plugins/hg4idea/src/org/zmlx/hg4idea/command/HgIdentifyCommand.java create mode 100644 plugins/hg4idea/src/org/zmlx/hg4idea/command/HgParentsCommand.java create mode 100644 plugins/hg4idea/src/org/zmlx/hg4idea/command/HgTrackFileNamesAccrossRevisionsCommand.java create mode 100644 plugins/hg4idea/src/org/zmlx/hg4idea/command/SocketServer.java create mode 100644 plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCheckoutProvider.java delete mode 100644 plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCurrentContentRevisionFactory.java create mode 100644 plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgCloneDialog.form create mode 100644 plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgCloneDialog.java create mode 100644 plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgUpdateDialog.form create mode 100644 plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgUpdateDialog.java create mode 100644 plugins/hg4idea/testSrc/org/zmlx/hg4idea/AbstractHgTestCase.java create mode 100644 plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgCatTestCase.java create mode 100644 plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgFromClonedTestCase.java create mode 100644 plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgLogTestCase.java create mode 100644 plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgResolveConflictTestCase.java create mode 100644 plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgRevertTestCase.java create mode 100644 plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgUpdateTestCase.java diff --git a/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties b/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties index 787b7e7aef65..dd0c21cc4651 100644 --- a/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties +++ b/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties @@ -1,9 +1,9 @@ group.hg4idea.global.menu.text=Mercurial -group.hg4idea.global.submenu.text=Mercurial Actions +group.hg4idea.global.submenu.text=Mercurial group.hg4idea.file.menu.text=Mercurial action.hg4idea.tag.text=Tag Repository action.hg4idea.tag.description=Create a tag for current revision -action.hg4idea.switch.text=Switch Working Directory +action.hg4idea.switch.text=Update to... action.hg4idea.switch.description=Switch working directory to another revision action.hg4idea.push.text=Push Changesets... action.hg4idea.push.description=Push outgoing changesets @@ -21,21 +21,34 @@ hg4idea.error=Error hg4idea.revert=Revert hg4idea.commit=Commit -hg4idea.init.destination.directory.description=Select directory where the new Mercurial repository will be created. -hg4idea.init.destination.directory.title=Select directory for hg init -hg4idea.init.error.already.under.hg=The selected directory {0} is already under hg. -hg4idea.init.error.title=hg init Error +hg4idea.clone.title=Clone Mercurial Repostiroy +hg4idea.clone.button.clone=Clone +hg4idea.clone.button.test=&Test Repository +hg4idea.clone.cloning.repository=Cloning source repository {0} +hg4idea.clone.error.destination.directory.exists=The path {0} exists. Mercurial cannot clone to existing directory. +hg4idea.clone.error.repository.url=Repository URL is a malformed URL or non-existent directory. +hg4idea.clone.error.test.failed=Repository test has failed. +hg4idea.clone.error.parent.directory.missing=The parent path {0} must exist. +hg4idea.clone.error.repository.url.is.not.directory=Repository URL is not a directory. +hg4idea.clone.repository.url=Mercurial &Repository URL +hg4idea.clone.parent.directory=&Parent Directory +hg4idea.clone.parent.directory.title=Parent Directory +hg4idea.clone.parent.directory.description=Select a parent directory destination directory for clone +hg4idea.clone.directory.name=Directory &Name +hg4idea.clone.test.testing=Testing repository {0} +hg4idea.clone.test.success.message=Connection to repository {0} has been successful. +hg4idea.clone.test.success=Connection successful hg4idea.configuration.title=Mercurial Configuration -hg4idea.configuration.description=Full path to hg executable -hg4idea.configuration.executable.error=\"{0}\" doesn\'t appear to be a valid hg executable +hg4idea.configuration.description=Path to hg executable +hg4idea.configuration.executable.error=\"{0}\" doesn't appear to be a valid hg executable hg4idea.command.executable.error=Error executing \"{0}\". Make sure you have setup the right executable in Mercurial configuration hg4idea.commit.error.messageEmpty=Please provide a commit message hg4idea.commit.error.unknown=Could not commit, no error message was provided -hg4idea.commit.repository.title=Commit Repository -hg4idea.commit.repository.body=Commit all changes in repository +hg4idea.commit.repository.title=Commit Repositories +hg4idea.commit.repository.body=Commit all changes in all affected repositories hg4idea.add.confirmation.title=Add file(s) hg4idea.add.confirmation.body=Do you want to schedule the following file for addition to Mercurial?\n{0} @@ -43,9 +56,16 @@ hg4idea.add.confirmation.body=Do you want to schedule the following file for add hg4idea.delete.confirmation.title=Delete file(s) hg4idea.delete.confirmation.body=Do you want to schedule the following file for deletion from Mercurial?\n{0} -hg4idea.update.error.manyHeads=Found {0} heads in repository, you will have to merge them manually. Update Aborted. -hg4idea.update.error.uncommitedChanges=Local changes found, update aborted -hg4idea.update.error.currentBranch=Could not determine current branch +hg4idea.update.error.uncommittedMerge=outstanding uncommitted merge in repository {0}, not updating or merging +hg4idea.update.error.localchanges=outstanding uncommitted changes in repository {0}, not merging with pulled head +hg4idea.update.error.merge.multipleLocalHeads=More than one local head in repository {0}, not merging +hg4idea.update.error.merge.multipleRemoteHeads=Pulled in {0} remote heads in repository {1}, not merging +hg4idea.update.warning.merge.conflicts=Merged with conflicts in repository {0}. Inspect the conflicts, and commit the merge when you are done +hg4idea.update.warning.multipleHeadsBeforeUpdate=Multiple heads in this branch in repository {0} before the update (use \"hg heads .\" and \"hg merge\" to merge) +hg4idea.update.progress.updating.to.pulled.head=Updating to pulled head +hg4idea.update.progress.merging=Merging with pulled head + +hg4idea.progress.updatingworkingdir=Updating local working directory hg4idea.progress.integrating=Integrating {0} ... hg4idea.progress.merging=Performing merge... @@ -54,8 +74,12 @@ hg4idea.progress.countingHeads=Checking number of heads... hg4idea.progress.pull.with.rebase=Rebasing patches hg4idea.progress.pull.with.update=Updating repository hg4idea.commit.success=Repository \"{0}\" commited +hg4idea.commit.partial.merge.message=Partial commits are not allowed during merge, and following files are not included:
    {0}
Perform commit with all files included ? +hg4idea.commit.partial.merge.title=Partial Merge Commit hg4idea.error.invalidTarget=Invalid integration target -hg4idea.status.currentBranch.text={0} -hg4idea.status.currentBranch.description=Current mercurial branch +hg4idea.status.currentSituationtext={0}({1}) +hg4idea.status.currentSituation.description=Current mercurial branch and parents of the working directory hg4idea.warning.no-default-update-path=Skipped \"{0}\". No default update path. hg4idea.merge.please-commit=Merged heads, please commit repository \"{0}\" +hg4idea.error.invalidExecutable=\"{0}\" is not a valid mercurial executable +hg4idea.integrate.other.head=Other head: {0} diff --git a/plugins/hg4idea/resources/python/filemerge.py b/plugins/hg4idea/resources/python/filemerge.py new file mode 100644 index 000000000000..37994bba426d --- /dev/null +++ b/plugins/hg4idea/resources/python/filemerge.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python + +from mercurial import filemerge, ui, util +from mercurial.node import short +import sys, struct, socket + +def monkeypatch_method(cls): + def decorator(func): + setattr(cls, func.__name__, func) + return func + return decorator + +@monkeypatch_method(filemerge) +def filemerge(repo, mynode, orig, fcd, fco, fca): + port = int(repo.ui.config( 'hg4ideafilemerge', 'port', None, True)) + + repo.ui.debug( "hg4idea server waiting on port %s" % port ) + + if not port: + util.abort("No port was specified") + + def send( client, data ): + length = struct.pack('>L', len(data)) + client.sendall( length ) + client.sendall( data) + + client = socket.socket( socket.AF_INET, socket.SOCK_STREAM ) + repo.ui.debug( "connecting ..." ) + try: + client.connect( ('127.0.0.1', port) ) + repo.ui.debug( "connected, sending data ..." ) + send( client, fcd.data() ) + send( client, fco.data() ) + send( client, fca.data() ) + print client.recv(1024) + return 1; + except: + util.abort( "Could not send data to hg4idea") diff --git a/plugins/hg4idea/resources/python/prompthooks.py b/plugins/hg4idea/resources/python/prompthooks.py new file mode 100644 index 000000000000..9641d0cb6fdb --- /dev/null +++ b/plugins/hg4idea/resources/python/prompthooks.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python + +from mercurial import filemerge, ui, util, dispatch +from mercurial.node import short +import sys, struct, socket + +def sendInt( client, number): + length = struct.pack('>L', number) + client.sendall( length ) + +def send( client, data ): + sendInt(client, len(data)) + client.sendall( data ) + +def receiveInt(client): + requiredLength = struct.calcsize('>L') + buffer = '' + while len(buffer)L', buffer) + + return intToReturn + +def receive( client ): + length = receiveInt(client) + buffer = '' + while len(buffer) < length : + chunk = client.recv(length - len(buffer)) + if chunk == '': + raise RuntimeError, "socket connection broken" + buffer = buffer+chunk + + return buffer + +# decorator to cleanly monkey patch methods in mercurial +def monkeypatch_method(cls): + def decorator(func): + setattr(cls, func.__name__, func) + return func + return decorator + +def sendchangestoidea(ui, msg, choices, default): + port = int(ui.config( 'hg4ideaprompt', 'port', None, True)) + + if not port: + raise util.Abort("No port was specified") + + numOfChoices = len(choices) + if numOfChoices == 0: + return default + + client = socket.socket( socket.AF_INET, socket.SOCK_STREAM ) + + try: + client.connect( ('127.0.0.1', port) ) + + send( client, msg ) + sendInt( client, numOfChoices ) + for choice in choices: + send( client, choice ) + sendInt( client, default ) + + answer = receiveInt( client ) + print "Received answer: %s" % answer + if answer == -1: + raise util.Abort("User cancelled") + else: + return answer + except: + raise + +# determine which method to monkey patch : +# in Mercurial 1.4 the prompt method was renamed to promptchoice +if getattr(ui.ui, 'promptchoice', None): + @monkeypatch_method(ui.ui) + def promptchoice(self, msg, choices=None, default=0): + return sendchangestoidea(self, msg, choices, default) +else: + @monkeypatch_method(ui.ui) + def prompt(self, msg, choices=None, default="y"): + resps = [s[s.index('&')+1].lower() for s in choices] + defaultIndex = resps.index( default ) + responseIndex = sendchangestoidea( self, msg, choices, defaultIndex) + return resps[responseIndex] + +original_warn = ui.ui.warn +@monkeypatch_method(ui.ui) +def warn(self, *msg): + original_warn(self, *msg) + + port = int(self.config( 'hg4ideawarn', 'port', None, True)) + + if not port: + raise util.Abort("No port was specified") + + self.debug( "hg4idea prompt server waiting on port %s" % port ) + + client = socket.socket( socket.AF_INET, socket.SOCK_STREAM ) + + self.debug( "connecting ..." ) + client.connect( ('127.0.0.1', port) ) + self.debug( "connected, sending data ..." ) + + sendInt( client, len(msg) ) + for message in msg: + send( client, message ) diff --git a/plugins/hg4idea/src/META-INF/plugin.xml b/plugins/hg4idea/src/META-INF/plugin.xml index 40524f75e207..0406e1850618 100644 --- a/plugins/hg4idea/src/META-INF/plugin.xml +++ b/plugins/hg4idea/src/META-INF/plugin.xml @@ -3,58 +3,59 @@ hg4idea IntelliJ IDEA plugin for Mercurial integration.
+ IntelliJ IDEA plugin for Mercurial integration - Luciad fork
RubyMine and WebIDE should work but hg4idea was never tested against them.

System Requirements:

  • IntelliJ IDEA (Ultimate or Community)
  • Java 5+ -
  • Mercurial 1.5+ +
  • Mercurial 1.3+

- If you found a bug or would like to see some features added to hg4idea please open a ticket in bugtracker. -

- When opening bugs don't forget to include: -

    -
  • IntelliJ IDEA version -
  • hg4idea version -
  • Mercurial version -
  • Exact steps to reproduce -
+ Please refer to the bitbucket site for more information. ]]>
VCS Integration 10.0 - Victor Iacoban + Victor Iacoban and Willem Verstraeten com.intellij.modules.vcs - + + - + + - - + - - - - + + + + + + + + + + + + @@ -62,12 +63,6 @@ - - - - - - @@ -84,29 +79,58 @@ org.zmlx.hg4idea.HgVcsMessages + Changes since 0.6.0 +

Changes in 0.6.16-luciad.9-9.0.2

    -
  • [feature] Folders under mercurial control are auto-detected on project creation -
  • [feature] New status notifications for incoming and outgoing changesets -
  • [enhancement] User was required to enter the hg executable path for every project -
  • [enhancement] Added support for multi-line commit messages +
  • [enhancement] you can now diff to renamed versions of a file in the history window +
  • [enhancement] you can now clone from within IntelliJ +
  • [bugfix] the revert command now also works during a merge operation +
  • [bugfix] moving a file between two mercurial repositories now works +
  • [bugfix] reduced the number of temporary files created and made sure that they and all their derivatives are deleted (again ...)
-

Changes since 0.5

+

Changes in 0.6.16-luciad.8-9.0.2

    -
  • [feature] Unresolved files show in red -
  • [feature] Added new action to resolve all conflicts, will open the merge dialog -
  • [feature] Added mercurial context action to mark a file as resolved -
  • [feature] New Mercurial menu action to rebase MQ patches -
  • [enhancement] When file is moved/renamed, it has a status of modified -
  • [enhancement] Added tooltip to mercurial status component -
  • [bugfix] exception clicking annotate in history view -
  • [bugfix] NPE on project integration -
  • Re-organized mercurial menu -
  • Performance improvements +
  • compatible with IntelliJ 9.0.2 +
  • [enhancement] the local pane of the diff window invoked from the 'Changes' view is now editable +
  • [bugfix] the history items are now sorted numerically on revision instead of lexically +
  • [bugfix] the history of a file now contains all revisions in which it changed +
  • [bugfix] renames are now shown properly in the changes view +
  • [bugfix] paths to hg.exe on Windows now also work +
+

Changes in 0.6.14-luciad.7-9.0.1

+
    +
  • [bugfix] the plugin now deletes _all_ temporary files it creates +
+

Changes in 0.6.14-luciad.6-9.0.1

+
    +
  • [bugfix] fixed possible exceptions when parsing revisions +
+

Changes in 0.6.14-luciad.5-9.0.1

+
    +
  • [bugfix] fixed distribution, the plugin can now be installed again +
+

Changes in 0.6.14-luciad.4-9.0.1

+
    +
  • [enhancement] the update behavior now emulates the fetch extension, except that it allows local modifications where possible +
  • [enhancement] added more VCS-related actions to the popup menus of files +
  • [bugfix] the plugin now cleans up the temporary files it creates +
+

Changes in 0.6.14-luciad.3-9.0.1

+
    +
  • [bugfix] committing a merge no longer complains about ignored files +
  • [enhancement] 'Add to VCS' action is now available in right-click of files (merged from upstream) +
+

Changes from the regular hg4idea

+
    +
  • [bugfix] three-way merge editor now shows the correct content +
  • [bugfix] prompts during merge and update etc. are now shown in the IDE instead of ignored +
  • [bugfix] authentication dialog is now shown on the correct thread, allowing push and pull to secured servers +
  • [enhancement] better error and warning reporting +
  • [enhancement] update now works more consistently, especially when not at head revisions +
  • [enhancement] default commit button now also works when committing merges
- For full changelog visit wiki changelog page. ]]>
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgContentRevision.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgContentRevision.java index 568d02de1a0b..8d063bf8a4d8 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgContentRevision.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgContentRevision.java @@ -12,21 +12,19 @@ // limitations under the License. package org.zmlx.hg4idea; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vcs.FilePath; -import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vcs.changes.ContentRevision; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.builder.EqualsBuilder; -import org.apache.commons.lang.builder.HashCodeBuilder; -import org.jetbrains.annotations.NotNull; -import org.zmlx.hg4idea.command.HgCatCommand; +import com.intellij.openapi.project.*; +import com.intellij.openapi.vcs.*; +import com.intellij.openapi.vcs.changes.*; +import org.apache.commons.lang.*; +import org.apache.commons.lang.builder.*; +import org.jetbrains.annotations.*; +import org.zmlx.hg4idea.command.*; public class HgContentRevision implements ContentRevision { private final Project project; private final HgFile hgFile; - private final HgRevisionNumber revisionNumber; + @NotNull private final HgRevisionNumber revisionNumber; private FilePath filePath; private String content; diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgCurrentBranchStatusUpdater.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgCurrentBranchStatusUpdater.java index 8478f6552a8b..0fb79d73d0e3 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgCurrentBranchStatusUpdater.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgCurrentBranchStatusUpdater.java @@ -12,15 +12,15 @@ // limitations under the License. package org.zmlx.hg4idea; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.fileEditor.FileDocumentManager; -import com.intellij.openapi.fileEditor.FileEditorManager; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.vcsUtil.VcsUtil; -import org.zmlx.hg4idea.command.HgTagBranchCommand; -import org.zmlx.hg4idea.ui.HgCurrentBranchStatus; +import com.intellij.openapi.editor.*; +import com.intellij.openapi.fileEditor.*; +import com.intellij.openapi.project.*; +import com.intellij.openapi.vfs.*; +import com.intellij.vcsUtil.*; +import org.zmlx.hg4idea.command.*; +import org.zmlx.hg4idea.ui.*; + +import java.util.*; class HgCurrentBranchStatusUpdater implements HgUpdater { @@ -31,21 +31,21 @@ class HgCurrentBranchStatusUpdater implements HgUpdater { } public void update(Project project) { - hgCurrentBranchStatus.setCurrentBranch(null); Editor textEditor = FileEditorManager.getInstance(project).getSelectedTextEditor(); - if (textEditor == null) { - return; - } - Document document = textEditor.getDocument(); - VirtualFile file = FileDocumentManager.getInstance().getFile(document); + if (textEditor != null) { + Document document = textEditor.getDocument(); + VirtualFile file = FileDocumentManager.getInstance().getFile(document); - VirtualFile repo = VcsUtil.getVcsRootFor(project, file); - String branch = null; - if (repo != null) { - HgTagBranchCommand hgTagBranchCommand = new HgTagBranchCommand(project, repo); - branch = hgTagBranchCommand.getCurrentBranch(); + VirtualFile repo = VcsUtil.getVcsRootFor(project, file); + if (repo != null) { + HgTagBranchCommand hgTagBranchCommand = new HgTagBranchCommand(project, repo); + String branch = hgTagBranchCommand.getCurrentBranch(); + List parents = new HgWorkingCopyRevisionsCommand(project).parents(repo); + hgCurrentBranchStatus.updateFor(branch, parents); + return; + } } - hgCurrentBranchStatus.setCurrentBranch(branch); + hgCurrentBranchStatus.updateFor(null, Collections.emptyList()); } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgErrorHandler.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgErrorHandler.java new file mode 100644 index 000000000000..aec0b6d0112b --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgErrorHandler.java @@ -0,0 +1,33 @@ +// Copyright 2010 Victor Iacoban +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under +// the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions and +// limitations under the License. +package org.zmlx.hg4idea; + +import com.intellij.openapi.vcs.*; +import org.zmlx.hg4idea.command.*; + +public abstract class HgErrorHandler { + + public static HgCommandResult ensureSuccess(HgCommandResult result) throws VcsException { + if (fatalErrorOccurred(result)) { + throw new VcsException(result.getRawError()); + } + return result; + } + + private static boolean fatalErrorOccurred(HgCommandResult result) { + return + result.getExitValue() == 255 || + result.getRawError().contains("** unknown exception encountered"); + } + +} \ No newline at end of file diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgExecutableValidator.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgExecutableValidator.java index c4663ce7f928..3e99ab843e54 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgExecutableValidator.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgExecutableValidator.java @@ -12,38 +12,33 @@ // limitations under the License. package org.zmlx.hg4idea; -import com.intellij.openapi.project.Project; -import org.zmlx.hg4idea.ui.HgSetExecutableDialog; +import com.intellij.openapi.project.*; +import org.zmlx.hg4idea.command.*; +import org.zmlx.hg4idea.ui.*; -import java.io.File; - -/** - * Validates the 'hg' executable file, which is specified in {@link HgGlobalSettings}}. - * Checks that the file specified exists and invokes the {@link org.zmlx.hg4idea.ui.HgSetExecutableDialog} - * if not. The dialog provides more detailed validation. - */ class HgExecutableValidator { - private final Project myProject; + private final Project project; public HgExecutableValidator(Project project) { - this.myProject = project; + this.project = project; } public boolean check(HgGlobalSettings globalSettings) { - String hgPath = globalSettings.getHgExecutable(); - if ((new File(hgPath)).exists()) { + HgVersionCommand command = new HgVersionCommand(); + if (command.isValid(globalSettings.getHgExecutable())) { return true; } + String previousHgPath = globalSettings.getHgExecutable(); boolean validHgExecutable; HgSetExecutableDialog dialog; do { - dialog = new HgSetExecutableDialog(myProject); - dialog.setBadHgPath(hgPath); + dialog = new HgSetExecutableDialog(project); + dialog.setBadHgPath(previousHgPath); dialog.show(); - validHgExecutable = dialog.isOK(); - hgPath = dialog.getNewHgPath(); + validHgExecutable = dialog.isOK() && command.isValid(dialog.getNewHgPath()); + previousHgPath = dialog.getNewHgPath(); } while (!validHgExecutable && dialog.isOK()); if (validHgExecutable) { diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgFileRevision.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgFileRevision.java index a55a646bf031..d6c67ba26630 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgFileRevision.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgFileRevision.java @@ -12,40 +12,45 @@ // limitations under the License. package org.zmlx.hg4idea; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vcs.history.VcsFileRevision; -import org.apache.commons.lang.builder.EqualsBuilder; -import org.apache.commons.lang.builder.HashCodeBuilder; -import org.zmlx.hg4idea.command.HgCatCommand; +import com.intellij.openapi.project.*; +import com.intellij.openapi.vcs.*; +import com.intellij.openapi.vcs.history.*; +import org.apache.commons.lang.builder.*; +import org.zmlx.hg4idea.command.*; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.nio.charset.Charset; -import java.util.Date; -import java.util.Map; -import java.util.Set; +import java.io.*; +import java.nio.charset.*; +import java.util.*; public class HgFileRevision implements VcsFileRevision { private final Project project; private final HgFile hgFile; private final HgRevisionNumber vcsRevisionNumber; - - private String branchName; - private Date revisionDate; - private String author; - private String commitMessage; - private Set filesModified; - private Set filesAdded; - private Map filesCopied; - private Set filesDeleted; + private final String branchName; + private final Date revisionDate; + private final String author; + private final String commitMessage; + private final Set filesModified; + private final Set filesAdded; + private final Set filesDeleted; private byte[] content; + private Map filesCopied; - public HgFileRevision(Project project, HgFile hgFile, HgRevisionNumber vcsRevisionNumber) { + public HgFileRevision(Project project, HgFile hgFile, HgRevisionNumber vcsRevisionNumber, + String branchName, Date revisionDate, String author, String commitMessage, + Set filesModified, Set filesAdded, Set filesDeleted, Map filesCopied) { this.project = project; this.hgFile = hgFile; this.vcsRevisionNumber = vcsRevisionNumber; + this.branchName = branchName; + this.revisionDate = revisionDate; + this.author = author; + this.commitMessage = commitMessage; + this.filesModified = filesModified; + this.filesAdded = filesAdded; + this.filesDeleted = filesDeleted; + this.filesCopied = filesCopied; } public HgRevisionNumber getRevisionNumber() { @@ -68,52 +73,20 @@ public class HgFileRevision implements VcsFileRevision { return commitMessage; } - public void setBranchName(String branchName) { - this.branchName = branchName; - } - - public void setRevisionDate(Date revisionDate) { - this.revisionDate = revisionDate; - } - - public void setAuthor(String author) { - this.author = author; - } - - public void setCommitMessage(String commitMessage) { - this.commitMessage = commitMessage; - } - - public Set getFilesModified() { + public Set getModifiedFiles() { return filesModified; } - public void setFilesModified(Set filesModified) { - this.filesModified = filesModified; - } - - public Set getFilesAdded() { + public Set getAddedFiles() { return filesAdded; } - public void setFilesAdded(Set filesAdded) { - this.filesAdded = filesAdded; - } - - public Map getFilesCopied() { - return filesCopied; - } - - public void setFilesCopied(Map filesCopied) { - this.filesCopied = filesCopied; - } - - public Set getFilesDeleted() { + public Set getDeletedFiles() { return filesDeleted; } - public void setFilesDeleted(Set filesDeleted) { - this.filesDeleted = filesDeleted; + public Map getCopiedFiles() { + return filesCopied; } public void loadContent() throws VcsException { diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgIdeConfigurable.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgIdeConfigurable.java index c360e1089dd8..861d0301ff36 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgIdeConfigurable.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgIdeConfigurable.java @@ -12,14 +12,15 @@ // limitations under the License. package org.zmlx.hg4idea; -import com.intellij.openapi.options.ConfigurationException; -import com.intellij.openapi.options.SearchableConfigurable; -import org.jetbrains.annotations.Nls; -import org.zmlx.hg4idea.ui.HgConfigurationIdePanel; +import com.intellij.openapi.components.*; +import com.intellij.openapi.options.*; +import org.jetbrains.annotations.*; +import org.zmlx.hg4idea.ui.*; import javax.swing.*; -public class HgIdeConfigurable implements SearchableConfigurable { +public class HgIdeConfigurable implements ApplicationComponent, Configurable { + private final HgConfigurationIdePanel panel; public HgIdeConfigurable(HgGlobalSettings globalSettings) { @@ -59,11 +60,14 @@ public class HgIdeConfigurable implements SearchableConfigurable { public void disposeUIResources() { } - public String getId() { - return "Mercurial"; + @NotNull + public String getComponentName() { + return getClass().getName(); } - public Runnable enableSearch(String option) { - return null; + public void initComponent() { + } + + public void disposeComponent() { } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgIncomingStatusUpdater.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgIncomingStatusUpdater.java index 63d5ef6cfae0..6dc67418635b 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgIncomingStatusUpdater.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgIncomingStatusUpdater.java @@ -12,24 +12,18 @@ // limitations under the License. package org.zmlx.hg4idea; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vcs.ProjectLevelVcsManager; -import com.intellij.openapi.vcs.VcsRoot; -import com.intellij.openapi.progress.Task; -import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.openapi.application.ApplicationManager; -import org.zmlx.hg4idea.command.HgIncomingCommand; -import org.zmlx.hg4idea.ui.HgChangesetStatus; -import org.jetbrains.annotations.NotNull; +import com.intellij.openapi.application.*; +import com.intellij.openapi.progress.*; +import com.intellij.openapi.project.*; +import com.intellij.openapi.vcs.*; +import org.jetbrains.annotations.*; +import org.zmlx.hg4idea.command.*; +import org.zmlx.hg4idea.ui.*; -import java.io.File; -import java.util.LinkedList; -import java.util.List; +import java.util.*; class HgIncomingStatusUpdater implements HgUpdater { - private static final int LIMIT = 100; - private final HgChangesetStatus status; private final HgProjectSettings projectSettings; @@ -46,30 +40,28 @@ class HgIncomingStatusUpdater implements HgUpdater { public void run() { new Task.Backgroundable(project, "Checking Incoming Changesets", true) { public void run(@NotNull ProgressIndicator indicator) { - if (project.isDisposed()) return; HgIncomingCommand command = new HgIncomingCommand(project); VcsRoot[] roots = ProjectLevelVcsManager.getInstance(project).getAllVcsRoots(); - List changesets = new LinkedList(); + List changesets = new LinkedList(); for (VcsRoot root : roots) { - HgFile hgFile = new HgFile(root.path, new File(".")); - changesets.addAll(command.execute(hgFile, LIMIT - changesets.size())); + changesets.addAll(command.execute(root.path)); } status.setChanges(changesets.size(), new IncomingChangesetFormatter(changesets)); } }.queue(); } - }, project.getDisposed()); + }); } private final class IncomingChangesetFormatter implements HgChangesetStatus.ChangesetWriter { private final StringBuilder builder = new StringBuilder(); - private IncomingChangesetFormatter(List changesets) { + private IncomingChangesetFormatter(List changesets) { builder.append(""); builder.append("Incoming changesets:
"); - for (HgFileRevision changeset : changesets) { + for (HgRevisionNumber changeset : changesets) { builder - .append(changeset.getRevisionNumber().asString()).append(" ") + .append(changeset.asString()).append(" ") .append(changeset.getCommitMessage()).append(" ") .append("(").append(changeset.getAuthor()).append(")
"); } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgOutgoingStatusUpdater.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgOutgoingStatusUpdater.java index 6cf9d12d8e6b..a652ceaffbdf 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgOutgoingStatusUpdater.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgOutgoingStatusUpdater.java @@ -12,24 +12,18 @@ // limitations under the License. package org.zmlx.hg4idea; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vcs.ProjectLevelVcsManager; -import com.intellij.openapi.vcs.VcsRoot; -import com.intellij.openapi.progress.Task; -import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.openapi.application.ApplicationManager; -import org.zmlx.hg4idea.command.HgOutgoingCommand; -import org.zmlx.hg4idea.ui.HgChangesetStatus; -import org.jetbrains.annotations.NotNull; +import com.intellij.openapi.application.*; +import com.intellij.openapi.progress.*; +import com.intellij.openapi.project.*; +import com.intellij.openapi.vcs.*; +import org.jetbrains.annotations.*; +import org.zmlx.hg4idea.command.*; +import org.zmlx.hg4idea.ui.*; -import java.io.File; -import java.util.LinkedList; -import java.util.List; +import java.util.*; class HgOutgoingStatusUpdater implements HgUpdater { - private static final int LIMIT = 10; - private final HgChangesetStatus status; private final HgProjectSettings projectSettings; @@ -46,31 +40,30 @@ class HgOutgoingStatusUpdater implements HgUpdater { public void run() { new Task.Backgroundable(project, "Checking Outgoing Changesets", true) { public void run(@NotNull ProgressIndicator indicator) { - if (project.isDisposed()) return; HgOutgoingCommand command = new HgOutgoingCommand(project); VcsRoot[] roots = ProjectLevelVcsManager.getInstance(project).getAllVcsRoots(); - List outgoing = new LinkedList(); + List outgoing = new LinkedList(); for (VcsRoot root : roots) { - HgFile hgFile = new HgFile(root.path, new File(".")); - outgoing.addAll(command.execute(hgFile, LIMIT - outgoing.size())); + outgoing.addAll(command.execute(root.path)); } status.setChanges(outgoing.size(), new OutgoingChangesetFormatter(outgoing)); + indicator.stop(); } }.queue(); } - }, project.getDisposed()); + }); } private final class OutgoingChangesetFormatter implements HgChangesetStatus.ChangesetWriter { private final StringBuilder builder = new StringBuilder(); - private OutgoingChangesetFormatter(List changesets) { + private OutgoingChangesetFormatter(List changesets) { builder.append(""); builder.append("Outgoing changesets:
"); - for (HgFileRevision changeset : changesets) { + for (HgRevisionNumber revisionNumber : changesets) { builder - .append(changeset.getRevisionNumber().asString()).append(" ") - .append(changeset.getCommitMessage()).append("
"); + .append(revisionNumber.asString()).append(" ") + .append(revisionNumber.getCommitMessage()).append("
"); } builder.append(""); } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgProjectConfigurable.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgProjectConfigurable.java index ad3b27528469..5ccba0456b07 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgProjectConfigurable.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgProjectConfigurable.java @@ -12,14 +12,13 @@ // limitations under the License. package org.zmlx.hg4idea; -import com.intellij.openapi.options.ConfigurationException; -import com.intellij.openapi.options.SearchableConfigurable; -import org.jetbrains.annotations.Nls; -import org.zmlx.hg4idea.ui.HgConfigurationProjectPanel; +import com.intellij.openapi.options.*; +import org.jetbrains.annotations.*; +import org.zmlx.hg4idea.ui.*; import javax.swing.*; -public class HgProjectConfigurable implements SearchableConfigurable { +public class HgProjectConfigurable implements Configurable { private final HgConfigurationProjectPanel hgConfigurationProjectPanel; @@ -59,11 +58,4 @@ public class HgProjectConfigurable implements SearchableConfigurable { public void disposeUIResources() { } - public String getId() { - return "Mercurial.Project"; - } - - public Runnable enableSearch(String option) { - return null; - } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgRevisionNumber.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgRevisionNumber.java index f9d4ad46d030..daf72a20bf96 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgRevisionNumber.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgRevisionNumber.java @@ -12,24 +12,41 @@ // limitations under the License. package org.zmlx.hg4idea; -import com.intellij.openapi.vcs.history.VcsRevisionNumber; -import org.apache.commons.lang.builder.HashCodeBuilder; +import com.intellij.openapi.vcs.history.*; +import org.apache.commons.lang.builder.*; + +import java.util.*; public final class HgRevisionNumber implements VcsRevisionNumber { private final String revision; private final String changeset; + private final String commitMessage; + private final String author; + private final List parents; + private final boolean isWorkingVersion; + public static HgRevisionNumber getInstance(String revision, String changeset, String author, String commitMessage) { + return new HgRevisionNumber(revision, changeset, author, commitMessage, Collections.emptyList()); + } + public static HgRevisionNumber getInstance(String revision, String changeset) { - return new HgRevisionNumber(revision, changeset); + return new HgRevisionNumber(revision, changeset, "", "", Collections.emptyList()); + } + + public static HgRevisionNumber getInstance(String revision, String changeset, List parents) { + return new HgRevisionNumber(revision, changeset, "", "", parents); } public static HgRevisionNumber getLocalInstance(String revision) { - return new HgRevisionNumber(revision, ""); + return new HgRevisionNumber(revision, "", "", "", Collections.emptyList()); } - private HgRevisionNumber(String revision, String changeset) { + private HgRevisionNumber(String revision, String changeset, String author, String commitMessage, List parents) { + this.commitMessage = commitMessage; + this.author = author; + this.parents = parents; this.revision = revision.trim(); this.changeset = changeset.trim(); isWorkingVersion = changeset.endsWith("+"); @@ -43,8 +60,16 @@ public final class HgRevisionNumber implements VcsRevisionNumber { return revision; } - public int getRevisionAsInt() { - return Integer.parseInt(revision); + public long getRevisionAsLong() { + return java.lang.Long.parseLong(revision); + } + + public String getCommitMessage() { + return commitMessage; + } + + public String getAuthor() { + return author; } public boolean isWorkingVersion() { @@ -55,6 +80,10 @@ public final class HgRevisionNumber implements VcsRevisionNumber { return revision + ":" + changeset; } + public List getParents() { + return parents; + } + public int compareTo(VcsRevisionNumber o) { if (this == o) { return 0; @@ -68,8 +97,7 @@ public final class HgRevisionNumber implements VcsRevisionNumber { if (changeset.equals(hgRevisionNumber.changeset)) { return 0; } - - return getRevisionAsInt() - hgRevisionNumber.getRevisionAsInt(); + return java.lang.Long.valueOf(revision).compareTo(java.lang.Long.valueOf(hgRevisionNumber.revision)); } @Override @@ -92,4 +120,8 @@ public final class HgRevisionNumber implements VcsRevisionNumber { return compareTo(that) == 0; } + @Override + public String toString() { + return asString(); + } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgUtil.java new file mode 100644 index 000000000000..4a8e593d66b4 --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgUtil.java @@ -0,0 +1,161 @@ +// Copyright 2010 Victor Iacoban +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under +// the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions and +// limitations under the License. +package org.zmlx.hg4idea; + +import com.intellij.openapi.application.*; +import com.intellij.openapi.project.*; +import com.intellij.openapi.vcs.FilePath; +import com.intellij.openapi.vcs.changes.*; +import com.intellij.openapi.vfs.*; +import com.intellij.vcsUtil.*; + +import java.io.*; + +/** + * TODO JavaDoc. + */ +public abstract class HgUtil { + + public static File copyResourceToTempFile(String basename, String extension) throws IOException { + final InputStream in = HgUtil.class.getClassLoader().getResourceAsStream("python/" + basename + extension); + + final File tempFile = File.createTempFile(basename, extension); + final byte[] buffer = new byte[4096]; + + OutputStream out = null; + try { + out = new FileOutputStream(tempFile, false); + int bytesRead; + while ((bytesRead = in.read(buffer)) != -1) + out.write(buffer, 0, bytesRead); + } finally { + try { + out.close(); + } + catch (IOException e) { + // ignore + } + } + try { + in.close(); + } + catch (IOException e) { + // ignore + } + tempFile.deleteOnExit(); + return tempFile; + } + + public static void markDirectoryDirty( final Project project, final FilePath file ) { + Application application = ApplicationManager.getApplication(); + application.runReadAction(new Runnable() { + @Override + public void run() { + VcsDirtyScopeManager.getInstance(project).dirDirtyRecursively(file); + } + } ); + application.runWriteAction(new Runnable() { + @Override + public void run() { + VirtualFile virtualFile = VcsUtil.getVirtualFile(file.getPath()); + if (virtualFile != null) { + virtualFile.refresh(true, true); + } + } + } ); + } + + public static void markDirectoryDirty( final Project project, final VirtualFile file ) { + Application application = ApplicationManager.getApplication(); + application.runReadAction(new Runnable() { + @Override + public void run() { + VcsDirtyScopeManager.getInstance(project).dirDirtyRecursively(file); + } + } ); + application.runWriteAction(new Runnable() { + @Override + public void run() { + file.refresh(true, true); + } + } ); + } + + public static void markFileDirty( final Project project, final FilePath file ) { + Application application = ApplicationManager.getApplication(); + application.runReadAction(new Runnable() { + @Override + public void run() { + VcsDirtyScopeManager.getInstance(project).fileDirty(file); + } + } ); + application.runWriteAction(new Runnable() { + @Override + public void run() { + VirtualFile virtualFile = VcsUtil.getVirtualFile(file.getPath()); + if (virtualFile != null) { + virtualFile.refresh(true, false); + } + } + } ); + } + + public static void markFileDirty( final Project project, final VirtualFile file ) { + Application application = ApplicationManager.getApplication(); + application.runReadAction(new Runnable() { + @Override + public void run() { + VcsDirtyScopeManager.getInstance(project).fileDirty(file); + } + } ); + application.runWriteAction(new Runnable() { + @Override + public void run() { + file.refresh(true, false); + } + } ); + } + + /** + * Returns a temporary python file that will be deleted on exit. + * + * Also all compiled version of the python file will be deleted. + * + * @param base The basename of the file to copy + * @return The temporary copy the specified python file, with all the necessary hooks installed + * to make sure it is completely removed at shutdown + */ + public static File getTemporaryPythonFile(String base) { + try { + final File file = copyResourceToTempFile(base, ".py"); + final String fileName = file.getName(); + Runtime.getRuntime().addShutdownHook(new Thread(){ + @Override + public void run() { + File[] files = file.getParentFile().listFiles(new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + return name.startsWith(fileName); + } + }); + for (File file1 : files) { + file1.delete(); + } + } + }); + return file; + } catch (IOException e) { + return null; + } + } +} diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java index e90361de79b7..75e93431f2f2 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java @@ -12,44 +12,30 @@ // limitations under the License. package org.zmlx.hg4idea; -import com.intellij.concurrency.JobScheduler; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.fileEditor.FileEditorManagerAdapter; -import com.intellij.openapi.fileEditor.FileEditorManagerEvent; -import com.intellij.openapi.fileEditor.FileEditorManagerListener; -import com.intellij.openapi.options.Configurable; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.IconLoader; -import com.intellij.openapi.vcs.AbstractVcs; -import com.intellij.openapi.vcs.CommittedChangesProvider; -import com.intellij.openapi.vcs.ProjectLevelVcsManager; -import com.intellij.openapi.vcs.annotate.AnnotationProvider; -import com.intellij.openapi.vcs.changes.ChangeListManager; -import com.intellij.openapi.vcs.changes.ChangeProvider; -import com.intellij.openapi.vcs.checkin.CheckinEnvironment; -import com.intellij.openapi.vcs.diff.DiffProvider; -import com.intellij.openapi.vcs.history.VcsHistoryProvider; -import com.intellij.openapi.vcs.rollback.RollbackEnvironment; -import com.intellij.openapi.vcs.update.UpdateEnvironment; -import com.intellij.openapi.vfs.LocalFileSystem; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.wm.StatusBar; -import com.intellij.openapi.wm.WindowManager; -import com.intellij.util.messages.MessageBus; -import com.intellij.util.messages.MessageBusConnection; -import com.intellij.util.messages.Topic; +import com.intellij.concurrency.*; +import com.intellij.openapi.fileEditor.*; +import com.intellij.openapi.options.*; +import com.intellij.openapi.project.*; +import com.intellij.openapi.util.*; +import com.intellij.openapi.vcs.*; +import com.intellij.openapi.vcs.annotate.*; +import com.intellij.openapi.vcs.changes.*; +import com.intellij.openapi.vcs.checkin.*; +import com.intellij.openapi.vcs.diff.*; +import com.intellij.openapi.vcs.history.*; +import com.intellij.openapi.vcs.rollback.*; +import com.intellij.openapi.vcs.update.*; +import com.intellij.openapi.vfs.*; +import com.intellij.openapi.wm.*; +import com.intellij.util.messages.*; import org.zmlx.hg4idea.provider.*; -import org.zmlx.hg4idea.provider.annotate.HgAnnotationProvider; -import org.zmlx.hg4idea.provider.commit.HgCheckinEnvironment; -import org.zmlx.hg4idea.provider.commit.HgCommitExecutor; -import org.zmlx.hg4idea.provider.update.HgIntegrateEnvironment; -import org.zmlx.hg4idea.provider.update.HgUpdateEnvironment; -import org.zmlx.hg4idea.ui.HgChangesetStatus; -import org.zmlx.hg4idea.ui.HgCurrentBranchStatus; +import org.zmlx.hg4idea.provider.annotate.*; +import org.zmlx.hg4idea.provider.commit.*; +import org.zmlx.hg4idea.provider.update.*; +import org.zmlx.hg4idea.ui.*; import javax.swing.*; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.*; public class HgVcs extends AbstractVcs { @@ -89,6 +75,8 @@ public class HgVcs extends AbstractVcs { private final HgGlobalSettings globalSettings; private final HgProjectSettings projectSettings; + private boolean started = false; + public HgVcs(Project project, HgGlobalSettings globalSettings, HgProjectSettings projectSettings) { super(project, VCS_NAME); @@ -118,21 +106,37 @@ public class HgVcs extends AbstractVcs { @Override public ChangeProvider getChangeProvider() { + if (!started) { + return null; + } + return changeProvider; } @Override public RollbackEnvironment getRollbackEnvironment() { + if (!started) { + return null; + } + return rollbackEnvironment; } @Override public DiffProvider getDiffProvider() { + if (!started) { + return null; + } + return diffProvider; } @Override public VcsHistoryProvider getVcsHistoryProvider() { + if (!started) { + return null; + } + return historyProvider; } @@ -143,31 +147,55 @@ public class HgVcs extends AbstractVcs { @Override public CheckinEnvironment getCheckinEnvironment() { + if (!started) { + return null; + } + return checkinEnvironment; } @Override public AnnotationProvider getAnnotationProvider() { + if (!started) { + return null; + } + return annotationProvider; } @Override public UpdateEnvironment getUpdateEnvironment() { + if (!started) { + return null; + } + return updateEnvironment; } @Override public UpdateEnvironment getIntegrateEnvironment() { + if (!started) { + return null; + } + return integrateEnvironment; } @Override public CommittedChangesProvider getCommittedChangesProvider() { - return commitedChangesProvider; + if (!started) { + return null; + } + return null; +// return commitedChangesProvider; } @Override public boolean isVersionedDirectory(VirtualFile dir) { + if (!started) { + return false; + } + VirtualFile currentDir = dir; while (currentDir != null) { if (currentDir.findFileByRelativePath(".hg") != null) { @@ -178,27 +206,27 @@ public class HgVcs extends AbstractVcs { return false; } + public boolean isStarted() { + return started; + } + @Override - protected void activate() { - ApplicationManager.getApplication().invokeLater(new Runnable() { - public void run() { - if (!validateHgExecutable()) { - return; - } - addListeners(); - } - }, myProject.getDisposed()); + protected void start() throws VcsException { + HgExecutableValidator validator = new HgExecutableValidator(myProject); + started = validator.check(globalSettings); } - public boolean validateHgExecutable() { - return (new HgExecutableValidator(myProject)).check(globalSettings); + @Override + protected void shutdown() throws VcsException { + started = false; } - public static HgVcs getInstance(Project project) { - return (HgVcs) ProjectLevelVcsManager.getInstance(project).findVcsByName(VCS_NAME); - } + @Override + public void activate() { + if (!started) { + return; + } - public void addListeners() { LocalFileSystem.getInstance().addVirtualFileListener(virtualFileListener); ChangeListManager.getInstance(myProject).registerCommitExecutor(commitExecutor); @@ -249,6 +277,10 @@ public class HgVcs extends AbstractVcs { @Override public void deactivate() { + if (!started) { + return; + } + LocalFileSystem.getInstance().removeVirtualFileListener(virtualFileListener); StatusBar statusBar = WindowManager.getInstance().getStatusBar(myProject); if (messageBusConnection != null) { @@ -264,4 +296,8 @@ public class HgVcs extends AbstractVcs { } } + public static HgVcs getInstance(Project project) { + return (HgVcs) ProjectLevelVcsManager.getInstance(project).findVcsByName(VCS_NAME); + } + } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgVirtualFileListener.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgVirtualFileListener.java index 8d3409179a4f..c1445965d595 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgVirtualFileListener.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgVirtualFileListener.java @@ -12,32 +12,20 @@ // limitations under the License. package org.zmlx.hg4idea; -import com.intellij.openapi.fileTypes.FileTypeManager; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vcs.AbstractVcs; -import com.intellij.openapi.vcs.AbstractVcsHelper; -import com.intellij.openapi.vcs.FileStatus; -import com.intellij.openapi.vcs.FileStatusManager; -import com.intellij.openapi.vcs.ProjectLevelVcsManager; -import com.intellij.openapi.vcs.VcsConfiguration; -import com.intellij.openapi.vcs.VcsShowConfirmationOption; -import static com.intellij.openapi.vcs.VcsShowConfirmationOption.Value.DO_ACTION_SILENTLY; -import static com.intellij.openapi.vcs.VcsShowConfirmationOption.Value.SHOW_CONFIRMATION; -import com.intellij.openapi.vcs.changes.ChangeListManager; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.vfs.VirtualFileAdapter; -import com.intellij.openapi.vfs.VirtualFileCopyEvent; -import com.intellij.openapi.vfs.VirtualFileEvent; -import com.intellij.openapi.vfs.VirtualFileMoveEvent; -import com.intellij.openapi.vfs.VirtualFilePropertyEvent; -import com.intellij.vcsUtil.VcsUtil; -import org.zmlx.hg4idea.command.HgAddCommand; -import org.zmlx.hg4idea.command.HgCopyCommand; -import org.zmlx.hg4idea.command.HgMoveCommand; -import org.zmlx.hg4idea.command.HgRemoveCommand; +import com.intellij.openapi.fileTypes.*; +import com.intellij.openapi.project.*; +import com.intellij.openapi.vcs.*; +import com.intellij.openapi.vcs.FilePath; +import com.intellij.openapi.vcs.changes.*; +import com.intellij.openapi.vfs.*; +import com.intellij.vcsUtil.*; +import org.jetbrains.annotations.*; +import org.zmlx.hg4idea.command.*; -import java.io.File; -import java.util.Arrays; +import java.io.*; +import java.util.*; + +import static com.intellij.openapi.vcs.VcsShowConfirmationOption.Value.*; public class HgVirtualFileListener extends VirtualFileAdapter { @@ -54,25 +42,56 @@ public class HgVirtualFileListener extends VirtualFileAdapter { if (event.isFromRefresh()) { return; } - final VirtualFile file = event.getFile(); - if (!VcsUtil.isFileForVcs(file, project, vcs)) { - return; - } - if (!isFileProcessable(file)) { - return; + final VirtualFile newFile = event.getFile(); + FilePath newPath = getFilePath(newFile); + VirtualFile newRepo = VcsUtil.getVcsRootFor(project, newFile); + boolean newFileProcessable = newRepo != null && VcsUtil.isFileForVcs(newFile, project, vcs) && isFileProcessable(newFile); + + final VirtualFile oldFile = event.getOriginalFile(); + FilePath oldPath = getFilePath(oldFile); + VirtualFile oldRepo = VcsUtil.getVcsRootFor(project, oldFile); + boolean oldFileProcessable = oldRepo != null && VcsUtil.isFileForVcs(oldFile, project, vcs) && isFileProcessable(oldFile); + + if (newFileProcessable && oldFileProcessable && oldRepo.equals(newRepo)) { + copyFile(newRepo, oldPath, newPath); + markDirty(newPath); + } else if (newFileProcessable) { + addFile(newRepo, newPath, false); + markDirty(newPath); } + } + + @Override + public void fileMoved(VirtualFileMoveEvent event) { + VirtualFile oldParent = event.getOldParent(); + String fileName = event.getFileName(); + + FilePath oldPath = VcsUtil.getFilePath(new File(new File(oldParent.getPath()), fileName)); + VirtualFile oldRepo = VcsUtil.getVcsRootFor(project, oldPath); + boolean oldFileProcessable = oldRepo != null && VcsUtil.isFileForVcs(oldPath, project, vcs) && isFileProcessable(oldPath); VirtualFile newFile = event.getFile(); - VirtualFile oldFile = event.getOriginalFile(); - VirtualFile repo = VcsUtil.getVcsRootFor(project, file); - if (repo == null) { - return; + FilePath newPath = getFilePath(newFile); + VirtualFile newRepo = VcsUtil.getVcsRootFor(project, newFile); + boolean newFileProcessable = newRepo != null && VcsUtil.isFileForVcs(newFile, project, vcs) && isFileProcessable(newFile); + + if (newFileProcessable && oldFileProcessable && oldRepo.equals(newRepo)) { + moveFile(oldRepo, newRepo, oldPath, newPath); + } else { + HgFileStatusEnum oldStatus = getStatus(oldRepo, oldPath); + boolean silent = oldStatus != HgFileStatusEnum.UNVERSIONED; + + if (oldFileProcessable) { + deleteFile(oldRepo, oldPath, silent); + } + + if (newFileProcessable) { + addFile(newRepo, newPath, silent); + } } - HgCopyCommand command = new HgCopyCommand(project); - HgFile source = new HgFile(repo, new File(oldFile.getPath())); - HgFile target = new HgFile(repo, new File(newFile.getPath())); - command.execute(source, target); + markDirty(oldPath); + markDirty(newPath); } @Override @@ -88,25 +107,14 @@ public class HgVirtualFileListener extends VirtualFileAdapter { return; } - String title = HgVcsMessages.message("hg4idea.add.confirmation.title"); - String message = HgVcsMessages.message("hg4idea.add.confirmation.body", file.getPath()); - - VcsShowConfirmationOption option = ProjectLevelVcsManager.getInstance(project) - .getStandardConfirmation(VcsConfiguration.StandardConfirmation.ADD, vcs); - - boolean processAdd = false; - if (DO_ACTION_SILENTLY == option.getValue()) { - processAdd = true; - } else if (SHOW_CONFIRMATION == option.getValue()) { - AbstractVcsHelper helper = AbstractVcsHelper.getInstance(project); - processAdd = null != helper.selectFilesToProcess( - Arrays.asList(file), title, null, title, message, option - ); - } VirtualFile repo = VcsUtil.getVcsRootFor(project, file); - if (processAdd && repo != null) { - new HgAddCommand(project).execute(new HgFile(repo, new File(file.getPath()))); + if (repo == null) { + return; } + + FilePath path = getFilePath(file); + addFile(repo, path, false); + markDirty(path); } @Override @@ -116,53 +124,19 @@ public class HgVirtualFileListener extends VirtualFileAdapter { } final VirtualFile file = event.getFile(); - if (!VcsUtil.isFileForVcs(file, project, vcs)) { + + if (!shouldProcess(file)) { return; } - if (!isFileProcessable(file)) { - return; - } - - FileStatus status = FileStatusManager.getInstance(project).getStatus(file); - if (status == FileStatus.UNKNOWN || status == FileStatus.IGNORED) { - return; - } - - String title = HgVcsMessages.message("hg4idea.delete.confirmation.title"); - String message = HgVcsMessages.message("hg4idea.delete.confirmation.body", file.getPath()); - - VcsShowConfirmationOption option = ProjectLevelVcsManager.getInstance(project) - .getStandardConfirmation(VcsConfiguration.StandardConfirmation.REMOVE, vcs); - - boolean processDelete = false; - if (DO_ACTION_SILENTLY == option.getValue()) { - processDelete = true; - } else if (SHOW_CONFIRMATION == option.getValue()) { - AbstractVcsHelper helper = AbstractVcsHelper.getInstance(project); - processDelete = null != helper.selectFilesToProcess( - Arrays.asList(file), title, null, title, message, option - ); - } VirtualFile repo = VcsUtil.getVcsRootFor(project, file); - if (processDelete && repo != null) { - new HgRemoveCommand(project).execute(new HgFile(repo, new File(file.getPath()))); - } - } - - @Override - public void fileMoved(VirtualFileMoveEvent event) { - VirtualFile newParent = event.getNewParent(); - VirtualFile oldParent = event.getOldParent(); - String fileName = event.getFileName(); - VirtualFile repo = VcsUtil.getVcsRootFor(project, event.getFile()); if (repo == null) { return; } - HgMoveCommand command = new HgMoveCommand(project); - HgFile source = new HgFile(repo, new File(oldParent.getPath(), fileName)); - HgFile target = new HgFile(repo, new File(newParent.getPath(), fileName)); - command.execute(source, target); + + FilePath path = getFilePath(file); + deleteFile(repo, path, false); + markDirty(path); } @Override @@ -173,18 +147,125 @@ public class HgVirtualFileListener extends VirtualFileAdapter { } private void fileRenamed(VirtualFilePropertyEvent event) { - VirtualFile file = event.getFile(); - VirtualFile parent = file.getParent(); String oldName = (String) event.getOldValue(); - String newName = (String) event.getNewValue(); - VirtualFile repo = VcsUtil.getVcsRootFor(project, file); - if (repo == null || parent == null) { + VirtualFile oldParent = event.getParent(); + + FilePath oldPath = VcsUtil.getFilePath(new File(new File(oldParent.getPath()), oldName)); + VirtualFile oldRepo = VcsUtil.getVcsRootFor(project, oldPath); + boolean oldFileProcessable = oldRepo != null && VcsUtil.isFileForVcs(oldPath, project, vcs) && isFileProcessable(oldPath); + + VirtualFile newFile = event.getFile(); + FilePath newPath = getFilePath(newFile); + VirtualFile newRepo = VcsUtil.getVcsRootFor(project, newFile); + boolean newFileProcessable = newRepo != null && VcsUtil.isFileForVcs(newFile, project, vcs) && isFileProcessable(newFile); + + if (newFileProcessable && oldFileProcessable && oldRepo.equals(newRepo)) { + renameFile(newRepo, oldPath, newPath); + } else { + if (oldFileProcessable) { + deleteFile(oldRepo, oldPath, false); + } + + if (newFileProcessable) { + addFile(newRepo, newPath, false); + } + } + markDirty(oldPath); + markDirty(newPath); + } + + private void markDirty(final FilePath path) { + HgUtil.markDirectoryDirty(project, path.getParentPath()); + } + + private FilePath getFilePath(VirtualFile file) { + return VcsUtil.getFilePath(file.getPath()); + } + + private void addFile(@NotNull VirtualFile repo, @NotNull FilePath path, boolean silent) { + if (silent || checkAdd(path)) { + new HgAddCommand(project).execute(new HgFile(repo, path)); + } + } + + private void copyFile(VirtualFile repo, FilePath oldPath, FilePath newPath) { + if (checkAdd(newPath)) { + HgCopyCommand command = new HgCopyCommand(project); + HgFile source = new HgFile(repo, oldPath); + HgFile target = new HgFile(repo, newPath); + command.execute(source, target); + } + } + + private void moveFile(@NotNull VirtualFile repo, VirtualFile newRepo, @NotNull FilePath oldPath, @NotNull FilePath newPath) { + HgMoveCommand command = new HgMoveCommand(project); + HgFile source = new HgFile(repo, oldPath); + HgFile target = new HgFile(repo, newPath); + command.execute(source, target); + } + + private void renameFile(@NotNull VirtualFile repo, @NotNull FilePath oldPath, @NotNull FilePath newPath) { + HgMoveCommand command = new HgMoveCommand(project); + HgFile source = new HgFile(repo, oldPath); + HgFile target = new HgFile(repo, newPath); + command.execute(source, target); + } + + private boolean checkAdd(FilePath path) { + String title = HgVcsMessages.message("hg4idea.add.confirmation.title"); + String message = HgVcsMessages.message("hg4idea.add.confirmation.body", path.getPath()); + + VcsShowConfirmationOption option = ProjectLevelVcsManager.getInstance(project) + .getStandardConfirmation(VcsConfiguration.StandardConfirmation.ADD, vcs); + + boolean processAdd = false; + if (DO_ACTION_SILENTLY == option.getValue()) { + processAdd = true; + } else if (SHOW_CONFIRMATION == option.getValue()) { + AbstractVcsHelper helper = AbstractVcsHelper.getInstance(project); + processAdd = null != helper.selectFilePathsToProcess( + Arrays.asList(path), title, null, title, message, option + ); + } + return processAdd; + } + + private void deleteFile(@NotNull VirtualFile repo, @NotNull FilePath path, boolean silent) { + HgFileStatusEnum status = getStatus(repo, path); + if (status == HgFileStatusEnum.UNVERSIONED || status == HgFileStatusEnum.IGNORED) { return; } - HgMoveCommand command = new HgMoveCommand(project); - HgFile source = new HgFile(repo, new File(parent.getPath(), oldName)); - HgFile target = new HgFile(repo, new File(parent.getPath(), newName)); - command.execute(source, target); + + String title = HgVcsMessages.message("hg4idea.delete.confirmation.title"); + String message = HgVcsMessages.message("hg4idea.delete.confirmation.body", path.getPath()); + + boolean processDelete = false; + + VcsShowConfirmationOption option = ProjectLevelVcsManager.getInstance(project) + .getStandardConfirmation(VcsConfiguration.StandardConfirmation.REMOVE, vcs); + + if (DO_ACTION_SILENTLY == option.getValue() || status == HgFileStatusEnum.ADDED || silent) { + processDelete = true; + } else if (SHOW_CONFIRMATION == option.getValue()) { + AbstractVcsHelper helper = AbstractVcsHelper.getInstance(project); + processDelete = null != helper.selectFilePathsToProcess( + Arrays.asList(path), title, null, title, message, option + ); + } + + if (processDelete) { + new HgRemoveCommand(project).execute(new HgFile(repo, path)); + } + } + + private HgFileStatusEnum getStatus(VirtualFile repo, FilePath file) { + HgStatusCommand status = new HgStatusCommand(project); + HgChange change = status.execute(repo, file.getPath()); + return change != null ? change.getStatus() : HgFileStatusEnum.UNVERSIONED; + } + + private boolean shouldProcess(VirtualFile file) { + return VcsUtil.isFileForVcs(file, project, vcs) && isFileProcessable(file); } private boolean isFileProcessable(VirtualFile file) { @@ -196,4 +277,10 @@ public class HgVirtualFileListener extends VirtualFileAdapter { || !changeListManager.isIgnoredFile(file); } + private boolean isFileProcessable(FilePath file) { + if (file == null) { + return false; + } + return !FileTypeManager.getInstance().isFileIgnored(file.getName()); + } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractFilesAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractFilesAction.java index 1ee4986c3dd5..c4d3e2b033fe 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractFilesAction.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractFilesAction.java @@ -13,18 +13,13 @@ package org.zmlx.hg4idea.action; import com.intellij.openapi.actionSystem.*; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vcs.AbstractVcsHelper; -import com.intellij.openapi.vcs.ProjectLevelVcsManager; -import com.intellij.openapi.vcs.TransactionRunnable; -import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager; -import com.intellij.openapi.vfs.VirtualFile; -import org.zmlx.hg4idea.HgVcs; +import com.intellij.openapi.application.*; +import com.intellij.openapi.project.*; +import com.intellij.openapi.vcs.*; +import com.intellij.openapi.vfs.*; +import org.zmlx.hg4idea.*; -import java.util.LinkedList; -import java.util.List; +import java.util.*; abstract class HgAbstractFilesAction extends AnAction { @@ -44,7 +39,7 @@ abstract class HgAbstractFilesAction extends AnAction { project.save(); - final HgVcs vcs = HgVcs.getInstance(project); + final HgVcs vcs = getHgVcs(project); if (!ProjectLevelVcsManager.getInstance(project).checkAllFilesAreUnder(vcs, files)) { return; } @@ -81,7 +76,12 @@ abstract class HgAbstractFilesAction extends AnAction { return; } - final HgVcs vcs = HgVcs.getInstance(project); + HgVcs vcs = getHgVcs(project); + if (!vcs.isStarted()) { + presentation.setEnabled(false); + return; + } + if (!ProjectLevelVcsManager.getInstance(project).checkAllFilesAreUnder(vcs, files)) { presentation.setEnabled(false); return; @@ -120,12 +120,12 @@ abstract class HgAbstractFilesAction extends AnAction { }); for (VirtualFile file : enabledFiles) { - doVcsRefresh(project, file); + HgUtil.markFileDirty(project, file); } } - private void doVcsRefresh(final Project project, final VirtualFile file) { - VcsDirtyScopeManager.getInstance(project).fileDirty(file); + private HgVcs getHgVcs(Project project) { + return (HgVcs) ProjectLevelVcsManager.getInstance(project).findVcsByName(HgVcs.VCS_NAME); } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalAction.java index 5dc7564d49a5..ac4f59b2d72c 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalAction.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalAction.java @@ -13,19 +13,15 @@ package org.zmlx.hg4idea.action; import com.intellij.openapi.actionSystem.*; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vcs.ProjectLevelVcsManager; -import com.intellij.openapi.vcs.VcsRoot; -import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.vcsUtil.VcsUtil; -import org.jetbrains.annotations.Nullable; -import org.zmlx.hg4idea.HgVcs; -import org.zmlx.hg4idea.command.HgCommandException; +import com.intellij.openapi.project.*; +import com.intellij.openapi.vcs.*; +import com.intellij.openapi.vfs.*; +import com.intellij.vcsUtil.*; +import org.jetbrains.annotations.*; +import org.zmlx.hg4idea.*; +import org.zmlx.hg4idea.command.*; -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; +import java.util.*; abstract class HgAbstractGlobalAction extends AnAction { @@ -47,9 +43,8 @@ abstract class HgAbstractGlobalAction extends AnAction { } catch (HgCommandException e) { VcsUtil.showErrorMessage(project, e.getMessage(), "Error"); } - VcsDirtyScopeManager vcsDirtyScopeManager = VcsDirtyScopeManager.getInstance(project); - vcsDirtyScopeManager.dirDirtyRecursively(command.getRepo()); - command.getRepo().refresh(true, true); + + HgUtil.markDirectoryDirty(project,command.getRepo()); } @Override @@ -64,6 +59,12 @@ abstract class HgAbstractGlobalAction extends AnAction { presentation.setEnabled(false); return; } + + HgVcs vcs = (HgVcs) ProjectLevelVcsManager.getInstance(project).findVcsByName(HgVcs.VCS_NAME); + + if (!vcs.isStarted()) { + presentation.setEnabled(false); + } } private List findRepos(Project project) { diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgMarkResolved.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgMarkResolved.java index 23e23f04806e..ae1f355ede56 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgMarkResolved.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgMarkResolved.java @@ -12,17 +12,15 @@ // limitations under the License. package org.zmlx.hg4idea.action; -import com.intellij.openapi.actionSystem.DataContext; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vcs.FileStatus; -import com.intellij.openapi.vcs.FileStatusManager; -import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.vcsUtil.VcsUtil; -import org.zmlx.hg4idea.HgVcs; -import org.zmlx.hg4idea.command.HgResolveCommand; +import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.project.*; +import com.intellij.openapi.vcs.*; +import com.intellij.openapi.vfs.*; +import com.intellij.vcsUtil.*; +import org.zmlx.hg4idea.*; +import org.zmlx.hg4idea.command.*; -import java.util.List; +import java.util.*; public class HgMarkResolved extends HgAbstractFilesAction { @@ -39,7 +37,7 @@ public class HgMarkResolved extends HgAbstractFilesAction { if (root == null) { return; } - resolveCommand.resolve(root, file); + resolveCommand.markResolved(root, file); } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgMercurialMenu.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgMercurialMenu.java index 603d428f0220..785bd53a078c 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgMercurialMenu.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgMercurialMenu.java @@ -12,11 +12,10 @@ // limitations under the License. package org.zmlx.hg4idea.action; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vcs.AbstractVcs; -import com.intellij.openapi.vcs.ProjectLevelVcsManager; -import com.intellij.openapi.vcs.actions.StandardVcsGroup; -import org.zmlx.hg4idea.HgVcs; +import com.intellij.openapi.project.*; +import com.intellij.openapi.vcs.*; +import com.intellij.openapi.vcs.actions.*; +import org.zmlx.hg4idea.*; public class HgMercurialMenu extends StandardVcsGroup { @@ -24,4 +23,8 @@ public class HgMercurialMenu extends StandardVcsGroup { return ProjectLevelVcsManager.getInstance(project).findVcsByName(HgVcs.VCS_NAME); } + @Override + public String getVcsName(Project project) { + return HgVcs.VCS_NAME; + } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgMqRebaseAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgMqRebaseAction.java index 44ea05ed37d9..7471680491aa 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgMqRebaseAction.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgMqRebaseAction.java @@ -12,25 +12,15 @@ // limitations under the License. package org.zmlx.hg4idea.action; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vfs.VirtualFile; -import org.apache.commons.lang.StringUtils; -import org.zmlx.hg4idea.HgFile; -import org.zmlx.hg4idea.HgRevisionNumber; -import org.zmlx.hg4idea.command.HgHeadsCommand; -import org.zmlx.hg4idea.command.HgMQCommand; -import org.zmlx.hg4idea.command.HgPullCommand; -import org.zmlx.hg4idea.command.HgRebaseCommand; -import org.zmlx.hg4idea.command.HgResolveCommand; -import org.zmlx.hg4idea.command.HgResolveStatusEnum; -import org.zmlx.hg4idea.command.HgTagBranchCommand; -import org.zmlx.hg4idea.provider.update.HgConflictResolver; -import org.zmlx.hg4idea.ui.HgPullDialog; +import com.intellij.openapi.project.*; +import com.intellij.openapi.vfs.*; +import org.apache.commons.lang.*; +import org.zmlx.hg4idea.*; +import org.zmlx.hg4idea.command.*; +import org.zmlx.hg4idea.provider.update.*; +import org.zmlx.hg4idea.ui.*; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; +import java.util.*; public class HgMqRebaseAction extends HgAbstractGlobalAction { @@ -73,11 +63,7 @@ public class HgMqRebaseAction extends HgAbstractGlobalAction { return; } - List heads = - new HgHeadsCommand(project, repository).execute(currentBranch); - - new HgConflictResolver(project, Collections.max(heads), Collections.min(heads)) - .resolve(repository); + new HgConflictResolver(project).resolve(repository); HgResolveCommand resolveCommand = new HgResolveCommand(project); Map status = resolveCommand.list(repository); diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgRunConflictResolverAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgRunConflictResolverAction.java index 987ce87eba9a..1652e0a5f7af 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgRunConflictResolverAction.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgRunConflictResolverAction.java @@ -12,52 +12,55 @@ // limitations under the License. package org.zmlx.hg4idea.action; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vfs.VirtualFile; -import org.zmlx.hg4idea.HgRevisionNumber; -import org.zmlx.hg4idea.command.HgHeadsCommand; -import org.zmlx.hg4idea.command.HgTagBranchCommand; -import org.zmlx.hg4idea.provider.update.HgConflictResolver; -import org.zmlx.hg4idea.ui.HgRunConflictResolverDialog; +import com.intellij.openapi.project.*; +import com.intellij.openapi.vfs.*; +import org.zmlx.hg4idea.provider.update.*; +import org.zmlx.hg4idea.ui.*; -import java.util.Collection; -import java.util.Collections; -import java.util.List; +import java.util.*; public class HgRunConflictResolverAction extends HgAbstractGlobalAction { protected HgGlobalCommandBuilder getHgGlobalCommandBuilder(final Project project) { return new HgGlobalCommandBuilder() { public HgGlobalCommand build(Collection repos) { - HgRunConflictResolverDialog dialog = new HgRunConflictResolverDialog(project); - dialog.setRoots(repos); - dialog.show(); - - if (dialog.isOK()) { - return buildCommand(dialog, project); + VirtualFile repository; + if (repos.size() > 1) { + repository = letUserSelectRepository(repos, project); } - return null; + else if (repos.size() == 1) { + repository = repos.iterator().next(); + } else { + repository = null; + } + if (repository != null) { + return buildResolverCommand(project, repository); + } + else return null; } }; } - private HgGlobalCommand buildCommand(HgRunConflictResolverDialog dialog, final Project project) { - final VirtualFile repository = dialog.getRepository(); + private VirtualFile letUserSelectRepository(Collection repos, Project project) { + HgRunConflictResolverDialog dialog = new HgRunConflictResolverDialog(project); + dialog.setRoots(repos); + dialog.show(); + + if (dialog.isOK()) { + return dialog.getRepository(); + } else { + return null; + } + } + + private HgGlobalCommand buildResolverCommand(final Project project, final VirtualFile repository) { return new HgGlobalCommand() { public VirtualFile getRepo() { return repository; } public void execute() { - String currentBranch = new HgTagBranchCommand(project, repository).getCurrentBranch(); - if (currentBranch == null) { - return; - } - List heads = - new HgHeadsCommand(project, repository).execute(currentBranch); - - new HgConflictResolver(project, Collections.max(heads), Collections.min(heads)) - .resolve(repository); + new HgConflictResolver(project).resolve(repository); } }; } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCatCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCatCommand.java index 824e7e5199de..551c81610d32 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCatCommand.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCatCommand.java @@ -12,15 +12,12 @@ // limitations under the License. package org.zmlx.hg4idea.command; -import com.intellij.openapi.project.Project; -import org.apache.commons.lang.StringUtils; -import org.zmlx.hg4idea.HgFile; -import org.zmlx.hg4idea.HgRevisionNumber; +import com.intellij.openapi.project.*; +import org.apache.commons.lang.*; +import org.zmlx.hg4idea.*; -import java.nio.charset.Charset; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; +import java.nio.charset.*; +import java.util.*; public class HgCatCommand { @@ -31,18 +28,77 @@ public class HgCatCommand { } public String execute(HgFile hgFile, HgRevisionNumber vcsRevisionNumber, Charset charset) { - List arguments = new LinkedList(); - if (StringUtils.isNotBlank(vcsRevisionNumber.getChangeset())) { - arguments.add("--rev"); - arguments.add(vcsRevisionNumber.getChangeset()); - } - arguments.add(hgFile.getRelativePath()); + List arguments = createArguments(vcsRevisionNumber, hgFile.getRelativePath()); HgCommandService service = HgCommandService.getInstance(project); HgCommandResult result = service.execute( hgFile.getRepo(), Collections.emptyList(), "cat", arguments, charset ); + + if (result.getExitValue() == 1) { + // file not found in given revision + return getContentFollowingRenames(hgFile, vcsRevisionNumber, charset, service); + } + return result.getRawOutput(); } + private String getContentFollowingRenames(HgFile hgFile, HgRevisionNumber vcsRevisionNumber, Charset charset, HgCommandService service) { + String currentRevision = getCurrentRevision(hgFile); + + HgTrackFileNamesAccrossRevisionsCommand trackCommand = new HgTrackFileNamesAccrossRevisionsCommand(project); + String renamedHgFile = trackCommand.execute(hgFile, currentRevision, vcsRevisionNumber.getRevision(), -1); + + if (renamedHgFile != null) { + List arguments = createArguments(vcsRevisionNumber, renamedHgFile); + + HgCommandResult result = service.execute( + hgFile.getRepo(), Collections.emptyList(), "cat", arguments, charset + ); + + return result.getRawOutput(); + } + + return ""; + } + + private String getCurrentRevision(HgFile hgFile) { + HgParentsCommand parentsCommand = new HgParentsCommand(project); + List parents = parentsCommand.execute(hgFile.getRepo()); + + String currentRevision = "0"; + + if (parents.size() == 1) { + currentRevision = parents.get(0).getRevision(); + } else if (parents.size() > 1) { + long maxParentNumber = Long.MIN_VALUE; + + for (HgRevisionNumber revisionNumber : parents) { + long revisionAsLong = revisionNumber.getRevisionAsLong(); + + if (revisionAsLong > maxParentNumber) { + maxParentNumber = revisionAsLong; + currentRevision = revisionNumber.getRevision(); + } + } + } + + return currentRevision; + } + + private List createArguments(HgRevisionNumber vcsRevisionNumber, String fileName) { + List arguments = new LinkedList(); + if (vcsRevisionNumber != null) { + arguments.add("--rev"); + if (StringUtils.isNotBlank(vcsRevisionNumber.getChangeset())) { + arguments.add(vcsRevisionNumber.getChangeset()); + } else { + arguments.add(vcsRevisionNumber.getRevision()); + } + } + + arguments.add(fileName); + return arguments; + } + } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgChangesetsCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgChangesetsCommand.java new file mode 100644 index 000000000000..3e446a880678 --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgChangesetsCommand.java @@ -0,0 +1,80 @@ +// Copyright 2008-2010 Victor Iacoban +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under +// the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions and +// limitations under the License. +package org.zmlx.hg4idea.command; + +import com.intellij.openapi.diagnostic.*; +import com.intellij.openapi.project.*; +import com.intellij.openapi.vfs.*; +import org.apache.commons.lang.*; +import org.zmlx.hg4idea.*; + +import java.util.*; + +/** + * Abstract base class for all commands that need to parse changeset information. + */ +public abstract class HgChangesetsCommand { + + private static final Logger LOG = Logger.getInstance(HgChangesetsCommand.class.getName()); + + private static final String SEPARATOR_STRING = "\u0017"; //ascii: end of transmission block + + private final Project project; + private final String command; + + public HgChangesetsCommand(Project project, String command) { + this.project = project; + this.command = command; + } + + public List execute(VirtualFile repo) { + return getRevisions(repo); + } + + protected List getRevisions(VirtualFile repo) { + HgCommandService commandService = HgCommandService.getInstance(project); + + + List args = new ArrayList(Arrays.asList( + "--template", + "{rev}|{node|short}|{author}|{desc|firstline}" + SEPARATOR_STRING + )); + + addArguments(args); + + HgCommandResult result = commandService.execute( + repo, Arrays.asList("--quiet"), command, args + ); + + String output = result.getRawOutput(); + if (StringUtils.isEmpty(output)) { + return Collections.emptyList(); + } + + String[] changesets = output.split(SEPARATOR_STRING); + List revisions = new ArrayList(changesets.length); + + for(String changeset: changesets) { + String[] parts = StringUtils.split(changeset, "|", 4); + if (parts.length == 4) { + revisions.add(HgRevisionNumber.getInstance(parts[0], parts[1], parts[2], parts[3])); + } else { + LOG.warn("Could not parse changeset [" + changeset + "]"); + } + } + + return revisions; + } + + protected abstract void addArguments(List args); +} diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCloneCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCloneCommand.java new file mode 100644 index 000000000000..5916b94c7b87 --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCloneCommand.java @@ -0,0 +1,41 @@ +package org.zmlx.hg4idea.command; + +import com.intellij.openapi.project.*; + +import java.nio.charset.*; +import java.util.*; + +public class HgCloneCommand { + private final Project project; + + private String repositoryURL; + private String directory; + + public HgCloneCommand(Project project) { + this.project = project; + } + + public String getDirectory() { + return directory; + } + + public void setDirectory(String directory) { + this.directory = directory; + } + + public String getRepositoryURL() { + return repositoryURL; + } + + public void setRepositoryURL(String repositoryURL) { + this.repositoryURL = repositoryURL; + } + + public HgCommandResult execute() { + List arguments = new LinkedList(); + arguments.add(repositoryURL); + arguments.add(directory); + + return HgCommandService.getInstance(project).execute(null, Collections.emptyList(), "clone", arguments, Charset.defaultCharset()); + } +} diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCommandAuthenticator.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCommandAuthenticator.java new file mode 100644 index 000000000000..3773dbd865b8 --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCommandAuthenticator.java @@ -0,0 +1,96 @@ +// Copyright 2008-2010 Victor Iacoban +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under +// the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions and +// limitations under the License. +package org.zmlx.hg4idea.command; + +import com.intellij.openapi.application.*; +import com.intellij.openapi.project.*; +import com.intellij.openapi.vfs.*; +import com.intellij.vcsUtil.*; +import org.zmlx.hg4idea.ui.*; + +import java.net.*; +import java.util.*; + +/** + * Base class for any command interacting with a remote repository and which needs authentication. + */ +class HgCommandAuthenticator { + + protected HgCommandResult executeCommandAndAuthenticateIfNecessary(Project project, VirtualFile localRepository, String remoteRepository, String command, List arguments) { + HgCommandService service = HgCommandService.getInstance(project); + HgCommandResult result = service.execute(localRepository, command, arguments); + if (HgErrorUtil.isAbort(result) && HgErrorUtil.isAuthorizationRequiredAbort(result)) { + try { + HgUrl hgUrl = new HgUrl(remoteRepository); + if (hgUrl.supportsAuthentication()) { + GetPasswordRunnable runnable = new GetPasswordRunnable(project, hgUrl); + if (!ApplicationManager.getApplication().isDispatchThread()) { + ApplicationManager.getApplication().invokeAndWait(runnable, ModalityState.defaultModalityState()); + } else { + runnable.run(); + } + + if ( runnable.isOk() ) { + hgUrl.setUsername( runnable.getUserName() ); + hgUrl.setPassword(String.valueOf( runnable.getPassword() )); + + arguments.set(arguments.size() - 1, hgUrl.asString()); + result = service.execute(localRepository, command, arguments); + } + } + } catch (URISyntaxException e) { + VcsUtil.showErrorMessage(project, "Invalid repository: " + remoteRepository, "Error"); + } + } + return result; + } + + private static class GetPasswordRunnable implements Runnable { + + private final HgUrl hgUrl; + private String userName; + private char[] password; + private Project project; + private boolean ok = false; + + public GetPasswordRunnable(Project project, HgUrl hgUrl) { + this.hgUrl = hgUrl; + this.project = project; + } + + public void run() { + HgUsernamePasswordDialog dialog = new HgUsernamePasswordDialog(project); + dialog.setUsername(hgUrl.getUsername()); + dialog.show(); + + if (dialog.isOK()) { + userName = dialog.getUsername(); + password = dialog.getPassword(); + ok = true; + } + } + + public String getUserName() { + return userName; + } + + public char[] getPassword() { + return password.clone(); + } + + public boolean isOk() { + return ok; + } + } + +} diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCommandResult.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCommandResult.java index aafd2630fbe4..287a363d0706 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCommandResult.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCommandResult.java @@ -12,25 +12,27 @@ // limitations under the License. package org.zmlx.hg4idea.command; -import com.intellij.openapi.util.text.LineTokenizer; +import com.intellij.openapi.util.text.*; -import java.io.StringWriter; -import java.util.Arrays; -import java.util.List; +import java.io.*; +import java.util.*; public final class HgCommandResult { - static final HgCommandResult EMPTY = new HgCommandResult(new StringWriter(), new StringWriter()); + static final HgCommandResult EMPTY = new HgCommandResult(new StringWriter(), new StringWriter(), 0); private final StringWriter out; private final StringWriter err; + private final int exitValue; private List outLines; private List errLines; + private String warnings; - public HgCommandResult(StringWriter out, StringWriter err) { + public HgCommandResult(StringWriter out, StringWriter err, int exitValue) { this.out = out; this.err = err; + this.exitValue = exitValue; } public List getOutputLines() { @@ -50,5 +52,20 @@ public final class HgCommandResult { public String getRawOutput() { return out.toString(); } + + public String getRawError() { + return err.toString(); + } + public int getExitValue() { + return exitValue; + } + + void setWarnings(String warnings) { + this.warnings = warnings; + } + + public String getWarnings() { + return warnings; + } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCommandService.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCommandService.java index 1b6fe411c00b..e4531f67fda7 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCommandService.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCommandService.java @@ -12,29 +12,34 @@ // limitations under the License. package org.zmlx.hg4idea.command; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.vcsUtil.VcsUtil; -import org.jetbrains.annotations.NotNull; -import org.zmlx.hg4idea.HgGlobalSettings; -import org.zmlx.hg4idea.HgVcs; -import org.zmlx.hg4idea.HgVcsMessages; +import com.intellij.openapi.application.*; +import com.intellij.openapi.diagnostic.*; +import com.intellij.openapi.project.*; +import com.intellij.openapi.vfs.*; +import com.intellij.vcsUtil.*; +import org.zmlx.hg4idea.*; -import java.nio.charset.Charset; -import java.util.Collections; -import java.util.LinkedList; +import javax.swing.*; +import java.awt.*; +import java.io.*; +import java.net.*; +import java.nio.charset.*; +import java.util.*; import java.util.List; public final class HgCommandService { + + private static final File PROMPT_HOOKS_PLUGIN = HgUtil.getTemporaryPythonFile("prompthooks"); static final Logger LOG = Logger.getInstance(HgCommandService.class.getName()); + private static final List DEFAULT_OPTIONS = Arrays.asList( + "--config", "ui.merge=internal:merge" + ); + private final Project project; private final HgGlobalSettings settings; - private HgVcs hgVcs; - public HgCommandService(Project project, HgGlobalSettings settings) { this.project = project; this.settings = settings; @@ -44,47 +49,71 @@ public final class HgCommandService { return project.getComponent(HgCommandService.class); } - HgCommandResult execute(@NotNull VirtualFile repo, String operation, List arguments) { + HgCommandResult execute(VirtualFile repo, String operation, List arguments) { return execute( - repo, Collections.emptyList(), operation, arguments, Charset.defaultCharset() + repo, DEFAULT_OPTIONS, operation, arguments, Charset.defaultCharset() ); } - HgCommandResult execute(@NotNull VirtualFile repo, List config, + HgCommandResult execute(VirtualFile repo, List hgOptions, String operation, List arguments) { - return execute(repo, config, operation, arguments, Charset.defaultCharset()); + return execute(repo, hgOptions, operation, arguments, Charset.defaultCharset()); } - HgCommandResult execute(@NotNull VirtualFile repo, List config, + HgCommandResult execute(VirtualFile repo, List hgOptions, String operation, List arguments, Charset charset) { - - if (hgVcs == null) { - hgVcs = HgVcs.getInstance(project); - } - - if (hgVcs == null || !hgVcs.validateHgExecutable()) { - return HgCommandResult.EMPTY; - } - List cmdLine = new LinkedList(); cmdLine.add(settings.getHgExecutable()); - if (config != null && !config.isEmpty()) { - cmdLine.add("--config"); - cmdLine.addAll(config); + if (repo != null) { + cmdLine.add("--repository"); + cmdLine.add(repo.getPath()); } + + SocketServer promptServer = new SocketServer(new PromptReceiver()); + WarningReceiver warningReceiver = new WarningReceiver(); + SocketServer warningServer = new SocketServer(warningReceiver); + if (PROMPT_HOOKS_PLUGIN == null) { + throw new RuntimeException("Could not hook into the prompt mechanism of Mercurial"); + } + try { + int promptPort = promptServer.start(); + int warningPort = warningServer.start(); + cmdLine.add("--config"); + cmdLine.add("extensions.hg4ideapromptextension=" + PROMPT_HOOKS_PLUGIN.getAbsolutePath()); + cmdLine.add("--config"); + cmdLine.add("hg4ideaprompt.port=" + promptPort); + cmdLine.add("--config"); + cmdLine.add("hg4ideawarn.port=" + warningPort); + + // Other parts of the plugin count on the availability of the MQ extension, so make sure it is enabled + cmdLine.add("--config"); + cmdLine.add("extensions.mq="); + } catch (IOException e) { + throw new RuntimeException(e); //TODO implement catch clause + } + cmdLine.addAll(hgOptions); cmdLine.add(operation); if (arguments != null && arguments.size() != 0) { cmdLine.addAll(arguments); } ShellCommand shellCommand = new ShellCommand(); + HgCommandResult result; try { - LOG.info(cmdLine.toString()); - return shellCommand.execute(cmdLine, repo.getPath(), charset); + LOG.debug(cmdLine.toString()); + String workingDir = repo != null ? repo.getPath() : null; + result = shellCommand.execute(cmdLine, workingDir, charset); } catch (ShellCommandException e) { showError(e); LOG.error(e.getMessage(), e); + result = HgCommandResult.EMPTY; + } finally { + promptServer.stop(); + warningServer.stop(); } - return HgCommandResult.EMPTY; + String warnings = warningReceiver.getWarnings(); + result.setWarnings(warnings); + return result; + } private void showError(Exception e) { @@ -102,4 +131,101 @@ public final class HgCommandService { ); } + private static class WarningReceiver extends SocketServer.Protocol{ + private StringBuffer warnings = new StringBuffer(); + + public boolean handleConnection(Socket socket) throws IOException { + DataInputStream dataInput = new DataInputStream(socket.getInputStream()); + + int numOfWarnings = dataInput.readInt(); + for (int i = 0; i < numOfWarnings; i++) { + warnings.append(new String(readDataBlock(dataInput))); + } + return true; + } + + + public String getWarnings() { + return warnings.toString(); + } + } + + private static class PromptReceiver extends SocketServer.Protocol { + + public boolean handleConnection(Socket socket) throws IOException { + DataInputStream dataInput = new DataInputStream(socket.getInputStream()); + final String message = new String(readDataBlock(dataInput)); + int numOfChoices = dataInput.readInt(); + final Choice[] choices = new Choice[numOfChoices]; + for (int i = 0; i < numOfChoices; i++) { + String choice = new String(readDataBlock(dataInput)); + choices[i] = new Choice(choice); + } + int defaultChoiceInt = dataInput.readInt(); + final Choice defaultChoice = choices[defaultChoiceInt]; + + final int[] index = new int[]{-1}; + ApplicationManager.getApplication().invokeAndWait(new Runnable() { + public void run() { + Window parent = ApplicationManager.getApplication().getComponent(Window.class); + index[0] = JOptionPane.showOptionDialog( + parent, + message, + "hg4idea", + JOptionPane.OK_CANCEL_OPTION, + JOptionPane.QUESTION_MESSAGE, + null, + choices, + defaultChoice); + } + }, ModalityState.defaultModalityState()); + + int chosen = index[0]; + DataOutputStream out = new DataOutputStream(socket.getOutputStream()); + if (chosen == JOptionPane.CLOSED_OPTION) { + out.writeInt(-1); + } else { + out.writeInt(chosen); + } + return true; + } + + private static class Choice{ + private final String fullString; + private final String representation; + private final String choiceChar; + + private Choice(String fullString) { + this.fullString = fullString; + this.representation = fullString.replaceAll("&", ""); + int index = fullString.indexOf("&"); + this.choiceChar = "" + fullString.charAt(index + 1); + + } + + @Override + public String toString() { + return representation; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Choice choice = (Choice) o; + + if (!fullString.equals(choice.fullString)) return false; + + return true; + } + + @Override + public int hashCode() { + return fullString.hashCode(); + } + } + } + + } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCommitCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCommitCommand.java index a2496f61fc5e..e1cb81714294 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCommitCommand.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCommitCommand.java @@ -12,24 +12,19 @@ // limitations under the License. package org.zmlx.hg4idea.command; -import com.intellij.openapi.application.PathManager; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.diagnostic.Logger; -import org.apache.commons.lang.StringUtils; -import org.jetbrains.annotations.NotNull; -import org.zmlx.hg4idea.HgFile; -import org.zmlx.hg4idea.HgVcsMessages; -import org.zmlx.hg4idea.HgVcs; +import com.intellij.openapi.application.*; +import com.intellij.openapi.diagnostic.*; +import com.intellij.openapi.project.*; +import com.intellij.openapi.vcs.*; +import com.intellij.openapi.vfs.*; +import org.apache.commons.lang.*; +import org.jetbrains.annotations.*; +import org.zmlx.hg4idea.*; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.Writer; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; +import java.io.*; +import java.util.*; + +import static org.zmlx.hg4idea.HgErrorHandler.*; public class HgCommitCommand { @@ -41,7 +36,7 @@ public class HgCommitCommand { private final VirtualFile repo; private final String message; - private List files = Collections.emptyList(); + private Set files = Collections.emptySet(); public HgCommitCommand(Project project, @NotNull VirtualFile repo, String message) { this.project = project; @@ -49,11 +44,11 @@ public class HgCommitCommand { this.message = message; } - public void setFiles(@NotNull List files) { + public void setFiles(@NotNull Set files) { this.files = files; } - public void execute() throws HgCommandException { + public void execute() throws HgCommandException, VcsException { if (StringUtils.isBlank(message)) { throw new HgCommandException(HgVcsMessages.message("hg4idea.commit.error.messageEmpty")); } @@ -64,7 +59,7 @@ public class HgCommitCommand { for (HgFile hgFile : files) { parameters.add(hgFile.getRelativePath()); } - HgCommandService.getInstance(project).execute(repo, "commit", parameters); + ensureSuccess(HgCommandService.getInstance(project).execute(repo, "commit", parameters)); project.getMessageBus().syncPublisher(HgVcs.OUTGOING_TOPIC).update(project); } catch (IOException e) { LOG.error(e); diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgHeadsCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgHeadsCommand.java index a34f5d72950b..afbbe129cbdd 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgHeadsCommand.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgHeadsCommand.java @@ -12,21 +12,16 @@ // limitations under the License. package org.zmlx.hg4idea.command; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vfs.VirtualFile; -import org.apache.commons.lang.StringUtils; -import org.jetbrains.annotations.NotNull; -import org.zmlx.hg4idea.HgRevisionNumber; +import com.intellij.openapi.project.*; +import com.intellij.openapi.vfs.*; +import org.apache.commons.lang.*; +import org.jetbrains.annotations.*; +import org.zmlx.hg4idea.*; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; +import java.util.*; public class HgHeadsCommand { - private static final Logger LOG = Logger.getInstance(HgHeadsCommand.class.getName()); - private final Project project; private final VirtualFile repo; @@ -35,22 +30,26 @@ public class HgHeadsCommand { this.repo = repo; } - public List execute(String branch) { - HgCommandService command = HgCommandService.getInstance(project); - - HgCommandResult result = command.execute(repo, "heads", - Arrays.asList("--template", "{rev}|{node|short}\\n", branch)); - - List heads = new ArrayList(); - for (String line : result.getOutputLines()) { - try { - String[] parts = StringUtils.split(line, '|'); - heads.add(HgRevisionNumber.getInstance(parts[0], parts[1])); - } catch (NumberFormatException e) { - LOG.warn("Unexpected head line '" + line + "'"); - } - } - return heads; + public List execute() { + return execute("."); } + public List execute(String branch) { + return new HeadsCommand(project, branch).execute(repo); + } + + private class HeadsCommand extends HgChangesetsCommand { + private final String branch; + public HeadsCommand(Project project, String branch) { + super(project, "heads"); + this.branch = branch; + } + + @Override + protected void addArguments(List args) { + if (StringUtils.isNotEmpty(branch)) { + args.add(branch); + } + } + } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgIdentifyCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgIdentifyCommand.java new file mode 100644 index 000000000000..af01433b1d77 --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgIdentifyCommand.java @@ -0,0 +1,32 @@ +package org.zmlx.hg4idea.command; + +import com.intellij.openapi.project.*; + +import java.nio.charset.*; +import java.util.*; + +public class HgIdentifyCommand { + private final Project project; + + private String source; + + public HgIdentifyCommand(Project project) { + this.project = project; + } + + public String getSource() { + return source; + } + + public void setSource(String source) { + this.source = source; + } + + public HgCommandResult execute() { + List arguments = new LinkedList(); + arguments.add(source); + + HgCommandService hgCommandService = HgCommandService.getInstance(project); + return hgCommandService.execute(null, Collections.emptyList(), "identify", arguments, Charset.defaultCharset()); + } +} diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgIncomingCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgIncomingCommand.java index 33824e04d8f2..1c4cf7c5dcc3 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgIncomingCommand.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgIncomingCommand.java @@ -12,23 +12,18 @@ // limitations under the License. package org.zmlx.hg4idea.command; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vfs.VirtualFile; -import org.zmlx.hg4idea.HgFile; +import com.intellij.openapi.project.*; -import java.util.Arrays; +import java.util.*; -public class HgIncomingCommand extends HgRevisionsCommand { +public class HgIncomingCommand extends HgChangesetsCommand { public HgIncomingCommand(Project project) { - super(project); + super(project, "incoming"); } @Override - protected HgCommandResult execute(HgCommandService service, VirtualFile repo, - String template, int limit, HgFile hgFile) { - return service.execute(repo, "incoming", - Arrays.asList("--newest-first", "--template", template, "--limit", String.valueOf(limit))); + protected void addArguments(List args) { + args.add("--newest-first"); } - } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgLogCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgLogCommand.java index 8d33efd63151..3ff53ab1e8a3 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgLogCommand.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgLogCommand.java @@ -12,15 +12,14 @@ // limitations under the License. package org.zmlx.hg4idea.command; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vfs.VirtualFile; -import org.zmlx.hg4idea.HgFile; +import com.intellij.openapi.project.*; +import com.intellij.openapi.vfs.*; +import org.zmlx.hg4idea.*; -import java.util.List; -import java.util.LinkedList; +import java.util.*; public class HgLogCommand extends HgRevisionsCommand { - + private boolean includeRemoved; private boolean followCopies; private boolean logFile = true; @@ -28,6 +27,10 @@ public class HgLogCommand extends HgRevisionsCommand { super(project); } + public void setIncludeRemoved(boolean includeRemoved) { + this.includeRemoved = includeRemoved; + } + public void setFollowCopies(boolean followCopies) { this.followCopies = followCopies; } @@ -43,10 +46,20 @@ public class HgLogCommand extends HgRevisionsCommand { if (followCopies) { arguments.add("--follow"); } + if (includeRemoved) { + // There is a bug in mercurial that causes --follow --removed to cause + // an error (http://mercurial.selenic.com/bts/issue2139). Avoid this combination + // for now, preferring to use --follow over --removed. + if (!(followCopies && logFile)) { + arguments.add("--removed"); + } + } arguments.add("--template"); arguments.add(template); - arguments.add("--limit"); - arguments.add(String.valueOf(limit)); + if (limit != -1) { + arguments.add("--limit"); + arguments.add(String.valueOf(limit)); + } if (logFile) { arguments.add(hgFile.getRelativePath()); } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgMergeCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgMergeCommand.java index bcab5a799748..ce5773869c15 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgMergeCommand.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgMergeCommand.java @@ -12,12 +12,11 @@ // limitations under the License. package org.zmlx.hg4idea.command; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vfs.VirtualFile; -import org.apache.commons.lang.StringUtils; +import com.intellij.openapi.project.*; +import com.intellij.openapi.vfs.*; +import org.apache.commons.lang.*; -import java.util.LinkedList; -import java.util.List; +import java.util.*; public class HgMergeCommand { @@ -42,8 +41,6 @@ public class HgMergeCommand { public HgCommandResult execute() { HgCommandService commandService = HgCommandService.getInstance(project); - List config = new LinkedList(); - config.add("ui.merge=internal:merge"); List arguments = new LinkedList(); if (StringUtils.isNotBlank(revision)) { arguments.add("--rev"); @@ -51,7 +48,7 @@ public class HgMergeCommand { } else if (StringUtils.isNotBlank(branch)) { arguments.add(branch); } - return commandService.execute(repo, config, "merge", arguments); + return commandService.execute(repo, "merge", arguments); } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgOutgoingCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgOutgoingCommand.java index 0ae2c786b41e..d0ec61946417 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgOutgoingCommand.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgOutgoingCommand.java @@ -12,22 +12,19 @@ // limitations under the License. package org.zmlx.hg4idea.command; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.project.Project; -import org.zmlx.hg4idea.HgFile; +import com.intellij.openapi.project.*; -import java.util.Arrays; +import java.util.*; -public class HgOutgoingCommand extends HgRevisionsCommand { +public class HgOutgoingCommand extends HgChangesetsCommand { public HgOutgoingCommand(Project project) { - super(project); + super(project, "outgoing"); } - protected HgCommandResult execute(HgCommandService service, VirtualFile repo, - String template, int limit, HgFile hgFile) { - return service.execute(repo, "outgoing", - Arrays.asList("--newest-first", "--template", template, "--limit", String.valueOf(limit))); + @Override + protected void addArguments(List args) { + args.add("--newest-first"); } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgParentsCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgParentsCommand.java new file mode 100644 index 000000000000..3f7419e1fe34 --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgParentsCommand.java @@ -0,0 +1,39 @@ +// Copyright 2008-2010 Victor Iacoban +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under +// the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions and +// limitations under the License. +package org.zmlx.hg4idea.command; + +import com.intellij.openapi.project.*; +import org.zmlx.hg4idea.*; + +import java.util.*; + +public class HgParentsCommand extends HgChangesetsCommand{ + + private HgRevisionNumber revision; + + public HgParentsCommand(Project project) { + super(project, "parents"); + } + + public void setRevision(HgRevisionNumber revision) { + this.revision = revision; + } + + @Override + protected void addArguments(List args) { + if (revision != null) { + args.add("--rev"); + args.add(revision.getChangeset()); + } + } +} diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgPullCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgPullCommand.java index 3f54e36763ac..1b541c489b86 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgPullCommand.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgPullCommand.java @@ -12,17 +12,13 @@ // limitations under the License. package org.zmlx.hg4idea.command; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.vcsUtil.VcsUtil; -import org.apache.commons.lang.StringUtils; -import org.jetbrains.annotations.NotNull; -import org.zmlx.hg4idea.ui.HgUsernamePasswordDialog; -import org.zmlx.hg4idea.HgVcs; +import com.intellij.openapi.project.*; +import com.intellij.openapi.vfs.*; +import org.apache.commons.lang.*; +import org.jetbrains.annotations.*; +import org.zmlx.hg4idea.*; -import java.util.LinkedList; -import java.util.List; -import java.net.URISyntaxException; +import java.util.*; public class HgPullCommand { @@ -33,6 +29,8 @@ public class HgPullCommand { private String revision; private boolean update = true; private boolean rebase = !update; + + private final HgCommandAuthenticator authenticator = new HgCommandAuthenticator(); public HgPullCommand(Project project, @NotNull VirtualFile repo) { this.project = project; @@ -70,25 +68,7 @@ public class HgPullCommand { arguments.add(source); - HgCommandResult result = HgCommandService.getInstance(project).execute(repo, "pull", arguments); - if (HgErrorUtil.isAbort(result) && HgErrorUtil.isAuthorizationRequiredAbort(result)) { - try { - HgUrl hgUrl = new HgUrl(source); - if (hgUrl.supportsAuthentication()) { - HgUsernamePasswordDialog dialog = new HgUsernamePasswordDialog(project); - dialog.setUsername(hgUrl.getUsername()); - dialog.show(); - if (dialog.isOK()) { - hgUrl.setUsername(dialog.getUsername()); - hgUrl.setPassword(String.valueOf(dialog.getPassword())); - arguments.set(arguments.size() - 1, hgUrl.asString()); - result = HgCommandService.getInstance(project).execute(repo, "pull", arguments); - } - } - } catch (URISyntaxException e) { - VcsUtil.showErrorMessage(project, "Invalid source: " + source, "Error"); - } - } + HgCommandResult result = authenticator.executeCommandAndAuthenticateIfNecessary(project, repo, source, "pull", arguments); project.getMessageBus().syncPublisher(HgVcs.INCOMING_TOPIC).update(project); diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgPushCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgPushCommand.java index 5e8a425ee22d..27f554d482b4 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgPushCommand.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgPushCommand.java @@ -12,23 +12,20 @@ // limitations under the License. package org.zmlx.hg4idea.command; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.vcsUtil.VcsUtil; -import org.apache.commons.lang.StringUtils; -import org.jetbrains.annotations.NotNull; -import org.zmlx.hg4idea.ui.HgUsernamePasswordDialog; -import org.zmlx.hg4idea.HgVcs; +import com.intellij.openapi.project.*; +import com.intellij.openapi.vfs.*; +import org.apache.commons.lang.*; +import org.jetbrains.annotations.*; +import org.zmlx.hg4idea.*; -import java.util.LinkedList; -import java.util.List; -import java.net.URISyntaxException; +import java.util.*; public class HgPushCommand { private final Project project; private final VirtualFile repo; private final String destination; + private final HgCommandAuthenticator authenticator = new HgCommandAuthenticator(); private String revision; @@ -49,25 +46,8 @@ public class HgPushCommand { arguments.add(revision); } arguments.add(destination); - HgCommandResult result = HgCommandService.getInstance(project).execute(repo, "push", arguments); - if (HgErrorUtil.isAbort(result) && HgErrorUtil.isAuthorizationRequiredAbort(result)) { - try { - HgUrl hgUrl = new HgUrl(destination); - if (hgUrl.supportsAuthentication()) { - HgUsernamePasswordDialog dialog = new HgUsernamePasswordDialog(project); - dialog.setUsername(hgUrl.getUsername()); - dialog.show(); - if (dialog.isOK()) { - hgUrl.setUsername(dialog.getUsername()); - hgUrl.setPassword(String.valueOf(dialog.getPassword())); - arguments.set(arguments.size() - 1, hgUrl.asString()); - result = HgCommandService.getInstance(project).execute(repo, "push", arguments); - } - } - } catch (URISyntaxException e) { - VcsUtil.showErrorMessage(project, "Invalid destination: " + destination, "Error"); - } - } + + HgCommandResult result = authenticator.executeCommandAndAuthenticateIfNecessary(project, repo, destination, "push", arguments); project.getMessageBus().syncPublisher(HgVcs.OUTGOING_TOPIC).update(project); diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgResolveCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgResolveCommand.java index 21edb62e3158..94b4d8e0d194 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgResolveCommand.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgResolveCommand.java @@ -12,19 +12,24 @@ // limitations under the License. package org.zmlx.hg4idea.command; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vfs.VirtualFile; -import org.apache.commons.lang.StringUtils; -import org.zmlx.hg4idea.HgFile; +import com.intellij.openapi.project.*; +import com.intellij.openapi.vcs.FilePath; +import com.intellij.openapi.vcs.*; +import com.intellij.openapi.vfs.*; +import org.apache.commons.lang.*; +import org.zmlx.hg4idea.*; -import java.io.File; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; +import java.io.*; +import java.net.*; +import java.util.*; +import java.util.concurrent.*; + +import static org.zmlx.hg4idea.HgErrorHandler.*; public class HgResolveCommand { + private static final File FILEMERGE_PLUGIN = HgUtil.getTemporaryPythonFile("filemerge"); + private static final int ITEM_COUNT = 3; private final Project project; @@ -55,9 +60,96 @@ public class HgResolveCommand { return resolveStatus; } - public void resolve(VirtualFile repo, VirtualFile path) { + public void markResolved(VirtualFile repo, VirtualFile path) { HgCommandService.getInstance(project) .execute(repo, "resolve", Arrays.asList("--mark", path.getPath())); } -} + public void markResolved(VirtualFile repo, FilePath path) { + HgCommandService.getInstance(project) + .execute(repo, "resolve", Arrays.asList("--mark", path.getPath())); + } + + public MergeData getResolveData(VirtualFile repo, VirtualFile path) throws VcsException { + //start an hg resolve command, configured with a mercurial extension + //which will transfer the contents of the base, local and other versions + //to the socket server we set up on this end. + + if (FILEMERGE_PLUGIN == null) { + throw new VcsException("Could not provide dynamic extension file"); + } + Receiver receiver = new Receiver(); + SocketServer server = new SocketServer(receiver); + try { + int port = server.start(); + + List hgOptions = Arrays.asList( + "--config", "extensions.hg4ideafilemerge=" + FILEMERGE_PLUGIN.getAbsolutePath(), + "--config", "hg4ideafilemerge.port=" + port); + ensureSuccess(HgCommandService.getInstance(project). + execute(repo, hgOptions, "resolve", Arrays.asList(path.getPath()))); + + } catch (IOException e) { + throw new VcsException(e); + } + try { + return receiver.getMergeParticipantsContents(); + } catch (InterruptedException e) { + //operation was cancelled, never mind what the contents of all the participants is. + return null; + } + } + + public static class Receiver extends SocketServer.Protocol{ + + private MergeData data; + private final CountDownLatch completed = new CountDownLatch(1); + + public boolean handleConnection(Socket socket) throws IOException { + DataInputStream dataInputStream = new DataInputStream(new BufferedInputStream(socket.getInputStream())); + byte[] local = readDataBlock(dataInputStream); + byte[] other = readDataBlock(dataInputStream); + byte[] base = readDataBlock(dataInputStream); + + new PrintStream(socket.getOutputStream()).println("Done"); + + data = new MergeData(local, other, base); + completed.countDown(); + return false; + } + + private MergeData getMergeParticipantsContents() throws InterruptedException, VcsException { + //join defines a 'happens-before' relationship, so no need for extra synchronization + completed.await(1, TimeUnit.SECONDS); + if (data == null) { + throw new VcsException("Did not receive data from Mercurial's resolve command"); + } + return data; + } + + } + + public final static class MergeData { + private final byte[] local; + private final byte[] other; + private final byte[] base; + + private MergeData(byte[] local, byte[] other, byte[] base) { + this.local = local; + this.other = other; + this.base = base; + } + + public byte[] getLocal() { + return local; + } + + public byte[] getOther() { + return other; + } + + public byte[] getBase() { + return base; + } + } +} \ No newline at end of file diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgRevertCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgRevertCommand.java index e861c20c0d09..aeed7bd3c65c 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgRevertCommand.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgRevertCommand.java @@ -12,10 +12,11 @@ // limitations under the License. package org.zmlx.hg4idea.command; -import com.intellij.openapi.project.Project; -import org.zmlx.hg4idea.HgFile; +import com.intellij.openapi.project.*; +import org.apache.commons.lang.*; +import org.zmlx.hg4idea.*; -import java.util.Arrays; +import java.util.*; public class HgRevertCommand { @@ -25,9 +26,24 @@ public class HgRevertCommand { this.project = project; } - public void execute(HgFile hgFile) { - HgCommandService.getInstance(project) - .execute(hgFile.getRepo(), "revert", Arrays.asList(hgFile.getRelativePath())); - } + public void execute(HgFile hgFile, HgRevisionNumber vcsRevisionNumber, boolean backupFile) { + List arguments = new LinkedList(); + if (vcsRevisionNumber != null) { + arguments.add("--rev"); + if (StringUtils.isNotBlank(vcsRevisionNumber.getChangeset())) { + arguments.add(vcsRevisionNumber.getChangeset()); + } else { + arguments.add(vcsRevisionNumber.getRevision()); + } + } + + if (!backupFile) { + arguments.add("--no-backup"); + } + + arguments.addAll(Arrays.asList(hgFile.getRelativePath())); + + HgCommandService.getInstance(project).execute(hgFile.getRepo(), "revert", arguments); + } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgRevisionsCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgRevisionsCommand.java index 4bcaa827f160..790f22caea6f 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgRevisionsCommand.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgRevisionsCommand.java @@ -12,54 +12,39 @@ // limitations under the License. package org.zmlx.hg4idea.command; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vfs.VirtualFile; -import org.apache.commons.lang.StringUtils; -import org.zmlx.hg4idea.HgFile; -import org.zmlx.hg4idea.HgFileRevision; -import org.zmlx.hg4idea.HgRevisionNumber; +import com.intellij.openapi.diagnostic.*; +import com.intellij.openapi.project.*; +import com.intellij.openapi.vfs.*; +import org.apache.commons.lang.*; +import org.zmlx.hg4idea.*; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Arrays; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.text.*; +import java.util.*; abstract class HgRevisionsCommand { private static final Logger LOG = Logger.getInstance(HgRevisionsCommand.class.getName()); + private static final String SEPARATOR_STRING = "\u0017"; //ascii: end of transmission block - private static final String TEMPLATE = "{rev}|" - + "{node|short}|" - + "{date|isodate}|" - + "{author}|" - + "{branches}|" - + "{desc}|" - + "{file_adds}|" - + "{file_mods}|" - + "{file_dels}|" - + "{file_copies}\\n"; + private static final String SHORT_TEMPLATE = "{rev}|{node|short}|{parents}|{date|isodatesec}|{author}|{branches}|{desc}" + SEPARATOR_STRING; + private static final int SHORT_ITEM_COUNT = 7; + private static final String LONG_TEMPLATE = "{rev}|{node|short}|{parents}|{date|isodatesec}|{author}|{branches}|{desc}|{file_adds}|{file_mods}|{file_dels}|{file_copies}" + SEPARATOR_STRING; + private static final int LONG_ITEM_COUNT = 11; private static final int REVISION_INDEX = 0; private static final int CHANGESET_INDEX = 1; - private static final int DATE_INDEX = 2; - private static final int AUTHOR_INDEX = 3; - private static final int BRANCH_INDEX = 4; - private static final int MESSAGE_INDEX = 5; - private static final int FILES_ADDED_INDEX = 6; - private static final int FILES_MODIFIED_INDEX = 7; - private static final int FILES_DELETED_INDEX = 8; - private static final int FILES_COPIES_INDEX = 9; - private static final int ITEM_COUNT = 10; + private static final int PARENTS_INDEX = 2; - private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm Z"); + private static final int DATE_INDEX = 3; + private static final int AUTHOR_INDEX = 4; + private static final int BRANCH_INDEX = 5; + private static final int MESSAGE_INDEX = 6; + private static final int FILES_ADDED_INDEX = 7; + private static final int FILES_MODIFIED_INDEX = 8; + private static final int FILES_DELETED_INDEX = 9; + private static final int FILES_COPIED_INDEX = 10; + + private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z"); private final Project project; @@ -71,60 +56,86 @@ abstract class HgRevisionsCommand { HgCommandService service, VirtualFile repo, String template, int limit, HgFile hgFile ); - public final List execute(HgFile hgFile, int limit) { - if (limit <= REVISION_INDEX || hgFile == null || hgFile.getRepo() == null) { + public final List execute(HgFile hgFile, int limit, boolean includeFiles) { + if ((limit <= 0 && limit != -1) || hgFile == null || hgFile.getRepo() == null) { return Collections.emptyList(); } HgCommandService hgCommandService = HgCommandService.getInstance(project); + String template = includeFiles ? LONG_TEMPLATE : SHORT_TEMPLATE; + int itemCount = includeFiles ? LONG_ITEM_COUNT : SHORT_ITEM_COUNT; + HgCommandResult result = execute( - hgCommandService, hgFile.getRepo(), TEMPLATE, limit, hgFile + hgCommandService, hgFile.getRepo(), template, limit, hgFile ); List revisions = new LinkedList(); - for (String line : result.getOutputLines()) { + String output = result.getRawOutput(); + String[] changeSets = output.split(SEPARATOR_STRING); + for (String line : changeSets) { try { String[] attributes = StringUtils.splitPreserveAllTokens(line, '|'); - if (attributes.length != ITEM_COUNT) { + if (attributes.length != itemCount) { LOG.debug("Wrong format. Skipping line " + line); continue; } + + String revisionString = attributes[REVISION_INDEX]; + String changeset = attributes[CHANGESET_INDEX]; + String parentsString = attributes[PARENTS_INDEX]; + + List parents = new ArrayList(2); + if (StringUtils.isEmpty(parentsString)) { + Long revision = Long.valueOf(revisionString); + HgRevisionNumber parentRevision = HgRevisionNumber.getLocalInstance(String.valueOf(revision - 1)); + parents.add(parentRevision); + } else { + //hg returns parents in the format 'rev:node rev:node ' (note the trailing space) + String[] parentStrings = parentsString.trim().split(" "); + for (String parentString : parentStrings) { + String[] parentParts = parentString.split(":"); + parents.add(HgRevisionNumber.getInstance(parentParts[0], parentParts[1])); + } + } HgRevisionNumber vcsRevisionNumber = HgRevisionNumber.getInstance( - attributes[REVISION_INDEX], - attributes[CHANGESET_INDEX] + revisionString, + changeset, + parents ); + Date revisionDate = DATE_FORMAT.parse(attributes[DATE_INDEX]); String author = attributes[AUTHOR_INDEX]; String branchName = attributes[BRANCH_INDEX]; String commitMessage = attributes[MESSAGE_INDEX]; - Set filesAdded = parseFileList(attributes[FILES_ADDED_INDEX]); - Set filesModified = parseFileList(attributes[FILES_MODIFIED_INDEX]); - Set filesDeleted = parseFileList(attributes[FILES_DELETED_INDEX]); - Map filesCopied = parseCopiesFileList(attributes[FILES_COPIES_INDEX]); - filesModified.removeAll(filesAdded); - filesModified.removeAll(filesDeleted); - filesCopied.keySet().removeAll(filesDeleted); - filesCopied.values().removeAll(filesAdded); + Set filesAdded; + Set filesModified; + Set filesDeleted; + Map copies; + if (FILES_ADDED_INDEX < itemCount) { + filesAdded = parseFileList(attributes[FILES_ADDED_INDEX]); + filesModified = parseFileList(attributes[FILES_MODIFIED_INDEX]); + filesDeleted = parseFileList(attributes[FILES_DELETED_INDEX]); - if (filesAdded.isEmpty() && filesModified.isEmpty() - && filesCopied.isEmpty() && filesDeleted.isEmpty()) { - continue; + copies = parseCopiesFileList(attributes[FILES_COPIED_INDEX]); + // Only keep renames, i.e. copies where the source file is also deleted. + Iterator keys = copies.keySet().iterator(); + while (keys.hasNext()) { + String s = keys.next(); + if (!filesDeleted.contains(s)) { + keys.remove(); + } + } + } else { + filesAdded = Collections.emptySet(); + filesModified = Collections.emptySet(); + filesDeleted = Collections.emptySet(); + copies = Collections.emptyMap(); } - HgFileRevision revision = new HgFileRevision(project, hgFile, vcsRevisionNumber); - revision.setBranchName(branchName); - revision.setRevisionDate(revisionDate); - revision.setAuthor(author); - revision.setCommitMessage(commitMessage); - revision.setFilesModified(filesModified); - revision.setFilesAdded(filesAdded); - revision.setFilesDeleted(filesDeleted); - revision.setFilesCopied(filesCopied); - - revisions.add(revision); - + revisions.add(new HgFileRevision(project, hgFile, vcsRevisionNumber, + branchName, revisionDate, author, commitMessage, filesModified, filesAdded, filesDeleted, copies)); } catch (NumberFormatException e) { LOG.warn("Error parsing rev in line " + line); } catch (ParseException e) { @@ -147,19 +158,18 @@ abstract class HgRevisionsCommand { return Collections.emptyMap(); } else { Map copies = new HashMap(); - //{file_copies} gives us a string of this shape: - // path1/File1 (path2/File2)path3/File3 path4/File4 - // where source (copy) - String[] filecopies = StringUtils.split(fileListString, ')'); - for (String filecopy : filecopies) { - String[] parts = StringUtils.split(filecopy, " ("); - if (parts.length != 2) { - continue; - } - copies.put(parts[1], parts[0]); + + String[] filesList = fileListString.split("\\)"); + + for (String files : filesList) { + String[] file = files.split(" \\("); + String target = file[0]; + String source = file[1]; + + copies.put(source, target); } + return copies; } } - } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgStatusCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgStatusCommand.java index 19e26c686373..f5963f022bec 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgStatusCommand.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgStatusCommand.java @@ -12,18 +12,15 @@ // limitations under the License. package org.zmlx.hg4idea.command; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vfs.VirtualFile; -import org.apache.commons.lang.StringUtils; -import org.zmlx.hg4idea.HgFile; +import com.intellij.openapi.diagnostic.*; +import com.intellij.openapi.project.*; +import com.intellij.openapi.vfs.*; +import org.apache.commons.lang.*; +import org.jetbrains.annotations.*; +import org.zmlx.hg4idea.*; -import java.io.File; -import java.util.Collections; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; +import java.io.*; +import java.util.*; public class HgStatusCommand { @@ -41,6 +38,8 @@ public class HgStatusCommand { private boolean includeUnknown = true; private boolean includeIgnored = true; private boolean includeCopySource = true; + private HgRevisionNumber baseRevision; + private HgRevisionNumber targetRevision; public HgStatusCommand(Project project) { this.project = project; @@ -74,7 +73,24 @@ public class HgStatusCommand { this.includeCopySource = includeCopySource; } + public void setBaseRevision(HgRevisionNumber base) { + baseRevision = base; + } + + public void setTargetRevision(HgRevisionNumber target) { + targetRevision = target; + } + public Set execute(VirtualFile repo) { + return doExecute(repo, null); + } + + public HgChange execute(VirtualFile repo, @NotNull String file) { + Set changes = doExecute(repo, file); + return changes.isEmpty() ? null : changes.iterator().next(); + } + + private Set doExecute(VirtualFile repo, String file) { if (repo == null) { return Collections.emptySet(); } @@ -103,6 +119,18 @@ public class HgStatusCommand { if (includeCopySource) { arguments.add("--copies"); } + if (baseRevision != null) { + arguments.add("--rev"); + arguments.add(baseRevision.getChangeset()); + if (targetRevision != null) { + arguments.add("--rev"); + arguments.add(targetRevision.getChangeset()); + } + } + + if (file != null) { + arguments.add(file); + } HgCommandResult result = service.execute(repo, "status", arguments); Set changes = new HashSet(); @@ -126,5 +154,4 @@ public class HgStatusCommand { } return changes; } - } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgTrackFileNamesAccrossRevisionsCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgTrackFileNamesAccrossRevisionsCommand.java new file mode 100644 index 000000000000..59c98a1d374b --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgTrackFileNamesAccrossRevisionsCommand.java @@ -0,0 +1,146 @@ +// Copyright 2008-2010 Victor Iacoban +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under +// the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions and +// limitations under the License. +package org.zmlx.hg4idea.command; + +import com.intellij.openapi.diagnostic.*; +import com.intellij.openapi.project.*; +import com.intellij.openapi.vfs.*; +import org.apache.commons.lang.*; +import org.zmlx.hg4idea.*; + +import java.util.*; + +class HgTrackFileNamesAccrossRevisionsCommand { + + private static final Logger LOG = Logger.getInstance(HgTrackFileNamesAccrossRevisionsCommand.class.getName()); + private static final String SEPARATOR_STRING = "\u0027"; //ascii: end of transmission block + + private static final String TEMPLATE = "{rev}|{file_dels}|{file_copies}" + SEPARATOR_STRING; + private static final int ITEM_COUNT = 3; + + private static final int REVISION_INDEX = 0; + private static final int FILES_DELETED_INDEX = 1; + private static final int FILES_COPIED_INDEX = 2; + + private final Project project; + + public HgTrackFileNamesAccrossRevisionsCommand(Project project) { + this.project = project; + } + + private HgCommandResult execute(HgCommandService service, VirtualFile repo, int limit, HgFile hgFile, String currentrevision, String givenRevision) { + List arguments = new LinkedList(); + + arguments.add("--rev"); + arguments.add(currentrevision + ":" + givenRevision); + + arguments.add("--follow"); + arguments.add("--template"); + arguments.add(TEMPLATE); + + if (limit != -1) { + arguments.add("--limit"); + arguments.add(String.valueOf(limit)); + } + + arguments.add(hgFile.getRelativePath()); + + return service.execute(repo, "log", arguments); + } + + public final String execute(HgFile hgFile, String currentRevision, String givenRevision, int limit) { + if (hgFile == null || hgFile.getRepo() == null) { + return null; + } + + HgCommandService hgCommandService = HgCommandService.getInstance(project); + HgCommandResult result = execute(hgCommandService, hgFile.getRepo(), limit, hgFile, currentRevision, givenRevision); + + String output = result.getRawOutput(); + String[] changeSets = output.split(SEPARATOR_STRING); + String currentFileName = hgFile.getRelativePath(); + // needed on windows machines + currentFileName = currentFileName.replaceAll("\\\\", "/"); + + for (String line : changeSets) { + try { + String[] attributes = StringUtils.splitPreserveAllTokens(line, '|'); + if (attributes.length != ITEM_COUNT) { + LOG.debug("Wrong format. Skipping line " + line); + continue; + } + + String revisionString = attributes[REVISION_INDEX]; + + if (revisionString.equals(givenRevision)) { + return currentFileName; + } + + Set filesDeleted; + Map copies; + + filesDeleted = parseFileList(attributes[FILES_DELETED_INDEX]); + copies = parseCopiesFileList(attributes[FILES_COPIED_INDEX]); + // Only keep renames, i.e. copies where the source file is also deleted. + Iterator keys = copies.keySet().iterator(); + while (keys.hasNext()) { + String s = keys.next(); + if (!filesDeleted.contains(s)) { + keys.remove(); + } + } + + if (copies.containsValue(currentFileName)) { + for (String key : copies.keySet()) { + if (copies.get(key).equals(currentFileName)) { + currentFileName = key; + break; + } + } + } + } catch (NumberFormatException e) { + LOG.warn("Error parsing rev in line " + line); + } + } + + return null; + } + + private Set parseFileList(String fileListString) { + if (StringUtils.isEmpty(fileListString)) { + return Collections.emptySet(); + } else { + return new HashSet(Arrays.asList(fileListString.split(" "))); + } + } + + private Map parseCopiesFileList(String fileListString) { + if (StringUtils.isEmpty(fileListString)) { + return Collections.emptyMap(); + } else { + Map copies = new HashMap(); + + String[] filesList = fileListString.split("\\)"); + + for (String files : filesList) { + String[] file = files.split(" \\("); + String target = file[0]; + String source = file[1]; + + copies.put(source, target); + } + + return copies; + } + } +} diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgVersionCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgVersionCommand.java index 1ce522af3d13..4ecc7d35f5de 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgVersionCommand.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgVersionCommand.java @@ -12,16 +12,16 @@ // limitations under the License. package org.zmlx.hg4idea.command; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.*; -import java.nio.charset.Charset; -import java.util.Arrays; +import java.nio.charset.*; +import java.util.*; public class HgVersionCommand { public boolean isValid(String executable) { String hgExecutable = StringUtils.trim(executable); - if (!hgExecutable.contains("hg")) { + if (!hgExecutable.endsWith("hg")) { return false; } ShellCommand shellCommand = new ShellCommand(); diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgWorkingCopyRevisionsCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgWorkingCopyRevisionsCommand.java index a39c1a691f3c..484970af9dbc 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgWorkingCopyRevisionsCommand.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgWorkingCopyRevisionsCommand.java @@ -12,14 +12,13 @@ // limitations under the License. package org.zmlx.hg4idea.command; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vfs.VirtualFile; -import org.apache.commons.lang.StringUtils; -import org.jetbrains.annotations.NotNull; -import org.zmlx.hg4idea.HgRevisionNumber; +import com.intellij.openapi.project.*; +import com.intellij.openapi.vfs.*; +import org.apache.commons.lang.*; +import org.jetbrains.annotations.*; +import org.zmlx.hg4idea.*; -import java.util.Arrays; -import java.util.List; +import java.util.*; public class HgWorkingCopyRevisionsCommand { @@ -29,26 +28,31 @@ public class HgWorkingCopyRevisionsCommand { this.project = project; } - public HgRevisionNumber parent(@NotNull VirtualFile repo) { - return getRevision(repo, "parents"); + public List parents(@NotNull VirtualFile repo) { + return getRevisions(repo, "parents"); + } + + @Nullable + public HgRevisionNumber firstParent(@NotNull VirtualFile repo) { + List parents = parents(repo); + if (parents.isEmpty()) { + //this is possible when we have a freshly initialized mercurial repository + return null; + } + else { + return parents.get(0); + } } public HgRevisionNumber tip(@NotNull VirtualFile repo) { - return getRevision(repo, "tip"); - } - - public HgRevisionNumber parent(@NotNull VirtualFile repo, HgRevisionNumber revision) { - HgCommandService commandService = HgCommandService.getInstance(project); - HgCommandResult result = commandService.execute( - repo, "parent", - Arrays.asList("--rev", revision.getChangeset(), "--template", "{rev}|{node|short}\\n") - ); - List lines = result.getOutputLines(); - if (!lines.isEmpty()) { - String[] parts = StringUtils.split(lines.get(0), '|'); - return HgRevisionNumber.getInstance(parts[0], parts[1]); + List tips = getRevisions(repo, "tip"); + if (tips.size() > 1) { + throw new IllegalStateException("There cannot be multiple tips"); } - return null; + if(!tips.isEmpty()) { + return tips.get(0); + } + else return null; } public HgRevisionNumber identify(@NotNull VirtualFile repo) { @@ -66,17 +70,20 @@ public class HgWorkingCopyRevisionsCommand { return null; } - private HgRevisionNumber getRevision(VirtualFile repo, String command) { + private List getRevisions(VirtualFile repo, String command) { HgCommandService commandService = HgCommandService.getInstance(project); HgCommandResult result = commandService.execute( repo, command, Arrays.asList("--template", "{rev}|{node|short}\\n") ); List lines = result.getOutputLines(); - if (!lines.isEmpty()) { - String[] parts = StringUtils.split(lines.get(0), '|'); - return HgRevisionNumber.getInstance(parts[0], parts[1]); + List revisions = new ArrayList(lines.size()); + + for(String line: lines) { + String[] parts = StringUtils.split(line, '|'); + revisions.add(HgRevisionNumber.getInstance(parts[0], parts[1])); } - return null; + + return revisions; } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/ShellCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/ShellCommand.java index 26956e5d6220..cb85b7d68ebe 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/ShellCommand.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/ShellCommand.java @@ -12,11 +12,11 @@ // limitations under the License. package org.zmlx.hg4idea.command; -import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.diagnostic.*; import java.io.*; -import java.nio.charset.Charset; -import java.util.List; +import java.nio.charset.*; +import java.util.*; final class ShellCommand { @@ -32,7 +32,6 @@ final class ShellCommand { } StringWriter out = new StringWriter(); StringWriter err = new StringWriter(); - HgCommandResult result = new HgCommandResult(out, err); try { ProcessBuilder processBuilder = new ProcessBuilder(commandLine); if (dir != null) { @@ -46,9 +45,10 @@ final class ShellCommand { new InputStreamReader(process.getErrorStream()), err ); process.waitFor(); + int exitValue = process.exitValue(); outReaderThread.join(); errReaderThread.join(); - return result; + return new HgCommandResult(out, err, exitValue ); } catch (IOException e) { throw new ShellCommandException(e); } catch (InterruptedException e) { diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/SocketServer.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/SocketServer.java new file mode 100644 index 000000000000..243ac3b1b18d --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/SocketServer.java @@ -0,0 +1,93 @@ +// Copyright 2008-2010 Victor Iacoban +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under +// the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions and +// limitations under the License. +package org.zmlx.hg4idea.command; + +import java.io.*; +import java.net.*; + +/** + * Common server class that contains the boiler-plate code to set up a server socket. + * The actual logic is delegated to the Protocol instance. + */ +public class SocketServer { + protected Thread serverThread; + protected ServerSocket serverSocket; + private final Protocol protocol; + + public SocketServer(Protocol protocol) { + this.protocol = protocol; + } + + public int start() throws IOException { + serverSocket = new ServerSocket(0); + int port = serverSocket.getLocalPort(); + + String name = "hg4idea prompt server"; + serverThread = new Thread(name) { + @Override + public void run() { + try { + boolean _continue = true; + while (_continue) { + Socket socket = serverSocket.accept(); + _continue = protocol.handleConnection(socket); + } + } catch (SocketException e) { + //socket was closed, that's OK + } catch (IOException e) { + throw new RuntimeException(e); //TODO implement catch clause + } + } + }; + serverThread.start(); + + return port; + } + + public void stop() { + serverThread.interrupt(); + try { + serverSocket.close(); + } catch (IOException e) { + throw new RuntimeException(e); //TODO implement catch clause + } + + } + + public static abstract class Protocol { + + /** + * Override this method to implement the actual logic of the protocol. + * + * @param socket The connected socket + * @return true if the server should keep listening for new incoming requests, + * false if the server handling the protocol can be shutdown. + * + * @throws IOException when the communication over the socket gives errors. + */ + public abstract boolean handleConnection(Socket socket) throws IOException; + + protected byte[] readDataBlock(DataInputStream inputStream) throws IOException { + int length = inputStream.readInt(); + byte[] data = new byte[length]; + inputStream.readFully(data); + return data; + } + + protected void sendDataBlock(DataOutputStream out, byte[] data) throws IOException { + out.writeInt(data.length); + out.write(data); + } + } + +} diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCachingCommitedChangesProvider.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCachingCommitedChangesProvider.java index 8a41340b420d..ac0bd625536b 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCachingCommitedChangesProvider.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCachingCommitedChangesProvider.java @@ -12,50 +12,27 @@ // limitations under the License. package org.zmlx.hg4idea.provider; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vcs.CachingCommittedChangesProvider; -import com.intellij.openapi.vcs.ChangeListColumn; +import com.intellij.openapi.project.*; +import com.intellij.openapi.vcs.*; import com.intellij.openapi.vcs.FilePath; -import com.intellij.openapi.vcs.RepositoryLocation; -import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vcs.changes.Change; -import com.intellij.openapi.vcs.changes.committed.DecoratorManager; -import com.intellij.openapi.vcs.changes.committed.VcsCommittedListsZipper; -import com.intellij.openapi.vcs.changes.committed.VcsCommittedViewAuxiliary; -import com.intellij.openapi.vcs.history.VcsRevisionNumber; -import com.intellij.openapi.vcs.versionBrowser.ChangeBrowserSettings; -import com.intellij.openapi.vcs.versionBrowser.ChangesBrowserSettingsEditor; -import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.AsynchConsumer; -import com.intellij.vcsUtil.VcsUtil; -import org.apache.commons.lang.StringUtils; -import org.jetbrains.annotations.Nls; -import org.jetbrains.annotations.Nullable; -import org.zmlx.hg4idea.HgContentRevision; -import org.zmlx.hg4idea.HgFile; -import org.zmlx.hg4idea.HgFileRevision; -import org.zmlx.hg4idea.HgRevisionNumber; -import org.zmlx.hg4idea.command.HgLogCommand; -import org.zmlx.hg4idea.command.HgShowConfigCommand; -import org.zmlx.hg4idea.command.HgWorkingCopyRevisionsCommand; +import com.intellij.openapi.vcs.changes.*; +import com.intellij.openapi.vcs.changes.committed.*; +import com.intellij.openapi.vcs.history.*; +import com.intellij.openapi.vcs.versionBrowser.*; +import com.intellij.openapi.vfs.*; +import com.intellij.util.*; +import com.intellij.vcsUtil.*; +import org.apache.commons.lang.*; +import org.jetbrains.annotations.*; +import org.zmlx.hg4idea.*; +import org.zmlx.hg4idea.command.*; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.File; -import java.io.IOException; -import java.net.MalformedURLException; -import java.util.Collection; -import java.util.Date; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; +import java.io.*; +import java.util.*; public class HgCachingCommitedChangesProvider implements CachingCommittedChangesProvider { - private static final int DEFAULT_MAX_COUNT = 500; - private final Project project; public HgCachingCommitedChangesProvider(Project project) { @@ -66,10 +43,33 @@ public class HgCachingCommitedChangesProvider return 0; } + public CommittedChangeList readChangeList(RepositoryLocation repositoryLocation, + DataInput dataInput) throws IOException { + HgRevisionNumber revision = HgRevisionNumber.getInstance( + dataInput.readUTF(), + dataInput.readUTF() + ); + String committerName = dataInput.readUTF(); + String comment = dataInput.readUTF(); + Date commitDate = new Date(dataInput.readLong()); + int changesCount = dataInput.readInt(); + List changes = new ArrayList(); + for (int i = 0; i < changesCount; i++) { + HgContentRevision beforeRevision = readRevision(repositoryLocation, dataInput); + HgContentRevision afterRevision = readRevision(repositoryLocation, dataInput); + changes.add(new Change(beforeRevision, afterRevision)); + } + return new HgCommitedChangeList( + revision, comment, + committerName, + commitDate, + changes); + } + public void writeChangeList(DataOutput dataOutput, CommittedChangeList committedChangeList) throws IOException { HgCommitedChangeList changeList = (HgCommitedChangeList) committedChangeList; - writeRevisionNumber(dataOutput, changeList.getRevisionNumber()); + writeRevisionNumber(dataOutput, changeList.getRevision()); dataOutput.writeUTF(changeList.getCommitterName()); dataOutput.writeUTF(changeList.getComment()); dataOutput.writeLong(changeList.getCommitDate().getTime()); @@ -80,38 +80,10 @@ public class HgCachingCommitedChangesProvider } } - public CommittedChangeList readChangeList(RepositoryLocation repositoryLocation, - DataInput dataInput) throws IOException { - HgRevisionNumber revisionNumber = readRevisionNumber(dataInput); - String committerName = dataInput.readUTF(); - String comment = dataInput.readUTF(); - Date commitDate = new Date(dataInput.readLong()); - int changesCount = dataInput.readInt(); - List changes = new LinkedList(); - for (int i = 0; i < changesCount; i++) { - HgContentRevision beforeRevision = readRevision(repositoryLocation, dataInput); - HgContentRevision afterRevision = readRevision(repositoryLocation, dataInput); - Change change = new Change(beforeRevision, afterRevision); - changes.add(change); - } - return new HgCommitedChangeList(comment, committerName, revisionNumber, commitDate, changes); - } - - private void writeRevision(DataOutput dataOutput, HgContentRevision revision) throws IOException { - if (revision == null) { - dataOutput.writeUTF(""); - dataOutput.writeUTF(""); - dataOutput.writeUTF(""); - } else { - dataOutput.writeUTF(revision.getFile().getIOFile().toString()); - writeRevisionNumber(dataOutput, revision.getRevisionNumber()); - } - } - - private HgContentRevision readRevision(RepositoryLocation repositoryLocation, DataInput dataInput) - throws IOException { + private HgContentRevision readRevision(RepositoryLocation repositoryLocation, DataInput dataInput) throws IOException { String revisionPath = dataInput.readUTF(); HgRevisionNumber revisionNumber = readRevisionNumber(dataInput); + if (!StringUtils.isEmpty(revisionPath)) { VirtualFile root = ((HgRepositoryLocation) repositoryLocation).getRoot(); return new HgContentRevision( @@ -124,10 +96,14 @@ public class HgCachingCommitedChangesProvider } } - private void writeRevisionNumber(DataOutput dataOutput, HgRevisionNumber revisionNumber) - throws IOException { - dataOutput.writeUTF(revisionNumber.getRevision()); - dataOutput.writeUTF(revisionNumber.getChangeset()); + private void writeRevision(DataOutput dataOutput, HgContentRevision revision) throws IOException { + if (revision == null) { + dataOutput.writeUTF(""); + writeRevisionNumber(dataOutput, HgRevisionNumber.getInstance("", "")); + } else { + dataOutput.writeUTF(revision.getFile().getIOFile().toString()); + writeRevisionNumber(dataOutput, revision.getRevisionNumber()); + } } private HgRevisionNumber readRevisionNumber(DataInput dataInput) throws IOException { @@ -136,6 +112,11 @@ public class HgCachingCommitedChangesProvider return HgRevisionNumber.getInstance(revisionRevision, revisionChangeset); } + private void writeRevisionNumber(DataOutput dataOutput, HgRevisionNumber revisionNumber) throws IOException { + dataOutput.writeUTF(revisionNumber.getRevision()); + dataOutput.writeUTF(revisionNumber.getChangeset()); + } + public boolean isMaxCountSupported() { return true; } @@ -157,15 +138,15 @@ public class HgCachingCommitedChangesProvider public boolean isChangeLocallyAvailable(FilePath filePath, @Nullable VcsRevisionNumber localRevision, VcsRevisionNumber changeRevision, CommittedChangeList committedChangeList) { - HgRevisionNumber hgLocalRevision = (HgRevisionNumber) localRevision; - HgRevisionNumber hgChangeRevision = (HgRevisionNumber) changeRevision; - - return hgLocalRevision != null && hgChangeRevision != null - && hgLocalRevision.getRevisionAsInt() >= hgChangeRevision.getRevisionAsInt(); + return localRevision != null && localRevision.compareTo(changeRevision) >= 0; } public boolean refreshIncomingWithCommitted() { - return true; + return false; + } + + public void loadCommittedChanges(ChangeBrowserSettings changeBrowserSettings, RepositoryLocation repositoryLocation, int i, AsynchConsumer committedChangeListAsynchConsumer) throws VcsException { + throw new UnsupportedOperationException(); //TODO implement method } public ChangeBrowserSettings createDefaultSettings() { @@ -181,17 +162,7 @@ public class HgCachingCommitedChangesProvider if (repo == null) { return null; } - HgShowConfigCommand configCommand = new HgShowConfigCommand(project); - String defaultPath = configCommand.getDefaultPath(repo); - VirtualFile baseDir = project.getBaseDir(); - if (StringUtils.isBlank(defaultPath) && baseDir != null) { - try { - defaultPath = new File(baseDir.getPath()).toURI().toURL().toString(); - } catch (MalformedURLException e) { - throw new RuntimeException(e); - } - } - return new HgRepositoryLocation(defaultPath, repo); + return new HgRepositoryLocation(repo.getUrl(), repo); } public RepositoryLocation getLocationFor(FilePath root, String repositoryPath) { @@ -212,54 +183,61 @@ public class HgCachingCommitedChangesProvider HgLogCommand hgLogCommand = new HgLogCommand(project); hgLogCommand.setLogFile(false); - List localRevisions = - hgLogCommand.execute(hgFile, maxCount > 0 ? maxCount : DEFAULT_MAX_COUNT); + List localRevisions = hgLogCommand.execute(hgFile, maxCount == 0 ? -1 : maxCount, true); //can be zero + List incomingRevisions = new HgIncomingCommand(project).execute(root); + + Collections.reverse(localRevisions); for (HgFileRevision revision : localRevisions) { HgRevisionNumber vcsRevisionNumber = revision.getRevisionNumber(); - List changes = new LinkedList(); - for (String file : revision.getFilesModified()) { - changes.add(createChange(root, vcsRevisionNumber, file, file)); + HgRevisionNumber firstParent = vcsRevisionNumber.getParents().get(0); + List changes = new ArrayList(); + for (String file : revision.getModifiedFiles()) { + changes.add(createChange(root, file, firstParent, file, vcsRevisionNumber, FileStatus.MODIFIED)); } - for (String file : revision.getFilesAdded()) { - changes.add(createChange(root, vcsRevisionNumber, null, file)); + for (String file : revision.getAddedFiles()) { + changes.add(createChange(root, null, null, file, vcsRevisionNumber, FileStatus.ADDED)); } - for (String file : revision.getFilesDeleted()) { - changes.add(createChange(root, vcsRevisionNumber, file, null)); + for (String file : revision.getDeletedFiles()) { + changes.add(createChange(root, file, firstParent, null, vcsRevisionNumber, FileStatus.DELETED)); } - for (Map.Entry copiedFile : revision.getFilesCopied().entrySet()) { - changes.add( - createChange(root, vcsRevisionNumber, copiedFile.getKey(), copiedFile.getValue()) - ); + for (Map.Entry copiedFile : revision.getCopiedFiles().entrySet()) { + changes.add(createChange(root, copiedFile.getKey(), firstParent, copiedFile.getValue(), vcsRevisionNumber, FileStatus.ADDED)); } - result.add( - new HgCommitedChangeList( - revision.getCommitMessage(), - revision.getAuthor(), - vcsRevisionNumber, - revision.getRevisionDate(), - changes - ) - ); + + result.add(new HgCommitedChangeList( + vcsRevisionNumber, revision.getCommitMessage(), + revision.getAuthor(), + revision.getRevisionDate(), + changes)); + } + Collections.reverse(result); return result; } - private Change createChange(VirtualFile root, HgRevisionNumber vcsRevisionNumber, - String fileBefore, String fileAfter) { + private Change createChange(VirtualFile root, + String fileBefore, + HgRevisionNumber revisionBefore, + String fileAfter, + HgRevisionNumber revisionAfter, + FileStatus aStatus ) { + HgContentRevision beforeRevision = fileBefore == null ? null : new HgContentRevision( project, new HgFile(root, new File(root.getPath(), fileBefore)), - new HgWorkingCopyRevisionsCommand(project).parent(root, vcsRevisionNumber) + revisionBefore ); - HgContentRevision afterRevision = fileAfter == null ? null : new HgContentRevision( - project, - new HgFile(root, new File(root.getPath(), fileAfter)), - vcsRevisionNumber - ); - - return new Change(beforeRevision, afterRevision); + project, + new HgFile(root, new File(root.getPath(), fileAfter)), + revisionAfter + ); + return new Change( + beforeRevision, + afterRevision, + aStatus + ); } public ChangeListColumn[] getColumns() { @@ -277,11 +255,6 @@ public class HgCachingCommitedChangesProvider } public int getUnlimitedCountValue() { - return DEFAULT_MAX_COUNT; - } - - public void loadCommittedChanges(ChangeBrowserSettings changeBrowserSettings, - RepositoryLocation repositoryLocation, int i, - AsynchConsumer committedChangeListAsynchConsumer) throws VcsException { + return -1; } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgChangeProvider.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgChangeProvider.java index c7b62511ec53..296aa95bf1ce 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgChangeProvider.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgChangeProvider.java @@ -12,35 +12,17 @@ // limitations under the License. package org.zmlx.hg4idea.provider; -import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.openapi.project.Project; +import com.intellij.openapi.progress.*; +import com.intellij.openapi.project.*; import com.intellij.openapi.vcs.FilePath; -import com.intellij.openapi.vcs.FileStatus; -import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vcs.VcsKey; -import com.intellij.openapi.vcs.changes.Change; -import com.intellij.openapi.vcs.changes.ChangeListManagerGate; -import com.intellij.openapi.vcs.changes.ChangeProvider; -import com.intellij.openapi.vcs.changes.ChangelistBuilder; -import com.intellij.openapi.vcs.changes.ContentRevision; -import com.intellij.openapi.vcs.changes.VcsDirtyScope; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.vcsUtil.VcsUtil; -import org.zmlx.hg4idea.HgFile; -import org.zmlx.hg4idea.HgRevisionNumber; -import org.zmlx.hg4idea.HgContentRevision; -import org.zmlx.hg4idea.command.HgChange; -import org.zmlx.hg4idea.command.HgFileStatusEnum; -import org.zmlx.hg4idea.command.HgResolveCommand; -import org.zmlx.hg4idea.command.HgResolveStatusEnum; -import org.zmlx.hg4idea.command.HgStatusCommand; -import org.zmlx.hg4idea.command.HgWorkingCopyRevisionsCommand; +import com.intellij.openapi.vcs.*; +import com.intellij.openapi.vcs.changes.*; +import com.intellij.openapi.vfs.*; +import com.intellij.vcsUtil.*; +import org.zmlx.hg4idea.*; +import org.zmlx.hg4idea.command.*; -import java.util.EnumMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; public class HgChangeProvider implements ChangeProvider { @@ -97,7 +79,7 @@ public class HgChangeProvider implements ChangeProvider { sendChanges(builder, hgChanges, new HgResolveCommand(project).list(repo), new HgWorkingCopyRevisionsCommand(project).identify(repo), - new HgWorkingCopyRevisionsCommand(project).parent(repo) + new HgWorkingCopyRevisionsCommand(project).firstParent(repo) ); processedRoots.add(repo); } @@ -115,12 +97,18 @@ public class HgChangeProvider implements ChangeProvider { builder.processChange( new Change( new HgContentRevision(project, beforeFile, parentRevision), - HgCurrentContentRevisionFactory.build(afterFile, workingRevision), + HgCurrentContentRevision.create(afterFile, workingRevision), FileStatus.MERGED_WITH_CONFLICTS ), vcsKey); continue; } + if (isDeleteOfCopiedFile(change, changes)) { + // Don't register the 'delete' change for renamed or moved files; IDEA already handles these + // itself. + continue; + } + HgChangeProcessor processor = PROCESSORS.get(status); if (processor != null) { processor.process(project, vcsKey, builder, @@ -129,131 +117,156 @@ public class HgChangeProvider implements ChangeProvider { } } -} - - -enum HgChangeProcessor { - ADDED() { - @Override - void process(Project project, VcsKey vcsKey, ChangelistBuilder builder, - HgRevisionNumber currentNumber, HgRevisionNumber parentRevision, - HgFile beforeFile, HgFile afterFile) { - processChange( - null, - HgCurrentContentRevisionFactory.build(afterFile, currentNumber), - FileStatus.ADDED, - builder, - vcsKey - ); + private boolean isDeleteOfCopiedFile(HgChange change, Set changes) { + if (change.getStatus().equals(HgFileStatusEnum.DELETED)) { + for (HgChange otherChange : changes) { + if (otherChange.getStatus().equals(HgFileStatusEnum.COPY) && + otherChange.beforeFile().equals(change.afterFile())) { + return true; + } + } } - }, - DELETED() { - @Override - void process(Project project, VcsKey vcsKey, ChangelistBuilder builder, - HgRevisionNumber currentNumber, HgRevisionNumber parentRevision, - HgFile beforeFile, HgFile afterFile) { - processChange( - new HgContentRevision(project, beforeFile, parentRevision), - null, - FileStatus.DELETED, - builder, - vcsKey - ); - } - }, - - IGNORED() { - @Override - void process(Project project, VcsKey vcsKey, ChangelistBuilder builder, - HgRevisionNumber currentNumber, HgRevisionNumber parentRevision, - HgFile beforeFile, HgFile afterFile) { - builder.processIgnoredFile(VcsUtil.getVirtualFile(afterFile.getFile())); - } - }, - - MISSING() { - @Override - void process(Project project, VcsKey vcsKey, ChangelistBuilder builder, - HgRevisionNumber currentNumber, HgRevisionNumber parentRevision, - HgFile beforeFile, HgFile afterFile) { - processChange( - new HgContentRevision(project, beforeFile, parentRevision), - null, - FileStatus.DELETED_FROM_FS, - builder, - vcsKey - ); - } - }, - - COPIED() { - @Override - void process(Project project, VcsKey vcsKey, ChangelistBuilder builder, - HgRevisionNumber currentNumber, HgRevisionNumber parentRevision, - HgFile beforeFile, HgFile afterFile) { - processChange( - new HgContentRevision(project, beforeFile, parentRevision), - HgCurrentContentRevisionFactory.build(afterFile, currentNumber), - FileStatus.MODIFIED, - builder, - vcsKey - ); - } - }, - - MODIFIED() { - @Override - void process(Project project, VcsKey vcsKey, ChangelistBuilder builder, - HgRevisionNumber currentNumber, HgRevisionNumber parentRevision, - HgFile beforeFile, HgFile afterFile) { - processChange( - new HgContentRevision(project, beforeFile, parentRevision), - HgCurrentContentRevisionFactory.build(afterFile, currentNumber), - FileStatus.MODIFIED, - builder, - vcsKey - ); - } - }, - - UNMODIFIED() { - @Override - void process(Project project, VcsKey vcsKey, ChangelistBuilder builder, - HgRevisionNumber currentNumber, HgRevisionNumber parentRevision, - HgFile beforeFile, HgFile afterFile) { - //DO NOTHING - } - }, - - UNVERSIONED() { - @Override - void process(Project project, VcsKey vcsKey, ChangelistBuilder builder, - HgRevisionNumber currentNumber, HgRevisionNumber parentRevision, - HgFile beforeFile, HgFile afterFile) { - builder.processUnversionedFile(VcsUtil.getVirtualFile(afterFile.getFile())); - } - }; - - abstract void process( - Project project, - VcsKey vcsKey, - ChangelistBuilder builder, - HgRevisionNumber currentNumber, - HgRevisionNumber parentRevision, - HgFile beforeFile, - HgFile afterFile - ); - - final void processChange(ContentRevision contentRevisionBefore, - ContentRevision contentRevisionAfter, FileStatus fileStatus, - ChangelistBuilder builder, VcsKey vcsKey) { - if (contentRevisionBefore == null && contentRevisionAfter == null) { - return; - } - builder.processChange( - new Change(contentRevisionBefore, contentRevisionAfter, fileStatus), - vcsKey - ); + return false; } -} + + private enum HgChangeProcessor { + ADDED() { + @Override + void process(Project project, VcsKey vcsKey, ChangelistBuilder builder, + HgRevisionNumber currentNumber, HgRevisionNumber parentRevision, + HgFile beforeFile, HgFile afterFile) { + processChange( + null, + HgCurrentContentRevision.create(afterFile, currentNumber), + FileStatus.ADDED, + builder, + vcsKey + ); + } + }, + + DELETED() { + @Override + void process(Project project, VcsKey vcsKey, ChangelistBuilder builder, + HgRevisionNumber currentNumber, HgRevisionNumber parentRevision, + HgFile beforeFile, HgFile afterFile) { + processChange( + new HgContentRevision(project, beforeFile, parentRevision), + null, + FileStatus.DELETED, + builder, + vcsKey + ); + } + }, + + IGNORED() { + @Override + void process(Project project, VcsKey vcsKey, ChangelistBuilder builder, + HgRevisionNumber currentNumber, HgRevisionNumber parentRevision, + HgFile beforeFile, HgFile afterFile) { + builder.processIgnoredFile(VcsUtil.getVirtualFile(afterFile.getFile())); + } + }, + + MISSING() { + @Override + void process(Project project, VcsKey vcsKey, ChangelistBuilder builder, + HgRevisionNumber currentNumber, HgRevisionNumber parentRevision, + HgFile beforeFile, HgFile afterFile) { + processChange( + new HgContentRevision(project, beforeFile, parentRevision), + null, + FileStatus.DELETED_FROM_FS, + builder, + vcsKey + ); + } + }, + + COPIED() { + @Override + void process(Project project, VcsKey vcsKey, ChangelistBuilder builder, + HgRevisionNumber currentNumber, HgRevisionNumber parentRevision, + HgFile beforeFile, HgFile afterFile) { + if (beforeFile.getFile().exists()) { + // The original file exists so this is a duplication of the file. + // Don't create the before ContentRevision or IDEA will think + // this was a rename. + processChange( + null, + HgCurrentContentRevision.create(afterFile, currentNumber), + FileStatus.ADDED, + builder, + vcsKey + ); + } else { + // The original file does not exists so this is a rename. + processChange( + new HgContentRevision(project, beforeFile, parentRevision), + HgCurrentContentRevision.create(afterFile, currentNumber), + FileStatus.MODIFIED, + builder, + vcsKey + ); + } + } + }, + + MODIFIED() { + @Override + void process(Project project, VcsKey vcsKey, ChangelistBuilder builder, + HgRevisionNumber currentNumber, HgRevisionNumber parentRevision, + HgFile beforeFile, HgFile afterFile) { + processChange( + new HgContentRevision(project, beforeFile, parentRevision), + HgCurrentContentRevision.create(afterFile, currentNumber), + FileStatus.MODIFIED, + builder, + vcsKey + ); + } + }, + + UNMODIFIED() { + @Override + void process(Project project, VcsKey vcsKey, ChangelistBuilder builder, + HgRevisionNumber currentNumber, HgRevisionNumber parentRevision, + HgFile beforeFile, HgFile afterFile) { + //DO NOTHING + } + }, + + UNVERSIONED() { + @Override + void process(Project project, VcsKey vcsKey, ChangelistBuilder builder, + HgRevisionNumber currentNumber, HgRevisionNumber parentRevision, + HgFile beforeFile, HgFile afterFile) { + builder.processUnversionedFile(VcsUtil.getVirtualFile(afterFile.getFile())); + } + }; + + abstract void process( + Project project, + VcsKey vcsKey, + ChangelistBuilder builder, + HgRevisionNumber currentNumber, + HgRevisionNumber parentRevision, + HgFile beforeFile, + HgFile afterFile + ); + + final void processChange(ContentRevision contentRevisionBefore, + ContentRevision contentRevisionAfter, FileStatus fileStatus, + ChangelistBuilder builder, VcsKey vcsKey) { + if (contentRevisionBefore == null && contentRevisionAfter == null) { + return; + } + builder.processChange( + new Change(contentRevisionBefore, contentRevisionAfter, fileStatus), + vcsKey + ); + } + } +} \ No newline at end of file diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCheckoutProvider.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCheckoutProvider.java new file mode 100644 index 000000000000..81d2e75a61d0 --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCheckoutProvider.java @@ -0,0 +1,80 @@ +/* + * Copyright 2000-2009 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.zmlx.hg4idea.provider; + +import com.intellij.openapi.application.*; +import com.intellij.openapi.fileEditor.*; +import com.intellij.openapi.project.*; +import com.intellij.openapi.vcs.*; +import com.intellij.openapi.vfs.*; +import org.jetbrains.annotations.*; +import org.zmlx.hg4idea.*; +import org.zmlx.hg4idea.command.*; +import org.zmlx.hg4idea.ui.*; + +import java.io.*; + +/** + * Checkout provider for Mercurial + */ +public class HgCheckoutProvider implements CheckoutProvider { + + /** + * {@inheritDoc} + */ + public void doCheckout(@NotNull final Project project, @Nullable final Listener listener) { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + FileDocumentManager.getInstance().saveAllDocuments(); + } + }); + + HgCloneDialog dialog = new HgCloneDialog(project); + dialog.show(); + if (!dialog.isOK()) { + return; + } + final VirtualFile destinationParent = LocalFileSystem.getInstance().findFileByIoFile(new File(dialog.getParentDirectory())); + if (destinationParent == null) { + return; + } + String targetDir = destinationParent.getPath() + File.separator + dialog.getDirectoryName(); + + final String sourceRepositoryURL = dialog.getSourceRepositoryURL(); + HgCloneCommand clone = new HgCloneCommand(project); + clone.setRepositoryURL(sourceRepositoryURL); + clone.setDirectory(targetDir); + HgCommandResult result = clone.execute(); + + HgUtil.markDirectoryDirty(project,destinationParent); + + if (result.getExitValue() == 0) { + if (listener != null) { + listener.directoryCheckedOut(new File(dialog.getParentDirectory(), dialog.getDirectoryName())); + } + } + if (listener != null) { + listener.checkoutCompleted(); + } + } + + /** + * {@inheritDoc} + */ + public String getVcsName() { + return "_Mercurial"; + } +} diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCommitedChangeList.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCommitedChangeList.java index 9091055881d4..eaaf8bfb527e 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCommitedChangeList.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCommitedChangeList.java @@ -1,41 +1,20 @@ -// Copyright 2008-2010 Victor Iacoban -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software distributed under -// the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, -// either express or implied. See the License for the specific language governing permissions and -// limitations under the License. package org.zmlx.hg4idea.provider; -import com.intellij.openapi.vcs.changes.Change; -import com.intellij.openapi.vcs.versionBrowser.CommittedChangeListImpl; -import org.zmlx.hg4idea.HgRevisionNumber; +import com.intellij.openapi.vcs.changes.*; +import com.intellij.openapi.vcs.versionBrowser.*; +import org.zmlx.hg4idea.*; -import java.util.Collection; -import java.util.Date; +import java.util.*; -final class HgCommitedChangeList extends CommittedChangeListImpl { +public class HgCommitedChangeList extends CommittedChangeListImpl { + private HgRevisionNumber revision; - private HgRevisionNumber revisionNumber; - - public HgCommitedChangeList(String comment, String committerName, - HgRevisionNumber revisionNumber, Date date, Collection commitDate) { - super(buildDisplayName(revisionNumber, comment), - comment, committerName, revisionNumber.getRevisionAsInt(), date, commitDate); - this.revisionNumber = revisionNumber; + public HgCommitedChangeList(HgRevisionNumber revision, String comment, String committerName, Date commitDate, Collection changes) { + super(revision.asString() + ": " + comment, comment, committerName, revision.getRevisionAsLong(), commitDate, changes); + this.revision = revision; } - public HgRevisionNumber getRevisionNumber() { - return revisionNumber; + public HgRevisionNumber getRevision() { + return revision; } - - private static String buildDisplayName(HgRevisionNumber number, String message) { - return number.asString() + " " + message; - } - } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCurrentBinaryContentRevision.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCurrentBinaryContentRevision.java index 846b205e9e36..1c48815de409 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCurrentBinaryContentRevision.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCurrentBinaryContentRevision.java @@ -12,33 +12,22 @@ // limitations under the License. package org.zmlx.hg4idea.provider; -import org.zmlx.hg4idea.HgFile; -import org.jetbrains.annotations.Nullable; -import com.intellij.openapi.vcs.history.VcsRevisionNumber; -import com.intellij.openapi.vcs.changes.BinaryContentRevision; -import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vcs.changes.*; +import com.intellij.openapi.vcs.history.*; +import org.jetbrains.annotations.*; +import org.zmlx.hg4idea.*; -import java.io.IOException; +final class HgCurrentBinaryContentRevision extends CurrentBinaryContentRevision { + private VcsRevisionNumber revisionNumber; -final class HgCurrentBinaryContentRevision - extends HgCurrentContentRevision implements BinaryContentRevision { - - private final VirtualFile virtualFile; - - HgCurrentBinaryContentRevision(HgFile hgFile, - VcsRevisionNumber revisionNumber, VirtualFile virtualFile) { - super(hgFile, revisionNumber, virtualFile); - this.virtualFile = virtualFile; + HgCurrentBinaryContentRevision(HgFile hgFile, VcsRevisionNumber revisionNumber) { + super(hgFile.toFilePath()); + this.revisionNumber = revisionNumber; } - @Nullable - public byte[] getBinaryContent() throws VcsException { - try { - return virtualFile.contentsToByteArray(); - } catch (IOException e) { - throw new VcsException(e); - } + @NotNull + @Override + public VcsRevisionNumber getRevisionNumber() { + return revisionNumber; } - } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCurrentContentRevision.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCurrentContentRevision.java index ed093f922d3a..65338a18991c 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCurrentContentRevision.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCurrentContentRevision.java @@ -12,55 +12,36 @@ // limitations under the License. package org.zmlx.hg4idea.provider; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.fileEditor.FileDocumentManager; -import com.intellij.openapi.util.Computable; -import com.intellij.openapi.vcs.FilePath; -import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vcs.changes.ContentRevision; -import com.intellij.openapi.vcs.history.VcsRevisionNumber; -import com.intellij.openapi.vfs.VirtualFile; -import org.jetbrains.annotations.NotNull; -import org.zmlx.hg4idea.HgFile; +import com.intellij.openapi.vcs.changes.*; +import com.intellij.openapi.vcs.history.*; +import com.intellij.openapi.vfs.*; +import com.intellij.vcsUtil.*; +import org.jetbrains.annotations.*; +import org.zmlx.hg4idea.*; -class HgCurrentContentRevision implements ContentRevision { - - private final HgFile hgFile; +class HgCurrentContentRevision extends CurrentContentRevision { private final VcsRevisionNumber revisionNumber; - private final VirtualFile virtualFile; - private FilePath filePath; - - public HgCurrentContentRevision(HgFile hgFile, - VcsRevisionNumber revisionNumber, VirtualFile virtualFile) { - this.hgFile = hgFile; + public HgCurrentContentRevision(HgFile hgFile, VcsRevisionNumber revisionNumber, VirtualFile virtualFile) { + super( hgFile.toFilePath() ); this.revisionNumber = revisionNumber; - this.virtualFile = virtualFile; - } - - public String getContent() throws VcsException { - Document doc = ApplicationManager.getApplication().runReadAction(new Computable() { - public Document compute() { - return FileDocumentManager.getInstance().getDocument(virtualFile); - } - }); - if (doc == null) { - return null; - } - return doc.getText(); - } - - @NotNull - public FilePath getFile() { - if (filePath == null) { - filePath = hgFile.toFilePath(); - } - return filePath; } @NotNull public VcsRevisionNumber getRevisionNumber() { return revisionNumber; } + + public static ContentRevision create(HgFile hgFile, HgRevisionNumber revision) { + VirtualFile virtualFile = VcsUtil.getVirtualFile(hgFile.getFile()); + if (virtualFile == null) { + return null; + } + + if (!virtualFile.getFileType().isBinary()) { + return new HgCurrentContentRevision(hgFile, revision, virtualFile); + } + + return new HgCurrentBinaryContentRevision(hgFile, revision); + } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCurrentContentRevisionFactory.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCurrentContentRevisionFactory.java deleted file mode 100644 index 26a496d9a252..000000000000 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCurrentContentRevisionFactory.java +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2008-2010 Victor Iacoban -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software distributed under -// the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, -// either express or implied. See the License for the specific language governing permissions and -// limitations under the License. -package org.zmlx.hg4idea.provider; - -import com.intellij.openapi.vcs.changes.ContentRevision; -import com.intellij.openapi.vcs.history.VcsRevisionNumber; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.vcsUtil.VcsUtil; -import org.jetbrains.annotations.Nullable; -import org.zmlx.hg4idea.HgFile; - -public final class HgCurrentContentRevisionFactory { - - private HgCurrentContentRevisionFactory() { } - - @Nullable - public static ContentRevision build(HgFile hgFile, VcsRevisionNumber revision) { - VirtualFile virtualFile = VcsUtil.getVirtualFile(hgFile.getFile()); - if (virtualFile == null) { - return null; - } - - if (!virtualFile.getFileType().isBinary()) { - return new HgCurrentContentRevision(hgFile, revision, virtualFile); - } - - return new HgCurrentBinaryContentRevision(hgFile, revision, virtualFile); - } - -} diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgDiffProvider.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgDiffProvider.java index 7a970f23a54e..1e0935ac0c3b 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgDiffProvider.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgDiffProvider.java @@ -12,19 +12,15 @@ // limitations under the License. package org.zmlx.hg4idea.provider; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vcs.changes.ContentRevision; -import com.intellij.openapi.vcs.diff.DiffProvider; -import com.intellij.openapi.vcs.diff.ItemLatestState; -import com.intellij.openapi.vcs.history.VcsRevisionNumber; +import com.intellij.openapi.project.*; import com.intellij.openapi.vcs.FilePath; -import com.intellij.openapi.vfs.VfsUtil; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.vcsUtil.VcsUtil; -import org.zmlx.hg4idea.HgFile; -import org.zmlx.hg4idea.HgContentRevision; -import org.zmlx.hg4idea.HgRevisionNumber; -import org.zmlx.hg4idea.command.HgWorkingCopyRevisionsCommand; +import com.intellij.openapi.vcs.changes.*; +import com.intellij.openapi.vcs.diff.*; +import com.intellij.openapi.vcs.history.*; +import com.intellij.openapi.vfs.*; +import com.intellij.vcsUtil.*; +import org.zmlx.hg4idea.*; +import org.zmlx.hg4idea.command.*; public class HgDiffProvider implements DiffProvider { @@ -47,7 +43,7 @@ public class HgDiffProvider implements DiffProvider { } if (currentRevision.isWorkingVersion()) { - return command.parent(vcsRoot); + return command.firstParent(vcsRoot); } return currentRevision; } @@ -78,7 +74,7 @@ public class HgDiffProvider implements DiffProvider { boolean fileExists = filePath.getIOFile().exists(); if (currentRevision.isWorkingVersion()) { - return new ItemLatestState(command.parent(vcsRoot), fileExists, true); + return new ItemLatestState(command.firstParent(vcsRoot), fileExists, true); } return new ItemLatestState(currentRevision, fileExists, true); diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgHistoryProvider.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgHistoryProvider.java index 492a078237f1..29cfc283db40 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgHistoryProvider.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgHistoryProvider.java @@ -12,35 +12,40 @@ // limitations under the License. package org.zmlx.hg4idea.provider; -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.project.Project; +import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.project.*; import com.intellij.openapi.vcs.FilePath; -import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vcs.*; import com.intellij.openapi.vcs.history.*; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.ui.ColumnInfo; -import com.intellij.vcsUtil.VcsUtil; -import org.zmlx.hg4idea.HgFile; -import org.zmlx.hg4idea.HgFileRevision; -import org.zmlx.hg4idea.command.HgLogCommand; +import com.intellij.openapi.vfs.*; +import com.intellij.util.ui.*; +import com.intellij.vcsUtil.*; +import org.jetbrains.annotations.*; +import org.zmlx.hg4idea.*; +import org.zmlx.hg4idea.command.*; import javax.swing.*; -import java.util.List; +import java.util.*; public class HgHistoryProvider implements VcsHistoryProvider { private static final int DEFAULT_LIMIT = 500; - private final Project myProject; + private final Project project; public HgHistoryProvider(Project project) { - this.myProject = project; + this.project = project; } - public VcsDependentHistoryComponents getUICustomization(VcsHistorySession session, JComponent forShortcutRegistration) { + public VcsDependentHistoryComponents getUICustomization(VcsHistorySession session, + JComponent forShortcutRegistration) { return VcsDependentHistoryComponents.createOnlyColumns(new ColumnInfo[0]); } + public AnAction[] getAdditionalActions(Runnable runnable) { + return new AnAction[0]; + } + public boolean isDateOmittable() { return false; } @@ -50,37 +55,84 @@ public class HgHistoryProvider implements VcsHistoryProvider { } public VcsHistorySession createSessionFor(FilePath filePath) throws VcsException { - final VirtualFile vcsRoot = VcsUtil.getVcsRootFor(myProject, filePath); + final VirtualFile vcsRoot = VcsUtil.getVcsRootFor(project, filePath); if (vcsRoot == null) { return null; } - final HgLogCommand logCommand = new HgLogCommand(myProject); - logCommand.setFollowCopies(true); - final HgFile file = new HgFile(vcsRoot, filePath); - final List revisions = logCommand.execute(file, DEFAULT_LIMIT); + HgFile hgFile = new HgFile(vcsRoot, filePath); + List revisions = getHistory(filePath, vcsRoot, project, DEFAULT_LIMIT); + final List result = new LinkedList(revisions); + return new VcsHistorySession() { + @Override + public VcsRevisionNumber getCurrentRevisionNumber() { + return new HgWorkingCopyRevisionsCommand(project).firstParent(vcsRoot); + } - return new VcsAbstractHistorySession(revisions) { + @Override + public HistoryAsTreeProvider getHistoryAsTreeProvider() { + return null; + } + + @Override + public List getRevisionList() { + return result; + } + + @Override + public boolean isCurrentRevision(VcsRevisionNumber vcsRevisionNumber) { + return vcsRevisionNumber.equals(getCurrentRevisionNumber()); + } + + @Override + public boolean shouldBeRefreshed() { + return false; + } + + @Override + public boolean allowAsyncRefresh() { + return false; + } + + @Override + public boolean isContentAvailable(VcsFileRevision vcsFileRevision) { + return false; + } + }; + } + + public void reportAppendableHistory(FilePath filePath, final VcsAppendableHistorySessionPartner partner) throws VcsException { + final VirtualFile vcsRoot = VcsUtil.getVcsRootFor(project, filePath); + List history = getHistory(filePath, vcsRoot, this.project, DEFAULT_LIMIT); + + if (history.size() == 0) return; + + final VcsAbstractHistorySession emptySession = new VcsAbstractHistorySession(Collections.emptyList()) { + @Nullable protected VcsRevisionNumber calcCurrentRevisionNumber() { - return logCommand.execute(file, 1).get(0).getRevisionNumber(); + return new HgWorkingCopyRevisionsCommand(project).firstParent(vcsRoot); } public HistoryAsTreeProvider getHistoryAsTreeProvider() { return null; } }; + partner.reportCreatedEmptySession(emptySession); + + for (HgFileRevision hgFileRevision : history) { + partner.acceptRevision(hgFileRevision); + } + partner.finished(); } - public AnAction[] getAdditionalActions(Runnable runnable) { - return new AnAction[0]; - } + private List getHistory(FilePath filePath, VirtualFile vcsRoot, Project project, int limit) { + HgLogCommand logCommand = new HgLogCommand(project); + logCommand.setFollowCopies(true); + logCommand.setIncludeRemoved(true); - public void reportAppendableHistory(FilePath filePath, final VcsAppendableHistorySessionPartner partner) throws VcsException { - final VcsHistorySession emptySession = createSessionFor(filePath); - partner.reportCreatedEmptySession((VcsAbstractHistorySession) emptySession); + return logCommand.execute(new HgFile(vcsRoot, filePath), limit, false); } public boolean supportsHistoryForDirectories() { return false; } - } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgRollbackEnvironment.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgRollbackEnvironment.java index 44146fcaa9c8..ff9c8938c1d8 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgRollbackEnvironment.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgRollbackEnvironment.java @@ -12,23 +12,18 @@ // limitations under the License. package org.zmlx.hg4idea.provider; -import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.*; import com.intellij.openapi.vcs.FilePath; -import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vcs.changes.Change; -import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager; -import com.intellij.openapi.vcs.changes.ContentRevision; -import com.intellij.openapi.vcs.rollback.RollbackEnvironment; -import com.intellij.openapi.vcs.rollback.RollbackProgressListener; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.vcsUtil.VcsUtil; -import org.zmlx.hg4idea.command.HgRevertCommand; -import org.zmlx.hg4idea.HgVcsMessages; -import org.zmlx.hg4idea.HgFile; -import org.jetbrains.annotations.NotNull; +import com.intellij.openapi.vcs.*; +import com.intellij.openapi.vcs.changes.*; +import com.intellij.openapi.vcs.rollback.*; +import com.intellij.openapi.vfs.*; +import com.intellij.vcsUtil.*; +import org.jetbrains.annotations.*; +import org.zmlx.hg4idea.*; +import org.zmlx.hg4idea.command.*; -import java.util.LinkedList; -import java.util.List; +import java.util.*; public class HgRollbackEnvironment implements RollbackEnvironment { @@ -84,13 +79,23 @@ public class HgRollbackEnvironment implements RollbackEnvironment { private void revert(List filePaths) { VcsDirtyScopeManager dirtyScopeManager = VcsDirtyScopeManager.getInstance(project); - HgRevertCommand command = new HgRevertCommand(project); + + HgWorkingCopyRevisionsCommand identifyCommand = new HgWorkingCopyRevisionsCommand(project); + HgRevertCommand revertCommand = new HgRevertCommand(project); + HgResolveCommand resolveCommand = new HgResolveCommand(project); + for (FilePath filePath : filePaths) { VirtualFile vcsRoot = VcsUtil.getVcsRootFor(project, filePath); if (vcsRoot == null) { continue; } - command.execute(new HgFile(vcsRoot, filePath)); + + HgFile hgFile = new HgFile(vcsRoot, filePath); + + HgRevisionNumber revisionNumber = identifyCommand.firstParent(vcsRoot); + revertCommand.execute(hgFile, revisionNumber, false); + resolveCommand.markResolved(vcsRoot, filePath); + dirtyScopeManager.dirDirtyRecursively(filePath.getParentPath()); } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/annotate/HgAnnotation.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/annotate/HgAnnotation.java index 865264263396..ad700de7e966 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/annotate/HgAnnotation.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/annotate/HgAnnotation.java @@ -12,21 +12,15 @@ // limitations under the License. package org.zmlx.hg4idea.provider.annotate; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vcs.annotate.AnnotationListener; -import com.intellij.openapi.vcs.annotate.FileAnnotation; -import com.intellij.openapi.vcs.annotate.LineAnnotationAspect; -import com.intellij.openapi.vcs.annotate.AnnotationSourceSwitcher; -import com.intellij.openapi.vcs.changes.CurrentContentRevision; -import com.intellij.openapi.vcs.history.VcsFileRevision; -import com.intellij.openapi.vcs.history.VcsRevisionNumber; -import org.apache.commons.lang.StringUtils; -import org.zmlx.hg4idea.HgFile; -import org.zmlx.hg4idea.HgFileRevision; +import com.intellij.openapi.diagnostic.*; +import com.intellij.openapi.vcs.*; +import com.intellij.openapi.vcs.annotate.*; +import com.intellij.openapi.vcs.changes.*; +import com.intellij.openapi.vcs.history.*; +import org.apache.commons.lang.*; +import org.zmlx.hg4idea.*; -import java.util.LinkedList; -import java.util.List; +import java.util.*; public class HgAnnotation implements FileAnnotation { @@ -108,11 +102,6 @@ public class HgAnnotation implements FileAnnotation { return result; } - public boolean revisionsNotEmpty() { - List revisions = getRevisions(); - return revisions != null && !revisions.isEmpty(); - } - class HgLineAnnotationAspect implements LineAnnotationAspect { private final FIELD aspectType; @@ -135,4 +124,7 @@ public class HgAnnotation implements FileAnnotation { } } + public boolean revisionsNotEmpty() { + return true; + } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/annotate/HgAnnotationProvider.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/annotate/HgAnnotationProvider.java index 4f82618b2ac6..02a997132422 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/annotate/HgAnnotationProvider.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/annotate/HgAnnotationProvider.java @@ -12,17 +12,14 @@ // limitations under the License. package org.zmlx.hg4idea.provider.annotate; -import com.intellij.openapi.vcs.annotate.AnnotationProvider; -import com.intellij.openapi.vcs.annotate.FileAnnotation; -import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vcs.history.VcsFileRevision; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.vfs.VfsUtil; -import com.intellij.openapi.project.Project; -import com.intellij.vcsUtil.VcsUtil; -import org.zmlx.hg4idea.command.HgAnnotateCommand; -import org.zmlx.hg4idea.command.HgLogCommand; -import org.zmlx.hg4idea.HgFile; +import com.intellij.openapi.project.*; +import com.intellij.openapi.vcs.*; +import com.intellij.openapi.vcs.annotate.*; +import com.intellij.openapi.vcs.history.*; +import com.intellij.openapi.vfs.*; +import com.intellij.vcsUtil.*; +import org.zmlx.hg4idea.*; +import org.zmlx.hg4idea.command.*; public class HgAnnotationProvider implements AnnotationProvider { @@ -45,7 +42,7 @@ public class HgAnnotationProvider implements AnnotationProvider { return new HgAnnotation( hgFile, hgAnnotateCommand.execute(hgFile), - hgLogCommand.execute(hgFile, DEFAULT_LIMIT) + hgLogCommand.execute(hgFile, DEFAULT_LIMIT, false) ); } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java index 0e837b2e6f1b..19995c49942e 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java @@ -12,29 +12,20 @@ // limitations under the License. package org.zmlx.hg4idea.provider.commit; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vcs.CheckinProjectPanel; +import com.intellij.openapi.application.*; +import com.intellij.openapi.project.*; +import com.intellij.openapi.ui.*; +import com.intellij.openapi.vcs.*; import com.intellij.openapi.vcs.FilePath; -import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vcs.changes.Change; -import com.intellij.openapi.vcs.changes.ChangeList; -import com.intellij.openapi.vcs.changes.ContentRevision; -import com.intellij.openapi.vcs.checkin.CheckinEnvironment; -import com.intellij.openapi.vcs.ui.RefreshableOnComponent; -import com.intellij.openapi.vfs.VfsUtil; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.vcsUtil.VcsUtil; -import org.zmlx.hg4idea.HgFile; -import org.zmlx.hg4idea.HgVcsMessages; -import org.zmlx.hg4idea.command.HgAddCommand; -import org.zmlx.hg4idea.command.HgCommitCommand; -import org.zmlx.hg4idea.command.HgRemoveCommand; -import org.zmlx.hg4idea.command.HgCommandException; +import com.intellij.openapi.vcs.changes.*; +import com.intellij.openapi.vcs.checkin.*; +import com.intellij.openapi.vcs.ui.*; +import com.intellij.openapi.vfs.*; +import com.intellij.vcsUtil.*; +import org.zmlx.hg4idea.*; +import org.zmlx.hg4idea.command.*; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; +import java.util.*; public class HgCheckinEnvironment implements CheckinEnvironment { @@ -63,18 +54,98 @@ public class HgCheckinEnvironment implements CheckinEnvironment { @SuppressWarnings({"ThrowableInstanceNeverThrown"}) public List commit(List changes, String preparedComment) { List exceptions = new LinkedList(); - for (Map.Entry> entry : getFilesByRepository(changes).entrySet()) { - HgCommitCommand command = new HgCommitCommand(project, entry.getKey(), preparedComment); - command.setFiles(entry.getValue()); + for (Map.Entry> entry : getFilesByRepository(changes).entrySet()) { + + VirtualFile repo = entry.getKey(); + Set selectedFiles = entry.getValue(); + + HgCommitCommand command = new HgCommitCommand(project, repo, preparedComment); + + if (isMergeCommit(repo)) { + //partial commits are not allowed during merges + //verifyResult that all changed files in the repo are selected + //If so, commit the entire repository + //If not, abort + + Set changedFilesNotInCommit = getChangedFilesNotInCommit(repo, selectedFiles); + boolean partial = !changedFilesNotInCommit.isEmpty(); + + + if (partial) { + final StringBuilder filesNotIncludedString = new StringBuilder(); + for (HgFile hgFile : changedFilesNotInCommit) { + filesNotIncludedString.append("
  • "); + filesNotIncludedString.append(hgFile.getRelativePath()); + filesNotIncludedString.append("
  • "); + } + if (!mayCommitEverything(filesNotIncludedString.toString())) { + //abort + return exceptions; + } + } + // else : all was included, or it was OK to commit everything, + // so no need to set the files on the command, because then mercurial will complain + } else { + command.setFiles(selectedFiles); + } try { command.execute(); } catch (HgCommandException e) { exceptions.add(new VcsException(e)); + } catch (VcsException e) { + exceptions.add(e); } } return exceptions; } + private boolean isMergeCommit(VirtualFile repo) { + return new HgWorkingCopyRevisionsCommand(project).parents(repo).size() > 1; + } + + private Set getChangedFilesNotInCommit(VirtualFile repo, Set selectedFiles) { + List parents = new HgWorkingCopyRevisionsCommand(project).parents(repo); + + HgStatusCommand statusCommand = new HgStatusCommand(project); + statusCommand.setBaseRevision(parents.get(0)); + statusCommand.setIncludeUnknown(false); + statusCommand.setIncludeIgnored(false); + Set allChangedFilesInRepo = statusCommand.execute(repo); + + Set filesNotIncluded = new HashSet(); + + for (HgChange change : allChangedFilesInRepo) { + HgFile beforeFile = change.beforeFile(); + HgFile afterFile = change.afterFile(); + if (!selectedFiles.contains(beforeFile)) { + filesNotIncluded.add(beforeFile); + } else if (!selectedFiles.contains(afterFile)) { + filesNotIncluded.add(afterFile); + } + } + return filesNotIncluded; + } + + private boolean mayCommitEverything(final String filesNotIncludedString) { + final int[] choice = new int[1]; + Runnable runnable = new Runnable() { + public void run() { + choice[0] = Messages.showOkCancelDialog( + project, + HgVcsMessages.message("hg4idea.commit.partial.merge.message", filesNotIncludedString), + HgVcsMessages.message("hg4idea.commit.partial.merge.title"), + null + ); + } + }; + if (!ApplicationManager.getApplication().isDispatchThread()) { + ApplicationManager.getApplication().invokeAndWait(runnable, ModalityState.defaultModalityState()); + } else { + runnable.run(); + } + return choice[0] == 0; + } + public List commit(List changes, String preparedComment, Object parameters) { return commit(changes, preparedComment); @@ -108,37 +179,39 @@ public class HgCheckinEnvironment implements CheckinEnvironment { return false; } - private Map> getFilesByRepository(List changes) { - Map> result = new HashMap>(); + private Map> getFilesByRepository(List changes) { + Map> result = new HashMap>(); for (Change change : changes) { ContentRevision afterRevision = change.getAfterRevision(); ContentRevision beforeRevision = change.getBeforeRevision(); - FilePath filePath = null; if (afterRevision != null) { - filePath = afterRevision.getFile(); - } else if (beforeRevision != null) { - filePath = beforeRevision.getFile(); + addFile(result, afterRevision.getFile()); } - - if (filePath == null) { - continue; + if (beforeRevision != null) { + addFile(result, beforeRevision.getFile()); } - - VirtualFile repo = VcsUtil.getVcsRootFor(project, filePath); - if (repo == null || filePath.isDirectory()) { - continue; - } - - List hgFiles = result.get(repo); - if (hgFiles == null) { - hgFiles = new LinkedList(); - result.put(repo, hgFiles); - } - - hgFiles.add(new HgFile(repo, filePath)); } return result; } + private void addFile(Map> result, FilePath filePath) { + if (filePath == null) { + return; + } + + VirtualFile repo = VcsUtil.getVcsRootFor(project, filePath); + if (repo == null || filePath.isDirectory()) { + return; + } + + Set hgFiles = result.get(repo); + if (hgFiles == null) { + hgFiles = new HashSet(); + result.put(repo, hgFiles); + } + + hgFiles.add(new HgFile(repo, filePath)); + } + } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCommitSession.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCommitSession.java index 8ca86fc31d4e..e0dd528cc63c 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCommitSession.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCommitSession.java @@ -12,23 +12,18 @@ // limitations under the License. package org.zmlx.hg4idea.provider.commit; -import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.*; import com.intellij.openapi.vcs.FilePath; -import com.intellij.openapi.vcs.changes.Change; -import com.intellij.openapi.vcs.changes.CommitSession; -import com.intellij.openapi.vcs.changes.ContentRevision; -import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.vcsUtil.VcsUtil; -import org.apache.commons.lang.StringUtils; -import org.zmlx.hg4idea.HgVcsMessages; -import org.zmlx.hg4idea.command.HgCommandException; -import org.zmlx.hg4idea.command.HgCommitCommand; +import com.intellij.openapi.vcs.*; +import com.intellij.openapi.vcs.changes.*; +import com.intellij.openapi.vfs.*; +import com.intellij.vcsUtil.*; +import org.apache.commons.lang.*; +import org.zmlx.hg4idea.*; +import org.zmlx.hg4idea.command.*; -import javax.swing.JComponent; -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; +import javax.swing.*; +import java.util.*; public class HgCommitSession implements CommitSession { @@ -59,11 +54,12 @@ public class HgCommitSession implements CommitSession { VcsUtil.showStatusMessage( project, HgVcsMessages.message("hg4idea.commit.success", root.getPath()) ); - VcsDirtyScopeManager vcsDirtyScopeManager = VcsDirtyScopeManager.getInstance(project); - vcsDirtyScopeManager.dirDirtyRecursively(root); + HgUtil.markDirectoryDirty(project, root); root.refresh(true, true); } catch (HgCommandException e) { VcsUtil.showErrorMessage(project, e.getMessage(), "Error"); + } catch (VcsException e) { + VcsUtil.showErrorMessage(project, e.getMessage(), "Error"); } } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgConflictResolver.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgConflictResolver.java index 5ee68c509662..606d0ab76c2f 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgConflictResolver.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgConflictResolver.java @@ -12,49 +12,31 @@ // limitations under the License. package org.zmlx.hg4idea.provider.update; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.vcs.AbstractVcsHelper; -import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vcs.merge.MergeData; -import com.intellij.openapi.vcs.merge.MergeProvider; -import com.intellij.openapi.vcs.update.FileGroup; -import com.intellij.openapi.vcs.update.UpdatedFiles; -import com.intellij.openapi.vfs.VfsUtil; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.vcsUtil.VcsUtil; -import org.jetbrains.annotations.NotNull; -import org.zmlx.hg4idea.HgFile; -import org.zmlx.hg4idea.HgRevisionNumber; -import org.zmlx.hg4idea.HgVcs; -import org.zmlx.hg4idea.command.HgCatCommand; -import org.zmlx.hg4idea.command.HgResolveCommand; -import org.zmlx.hg4idea.command.HgResolveStatusEnum; +import com.intellij.openapi.application.*; +import com.intellij.openapi.project.*; +import com.intellij.openapi.vcs.*; +import com.intellij.openapi.vcs.merge.*; +import com.intellij.openapi.vcs.update.*; +import com.intellij.openapi.vfs.*; +import com.intellij.vcsUtil.*; +import org.jetbrains.annotations.*; +import org.zmlx.hg4idea.*; +import org.zmlx.hg4idea.command.*; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; +import java.io.*; +import java.util.*; public final class HgConflictResolver { - private final Project project; - private final HgRevisionNumber incomingRevision; - private final HgRevisionNumber localRevision; + @NotNull private final Project project; private final UpdatedFiles updatedFiles; - public HgConflictResolver(Project project, - HgRevisionNumber incomingRevision, HgRevisionNumber localRevision) { - this(project, incomingRevision, localRevision, null); + public HgConflictResolver(@NotNull Project project) { + this(project, null); } - public HgConflictResolver(Project project, HgRevisionNumber incomingRevision, - HgRevisionNumber localRevision, UpdatedFiles updatedFiles) { + public HgConflictResolver(Project project, UpdatedFiles updatedFiles) { this.project = project; - this.incomingRevision = incomingRevision; - this.localRevision = localRevision; this.updatedFiles = updatedFiles; } @@ -75,8 +57,10 @@ public final class HgConflictResolver { default: } if (updatedFiles != null && fileGroupId != null) { + updatedFiles.getGroupById(FileGroup.UPDATED_ID).remove(file.getAbsolutePath()); + //TODO get the correct revision to pass to the UpdatedFiles updatedFiles.getGroupById(fileGroupId) - .add(file.getPath(), HgVcs.VCS_NAME, incomingRevision); + .add(file.getPath(), HgVcs.VCS_NAME, null); } } @@ -84,56 +68,27 @@ public final class HgConflictResolver { return; } - AbstractVcsHelper.getInstance(project).showMergeDialog(conflicts, buildMergeProvider(repo)); + if (!ApplicationManager.getApplication().isUnitTestMode()) { + AbstractVcsHelper.getInstance(project).showMergeDialog(conflicts, buildMergeProvider(repo)); + } } private MergeProvider buildMergeProvider(final VirtualFile repo) { return new MergeProvider() { @NotNull public MergeData loadRevisions(VirtualFile file) throws VcsException { - try { - MergeData mergeData = new MergeData(); - final FileInputStream stream = new FileInputStream(file.getPath() + ".orig"); - try { - mergeData.ORIGINAL = FileUtil.loadBytes(stream); - } - finally { - stream.close(); - } - mergeData.LAST_REVISION_NUMBER = incomingRevision; - HgFile hgFile = new HgFile(repo, VfsUtil.virtualToIoFile(file)); + HgResolveCommand.MergeData resolveData = new HgResolveCommand(project).getResolveData(repo, file); - HgCatCommand hgCatCommand = new HgCatCommand(project); - String last = hgCatCommand.execute( - hgFile, - (HgRevisionNumber) mergeData.LAST_REVISION_NUMBER, - file.getCharset() - ); - if (last != null) { - mergeData.LAST = last.getBytes(file.getCharset().name()); - } else { - mergeData.LAST = new byte[0]; - } - - String current = hgCatCommand.execute( - hgFile, localRevision, file.getCharset() - ); - - if (current != null) { - mergeData.CURRENT = current.getBytes(file.getCharset().name()); - } else { - mergeData.CURRENT = new byte[0]; - } - - return mergeData; - } catch (IOException e) { - throw new VcsException(e); - } + MergeData mergeData = new MergeData(); + mergeData.ORIGINAL = resolveData.getBase(); + mergeData.CURRENT = resolveData.getLocal(); + mergeData.LAST = resolveData.getOther(); + return mergeData; } public void conflictResolvedForFile(VirtualFile file) { - new HgResolveCommand(project).resolve(repo, file); + new HgResolveCommand(project).markResolved(repo, file); } public boolean isBinary(VirtualFile file) { diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgHeadMerger.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgHeadMerger.java index 1837fb790c43..5a31d4623dbd 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgHeadMerger.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgHeadMerger.java @@ -12,23 +12,18 @@ // limitations under the License. package org.zmlx.hg4idea.provider.update; -import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vcs.history.VcsRevisionNumber; -import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager; -import com.intellij.openapi.vcs.update.FileGroup; -import com.intellij.openapi.vcs.update.UpdatedFiles; -import com.intellij.openapi.vfs.VirtualFile; -import org.jetbrains.annotations.NotNull; -import org.zmlx.hg4idea.HgFile; -import org.zmlx.hg4idea.HgVcsMessages; -import org.zmlx.hg4idea.HgVcs; -import org.zmlx.hg4idea.command.HgChange; -import org.zmlx.hg4idea.command.HgMergeCommand; -import org.zmlx.hg4idea.command.HgStatusCommand; +import com.intellij.openapi.project.*; +import com.intellij.openapi.vcs.*; +import com.intellij.openapi.vcs.history.*; +import com.intellij.openapi.vcs.update.*; +import com.intellij.openapi.vfs.*; +import org.jetbrains.annotations.*; +import org.zmlx.hg4idea.*; +import org.zmlx.hg4idea.command.*; -import java.util.Set; +import java.util.*; + +import static org.zmlx.hg4idea.HgErrorHandler.*; final class HgHeadMerger { @@ -40,43 +35,39 @@ final class HgHeadMerger { this.hgMergeCommand = hgMergeCommand; } - public void merge(VirtualFile repo, UpdatedFiles updatedFiles, - ProgressIndicator indicator, VcsRevisionNumber revisionNumber) throws VcsException { - indicator.setText2(HgVcsMessages.message("hg4idea.progress.merging")); + public HgCommandResult merge(VirtualFile repo, UpdatedFiles updatedFiles, + VcsRevisionNumber revisionNumber) throws VcsException { - hgMergeCommand.execute(); + HgCommandResult commandResult = ensureSuccess(hgMergeCommand.execute()); - VcsDirtyScopeManager vcsDirtyScopeManager = VcsDirtyScopeManager.getInstance(project); - vcsDirtyScopeManager.dirDirtyRecursively(repo); - repo.refresh(false, true); + HgUtil.markDirectoryDirty(project, repo); HgStatusCommand hgStatusCommand = new HgStatusCommand(project); hgStatusCommand.setIncludeIgnored(false); hgStatusCommand.setIncludeUnknown(false); Set changes = hgStatusCommand.execute(repo); - if (changes.isEmpty()) { - return; - } - - for (HgChange change : changes) { - HgFile afterFile = change.afterFile(); - HgFile beforeFile = change.beforeFile(); - String fileGroupId = null; - String filePath = null; - if (afterFile != null && beforeFile != null) { - fileGroupId = FileGroup.MODIFIED_ID; - filePath = afterFile.getFile().getAbsolutePath(); - } else if (beforeFile != null) { - fileGroupId = FileGroup.LOCALLY_REMOVED_ID; - filePath = beforeFile.getFile().getAbsolutePath(); - } else if (afterFile != null) { - fileGroupId = FileGroup.LOCALLY_ADDED_ID; - filePath = afterFile.getFile().getAbsolutePath(); - } - if (fileGroupId != null && filePath != null) { - updatedFiles.getGroupById(fileGroupId).add(filePath, HgVcs.VCS_NAME, revisionNumber); + if (!changes.isEmpty()) { + for (HgChange change : changes) { + HgFile afterFile = change.afterFile(); + HgFile beforeFile = change.beforeFile(); + String fileGroupId = null; + String filePath = null; + if (afterFile != null && beforeFile != null) { + fileGroupId = FileGroup.MODIFIED_ID; + filePath = afterFile.getFile().getAbsolutePath(); + } else if (beforeFile != null) { + fileGroupId = FileGroup.LOCALLY_REMOVED_ID; + filePath = beforeFile.getFile().getAbsolutePath(); + } else if (afterFile != null) { + fileGroupId = FileGroup.LOCALLY_ADDED_ID; + filePath = afterFile.getFile().getAbsolutePath(); + } + if (fileGroupId != null && filePath != null) { + updatedFiles.getGroupById(fileGroupId).add(filePath, HgVcs.VCS_NAME, revisionNumber); + } } } + return commandResult; } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgIntegrateEnvironment.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgIntegrateEnvironment.java index 339182b2817d..380240cebfc9 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgIntegrateEnvironment.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgIntegrateEnvironment.java @@ -12,31 +12,22 @@ // limitations under the License. package org.zmlx.hg4idea.provider.update; -import com.intellij.openapi.options.Configurable; -import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Ref; +import com.intellij.openapi.application.*; +import com.intellij.openapi.options.*; +import com.intellij.openapi.progress.*; +import com.intellij.openapi.project.*; +import com.intellij.openapi.util.*; import com.intellij.openapi.vcs.FilePath; -import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vcs.update.SequentialUpdatesContext; -import com.intellij.openapi.vcs.update.UpdateEnvironment; -import com.intellij.openapi.vcs.update.UpdateSession; -import com.intellij.openapi.vcs.update.UpdateSessionAdapter; -import com.intellij.openapi.vcs.update.UpdatedFiles; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ModalityState; -import org.jetbrains.annotations.NotNull; -import org.zmlx.hg4idea.HgVcsMessages; -import org.zmlx.hg4idea.HgRevisionNumber; -import org.zmlx.hg4idea.command.HgMergeCommand; -import org.zmlx.hg4idea.command.HgTagBranch; -import org.zmlx.hg4idea.command.HgWorkingCopyRevisionsCommand; -import org.zmlx.hg4idea.ui.HgIntegrateDialog; +import com.intellij.openapi.vcs.*; +import com.intellij.openapi.vcs.update.*; +import com.intellij.openapi.vfs.*; +import org.apache.commons.lang.*; +import org.jetbrains.annotations.*; +import org.zmlx.hg4idea.*; +import org.zmlx.hg4idea.command.*; +import org.zmlx.hg4idea.ui.*; -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; +import java.util.*; public class HgIntegrateEnvironment implements UpdateEnvironment { @@ -82,19 +73,28 @@ public class HgIntegrateEnvironment implements UpdateEnvironment { incomingRevision = HgRevisionNumber.getLocalInstance(revision); } + HgRevisionNumber otherHead = mergeDialog.getOtherHead(); + if (otherHead != null) { + hgMergeCommand.setRevision(otherHead.getRevision()); + incomingRevision = otherHead; + } + if (incomingRevision != null) { try { - new HgHeadMerger(project, hgMergeCommand) - .merge(repo, updatedFiles, progressIndicator, incomingRevision); + progressIndicator.setText2(HgVcsMessages.message("hg4idea.progress.merging")); + String warnings = new HgHeadMerger(project, hgMergeCommand) + .merge(repo, updatedFiles, incomingRevision).getWarnings(); - final HgRevisionNumber localRevision = - new HgWorkingCopyRevisionsCommand(project).parent(repo); + if (!StringUtils.isBlank(warnings)) { + //noinspection ThrowableInstanceNeverThrown + VcsException warning = new VcsException(warnings); + warning.setIsWarning(true); + exceptions.add(warning); + } - final HgRevisionNumber incomingRevisionFinal = incomingRevision; ApplicationManager.getApplication().invokeAndWait(new Runnable() { public void run() { - new HgConflictResolver(project, incomingRevisionFinal, localRevision, updatedFiles) - .resolve(repo); + new HgConflictResolver(project, updatedFiles).resolve(repo); } }, ModalityState.defaultModalityState()); diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgRegularUpdater.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgRegularUpdater.java index ade40f67e211..e0eff635a678 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgRegularUpdater.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgRegularUpdater.java @@ -12,73 +12,193 @@ // limitations under the License. package org.zmlx.hg4idea.provider.update; -import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vcs.update.UpdatedFiles; -import com.intellij.openapi.vfs.VirtualFile; -import org.apache.commons.lang.StringUtils; -import org.zmlx.hg4idea.HgRevisionNumber; -import org.zmlx.hg4idea.HgVcsMessages; -import org.zmlx.hg4idea.command.HgHeadsCommand; -import org.zmlx.hg4idea.command.HgMergeCommand; -import org.zmlx.hg4idea.command.HgPullCommand; -import org.zmlx.hg4idea.command.HgShowConfigCommand; -import org.zmlx.hg4idea.command.HgTagBranchCommand; +import com.intellij.openapi.application.*; +import com.intellij.openapi.progress.*; +import com.intellij.openapi.project.*; +import com.intellij.openapi.vcs.*; +import com.intellij.openapi.vcs.update.*; +import com.intellij.openapi.vfs.*; +import org.apache.commons.lang.*; +import org.jetbrains.annotations.*; +import org.zmlx.hg4idea.*; +import org.zmlx.hg4idea.command.*; -import java.util.List; +import java.util.*; -class HgRegularUpdater implements HgUpdater { +import static org.zmlx.hg4idea.HgErrorHandler.*; + +public class HgRegularUpdater implements HgUpdater { private final Project project; - private final VirtualFile repository; + @NotNull private final VirtualFile repository; + @NotNull private final UpdateConfiguration updateConfiguration; - public HgRegularUpdater(Project project, VirtualFile repository) { + public HgRegularUpdater(Project project, @NotNull VirtualFile repository, @NotNull UpdateConfiguration configuration) { this.project = project; this.repository = repository; + this.updateConfiguration = configuration; } - public void update(UpdatedFiles updatedFiles, ProgressIndicator indicator) + private boolean shouldPull() { + return updateConfiguration.shouldPull(); + } + + private boolean shouldUpdate() { + return updateConfiguration.shouldUpdate(); + } + + private boolean shouldMerge() { + return updateConfiguration.shouldMerge(); + } + + private boolean shouldCommitAfterMerge() { + return updateConfiguration.shouldCommitAfterMerge(); + } + + public void update(final UpdatedFiles updatedFiles, ProgressIndicator indicator, List warnings) throws VcsException { - indicator.setText( - HgVcsMessages.message("hg4idea.progress.updating", repository.getPath()) - ); + indicator.setText(HgVcsMessages.message("hg4idea.progress.updating", repository.getPath())); HgShowConfigCommand configCommand = new HgShowConfigCommand(project); String defaultPath = configCommand.getDefaultPath(repository); if (StringUtils.isBlank(defaultPath)) { - VcsException e = new VcsException( - HgVcsMessages.message("hg4idea.warning.no-default-update-path", repository.getPath()) - ); - e.setIsWarning(true); - throw e; + throw new VcsException(HgVcsMessages.message("hg4idea.warning.no-default-update-path", repository.getPath())); } - pull(repository, indicator); - String currentBranch = new HgTagBranchCommand(project, repository).getCurrentBranch(); - if (StringUtils.isBlank(currentBranch)) { - throw new VcsException( - HgVcsMessages.message("hg4idea.update.error.currentBranch") - ); + List branchHeadsBeforePull = new HgHeadsCommand(project, repository).execute(); + + if (branchHeadsBeforePull.size() > 1) { + reportWarning(warnings, HgVcsMessages.message("hg4idea.update.warning.multipleHeadsBeforeUpdate", repository.getPath())); } - //count heads in repository - List heads = new HgHeadsCommand(project, repository).execute(currentBranch); - indicator.setText2(HgVcsMessages.message("hg4idea.progress.countingHeads")); - if (heads.size() < 2) { - return; + //TODO perhaps report a warning in this case ? +// //if the parent of the working dir is not the tip of the current branch, the user has +// //manually brought his working copy to some specific revision. In that case we won't touch +// //his setup +// if (!parentRevision.equals(currentBranchHead)) { +// throw new VcsException("working dir not at branch tip (use \"Update to...\" to check out branch tip)"); +// } + + if (shouldPull()) { + pull(repository, indicator); } - if (heads.size() > 2) { - throw new VcsException( - HgVcsMessages.message("hg4idea.update.error.manyHeads", heads.size()) - ); - } + if (shouldUpdate()) { - new HgHeadMerger(project, new HgMergeCommand(project, repository)) - .merge(repository, updatedFiles, indicator, heads.get(heads.size() - 1)); + List parentsBeforeUpdate = new HgWorkingCopyRevisionsCommand(project).parents(repository); + if (parentsBeforeUpdate.size() > 1) { + throw new VcsException(HgVcsMessages.message("hg4idea.update.error.uncommittedMerge", repository.getPath())); + } + + indicator.setText2(HgVcsMessages.message("hg4idea.progress.countingHeads")); + + List branchHeadsAfterPull = new HgHeadsCommand(project, repository).execute(); + List pulledBranchHeads = determinePulledBranchHeads(branchHeadsBeforePull, branchHeadsAfterPull); + List remainingOriginalBranchHeads = determingRemainingOriginalBranchHeads(branchHeadsBeforePull, branchHeadsAfterPull); + + if (branchHeadsAfterPull.size() > 1 && shouldMerge()) { + abortOnLocalChanges(); + abortOnMultiplePulledHeads(pulledBranchHeads); + abortOnMultipleLocalHeads(remainingOriginalBranchHeads); + + //update to the pulled in head, because we consider that head as the 'authoritative' head + updateToPulledHead(pulledBranchHeads.get(0), indicator); + + HgCommandResult mergeResult = doMerge(updatedFiles, indicator, warnings, remainingOriginalBranchHeads.get(0)); + + if (shouldCommitAfterMerge()) { + commitOrWarnAboutConflicts(warnings, mergeResult); + } + } else { + //in case of multiple heads the update will report the appropriate error + update(repository, indicator, updatedFiles, warnings); + } + + //any kind of update could have resulted in merges and merge conflicts, so run the resolver + resolvePossibleConflicts(updatedFiles); + } + } + + private List determingRemainingOriginalBranchHeads(List branchHeadsBeforePull, List branchHeadsAfterPull) { + List originalBranchHeadsRemaining = new ArrayList(); + for (HgRevisionNumber headAfterPull : branchHeadsAfterPull) { + if (branchHeadsBeforePull.contains(headAfterPull)) { + originalBranchHeadsRemaining.add(headAfterPull); + } + } + return originalBranchHeadsRemaining; + } + + private List determinePulledBranchHeads(List branchHeadsBeforePull, List branchHeadsAfterPull) { + List pulledBranchHeads = new ArrayList(branchHeadsAfterPull); + pulledBranchHeads.removeAll(branchHeadsBeforePull); + return pulledBranchHeads; + } + + private void abortOnMultipleLocalHeads(List originalBranchHeadsRemaining) throws VcsException { + if (originalBranchHeadsRemaining.size() != 1) { + throw new VcsException(HgVcsMessages.message("hg4idea.update.error.merge.multipleLocalHeads", repository.getPath())); + } + } + + private void abortOnMultiplePulledHeads(List newBranchHeadsAfterPull) throws VcsException { + if (newBranchHeadsAfterPull.size() != 1) { + throw new VcsException(HgVcsMessages.message("hg4idea.update.error.merge.multipleRemoteHeads", newBranchHeadsAfterPull.size(), repository.getPath())); + } + } + + private void updateToPulledHead(HgRevisionNumber newHead, ProgressIndicator indicator) { + indicator.setText2(HgVcsMessages.message("hg4idea.update.progress.updating.to.pulled.head")); + HgUpdateCommand updateCommand = new HgUpdateCommand(project, repository); + updateCommand.setRevision(newHead.getChangeset()); + updateCommand.setClean(true); + updateCommand.execute(); + } + + private void commitOrWarnAboutConflicts(List exceptions, HgCommandResult mergeResult) throws VcsException { + if (mergeResult.getExitValue() == 0) { //operation successful and no conflicts + try { + new HgCommitCommand(project, repository, "Automated merge").execute(); + } catch (HgCommandException e) { + throw new VcsException(e); + } + } else { + reportWarning(exceptions, HgVcsMessages.message("hg4idea.update.warning.merge.conflicts", repository.getPath())); + } + } + + private HgCommandResult doMerge(UpdatedFiles updatedFiles, ProgressIndicator indicator, List exceptions, HgRevisionNumber headToMerge) throws VcsException { + indicator.setText2(HgVcsMessages.message("hg4idea.update.progress.merging")); + HgMergeCommand mergeCommand = new HgMergeCommand(project, repository); + //do not explicitly set the revision, that way mercurial itself checks that there are exactly + //two heads in this branch +// mergeCommand.setRevision(headToMerge.getRevision()); + HgCommandResult mergeResult = new HgHeadMerger(project, mergeCommand).merge(repository, updatedFiles, headToMerge); + handlePossibleWarning(exceptions, mergeResult.getWarnings()); + return mergeResult; + } + + private void abortOnLocalChanges() throws VcsException { + if (getLocalChanges().size() != 0) { + throw new VcsException(HgVcsMessages.message("hg4idea.update.error.localchanges", repository.getPath())); + } + } + + private void resolvePossibleConflicts(final UpdatedFiles updatedFiles) { + ApplicationManager.getApplication().invokeAndWait(new Runnable() { + public void run() { + new HgConflictResolver(project, updatedFiles).resolve(repository); + } + }, ModalityState.defaultModalityState()); + } + + private Set getLocalChanges() { + HgStatusCommand statusCommand = new HgStatusCommand(project); + statusCommand.setIncludeIgnored(false); + statusCommand.setIncludeUnknown(false); + return statusCommand.execute(repository); } private void pull(VirtualFile repo, ProgressIndicator indicator) @@ -86,9 +206,65 @@ class HgRegularUpdater implements HgUpdater { indicator.setText2(HgVcsMessages.message("hg4idea.progress.pull.with.update")); HgPullCommand hgPullCommand = new HgPullCommand(project, repo); hgPullCommand.setSource(new HgShowConfigCommand(project).getDefaultPath(repo)); - hgPullCommand.setUpdate(true); + hgPullCommand.setUpdate(false); hgPullCommand.setRebase(false); - hgPullCommand.execute(); + ensureSuccess(hgPullCommand.execute()); } + private void update(@NotNull VirtualFile repo, ProgressIndicator indicator, UpdatedFiles updatedFiles, List warnings) throws VcsException { + indicator.setText2(HgVcsMessages.message("hg4idea.progress.updatingworkingdir")); + + HgRevisionNumber parentBeforeUpdate = new HgWorkingCopyRevisionsCommand(project).firstParent(repo); + HgUpdateCommand hgUpdateCommand = new HgUpdateCommand(project, repo); + String warningMessages = ensureSuccess(hgUpdateCommand.execute()).getWarnings(); + handlePossibleWarning(warnings, warningMessages); + + HgRevisionNumber parentAfterUpdate = new HgWorkingCopyRevisionsCommand(project).firstParent(repo); + + addUpdatedFiles(repo, updatedFiles, parentBeforeUpdate, parentAfterUpdate); + } + + private void handlePossibleWarning(List exceptions, String possibleWarning) { + if (!StringUtils.isBlank(possibleWarning)) { + reportWarning(exceptions, possibleWarning); + } + } + + private void reportWarning(List exceptions, String warningMessage) { + @SuppressWarnings({"ThrowableInstanceNeverThrown"}) + VcsException warningException = new VcsException(warningMessage); + warningException.setIsWarning(true); + exceptions.add(warningException); + } + + private void addUpdatedFiles(VirtualFile repo, UpdatedFiles updatedFiles, HgRevisionNumber parentBeforeUpdate, HgRevisionNumber parentAfterUpdate) { + HgStatusCommand statusCommand = new HgStatusCommand(project); + statusCommand.setBaseRevision(parentBeforeUpdate); + statusCommand.setTargetRevision(parentAfterUpdate); + Set changes = statusCommand.execute(repo); + for (HgChange change : changes) { + HgFileStatusEnum status = change.getStatus(); + switch (status) { + case ADDED: + addToGroup(updatedFiles, change, FileGroup.CREATED_ID); + break; + case MODIFIED: + addToGroup(updatedFiles, change, FileGroup.UPDATED_ID); + break; + case DELETED: + addToGroup(updatedFiles, change, FileGroup.REMOVED_FROM_REPOSITORY_ID); + break; + case COPY: + addToGroup(updatedFiles, change, FileGroup.CHANGED_ON_SERVER_ID); + break; + default: + //do nothing + break; + } + } + } + + private static void addToGroup(UpdatedFiles updatedFiles, HgChange change, String id) { + updatedFiles.getGroupById(id).add(change.afterFile().getFile().getAbsolutePath(), HgVcs.VCS_NAME, null); + } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgUpdateEnvironment.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgUpdateEnvironment.java index 680029297f5f..06acf919a91e 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgUpdateEnvironment.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgUpdateEnvironment.java @@ -12,30 +12,25 @@ // limitations under the License. package org.zmlx.hg4idea.provider.update; -import com.intellij.openapi.options.Configurable; -import com.intellij.openapi.progress.ProcessCanceledException; -import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Ref; +import com.intellij.openapi.options.*; +import com.intellij.openapi.progress.*; +import com.intellij.openapi.project.*; +import com.intellij.openapi.util.*; import com.intellij.openapi.vcs.FilePath; -import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vcs.ProjectLevelVcsManager; -import com.intellij.openapi.vcs.update.SequentialUpdatesContext; -import com.intellij.openapi.vcs.update.UpdateEnvironment; -import com.intellij.openapi.vcs.update.UpdateSession; -import com.intellij.openapi.vcs.update.UpdateSessionAdapter; -import com.intellij.openapi.vcs.update.UpdatedFiles; -import com.intellij.openapi.vfs.VirtualFile; -import org.jetbrains.annotations.NotNull; +import com.intellij.openapi.vcs.*; +import com.intellij.openapi.vcs.update.*; +import com.intellij.openapi.vfs.*; +import org.jetbrains.annotations.*; +import org.zmlx.hg4idea.ui.*; -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; +import javax.swing.*; +import java.util.*; public class HgUpdateEnvironment implements UpdateEnvironment { private final Project project; private final HgUpdaterFactory hgUpdaterFactory; + private final HgUpdater.UpdateConfiguration updateConfiguration = new HgUpdater.UpdateConfiguration(); public HgUpdateEnvironment(Project project) { this.project = project; @@ -49,6 +44,7 @@ public class HgUpdateEnvironment implements UpdateEnvironment { public UpdateSession updateDirectories(@NotNull FilePath[] contentRoots, UpdatedFiles updatedFiles, ProgressIndicator indicator, @NotNull Ref context) { + List exceptions = new LinkedList(); for (FilePath contentRoot : contentRoots) { @@ -64,8 +60,10 @@ public class HgUpdateEnvironment implements UpdateEnvironment { continue; } try { - hgUpdaterFactory.buildUpdater(repository).update(updatedFiles, indicator); + HgUpdater updater = hgUpdaterFactory.buildUpdater(repository, updateConfiguration); + updater.update(updatedFiles, indicator, exceptions); } catch (VcsException e) { + //TODO include module name where exception occurred exceptions.add(e); } if (indicator != null) { @@ -75,12 +73,55 @@ public class HgUpdateEnvironment implements UpdateEnvironment { return new UpdateSessionAdapter(exceptions, false); } - public Configurable createConfigurable(Collection files) { - return null; + public Configurable createConfigurable(Collection contentRoots) { + return new UpdateConfigurable(updateConfiguration); } public boolean validateOptions(Collection roots) { return true; } + + public static class UpdateConfigurable implements Configurable { + private final HgUpdater.UpdateConfiguration updateConfiguration; + protected HgUpdateDialog updateDialog; + + public UpdateConfigurable(HgUpdater.UpdateConfiguration updateConfiguration) { + this.updateConfiguration = updateConfiguration; + } + + @Nls + public String getDisplayName() { + return "Update"; + } + + public Icon getIcon() { + return IconLoader.getIcon("/images/mercurial.png"); + } + + public String getHelpTopic() { + return null; + } + + public JComponent createComponent() { + updateDialog = new HgUpdateDialog(); + return updateDialog.createCenterPanel(); + } + + public boolean isModified() { + return true; + } + + public void apply() throws ConfigurationException { + updateDialog.applyTo(updateConfiguration); + } + + public void reset() { + updateDialog.updateFrom(updateConfiguration); + } + + public void disposeUIResources() { + updateDialog = null; + } + } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgUpdater.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgUpdater.java index ef1b3807b0a6..180a0e95e71b 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgUpdater.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgUpdater.java @@ -12,13 +12,53 @@ // limitations under the License. package org.zmlx.hg4idea.provider.update; -import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vcs.update.UpdatedFiles; +import com.intellij.openapi.progress.*; +import com.intellij.openapi.vcs.*; +import com.intellij.openapi.vcs.update.*; -interface HgUpdater { +import java.util.*; - void update(UpdatedFiles updatedFiles, ProgressIndicator indicator) +public interface HgUpdater { + + void update(UpdatedFiles updatedFiles, ProgressIndicator indicator, List exceptions) throws VcsException; + static class UpdateConfiguration{ + private boolean shouldPull = true; + private boolean shouldUpdate = true; + private boolean shouldMerge = true; + private boolean shouldCommitAfterMerge = true; + + public void setShouldPull(boolean shouldPull) { + this.shouldPull = shouldPull; + } + + public void setShouldUpdate(boolean shouldUpdate) { + this.shouldUpdate = shouldUpdate; + } + + public void setShouldMerge(boolean shouldMerge) { + this.shouldMerge = shouldMerge; + } + + public void setShouldCommitAfterMerge(boolean shouldCommitAfterMerge) { + this.shouldCommitAfterMerge = shouldCommitAfterMerge; + } + + public boolean shouldPull() { + return shouldPull; + } + + public boolean shouldUpdate() { + return shouldUpdate; + } + + public boolean shouldMerge() { + return shouldUpdate() && shouldMerge; + } + + public boolean shouldCommitAfterMerge() { + return shouldMerge() && shouldCommitAfterMerge; + } + } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgUpdaterFactory.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgUpdaterFactory.java index 3044ada0fb4e..ba7d0b80080f 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgUpdaterFactory.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/update/HgUpdaterFactory.java @@ -12,11 +12,11 @@ // limitations under the License. package org.zmlx.hg4idea.provider.update; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.vcs.VcsException; -import org.jetbrains.annotations.NotNull; -import org.zmlx.hg4idea.command.HgMQCommand; +import com.intellij.openapi.project.*; +import com.intellij.openapi.vcs.*; +import com.intellij.openapi.vfs.*; +import org.jetbrains.annotations.*; +import org.zmlx.hg4idea.command.*; class HgUpdaterFactory { @@ -26,13 +26,13 @@ class HgUpdaterFactory { this.project = project; } - HgUpdater buildUpdater(@NotNull VirtualFile repository) throws VcsException { + HgUpdater buildUpdater(@NotNull VirtualFile repository, @NotNull HgUpdater.UpdateConfiguration configuration) throws VcsException { HgMQCommand mqCommand = new HgMQCommand(project); boolean foundAppliedPatches = !mqCommand.qapplied(repository).isEmpty(); if (foundAppliedPatches) { throw new VcsException("Cannot update with applied MQ patches, please use rebase"); } else { - return new HgRegularUpdater(project, repository); + return new HgRegularUpdater(project, repository, configuration); } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgCloneDialog.form b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgCloneDialog.form new file mode 100644 index 000000000000..a06a92842578 --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgCloneDialog.form @@ -0,0 +1,84 @@ + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgCloneDialog.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgCloneDialog.java new file mode 100644 index 000000000000..6e19e6c2d064 --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgCloneDialog.java @@ -0,0 +1,446 @@ +/* + * Copyright 2000-2009 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.zmlx.hg4idea.ui; + +import com.intellij.openapi.fileChooser.*; +import com.intellij.openapi.project.*; +import com.intellij.openapi.ui.*; +import com.intellij.openapi.vfs.*; +import com.intellij.uiDesigner.core.*; +import org.zmlx.hg4idea.*; +import org.zmlx.hg4idea.command.*; + +import javax.swing.*; +import javax.swing.event.*; +import java.awt.*; +import java.awt.event.*; +import java.io.*; +import java.net.*; +import java.util.*; + +/** + * A dialog for the mercurial clone options + */ +public class HgCloneDialog extends DialogWrapper { + + /** + * repository URL + */ + private JTextField repositoryURL; + /** + * parent directory + */ + private TextFieldWithBrowseButton parentDirectory; + /** + * test repository URL button + */ + private JButton testButton; + /** + * the repository URL at the time of the last test + */ + private String testURL; + /** + * the test result of the last test or null if not tested + */ + private Boolean testResult; + /** + * directory name button + */ + private JTextField directoryName; + /** + * current default directory name + */ + private String defaultDirectoryName = ""; + /** + * panel that wraps it all + */ + private JPanel clonePanel; + /** + * the project for checkout + */ + private final Project project; + + /** + * A constructor + * + * @param project a project for checkout action + */ + public HgCloneDialog(Project project) { + super(project, true); + this.project = project; + init(); + initListeners(); + setTitle(HgVcsMessages.message("hg4idea.clone.title")); + setOKButtonText(HgVcsMessages.message("hg4idea.clone.button.clone")); + } + + /** + * @return the URL of the source repository + */ + public String getSourceRepositoryURL() { + return repositoryURL.getText(); + } + + /** + * @return the parent directory for checkout + */ + public String getParentDirectory() { + return parentDirectory.getText(); + } + + /** + * @return the directory name to checkout to + */ + public String getDirectoryName() { + return directoryName.getText(); + } + + /** + * Init components + */ + private void initListeners() { + FileChooserDescriptor fcd = new FileChooserDescriptor(false, true, false, false, false, false); + fcd.setShowFileSystemRoots(true); + fcd.setTitle(HgVcsMessages.message("hg4idea.clone.parent.directory.title")); + fcd.setDescription(HgVcsMessages.message("hg4idea.clone.parent.directory.description")); + fcd.setHideIgnored(false); + parentDirectory.addActionListener( + new ComponentWithBrowseButton.BrowseFolderActionListener(fcd.getTitle(), fcd.getDescription(), parentDirectory, + project, fcd, TextComponentAccessor.TEXT_FIELD_WHOLE_TEXT) { + @Override + protected VirtualFile getInitialFile() { + // suggest project base directory only if nothing is typed in the component. + String text = getComponentText(); + if (text.length() == 0) { + VirtualFile file = project.getBaseDir(); + if (file != null) { + return file; + } + } + return super.getInitialFile(); + } + }); + final DocumentListener updateOkButtonListener = new DocumentListener() { + // update Ok button state depending on the current state of the fields + public void insertUpdate(final DocumentEvent e) { + updateCloneButton(); + } + + public void removeUpdate(final DocumentEvent e) { + updateCloneButton(); + } + + public void changedUpdate(final DocumentEvent e) { + updateCloneButton(); + } + }; + parentDirectory.getChildComponent().getDocument().addDocumentListener(updateOkButtonListener); + directoryName.getDocument().addDocumentListener(updateOkButtonListener); + repositoryURL.getDocument().addDocumentListener(new DocumentListener() { + // enable test button only if something is entered in repository URL + public void insertUpdate(final DocumentEvent e) { + changed(); + } + + public void removeUpdate(final DocumentEvent e) { + changed(); + } + + public void changedUpdate(final DocumentEvent e) { + changed(); + } + + private void changed() { + final String url = repositoryURL.getText(); + testButton.setEnabled(url.length() != 0); + if (defaultDirectoryName.equals(directoryName.getText()) || directoryName.getText().length() == 0) { + // modify field if it was unmodified or blank + defaultDirectoryName = defaultDirectoryName(url); + directoryName.setText(defaultDirectoryName); + } + updateCloneButton(); + } + }); + testButton.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + testURL = repositoryURL.getText(); + boolean succeeded = testRepository(project, testURL); + if (succeeded) { + Messages.showInfoMessage(testButton, HgVcsMessages.message("hg4idea.clone.test.success.message", testURL), + HgVcsMessages.message("hg4idea.clone.test.success")); + testResult = Boolean.TRUE; + } else { + testResult = Boolean.FALSE; + } + updateCloneButton(); + } + }); + setOKActionEnabled(false); + } + + /** + * Check fields and display error in the wrapper if there is a problem + */ + private void updateCloneButton() { + if (!checkRepositoryURL()) { + return; + } + if (!checkDestination()) { + return; + } + setErrorText(null); + setOKActionEnabled(true); + } + + /** + * Check destination directory and set appropriate error text if there are problems + * + * @return true if destination components are OK. + */ + private boolean checkDestination() { + if (parentDirectory.getText().length() == 0 || directoryName.getText().length() == 0) { + setErrorText(null); + setOKActionEnabled(false); + return false; + } + File file = new File(parentDirectory.getText(), directoryName.getText()); + if (file.exists()) { + setErrorText(HgVcsMessages.message("hg4idea.clone.error.destination.directory.exists", file)); + setOKActionEnabled(false); + return false; + } else if (!file.getParentFile().exists()) { + setErrorText(HgVcsMessages.message("hg4idea.clone.error.parent.directory.missing", file.getParent())); + setOKActionEnabled(false); + return false; + } + return true; + } + + /** + * Check repository URL and set appropriate error text if there are problems + * + * @return true if repository URL is OK. + */ + private boolean checkRepositoryURL() { + String repository = repositoryURL.getText(); + if (repository.length() == 0) { + setErrorText(null); + setOKActionEnabled(false); + return false; + } + if (testResult != null && repository.equals(testURL)) { + if (!testResult) { + setErrorText(HgVcsMessages.message("hg4idea.clone.error.test.failed")); + setOKActionEnabled(false); + return false; + } else { + return true; + } + } + try { + if (new URI(repository).isAbsolute()) { + return true; + } + } + catch (URISyntaxException urlExp) { + // do nothing + } + try { + File file = new File(repository); + if (file.exists()) { + if (!file.isDirectory()) { + setErrorText(HgVcsMessages.message("hg4idea.clone.error.repository.url.is.not.directory")); + setOKActionEnabled(false); + } + return true; + } + } + catch (Exception fileExp) { + // do nothing + } + setErrorText(HgVcsMessages.message("hg4idea.clone.error.repository.url")); + setOKActionEnabled(false); + return false; + } + + /** + * Get default name for checked out directory + * + * @param url an URL to checkout + * @return a default repository name + */ + private static String defaultDirectoryName(final String url) { + String nonSystemName; + //noinspection HardCodedStringLiteral + if (url.endsWith("/.hg") || url.endsWith(File.separator + ".hg")) { + nonSystemName = url.substring(0, url.length() - 5); + } else { + //noinspection HardCodedStringLiteral + if (url.endsWith(".hg")) { + nonSystemName = url.substring(0, url.length() - 4); + } else { + nonSystemName = url; + } + } + int i = nonSystemName.lastIndexOf('/'); + if (i == -1 && File.separatorChar != '/') { + i = nonSystemName.lastIndexOf(File.separatorChar); + } + return i >= 0 ? nonSystemName.substring(i + 1) : ""; + } + + /** + * {@inheritDoc} + */ + protected JComponent createCenterPanel() { + return clonePanel; + } + + /** + * {@inheritDoc} + */ + @Override + protected String getDimensionServiceKey() { + return "HgCloneDialog"; + } + + @Override + public JComponent getPreferredFocusedComponent() { + return repositoryURL; + } + + /** + * {@inheritDoc} + */ + @Override + protected String getHelpId() { + return "reference.VersionControl.Hg.CloneRepository"; + } + + private boolean testRepository(Project project, final String repositoryUrl) { + HgIdentifyCommand identifyCommand = new HgIdentifyCommand(project); + identifyCommand.setSource(repositoryUrl); + HgCommandResult result = identifyCommand.execute(); + + return result.getExitValue() == 0; + } + + { +// GUI initializer generated by IntelliJ IDEA GUI Designer +// >>> IMPORTANT!! <<< +// DO NOT EDIT OR ADD ANY CODE HERE! + $$$setupUI$$$(); + } + + /** + * Method generated by IntelliJ IDEA GUI Designer + * >>> IMPORTANT!! <<< + * DO NOT edit this method OR call it in your code! + * + * @noinspection ALL + */ + private void $$$setupUI$$$() { + clonePanel = new JPanel(); + clonePanel.setLayout(new GridLayoutManager(4, 4, new Insets(0, 0, 0, 0), -1, -1)); + final JLabel label1 = new JLabel(); + this.$$$loadLabelText$$$(label1, ResourceBundle.getBundle("org/zmlx/hg4idea/HgVcsMessages").getString("hg4idea.clone.repository.url")); + clonePanel.add(label1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final Spacer spacer1 = new Spacer(); + clonePanel.add(spacer1, new GridConstraints(3, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + final Spacer spacer2 = new Spacer(); + clonePanel.add(spacer2, new GridConstraints(3, 1, 1, 3, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false)); + repositoryURL = new JTextField(); + clonePanel.add(repositoryURL, new GridConstraints(0, 1, 1, 2, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(150, -1), null, 0, false)); + final JLabel label2 = new JLabel(); + this.$$$loadLabelText$$$(label2, ResourceBundle.getBundle("org/zmlx/hg4idea/HgVcsMessages").getString("hg4idea.clone.parent.directory")); + clonePanel.add(label2, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + parentDirectory = new TextFieldWithBrowseButton(); + clonePanel.add(parentDirectory, new GridConstraints(1, 1, 1, 3, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final JLabel label3 = new JLabel(); + this.$$$loadLabelText$$$(label3, ResourceBundle.getBundle("org/zmlx/hg4idea/HgVcsMessages").getString("hg4idea.clone.directory.name")); + clonePanel.add(label3, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + testButton = new JButton(); + this.$$$loadButtonText$$$(testButton, ResourceBundle.getBundle("org/zmlx/hg4idea/HgVcsMessages").getString("hg4idea.clone.button.test")); + clonePanel.add(testButton, new GridConstraints(0, 3, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + directoryName = new JTextField(); + clonePanel.add(directoryName, new GridConstraints(2, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(150, -1), null, 0, false)); + final Spacer spacer3 = new Spacer(); + clonePanel.add(spacer3, new GridConstraints(2, 2, 1, 2, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false)); + label1.setLabelFor(repositoryURL); + label3.setLabelFor(directoryName); + } + + /** + * @noinspection ALL + */ + private void $$$loadLabelText$$$(JLabel component, String text) { + StringBuffer result = new StringBuffer(); + boolean haveMnemonic = false; + char mnemonic = '\0'; + int mnemonicIndex = -1; + for (int i = 0; i < text.length(); i++) { + if (text.charAt(i) == '&') { + i++; + if (i == text.length()) break; + if (!haveMnemonic && text.charAt(i) != '&') { + haveMnemonic = true; + mnemonic = text.charAt(i); + mnemonicIndex = result.length(); + } + } + result.append(text.charAt(i)); + } + component.setText(result.toString()); + if (haveMnemonic) { + component.setDisplayedMnemonic(mnemonic); + component.setDisplayedMnemonicIndex(mnemonicIndex); + } + } + + /** + * @noinspection ALL + */ + private void $$$loadButtonText$$$(AbstractButton component, String text) { + StringBuffer result = new StringBuffer(); + boolean haveMnemonic = false; + char mnemonic = '\0'; + int mnemonicIndex = -1; + for (int i = 0; i < text.length(); i++) { + if (text.charAt(i) == '&') { + i++; + if (i == text.length()) break; + if (!haveMnemonic && text.charAt(i) != '&') { + haveMnemonic = true; + mnemonic = text.charAt(i); + mnemonicIndex = result.length(); + } + } + result.append(text.charAt(i)); + } + component.setText(result.toString()); + if (haveMnemonic) { + component.setMnemonic(mnemonic); + component.setDisplayedMnemonicIndex(mnemonicIndex); + } + } + + /** + * @noinspection ALL + */ + public JComponent $$$getRootComponent$$$() { + return clonePanel; + } +} diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationIdePanel.form b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationIdePanel.form index 4dcb91491827..79ffd1b867bb 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationIdePanel.form +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationIdePanel.form @@ -34,7 +34,7 @@ - + diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationIdePanel.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationIdePanel.java index 0fdacc8fe5ce..cbad294a253f 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationIdePanel.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationIdePanel.java @@ -12,26 +12,17 @@ // limitations under the License. package org.zmlx.hg4idea.ui; -import com.intellij.openapi.fileChooser.FileChooserDescriptor; -import com.intellij.openapi.options.ConfigurationException; -import com.intellij.openapi.ui.TextFieldWithBrowseButton; -import com.intellij.uiDesigner.core.GridConstraints; -import com.intellij.uiDesigner.core.GridLayoutManager; -import com.intellij.uiDesigner.core.Spacer; -import org.apache.commons.lang.StringUtils; -import org.zmlx.hg4idea.HgGlobalSettings; -import org.zmlx.hg4idea.HgVcsMessages; -import org.zmlx.hg4idea.command.HgVersionCommand; +import com.intellij.openapi.fileChooser.*; +import com.intellij.openapi.options.*; +import com.intellij.openapi.ui.*; +import com.intellij.uiDesigner.core.*; +import org.apache.commons.lang.*; +import org.zmlx.hg4idea.*; +import org.zmlx.hg4idea.command.*; -import javax.swing.BorderFactory; -import javax.swing.ButtonGroup; -import javax.swing.JComponent; -import javax.swing.JPanel; -import javax.swing.JRadioButton; -import java.awt.Dimension; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; public class HgConfigurationIdePanel { private JRadioButton autoRadioButton; @@ -45,6 +36,14 @@ public class HgConfigurationIdePanel { this.globalSettings = globalSettings; loadSettings(); + String title = HgVcsMessages.message("hg4idea.configuration.title"); + String description = HgVcsMessages.message("hg4idea.configuration.description"); + + pathSelector.addBrowseFolderListener( + title, description, null, + new FileChooserDescriptor(true, false, false, false, false, false) + ); + final ActionListener listener = new ActionListener() { public void actionPerformed(ActionEvent e) { pathSelector.setEnabled(selectRadioButton.isSelected()); @@ -101,7 +100,54 @@ public class HgConfigurationIdePanel { } } - private void createUIComponents() { - pathSelector = new HgSetExecutablePathPanel(); + { +// GUI initializer generated by IntelliJ IDEA GUI Designer +// >>> IMPORTANT!! <<< +// DO NOT EDIT OR ADD ANY CODE HERE! + $$$setupUI$$$(); + } + + /** + * Method generated by IntelliJ IDEA GUI Designer + * >>> IMPORTANT!! <<< + * DO NOT edit this method OR call it in your code! + * + * @noinspection ALL + */ + private void $$$setupUI$$$() { + basePanel = new JPanel(); + basePanel.setLayout(new GridLayoutManager(2, 1, new Insets(0, 0, 0, 0), -1, -1)); + final JPanel panel1 = new JPanel(); + panel1.setLayout(new GridLayoutManager(2, 2, new Insets(0, 0, 0, 0), -1, -1)); + basePanel.add(panel1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); + panel1.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Path to hg executable")); + autoRadioButton = new JRadioButton(); + autoRadioButton.setSelected(true); + autoRadioButton.setText("Autodetect hg in PATH"); + autoRadioButton.setMnemonic('A'); + autoRadioButton.setDisplayedMnemonicIndex(0); + panel1.add(autoRadioButton, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + selectRadioButton = new JRadioButton(); + selectRadioButton.setEnabled(true); + selectRadioButton.setText("Specify executable path"); + selectRadioButton.setMnemonic('S'); + selectRadioButton.setDisplayedMnemonicIndex(0); + panel1.add(selectRadioButton, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + pathSelector = new TextFieldWithBrowseButton(); + pathSelector.setEnabled(false); + panel1.add(pathSelector, new GridConstraints(1, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, new Dimension(100, -1), null, null, 0, false)); + final Spacer spacer1 = new Spacer(); + basePanel.add(spacer1, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + ButtonGroup buttonGroup; + buttonGroup = new ButtonGroup(); + buttonGroup.add(autoRadioButton); + buttonGroup.add(selectRadioButton); + } + + /** + * @noinspection ALL + */ + public JComponent $$$getRootComponent$$$() { + return basePanel; } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgCurrentBranchStatus.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgCurrentBranchStatus.java index 7ebf6b8137df..3296a231f299 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgCurrentBranchStatus.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgCurrentBranchStatus.java @@ -12,13 +12,13 @@ // limitations under the License. package org.zmlx.hg4idea.ui; -import com.intellij.openapi.util.IconLoader; -import org.apache.commons.lang.StringUtils; -import org.zmlx.hg4idea.HgVcsMessages; +import com.intellij.openapi.util.*; +import org.apache.commons.lang.*; +import org.jetbrains.annotations.*; +import org.zmlx.hg4idea.*; -import javax.swing.Icon; -import javax.swing.JLabel; -import javax.swing.SwingConstants; +import javax.swing.*; +import java.util.*; public class HgCurrentBranchStatus extends JLabel { @@ -29,12 +29,21 @@ public class HgCurrentBranchStatus extends JLabel { setVisible(false); } - public void setCurrentBranch(String branch) { + public void updateFor(@Nullable String branch, @NotNull List parents) { + StringBuffer parentsBuffer = new StringBuffer(); + for (HgRevisionNumber parent : parents) { + String rev = parent.getRevision(); + parentsBuffer.append(rev).append(", "); + } + int length = parentsBuffer.length(); + if (length > 2) { + parentsBuffer.delete(length - 2, length); + } String statusText = StringUtils.isNotBlank(branch) - ? HgVcsMessages.message("hg4idea.status.currentBranch.text", branch) : ""; + ? HgVcsMessages.message("hg4idea.status.currentSituationtext", branch, parentsBuffer.toString()) : ""; - String toolTipText = StringUtils.isNotBlank(branch) - ? HgVcsMessages.message("hg4idea.status.currentBranch.description") : ""; + String toolTipText = StringUtils.isNotBlank(statusText) + ? HgVcsMessages.message("hg4idea.status.currentSituation.description") : ""; setVisible(StringUtils.isNotBlank(branch)); setText(statusText); diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgIntegrateDialog.form b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgIntegrateDialog.form index 954c52f1eda0..09d58c7222fe 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgIntegrateDialog.form +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgIntegrateDialog.form @@ -8,7 +8,7 @@ - + @@ -18,7 +18,7 @@ - + @@ -27,7 +27,7 @@ - + @@ -35,7 +35,7 @@ - + @@ -43,7 +43,7 @@ - + @@ -51,12 +51,12 @@ - + - + @@ -66,13 +66,31 @@ - + + + + + + + + + + + + + + + + + + + @@ -92,6 +110,7 @@ + diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgIntegrateDialog.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgIntegrateDialog.java index 03b7a08766cf..839ce4f106d5 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgIntegrateDialog.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgIntegrateDialog.java @@ -12,36 +12,18 @@ // limitations under the License. package org.zmlx.hg4idea.ui; -import com.intellij.openapi.options.Configurable; -import com.intellij.openapi.options.ConfigurationException; +import com.intellij.openapi.options.*; +import com.intellij.openapi.project.*; import com.intellij.openapi.vcs.FilePath; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.project.Project; -import com.intellij.uiDesigner.core.GridConstraints; -import com.intellij.uiDesigner.core.GridLayoutManager; -import com.intellij.uiDesigner.core.Spacer; -import org.jetbrains.annotations.Nls; -import org.zmlx.hg4idea.command.HgTagBranch; -import org.zmlx.hg4idea.command.HgTagBranchCommand; +import com.intellij.openapi.vfs.*; +import org.jetbrains.annotations.*; +import org.zmlx.hg4idea.*; +import org.zmlx.hg4idea.command.*; -import javax.swing.BorderFactory; -import javax.swing.ButtonGroup; -import javax.swing.DefaultComboBoxModel; -import javax.swing.Icon; -import javax.swing.JComboBox; -import javax.swing.JComponent; -import javax.swing.JPanel; -import javax.swing.JRadioButton; -import javax.swing.JTextField; -import javax.swing.event.ChangeListener; -import javax.swing.event.ChangeEvent; -import java.awt.Dimension; -import java.awt.Insets; -import java.awt.event.ActionListener; -import java.awt.event.ActionEvent; -import java.util.Collection; -import java.util.List; -import java.util.LinkedList; +import javax.swing.*; +import javax.swing.event.*; +import java.awt.event.*; +import java.util.*; public class HgIntegrateDialog implements Configurable { @@ -55,6 +37,10 @@ public class HgIntegrateDialog implements Configurable { private JComboBox tagSelector; private JPanel contentPanel; private HgRepositorySelectorComponent hgRepositorySelectorComponent; + private JRadioButton otherHeadRadioButton; + private JLabel otherHeadLabel; + + private HgRevisionNumber otherHead; public HgIntegrateDialog(Project project, Collection roots) { this.project = project; @@ -74,6 +60,7 @@ public class HgIntegrateDialog implements Configurable { branchOption.addChangeListener(changeListener); tagOption.addChangeListener(changeListener); revisionOption.addChangeListener(changeListener); + otherHeadRadioButton.addChangeListener(changeListener); updateRepository(); } @@ -94,6 +81,10 @@ public class HgIntegrateDialog implements Configurable { return revisionOption.isSelected() ? revisionTxt.getText() : null; } + public HgRevisionNumber getOtherHead() { + return otherHeadRadioButton.isSelected() ? otherHead : null; + } + @Nls public String getDisplayName() { return null; @@ -125,6 +116,7 @@ public class HgIntegrateDialog implements Configurable { VirtualFile repo = getRepository(); loadBranches(repo); loadTags(repo); + loadHeads(repo); } private void updateOptions() { @@ -143,6 +135,33 @@ public class HgIntegrateDialog implements Configurable { tagSelector.setModel(new DefaultComboBoxModel(tags.toArray())); } + private void loadHeads(VirtualFile root) { + List heads = new HgHeadsCommand(project, root).execute(); + if (heads.size() != 2) { + disableOtherHeadsChoice(); + return; + } + + otherHeadRadioButton.setVisible(true); + otherHeadLabel.setVisible(true); + + HgRevisionNumber currentParent = new HgWorkingCopyRevisionsCommand(project).identify(root); + heads.remove(currentParent); + + if (heads.size() == 1) { + otherHead = heads.get(0); + otherHeadLabel.setText(HgVcsMessages.message("hg4idea.integrate.other.head", otherHead.asString())); + } else { + //apparently we are not at one of the heads + disableOtherHeadsChoice(); + } + } + + private void disableOtherHeadsChoice() { + otherHeadLabel.setVisible(false); + otherHeadRadioButton.setVisible(false); + } + private List pathsToFiles(Collection paths) { List files = new LinkedList(); for (FilePath path : paths) { @@ -154,70 +173,4 @@ public class HgIntegrateDialog implements Configurable { public void disposeUIResources() { } - { -// GUI initializer generated by IntelliJ IDEA GUI Designer -// >>> IMPORTANT!! <<< -// DO NOT EDIT OR ADD ANY CODE HERE! - $$$setupUI$$$(); - } - - /** - * Method generated by IntelliJ IDEA GUI Designer - * >>> IMPORTANT!! <<< - * DO NOT edit this method OR call it in your code! - * - * @noinspection ALL - */ - private void $$$setupUI$$$() { - contentPanel = new JPanel(); - contentPanel.setLayout(new GridLayoutManager(3, 1, new Insets(0, 0, 0, 0), -1, -1)); - final JPanel panel1 = new JPanel(); - panel1.setLayout(new GridLayoutManager(4, 2, new Insets(0, 0, 0, 0), -1, -1)); - contentPanel.add(panel1, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); - panel1.setBorder(BorderFactory.createTitledBorder("Merge with:")); - branchOption = new JRadioButton(); - branchOption.setSelected(true); - branchOption.setText("Branch"); - branchOption.setMnemonic('B'); - branchOption.setDisplayedMnemonicIndex(0); - panel1.add(branchOption, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); - tagOption = new JRadioButton(); - tagOption.setText("Tag"); - tagOption.setMnemonic('T'); - tagOption.setDisplayedMnemonicIndex(0); - panel1.add(tagOption, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); - branchSelector = new JComboBox(); - branchSelector.setEnabled(true); - panel1.add(branchSelector, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); - tagSelector = new JComboBox(); - tagSelector.setEnabled(false); - panel1.add(tagSelector, new GridConstraints(1, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); - final Spacer spacer1 = new Spacer(); - panel1.add(spacer1, new GridConstraints(3, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false)); - revisionTxt = new JTextField(); - revisionTxt.setEnabled(false); - panel1.add(revisionTxt, new GridConstraints(2, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(150, -1), null, 0, false)); - revisionOption = new JRadioButton(); - revisionOption.setSelected(false); - revisionOption.setText("Revision"); - revisionOption.setMnemonic('R'); - revisionOption.setDisplayedMnemonicIndex(0); - panel1.add(revisionOption, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); - final Spacer spacer2 = new Spacer(); - contentPanel.add(spacer2, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); - hgRepositorySelectorComponent = new HgRepositorySelectorComponent(); - contentPanel.add(hgRepositorySelectorComponent.$$$getRootComponent$$$(), new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); - ButtonGroup buttonGroup; - buttonGroup = new ButtonGroup(); - buttonGroup.add(revisionOption); - buttonGroup.add(branchOption); - buttonGroup.add(tagOption); - } - - /** - * @noinspection ALL - */ - public JComponent $$$getRootComponent$$$() { - return contentPanel; - } -} +} \ No newline at end of file diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgSetExecutableDialog.form b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgSetExecutableDialog.form index 9ba2bbb7a460..2a0505454315 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgSetExecutableDialog.form +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgSetExecutableDialog.form @@ -1,6 +1,6 @@
    - + @@ -8,7 +8,7 @@ - + @@ -16,17 +16,27 @@ - + - + + + + + + + + + + + - + diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgSetExecutableDialog.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgSetExecutableDialog.java index 915ed8000f75..6b9530eb03c5 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgSetExecutableDialog.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgSetExecutableDialog.java @@ -12,18 +12,20 @@ // limitations under the License. package org.zmlx.hg4idea.ui; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.DialogWrapper; -import org.zmlx.hg4idea.HgVcsMessages; +import com.intellij.openapi.project.*; +import com.intellij.openapi.ui.*; +import com.intellij.uiDesigner.core.*; +import org.zmlx.hg4idea.*; import javax.swing.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; +import java.awt.*; +import java.util.*; public class HgSetExecutableDialog extends DialogWrapper { - private JPanel myCenterPanel; - private HgSetExecutablePathPanel myHgExecutablePath; - private JLabel myInfoLabel; + private JPanel centerPanel; + private TextFieldWithBrowseButton hgExecutablePath; + private JLabel infoLabel; + private JLabel errorLabel; public HgSetExecutableDialog(Project project) { super(project, false); @@ -32,24 +34,81 @@ public class HgSetExecutableDialog extends DialogWrapper { @Override protected JComponent createCenterPanel() { - return myCenterPanel; + return centerPanel; } public void setBadHgPath(String hgPath) { - myHgExecutablePath.setText(hgPath); - setErrorText(HgVcsMessages.message("hg4idea.configuration.executable.error", hgPath)); + hgExecutablePath.setText(hgPath); + errorLabel.setText(HgVcsMessages.message("hg4idea.error.invalidExecutable", hgPath)); } public String getNewHgPath() { - return myHgExecutablePath.getText(); + return hgExecutablePath.getText(); } - private void createUIComponents() { - myHgExecutablePath = new HgSetExecutablePathPanel(); - myHgExecutablePath.addOKListener(new ActionListener() { - public void actionPerformed(ActionEvent event) { - setErrorText(""); + + { +// GUI initializer generated by IntelliJ IDEA GUI Designer +// >>> IMPORTANT!! <<< +// DO NOT EDIT OR ADD ANY CODE HERE! + $$$setupUI$$$(); + } + + /** + * Method generated by IntelliJ IDEA GUI Designer + * >>> IMPORTANT!! <<< + * DO NOT edit this method OR call it in your code! + * + * @noinspection ALL + */ + private void $$$setupUI$$$() { + centerPanel = new JPanel(); + centerPanel.setLayout(new GridLayoutManager(4, 1, new Insets(0, 0, 0, 0), -1, -1)); + hgExecutablePath = new TextFieldWithBrowseButton(); + centerPanel.add(hgExecutablePath, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_NORTHWEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, new Dimension(400, -1), null, 0, false)); + infoLabel = new JLabel(); + infoLabel.setText("Full path to hg executable or 'hg' if PATH has it:"); + centerPanel.add(infoLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + errorLabel = new JLabel(); + errorLabel.setFont(new Font(errorLabel.getFont().getName(), Font.ITALIC, errorLabel.getFont().getSize())); + errorLabel.setForeground(Color.red); + this.$$$loadLabelText$$$(errorLabel, ResourceBundle.getBundle("org/zmlx/hg4idea/HgVcsMessages").getString("hg4idea.error.invalidExecutable")); + centerPanel.add(errorLabel, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final Spacer spacer1 = new Spacer(); + centerPanel.add(spacer1, new GridConstraints(3, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + } + + /** + * @noinspection ALL + */ + private void $$$loadLabelText$$$(JLabel component, String text) { + StringBuffer result = new StringBuffer(); + boolean haveMnemonic = false; + char mnemonic = '\0'; + int mnemonicIndex = -1; + for (int i = 0; i < text.length(); i++) { + if (text.charAt(i) == '&') { + i++; + if (i == text.length()) break; + if (!haveMnemonic && text.charAt(i) != '&') { + haveMnemonic = true; + mnemonic = text.charAt(i); + mnemonicIndex = result.length(); + } } - }); + result.append(text.charAt(i)); + } + component.setText(result.toString()); + if (haveMnemonic) { + component.setDisplayedMnemonic(mnemonic); + component.setDisplayedMnemonicIndex(mnemonicIndex); + } + } + + /** + * @noinspection ALL + */ + public JComponent $$$getRootComponent$$$() { + return centerPanel; } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgUpdateDialog.form b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgUpdateDialog.form new file mode 100644 index 000000000000..34b0d83022ba --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgUpdateDialog.form @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgUpdateDialog.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgUpdateDialog.java new file mode 100644 index 000000000000..6da6b5e933d3 --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgUpdateDialog.java @@ -0,0 +1,120 @@ +// Copyright 2008-2010 Victor Iacoban +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under +// the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions and +// limitations under the License. +package org.zmlx.hg4idea.ui; + +import com.intellij.uiDesigner.core.*; +import org.zmlx.hg4idea.provider.update.*; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; + +/** + * Configuration dialog for the update process. + */ +public class HgUpdateDialog { + private JPanel contentPane; + private JCheckBox pullCheckBox; + private JCheckBox updateCheckBox; + private JCheckBox mergeCheckBox; + private JCheckBox commitAfterMergeCheckBox; + + public HgUpdateDialog() { + ItemListener enabledListener = new ItemListener() { + public void itemStateChanged(ItemEvent e) { + updateEnabledStates(); + } + }; + updateCheckBox.addItemListener(enabledListener); + mergeCheckBox.addItemListener(enabledListener); + updateEnabledStates(); + } + + private void updateEnabledStates() { + //TODO this information is actually duplicated in the HgRegularUpdater (as a series of nested ifs) + mergeCheckBox.setEnabled(updateCheckBox.isSelected()); + commitAfterMergeCheckBox.setEnabled(mergeCheckBox.isEnabled() && mergeCheckBox.isSelected()); + } + + public void applyTo(HgUpdater.UpdateConfiguration updateConfiguration) { + updateConfiguration.setShouldPull(pullCheckBox.isSelected()); + updateConfiguration.setShouldUpdate(updateCheckBox.isSelected()); + updateConfiguration.setShouldMerge(mergeCheckBox.isSelected()); + updateConfiguration.setShouldCommitAfterMerge(commitAfterMergeCheckBox.isSelected()); + } + + public JComponent createCenterPanel() { + return contentPane; + } + + public void updateFrom(HgUpdater.UpdateConfiguration updateConfiguration) { + pullCheckBox.setSelected(updateConfiguration.shouldPull()); + updateCheckBox.setSelected(updateConfiguration.shouldUpdate()); + mergeCheckBox.setSelected(updateConfiguration.shouldMerge()); + commitAfterMergeCheckBox.setSelected(updateConfiguration.shouldCommitAfterMerge()); + } + + { +// GUI initializer generated by IntelliJ IDEA GUI Designer +// >>> IMPORTANT!! <<< +// DO NOT EDIT OR ADD ANY CODE HERE! + $$$setupUI$$$(); + } + + /** + * Method generated by IntelliJ IDEA GUI Designer + * >>> IMPORTANT!! <<< + * DO NOT edit this method OR call it in your code! + * + * @noinspection ALL + */ + private void $$$setupUI$$$() { + contentPane = new JPanel(); + contentPane.setLayout(new GridLayoutManager(5, 2, new Insets(0, 0, 0, 0), -1, -1)); + pullCheckBox = new JCheckBox(); + pullCheckBox.setText("pull"); + pullCheckBox.setMnemonic('P'); + pullCheckBox.setDisplayedMnemonicIndex(0); + pullCheckBox.setToolTipText("pull from the default remote repository"); + contentPane.add(pullCheckBox, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final Spacer spacer1 = new Spacer(); + contentPane.add(spacer1, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false)); + updateCheckBox = new JCheckBox(); + updateCheckBox.setText("update"); + updateCheckBox.setMnemonic('U'); + updateCheckBox.setDisplayedMnemonicIndex(0); + updateCheckBox.setToolTipText("update to the head of the current branch"); + contentPane.add(updateCheckBox, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + mergeCheckBox = new JCheckBox(); + mergeCheckBox.setText("merge"); + mergeCheckBox.setMnemonic('M'); + mergeCheckBox.setDisplayedMnemonicIndex(0); + mergeCheckBox.setToolTipText("merge if pulling resulted in extra heads"); + contentPane.add(mergeCheckBox, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + commitAfterMergeCheckBox = new JCheckBox(); + commitAfterMergeCheckBox.setText("commit after merge without conflicts"); + commitAfterMergeCheckBox.setMnemonic('C'); + commitAfterMergeCheckBox.setDisplayedMnemonicIndex(0); + commitAfterMergeCheckBox.setToolTipText("commit automatically after the merge"); + contentPane.add(commitAfterMergeCheckBox, new GridConstraints(3, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); + final Spacer spacer2 = new Spacer(); + contentPane.add(spacer2, new GridConstraints(4, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + } + + /** + * @noinspection ALL + */ + public JComponent $$$getRootComponent$$$() { + return contentPane; + } +} diff --git a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/AbstractHgTestCase.java b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/AbstractHgTestCase.java new file mode 100644 index 000000000000..9f09649d5df3 --- /dev/null +++ b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/AbstractHgTestCase.java @@ -0,0 +1,105 @@ +// Copyright 2010 Victor Iacoban +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under +// the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions and +// limitations under the License. +package org.zmlx.hg4idea; + +import com.intellij.execution.process.*; +import com.intellij.openapi.util.*; +import com.intellij.openapi.vcs.*; +import com.intellij.openapi.vcs.changes.*; +import com.intellij.openapi.vfs.*; +import com.intellij.testFramework.*; +import com.intellij.vcsUtil.*; + +import java.io.*; + +import static org.testng.Assert.*; + +/** + * TODO JavaDoc. + */ +public class AbstractHgTestCase extends AbstractVcsTestCase { + protected void enableSilentOperation(final VcsConfiguration.StandardConfirmation op) { + setStandardConfirmation( + HgVcs.VCS_NAME, op, VcsShowConfirmationOption.Value.DO_ACTION_SILENTLY + ); + } + + protected void disableSilentOperation(final VcsConfiguration.StandardConfirmation op) { + setStandardConfirmation( + HgVcs.VCS_NAME, op, VcsShowConfirmationOption.Value.DO_NOTHING_SILENTLY + ); + } + + protected VirtualFile makeFile(File file) throws IOException { + file.createNewFile(); + VcsDirtyScopeManager.getInstance(myProject).fileDirty(myWorkingCopyDir); + LocalFileSystem.getInstance().refresh(false); + return VcsUtil.getVirtualFile(file); + } + + protected ProcessOutput runHg(File aHgRepository, String... commandLine) throws IOException { + String exe = SystemInfo.isWindows ? "hg.exe" : "hg"; + return runClient(exe, null, aHgRepository, commandLine); + } + + protected File fillFile(File aParentDir, String[] filePath, String fileContents) throws FileNotFoundException { + File parentDir = aParentDir; + for (int i = 0; i < filePath.length - 1; i++) { + File current = new File(parentDir, filePath[i]); + if (!current.exists() || !current.isDirectory()) { + assertTrue(current.mkdir()); + } + parentDir = current; + } + File outputFile = new File(parentDir, filePath[filePath.length - 1]); + + PrintStream printer = new PrintStream(new FileOutputStream(outputFile)); + printer.print(fileContents); + printer.close(); + + return outputFile; + } + + public static String added(String... path) { + return "A " + path(path); + } + + public static String removed(String... path) { + return "R " + path(path); + } + + public static String unknown(String... path) { + return "? " + path(path); + } + + public static String modified(String... path) { + return "M " + path(path); + } + + public static String path(String... line) { + StringBuilder builder = new StringBuilder(); + + int linePartCount = line.length; + + for (int i = 0; i < linePartCount; i++) { + String linePart = line[i]; + builder.append(linePart); + + if (i < linePartCount - 1) { + builder.append(File.separator); + } + } + + return builder.toString(); + } +} diff --git a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgAddTestCase.java b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgAddTestCase.java index 598738748cae..17b2a1417f2d 100644 --- a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgAddTestCase.java +++ b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgAddTestCase.java @@ -12,22 +12,21 @@ // limitations under the License. package org.zmlx.hg4idea; -import com.intellij.openapi.vfs.VirtualFile; -import org.testng.annotations.Test; +import com.intellij.openapi.vfs.*; +import org.testng.annotations.*; public class HgAddTestCase extends HgTestCase { @Test public void testAddFile() throws Exception { createFileInCommand("a.txt", "new file content"); - verify(runHg("status"), "A a.txt"); + verify(runHgOnProjectRepo("status"), added("a.txt")); } @Test public void testAddFileInDirectory() throws Exception { VirtualFile parent = createDirInCommand(myWorkingCopyDir, "com"); createFileInCommand(parent, "a.txt", "new file content"); - verify(runHg("status"), "A com/a.txt"); + verify(runHgOnProjectRepo("status"), added("com", "a.txt")); } - } diff --git a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgCatTestCase.java b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgCatTestCase.java new file mode 100644 index 000000000000..7220950a0fee --- /dev/null +++ b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgCatTestCase.java @@ -0,0 +1,57 @@ +package org.zmlx.hg4idea; + +import org.testng.annotations.*; +import org.zmlx.hg4idea.command.*; + +import java.nio.charset.*; + +import static org.testng.Assert.*; + +public class HgCatTestCase extends HgTestCase { + @Test + public void testCatCurrentRevision() throws Exception { + fillFile(projectRepo, new String[]{"file.txt"}, "initial contents"); + runHgOnProjectRepo("add", "."); + runHgOnProjectRepo("commit", "-m", "initial contents"); + + HgCatCommand command = new HgCatCommand(myProject); + String content = command.execute(getHgFile("file.txt"), HgRevisionNumber.getLocalInstance("0"), Charset.defaultCharset()); + assertEquals(content, "initial contents"); + } + + + @Test + public void testCatPastRevision() throws Exception { + fillFile(projectRepo, new String[]{"file.txt"}, "initial contents"); + runHgOnProjectRepo("add", "."); + runHgOnProjectRepo("commit", "-m", "initial contents"); + + runHgOnProjectRepo("rename", "file.txt", "file2.txt"); + runHgOnProjectRepo("commit", "-m", "file renamed"); + + fillFile(projectRepo, new String[]{"file2.txt"}, "updated contents"); + runHgOnProjectRepo("commit", "-m", "updated contents"); + + HgCatCommand command = new HgCatCommand(myProject); + String content = command.execute(getHgFile("file.txt"), HgRevisionNumber.getLocalInstance("0"), Charset.defaultCharset()); + assertEquals(content, "initial contents"); + } + + + @Test + public void testCatTrackFileNames() throws Exception { + fillFile(projectRepo, new String[]{"file.txt"}, "initial contents"); + runHgOnProjectRepo("add", "."); + runHgOnProjectRepo("commit", "-m", "initial contents"); + + runHgOnProjectRepo("rename", "file.txt", "file2.txt"); + runHgOnProjectRepo("commit", "-m", "file renamed"); + + fillFile(projectRepo, new String[]{"file2.txt"}, "updated contents"); + runHgOnProjectRepo("commit", "-m", "updated contents"); + + HgCatCommand command = new HgCatCommand(myProject); + String content = command.execute(getHgFile("file2.txt"), HgRevisionNumber.getLocalInstance("0"), Charset.defaultCharset()); + assertEquals(content, "initial contents"); + } +} diff --git a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgCopyTestCase.java b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgCopyTestCase.java index 386c40d1f744..bad194c25019 100644 --- a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgCopyTestCase.java +++ b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgCopyTestCase.java @@ -12,54 +12,54 @@ // limitations under the License. package org.zmlx.hg4idea; -import com.intellij.openapi.vfs.VirtualFile; -import org.testng.annotations.Test; +import com.intellij.openapi.vfs.*; +import org.testng.annotations.*; -import java.io.File; +import java.io.*; public class HgCopyTestCase extends HgTestCase { @Test public void testCopyUnmodifiedFile() throws Exception { VirtualFile file = createFileInCommand("a.txt", "new file content"); - runHg("commit", "-m", "added file"); + runHgOnProjectRepo("commit", "-m", "added file"); copyFileInCommand(file, "b.txt"); - verify(runHg("status"), "A b.txt"); + verify(runHgOnProjectRepo("status"), added("b.txt")); } @Test public void testCopyModifiedFile() throws Exception { VirtualFile file = createFileInCommand("a.txt", "new file content"); - runHg("commit", "-m", "added file"); + runHgOnProjectRepo("commit", "-m", "added file"); editFileInCommand(myProject, file, "newer content"); - verify(runHg("status"), "M a.txt"); + verify(runHgOnProjectRepo("status"), modified("a.txt")); copyFileInCommand(file, "b.txt"); - verify(runHg("status"), "M a.txt", "A b.txt"); + verify(runHgOnProjectRepo("status"), modified("a.txt"), added("b.txt")); } @Test public void testCopyUnversionedFile() throws Exception { VirtualFile file = makeFile(new File(myWorkingCopyDir.getPath(), "a.txt")); copyFileInCommand(file, "b.txt"); - verify(runHg("status"), "? a.txt", "? b.txt"); + verify(runHgOnProjectRepo("status"), unknown("a.txt"), unknown("b.txt")); } @Test public void testCopyCopiedFile() throws Exception { VirtualFile file = createFileInCommand("a.txt", "new file content"); - runHg("commit", "-m", "added file"); + runHgOnProjectRepo("commit", "-m", "added file"); copyFileInCommand(file, "b.txt"); copyFileInCommand(file, "c.txt"); - verify(runHg("status"), "A b.txt", "A c.txt"); + verify(runHgOnProjectRepo("status"), added("b.txt"), added("c.txt")); } @Test public void testCopyDirWithFiles() throws Exception { VirtualFile parent = createDirInCommand(myWorkingCopyDir, "com"); createFileInCommand(parent, "a.txt", "new file content"); - runHg("commit", "-m", "added file"); + runHgOnProjectRepo("commit", "-m", "added file"); copyFileInCommand(parent, "org"); - verify(runHg("status"), "A org/a.txt"); + verify(runHgOnProjectRepo("status"), added("org", "a.txt")); } } diff --git a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgDeleteTestCase.java b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgDeleteTestCase.java index 38f90a611f3a..5ee97db38a88 100644 --- a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgDeleteTestCase.java +++ b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgDeleteTestCase.java @@ -12,26 +12,26 @@ // limitations under the License. package org.zmlx.hg4idea; -import com.intellij.openapi.vfs.VirtualFile; -import org.testng.Assert; -import org.testng.annotations.Test; +import com.intellij.openapi.vfs.*; +import org.testng.*; +import org.testng.annotations.*; -import java.io.File; +import java.io.*; public class HgDeleteTestCase extends HgTestCase { @Test public void testDeleteUnmodifiedFile() throws Exception { VirtualFile file = createFileInCommand("a.txt", "new file content"); - runHg("commit", "-m", "added file"); + runHgOnProjectRepo("commit", "-m", "added file"); deleteFileInCommand(file); - verify(runHg("status"), "R a.txt"); + verify(runHgOnProjectRepo("status"), removed("a.txt")); } @Test public void testDeleteUnversionedFile() throws Exception { VirtualFile file = makeFile(new File(myWorkingCopyDir.getPath(), "a.txt")); - verify(runHg("status"), "? a.txt"); + verify(runHgOnProjectRepo("status"), unknown("a.txt")); deleteFileInCommand(file); Assert.assertFalse(file.exists()); } @@ -46,20 +46,20 @@ public class HgDeleteTestCase extends HgTestCase { @Test public void testDeleteModifiedFile() throws Exception { VirtualFile file = createFileInCommand("a.txt", "new file content"); - runHg("commit", "-m", "added file"); + runHgOnProjectRepo("commit", "-m", "added file"); editFileInCommand(myProject, file, "even newer content"); - verify(runHg("status"), "M a.txt"); + verify(runHgOnProjectRepo("status"), modified("a.txt")); deleteFileInCommand(file); - verify(runHg("status"), "R a.txt"); + verify(runHgOnProjectRepo("status"), removed("a.txt")); } @Test public void testDeleteDirWithFiles() throws Exception { VirtualFile parent = createDirInCommand(myWorkingCopyDir, "com"); createFileInCommand(parent, "a.txt", "new file content"); - runHg("commit", "-m", "added file"); + runHgOnProjectRepo("commit", "-m", "added file"); deleteFileInCommand(parent); - verify(runHg("status"), "R com/a.txt"); + verify(runHgOnProjectRepo("status"), removed("com", "a.txt")); } } diff --git a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgFromClonedTestCase.java b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgFromClonedTestCase.java new file mode 100644 index 000000000000..f6a65b2a9ad9 --- /dev/null +++ b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgFromClonedTestCase.java @@ -0,0 +1,82 @@ +// Copyright 2010 Victor Iacoban +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under +// the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions and +// limitations under the License. +package org.zmlx.hg4idea; + +import com.intellij.openapi.vcs.*; +import com.intellij.openapi.vfs.*; +import com.intellij.testFramework.fixtures.*; +import com.intellij.vcsUtil.*; +import org.testng.annotations.*; + +import java.io.*; + +import static org.testng.Assert.*; + +public class HgFromClonedTestCase extends AbstractHgTestCase { + + protected File remoteRepo; + protected File projectRepo; + private TempDirTestFixture remoteRepoDir; + private TempDirTestFixture projectRepoDir; + protected VirtualFile projectRepoVirtualFile; + + @BeforeMethod + public void setUp() throws Exception { + remoteRepoDir = IdeaTestFixtureFactory.getFixtureFactory().createTempDirTestFixture(); + projectRepoDir = IdeaTestFixtureFactory.getFixtureFactory().createTempDirTestFixture(); + + remoteRepo = createAndFillHgRepo(remoteRepoDir, "remote"); + projectRepo = cloneRemoteRepository(projectRepoDir, remoteRepo, "project"); + + initProject(projectRepo); + activateVCS(HgVcs.VCS_NAME); + + projectRepoVirtualFile = VcsUtil.getVirtualFile(projectRepo); + + enableSilentOperation(VcsConfiguration.StandardConfirmation.ADD); + enableSilentOperation(VcsConfiguration.StandardConfirmation.REMOVE); + } + + private File cloneRemoteRepository(TempDirTestFixture projectRepoDir, File remoteRepo, String destination) throws Exception { + projectRepoDir.setUp(); + String projectTempParent = projectRepoDir.getTempDirPath(); + + File projectRepo = new File(projectTempParent, destination); + runHg(null, "clone", remoteRepo.getAbsolutePath(), projectRepo.getAbsolutePath()); + assertTrue(projectRepo.exists()); + return projectRepo; + } + + private File createAndFillHgRepo(TempDirTestFixture remoteRepoDir, String dirName) throws Exception { + remoteRepoDir.setUp(); + File remoteRepo = new File(remoteRepoDir.getTempDirPath(), dirName); + assertTrue(remoteRepo.mkdir()); + + + verify(runHg(remoteRepo, "init")); + + File aFile = fillFile(remoteRepo, new String[]{"com", "a.txt"}, "file contents"); + + verify(runHg(remoteRepo, "add", aFile.getPath())); + verify(runHg(remoteRepo, "status"), added("com", "a.txt")); + verify(runHg(remoteRepo, "commit", "-m", "initial contents")); + + return remoteRepo; + } + + @AfterMethod + public void tearDown() throws Exception { +// remoteRepoDir.tearDown(); +// projectRepoDir.tearDown(); + } +} diff --git a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgLogTestCase.java b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgLogTestCase.java new file mode 100644 index 000000000000..b037d391f7f0 --- /dev/null +++ b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgLogTestCase.java @@ -0,0 +1,36 @@ +// Copyright 2008-2010 Victor Iacoban +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under +// the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions and +// limitations under the License. +package org.zmlx.hg4idea; + +import org.testng.annotations.*; +import org.zmlx.hg4idea.command.*; + +import java.util.*; + +import static org.testng.Assert.*; + +public class HgLogTestCase extends HgTestCase { + + @Test + public void testCommitMessagesWithMultipleLines() throws Exception { + fillFile(projectRepo, new String[]{"file.txt"}, "initial contents"); + runHgOnProjectRepo("add", "."); + runHgOnProjectRepo("commit", "-m", "initial\ncontents"); + + fillFile(projectRepo, new String[]{"file.txt"}, "updated contents"); + runHgOnProjectRepo("commit", "-m", "updated\ncontents"); + + List fileLog = new HgLogCommand(myProject).execute(getHgFile("file.txt"), 10, false); + assertEquals(fileLog.size(), 2, "The file history should show two entries"); + } +} diff --git a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgMoveTestCase.java b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgMoveTestCase.java index 2507f22b20b5..387557b7fad9 100644 --- a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgMoveTestCase.java +++ b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgMoveTestCase.java @@ -12,10 +12,10 @@ // limitations under the License. package org.zmlx.hg4idea; -import com.intellij.openapi.vfs.VirtualFile; -import org.testng.annotations.Test; +import com.intellij.openapi.vfs.*; +import org.testng.annotations.*; -import java.io.File; +import java.io.*; public class HgMoveTestCase extends HgTestCase { @@ -27,19 +27,19 @@ public class HgMoveTestCase extends HgTestCase { VirtualFile parent2 = createDirInCommand(myWorkingCopyDir, "org"); moveFileInCommand(file, parent2); - verify(runHg("status"), "A org/a.txt"); + verify(runHgOnProjectRepo("status"), added("org", "a.txt")); } @Test public void testMoveUnchangedFile() throws Exception { VirtualFile parent1 = createDirInCommand(myWorkingCopyDir, "com"); VirtualFile file = createFileInCommand(parent1, "a.txt", "new file content"); - runHg("commit", "-m", "added file"); + runHgOnProjectRepo("commit", "-m", "added file"); VirtualFile parent2 = createDirInCommand(myWorkingCopyDir, "org"); moveFileInCommand(file, parent2); - verify(runHg("status"), "A org/a.txt", "R com/a.txt"); + verify(runHgOnProjectRepo("status"), added("org", "a.txt"), removed("com", "a.txt")); } @Test @@ -47,12 +47,12 @@ public class HgMoveTestCase extends HgTestCase { VirtualFile parent1 = createDirInCommand(myWorkingCopyDir, "com"); VirtualFile dir = createDirInCommand(parent1, "zzz"); createFileInCommand(dir, "a.txt", "new file content"); - runHg("commit", "-m", "added file"); + runHgOnProjectRepo("commit", "-m", "added file"); VirtualFile parent2 = createDirInCommand(myWorkingCopyDir, "org"); moveFileInCommand(dir, parent2); - verify(runHg("status"), "A org/zzz/a.txt", "R com/zzz/a.txt"); + verify(runHgOnProjectRepo("status"), added("org", "zzz", "a.txt"), removed("com", "zzz", "a.txt")); } @Test @@ -62,12 +62,12 @@ public class HgMoveTestCase extends HgTestCase { File unversionedFile = new File(parent1.getPath(), "a.txt"); VirtualFile file = makeFile(unversionedFile); - verify(runHg("status"), "? com/a.txt"); + verify(runHgOnProjectRepo("status"), unknown("com", "a.txt")); VirtualFile parent2 = createDirInCommand(myWorkingCopyDir, "org"); moveFileInCommand(file, parent2); - verify(runHg("status"), "? org/a.txt"); + verify(runHgOnProjectRepo("status"), unknown("org", "a.txt")); } } diff --git a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgRenameTestCase.java b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgRenameTestCase.java index f14a5b9e0d20..1e923a2705d3 100644 --- a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgRenameTestCase.java +++ b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgRenameTestCase.java @@ -12,54 +12,54 @@ // limitations under the License. package org.zmlx.hg4idea; -import com.intellij.openapi.vfs.VirtualFile; -import org.testng.annotations.Test; +import com.intellij.openapi.vfs.*; +import org.testng.annotations.*; -import java.io.File; +import java.io.*; public class HgRenameTestCase extends HgTestCase { @Test public void testRenameUnmodifiedFile() throws Exception { VirtualFile file = createFileInCommand("a.txt", "new file content"); - runHg("commit", "-m", "added file"); + runHgOnProjectRepo("commit", "-m", "added file"); renameFileInCommand(file, "b.txt"); - verify(runHg("status"), "A b.txt", "R a.txt"); + verify(runHgOnProjectRepo("status"), added("b.txt"), removed("a.txt")); } @Test public void testRenameModifiedFile() throws Exception { VirtualFile file = createFileInCommand("a.txt", "new file content"); - runHg("commit", "-m", "added file"); + runHgOnProjectRepo("commit", "-m", "added file"); editFileInCommand(myProject, file, "modified new file content"); - verify(runHg("status"), "M a.txt"); + verify(runHgOnProjectRepo("status"), modified("a.txt")); renameFileInCommand(file, "b.txt"); - verify(runHg("status"), "A b.txt", "R a.txt"); + verify(runHgOnProjectRepo("status"), added("b.txt"), removed("a.txt")); } @Test public void testRenameNewFile() throws Exception { VirtualFile file = createFileInCommand("a.txt", "new file content"); renameFileInCommand(file, "b.txt"); - verify(runHg("status"), "A b.txt"); + verify(runHgOnProjectRepo("status"), added("b.txt")); } @Test public void testRenameRenamedFile() throws Exception { VirtualFile file = createFileInCommand("a.txt", "new file content"); - runHg("commit", "-m", "added file"); + runHgOnProjectRepo("commit", "-m", "added file"); renameFileInCommand(file, "b.txt"); renameFileInCommand(file, "c.txt"); - verify(runHg("status"), "A c.txt", "R a.txt"); + verify(runHgOnProjectRepo("status"), added("c.txt"), removed("a.txt")); } @Test public void testRenameVersionedFolder() throws Exception { VirtualFile parent = createDirInCommand(myWorkingCopyDir, "com"); createFileInCommand(parent, "a.txt", "new file content"); - runHg("commit", "-m", "added file"); + runHgOnProjectRepo("commit", "-m", "added file"); renameFileInCommand(parent, "org"); - verify(runHg("status"), "A org/a.txt", "R com/a.txt"); + verify(runHgOnProjectRepo("status"), added("org", "a.txt"), removed("com", "a.txt")); } @Test @@ -68,20 +68,20 @@ public class HgRenameTestCase extends HgTestCase { File unversionedFile = new File(parent.getPath(), "a.txt"); makeFile(unversionedFile); - verify(runHg("status"), "? com/a.txt"); + verify(runHgOnProjectRepo("status"), unknown("com", "a.txt")); renameFileInCommand(parent, "org"); - verify(runHg("status"), "? org/a.txt"); + verify(runHgOnProjectRepo("status"), unknown("org", "a.txt")); } @Test public void testRenameUnversionedFile() throws Exception { File unversionedFile = new File(myWorkingCopyDir.getPath(), "a.txt"); VirtualFile file = makeFile(unversionedFile); - verify(runHg("status"), "? a.txt"); + verify(runHgOnProjectRepo("status"), unknown("a.txt")); renameFileInCommand(file, "b.txt"); - verify(runHg("status"), "? b.txt"); + verify(runHgOnProjectRepo("status"), unknown("b.txt")); } } diff --git a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgResolveConflictTestCase.java b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgResolveConflictTestCase.java new file mode 100644 index 000000000000..fc121c421964 --- /dev/null +++ b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgResolveConflictTestCase.java @@ -0,0 +1,62 @@ +// Copyright 2008-2010 Victor Iacoban +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under +// the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions and +// limitations under the License. +package org.zmlx.hg4idea; + +import com.intellij.openapi.vfs.*; +import org.testng.*; +import org.testng.annotations.*; +import org.zmlx.hg4idea.command.*; + +public class HgResolveConflictTestCase extends HgTestCase{ + + public static final String BASE = "one\n" + + "conflicting\n" + + "two"; + + public static final String HEAD_ONE = "one\n" + + "conflicting in one\n" + + "two"; + + public static final String HEAD_TWO = "one\n" + + "conflicting in two\n" + + "two"; + + + @Test + public void testMergeDataIsCorrect() throws Exception { + createFileInCommand("conflicting", BASE); + runHgOnProjectRepo("commit", "-m", "initial version"); + + createFileInCommand("conflicting", HEAD_ONE); + runHgOnProjectRepo("commit", "-m", "first head"); + + //revert to the first commit + runHgOnProjectRepo("up", "--clean", "0"); + createFileInCommand("conflicting", HEAD_TWO); + runHgOnProjectRepo("commit", "-m", "second head"); + + runHgOnProjectRepo("--config", "ui.merge=internal:merge", "merge"); + + VirtualFile repoFile = makeFile(projectRepo); + HgResolveCommand.MergeData data = new HgResolveCommand(myProject).getResolveData(repoFile, repoFile.findChild("conflicting")); + + Assert.assertEquals(data.getBase(), BASE.getBytes(), + "The base merge information should correspond to the common ancestor"); + Assert.assertEquals(data.getLocal(), HEAD_TWO.getBytes(), + "The local merge information should correspond to the original parent before the merge"); + Assert.assertEquals(data.getOther(), HEAD_ONE.getBytes(), + "The 'remote' merge information should correspond to the merged in head"); + + + } +} diff --git a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgRevertTestCase.java b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgRevertTestCase.java new file mode 100644 index 000000000000..aff316032bc8 --- /dev/null +++ b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgRevertTestCase.java @@ -0,0 +1,47 @@ +package org.zmlx.hg4idea; + +import org.testng.annotations.*; +import org.zmlx.hg4idea.command.*; + +import java.nio.charset.*; + +import static org.testng.Assert.*; + +public class HgRevertTestCase extends HgTestCase { + @Test + public void testRevertToCurrentRevision() throws Exception { + fillFile(projectRepo, new String[]{"file.txt"}, "initial contents"); + runHgOnProjectRepo("add", "."); + runHgOnProjectRepo("commit", "-m", "initial contents"); + + fillFile(projectRepo, new String[]{"file.txt"}, "new contents"); + + HgRevertCommand revertCommand = new HgRevertCommand(myProject); + revertCommand.execute(getHgFile("file.txt"), null, false); + + HgCatCommand catCommand = new HgCatCommand(myProject); + String content = catCommand.execute(getHgFile("file.txt"), null, Charset.defaultCharset()); + + assertEquals(content, "initial contents"); + } + + + @Test + public void testRevertToGivenRevision() throws Exception { + fillFile(projectRepo, new String[]{"file.txt"}, "initial contents"); + runHgOnProjectRepo("add", "."); + runHgOnProjectRepo("commit", "-m", "initial contents"); + + fillFile(projectRepo, new String[]{"file.txt"}, "new contents"); + runHgOnProjectRepo("commit", "-m", "new contents"); + + HgRevertCommand revertCommand = new HgRevertCommand(myProject); + revertCommand.execute(getHgFile("file.txt"), HgRevisionNumber.getLocalInstance("0"), false); + + HgCatCommand catCommand = new HgCatCommand(myProject); + String content = catCommand.execute(getHgFile("file.txt"), HgRevisionNumber.getLocalInstance("0"), Charset.defaultCharset()); + + assertEquals(content, "initial contents"); + } + +} diff --git a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgTestCase.java b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgTestCase.java index 94d391534271..9ab1c2ee4262 100644 --- a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgTestCase.java +++ b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgTestCase.java @@ -12,66 +12,49 @@ // limitations under the License. package org.zmlx.hg4idea; -import com.intellij.execution.process.ProcessOutput; -import com.intellij.openapi.vcs.VcsConfiguration; -import com.intellij.openapi.vcs.VcsShowConfirmationOption; -import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager; -import com.intellij.openapi.vfs.LocalFileSystem; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.testFramework.AbstractVcsTestCase; -import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory; -import com.intellij.testFramework.fixtures.TempDirTestFixture; -import com.intellij.vcsUtil.VcsUtil; -import org.testng.Assert; -import org.testng.annotations.BeforeMethod; +import com.intellij.execution.process.*; +import com.intellij.openapi.vcs.*; +import com.intellij.testFramework.fixtures.*; +import org.testng.*; +import org.testng.annotations.*; -import java.io.File; -import java.io.IOException; +import java.io.*; -public abstract class HgTestCase extends AbstractVcsTestCase { +public abstract class HgTestCase extends AbstractHgTestCase { - private File repo; + protected File projectRepo; + private TempDirTestFixture tempDirTestFixture; @BeforeMethod public void setUp() throws Exception { - final IdeaTestFixtureFactory fixtureFactory = IdeaTestFixtureFactory.getFixtureFactory(); - TempDirTestFixture testFixture = fixtureFactory.createTempDirTestFixture(); - testFixture.setUp(); + tempDirTestFixture = IdeaTestFixtureFactory.getFixtureFactory().createTempDirTestFixture(); + tempDirTestFixture.setUp(); + projectRepo = new File(tempDirTestFixture.getTempDirPath(), "repo"); + Assert.assertTrue(projectRepo.mkdir()); - repo = new File(testFixture.getTempDirPath(), "repo"); - Assert.assertTrue(repo.mkdir()); - - myClientBinaryPath = new File("/usr/bin"); - - verify(runClient("hg", null, repo, new String[] {"init"})); - initProject(repo); + ProcessOutput processOutput = runHg(projectRepo, "init"); + verify(processOutput); + initProject(projectRepo); activateVCS(HgVcs.VCS_NAME); enableSilentOperation(VcsConfiguration.StandardConfirmation.ADD); enableSilentOperation(VcsConfiguration.StandardConfirmation.REMOVE); } - protected ProcessOutput runHg(String... commandLine) throws IOException { - return runClient("hg", null, repo, commandLine); + @AfterMethod + public void tearDown() throws Exception { +// tempDirTestFixture.tearDown(); } - protected void enableSilentOperation(final VcsConfiguration.StandardConfirmation op) { - setStandardConfirmation( - HgVcs.VCS_NAME, op, VcsShowConfirmationOption.Value.DO_ACTION_SILENTLY - ); + protected ProcessOutput runHgOnProjectRepo(String... commandLine) throws IOException { + return runHg(projectRepo, commandLine); } - protected void disableSilentOperation(final VcsConfiguration.StandardConfirmation op) { - setStandardConfirmation( - HgVcs.VCS_NAME, op, VcsShowConfirmationOption.Value.DO_NOTHING_SILENTLY - ); + protected HgFile getHgFile(String... filepath) { + File fileToInclude = projectRepo; + for (String path : filepath) { + fileToInclude = new File(fileToInclude, path); + } + return new HgFile(myWorkingCopyDir, fileToInclude); } - - protected VirtualFile makeFile(File file) throws IOException { - Assert.assertTrue(file.createNewFile()); - VcsDirtyScopeManager.getInstance(myProject).fileDirty(myWorkingCopyDir); - LocalFileSystem.getInstance().refresh(false); - return VcsUtil.getVirtualFile(file); - } - } diff --git a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgUpdateTestCase.java b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgUpdateTestCase.java new file mode 100644 index 000000000000..5343675d13d5 --- /dev/null +++ b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/HgUpdateTestCase.java @@ -0,0 +1,283 @@ +// Copyright 2010 Victor Iacoban +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under +// the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions and +// limitations under the License. +package org.zmlx.hg4idea; + +import com.intellij.execution.process.*; +import com.intellij.openapi.progress.*; +import com.intellij.openapi.vcs.*; +import com.intellij.openapi.vcs.update.*; +import com.intellij.openapi.vfs.*; +import org.testng.annotations.*; +import org.zmlx.hg4idea.command.*; +import org.zmlx.hg4idea.provider.update.*; + +import java.io.*; +import java.util.*; + +import static org.testng.Assert.*; + +@SuppressWarnings({"ConstantConditions", "ThrowableResultOfMethodCallIgnored"}) +public class HgUpdateTestCase extends HgFromClonedTestCase { + + @Test + public void updateKeepsWorkingAfterPull() throws Exception { + + changeFile_A_AndCommitInRemoteRepository(); + + //do a simple pull without an update + HgPullCommand pull = new HgPullCommand(myProject, projectRepoVirtualFile); + pull.setSource(new HgShowConfigCommand(myProject).getDefaultPath(projectRepoVirtualFile)); + pull.setUpdate(false); + pull.execute(); + + assertEquals( determineNumberOfIncomingChanges( projectRepo ), 0, + "The update operation should have pulled the incoming changes from the default repository." ); + + updateThroughPlugin(); + + HgRevisionNumber parentRevision = new HgWorkingCopyRevisionsCommand(myProject).firstParent(projectRepoVirtualFile); + assertEquals( parentRevision.getRevision(), "1", + "The working directory should have been updated to the latest version" ); + + } + + @Test + public void updateShouldMergeAndCommitChanges() throws Exception{ + changeFile_A_AndCommitInRemoteRepository(); + createAndCommitNewFileInLocalRepository(); + //we've got diverging heads in remote and local now + + PreUpdateInformation preUpdateInformation = new PreUpdateInformation().getPreUpdateInformation(); + HgRevisionNumber incomingHead = preUpdateInformation.getIncomingHead(); + HgRevisionNumber headBeforeUpdate = preUpdateInformation.getHeadBeforeUpdate(); + + List warnings = updateThroughPlugin(); + + assertEquals(warnings.size(), 0, "Plain update should not generate warnings"); + + assertCurrentHeadIsMerge(incomingHead, headBeforeUpdate); + } + + @Test + public void updateShouldNotMergeIfMultipleHeadsBeforeUpdate() throws Exception { + changeFile_A_AndCommitInRemoteRepository(); + createAndCommitNewFileInLocalRepository(); + + //create multiple heads locally + HgUpdateCommand updateCommand = new HgUpdateCommand(myProject, projectRepoVirtualFile); + HgRevisionNumber parent = new HgParentsCommand(myProject).execute(projectRepoVirtualFile).get(0); + HgParentsCommand parentsCommand = new HgParentsCommand(myProject); + parentsCommand.setRevision(parent); + List parents = parentsCommand.execute(projectRepoVirtualFile); + updateCommand.setRevision(parents.get(0).getChangeset()); + updateCommand.execute(); + + createFileInCommand(projectRepoVirtualFile.findChild("com"),"c.txt", "updated content"); + runHg(projectRepo, "commit", "-m", "creating new local head"); + + List branchHeads = new HgHeadsCommand(myProject, projectRepoVirtualFile).execute(); + assertEquals(branchHeads.size(), 2); + + HgRevisionNumber parentBeforeUpdate = new HgWorkingCopyRevisionsCommand(myProject).identify(projectRepoVirtualFile); + assertUpdateThroughPluginFails(); + HgRevisionNumber parentAfterUpdate = new HgWorkingCopyRevisionsCommand(myProject).identify(projectRepoVirtualFile); + List branchHeadsAfterUpdate = new HgHeadsCommand(myProject, projectRepoVirtualFile).execute(); + + assertEquals(branchHeadsAfterUpdate.size(), 3); + assertEquals(parentBeforeUpdate, parentAfterUpdate); + } + + @Test + public void localChangesShouldBeAllowedWithFastForwardUpdate() throws Exception{ + createFileInCommand(projectRepoVirtualFile.findChild("com"), "b.txt", "other file"); + runHg(projectRepo, "commit", "-m", "adding second file"); + runHg(projectRepo, "push"); + + runHg(remoteRepo, "update"); + changeFile_A_AndCommitInRemoteRepository(); + + fillFile(projectRepo, new String[]{"com", "b.txt"}, "local change"); + createFileInCommand(projectRepoVirtualFile.findChild("com"), "c.txt", "other file"); + + + assertIsChanged(HgFileStatusEnum.MODIFIED, "com", "b.txt"); + assertIsChanged(HgFileStatusEnum.ADDED, "com", "c.txt"); + + PreUpdateInformation information = new PreUpdateInformation().getPreUpdateInformation(); + HgRevisionNumber incomingHead = information.getIncomingHead(); + + List nonFatalWarnings = updateThroughPlugin(); + + assertTrue(nonFatalWarnings.isEmpty()); + HgRevisionNumber parentAfterUpdate = new HgParentsCommand(myProject).execute(projectRepoVirtualFile).get(0); + assertEquals(incomingHead, parentAfterUpdate); + + assertIsChanged(HgFileStatusEnum.MODIFIED, "com", "b.txt"); + assertIsChanged(HgFileStatusEnum.ADDED, "com", "c.txt"); + } + + @Test + public void updateShouldNotMergeTwoHeadsComingFromRemote() throws Exception { + String originalParent = runHg(remoteRepo, "parents", "--template", "{rev}\n").getStdout().trim(); + changeFile_A_AndCommitInRemoteRepository(); + + runHg(remoteRepo, "update", "--clean", originalParent); + + File file = fillFile(remoteRepo, new String[]{"com", "b.txt"}, "second file"); + runHg(remoteRepo, "add", file.getPath()); + runHg(remoteRepo, "commit", "-m", "adding second file"); + + assertUpdateThroughPluginFails(); + + List branchHeads = new HgHeadsCommand(myProject, projectRepoVirtualFile).execute(); + assertEquals(branchHeads.size(), 2); + + + } + + private void assertIsChanged(HgFileStatusEnum status, String... filepath) { + Set localChanges = new HgStatusCommand(myProject).execute(projectRepoVirtualFile); + assertTrue(localChanges.contains(new HgChange(getHgFile(filepath), status))); + } + + private HgFile getHgFile(String... filepath) { + File fileToInclude = projectRepo; + for (int i = 0; i < filepath.length; i++) { + fileToInclude = new File(fileToInclude, filepath[i]); + } + return new HgFile(projectRepoVirtualFile, fileToInclude); + } + + private void assertCurrentHeadIsMerge(HgRevisionNumber incomingHead, HgRevisionNumber headBeforeUpdate) { + List newHeads = new HgHeadsCommand(myProject, projectRepoVirtualFile).execute(); + assertEquals(newHeads.size(), 1, "After updating, there should be only one head because the remote heads should have been merged"); + HgRevisionNumber newHead = newHeads.get(0); + HgParentsCommand parents = new HgParentsCommand(myProject); + parents.setRevision(newHead); + List parentRevisions = parents.execute(projectRepoVirtualFile); + assertEquals(parentRevisions.size(), 2); + assertTrue(parentRevisions.contains(incomingHead)); + assertTrue(parentRevisions.contains(headBeforeUpdate)); + } + + @Test + public void updateShouldMergeButNotCommitWithConflicts() throws Exception{ + changeFile_A_AndCommitInRemoteRepository(); + + VirtualFile commonFile = projectRepoVirtualFile.findChild("com").findChild("a.txt"); + assertNotNull(commonFile); + + editFileInCommand(myProject, commonFile, "conflicting content"); + runHg(projectRepo, "commit", "-m", "adding conflicting history to local repository"); + + PreUpdateInformation preUpdateInformation = new PreUpdateInformation().getPreUpdateInformation(); + HgRevisionNumber incomingHead = preUpdateInformation.getIncomingHead(); + HgRevisionNumber headBeforeUpdate = preUpdateInformation.getHeadBeforeUpdate(); + + List warnings = updateThroughPlugin(); + assertFalse(warnings.isEmpty()); + assertTrue(warnings.get(warnings.size()-1).getMessage().contains("conflicts")); + assertTrue(warnings.get(warnings.size()-1).getMessage().contains("commit")); + + List parents = new HgWorkingCopyRevisionsCommand(myProject).parents(projectRepoVirtualFile); + assertEquals(parents.size(), 2); + assertTrue(parents.contains(incomingHead)); + assertTrue(parents.contains(headBeforeUpdate)); + } + + @Test + public void updateShouldNotMergeWithNonCommittedChanges() throws Exception { + changeFile_A_AndCommitInRemoteRepository(); + + //generate some extra local history + createAndCommitNewFileInLocalRepository(); + + HgRevisionNumber parentBeforeUpdate = new HgWorkingCopyRevisionsCommand(myProject).parents(projectRepoVirtualFile).get(0); + + editFileInCommand(myProject, projectRepoVirtualFile.findFileByRelativePath("com/a.txt"), "modified file contents"); + + assertUpdateThroughPluginFails(); + + assertEquals( new HgHeadsCommand( myProject, projectRepoVirtualFile ).execute().size(), 2, + "Remote head should have been pulled in" ); + + assertEquals( new HgWorkingCopyRevisionsCommand( myProject ).parents( projectRepoVirtualFile ).size(), 1, + "No merge should have been attempted" ); + + assertEquals( new HgWorkingCopyRevisionsCommand( myProject ).parents( projectRepoVirtualFile ).get(0), parentBeforeUpdate, + "No merge should have been attempted" ); + } + + private void assertUpdateThroughPluginFails() { + try { + updateThroughPlugin(); + fail("The update should have failed because a merge cannot be initiated with outstanding changes"); + } catch (VcsException e) { + //expected + } + } + + private void createAndCommitNewFileInLocalRepository() throws IOException { + createFileInCommand(projectRepoVirtualFile.findChild("com"), "b.txt", "other file"); + runHg(projectRepo, "commit", "-m", "adding non-conflicting history to local repository"); + } + + private List updateThroughPlugin() throws VcsException { + HgRegularUpdater updater = new HgRegularUpdater(myProject, projectRepoVirtualFile, new org.zmlx.hg4idea.provider.update.HgUpdater.UpdateConfiguration()); + UpdatedFiles updatedFiles = UpdatedFiles.create(); + EmptyProgressIndicator indicator = new EmptyProgressIndicator(); + ArrayList nonFatalWarnings = new ArrayList(); + updater.update(updatedFiles, indicator, nonFatalWarnings); + return nonFatalWarnings; + } + + private void changeFile_A_AndCommitInRemoteRepository() throws IOException { + fillFile(remoteRepo, new String[]{"com", "a.txt"}, "update file contents"); + runHg(remoteRepo, "commit", "-m", "Adding history to remote repository"); + + assertEquals( determineNumberOfIncomingChanges( projectRepo ), 1, + "The remote repository should have gotten new history" ); + } + + private int determineNumberOfIncomingChanges(File repo) throws IOException { + ProcessOutput result = runHg(repo, "-q", "incoming", "--template", "{rev} "); + String output = result.getStdout(); + return output.length() == 0 ? 0 : output.split(" ").length; + } + + private class PreUpdateInformation { + private HgRevisionNumber incomingHead; + private HgRevisionNumber headBeforeUpdate; + + public HgRevisionNumber getIncomingHead() { + return incomingHead; + } + + public HgRevisionNumber getHeadBeforeUpdate() { + return headBeforeUpdate; + } + + public PreUpdateInformation getPreUpdateInformation() { + List currentHeads = new HgHeadsCommand(myProject, projectRepoVirtualFile).execute(); + List incomingChangesets = new HgIncomingCommand(myProject).execute(projectRepoVirtualFile); + + assertEquals(currentHeads.size(), 1); + assertEquals(incomingChangesets.size(), 1); + + incomingHead = incomingChangesets.get(0); + headBeforeUpdate = currentHeads.get(0); + return this; + } + } +} + From be73916330fd95330ac6c9c3f6d5077b4e9affbd Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Mon, 31 May 2010 18:17:05 +0400 Subject: [PATCH 032/212] Merge. don't run HgExecutableValidator in unit test mode --- plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java index 75e93431f2f2..da2c5089f196 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java @@ -13,6 +13,7 @@ package org.zmlx.hg4idea; import com.intellij.concurrency.*; +import com.intellij.openapi.application.*; import com.intellij.openapi.fileEditor.*; import com.intellij.openapi.options.*; import com.intellij.openapi.project.*; @@ -212,8 +213,12 @@ public class HgVcs extends AbstractVcs { @Override protected void start() throws VcsException { - HgExecutableValidator validator = new HgExecutableValidator(myProject); - started = validator.check(globalSettings); + if (ApplicationManager.getApplication().isUnitTestMode()) { + started = true; + } else { + HgExecutableValidator validator = new HgExecutableValidator(myProject); + started = validator.check(globalSettings); + } } @Override From 2d6dc187ea5960d9fbba84593504aa5f0c2c6af9 Mon Sep 17 00:00:00 2001 From: Alexey Pegov Date: Mon, 31 May 2010 18:45:00 +0400 Subject: [PATCH 033/212] statusbar gray icons --- platform/icons/src/ide/emptyFatalError.png | Bin 525 -> 386 bytes platform/icons/src/ide/hectorNo.png | Bin 509 -> 436 bytes platform/icons/src/ide/readwrite.png | Bin 316 -> 322 bytes 3 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 platform/icons/src/ide/hectorNo.png diff --git a/platform/icons/src/ide/emptyFatalError.png b/platform/icons/src/ide/emptyFatalError.png index e15858a947c849d969dcfb0340926b053472878c..7594291f2229eb4c2ae3d813640210aea61e0e91 100755 GIT binary patch delta 322 zcmV-I0lof>1cC#QNq;0sL_t(|+Qd__ZNxAPz^ofsvsM9 z3Ii@&q)FigJOcknQL-L3(tHsC21SWH-cdAERi0Td^5lBWo6Gg)79uB_p1fMx2I+bc zV5S{Kbv4f4pC69^o(#NE(wVlCEDa9P^4tL5=?%R9J(6$|OMe#WtSFJi7OgUhT_B(*k?3L6!1dua90SlP+h(S~LLp``uO<+=FHM>`kpsgMp zKC%Sgi2gMPyk1IyEJG@Rg@ZS9IeLXTcfYnOxt{@<$jtj503*#*kG4NuswhQ>>f{4; zz+h$Iz@Q2F**hX@n+sU-z>{^?#Hef&_Qmgq2{wIA@Hfq*ts`O9x;yyyzws`>0C5q2 U>6oVCod5s;07*qoM6N<$f-6&$r2qf` delta 462 zcmV;<0Wto91C0cbNq?_NL_t(|+Qd`6Pr^_Te=QD1J_?aw!k~PWP$e;8k(d~_PW}=7 za~K?)j3bl(gAAJJAd6A7QpAtZ#Da;sweQ}m_o~H`vN8CQ%e%IBzx&>nHw2N$*)!L8AZ!fLZ|11z;V<*cg3s+_` zD9JcGIlV9tq=hNtDGiXWuGK1ewN%iMK0Z_51PHS7tx_&%_4R5V!}W-WfIXMiR%OR= zCdmOn7(^`>WPiMykrq$`ZE0ySCX$fiBq40#y^>7iu&w188ZaWL%d+eT1{O{Z?wMl* zaIMkkJ(tNSDIr`KBy1m_UpD8S9nk>MyZ3`fK1;lC<-zbpINb;UPN9Rde(gUzS%Gi? zNU-jM;j<-T2=O|R7Q}{$B{@64G;DhmQ_Dp;tt4~en@6B6D)-F68-n2?{p`RrfasBN z)AM)>1NH0MeiH*xZBH<;e`$-#V@diGQTq44@mqia0MJ-;h+P*RDF6Tf07*qoM6N<$ Ef<7JAmH+?% diff --git a/platform/icons/src/ide/hectorNo.png b/platform/icons/src/ide/hectorNo.png old mode 100644 new mode 100755 index 5d364814ed37fe1605f37811e7cd758fb6384782..9328a0876e6cbc0852d462958606af21084d400b GIT binary patch delta 372 zcmV-)0gL|q1GEE>Nq<&JL_t(|+MH9nPQ*YA^hEgxI$C-pDyXkdfhds>If;&+0g3A9 z5PShW(lyW`pyw|*nQ^?%dP9e$&F*@~9=`%r6_c~`E3q@|0vz%@`jHyLaHsB$w>Pse z+{68?bP}QkEHV%|f{-va19y&*=K&6%q^tH?v{+4Sowv_$Qrh@M zHy`%y>{tv^9g+dHY%kFuu9MO#n}O#*_p+?I|8=1~#v;Y|xuOP0;D5=l00RJb)}|F9 SBGG>U00001N{S#Nq?V7L_t(|+MH6mio#G3oje2uwGbbO#ag6Iu|*&tS_>A7SX=B* zXzQPB;RmGLSc|p77J?dZ3lUqj@a^UddoS7eDE7eQPVUT{duHxcuGcF8tyYUprxQ&k z6a2pT_D;9>@a?-?F7r>j-6mB;R8?im=kped{gtxWETvK@ihsxB6pcpdm(=R_`;t)- z=(^6fTrO*wOooofBP)VkE*CnV&!i{{Qfom;l3+9%Q6v&!AH}f4;UGysAle0l3N=7x zjmP6RI4Bgwl}bgb2mpC@m>|8|?Op|eP|)l3!o>jc(%ib(NhA`V{(>uL8iqmZ^_qu@ z0dBWj&VfIh&41u_ee=Q!fM%&wqFgRVp67AT@Tb!$X`049;>f!hV!d9MEQ`g0s?{n% z2>`!XEb@LhUk@qh4hDlJP8tq}v|6oX0DE`~^Z8t~aB~Y_<-TIE8146aGEI|D$BLUs zCX;{i?#%$`;1t`osZc2J23E_m#OWQ!ab&W7hrq oKIKPnUH55R3BK?D;75P~0L>M_^dU4=od5s;07*qoM6N<$f(7;2MF0Q* diff --git a/platform/icons/src/ide/readwrite.png b/platform/icons/src/ide/readwrite.png index eca7170a6ae840d0cddd2be7b316c285673575eb..469f8f1f4a5fe317c0ff4d656f1f677049ff3a78 100755 GIT binary patch delta 257 zcmV+c0sj8H0>T22Nq^)?L_t(|+Qd_#4#F@LyaxybpFmIxAAv*6pa=@Hkl^?tG(n+2 z5I%tqn4U*6gCxhbD^p8WGQmsQU7Njo_pYsxM3?BHV+@)$*PEUD%%p8;KmxNuN-x^G zpAP#t1wPp<7u;&(!XmS{7J@5@#ucy<atp! z4Wmp{EL1VI&`#YuId*=u66p6dcu>3Iu1lb~wG!~#0(sQ@*0L`ZS;HYTd*CJek}kpWrU2=eK->cq&><-d7#SHkfYeJU z_aji`4p7jHXaf+j!-$~%|K}kp5DhI|GMN||lK=k)>taAMN^~7a?ZdDM9UEG>ocWIh z01ZBau9gM6{}~vbJbA*9nq307WX`l+;u8|g``b6J0DED_rj@7? Date: Mon, 31 May 2010 18:54:43 +0400 Subject: [PATCH 034/212] [Mercurial] More merge. --- .../hg4idea/src/org/zmlx/hg4idea/HgIncomingStatusUpdater.java | 3 ++- .../hg4idea/src/org/zmlx/hg4idea/HgOutgoingStatusUpdater.java | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgIncomingStatusUpdater.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgIncomingStatusUpdater.java index 6dc67418635b..22167ba20b70 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgIncomingStatusUpdater.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgIncomingStatusUpdater.java @@ -40,6 +40,7 @@ class HgIncomingStatusUpdater implements HgUpdater { public void run() { new Task.Backgroundable(project, "Checking Incoming Changesets", true) { public void run(@NotNull ProgressIndicator indicator) { + if (project.isDisposed()) return; HgIncomingCommand command = new HgIncomingCommand(project); VcsRoot[] roots = ProjectLevelVcsManager.getInstance(project).getAllVcsRoots(); List changesets = new LinkedList(); @@ -50,7 +51,7 @@ class HgIncomingStatusUpdater implements HgUpdater { } }.queue(); } - }); + }, project.getDisposed()); } private final class IncomingChangesetFormatter implements HgChangesetStatus.ChangesetWriter { diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgOutgoingStatusUpdater.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgOutgoingStatusUpdater.java index a652ceaffbdf..f48b088c3861 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgOutgoingStatusUpdater.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgOutgoingStatusUpdater.java @@ -40,6 +40,7 @@ class HgOutgoingStatusUpdater implements HgUpdater { public void run() { new Task.Backgroundable(project, "Checking Outgoing Changesets", true) { public void run(@NotNull ProgressIndicator indicator) { + if (project.isDisposed()) return; HgOutgoingCommand command = new HgOutgoingCommand(project); VcsRoot[] roots = ProjectLevelVcsManager.getInstance(project).getAllVcsRoots(); List outgoing = new LinkedList(); @@ -51,7 +52,7 @@ class HgOutgoingStatusUpdater implements HgUpdater { } }.queue(); } - }); + }, project.getDisposed()); } private final class OutgoingChangesetFormatter implements HgChangesetStatus.ChangesetWriter { From 15c4d28a876f24d4723549a7ee5b80c31fd90cba Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Mon, 31 May 2010 19:18:30 +0400 Subject: [PATCH 035/212] ability to change name of method to any string constant. Detection of incorrect usages --- .../actions/ChangeSignatureAction.java | 57 +++++++++++++++++-- .../ChangeSignatureProcessor.java | 8 +++ .../JavaChangeSignatureHandler.java | 14 ++++- .../JavaChangeSignatureUsageProcessor.java | 5 ++ .../PossiblyIncorrectUsage.java | 24 ++++++++ .../ChangeSignatureTargetTest.java | 5 +- .../ChangeSignatureHandler.java | 5 +- .../ChangeSignatureUsageProcessor.java | 2 + .../src/messages/RefactoringBundle.properties | 1 + .../GrChageSignatureUsageSearcher.java | 17 ++---- .../changeSignature/GrChangeInfoImpl.java | 9 ++- .../GrChangeSignatureDialog.java | 15 ++++- .../GrChangeSignatureHandler.java | 30 ++++++++-- .../GrChangeSignatureProcessor.java | 13 ++++- .../GrChangeSignatureUsageProcessor.java | 11 ++++ .../GrMethodCallUsageInfo.java | 38 ++++++++----- .../ReplaceVarargWithArray.groovy | 6 +- .../ReplaceVarargWithArray_after.groovy | 4 +- 18 files changed, 212 insertions(+), 52 deletions(-) create mode 100644 java/java-impl/src/com/intellij/refactoring/changeSignature/PossiblyIncorrectUsage.java diff --git a/java/java-impl/src/com/intellij/refactoring/actions/ChangeSignatureAction.java b/java/java-impl/src/com/intellij/refactoring/actions/ChangeSignatureAction.java index 382cc4adb1ed..4c21639f963a 100644 --- a/java/java-impl/src/com/intellij/refactoring/actions/ChangeSignatureAction.java +++ b/java/java-impl/src/com/intellij/refactoring/actions/ChangeSignatureAction.java @@ -21,9 +21,12 @@ import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.actionSystem.LangDataKeys; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.ScrollType; +import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.refactoring.RefactoringActionHandler; import com.intellij.refactoring.changeSignature.ChangeSignatureHandler; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public class ChangeSignatureAction extends BaseRefactoringAction { @@ -38,18 +41,60 @@ public class ChangeSignatureAction extends BaseRefactoringAction { protected boolean isAvailableOnElementInEditor(final PsiElement element, final Editor editor) { final Document document = editor.getDocument(); final PsiFile file = PsiDocumentManager.getInstance(element.getProject()).getPsiFile(document); - final ChangeSignatureHandler handler = getChangeSignatureHandler(element.getLanguage()); - if (handler == null) return false; - if (file != null && handler.findTargetMember(file, editor) != null) { - return true; + if (file == null) return false; + PsiElement targetMember = findTargetMember(file, editor); + if (targetMember == null) return false; + final ChangeSignatureHandler targetHandler = getChangeSignatureHandler(targetMember.getLanguage()); + if (targetHandler == null) return false; + return true; + } + + @Nullable + private static PsiElement findTargetMember(PsiFile file, Editor editor) { + final PsiElement element = file.findElementAt(editor.getCaretModel().getOffset()); + final PsiElement targetMember = findTargetMember(element); + if (targetMember != null) return targetMember; + + final PsiReference reference = file.findReferenceAt(editor.getCaretModel().getOffset()); + if (reference == null) return null; + return reference.resolve(); + } + + @Nullable + private static PsiElement findTargetMember(@Nullable PsiElement element) { + if (element == null) return null; + final ChangeSignatureHandler fileHandler = getChangeSignatureHandler(element.getLanguage()); + if (fileHandler != null) { + final PsiElement targetMember = fileHandler.findTargetMember(element); + if (targetMember != null) return targetMember; } - return element instanceof PsiMethod || element instanceof PsiClass; + final PsiReference reference = element.getReference(); + if (reference == null) return null; + return reference.resolve(); } public RefactoringActionHandler getHandler(DataContext dataContext) { final Language language = LangDataKeys.LANGUAGE.getData(dataContext); if (language != null) { - return getChangeSignatureHandler(language); + return new RefactoringActionHandler() { + public void invoke(@NotNull Project project, Editor editor, PsiFile file, DataContext dataContext) { + editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE); + final PsiElement targetMember = findTargetMember(file, editor); + if (targetMember == null) return; + final ChangeSignatureHandler handler = getChangeSignatureHandler(targetMember.getLanguage()); + if (handler == null) return; + handler.invoke(project, new PsiElement[]{targetMember}, dataContext); + } + + public void invoke(@NotNull Project project, @NotNull PsiElement[] elements, DataContext dataContext) { + if (elements.length != 1) return; + final PsiElement targetMember = findTargetMember(elements[0]); + if (targetMember == null) return; + final ChangeSignatureHandler handler = getChangeSignatureHandler(targetMember.getLanguage()); + if (handler == null) return; + handler.invoke(project, new PsiElement[]{targetMember}, dataContext); + } + }; } return null; } diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java index c543d4ee7b8b..286ad737555a 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java @@ -204,6 +204,14 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor { protected void preprocessCovariantOverriders(final List covariantOverriderInfos) { } + @Override + protected boolean isPreviewUsages(UsageInfo[] usages) { + for (ChangeSignatureUsageProcessor processor : ChangeSignatureUsageProcessor.EP_NAME.getExtensions()) { + if (processor.shouldPreviewUsages(myChangeInfo, usages)) return true; + } + return super.isPreviewUsages(usages); + } + protected boolean isProcessCovariantOverriders() { return Messages .showYesNoDialog(myProject, RefactoringBundle.message("do.you.want.to.process.overriding.methods.with.covariant.return.type"), diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureHandler.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureHandler.java index 0a40702708d5..dc627dc1d068 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureHandler.java @@ -97,12 +97,20 @@ public class JavaChangeSignatureHandler implements ChangeSignatureHandler { } @Nullable - public PsiMember findTargetMember(PsiFile file, Editor editor) { + public PsiElement findTargetMember(PsiFile file, Editor editor) { PsiElement element = file.findElementAt(editor.getCaretModel().getOffset()); + return findTargetMember(element); + } + + public PsiElement findTargetMember(PsiElement element) { if (PsiTreeUtil.getParentOfType(element, PsiParameterList.class) != null) { return PsiTreeUtil.getParentOfType(element, PsiMethod.class); } + if (element.getParent() instanceof PsiMethod && ((PsiMethod)element.getParent()).getNameIdentifier()==element) { + return element.getParent(); + } + final PsiMethodCallExpression expression = PsiTreeUtil.getParentOfType(element, PsiMethodCallExpression.class); if (expression != null) { assert element != null; @@ -133,10 +141,10 @@ public class JavaChangeSignatureHandler implements ChangeSignatureHandler { if (referenceElement != null) { final PsiElement resolved = referenceElement.resolve(); if (resolved instanceof PsiClass) { - return (PsiMember)resolved; + return resolved; } else if (resolved instanceof PsiMethod) { - return (PsiMember)resolved; + return resolved; } } } diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java index 08ea1f00f740..907cb41ccb74 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java @@ -524,6 +524,10 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr return true; } + public boolean shouldPreviewUsages(ChangeInfo changeInfo, UsageInfo[] usages) { + return false; + } + private static void generateDelegate(JavaChangeInfo changeInfo) throws IncorrectOperationException { final PsiMethod delegate = (PsiMethod)changeInfo.getMethod().copy(); final PsiClass targetClass = changeInfo.getMethod().getContainingClass(); @@ -854,6 +858,7 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr try { PsiMethod prototype; final PsiMethod method = myChangeInfo.getMethod(); + if (!StdLanguages.JAVA.equals(method.getLanguage())) return; PsiManager manager = PsiManager.getInstance(method.getProject()); PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory(); final CanonicalTypes.Type returnType = myChangeInfo.getNewReturnType(); diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/PossiblyIncorrectUsage.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/PossiblyIncorrectUsage.java new file mode 100644 index 000000000000..68c2fd17f529 --- /dev/null +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/PossiblyIncorrectUsage.java @@ -0,0 +1,24 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.refactoring.changeSignature; + +/** + * All Usages that may be incorrect must implement this interface. In other case incorrect usages will be processed by default processor + * @author Maxim.Medvedev + */ +public interface PossiblyIncorrectUsage { + boolean isCorrect(); +} diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTargetTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTargetTest.java index c2161d9179ce..e27c45a45726 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTargetTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTargetTest.java @@ -7,6 +7,7 @@ package com.intellij.refactoring; import com.intellij.JavaTestUtil; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.projectRoots.impl.JavaSdkImpl; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiMember; import com.intellij.refactoring.changeSignature.JavaChangeSignatureHandler; import com.intellij.testFramework.LightCodeInsightTestCase; @@ -43,8 +44,8 @@ public class ChangeSignatureTargetTest extends LightCodeInsightTestCase { String basePath = "/refactoring/changeSignatureTarget/" + getTestName(true); @NonNls final String filePath = basePath + ".java"; configureByFile(filePath); - final PsiMember member = new JavaChangeSignatureHandler().findTargetMember(getFile(), getEditor()); + final PsiElement member = new JavaChangeSignatureHandler().findTargetMember(getFile(), getEditor()); assertNotNull(member); - assertEquals(expectedMemberName, member.getName()); + assertEquals(expectedMemberName, ((PsiMember)member).getName()); } } diff --git a/platform/lang-api/src/com/intellij/refactoring/changeSignature/ChangeSignatureHandler.java b/platform/lang-api/src/com/intellij/refactoring/changeSignature/ChangeSignatureHandler.java index 00a88165b802..4a1dc6b870fb 100644 --- a/platform/lang-api/src/com/intellij/refactoring/changeSignature/ChangeSignatureHandler.java +++ b/platform/lang-api/src/com/intellij/refactoring/changeSignature/ChangeSignatureHandler.java @@ -25,9 +25,12 @@ import org.jetbrains.annotations.Nullable; /** * @author Maxim.Medvedev */ -public interface ChangeSignatureHandler extends RefactoringActionHandler{ +public interface ChangeSignatureHandler extends RefactoringActionHandler { String REFACTORING_NAME = RefactoringBundle.message("changeSignature.refactoring.name"); @Nullable PsiElement findTargetMember(PsiFile file, Editor editor); + + @Nullable + PsiElement findTargetMember(PsiElement element); } diff --git a/platform/lang-api/src/com/intellij/refactoring/changeSignature/ChangeSignatureUsageProcessor.java b/platform/lang-api/src/com/intellij/refactoring/changeSignature/ChangeSignatureUsageProcessor.java index 3857afd60dda..240c05f885f8 100644 --- a/platform/lang-api/src/com/intellij/refactoring/changeSignature/ChangeSignatureUsageProcessor.java +++ b/platform/lang-api/src/com/intellij/refactoring/changeSignature/ChangeSignatureUsageProcessor.java @@ -35,4 +35,6 @@ public interface ChangeSignatureUsageProcessor { boolean processUsage(ChangeInfo changeInfo, UsageInfo usageInfo, boolean beforeMethodChange, UsageInfo[] usages); boolean processPrimaryMethod(ChangeInfo changeInfo); + + boolean shouldPreviewUsages(ChangeInfo changeInfo, UsageInfo[] usages); } diff --git a/platform/platform-resources-en/src/messages/RefactoringBundle.properties b/platform/platform-resources-en/src/messages/RefactoringBundle.properties index 97799609dd07..34e5f971a7ed 100644 --- a/platform/platform-resources-en/src/messages/RefactoringBundle.properties +++ b/platform/platform-resources-en/src/messages/RefactoringBundle.properties @@ -261,6 +261,7 @@ do.you.want.to.process.overriding.methods.with.covariant.return.type=Do you want changing.signature.of.0=Changing signature of {0} there.is.already.a.0.in.1.it.will.conflict.with.the.new.parameter=There is already a {0} in {1}. It will conflict with the new parameter. 0.to.change.signature={0} to change signature +New.name.of.method.is.not.java.identifier=New name of method is not Java identifier references.to.be.changed=References to be changed {0} source.folder.0.has.package.prefix.1=Source folder {0} has package prefix ''{1}''\nPackage ''{2}'' cannot be created there. javadoc.as.is=&As is diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChageSignatureUsageSearcher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChageSignatureUsageSearcher.java index 01a4d03ea1f6..4404a611603b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChageSignatureUsageSearcher.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChageSignatureUsageSearcher.java @@ -34,10 +34,8 @@ import com.intellij.usageView.UsageViewUtil; import com.intellij.util.containers.HashSet; import org.jetbrains.plugins.groovy.GroovyFileType; import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocTagValueToken; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousClassDefinition; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; @@ -206,16 +204,7 @@ class GrChageSignatureUsageSearcher { boolean isToCatchExceptions = isToThrowExceptions && needToCatchExceptions(RefactoringUtil.getEnclosingMethod(element)); if (PsiUtil.isMethodUsage(element)) { - final GrArgumentList argList = PsiUtil.getArgumentsList(element); - //enum constant may not have argList - if (argList == null) { - if (element instanceof GrEnumConstant) { - result.add(new GrMethodCallUsageInfo(element, isToModifyArgs, isToCatchExceptions)); - } - } - else { - result.add(new GrMethodCallUsageInfo(element, isToModifyArgs,isToCatchExceptions)); - } + result.add(new GrMethodCallUsageInfo(element, isToModifyArgs, isToCatchExceptions, method)); } else if (element instanceof GrDocTagValueToken) { result.add(new UsageInfo(ref.getElement())); @@ -229,7 +218,7 @@ class GrChageSignatureUsageSearcher { LOG.assertTrue(method.isConstructor()); final PsiClass psiClass = (PsiClass)element; if (psiClass instanceof GrAnonymousClassDefinition) { - result.add(new GrMethodCallUsageInfo(element, isToModifyArgs, isToCatchExceptions)); + result.add(new GrMethodCallUsageInfo(element, isToModifyArgs, isToCatchExceptions, method)); continue; } /*if (!(myChangeInfo instanceof JavaChangeInfoImpl)) continue; todo propagate methods @@ -274,6 +263,8 @@ class GrChageSignatureUsageSearcher { return overridingMethods; } + + private static void addParameterUsages(PsiParameter parameter, ArrayList results, ParameterInfo info) { PsiManager manager = parameter.getManager(); GlobalSearchScope projectScope = GlobalSearchScope.projectScope(manager.getProject()); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeInfoImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeInfoImpl.java index 935fb50e6100..a7ab92d8f41a 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeInfoImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeInfoImpl.java @@ -16,6 +16,7 @@ package org.jetbrains.plugins.groovy.refactoring.changeSignature; import com.intellij.lang.Language; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.refactoring.changeSignature.JavaChangeInfo; import com.intellij.refactoring.changeSignature.JavaParameterInfo; @@ -151,7 +152,11 @@ class GrChangeInfoImpl implements JavaChangeInfo { } if (myIsNameChanged) { - myNewNameIdentifier = JavaPsiFacade.getElementFactory(getMethod().getProject()).createIdentifier(newName); + if (StringUtil.isJavaIdentifier(newName)) { + myNewNameIdentifier = JavaPsiFacade.getElementFactory(getMethod().getProject()).createIdentifier(newName); + } else { + myNewNameIdentifier = getMethod().getNameIdentifier(); + } } PsiElementFactory factory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory(); @@ -189,8 +194,6 @@ class GrChangeInfoImpl implements JavaChangeInfo { } } } - - } @NotNull diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java index a395ba7e7e53..7d6a6378fc11 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.java @@ -35,6 +35,7 @@ import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.debugger.fragments.GroovyCodeFragment; +import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement; @@ -313,8 +314,19 @@ public class GrChangeSignatureDialog extends RefactoringDialog { CommonRefactoringUtil.showErrorHint(myProject, null, hint, GroovyRefactoringBundle.message("incorrect.data"), HelpID.CHANGE_SIGNATURE); } + private boolean isGroovyMethodName(String name) { + String methodText = "def " + name + "(){}"; + try { + final GrMethod method = GroovyPsiElementFactory.getInstance(getProject()).createMethodFromText(methodText); + return method != null; + } + catch (Throwable e) { + return false; + } + } + private boolean validateInputData() { - if (!StringUtil.isJavaIdentifier(getNewName())) { + if (!isGroovyMethodName(getNewName())) { showErrorHint(message("name.is.wrong", getNewName())); return false; } @@ -327,6 +339,7 @@ public class GrChangeSignatureDialog extends RefactoringDialog { for (GrTableParameterInfo info : myParameterModel.getParameterInfos()) { if (!StringUtil.isJavaIdentifier(info.getName())) { showErrorHint(message("name.is.wrong", info.getName())); + return false; } if (!checkType(info.getTypeFragment())) { showErrorHint(message("type.for.parameter.is.incorrect", info.getName())); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureHandler.java index 0ff6bf70226f..72f9b39c5bea 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureHandler.java @@ -25,6 +25,7 @@ import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiMethod; +import com.intellij.psi.PsiReference; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.HelpID; import com.intellij.refactoring.RefactoringBundle; @@ -87,15 +88,36 @@ public class GrChangeSignatureHandler implements ChangeSignatureHandler { } @Nullable - public PsiMethod findTargetMember(PsiFile file, Editor editor) { + public PsiElement findTargetMember(PsiFile file, Editor editor) { final PsiElement element = file.findElementAt(editor.getCaretModel().getOffset()); + final PsiElement targetMember = findTargetMember(element); + if (targetMember != null) return targetMember; + + final PsiReference reference = file.findReferenceAt(editor.getCaretModel().getOffset()); + if (reference != null) { + return reference.resolve(); + } + return null; + } + + @Nullable + public PsiElement findTargetMember(PsiElement element) { final GrParameterList parameterList = PsiTreeUtil.getParentOfType(element, GrParameterList.class); if (parameterList != null) { final PsiElement parent = parameterList.getParent(); - if (parent instanceof PsiMethod) return (PsiMethod)parent; + if (parent instanceof PsiMethod) return parent; + } + + if (element.getParent() instanceof GrMethod && ((GrMethod)element.getParent()).getNameIdentifierGroovy() == element) { + return element.getParent(); } final GrMethodCallExpression expression = PsiTreeUtil.getParentOfType(element, GrMethodCallExpression.class); - if (expression == null) return null; - return expression.resolveMethod(); + if (expression != null) { + return expression.resolveMethod(); + } + + final PsiReference ref = element.getReference(); + if (ref == null) return null; + return ref.resolve(); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java index b18e4fafe209..901ce677d63c 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureProcessor.java @@ -23,6 +23,7 @@ import com.intellij.psi.PsiMethod; import com.intellij.refactoring.BaseRefactoringProcessor; import com.intellij.refactoring.changeSignature.ChangeSignatureUsageProcessor; import com.intellij.refactoring.changeSignature.ChangeSignatureViewDescriptor; +import com.intellij.refactoring.changeSignature.PossiblyIncorrectUsage; import com.intellij.refactoring.rename.RenameUtil; import com.intellij.refactoring.ui.ConflictsDialog; import com.intellij.refactoring.util.MoveRenameUsageInfo; @@ -85,7 +86,9 @@ public class GrChangeSignatureProcessor extends BaseRefactoringProcessor { else { moveRenameInfos.remove(element); usedElements.add(element); - result.add(info); + if (!(info instanceof PossiblyIncorrectUsage) || ((PossiblyIncorrectUsage)info).isCorrect()) { + result.add(info); + } } } result.addAll(moveRenameInfos.values()); @@ -158,4 +161,12 @@ public class GrChangeSignatureProcessor extends BaseRefactoringProcessor { prepareSuccessful(); return true; } + + @Override + protected boolean isPreviewUsages(UsageInfo[] usages) { + for (ChangeSignatureUsageProcessor processor : ChangeSignatureUsageProcessor.EP_NAME.getExtensions()) { + if (processor.shouldPreviewUsages(myChangeInfo, usages)) return true; + } + return super.isPreviewUsages(usages); + } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java index dc01b03df1b5..67b5a8dabe06 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java @@ -106,6 +106,17 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc return processPrimaryMethodInner(grInfo, method, null); } + public boolean shouldPreviewUsages(ChangeInfo changeInfo, UsageInfo[] usages) { + if (!StringUtil.isJavaIdentifier(changeInfo.getNewName())) return true; + + for (UsageInfo usage : usages) { + if (usage instanceof GrMethodCallUsageInfo) { + if (((GrMethodCallUsageInfo)usage).isPossibleUsage()) return true; + } + } + return false; + } + private static boolean generateDelegate(GrChangeInfoImpl grInfo) { final GrMethod method = grInfo.getMethod(); final PsiClass psiClass = method.getContainingClass(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodCallUsageInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodCallUsageInfo.java index a92476e6e3c1..86c5adeb6848 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodCallUsageInfo.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodCallUsageInfo.java @@ -18,6 +18,8 @@ package org.jetbrains.plugins.groovy.refactoring.changeSignature; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiSubstitutor; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.refactoring.changeSignature.PossiblyIncorrectUsage; import com.intellij.usageView.UsageInfo; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; @@ -35,10 +37,9 @@ import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; /** * @author Maxim.Medvedev */ -public class GrMethodCallUsageInfo extends UsageInfo { +public class GrMethodCallUsageInfo extends UsageInfo implements PossiblyIncorrectUsage { private final boolean myToChangeArguments; private final boolean myToCatchExceptions; - private final PsiMethod myReferencedMethod; private GrClosureSignatureUtil.ArgInfo[] myMapToArguments; private PsiSubstitutor mySubstitutor; @@ -50,30 +51,35 @@ public class GrMethodCallUsageInfo extends UsageInfo { return myToChangeArguments; } - public GrMethodCallUsageInfo(PsiElement element, boolean isToChangeArguments, boolean isToCatchExceptions) { + public GrMethodCallUsageInfo(PsiElement element, boolean isToChangeArguments, boolean isToCatchExceptions, PsiMethod method) { super(element); + final GroovyResolveResult resolveResult = resolveMethod(element); + if (resolveResult == null || resolveResult.getElement() == null) { + mySubstitutor = PsiSubstitutor.EMPTY; + } + else { + mySubstitutor = resolveResult.getSubstitutor(); + } + GrClosureSignature signature = GrClosureSignatureUtil.createSignature(method, mySubstitutor); myToChangeArguments = isToChangeArguments; myToCatchExceptions = isToCatchExceptions; - final GroovyResolveResult resolveResult = resolveMethod(element); - myReferencedMethod = (PsiMethod)resolveResult.getElement(); - mySubstitutor = resolveResult.getSubstitutor(); final GrArgumentList list = PsiUtil.getArgumentsList(element); if (list == null) { myMapToArguments = GrClosureSignatureUtil.ArgInfo.EMPTY_ARRAY; } else { - final GrClosureSignature signature = GrClosureSignatureUtil.createSignature(myReferencedMethod, mySubstitutor); myMapToArguments = - GrClosureSignatureUtil.mapParametersToArguments(signature, list, element.getManager(), myReferencedMethod.getResolveScope()); + GrClosureSignatureUtil.mapParametersToArguments(signature, list, element.getManager(), GlobalSearchScope.allScope(getProject())); } } @Nullable - private static GroovyResolveResult resolveMethod(final PsiElement ref) { + public static GroovyResolveResult resolveMethod(final PsiElement ref) { if (ref instanceof GrEnumConstant) return ((GrEnumConstant)ref).resolveConstructorGenerics(); PsiElement parent = ref.getParent(); if (parent instanceof GrCallExpression) { - return ((GrCallExpression)parent).getMethodVariants()[0]; + final GroovyResolveResult[] variants = ((GrCallExpression)parent).getMethodVariants(); + return variants.length == 1 ? variants[0] : null; } else if (parent instanceof GrApplicationStatement) { final GrExpression expression = ((GrApplicationStatement)parent).getFunExpression(); @@ -88,9 +94,6 @@ public class GrMethodCallUsageInfo extends UsageInfo { return null; } - public PsiMethod getReferencedMethod() { - return myReferencedMethod; - } public GrClosureSignatureUtil.ArgInfo[] getMapToArguments() { return myMapToArguments; @@ -99,4 +102,13 @@ public class GrMethodCallUsageInfo extends UsageInfo { public PsiSubstitutor getSubstitutor() { return mySubstitutor; } + + public boolean isPossibleUsage() { + final GroovyResolveResult resolveResult = resolveMethod(getElement()); + return resolveResult == null || resolveResult.getElement() == null; + } + + public boolean isCorrect() { + return myMapToArguments != null; + } } diff --git a/plugins/groovy/testdata/refactoring/changeSignature/ReplaceVarargWithArray.groovy b/plugins/groovy/testdata/refactoring/changeSignature/ReplaceVarargWithArray.groovy index d47669e10e5a..474f03f2e63e 100644 --- a/plugins/groovy/testdata/refactoring/changeSignature/ReplaceVarargWithArray.groovy +++ b/plugins/groovy/testdata/refactoring/changeSignature/ReplaceVarargWithArray.groovy @@ -1,14 +1,14 @@ class List {} class Base { - void foo(String s, List... l) {} + def foo(String s, List... l) {} } class Inheritor extends Base { - void foo(String s, List... l) {} + def foo(String s, List... l) {} { - new Inheritor().foo("a", new ArrayList()); + new Inheritor().foo("a", new List()); } } diff --git a/plugins/groovy/testdata/refactoring/changeSignature/ReplaceVarargWithArray_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/ReplaceVarargWithArray_after.groovy index be83d989534c..dcd4a35fed33 100644 --- a/plugins/groovy/testdata/refactoring/changeSignature/ReplaceVarargWithArray_after.groovy +++ b/plugins/groovy/testdata/refactoring/changeSignature/ReplaceVarargWithArray_after.groovy @@ -1,11 +1,11 @@ class List {} class Base { - void foo(List[] l, String s) {} + def foo(List[] l, String s) {} } class Inheritor extends Base { - void foo(List[] l, String s) {} + def foo(List[] l, String s) {} { new Inheritor().foo([new List()] as List[], "a"); From 6283165ab2d3ad3c77a16501ca4c27a0b2515611 Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 31 May 2010 16:45:01 +0400 Subject: [PATCH 036/212] find method duplicates: match super expressions ( IDEA-45118 ) --- .../util/duplicates/DuplicatesFinder.java | 7 +++++++ .../SuperInTheSameContext.java | 17 ++++++++++++++++ .../SuperInTheSameContextQualified.java | 20 +++++++++++++++++++ .../SuperInTheSameContextQualified.java.after | 20 +++++++++++++++++++ .../FindMethodDuplicatesMiscTest.java | 8 ++++++++ 5 files changed, 72 insertions(+) create mode 100644 java/java-tests/testData/refactoring/methodDuplicatesMisc/SuperInTheSameContext.java create mode 100644 java/java-tests/testData/refactoring/methodDuplicatesMisc/SuperInTheSameContextQualified.java create mode 100644 java/java-tests/testData/refactoring/methodDuplicatesMisc/SuperInTheSameContextQualified.java.after diff --git a/java/java-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java b/java/java-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java index 2d2c2d5892a1..798d8832701c 100644 --- a/java/java-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java +++ b/java/java-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java @@ -435,6 +435,13 @@ public class DuplicatesFinder { final PsiElement candidateContextClass = candidateQualifier == null ? PsiTreeUtil.getParentOfType(candidate, PsiClass.class) : candidateQualifier.resolve(); return contextClass == candidateContextClass; } + } else if (pattern instanceof PsiSuperExpression) { + final PsiJavaCodeReferenceElement qualifier = ((PsiSuperExpression)pattern).getQualifier(); + final PsiElement contextClass = qualifier == null ? PsiTreeUtil.getParentOfType(pattern, PsiClass.class) : qualifier.resolve(); + if (candidate instanceof PsiSuperExpression) { + final PsiJavaCodeReferenceElement candidateQualifier = ((PsiSuperExpression)candidate).getQualifier(); + return contextClass == (candidateQualifier != null ? candidateQualifier.resolve() : PsiTreeUtil.getParentOfType(candidate, PsiClass.class)); + } } PsiElement[] children1 = getFilteredChildren(pattern); diff --git a/java/java-tests/testData/refactoring/methodDuplicatesMisc/SuperInTheSameContext.java b/java/java-tests/testData/refactoring/methodDuplicatesMisc/SuperInTheSameContext.java new file mode 100644 index 000000000000..a1d887e47378 --- /dev/null +++ b/java/java-tests/testData/refactoring/methodDuplicatesMisc/SuperInTheSameContext.java @@ -0,0 +1,17 @@ +public class a { + public void login() { + System.out.println(); + } +} + +class b extends a { + public void doLogin() throws Exception { + super.login(); + } +} + +class c extends a { + public void doLogin() throws Exception { + super.login(); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/methodDuplicatesMisc/SuperInTheSameContextQualified.java b/java/java-tests/testData/refactoring/methodDuplicatesMisc/SuperInTheSameContextQualified.java new file mode 100644 index 000000000000..cfa8195a874d --- /dev/null +++ b/java/java-tests/testData/refactoring/methodDuplicatesMisc/SuperInTheSameContextQualified.java @@ -0,0 +1,20 @@ +public class a { + public void login() { + System.out.println(); + } +} + +class b extends a { + public void doLogin() throws Exception { + super.login(); + } + + public void foo() throws Exception { + new Runnable() { + public void run() { + b.super.login(); + } + }.run(); + } +} + diff --git a/java/java-tests/testData/refactoring/methodDuplicatesMisc/SuperInTheSameContextQualified.java.after b/java/java-tests/testData/refactoring/methodDuplicatesMisc/SuperInTheSameContextQualified.java.after new file mode 100644 index 000000000000..8fdb60b8d25c --- /dev/null +++ b/java/java-tests/testData/refactoring/methodDuplicatesMisc/SuperInTheSameContextQualified.java.after @@ -0,0 +1,20 @@ +public class a { + public void login() { + System.out.println(); + } +} + +class b extends a { + public void doLogin() throws Exception { + super.login(); + } + + public void foo() throws Exception { + new Runnable() { + public void run() { + doLogin(); + } + }.run(); + } +} + diff --git a/java/java-tests/testSrc/com/intellij/refactoring/FindMethodDuplicatesMiscTest.java b/java/java-tests/testSrc/com/intellij/refactoring/FindMethodDuplicatesMiscTest.java index cc6e5789936c..de1cf687c778 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/FindMethodDuplicatesMiscTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/FindMethodDuplicatesMiscTest.java @@ -53,4 +53,12 @@ public class FindMethodDuplicatesMiscTest extends FindMethodDuplicatesBaseTest { public void testCorrectThis() throws Exception { doTest(); } + + public void testSuperInTheSameContext() throws Exception { + doTest(false); + } + + public void testSuperInTheSameContextQualified() throws Exception { + doTest(); + } } \ No newline at end of file From 2c00677a5385a8b8a7ea83de89c3b53f484d0d24 Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 31 May 2010 17:58:52 +0400 Subject: [PATCH 037/212] introduce PsiQualifiedExpression --- .../intellij/psi/PsiQualifiedExpression.java | 23 +++++++++++++++++++ .../com/intellij/psi/PsiSuperExpression.java | 2 +- .../com/intellij/psi/PsiThisExpression.java | 2 +- 3 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 java/openapi/src/com/intellij/psi/PsiQualifiedExpression.java diff --git a/java/openapi/src/com/intellij/psi/PsiQualifiedExpression.java b/java/openapi/src/com/intellij/psi/PsiQualifiedExpression.java new file mode 100644 index 000000000000..58ea092e2760 --- /dev/null +++ b/java/openapi/src/com/intellij/psi/PsiQualifiedExpression.java @@ -0,0 +1,23 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.psi; + +import org.jetbrains.annotations.Nullable; + +public interface PsiQualifiedExpression extends PsiExpression { + @Nullable + PsiJavaCodeReferenceElement getQualifier(); +} \ No newline at end of file diff --git a/java/openapi/src/com/intellij/psi/PsiSuperExpression.java b/java/openapi/src/com/intellij/psi/PsiSuperExpression.java index 858bceef4d20..95215d17ea35 100644 --- a/java/openapi/src/com/intellij/psi/PsiSuperExpression.java +++ b/java/openapi/src/com/intellij/psi/PsiSuperExpression.java @@ -21,7 +21,7 @@ import org.jetbrains.annotations.Nullable; * Represents a Java super expression in a super method call. Note that the qualifier of * a super constructor call is represented as a {@link PsiKeyword} rather than a PsiSuperExpression. */ -public interface PsiSuperExpression extends PsiExpression { +public interface PsiSuperExpression extends PsiQualifiedExpression { /** * Returns the expression representing the class name qualifying the super * expression. diff --git a/java/openapi/src/com/intellij/psi/PsiThisExpression.java b/java/openapi/src/com/intellij/psi/PsiThisExpression.java index 9436a891711f..673e75188f4f 100644 --- a/java/openapi/src/com/intellij/psi/PsiThisExpression.java +++ b/java/openapi/src/com/intellij/psi/PsiThisExpression.java @@ -20,7 +20,7 @@ import org.jetbrains.annotations.Nullable; /** * Represents a Java this expression. */ -public interface PsiThisExpression extends PsiExpression { +public interface PsiThisExpression extends PsiQualifiedExpression { /** * Returns the expression representing the class name qualifying the this * expression. From 40d73b7c32e79fbb66fae029e285b885dee24bf5 Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 31 May 2010 18:01:25 +0400 Subject: [PATCH 038/212] replace method duplicates: qualify with super instead of this when method is located in the base class ( IDEA-21753 ) --- .../refactoring/util/RefactoringUtil.java | 32 ++++++++++++------- .../duplicates/MethodDuplicatesHandler.java | 7 +++- ...InsertSuperQualifierWhenNameConflicts.java | 11 +++++++ ...SuperQualifierWhenNameConflicts.java.after | 11 +++++++ .../FindMethodDuplicatesMiscTest.java | 4 +++ 5 files changed, 52 insertions(+), 13 deletions(-) create mode 100644 java/java-tests/testData/refactoring/methodDuplicatesMisc/InsertSuperQualifierWhenNameConflicts.java create mode 100644 java/java-tests/testData/refactoring/methodDuplicatesMisc/InsertSuperQualifierWhenNameConflicts.java.after diff --git a/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java b/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java index 33309695429d..8249dc4eb6ce 100644 --- a/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java +++ b/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java @@ -413,20 +413,28 @@ public class RefactoringUtil { } public static PsiThisExpression createThisExpression(PsiManager manager, PsiClass qualifierClass) throws IncorrectOperationException { - PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory(); - if (qualifierClass != null) { - PsiThisExpression qualifiedThis = (PsiThisExpression)factory.createExpressionFromText("q.this", null); - qualifiedThis = (PsiThisExpression)CodeStyleManager.getInstance(manager.getProject()).reformat(qualifiedThis); - PsiJavaCodeReferenceElement thisQualifier = qualifiedThis.getQualifier(); - LOG.assertTrue(thisQualifier != null); - thisQualifier.bindToElement(qualifierClass); - return qualifiedThis; - } - else { - return (PsiThisExpression)factory.createExpressionFromText("this", null); - } + return RefactoringUtil.createQualifiedExpression(manager, qualifierClass, "this"); } + public static PsiSuperExpression createSuperExpression(PsiManager manager, PsiClass qualifierClass) throws IncorrectOperationException { + return RefactoringUtil.createQualifiedExpression(manager, qualifierClass, "super"); + } + + private static T createQualifiedExpression(PsiManager manager, PsiClass qualifierClass, String qName) throws IncorrectOperationException { + PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory(); + if (qualifierClass != null) { + T qualifiedThis = (T)factory.createExpressionFromText("q." + qName, null); + qualifiedThis = (T)CodeStyleManager.getInstance(manager.getProject()).reformat(qualifiedThis); + PsiJavaCodeReferenceElement thisQualifier = qualifiedThis.getQualifier(); + LOG.assertTrue(thisQualifier != null); + thisQualifier.bindToElement(qualifierClass); + return qualifiedThis; + } + else { + return (T)factory.createExpressionFromText(qName, null); + } + } + /** * removes a reference to the specified class from the reference list given * diff --git a/java/java-impl/src/com/intellij/refactoring/util/duplicates/MethodDuplicatesHandler.java b/java/java-impl/src/com/intellij/refactoring/util/duplicates/MethodDuplicatesHandler.java index 546b6f4606c9..bb27d8b637fb 100644 --- a/java/java-impl/src/com/intellij/refactoring/util/duplicates/MethodDuplicatesHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/util/duplicates/MethodDuplicatesHandler.java @@ -257,7 +257,12 @@ public class MethodDuplicatesHandler implements RefactoringActionHandler { } else if (needStaticQualifier || myMethod.hasModifierProperty(PsiModifier.STATIC)) { qualifierExpression.replace(factory.createReferenceExpression(containingClass)); } else { - qualifierExpression.replace(RefactoringUtil.createThisExpression(containingClass.getManager(), containingClass)); + final PsiClass psiClass = PsiTreeUtil.getParentOfType(match.getMatchStart(), PsiClass.class); + if (psiClass != null && psiClass.isInheritor(containingClass, true)) { + qualifierExpression.replace(RefactoringUtil.createSuperExpression(containingClass.getManager(), psiClass)); + } else { + qualifierExpression.replace(RefactoringUtil.createThisExpression(containingClass.getManager(), containingClass)); + } } } VisibilityUtil.escalateVisibility(myMethod, match.getMatchStart()); diff --git a/java/java-tests/testData/refactoring/methodDuplicatesMisc/InsertSuperQualifierWhenNameConflicts.java b/java/java-tests/testData/refactoring/methodDuplicatesMisc/InsertSuperQualifierWhenNameConflicts.java new file mode 100644 index 000000000000..4683cf7ed776 --- /dev/null +++ b/java/java-tests/testData/refactoring/methodDuplicatesMisc/InsertSuperQualifierWhenNameConflicts.java @@ -0,0 +1,11 @@ +public class a { + void foo() { + System.out.println(); + } +} + +class b extends a { + void foo() { + System.out.println(); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/methodDuplicatesMisc/InsertSuperQualifierWhenNameConflicts.java.after b/java/java-tests/testData/refactoring/methodDuplicatesMisc/InsertSuperQualifierWhenNameConflicts.java.after new file mode 100644 index 000000000000..7cb74574c4f5 --- /dev/null +++ b/java/java-tests/testData/refactoring/methodDuplicatesMisc/InsertSuperQualifierWhenNameConflicts.java.after @@ -0,0 +1,11 @@ +public class a { + void foo() { + System.out.println(); + } +} + +class b extends a { + void foo() { + b.super.foo(); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/refactoring/FindMethodDuplicatesMiscTest.java b/java/java-tests/testSrc/com/intellij/refactoring/FindMethodDuplicatesMiscTest.java index de1cf687c778..4274ff719da1 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/FindMethodDuplicatesMiscTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/FindMethodDuplicatesMiscTest.java @@ -61,4 +61,8 @@ public class FindMethodDuplicatesMiscTest extends FindMethodDuplicatesBaseTest { public void testSuperInTheSameContextQualified() throws Exception { doTest(); } + + public void testInsertSuperQualifierWhenNameConflicts() throws Exception { + doTest(); + } } \ No newline at end of file From 3f3d8329ed97b3a44d8844f1cc0f55308390bb37 Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 31 May 2010 18:40:02 +0400 Subject: [PATCH 039/212] replace method duplicates: qualified/unqualified static access ( IDEA-23412 ) --- .../util/duplicates/DuplicatesFinder.java | 14 ++++++++++++++ .../CandidateUnqualifiedStaticAccess.java | 17 +++++++++++++++++ .../CandidateUnqualifiedStaticAccess.java.after | 17 +++++++++++++++++ .../UnqualifiedStaticAccess.java | 17 +++++++++++++++++ .../UnqualifiedStaticAccess.java.after | 17 +++++++++++++++++ .../FindMethodDuplicatesMiscTest.java | 10 ++++++++++ 6 files changed, 92 insertions(+) create mode 100644 java/java-tests/testData/refactoring/methodDuplicatesMisc/CandidateUnqualifiedStaticAccess.java create mode 100644 java/java-tests/testData/refactoring/methodDuplicatesMisc/CandidateUnqualifiedStaticAccess.java.after create mode 100644 java/java-tests/testData/refactoring/methodDuplicatesMisc/UnqualifiedStaticAccess.java create mode 100644 java/java-tests/testData/refactoring/methodDuplicatesMisc/UnqualifiedStaticAccess.java.after diff --git a/java/java-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java b/java/java-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java index 798d8832701c..0f51665108ac 100644 --- a/java/java-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java +++ b/java/java-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java @@ -378,6 +378,12 @@ public class DuplicatesFinder { final PsiExpression candidateQualifier = candidateRefExpr.getQualifierExpression(); if (patternQualifier == null) { PsiClass contextClass = PsiTreeUtil.getParentOfType(pattern, PsiClass.class); + if (candidateQualifier instanceof PsiReferenceExpression) { + final PsiElement resolved = ((PsiReferenceExpression)candidateQualifier).resolve(); + if (resolved instanceof PsiClass && contextClass != null && contextClass.isInheritor((PsiClass)resolved, true)) { + return true; + } + } return contextClass != null && match.registerInstanceExpression(candidateQualifier, contextClass); } else { if (candidateQualifier == null) { @@ -405,6 +411,14 @@ public class DuplicatesFinder { contextClass = thisCandidate; } return contextClass != null && match.putParameter(parameter, RefactoringUtil.createThisExpression(patternQualifier.getManager(), contextClass)); + } else if (patternQualifier instanceof PsiReferenceExpression) { + final PsiElement resolved = ((PsiReferenceExpression)patternQualifier).resolve(); + if (resolved instanceof PsiClass) { + final PsiClass classContext = PsiTreeUtil.getParentOfType(candidate, PsiClass.class); + if (classContext != null && classContext.isInheritor((PsiClass)resolved, true)) { + return true; + } + } } return false; diff --git a/java/java-tests/testData/refactoring/methodDuplicatesMisc/CandidateUnqualifiedStaticAccess.java b/java/java-tests/testData/refactoring/methodDuplicatesMisc/CandidateUnqualifiedStaticAccess.java new file mode 100644 index 000000000000..b084a06ac3b6 --- /dev/null +++ b/java/java-tests/testData/refactoring/methodDuplicatesMisc/CandidateUnqualifiedStaticAccess.java @@ -0,0 +1,17 @@ +public class aa { + public static boolean isVisualUpdate(int update_type) { + return update_type <= Iaaa.FULL_QUOTE_VISUAL; + } +} + +interface Iaaa { + int FULL_QUOTE_VISUAL = 0; +} + +class a implements Iaaa { + int update_type = 8; + + public static boolean blabla(int update_type) { + return update_type <= FULL_QUOTE_VISUAL; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/methodDuplicatesMisc/CandidateUnqualifiedStaticAccess.java.after b/java/java-tests/testData/refactoring/methodDuplicatesMisc/CandidateUnqualifiedStaticAccess.java.after new file mode 100644 index 000000000000..ee79c5362672 --- /dev/null +++ b/java/java-tests/testData/refactoring/methodDuplicatesMisc/CandidateUnqualifiedStaticAccess.java.after @@ -0,0 +1,17 @@ +public class aa { + public static boolean isVisualUpdate(int update_type) { + return update_type <= Iaaa.FULL_QUOTE_VISUAL; + } +} + +interface Iaaa { + int FULL_QUOTE_VISUAL = 0; +} + +class a implements Iaaa { + int update_type = 8; + + public static boolean blabla(int update_type) { + return aa.isVisualUpdate(update_type); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/methodDuplicatesMisc/UnqualifiedStaticAccess.java b/java/java-tests/testData/refactoring/methodDuplicatesMisc/UnqualifiedStaticAccess.java new file mode 100644 index 000000000000..0fba02b9d4c0 --- /dev/null +++ b/java/java-tests/testData/refactoring/methodDuplicatesMisc/UnqualifiedStaticAccess.java @@ -0,0 +1,17 @@ +public class aa { + public static boolean isVisualUpdate(int update_type) { + return update_type <= Iaaa.FULL_QUOTE_VISUAL; + } +} + +interface Iaaa { + int FULL_QUOTE_VISUAL = 0; +} + +class a implements Iaaa { + int update_type = 8; + + public static boolean blabla(int update_type) { + return update_type <= FULL_QUOTE_VISUAL; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/methodDuplicatesMisc/UnqualifiedStaticAccess.java.after b/java/java-tests/testData/refactoring/methodDuplicatesMisc/UnqualifiedStaticAccess.java.after new file mode 100644 index 000000000000..440f2b07bfff --- /dev/null +++ b/java/java-tests/testData/refactoring/methodDuplicatesMisc/UnqualifiedStaticAccess.java.after @@ -0,0 +1,17 @@ +public class aa { + public static boolean isVisualUpdate(int update_type) { + return a.blabla(update_type); + } +} + +interface Iaaa { + int FULL_QUOTE_VISUAL = 0; +} + +class a implements Iaaa { + int update_type = 8; + + public static boolean blabla(int update_type) { + return update_type <= FULL_QUOTE_VISUAL; + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/refactoring/FindMethodDuplicatesMiscTest.java b/java/java-tests/testSrc/com/intellij/refactoring/FindMethodDuplicatesMiscTest.java index 4274ff719da1..50ad3f496723 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/FindMethodDuplicatesMiscTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/FindMethodDuplicatesMiscTest.java @@ -65,4 +65,14 @@ public class FindMethodDuplicatesMiscTest extends FindMethodDuplicatesBaseTest { public void testInsertSuperQualifierWhenNameConflicts() throws Exception { doTest(); } + + public void testUnqualifiedStaticAccess() throws Exception { + doTest(); + } + + public void testCandidateUnqualifiedStaticAccess() throws Exception { + doTest(); + } + + } \ No newline at end of file From dda3a867635375ccbc7cb61cb1bb6af872eb7598 Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 31 May 2010 20:21:45 +0400 Subject: [PATCH 040/212] testdatafixed --- .../methodDuplicatesMisc/CorrectThis.java | 15 --------------- .../RenameTypeParameterToExistingClassName.java | 15 --------------- 2 files changed, 30 deletions(-) diff --git a/java/java-tests/testData/refactoring/methodDuplicatesMisc/CorrectThis.java b/java/java-tests/testData/refactoring/methodDuplicatesMisc/CorrectThis.java index eccbde54a2ec..3b99a587f204 100644 --- a/java/java-tests/testData/refactoring/methodDuplicatesMisc/CorrectThis.java +++ b/java/java-tests/testData/refactoring/methodDuplicatesMisc/CorrectThis.java @@ -1,18 +1,3 @@ -/* - * Copyright 2000-2010 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ public class BaseClass extends JComponent { } diff --git a/java/java-tests/testData/refactoring/renameCollisions/RenameTypeParameterToExistingClassName.java b/java/java-tests/testData/refactoring/renameCollisions/RenameTypeParameterToExistingClassName.java index fe28257806d7..2bc8f20fc2b2 100644 --- a/java/java-tests/testData/refactoring/renameCollisions/RenameTypeParameterToExistingClassName.java +++ b/java/java-tests/testData/refactoring/renameCollisions/RenameTypeParameterToExistingClassName.java @@ -1,18 +1,3 @@ -/* - * Copyright 2000-2010 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ public class Test extends String> {} class P {} \ No newline at end of file From b67a47c7325dbfe12a1599740ada953409ac019d Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 31 May 2010 20:33:22 +0400 Subject: [PATCH 041/212] compilation fix --- plugins/hg4idea/src/org/zmlx/hg4idea/HgUtil.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgUtil.java index 4a8e593d66b4..994c8b2c9e1a 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgUtil.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgUtil.java @@ -59,13 +59,11 @@ public abstract class HgUtil { public static void markDirectoryDirty( final Project project, final FilePath file ) { Application application = ApplicationManager.getApplication(); application.runReadAction(new Runnable() { - @Override public void run() { VcsDirtyScopeManager.getInstance(project).dirDirtyRecursively(file); } } ); application.runWriteAction(new Runnable() { - @Override public void run() { VirtualFile virtualFile = VcsUtil.getVirtualFile(file.getPath()); if (virtualFile != null) { @@ -78,13 +76,11 @@ public abstract class HgUtil { public static void markDirectoryDirty( final Project project, final VirtualFile file ) { Application application = ApplicationManager.getApplication(); application.runReadAction(new Runnable() { - @Override public void run() { VcsDirtyScopeManager.getInstance(project).dirDirtyRecursively(file); } } ); application.runWriteAction(new Runnable() { - @Override public void run() { file.refresh(true, true); } @@ -94,13 +90,11 @@ public abstract class HgUtil { public static void markFileDirty( final Project project, final FilePath file ) { Application application = ApplicationManager.getApplication(); application.runReadAction(new Runnable() { - @Override public void run() { VcsDirtyScopeManager.getInstance(project).fileDirty(file); } } ); application.runWriteAction(new Runnable() { - @Override public void run() { VirtualFile virtualFile = VcsUtil.getVirtualFile(file.getPath()); if (virtualFile != null) { @@ -113,13 +107,11 @@ public abstract class HgUtil { public static void markFileDirty( final Project project, final VirtualFile file ) { Application application = ApplicationManager.getApplication(); application.runReadAction(new Runnable() { - @Override public void run() { VcsDirtyScopeManager.getInstance(project).fileDirty(file); } } ); application.runWriteAction(new Runnable() { - @Override public void run() { file.refresh(true, false); } @@ -143,7 +135,6 @@ public abstract class HgUtil { @Override public void run() { File[] files = file.getParentFile().listFiles(new FilenameFilter() { - @Override public boolean accept(File dir, String name) { return name.startsWith(fileName); } From feb2bb004db81c562ba3ecd43aadffb5213a213f Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Mon, 31 May 2010 20:51:06 +0400 Subject: [PATCH 042/212] start -> activate --- plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java index 9dd35609e90b..848cfef09c63 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java @@ -211,16 +211,6 @@ public class HgVcs extends AbstractVcs { return started; } - @Override - protected void start() throws VcsException { - if (ApplicationManager.getApplication().isUnitTestMode()) { - started = true; - } else { - HgExecutableValidator validator = new HgExecutableValidator(myProject); - started = validator.check(globalSettings); - } - } - @Override protected void shutdown() throws VcsException { started = false; @@ -228,6 +218,13 @@ public class HgVcs extends AbstractVcs { @Override public void activate() { + if (ApplicationManager.getApplication().isUnitTestMode()) { + started = true; + } else { + HgExecutableValidator validator = new HgExecutableValidator(myProject); + started = validator.check(globalSettings); + } + if (!started) { return; } From 5a887a844c8c48ba888c62248c438eecdf182373 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Mon, 31 May 2010 21:14:09 +0400 Subject: [PATCH 043/212] compilation fix again --- .../src/org/zmlx/hg4idea/provider/HgHistoryProvider.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgHistoryProvider.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgHistoryProvider.java index 29cfc283db40..8b8595eff3d7 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgHistoryProvider.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgHistoryProvider.java @@ -63,37 +63,30 @@ public class HgHistoryProvider implements VcsHistoryProvider { List revisions = getHistory(filePath, vcsRoot, project, DEFAULT_LIMIT); final List result = new LinkedList(revisions); return new VcsHistorySession() { - @Override public VcsRevisionNumber getCurrentRevisionNumber() { return new HgWorkingCopyRevisionsCommand(project).firstParent(vcsRoot); } - @Override public HistoryAsTreeProvider getHistoryAsTreeProvider() { return null; } - @Override public List getRevisionList() { return result; } - @Override public boolean isCurrentRevision(VcsRevisionNumber vcsRevisionNumber) { return vcsRevisionNumber.equals(getCurrentRevisionNumber()); } - @Override public boolean shouldBeRefreshed() { return false; } - @Override public boolean allowAsyncRefresh() { return false; } - @Override public boolean isContentAvailable(VcsFileRevision vcsFileRevision) { return false; } From 6a3d6bdf6adb574d56bcf440adf5332b2dfa9abe Mon Sep 17 00:00:00 2001 From: Constantine Plotnikov Date: Mon, 31 May 2010 18:06:54 +0400 Subject: [PATCH 044/212] git4idea: The command line size limit is lowered since cygwin git cannot handle big command lines for some reason. --- plugins/git4idea/src/git4idea/commands/GitFileUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/git4idea/src/git4idea/commands/GitFileUtils.java b/plugins/git4idea/src/git4idea/commands/GitFileUtils.java index f269d89b7fa0..f4756d7e39f2 100644 --- a/plugins/git4idea/src/git4idea/commands/GitFileUtils.java +++ b/plugins/git4idea/src/git4idea/commands/GitFileUtils.java @@ -34,7 +34,7 @@ public class GitFileUtils { * If multiple paths are specified on the command line, this limit is used to split paths into chunks. * The limit is less than OS limit to leave space to quoting, spaces, charset conversion, and commands arguments. */ - public static final int FILE_PATH_LIMIT = 10000; + public static final int FILE_PATH_LIMIT = 7600; /** * The private constructor for static utility class From 4b42272b40dcb6c6d02a979318379816fb7e8065 Mon Sep 17 00:00:00 2001 From: Constantine Plotnikov Date: Mon, 31 May 2010 21:03:20 +0400 Subject: [PATCH 045/212] git4idea: IDEA-52513: files under ignored directories are not shown in add dialog (for git 1.7.0 or higher) --- .../src/git4idea/i18n/GitBundle.properties | 13 ++-- .../src/git4idea/vfs/GitVFSListener.java | 65 +++++++++++++++++-- 2 files changed, 66 insertions(+), 12 deletions(-) diff --git a/plugins/git4idea/src/git4idea/i18n/GitBundle.properties b/plugins/git4idea/src/git4idea/i18n/GitBundle.properties index 9f5748198991..96a9bbff61dd 100644 --- a/plugins/git4idea/src/git4idea/i18n/GitBundle.properties +++ b/plugins/git4idea/src/git4idea/i18n/GitBundle.properties @@ -430,18 +430,18 @@ update.locally.modified.title=Locally modified files are detected update.options.display.name=Git Update Settings update.options.no.commit=No &Commit update.options.save.before.update=Clean working tree before update -update.options.save.keep=Do &Not Clean update.options.save.keep.tooltip=Leave changes on working tree -update.options.save.shelve=Using She&lve +update.options.save.keep=Do &Not Clean update.options.save.shelve.tooltip=Use IDEA Shelve (the files will be restored when update finishes) -update.options.save.stash=Using S&tash +update.options.save.shelve=Using She&lve update.options.save.stash.tooltip=Use 'git stash' to save changes (the files will be restored when update finishes) -update.options.type.default=Branch &Default +update.options.save.stash=Using S&tash update.options.type.default.tooltip=Use branch default update strategy for all updated git vcs roots -update.options.type.merge=&Merge +update.options.type.default=Branch &Default update.options.type.merge.tooltip=Use merge update strategy for all git vcs roots -update.options.type.rebase=&Rebase +update.options.type.merge=&Merge update.options.type.rebase.tooltip=Use rebase update strategy for all git vcs roots +update.options.type.rebase=&Rebase update.options.type=Update Type update.rebase.no.change.cancel=Cancel Update update.rebase.no.change.retry=Retry Continue @@ -466,6 +466,7 @@ vcs.unsupported.version=Unsupported version of git configured: {0}. The minimal vfs.listener.add.single.prompt=Do you want to add the following file to Git?\n{0}\n\nIf you say NO, you can still add it later manually. vfs.listener.add.single.title=Add file to Git vfs.listener.add.title=Add files to Git +vfs.listener.checking.ignored=Checking for ignored files vfs.listener.delete.single.prompt=Do you want to delete the following file from Git?\n{0}\n\nIf you say NO, you can still delete it later manually. vfs.listener.delete.single.title=Delete file from Git vfs.listener.delete.title=Delete files from Git diff --git a/plugins/git4idea/src/git4idea/vfs/GitVFSListener.java b/plugins/git4idea/src/git4idea/vfs/GitVFSListener.java index 5a3d743e5555..8379f8819505 100644 --- a/plugins/git4idea/src/git4idea/vfs/GitVFSListener.java +++ b/plugins/git4idea/src/git4idea/vfs/GitVFSListener.java @@ -16,6 +16,7 @@ package git4idea.vfs; import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; import com.intellij.openapi.vcs.FilePath; @@ -27,14 +28,14 @@ import com.intellij.util.ui.UIUtil; import com.intellij.vcsUtil.VcsUtil; import git4idea.GitUtil; import git4idea.GitVcs; +import git4idea.commands.GitCommand; import git4idea.commands.GitFileUtils; +import git4idea.commands.GitSimpleHandler; +import git4idea.commands.StringScanner; import git4idea.i18n.GitBundle; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.concurrent.atomic.AtomicInteger; /** @@ -100,6 +101,58 @@ public class GitVFSListener extends VcsVFSListener { return GitBundle.getString("vfs.listener.add.single.prompt"); } + /** + * {@inheritDoc} + */ + @Override + protected void executeAdd() { + // Filter added files before further processing + final Map> sortedFiles; + try { + sortedFiles = GitUtil.sortFilesByGitRoot(myAddedFiles, true); + } + catch (VcsException e) { + throw new RuntimeException("The exception is not expected here", e); + } + final HashSet retainedFiles = new HashSet(); + final ProgressManager progressManager = ProgressManager.getInstance(); + progressManager.runProcessWithProgressSynchronously(new Runnable() { + public void run() { + ProgressIndicator pi = progressManager.getProgressIndicator(); + for (Map.Entry> e : sortedFiles.entrySet()) { + VirtualFile root = e.getKey(); + pi.setText(root.getPresentableUrl()); + for (List paths : GitFileUtils.chunkFiles(root, e.getValue())) { + pi.setText2(paths.get(0) + "..."); + try { + GitSimpleHandler h = new GitSimpleHandler(myProject, root, GitCommand.LS_FILES); + h.setNoSSH(true); + h.addParameters("--exclude-standard", "--others"); + h.endOptions(); + h.addParameters(paths); + for (StringScanner s = new StringScanner(h.run()); s.hasMoreData();) { + String l = s.line(); + String p = GitUtil.unescapePath(l); + VirtualFile f = root.findFileByRelativePath(p); + assert f != null : "The virtual file must be available at this point: " + p + " (" + root.getPresentableUrl() + ")"; + retainedFiles.add(f); + } + } + catch (final VcsException ex) { + UIUtil.invokeLaterIfNeeded(new Runnable() { + public void run() { + gitVcs().showMessages(ex.getMessage()); + } + }); + } + } + } + } + }, GitBundle.getString("vfs.listener.checking.ignored"), false, myProject); + myAddedFiles.retainAll(retainedFiles); + super.executeAdd(); + } + /** * {@inheritDoc} */ @@ -212,7 +265,7 @@ public class GitVFSListener extends VcsVFSListener { return; } gitVcs().runInBackground(new Task.Backgroundable(myProject, GitBundle.getString("remove.removing")) { - + public void run(@NotNull ProgressIndicator indicator) { for (Map.Entry> e : sortedFiles.entrySet()) { try { @@ -263,4 +316,4 @@ public class GitVFSListener extends VcsVFSListener { // For git asking about vcs delete does not make much sense. The result is practically identical. return deletedFiles; } -} \ No newline at end of file +} From 4e3266927713d34037a3e371a9b03addc52288fe Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Mon, 31 May 2010 22:04:44 +0400 Subject: [PATCH 046/212] IDEA-25151: @Override annotation is not highlighted/processed in Groovy code --- .../overrideImplement/GroovyOverrideImplementUtil.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/overrideImplement/GroovyOverrideImplementUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/overrideImplement/GroovyOverrideImplementUtil.java index 57f65851f298..1bcfbca03ea5 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/overrideImplement/GroovyOverrideImplementUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/overrideImplement/GroovyOverrideImplementUtil.java @@ -59,11 +59,12 @@ import java.util.Properties; */ public class GroovyOverrideImplementUtil { private static final Logger LOG = Logger.getInstance("org.jetbrains.plugins.groovy.overrideImplement.GroovyOverrideImplementUtil"); + private static final String JAVA_LANG_OVERRIDE = "java.lang.Override"; private GroovyOverrideImplementUtil() { } - public static void invokeOverrideImplement(final Project project, final Editor editor, final PsiFile file, boolean isImplement) { + public static void invokeOverrideImplement(final Project project, final Editor editor, final PsiFile file, final boolean isImplement) { final int offset = editor.getCaretModel().getOffset(); PsiElement parent = file.findElementAt(offset); @@ -119,6 +120,9 @@ public class GroovyOverrideImplementUtil { modifierList.setModifierProperty(PsiModifier.NATIVE, false); setupOverridingMethodBody(project, method, result, template, substitutor); + if (!isImplement) { + result.getModifierList().addAnnotation(JAVA_LANG_OVERRIDE); + } final GrTypeDefinitionBody classBody = aClass.getBody(); final PsiMethod[] methods = aClass.getMethods(); From b8b3b86943405deecefab1503bac508e2129841e Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Mon, 31 May 2010 20:15:09 +0400 Subject: [PATCH 047/212] WI-1830 Make html code completion behave in php editor as it behaves in html editor --- .../completion/XmlAutoLookupHandler.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/xml/impl/src/com/intellij/codeInsight/completion/XmlAutoLookupHandler.java b/xml/impl/src/com/intellij/codeInsight/completion/XmlAutoLookupHandler.java index 8b4a7932f812..a883e074e21e 100644 --- a/xml/impl/src/com/intellij/codeInsight/completion/XmlAutoLookupHandler.java +++ b/xml/impl/src/com/intellij/codeInsight/completion/XmlAutoLookupHandler.java @@ -19,10 +19,12 @@ import com.intellij.lang.Language; import com.intellij.lang.xml.XMLLanguage; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.util.Ref; +import com.intellij.psi.FileViewProvider; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiWhiteSpace; import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; +import com.intellij.psi.templateLanguages.TemplateLanguageFileViewProvider; import com.intellij.xml.util.XmlUtil; /** @@ -53,6 +55,27 @@ public class XmlAutoLookupHandler extends CodeCompletionHandlerBase { PsiElement lastElement = InjectedLanguageUtil.findElementAtNoCommit(file, offset - 1); if (lastElement == null) return; + if(!doCompleteIfNeeded(offset1, offset2, context, dummyIdentifier, editor, invocationCount, file, lastElement)) { + // In template language based file we need to check element from template data language tree, not from base language + FileViewProvider fileViewProvider = file.getViewProvider(); + Language templateDataLanguage; + + if (fileViewProvider instanceof TemplateLanguageFileViewProvider && + (templateDataLanguage = ((TemplateLanguageFileViewProvider)fileViewProvider).getTemplateDataLanguage()) != lastElement.getParent().getLanguage() + ) { + lastElement = fileViewProvider.findElementAt(offset - 1, templateDataLanguage); + if (lastElement == null) return; + doCompleteIfNeeded(offset1, offset2, context, dummyIdentifier, editor, invocationCount, file, lastElement); + } + } + } + + private boolean doCompleteIfNeeded(int offset1, + int offset2, + CompletionContext context, + FileCopyPatcher dummyIdentifier, + Editor editor, + int invocationCount, PsiFile file, PsiElement lastElement) { final Ref isRelevantLanguage = new Ref(); final Ref isAnt = new Ref(); String text = lastElement.getText(); @@ -66,7 +89,10 @@ public class XmlAutoLookupHandler extends CodeCompletionHandlerBase { text.endsWith("@{") && isLanguageRelevant(lastElement, file, isRelevantLanguage, isAnt) && isAnt.get().booleanValue() || text.endsWith(" Date: Mon, 31 May 2010 21:25:54 +0400 Subject: [PATCH 048/212] WI-1748 URI is not registered when using quote escapes --- .../psi/impl/source/xml/XmlDoctypeImpl.java | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlDoctypeImpl.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlDoctypeImpl.java index 9e8512c7573b..e2ab4ecdd4e7 100644 --- a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlDoctypeImpl.java +++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlDoctypeImpl.java @@ -87,8 +87,34 @@ public class XmlDoctypeImpl extends XmlElementImpl implements XmlDoctype, XmlEle return extractValue(dtdUrlElement); } - private String extractValue(PsiElement element) { - return StringUtil.stripQuotesAroundValue(element.getText()); + private static String extractValue(PsiElement element) { + String text = element.getText(); + + if (!text.startsWith("\"") && !text.startsWith("\'")) { + if (hasInjectedEscapingQuotes(element, text)) return stripInjectedEscapingQuotes(text); + } + return StringUtil.stripQuotesAroundValue(text); + } + + // TODO: share common code + private static String stripInjectedEscapingQuotes(String text) { + return text.substring(2, text.length() - 2); + } + + private static boolean hasInjectedEscapingQuotes(PsiElement element, String text) { + if (text.startsWith("\\") && text.length() >= 4) { + char escapedChar = text.charAt(1); + PsiElement context = element.getContainingFile().getContext(); + + if (context != null && + context.textContains(escapedChar) && + context.getText().startsWith(String.valueOf(escapedChar)) && + text.endsWith("\\"+escapedChar) + ) { + return true; + } + } + return false; } @Nullable From 04f5ee4502026fed1ed007e7cc04d0845d5e4ba9 Mon Sep 17 00:00:00 2001 From: Gregory Shrago Date: Mon, 31 May 2010 22:18:27 +0400 Subject: [PATCH 049/212] scroll selection to visible fix --- platform/util/src/com/intellij/ui/TableUtil.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform/util/src/com/intellij/ui/TableUtil.java b/platform/util/src/com/intellij/ui/TableUtil.java index b9f625cc061d..76bbce078365 100644 --- a/platform/util/src/com/intellij/ui/TableUtil.java +++ b/platform/util/src/com/intellij/ui/TableUtil.java @@ -49,9 +49,9 @@ public class TableUtil { ListSelectionModel selectionModel = table.getSelectionModel(); int maxSelectionIndex = selectionModel.getMaxSelectionIndex(); int minSelectionIndex = selectionModel.getMinSelectionIndex(); - final int maxColumnSelectionIndex = table.getColumnModel().getSelectionModel().getMinSelectionIndex(); - final int minColumnSelectionIndex = table.getColumnModel().getSelectionModel().getMaxSelectionIndex(); - if(maxSelectionIndex == -1 || maxColumnSelectionIndex == -1){ + final int maxColumnSelectionIndex = Math.max(0, table.getColumnModel().getSelectionModel().getMinSelectionIndex()); + final int minColumnSelectionIndex = Math.max(0, table.getColumnModel().getSelectionModel().getMaxSelectionIndex()); + if(maxSelectionIndex == -1){ return; } Rectangle minCellRect = table.getCellRect(minSelectionIndex, minColumnSelectionIndex, false); From f367a866ec4c89d3617e9c787945c874e84999e5 Mon Sep 17 00:00:00 2001 From: peter Date: Sun, 30 May 2010 22:47:12 +0100 Subject: [PATCH 050/212] currentFileResolveContext -> ResolveState --- .../blocks/GrClosableBlockImpl.java | 47 +++---- .../imports/GrImportStatementImpl.java | 132 +++++++++--------- .../plugins/groovy/lang/psi/util/PsiUtil.java | 10 +- .../groovy/lang/resolve/ResolveUtil.java | 11 +- .../processors/MethodResolverProcessor.java | 9 +- .../resolve/processors/ResolverProcessor.java | 20 +-- 6 files changed, 104 insertions(+), 125 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrClosableBlockImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrClosableBlockImpl.java index 698bd06d082e..69fcf6f51c91 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrClosableBlockImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrClosableBlockImpl.java @@ -63,39 +63,34 @@ public class GrClosableBlockImpl extends GrBlockImpl implements GrClosableBlock } public boolean processDeclarations(@NotNull PsiScopeProcessor processor, - @NotNull ResolveState state, + @NotNull ResolveState _state, PsiElement lastParent, @NotNull PsiElement place) { if (lastParent == null) return true; - if (processor instanceof ResolverProcessor) ((ResolverProcessor)processor).setCurrentFileResolveContext(this); - try { - if (!super.processDeclarations(processor, state, lastParent, place)) return false; + ResolveState state = _state.put(ResolverProcessor.RESOLVE_CONTEXT, this); + if (!super.processDeclarations(processor, state, lastParent, place)) return false; - for (final PsiParameter parameter : getAllParameters()) { - if (!ResolveUtil.processElement(processor, parameter)) return false; - } - - if (processor instanceof PropertyResolverProcessor && OWNER_NAME.equals(((PropertyResolverProcessor)processor).getName())) { - processor.handleEvent(ResolveUtil.DECLARATION_SCOPE_PASSED, this); - } - - if (!ResolveUtil.processElement(processor, getOwner())) return false; - - final PsiClass closureClass = JavaPsiFacade.getInstance(getProject()).findClass(GROOVY_LANG_CLOSURE, getResolveScope()); - if (closureClass != null) { - if (!closureClass.processDeclarations(processor, state, lastParent, place)) return false; - - // Process non-code in closures - PsiType clType = JavaPsiFacade.getInstance(getProject()).getElementFactory().createType(closureClass, PsiSubstitutor.EMPTY); - if (!ResolveUtil.processNonCodeMethods(clType, processor, getProject(), place, true)) return false; - } - - return true; + for (final PsiParameter parameter : getAllParameters()) { + if (!ResolveUtil.processElement(processor, parameter)) return false; } - finally { - if (processor instanceof ResolverProcessor) ((ResolverProcessor)processor).setCurrentFileResolveContext(null); + + if (processor instanceof PropertyResolverProcessor && OWNER_NAME.equals(((PropertyResolverProcessor)processor).getName())) { + processor.handleEvent(ResolveUtil.DECLARATION_SCOPE_PASSED, this); } + + if (!ResolveUtil.processElement(processor, getOwner())) return false; + + final PsiClass closureClass = JavaPsiFacade.getInstance(getProject()).findClass(GROOVY_LANG_CLOSURE, getResolveScope()); + if (closureClass != null) { + if (!closureClass.processDeclarations(processor, state, lastParent, place)) return false; + + // Process non-code in closures + PsiType clType = JavaPsiFacade.getInstance(getProject()).getElementFactory().createType(closureClass, PsiSubstitutor.EMPTY); + if (!ResolveUtil.processNonCodeMethods(clType, processor, getProject(), place, true)) return false; + } + + return true; } public String toString() { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/toplevel/imports/GrImportStatementImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/toplevel/imports/GrImportStatementImpl.java index 825dcb5e2e53..39b9b21e3f77 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/toplevel/imports/GrImportStatementImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/toplevel/imports/GrImportStatementImpl.java @@ -53,85 +53,84 @@ public class GrImportStatementImpl extends GroovyPsiElementImpl implements GrImp } public boolean processDeclarations(@NotNull PsiScopeProcessor processor, - @NotNull ResolveState state, + @NotNull ResolveState _state, PsiElement lastParent, @NotNull PsiElement place) { if (PsiTreeUtil.isAncestor(this, place, false)) { return true; } - if (processor instanceof ResolverProcessor) ((ResolverProcessor)processor).setCurrentFileResolveContext(this); - try { - JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject()); - if (isOnDemand()) { - GrCodeReferenceElement ref = getImportReference(); - if (ref != null) { - if (isStatic()) { - final PsiElement resolved = ref.resolve(); - if (resolved instanceof PsiClass) { - final PsiClass clazz = (PsiClass)resolved; - if (clazz != null) { - if (!processAllMembers(processor, clazz)) return false; - } + + ResolveState state = _state.put(ResolverProcessor.RESOLVE_CONTEXT, this); + JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject()); + if (isOnDemand()) { + GrCodeReferenceElement ref = getImportReference(); + if (ref != null) { + if (isStatic()) { + final PsiElement resolved = ref.resolve(); + if (resolved instanceof PsiClass) { + final PsiClass clazz = (PsiClass)resolved; + if (clazz != null) { + if (!processAllMembers(processor, clazz)) return false; } } - else { - String qName = PsiUtil.getQualifiedReferenceText(ref); - if (qName != null) { - PsiPackage aPackage = facade.findPackage(qName); - if (aPackage != null) { - if (!aPackage.processDeclarations(processor, state, lastParent, place)) return false; - } + } + else { + String qName = PsiUtil.getQualifiedReferenceText(ref); + if (qName != null) { + PsiPackage aPackage = facade.findPackage(qName); + if (aPackage != null) { + if (!aPackage.processDeclarations(processor, state, lastParent, place)) return false; } } } } - else { - String name = getImportedName(); - if (name != null) { - NameHint nameHint = processor.getHint(NameHint.KEY); - //todo [DIANA] look more carefully + } + else { + String name = getImportedName(); + if (name != null) { + NameHint nameHint = processor.getHint(NameHint.KEY); + //todo [DIANA] look more carefully - GrCodeReferenceElement ref = getImportReference(); - if (ref != null) { - String qName = ref.getCanonicalText(); - if (qName != null && qName.indexOf('.') > 0) { - if (!isStatic()) { - if (nameHint == null || name.equals(nameHint.getName(state))) { - PsiClass clazz = facade.findClass(qName, getResolveScope()); - if (clazz != null && !processor.execute(clazz, state)) return false; - } + GrCodeReferenceElement ref = getImportReference(); + if (ref != null) { + String qName = ref.getCanonicalText(); + if (qName != null && qName.indexOf('.') > 0) { + if (!isStatic()) { + if (nameHint == null || name.equals(nameHint.getName(state))) { + PsiClass clazz = facade.findClass(qName, getResolveScope()); + if (clazz != null && !processor.execute(clazz, state)) return false; } - else { - final int i = qName.lastIndexOf('.'); - if (i > 0) { - final String classQName = qName.substring(0, i); - PsiClass clazz = facade.findClass(classQName, getResolveScope()); - if (clazz != null) { - final String refName = ref.getReferenceName(); - if (nameHint == null || name.equals(nameHint.getName(state))) { - final PsiField field = clazz.findFieldByName(refName, false); - if (field != null && field.hasModifierProperty(PsiModifier.STATIC) && !processor.execute(field, state)) { - return false; - } - - for (PsiMethod method : clazz.findMethodsByName(refName, false)) { - if (method.hasModifierProperty(PsiModifier.STATIC) && !processor.execute(method, state)) return false; - } + } + else { + final int i = qName.lastIndexOf('.'); + if (i > 0) { + final String classQName = qName.substring(0, i); + PsiClass clazz = facade.findClass(classQName, getResolveScope()); + if (clazz != null) { + final String refName = ref.getReferenceName(); + if (nameHint == null || name.equals(nameHint.getName(state))) { + final PsiField field = clazz.findFieldByName(refName, false); + if (field != null && field.hasModifierProperty(PsiModifier.STATIC) && !processor.execute(field, state)) { + return false; } - if (processor instanceof AccessorResolverProcessor) { - final PsiMethod getter = GroovyPropertyUtils.findPropertyGetter(clazz, refName, true, true); - if (getter != null && - (nameHint == null || - name.equals(GroovyPropertyUtils.getPropertyNameByGetterName(nameHint.getName(state), true)))) { - processor.execute(getter, state); - } + for (PsiMethod method : clazz.findMethodsByName(refName, false)) { + if (method.hasModifierProperty(PsiModifier.STATIC) && !processor.execute(method, state)) return false; + } + } - final PsiMethod setter = GroovyPropertyUtils.findPropertySetter(clazz, refName, true, true); - if (setter != null && - (nameHint == null || name.equals(GroovyPropertyUtils.getPropertyNameBySetterName(nameHint.getName(state))))) { - processor.execute(setter, state); - } + if (processor instanceof AccessorResolverProcessor) { + final PsiMethod getter = GroovyPropertyUtils.findPropertyGetter(clazz, refName, true, true); + if (getter != null && + (nameHint == null || + name.equals(GroovyPropertyUtils.getPropertyNameByGetterName(nameHint.getName(state), true)))) { + processor.execute(getter, state); + } + + final PsiMethod setter = GroovyPropertyUtils.findPropertySetter(clazz, refName, true, true); + if (setter != null && + (nameHint == null || name.equals(GroovyPropertyUtils.getPropertyNameBySetterName(nameHint.getName(state))))) { + processor.execute(setter, state); } } } @@ -140,12 +139,9 @@ public class GrImportStatementImpl extends GroovyPsiElementImpl implements GrImp } } } + } - return true; - } - finally { - if (processor instanceof ResolverProcessor) ((ResolverProcessor)processor).setCurrentFileResolveContext(null); - } + return true; } private static boolean processAllMembers(PsiScopeProcessor processor, PsiClass clazz) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java index 8092bb4a9323..9f5f06794654 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java @@ -72,6 +72,7 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil; import org.jetbrains.plugins.groovy.lang.resolve.NonCodeMembersProcessor; import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil; import org.jetbrains.plugins.groovy.lang.resolve.processors.MethodResolverProcessor; +import org.jetbrains.plugins.groovy.lang.resolve.processors.ResolverProcessor; import java.util.*; @@ -751,12 +752,11 @@ public class PsiUtil { PsiClass clazz = (PsiClass)element; String className = clazz.getName(); PsiType thisType = JavaPsiFacade.getInstance(place.getProject()).getElementFactory().createType(clazz, classResult.getSubstitutor()); - final MethodResolverProcessor processor = new MethodResolverProcessor(className, place, true, thisType, argTypes, PsiType.EMPTY_ARRAY) - ; - processor.setCurrentFileResolveContext(context); + final MethodResolverProcessor processor = new MethodResolverProcessor(className, place, true, thisType, argTypes, PsiType.EMPTY_ARRAY); PsiSubstitutor substitutor = classResult.getSubstitutor(); - final boolean toBreak = - element.processDeclarations(processor, ResolveState.initial().put(PsiSubstitutor.KEY, substitutor), null, place); + final ResolveState state = + ResolveState.initial().put(PsiSubstitutor.KEY, substitutor).put(ResolverProcessor.RESOLVE_CONTEXT, context); + final boolean toBreak = element.processDeclarations(processor, state, null, place); for (NonCodeMembersProcessor membersProcessor : NonCodeMembersProcessor.EP_NAME.getExtensions()) { if (!membersProcessor.processNonCodeMembers(thisType, processor, place, true)) break; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java index bfed58cec35e..ca426ca45c10 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java @@ -321,14 +321,9 @@ public class ResolveUtil { final GrExpression[] args = argList.getExpressionArguments(); if (args.length == 1 && args[0] instanceof GrReferenceExpression) { final PsiElement resolved = ((GrReferenceExpression)args[0]).resolve(); - if (resolved instanceof PsiClass) { - try { - processor.setCurrentFileResolveContext(call); - if (!resolved.processDeclarations(processor, ResolveState.initial(), null, place)) return false; - } - finally { - processor.setCurrentFileResolveContext(null); - } + if (resolved instanceof PsiClass && + !resolved.processDeclarations(processor, ResolveState.initial().put(ResolverProcessor.RESOLVE_CONTEXT, call), null, place)) { + return false; } } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/MethodResolverProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/MethodResolverProcessor.java index c7f2fa6df083..adb7b1f94211 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/MethodResolverProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/MethodResolverProcessor.java @@ -76,11 +76,12 @@ public class MethodResolverProcessor extends ResolverProcessor { if (substitutor == null) substitutor = PsiSubstitutor.EMPTY; substitutor = obtainSubstitutor(substitutor, method); boolean isAccessible = isAccessible(method); - boolean isStaticsOK = isStaticsOK(method); - if (PsiUtil.isApplicable(myArgumentTypes, method, substitutor, myCurrentFileResolveContext instanceof GrMethodCallExpression, (GroovyPsiElement)myPlace)) { - myCandidates.add(new GroovyResolveResultImpl(method, myCurrentFileResolveContext, substitutor, isAccessible, isStaticsOK)); + GroovyPsiElement fileResolveContext = state.get(RESOLVE_CONTEXT); + boolean isStaticsOK = isStaticsOK(method, fileResolveContext); + if (PsiUtil.isApplicable(myArgumentTypes, method, substitutor, fileResolveContext instanceof GrMethodCallExpression, (GroovyPsiElement)myPlace)) { + myCandidates.add(new GroovyResolveResultImpl(method, fileResolveContext, substitutor, isAccessible, isStaticsOK)); } else { - myInapplicableCandidates.add(new GroovyResolveResultImpl(method, myCurrentFileResolveContext, substitutor, isAccessible, isStaticsOK)); + myInapplicableCandidates.add(new GroovyResolveResultImpl(method, fileResolveContext, substitutor, isAccessible, isStaticsOK)); } return true; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/ResolverProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/ResolverProcessor.java index 426b710047bc..4f4f05186e6b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/ResolverProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/ResolverProcessor.java @@ -40,6 +40,7 @@ import static org.jetbrains.plugins.groovy.lang.resolve.processors.ClassHint.Res * @author ven */ public class ResolverProcessor implements PsiScopeProcessor, NameHint, ClassHint, ElementClassHint { + public static final Key RESOLVE_CONTEXT = Key.create("RESOLVE_CONTEXT"); protected String myName; private final EnumSet myResolveTargetKinds; private final Set myProcessedClasses = new HashSet(); @@ -49,16 +50,6 @@ public class ResolverProcessor implements PsiScopeProcessor, NameHint, ClassHint protected Set myCandidates = new LinkedHashSet(); - public GroovyPsiElement getCurrentFileResolveContext() { - return myCurrentFileResolveContext; - } - - public void setCurrentFileResolveContext(GroovyPsiElement currentFileResolveContext) { - myCurrentFileResolveContext = currentFileResolveContext; - } - - protected GroovyPsiElement myCurrentFileResolveContext; - protected ResolverProcessor(String name, EnumSet resolveTargets, PsiElement place, @NotNull PsiType[] typeArguments) { @@ -89,8 +80,9 @@ public class ResolverProcessor implements PsiScopeProcessor, NameHint, ClassHint } boolean isAccessible = isAccessible(namedElement); - boolean isStaticsOK = isStaticsOK(namedElement); - myCandidates.add(new GroovyResolveResultImpl(namedElement, myCurrentFileResolveContext, substitutor, isAccessible, isStaticsOK)); + final GroovyPsiElement resolveContext = state.get(RESOLVE_CONTEXT); + boolean isStaticsOK = isStaticsOK(namedElement, resolveContext); + myCandidates.add(new GroovyResolveResultImpl(namedElement, resolveContext, substitutor, isAccessible, isStaticsOK)); return !isAccessible; } @@ -102,8 +94,8 @@ public class ResolverProcessor implements PsiScopeProcessor, NameHint, ClassHint PsiUtil.isAccessible(myPlace, ((PsiMember) namedElement)); } - protected boolean isStaticsOK(PsiNamedElement element) { - if (myCurrentFileResolveContext instanceof GrImportStatement) return true; + protected boolean isStaticsOK(PsiNamedElement element, GroovyPsiElement resolveContext) { + if (resolveContext instanceof GrImportStatement) return true; if (element instanceof PsiModifierListOwner) { return PsiUtil.isStaticsOK((PsiModifierListOwner) element, myPlace); From b6fd1f92227f32581ba5a816aa37225218283869 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 31 May 2010 14:41:47 +0100 Subject: [PATCH 051/212] speedup groovy implicit import resolve --- .../groovy/lang/psi/impl/GroovyFileImpl.java | 140 ++++++------------ .../groovy/compiler/GroovyCompilerTest.groovy | 2 +- 2 files changed, 46 insertions(+), 96 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileImpl.java index 9e852fecdd33..3a191bd9b0c3 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileImpl.java @@ -38,7 +38,7 @@ import com.intellij.psi.util.CachedValue; import com.intellij.psi.util.CachedValueProvider; import com.intellij.psi.util.CachedValuesManager; import com.intellij.util.IncorrectOperationException; -import gnu.trove.THashSet; +import com.intellij.util.containers.FactoryMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.GroovyFileType; @@ -63,7 +63,6 @@ import javax.swing.*; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.Set; /** * Implements all abstractions related to Groovy file @@ -71,6 +70,7 @@ import java.util.Set; * @author ilyas */ public class GroovyFileImpl extends GroovyFileBaseImpl implements GroovyFile { + private static final Key>> IMPLICITLY_IMPORTABLE_CLASSES = Key.create("IMplicitlyImportable"); private static final Logger LOG = Logger.getInstance("org.jetbrains.plugins.groovy.lang.psi.impl.GroovyFileImpl"); private static final Object lock = new Object(); @@ -136,41 +136,37 @@ public class GroovyFileImpl extends GroovyFileBaseImpl implements GroovyFile { if (!processChildrenScopes(this, processor, state, lastParent, place)) return false; - JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject()); + final ClassHint classHint = processor.getHint(ClassHint.KEY); + final boolean processClasses = classHint == null || classHint.shouldProcess(ClassHint.ResolveKind.CLASS); - final GrImportStatement[] imports = getImportStatements(); + final NameHint nameHint = processor.getHint(NameHint.KEY); + final String expectedName = nameHint == null ? null : nameHint.getName(state); - for (GrImportStatement importStatement : imports) { - if (importStatement.isAliasedImport() && !importStatement.processDeclarations(processor, state, lastParent, place)) { + PsiScopeProcessor importProcessor = !processClasses || expectedName == null ? processor : new BaseScopeProcessor() { + public boolean execute(PsiElement element, ResolveState state) { + return isImplicitlyImported(element, expectedName) || processor.execute(element, state); + } + + @Override + public T getHint(Key hintKey) { + return processor.getHint(hintKey); + } + }; + for (GrImportStatement importStatement : getImportStatements()) { + if (!importStatement.processDeclarations(importProcessor, state, lastParent, place)) { return false; } } - final String className = getWantedClassName(processor, state); - if (className != null) { - final Set maybeImplicit = getImplicitlyImportableClasses(facade, className); - if (!maybeImplicit.isEmpty()) { - if (isResolvableViaImplictImports(processor, state, lastParent, place, className, maybeImplicit, imports)) { - if (!processImplicitImports(processor, state, lastParent, place, facade)) { - return false; - } - } - } + if (processClasses && !processImplicitImports(processor, state, lastParent, place)) { + return false; } - for (GrImportStatement importStatement : imports) { - if (!importStatement.isAliasedImport() && !importStatement.processDeclarations(processor, state, lastParent, place)) { - return false; - } - } - - if (!processImplicitImports(processor, state, lastParent, place, facade)) return false; - - if (StringUtil.isNotEmpty(getPackageName())) { //otherwise already processed default package - PsiPackage defaultPackage = facade.findPackage(""); + if (classHint == null || classHint.shouldProcess(ClassHint.ResolveKind.PACKAGE)) { + PsiPackage defaultPackage = JavaPsiFacade.getInstance(getProject()).findPackage(""); if (defaultPackage != null) { - for (PsiPackage subpackage : defaultPackage.getSubPackages(getResolveScope())) { - if (!ResolveUtil.processElement(processor, subpackage)) return false; + for (PsiPackage subPackage : defaultPackage.getSubPackages(getResolveScope())) { + if (!ResolveUtil.processElement(processor, subPackage)) return false; } } } @@ -178,64 +174,33 @@ public class GroovyFileImpl extends GroovyFileBaseImpl implements GroovyFile { return true; } + private boolean isImplicitlyImported(PsiElement element, String expectedName) { + if (!(element instanceof PsiClass)) return false; - private static boolean isResolvableViaImplictImports(final PsiScopeProcessor processor, ResolveState state, PsiElement lastParent, - PsiElement place, - @NotNull final String className, - final Set maybeImplicit, GrImportStatement[] imports) { - boolean isImplicitlyImported = true; - for (GrImportStatement importStatement : imports) { - if (!importStatement.processDeclarations(new BaseScopeProcessor() { - public boolean execute(PsiElement element, ResolveState state) { - if (element instanceof PsiClass) { - final PsiClass psiClass = (PsiClass)element; - final String qname = psiClass.getQualifiedName(); - if (qname != null && className.equals(psiClass.getName()) && !maybeImplicit.contains(qname)) { - return false; - } - } - return true; - } + final PsiClass psiClass = (PsiClass)element; + if (!expectedName.equals(psiClass.getName())) return false; - @Override - public T getHint(Key hintKey) { - return processor.getHint(hintKey); - } - }, state, lastParent, place)) { - isImplicitlyImported = false; - break; + final String qname = psiClass.getQualifiedName(); + if (qname == null) return false; + + for (String importedClass : IMPLICITLY_IMPORTED_CLASSES) { + if (qname.equals(importedClass)) { + return true; } } - return isImplicitlyImported; + for (String pkg : getImplicitlyImportedPackages()) { + if (qname.equals(pkg + "." + expectedName)) { + return true; + } + } + return false; } - private Set getImplicitlyImportableClasses(JavaPsiFacade facade, @NotNull String className) { - final Set maybeImplicit = new THashSet(); - final String suffix = "." + className; - for (String implicitlyImportedClass : IMPLICITLY_IMPORTED_CLASSES) { - if (implicitlyImportedClass.endsWith(suffix)) { - maybeImplicit.add(implicitlyImportedClass); - } - } - - for (final String implicitlyImported : getImplicitlyImportedPackages()) { - final String candidate = implicitlyImported + suffix; - if (facade.findClass(candidate, getResolveScope()) != null) { - maybeImplicit.add(candidate); - } - } - - final String pkg = getPackageName(); - final String candidate = StringUtil.isEmpty(pkg) ? className : pkg + suffix; - if (facade.findClass(candidate, getResolveScope()) != null) { - maybeImplicit.add(candidate); - } - - return maybeImplicit; - } private List getImplicitlyImportedPackages() { - final ArrayList result = new ArrayList(Arrays.asList(IMPLICITLY_IMPORTED_PACKAGES)); + final ArrayList result = new ArrayList(); + result.add(getPackageName()); + result.addAll(Arrays.asList(IMPLICITLY_IMPORTED_PACKAGES)); if (isScript()) { result.addAll(GroovyScriptType.getScriptType(this).appendImplicitImports(this)); } @@ -243,13 +208,8 @@ public class GroovyFileImpl extends GroovyFileBaseImpl implements GroovyFile { } private boolean processImplicitImports(PsiScopeProcessor processor, ResolveState state, PsiElement lastParent, - PsiElement place, - JavaPsiFacade facade) { - String currentPackageName = getPackageName(); - PsiPackage currentPackage = facade.findPackage(currentPackageName); - - if (currentPackage != null && !currentPackage.processDeclarations(processor, state, lastParent, place)) return false; - + PsiElement place) { + JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject()); for (final String implicitlyImported : getImplicitlyImportedPackages()) { PsiPackage aPackage = facade.findPackage(implicitlyImported); if (aPackage != null && !aPackage.processDeclarations(processor, state, lastParent, place)) return false; @@ -262,16 +222,6 @@ public class GroovyFileImpl extends GroovyFileBaseImpl implements GroovyFile { return true; } - @Nullable - private static String getWantedClassName(PsiScopeProcessor processor, ResolveState state) { - final ClassHint hint = processor.getHint(ClassHint.KEY); - final NameHint nameHint = processor.getHint(NameHint.KEY); - if (hint != null && hint.shouldProcess(ClassHint.ResolveKind.CLASS) && nameHint != null) { - return nameHint.getName(state); - } - return null; - } - private static boolean processChildrenScopes(PsiElement element, PsiScopeProcessor processor, diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy index a02797bbe10f..d88634a6f577 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy @@ -318,7 +318,7 @@ class Bar {} package pack class Foo extends Goo { }""" - def goo = myFixture.addFileToProject("Goo.groovy", """ + def goo = myFixture.addFileToProject("pack/Goo.groovy", """ package pack class Goo {}""") From b89d44f2e2ed04a05ba312dc2e9b18c9e53849ba Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 31 May 2010 16:44:03 +0100 Subject: [PATCH 052/212] cache groovy implicitly importable class names --- .../groovy/lang/psi/impl/GroovyFileImpl.java | 54 ++++++++++++++++--- 1 file changed, 47 insertions(+), 7 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileImpl.java index 3a191bd9b0c3..bbdfcbb18620 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileImpl.java @@ -18,11 +18,14 @@ package org.jetbrains.plugins.groovy.lang.psi.impl; import com.intellij.lang.ASTNode; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.UserDataCache; +import com.intellij.openapi.util.UserDataHolder; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; @@ -37,7 +40,10 @@ import com.intellij.psi.stubs.StubElement; import com.intellij.psi.util.CachedValue; import com.intellij.psi.util.CachedValueProvider; import com.intellij.psi.util.CachedValuesManager; +import com.intellij.psi.util.PsiModificationTracker; import com.intellij.util.IncorrectOperationException; +import com.intellij.util.containers.ConcurrentFactoryMap; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.FactoryMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -60,9 +66,7 @@ import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil; import org.jetbrains.plugins.groovy.lang.resolve.processors.ClassHint; import javax.swing.*; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; +import java.util.*; /** * Implements all abstractions related to Groovy file @@ -70,7 +74,7 @@ import java.util.List; * @author ilyas */ public class GroovyFileImpl extends GroovyFileBaseImpl implements GroovyFile { - private static final Key>> IMPLICITLY_IMPORTABLE_CLASSES = Key.create("IMplicitlyImportable"); + private static final Key>>> IMPLICITLY_IMPORTABLE_CLASSES = Key.create("IMplicitlyImportable"); private static final Logger LOG = Logger.getInstance("org.jetbrains.plugins.groovy.lang.psi.impl.GroovyFileImpl"); private static final Object lock = new Object(); @@ -158,7 +162,7 @@ public class GroovyFileImpl extends GroovyFileBaseImpl implements GroovyFile { } } - if (processClasses && !processImplicitImports(processor, state, lastParent, place)) { + if (processClasses && !processImplicitImports(processor, state, lastParent, place, expectedName)) { return false; } @@ -189,7 +193,7 @@ public class GroovyFileImpl extends GroovyFileBaseImpl implements GroovyFile { } } for (String pkg : getImplicitlyImportedPackages()) { - if (qname.equals(pkg + "." + expectedName)) { + if (qname.equals(pkg + "." + expectedName) || pkg.length() == 0 && qname.equals(expectedName)) { return true; } } @@ -208,9 +212,16 @@ public class GroovyFileImpl extends GroovyFileBaseImpl implements GroovyFile { } private boolean processImplicitImports(PsiScopeProcessor processor, ResolveState state, PsiElement lastParent, - PsiElement place) { + PsiElement place, @Nullable String className) { JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject()); + + final FactoryMap> cache = getImplicitlyImportableClassNames(); + for (final String implicitlyImported : getImplicitlyImportedPackages()) { + if (className != null && !cache.get(implicitlyImported).contains(className)) { + continue; + } + PsiPackage aPackage = facade.findPackage(implicitlyImported); if (aPackage != null && !aPackage.processDeclarations(processor, state, lastParent, place)) return false; } @@ -222,6 +233,35 @@ public class GroovyFileImpl extends GroovyFileBaseImpl implements GroovyFile { return true; } + @NotNull + private FactoryMap> getImplicitlyImportableClassNames() { + final Module module = ModuleUtil.findModuleForPsiElement(this); + UserDataHolder holder = module != null ? module : this; + + return CachedValuesManager.getManager(getProject()).getCachedValue(holder, IMPLICITLY_IMPORTABLE_CLASSES, new CachedValueProvider>>() { + public Result>> compute() { + final JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject()); + + final FactoryMap> result = new ConcurrentFactoryMap>() { + @Override + protected Set create(String pkgName) { + final HashSet shortNames = new HashSet(); + PsiPackage aPackage = facade.findPackage(pkgName); + if (aPackage != null) { + for (PsiClass aClass : aPackage.getClasses()) { + ContainerUtil.addIfNotNull(aClass.getName(), shortNames); + } + } + return shortNames; + } + }; + + return Result.create(result, ProjectRootManager.getInstance(getProject()), PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT); + } + }, false); + } + + private static boolean processChildrenScopes(PsiElement element, PsiScopeProcessor processor, From d2650031a87caae6084464b729de90a9d58a9f1a Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 31 May 2010 17:20:35 +0100 Subject: [PATCH 053/212] cleanup --- .../MethodLateBoundReferencesSearcher.java | 74 +++++++++---------- 1 file changed, 34 insertions(+), 40 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/MethodLateBoundReferencesSearcher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/MethodLateBoundReferencesSearcher.java index 498bc9fcc3b0..12707c5f340b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/MethodLateBoundReferencesSearcher.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/MethodLateBoundReferencesSearcher.java @@ -31,7 +31,6 @@ import com.intellij.psi.util.PropertyUtil; import com.intellij.util.Processor; import com.intellij.util.QueryExecutor; import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; import org.jetbrains.plugins.groovy.lang.psi.impl.search.GrSourceFilterScope; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; @@ -41,43 +40,36 @@ import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; */ public class MethodLateBoundReferencesSearcher implements QueryExecutor { public boolean execute(final MethodReferencesSearch.SearchParameters params, final Processor consumer) { - final PsiElement element = params.getMethod(); - if (element instanceof PsiMethod) { - final PsiMethod method = (PsiMethod) element; - SearchScope searchScope = PsiUtil.restrictScopeToGroovyFiles(new Computable() { - public SearchScope compute() { - return params.getScope().intersectWith(getUseScopeInReadAction(method)); - } - }); - - final String name = method.getName(); - - final Project project = element.getProject(); - if (!processTextOccurrences(searchScope, name, consumer, project)) return false; - - final String propName = getPropertyName(method); - if (propName != null) { - if (!processTextOccurrences(searchScope, propName, consumer, project)) return false; + final PsiMethod method = params.getMethod(); + SearchScope searchScope = PsiUtil.restrictScopeToGroovyFiles(new Computable() { + public SearchScope compute() { + return params.getScope().intersectWith(getUseScope(method)); } + }); + + final String name = method.getName(); + + final Project project = method.getProject(); + if (!processTextOccurrences(searchScope, name, consumer, project)) return false; + + final String propName = getPropertyName(method); + if (propName != null) { + if (!processTextOccurrences(searchScope, propName, consumer, project)) return false; } return true; } - private static SearchScope getUseScopeInReadAction(final PsiMethod method) { - return ApplicationManager.getApplication().runReadAction(new Computable() { - public SearchScope compute() { - final SearchScope scope = method.getUseScope(); - final PsiFile file = method.getContainingFile(); - if (file != null && scope instanceof GlobalSearchScope) { - final VirtualFile vfile = file.getOriginalFile().getVirtualFile(); - final Project project = method.getProject(); - if (vfile != null && ProjectRootManager.getInstance(project).getFileIndex().isInSource(vfile)) { - return new GrSourceFilterScope((GlobalSearchScope)scope, project); - } - } - return scope; + private static SearchScope getUseScope(final PsiMethod method) { + final SearchScope scope = method.getUseScope(); + final PsiFile file = method.getContainingFile(); + if (file != null && scope instanceof GlobalSearchScope) { + final VirtualFile vfile = file.getOriginalFile().getVirtualFile(); + final Project project = method.getProject(); + if (vfile != null && ProjectRootManager.getInstance(project).getFileIndex().isInSource(vfile)) { + return new GrSourceFilterScope((GlobalSearchScope)scope, project); } - }); + } + return scope; } private static String getPropertyName(final PsiMethod method) { @@ -92,19 +84,21 @@ public class MethodLateBoundReferencesSearcher implements QueryExecutor consumer, Project project) { final TextOccurenceProcessor processor = new TextOccurenceProcessor() { public boolean execute(PsiElement element, int offsetInElement) { - PsiReference ref = element.getReference(); - if (element instanceof GrReferenceExpression && - name.equals(((GrReferenceExpression) element).getReferenceName()) && - ref != null && ref.resolve() == null && - !PsiUtil.isLValue((GroovyPsiElement) element)) { - if (!consumer.process((PsiReference) element)) return false; + if (!(element instanceof GrReferenceExpression)) { + return true; } - return true; + + final GrReferenceExpression ref = (GrReferenceExpression)element; + if (!name.equals(ref.getReferenceName()) || PsiUtil.isLValue(ref) || ref.resolve() != null) { + return true; + } + + return consumer.process((PsiReference)element); } }; return PsiManager.getInstance(project).getSearchHelper().processElementsWithWord(processor, - searchScope, name, UsageSearchContext.IN_CODE, true); + searchScope, name, UsageSearchContext.IN_CODE, true); } } \ No newline at end of file From fa06ce1faa54f1f532b931dc156c6b0d33cbe9f5 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 31 May 2010 17:46:33 +0100 Subject: [PATCH 054/212] cache package's classes in package itself. remove similar cache from groovy --- .../psi/impl/file/PsiPackageImpl.java | 3 +- .../groovy/lang/psi/impl/GroovyFileImpl.java | 54 ++----------------- 2 files changed, 7 insertions(+), 50 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java b/java/java-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java index 30b807bf0d47..bd7885956600 100644 --- a/java/java-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java @@ -496,7 +496,8 @@ public class PsiPackageImpl extends PsiElementBase implements PsiPackage, Querya if (classHint == null || classHint.shouldProcess(ElementClassHint.DeclaractionKind.CLASS)) { NameHint nameHint = processor.getHint(NameHint.KEY); if (nameHint != null) { - if (processClassesByName(processor, state, place, scope, nameHint.getName(state))) return false; + final String shortName = nameHint.getName(state); + if (containsClassNamed(shortName) && processClassesByName(processor, state, place, scope, shortName)) return false; } else if (prefixMatcher != null && migration == null) { for (String className : getClassNamesCache()) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileImpl.java index bbdfcbb18620..c414d89f5738 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileImpl.java @@ -18,14 +18,11 @@ package org.jetbrains.plugins.groovy.lang.psi.impl; import com.intellij.lang.ASTNode; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.UserDataCache; -import com.intellij.openapi.util.UserDataHolder; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; @@ -40,11 +37,7 @@ import com.intellij.psi.stubs.StubElement; import com.intellij.psi.util.CachedValue; import com.intellij.psi.util.CachedValueProvider; import com.intellij.psi.util.CachedValuesManager; -import com.intellij.psi.util.PsiModificationTracker; import com.intellij.util.IncorrectOperationException; -import com.intellij.util.containers.ConcurrentFactoryMap; -import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.containers.FactoryMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.GroovyFileType; @@ -66,7 +59,9 @@ import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil; import org.jetbrains.plugins.groovy.lang.resolve.processors.ClassHint; import javax.swing.*; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; /** * Implements all abstractions related to Groovy file @@ -74,7 +69,6 @@ import java.util.*; * @author ilyas */ public class GroovyFileImpl extends GroovyFileBaseImpl implements GroovyFile { - private static final Key>>> IMPLICITLY_IMPORTABLE_CLASSES = Key.create("IMplicitlyImportable"); private static final Logger LOG = Logger.getInstance("org.jetbrains.plugins.groovy.lang.psi.impl.GroovyFileImpl"); private static final Object lock = new Object(); @@ -82,8 +76,6 @@ public class GroovyFileImpl extends GroovyFileBaseImpl implements GroovyFile { private GroovyScriptClass myScriptClass; private static final String SYNTHETIC_PARAMETER_NAME = "args"; private GrParameter mySyntheticArgsParameter = null; - - private PsiElement myContext; public GroovyFileImpl(FileViewProvider viewProvider) { @@ -162,7 +154,7 @@ public class GroovyFileImpl extends GroovyFileBaseImpl implements GroovyFile { } } - if (processClasses && !processImplicitImports(processor, state, lastParent, place, expectedName)) { + if (processClasses && !processImplicitImports(processor, state, lastParent, place)) { return false; } @@ -212,16 +204,10 @@ public class GroovyFileImpl extends GroovyFileBaseImpl implements GroovyFile { } private boolean processImplicitImports(PsiScopeProcessor processor, ResolveState state, PsiElement lastParent, - PsiElement place, @Nullable String className) { + PsiElement place) { JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject()); - final FactoryMap> cache = getImplicitlyImportableClassNames(); - for (final String implicitlyImported : getImplicitlyImportedPackages()) { - if (className != null && !cache.get(implicitlyImported).contains(className)) { - continue; - } - PsiPackage aPackage = facade.findPackage(implicitlyImported); if (aPackage != null && !aPackage.processDeclarations(processor, state, lastParent, place)) return false; } @@ -233,36 +219,6 @@ public class GroovyFileImpl extends GroovyFileBaseImpl implements GroovyFile { return true; } - @NotNull - private FactoryMap> getImplicitlyImportableClassNames() { - final Module module = ModuleUtil.findModuleForPsiElement(this); - UserDataHolder holder = module != null ? module : this; - - return CachedValuesManager.getManager(getProject()).getCachedValue(holder, IMPLICITLY_IMPORTABLE_CLASSES, new CachedValueProvider>>() { - public Result>> compute() { - final JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject()); - - final FactoryMap> result = new ConcurrentFactoryMap>() { - @Override - protected Set create(String pkgName) { - final HashSet shortNames = new HashSet(); - PsiPackage aPackage = facade.findPackage(pkgName); - if (aPackage != null) { - for (PsiClass aClass : aPackage.getClasses()) { - ContainerUtil.addIfNotNull(aClass.getName(), shortNames); - } - } - return shortNames; - } - }; - - return Result.create(result, ProjectRootManager.getInstance(getProject()), PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT); - } - }, false); - } - - - private static boolean processChildrenScopes(PsiElement element, PsiScopeProcessor processor, ResolveState state, From 46bd89c489a2e1b5a95590dabe8a5365fe6f959f Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 31 May 2010 18:15:55 +0100 Subject: [PATCH 055/212] stateless DefaultInsertHandler --- .../completion/DefaultInsertHandler.java | 209 +++++++++--------- 1 file changed, 103 insertions(+), 106 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/DefaultInsertHandler.java b/java/java-impl/src/com/intellij/codeInsight/completion/DefaultInsertHandler.java index a699861def3e..0b4ddd7f2a0b 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/DefaultInsertHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/DefaultInsertHandler.java @@ -37,21 +37,14 @@ import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public class DefaultInsertHandler extends TemplateInsertHandler implements Cloneable { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.completion.DefaultInsertHandler"); - protected InsertionContext myContext; - private LookupItem myLookupItem; - - private Project myProject; - private PsiFile myFile; - private Editor myEditor; - protected Document myDocument; - private InsertHandlerState myState; public static final DefaultInsertHandler NO_TAIL_HANDLER = new DefaultInsertHandler(){ @Override - protected TailType getTailType(char completionChar) { + protected TailType getTailType(char completionChar, LookupItem item) { return TailType.NONE; } }; @@ -64,107 +57,105 @@ public class DefaultInsertHandler extends TemplateInsertHandler implements Clone private void handleInsertInner(InsertionContext context, LookupItem item, final char completionChar) { LOG.assertTrue(CommandProcessor.getInstance().getCurrentCommand() != null); - PsiDocumentManager.getInstance(context.getProject()).commitDocument(context.getEditor().getDocument()); - myContext = context; - myLookupItem = item; + final Project project = context.getProject(); + final Editor editor = context.getEditor(); + final Document document = editor.getDocument(); + PsiDocumentManager.getInstance(project).commitDocument(document); - myProject = myContext.getProject(); - myFile = myContext.getFile(); - myEditor = myContext.getEditor(); - myDocument = myEditor.getDocument(); + final PsiFile file = context.getFile(); - TailType tailType = getTailType(completionChar); + TailType tailType = getTailType(completionChar, item); - myState = new InsertHandlerState(myContext.getSelectionEndOffset(), myContext.getSelectionEndOffset()); + InsertHandlerState state = new InsertHandlerState(context.getSelectionEndOffset(), context.getSelectionEndOffset()); - final boolean needLeftParenth = isToInsertParenth(); - final boolean hasParams = needLeftParenth && hasParams(); + final boolean needLeftParenth = isToInsertParenth(context, item); + final boolean hasParams = needLeftParenth && hasParams(context, item); if (CompletionUtil.isOverwrite(item, completionChar)) { - removeEndOfIdentifier(needLeftParenth && hasParams); + removeEndOfIdentifier(needLeftParenth && hasParams, context); } - else if(myContext.getOffsetMap().getOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET) != myContext.getSelectionEndOffset()) { + else if(context.getOffsetMap().getOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET) != context.getSelectionEndOffset()) { JavaCompletionUtil.resetParensInfo(context.getOffsetMap()); } - handleParenses(hasParams, needLeftParenth, tailType); - handleBrackets(); + handleParentheses(hasParams, needLeftParenth, tailType, context, state); + handleBrackets(item, document, state); - if (myLookupItem.getObject() instanceof PsiVariable) { - if (completionChar == '!' && PsiType.BOOLEAN.isAssignableFrom(((PsiVariable) myLookupItem.getObject()).getType())) { - PsiDocumentManager.getInstance(myProject).commitDocument(myDocument); + if (item.getObject() instanceof PsiVariable) { + if (completionChar == '!' && PsiType.BOOLEAN.isAssignableFrom(((PsiVariable) item.getObject()).getType())) { + PsiDocumentManager.getInstance(project).commitDocument(document); final PsiReferenceExpression ref = - PsiTreeUtil.findElementOfClassAtOffset(myFile, myState.tailOffset - 1, PsiReferenceExpression.class, false); + PsiTreeUtil.findElementOfClassAtOffset(file, state.tailOffset - 1, PsiReferenceExpression.class, false); if (ref != null) { FeatureUsageTracker.getInstance().triggerFeatureUsed(CodeCompletionFeatures.EXCLAMATION_FINISH); - myDocument.insertString(ref.getTextRange().getStartOffset(), "!"); - myState.caretOffset++; - myState.tailOffset++; + document.insertString(ref.getTextRange().getStartOffset(), "!"); + state.caretOffset++; + state.tailOffset++; } } } - myContext.setTailOffset(myState.tailOffset); - myState.caretOffset = processTail(tailType, myState.caretOffset, myState.tailOffset); - myEditor.getSelectionModel().removeSelection(); + context.setTailOffset(state.tailOffset); + state.caretOffset = processTail(tailType, state.caretOffset, state.tailOffset, editor); + editor.getSelectionModel().removeSelection(); - qualifyIfNeeded(); + qualifyIfNeeded(context, item); if (needLeftParenth && hasParams){ // Invoke parameters popup - AutoPopupController.getInstance(myProject).autoPopupParameterInfo(myEditor, null); + AutoPopupController.getInstance(project).autoPopupParameterInfo(editor, null); } if (tailType == TailType.DOT){ - AutoPopupController.getInstance(myProject).autoPopupMemberLookup(myEditor, null); + AutoPopupController.getInstance(project).autoPopupMemberLookup(editor, null); } if (completionChar == '#') { context.setLaterRunnable(new Runnable() { public void run() { - new CodeCompletionHandlerBase(CompletionType.BASIC) { - }.invoke(myProject, myEditor, myFile); + new CodeCompletionHandlerBase(CompletionType.BASIC).invoke(project, editor, file); } }); } - if (insertingAnnotation()) { + if (insertingAnnotation(context, item)) { // Check if someone inserts annotation class that require @ - PsiElement elementAt = myFile.findElementAt(myContext.getStartOffset()); + PsiElement elementAt = file.findElementAt(context.getStartOffset()); final PsiElement parentElement = elementAt != null ? elementAt.getParent():null; if (elementAt instanceof PsiIdentifier && (PsiTreeUtil.getParentOfType(elementAt, PsiAnnotationParameterList.class) != null || parentElement instanceof PsiErrorElement && parentElement.getParent() instanceof PsiJavaFile // top level annotation without @ ) - && isAtTokenNeeded()) { + && isAtTokenNeeded(context)) { int expectedOffsetForAtToken = elementAt.getTextRange().getStartOffset(); - myDocument.insertString(expectedOffsetForAtToken, "@"); + document.insertString(expectedOffsetForAtToken, "@"); } } } - private void qualifyIfNeeded() { + private static void qualifyIfNeeded(InsertionContext context, LookupElement item) { try{ - if (myLookupItem.getObject() instanceof PsiField) { - PsiDocumentManager.getInstance(myFile.getProject()).commitAllDocuments(); - PsiReference reference = myFile.findReferenceAt(myContext.getStartOffset()); + final PsiFile file = context.getFile(); + if (item.getObject() instanceof PsiField) { + PsiDocumentManager.getInstance(file.getProject()).commitAllDocuments(); + PsiReference reference = file.findReferenceAt(context.getStartOffset()); if (reference instanceof PsiReferenceExpression && !((PsiReferenceExpression) reference).isQualified()) { - final PsiField member = (PsiField)myLookupItem.getObject(); + final PsiField member = (PsiField)item.getObject(); final PsiVariable target = - JavaPsiFacade.getInstance(myProject).getResolveHelper().resolveReferencedVariable(member.getName(), (PsiElement)reference); + JavaPsiFacade.getInstance(context.getProject()).getResolveHelper().resolveReferencedVariable(member.getName(), (PsiElement)reference); if (member.getManager().areElementsEquivalent(target, JavaCompletionUtil.getOriginalElement(member))) return; final PsiClass psiClass = member.getContainingClass(); if (psiClass != null && StringUtil.isNotEmpty(psiClass.getName())) { - myDocument.insertString(myContext.getStartOffset(), psiClass.getName() + "."); + context.getEditor().getDocument().insertString(context.getStartOffset(), psiClass.getName() + "."); } } } - addImportForItem(myFile, myContext.getStartOffset(), myLookupItem); - if (myContext.getTailOffset() < 0) { //hack, hack, hack. ideally the tail offset just should survive after the importing stuff - myContext.setTailOffset(myEditor.getCaretModel().getOffset()); + addImportForItem(file, context.getStartOffset(), item); + if (context.getTailOffset() < 0) { //hack, hack, hack. ideally the tail offset just should survive after the importing stuff + context.setTailOffset(context.getEditor().getCaretModel().getOffset()); } } catch(IncorrectOperationException e){ @@ -172,7 +163,7 @@ public class DefaultInsertHandler extends TemplateInsertHandler implements Clone } } - private boolean isAtTokenNeeded() { + private static boolean isAtTokenNeeded(InsertionContext myContext) { HighlighterIterator iterator = ((EditorEx)myContext.getEditor()).getHighlighter().createIterator(myContext.getStartOffset()); LOG.assertTrue(iterator.getTokenType() == JavaTokenType.IDENTIFIER); iterator.retreat(); @@ -180,53 +171,54 @@ public class DefaultInsertHandler extends TemplateInsertHandler implements Clone return iterator.getTokenType() != JavaTokenType.AT && iterator.getTokenType() != JavaTokenType.DOT; } - private void handleBrackets(){ + private static void handleBrackets(LookupElement item, Document document, InsertHandlerState myState){ // brackets - final Integer bracketsAttr = (Integer)myLookupItem.getUserData(LookupItem.BRACKETS_COUNT_ATTR); + final Integer bracketsAttr = (Integer)item.getUserData(LookupItem.BRACKETS_COUNT_ATTR); if (bracketsAttr != null){ int count = bracketsAttr.intValue(); if(count > 0) myState.caretOffset = myState.tailOffset + 1; for(int i = 0; i < count; i++){ - myDocument.insertString(myState.tailOffset, "[]"); + document.insertString(myState.tailOffset, "[]"); myState.tailOffset += 2; } } } - private void handleParenses(final boolean hasParams, final boolean needParenth, TailType tailType){ + private static void handleParentheses(final boolean hasParams, final boolean needParenth, TailType tailType, InsertionContext context, InsertHandlerState myState){ + final Document document = context.getEditor().getDocument(); boolean insertRightParenth = tailType != TailType.SMART_COMPLETION; if (needParenth){ - if (myContext.getOffsetMap().getOffset(JavaCompletionUtil.LPAREN_OFFSET) >= 0 && myContext.getOffsetMap().getOffset(JavaCompletionUtil.ARG_LIST_END_OFFSET) >= 0){ - myState.tailOffset = myContext.getOffsetMap().getOffset(JavaCompletionUtil.ARG_LIST_END_OFFSET); - if (myContext.getOffsetMap().getOffset(JavaCompletionUtil.RPAREN_OFFSET) < 0 && insertRightParenth){ - myDocument.insertString(myState.tailOffset, ")"); + if (context.getOffsetMap().getOffset(JavaCompletionUtil.LPAREN_OFFSET) >= 0 && context.getOffsetMap().getOffset(JavaCompletionUtil.ARG_LIST_END_OFFSET) >= 0){ + myState.tailOffset = context.getOffsetMap().getOffset(JavaCompletionUtil.ARG_LIST_END_OFFSET); + if (context.getOffsetMap().getOffset(JavaCompletionUtil.RPAREN_OFFSET) < 0 && insertRightParenth){ + document.insertString(myState.tailOffset, ")"); myState.tailOffset += 1; } if (hasParams){ - myState.caretOffset = myContext.getOffsetMap().getOffset(JavaCompletionUtil.LPAREN_OFFSET) + 1; + myState.caretOffset = context.getOffsetMap().getOffset(JavaCompletionUtil.LPAREN_OFFSET) + 1; } else{ - myState.caretOffset = myContext.getOffsetMap().getOffset(JavaCompletionUtil.ARG_LIST_END_OFFSET); + myState.caretOffset = context.getOffsetMap().getOffset(JavaCompletionUtil.ARG_LIST_END_OFFSET); } } else{ - final CodeStyleSettings styleSettings = CodeStyleSettingsManager.getSettings(myProject); - myState.tailOffset = myContext.getSelectionEndOffset(); - myState.caretOffset = myContext.getSelectionEndOffset(); + final CodeStyleSettings styleSettings = CodeStyleSettingsManager.getSettings(context.getProject()); + myState.tailOffset = context.getSelectionEndOffset(); + myState.caretOffset = context.getSelectionEndOffset(); if(styleSettings.SPACE_BEFORE_METHOD_CALL_PARENTHESES){ - myDocument.insertString(myState.tailOffset++, " "); + document.insertString(myState.tailOffset++, " "); myState.caretOffset ++; } if (insertRightParenth) { - final CharSequence charsSequence = myDocument.getCharsSequence(); + final CharSequence charsSequence = document.getCharsSequence(); if (charsSequence.length() <= myState.tailOffset || charsSequence.charAt(myState.tailOffset) != '(') { - myDocument.insertString(myState.tailOffset, "("); + document.insertString(myState.tailOffset, "("); } - myDocument.insertString(myState.tailOffset + 1, ")"); + document.insertString(myState.tailOffset + 1, ")"); if (hasParams){ myState.tailOffset += 2; myState.caretOffset++; @@ -243,26 +235,26 @@ public class DefaultInsertHandler extends TemplateInsertHandler implements Clone } } else{ - myDocument.insertString(myState.tailOffset++, "("); + document.insertString(myState.tailOffset++, "("); myState.caretOffset ++; } if(hasParams && styleSettings.SPACE_WITHIN_METHOD_CALL_PARENTHESES){ - myDocument.insertString(myState.caretOffset++, " "); + document.insertString(myState.caretOffset++, " "); myState.tailOffset++; } } } } - protected boolean isToInsertParenth(){ - return insertingAnnotationWithParameters(); + protected static boolean isToInsertParenth(InsertionContext context, LookupElement item){ + return insertingAnnotationWithParameters(context, item); } - private boolean hasParams(){ - final String lookupString = myLookupItem.getLookupString(); + private static boolean hasParams(InsertionContext context, LookupElement item){ + final String lookupString = item.getLookupString(); if (PsiKeyword.SYNCHRONIZED.equals(lookupString)) { - final PsiElement place = myFile.findElementAt(myContext.getStartOffset()); + final PsiElement place = context.getFile().findElementAt(context.getStartOffset()); return PsiTreeUtil.getParentOfType(place, PsiMember.class, PsiCodeBlock.class) instanceof PsiCodeBlock; } else if(PsiKeyword.CATCH.equals(lookupString) || @@ -270,21 +262,21 @@ public class DefaultInsertHandler extends TemplateInsertHandler implements Clone PsiKeyword.WHILE.equals(lookupString) || PsiKeyword.FOR.equals(lookupString)) return true; - else if (insertingAnnotationWithParameters()) { + else if (insertingAnnotationWithParameters(context, item)) { return true; } return false; } - private boolean insertingAnnotationWithParameters() { - if(insertingAnnotation()) { - final Document document = myContext.getEditor().getDocument(); - PsiDocumentManager.getInstance(myContext.getProject()).commitDocument(document); - PsiElement elementAt = myFile.findElementAt(myContext.getStartOffset()); + private static boolean insertingAnnotationWithParameters(InsertionContext context, LookupElement item) { + if(insertingAnnotation(context, item)) { + final Document document = context.getEditor().getDocument(); + PsiDocumentManager.getInstance(context.getProject()).commitDocument(document); + PsiElement elementAt = context.getFile().findElementAt(context.getStartOffset()); if (elementAt instanceof PsiIdentifier) { final PsiModifierListOwner parent = PsiTreeUtil.getParentOfType(elementAt, PsiModifierListOwner.class, false, PsiCodeBlock.class); if (parent != null) { - for (PsiMethod m : ((PsiClass)myLookupItem.getObject()).getMethods()) { + for (PsiMethod m : ((PsiClass)item.getObject()).getMethods()) { if (!(m instanceof PsiAnnotationMethod)) continue; final PsiAnnotationMemberValue defaultValue = ((PsiAnnotationMethod)m).getDefaultValue(); if (defaultValue == null) return true; @@ -295,35 +287,38 @@ public class DefaultInsertHandler extends TemplateInsertHandler implements Clone return false; } - private boolean insertingAnnotation() { - final Object obj = myLookupItem.getObject(); + private static boolean insertingAnnotation(InsertionContext context, LookupElement item) { + final Object obj = item.getObject(); if (!(obj instanceof PsiClass) || !((PsiClass)obj).isAnnotationType()) return false; - final Document document = myEditor.getDocument(); - PsiDocumentManager.getInstance(myFile.getProject()).commitDocument(document); - final int offset = myContext.getStartOffset(); + final Document document = context.getEditor().getDocument(); + PsiDocumentManager.getInstance(context.getProject()).commitDocument(document); + final int offset = context.getStartOffset(); - if (PsiTreeUtil.findElementOfClassAtOffset(myFile, offset, PsiImportStatement.class, false) != null) return false; + final PsiFile file = context.getFile(); + + if (PsiTreeUtil.findElementOfClassAtOffset(file, offset, PsiImportStatement.class, false) != null) return false; //outside of any class: we are surely inserting an annotation - if (PsiTreeUtil.findElementOfClassAtOffset(myFile, offset, PsiClass.class, false) == null) return true; + if (PsiTreeUtil.findElementOfClassAtOffset(file, offset, PsiClass.class, false) == null) return true; //the easiest check that there's a @ before the identifier - return PsiTreeUtil.findElementOfClassAtOffset(myFile, offset, PsiAnnotation.class, false) != null; + return PsiTreeUtil.findElementOfClassAtOffset(file, offset, PsiAnnotation.class, false) != null; } - protected void removeEndOfIdentifier(boolean needParenth){ - JavaCompletionUtil.initOffsets(myContext.getFile(), myContext.getProject(), myContext.getOffsetMap()); - myDocument.deleteString(myContext.getSelectionEndOffset(), myContext.getOffsetMap().getOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET)); - if(myContext.getOffsetMap().getOffset(JavaCompletionUtil.LPAREN_OFFSET) > 0 && !needParenth){ - myDocument.deleteString(myContext.getOffsetMap().getOffset(JavaCompletionUtil.LPAREN_OFFSET), - myContext.getOffsetMap().getOffset(JavaCompletionUtil.ARG_LIST_END_OFFSET)); - JavaCompletionUtil.resetParensInfo(myContext.getOffsetMap()); + protected static void removeEndOfIdentifier(boolean needParenth, InsertionContext context){ + final Document document = context.getEditor().getDocument(); + JavaCompletionUtil.initOffsets(context.getFile(), context.getProject(), context.getOffsetMap()); + document.deleteString(context.getSelectionEndOffset(), context.getOffsetMap().getOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET)); + if(context.getOffsetMap().getOffset(JavaCompletionUtil.LPAREN_OFFSET) > 0 && !needParenth){ + document.deleteString(context.getOffsetMap().getOffset(JavaCompletionUtil.LPAREN_OFFSET), + context.getOffsetMap().getOffset(JavaCompletionUtil.ARG_LIST_END_OFFSET)); + JavaCompletionUtil.resetParensInfo(context.getOffsetMap()); } } - protected TailType getTailType(final char completionChar){ + protected TailType getTailType(final char completionChar, LookupItem item){ switch(completionChar){ case '.': return TailType.DOT; case ',': return TailType.COMMA; @@ -337,14 +332,14 @@ public class DefaultInsertHandler extends TemplateInsertHandler implements Clone case '\"': case '[': return TailType.createSimpleTailType(completionChar); } - final TailType attr = myLookupItem.getTailType(); + final TailType attr = item.getTailType(); return attr == TailType.UNKNOWN ? TailType.NONE : attr; } - private int processTail(TailType tailType, int caretOffset, int tailOffset) { - myEditor.getCaretModel().moveToOffset(caretOffset); - tailType.processTail(myEditor, tailOffset); - return myEditor.getCaretModel().getOffset(); + private static int processTail(TailType tailType, int caretOffset, int tailOffset, Editor editor) { + editor.getCaretModel().moveToOffset(caretOffset); + tailType.processTail(editor, tailOffset); + return editor.getCaretModel().getOffset(); } @Override @@ -392,6 +387,7 @@ public class DefaultInsertHandler extends TemplateInsertHandler implements Clone private static void shortenReference(final PsiFile file, final int offset) throws IncorrectOperationException { final PsiDocumentManager manager = PsiDocumentManager.getInstance(file.getProject()); final Document document = manager.getDocument(file); + assert document != null; manager.commitDocument(document); final PsiReference ref = file.findReferenceAt(offset); if (ref instanceof PsiJavaCodeReferenceElement) { @@ -480,6 +476,7 @@ public class DefaultInsertHandler extends TemplateInsertHandler implements Clone return toDelete; } + @Nullable static PsiElement resolveReference(final PsiReference psiReference) { if (psiReference instanceof PsiPolyVariantReference) { final ResolveResult[] results = ((PsiPolyVariantReference)psiReference).multiResolve(true); From 7c51c983759146a83c6ae98e8879d32d0c9ec4ea Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 31 May 2010 18:46:51 +0100 Subject: [PATCH 056/212] correctly generate anonymos body when completing after new inside another anonymous --- .../completion/ConstructorInsertHandler.java | 37 +++++++++---------- .../NewAbstractInsideAnonymous-out.java | 19 ++++++++++ .../smartType/NewAbstractInsideAnonymous.java | 14 +++++++ .../completion/SmartTypeCompletionTest.java | 2 + 4 files changed, 52 insertions(+), 20 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/NewAbstractInsideAnonymous-out.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/NewAbstractInsideAnonymous.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java b/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java index 73422a5172ce..aa82cc1db9ef 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java @@ -38,33 +38,30 @@ class ConstructorInsertHandler implements InsertHandler item) { @SuppressWarnings({"unchecked"}) final LookupItem delegate = item.getDelegate(); + final PsiElement position = SmartCompletionDecorator.getPosition(context, delegate); + final PsiExpression enclosing = PsiTreeUtil.getContextOfType(position, PsiExpression.class, true); + final PsiAnonymousClass anonymousClass = PsiTreeUtil.getParentOfType(position, PsiAnonymousClass.class); + final boolean inAnonymous = anonymousClass != null && anonymousClass.getParent() == enclosing; + insertParentheses(context, delegate, delegate.getObject()); DefaultInsertHandler.addImportForItem(context.getFile(), context.getStartOffset(), delegate); - final PsiElement position = SmartCompletionDecorator.getPosition(context, delegate); - final PsiExpression enclosing = PsiTreeUtil.getContextOfType(position, PsiExpression.class, true); - if (item.getUserData(LookupItem.BRACKETS_COUNT_ATTR) == null) { - final PsiAnonymousClass anonymousClass = PsiTreeUtil.getParentOfType(position, PsiAnonymousClass.class); - if (anonymousClass == null || anonymousClass.getParent() != enclosing) { + if (item.getUserData(LookupItem.BRACKETS_COUNT_ATTR) == null && !inAnonymous) { + if (((PsiClass)item.getObject()).hasModifierProperty(PsiModifier.ABSTRACT)) { + FeatureUsageTracker.getInstance().triggerFeatureUsed("editing.completion.smarttype.anonymous"); - final PsiClass psiClass = (PsiClass)item.getObject(); + PostprocessReformattingAspect.getInstance(context.getProject()).doPostponedFormatting(context.getFile().getViewProvider()); - if (psiClass.hasModifierProperty(PsiModifier.ABSTRACT) || psiClass.isInterface()) { - FeatureUsageTracker.getInstance().triggerFeatureUsed("editing.completion.smarttype.anonymous"); - - PostprocessReformattingAspect.getInstance(context.getProject()).doPostponedFormatting(context.getFile().getViewProvider()); - - final Editor editor = context.getEditor(); - final int offset = context.getTailOffset(); - editor.getDocument().insertString(offset, " {}"); - editor.getCaretModel().moveToOffset(offset + 2); - context.setLaterRunnable(generateAnonymousBody(editor, context.getFile())); - } - else { - FeatureUsageTracker.getInstance().triggerFeatureUsed("editing.completion.smarttype.afternew"); - } + final Editor editor = context.getEditor(); + final int offset = context.getTailOffset(); + editor.getDocument().insertString(offset, " {}"); + editor.getCaretModel().moveToOffset(offset + 2); + context.setLaterRunnable(generateAnonymousBody(editor, context.getFile())); + } + else { + FeatureUsageTracker.getInstance().triggerFeatureUsed("editing.completion.smarttype.afternew"); } } } diff --git a/java/java-tests/testData/codeInsight/completion/smartType/NewAbstractInsideAnonymous-out.java b/java/java-tests/testData/codeInsight/completion/smartType/NewAbstractInsideAnonymous-out.java new file mode 100644 index 000000000000..3c290421b29b --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/NewAbstractInsideAnonymous-out.java @@ -0,0 +1,19 @@ +public class Foo { + + public Foo() { + Runnable r = new Runnable() { + public void run() { + Goo g = new Goo() { + @Override + void foo() { + //To change body of implemented methods use File | Settings | File Templates. + } + }; + } + }; + } +} + +abstract class Goo { + abstract void foo(); +} diff --git a/java/java-tests/testData/codeInsight/completion/smartType/NewAbstractInsideAnonymous.java b/java/java-tests/testData/codeInsight/completion/smartType/NewAbstractInsideAnonymous.java new file mode 100644 index 000000000000..b3a141712bd7 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/NewAbstractInsideAnonymous.java @@ -0,0 +1,14 @@ +public class Foo { + + public Foo() { + Runnable r = new Runnable() { + public void run() { + Goo g = new G + } + }; + } +} + +abstract class Goo { + abstract void foo(); +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java index 2eb7e0ff5d59..9932fd937875 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java @@ -951,6 +951,8 @@ public class SmartTypeCompletionTest extends LightCompletionTestCase { public void testEnumAsDefaultAnnotationParam() throws Throwable { doTest(); } + public void testNewAbstractInsideAnonymous() throws Throwable { doTest(); } + public void testFilterPrivateConstructors() throws Throwable { doTest(); } public void testExplicitMethodTypeParametersQualify() throws Throwable { doTest(); } From 40f40828f85ee923fc47f8d68f39d1161ae6bfe7 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 31 May 2010 21:37:43 +0100 Subject: [PATCH 057/212] fix Groovy SDK detection in Groovy project itself --- .../org/jetbrains/plugins/groovy/util/LibrariesUtil.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/util/LibrariesUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/util/LibrariesUtil.java index 78b7ebcb6685..b3529cb502cc 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/util/LibrariesUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/util/LibrariesUtil.java @@ -105,9 +105,9 @@ public class LibrariesUtil { @Nullable public static String getGroovyHomePath(@NotNull Module module) { - final PsiClass cUnit = JavaPsiFacade.getInstance(module.getProject()) - .findClass("org.codehaus.groovy.control.CompilationUnit", GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module)); - if (cUnit != null) { + final PsiClass[] classes = JavaPsiFacade.getInstance(module.getProject()) + .findClasses("org.codehaus.groovy.control.CompilationUnit", GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module)); + for (PsiClass cUnit : classes) { final VirtualFile local = JarFileSystem.getInstance().getVirtualFileForJar(cUnit.getContainingFile().getVirtualFile()); if (local != null) { final VirtualFile parent = local.getParent(); From eb42b989ca8bc41915b4f322c2ef6a849c6c1c9e Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 31 May 2010 22:32:04 +0100 Subject: [PATCH 058/212] cache method signatures for non-physical classes (completion works on non-physical file copy => will be faster) --- .../com/intellij/psi/impl/PsiSuperMethodImplUtil.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java b/java/java-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java index 797385f2f512..0db41dc1a9eb 100644 --- a/java/java-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java +++ b/java/java-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java @@ -301,12 +301,9 @@ public class PsiSuperMethodImplUtil { CachedValue> value = aClass.getUserData(SIGNATURES_KEY); if (value == null) { BySignaturesCachedValueProvider provider = new BySignaturesCachedValueProvider(aClass); - value = CachedValuesManager.getManager(aClass.getProject()).createCachedValue(provider, false); - //Do not cache for nonphysical elements - if (aClass.isPhysical()) { - UserDataHolderEx dataHolder = (UserDataHolderEx)aClass; - value = dataHolder.putUserDataIfAbsent(SIGNATURES_KEY, value); - } + UserDataHolderEx dataHolder = (UserDataHolderEx)aClass; + value = dataHolder.putUserDataIfAbsent(SIGNATURES_KEY, + CachedValuesManager.getManager(aClass.getProject()).createCachedValue(provider, false)); } return value.getValue(); From 5418d8e78ceeceac080c89761afbb643790cf1f8 Mon Sep 17 00:00:00 2001 From: Gregory Shrago Date: Tue, 1 Jun 2010 03:05:23 +0400 Subject: [PATCH 059/212] improve generic injection editor (groovy completion) --- .../PatternBasedInjectionHelper.java | 183 ++++++++++++++++-- .../AbstractLanguageInjectionSupport.java | 5 +- .../inject/config/BaseInjection.java | 7 + .../inject/config/ui/BaseInjectionPanel.form | 35 +++- .../inject/config/ui/BaseInjectionPanel.java | 25 ++- .../META-INF/intellilang-groovy-support.xml | 3 + .../PatternEditorContextMembersProvider.java | 54 ++++++ 7 files changed, 284 insertions(+), 28 deletions(-) create mode 100644 plugins/groovy/src/org/intellij/plugins/intelliLang/inject/groovy/PatternEditorContextMembersProvider.java diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/PatternBasedInjectionHelper.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/PatternBasedInjectionHelper.java index 3d98cc71245a..9f586594b3a2 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/PatternBasedInjectionHelper.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/PatternBasedInjectionHelper.java @@ -25,15 +25,12 @@ import com.intellij.util.Function; import com.intellij.util.ReflectionCache; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.Stack; +import gnu.trove.THashMap; import gnu.trove.THashSet; import org.intellij.plugins.intelliLang.inject.LanguageInjectionSupport; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; -import java.lang.reflect.Array; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; +import java.lang.reflect.*; import java.util.*; /** @@ -123,9 +120,23 @@ public class PatternBasedInjectionHelper { } } - public static ElementPattern compileElementPattern(final String text, final String supportId) { + public static ElementPattern compileElementPattern(final String text, final String supportId) { + final Set staticMethods = getStaticMethods(supportId); + return createElementPatternNoGroovy(text, new Function() { + public Object fun(final Frame frame) { + try { + return invokeMethod(frame.target, frame.methodName, frame.params.toArray(), staticMethods); + } + catch (Throwable throwable) { + throw new IllegalArgumentException(text, throwable); + } + } + }); + } + + private static Set getStaticMethods(String supportId) { final Class[] patternClasses = getPatternClasses(supportId); - final Set staticMethods = new THashSet(ContainerUtil.concat(patternClasses, new Function>() { + return new THashSet(ContainerUtil.concat(patternClasses, new Function>() { public Collection fun(final Class aClass) { return ContainerUtil.findAll(ReflectionCache.getMethods(aClass), new Condition() { public boolean value(final Method method) { @@ -137,16 +148,6 @@ public class PatternBasedInjectionHelper { }); } })); - return createElementPatternNoGroovy(text, new Function() { - public Object fun(final Frame frame) { - try { - return invokeMethod(frame.target, frame.methodName, frame.params.toArray(), staticMethods); - } - catch (Throwable throwable) { - throw new IllegalArgumentException(text, throwable); - } - } - }); } private static enum State { @@ -366,4 +367,152 @@ public class PatternBasedInjectionHelper { }, ", ")+")"); } + + public static String dumpContextDeclarations(String injectorId) { + final Set methods = getStaticMethods(injectorId); + final StringBuilder sb = new StringBuilder(); + final THashMap> classes = new THashMap>(); + final THashSet missingClasses = new THashSet(); + classes.put(Object.class, missingClasses); + for (Method method : methods) { + for (Class type = method.getReturnType(); type != null && ElementPattern.class.isAssignableFrom(type); type = type.getSuperclass()) { + final Class enclosingClass = type.getEnclosingClass(); + if (enclosingClass != null) { + Collection list = classes.get(enclosingClass); + if (list == null) { + list = new THashSet(); + classes.put(enclosingClass, list); + } + list.add(type); + } + else if (!classes.containsKey(type)) { + classes.put(type, null); + } + } + } + for (Class aClass : classes.keySet()) { + if (aClass == Object.class) continue; + printClass(aClass, classes, sb); + } + for (Method method : methods) { + printMethodDeclaration(method, sb, classes); + } + for (Class aClass : missingClasses) { + sb.append("class ").append(aClass.getSimpleName()); + final Class superclass = aClass.getSuperclass(); + if (missingClasses.contains(superclass)) { + sb.append(" extends ").append(superclass.getSimpleName()); + } + sb.append("{}\n"); + } + //System.out.println(sb); + return sb.toString(); + } + + private static void printClass(Class aClass, Map> classes, StringBuilder sb) { + final boolean isInterface = aClass.isInterface(); + sb.append(isInterface ? "interface ": "class "); + dumpType(aClass, aClass, sb, classes); + final Type superClass = aClass.getGenericSuperclass(); + final Class rawSuperClass = (Class)(superClass instanceof ParameterizedType ? ((ParameterizedType)superClass).getRawType() : superClass); + if (superClass != null && classes.containsKey(rawSuperClass)) { + sb.append(" extends "); + dumpType(null, superClass, sb, classes); + } + int implementsIdx = 1; + for (Type superInterface : aClass.getGenericInterfaces()) { + final Class rawSuperInterface = (Class)(superInterface instanceof ParameterizedType ? ((ParameterizedType)superInterface).getRawType() : superClass); + if (classes.containsKey(rawSuperInterface)) { + if (implementsIdx++ == 1) sb.append(isInterface? " extends " : " implements "); + else sb.append(", "); + dumpType(null, superInterface, sb, classes); + } + } + sb.append(" {\n"); + for (Method method : aClass.getDeclaredMethods()) { + if (Modifier.isStatic(method.getModifiers()) || + !Modifier.isPublic(method.getModifiers()) || + Modifier.isVolatile(method.getModifiers())) continue; + printMethodDeclaration(method, sb.append(" "), classes); + } + final Collection innerClasses = classes.get(aClass); + sb.append("}\n"); + if (innerClasses != null) { + for (Class innerClass : innerClasses) { + printClass(innerClass, classes, sb); + } + } + } + + private static void dumpType(GenericDeclaration owner, Type type, StringBuilder sb, Map> classes) { + if (type instanceof Class) { + final Class aClass = (Class)type; + final Class enclosingClass = aClass.getEnclosingClass(); + if (enclosingClass != null) { + sb.append(enclosingClass.getSimpleName()).append("_"); + } + else if (!aClass.isArray() && !aClass.isPrimitive() && !aClass.getName().startsWith("java.") && !classes.containsKey(aClass)) { + classes.get(Object.class).add(aClass); + } + sb.append(aClass.getSimpleName()); + if (owner == aClass) { + dumpTypeParametersArray(owner, aClass.getTypeParameters(), sb, "<", ">", classes); + } + } + else if (type instanceof TypeVariable) { + TypeVariable typeVariable = (TypeVariable)type; + sb.append(typeVariable.getName()); + if (typeVariable.getGenericDeclaration() == owner) { + dumpTypeParametersArray(null, typeVariable.getBounds(), sb, " extends ", "", classes); + } + } + else if (type instanceof WildcardType) { + final WildcardType wildcardType = (WildcardType)type; + sb.append("?"); + dumpTypeParametersArray(owner, wildcardType.getUpperBounds(), sb, " extends ", "", classes); + dumpTypeParametersArray(owner, wildcardType.getLowerBounds(), sb, " super ", "", classes); + } + else if (type instanceof ParameterizedType) { + final ParameterizedType parameterizedType = (ParameterizedType)type; + final Type raw = parameterizedType.getRawType(); + dumpType(null, raw, sb, classes); + dumpTypeParametersArray(owner, parameterizedType.getActualTypeArguments(), sb, "<", ">", classes); + } + else if (type instanceof GenericArrayType) { + dumpType(owner, ((GenericArrayType)type).getGenericComponentType(), sb, classes); + sb.append("[]"); + } + } + + private static void dumpTypeParametersArray(GenericDeclaration owner, final Type[] typeVariables, + final StringBuilder sb, + final String prefix, final String suffix, Map> classes) { + int typeVarIdx = 1; + for (Type typeVariable : typeVariables) { + if (typeVariable == Object.class) continue; + if (typeVarIdx++ == 1) sb.append(prefix); + else sb.append(", "); + dumpType(owner, typeVariable, sb, classes); + } + if (typeVarIdx > 1) sb.append(suffix); + } + + private static void printMethodDeclaration(Method method, StringBuilder sb, Map> classes) { + if (Modifier.isStatic(method.getModifiers())) { + sb.append("static "); + } + dumpTypeParametersArray(method, method.getTypeParameters(), sb, "<", "> ", classes); + dumpType(null, method.getGenericReturnType(), sb, classes); + sb.append(" ").append(method.getName()).append("("); + int paramIdx = 1; + for (Type parameter : method.getGenericParameterTypes()) { + if (paramIdx != 1) sb.append(", "); + dumpType(null, parameter, sb, classes); + sb.append(" ").append("p").append(paramIdx++); + } + sb.append(")"); + if (!method.getDeclaringClass().isInterface()) sb.append("{}"); + sb.append("\n"); + } + } diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/AbstractLanguageInjectionSupport.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/AbstractLanguageInjectionSupport.java index 73f08c034238..eeb554824b18 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/AbstractLanguageInjectionSupport.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/AbstractLanguageInjectionSupport.java @@ -19,7 +19,6 @@ package org.intellij.plugins.intelliLang.inject; import com.intellij.lang.Language; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.application.ex.ApplicationEx; import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.project.Project; @@ -27,6 +26,7 @@ import com.intellij.openapi.ui.DialogBuilder; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Factory; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiLanguageInjectionHost; import com.intellij.ui.SimpleColoredText; @@ -99,10 +99,11 @@ public abstract class AbstractLanguageInjectionSupport extends LanguageInjection public static AnAction createDefaultAddAction(final Project project, final Consumer consumer, final AbstractLanguageInjectionSupport support) { - return new AnAction("Generic "+support.getId().toUpperCase(), null, Icons.FILE_ICON) { + return new AnAction("Generic "+ StringUtil.capitalize(support.getId()), null, Icons.FILE_ICON) { @Override public void actionPerformed(AnActionEvent e) { final BaseInjection injection = new BaseInjection(support.getId()); + injection.setDisplayName("New "+support.getId()+" Injection"); final BaseInjection newInjection = showInjectionUI(project, injection); if (newInjection != null) { consumer.consume(injection); diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/BaseInjection.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/BaseInjection.java index df9d93acb57b..710a47b8440c 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/BaseInjection.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/BaseInjection.java @@ -20,6 +20,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.JDOMExternalizer; +import com.intellij.openapi.util.Key; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.ElementManipulators; @@ -49,6 +50,8 @@ import java.util.regex.Pattern; */ public class BaseInjection implements Injection, PersistentStateComponent { + public static final Key INJECTION_KEY = Key.create("INJECTION_KEY"); + @NotNull private final String mySupportId; private String myDisplayName; @@ -89,6 +92,10 @@ public class BaseInjection implements Injection, PersistentStateComponent
    - + @@ -10,12 +10,12 @@ - + - + @@ -23,9 +23,36 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/BaseInjectionPanel.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/BaseInjectionPanel.java index 91ad20570129..1cee03a0e9be 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/BaseInjectionPanel.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/BaseInjectionPanel.java @@ -15,16 +15,18 @@ */ package org.intellij.plugins.intelliLang.inject.config.ui; -import com.intellij.openapi.editor.colors.EditorColorsManager; -import com.intellij.openapi.editor.colors.EditorFontType; +import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.fileTypes.FileTypes; import com.intellij.openapi.fileTypes.UnknownFileType; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiFileFactory; import com.intellij.ui.EditorTextField; -import com.intellij.ui.ScrollPaneFactory; import org.intellij.plugins.intelliLang.PatternBasedInjectionHelper; import org.intellij.plugins.intelliLang.inject.config.BaseInjection; import org.intellij.plugins.intelliLang.inject.config.InjectionPlace; @@ -46,26 +48,38 @@ public class BaseInjectionPanel extends AbstractInjectionPanel { AdvancedPanel myAdvancedPanel; private JPanel myRoot; + private JTextField myNameTextField; public BaseInjectionPanel(BaseInjection injection, Project project) { super(injection, project); $$$setupUI$$$(); // see IDEA-9987 final FileType groovy = FileTypeManager.getInstance().getFileTypeByExtension("groovy"); - myTextArea = new EditorTextField("", project, groovy == UnknownFileType.INSTANCE? FileTypes.PLAIN_TEXT : groovy) { + final FileType realFileType = groovy == UnknownFileType.INSTANCE ? FileTypes.PLAIN_TEXT : groovy; + final PsiFile psiFile = PsiFileFactory.getInstance(project).createFileFromText("injection." + realFileType.getDefaultExtension(), realFileType, "", 0, true); + final Document document = PsiDocumentManager.getInstance(project).getDocument(psiFile); + psiFile.putUserData(BaseInjection.INJECTION_KEY, injection); + myTextArea = new EditorTextField(document, project, realFileType) { @Override protected EditorEx createEditor() { final EditorEx ex = super.createEditor(); ex.setOneLineMode(false); + ex.setVerticalScrollbarVisible(true); + ex.setHorizontalScrollbarVisible(true); return ex; } }; - myCenterPanel.add(ScrollPaneFactory.createScrollPane(myTextArea), BorderLayout.CENTER); + myCenterPanel.add(myTextArea, BorderLayout.CENTER); myTextArea.setFontInheritedFromLAF(false); //myTextArea.setFont(EditorColorsManager.getInstance().getGlobalScheme().getFont(EditorFontType.PLAIN)); init(injection.copy()); } protected void apply(BaseInjection other) { + final String displayName = myNameTextField.getText(); + if (StringUtil.isEmpty(displayName)) { + throw new IllegalArgumentException("Display name should not be empty"); + } + other.setDisplayName(displayName); boolean enabled = true; final StringBuilder sb = new StringBuilder(); final ArrayList places = new ArrayList(); @@ -104,6 +118,7 @@ public class BaseInjectionPanel extends AbstractInjectionPanel { sb.append(place.isEnabled()?"+ ":"- ").append(place.getText()).append("\n"); } myTextArea.setText(sb.toString()); + myNameTextField.setText(myOrigInjection.getDisplayName()); } public JPanel getComponent() { diff --git a/plugins/groovy/src/META-INF/intellilang-groovy-support.xml b/plugins/groovy/src/META-INF/intellilang-groovy-support.xml index 365491c9511e..e731f61f3561 100644 --- a/plugins/groovy/src/META-INF/intellilang-groovy-support.xml +++ b/plugins/groovy/src/META-INF/intellilang-groovy-support.xml @@ -6,5 +6,8 @@ + + + diff --git a/plugins/groovy/src/org/intellij/plugins/intelliLang/inject/groovy/PatternEditorContextMembersProvider.java b/plugins/groovy/src/org/intellij/plugins/intelliLang/inject/groovy/PatternEditorContextMembersProvider.java new file mode 100644 index 000000000000..b78c9061bd0e --- /dev/null +++ b/plugins/groovy/src/org/intellij/plugins/intelliLang/inject/groovy/PatternEditorContextMembersProvider.java @@ -0,0 +1,54 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.intellij.plugins.intelliLang.inject.groovy; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.AtomicNotNullLazyValue; +import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.UserDataHolderEx; +import com.intellij.psi.*; +import com.intellij.psi.scope.PsiScopeProcessor; +import org.intellij.plugins.intelliLang.PatternBasedInjectionHelper; +import org.intellij.plugins.intelliLang.inject.config.BaseInjection; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.groovy.GroovyFileType; +import org.jetbrains.plugins.groovy.lang.resolve.NonCodeMembersProcessor; + +/** + * @author Gregory.Shrago + */ +public class PatternEditorContextMembersProvider implements NonCodeMembersProcessor { + + public static final Key> INJECTION_PARSED_CONTEXT = Key.create("INJECTION_PARSED_CONTEXT"); + + public boolean processNonCodeMembers(PsiType type, PsiScopeProcessor processor, PsiElement place, boolean forCompletion) { + final PsiFile file = place.getContainingFile().getOriginalFile(); + final BaseInjection injection = file.getUserData(BaseInjection.INJECTION_KEY); + if (injection == null) return true; + return ((UserDataHolderEx)file).putUserDataIfAbsent(INJECTION_PARSED_CONTEXT, new AtomicNotNullLazyValue() { + @NotNull + @Override + protected PsiFile compute() { + return parseInjectionContext(injection, file.getProject()); + } + }).getValue().processDeclarations(processor, ResolveState.initial(), null, place); + } + + private static PsiFile parseInjectionContext(@NotNull BaseInjection injection, Project project) { + final String text = PatternBasedInjectionHelper.dumpContextDeclarations(injection.getSupportId()); + return PsiFileFactory.getInstance(project).createFileFromText("context.groovy", GroovyFileType.GROOVY_FILE_TYPE, text); + } +} From 31ce0fe7627abc66306c02bb529405b186886f79 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Tue, 11 May 2010 17:46:41 +0400 Subject: [PATCH 060/212] Maven: remote maven facade --- .../execution/rmi/RemoteProcessSupport.java | 33 +- .../impl/DocumentReferenceManagerImpl.java | 1 + .../com/intellij/util/io/fs}/FilePath.java | 2 +- .../lib/lucene-core-2.3.0.jar | Bin plugins/maven/facade-api/maven-facade-api.iml | 23 + .../idea/maven/facade/MavenFacade.java | 47 ++ .../idea/maven/facade/MavenFacadeConsole.java | 31 + .../maven/facade/MavenFacadeEmbedder.java | 74 +++ .../idea/maven/facade/MavenFacadeIndexer.java | 59 ++ .../facade/MavenFacadeIndexerException.java} | 17 +- .../idea/maven/facade/MavenFacadeLogger.java | 27 + .../MavenFacadeProcessCanceledException.java | 21 + .../facade/MavenFacadeProgressIndicator.java | 30 + .../maven/facade/MavenFacadeSettings.java | 107 +++ .../facade/MavenFacadeTransferListener.java} | 7 +- .../idea/maven/facade/MavenFacadeUtil.java | 69 ++ .../facade/MavenWrapperExecutionResult.java | 59 ++ .../facade/NativeMavenProjectHolder.java | 8 + .../facade/ProfileApplicationResult.java | 40 ++ .../idea/maven/facade/RemoteObject.java} | 54 +- .../idea/maven/model/MavenArchetype.java} | 19 +- .../idea/maven/model}/MavenArtifact.java | 166 ++--- .../idea/maven/model/MavenArtifactInfo.java | 86 +++ .../idea/maven/model}/MavenArtifactNode.java | 29 +- .../idea/maven/model}/MavenArtifactState.java | 2 +- .../idea/maven/model/MavenBuild.java | 72 ++ .../idea/maven/model/MavenBuildBase.java | 77 +++ .../idea/maven/model}/MavenConstants.java | 21 +- .../jetbrains/idea/maven/model}/MavenId.java | 21 +- .../idea/maven/model/MavenModel.java | 73 ++ .../idea/maven/model/MavenModelBase.java | 88 +++ .../idea/maven/model/MavenParent.java | 36 + .../idea/maven/model}/MavenPlugin.java | 100 +-- .../idea/maven/model/MavenProfile.java | 54 ++ .../maven/model/MavenProfileActivation.java | 66 ++ .../model/MavenProfileActivationFile.java | 36 + .../maven/model/MavenProfileActivationOS.java | 48 ++ .../model/MavenProfileActivationProperty.java | 36 + .../idea/maven/model/MavenProfileKind.java} | 6 +- .../idea/maven/model/MavenProjectProblem.java | 96 +++ .../maven/model/MavenRemoteRepository.java | 115 ++++ .../maven/model/MavenRepositoryInfo.java} | 33 +- .../idea/maven/model}/MavenResource.java | 35 +- .../{ => facade-impl}/lib/activation-1.1.jar | Bin .../archetype-common-2.0-alpha-4-SNAPSHOT.jar | Bin .../{ => facade-impl}/lib/classworlds-1.1.jar | Bin .../lib/commons-beanutils.jar | Bin .../lib/commons-logging-1.1.1.jar | Bin .../{ => facade-impl}/lib/jaxb-api-2.1.jar | Bin .../lib/jaxb-impl-2.1.10.jar | Bin .../lib/maven-2.2.1-uber.jar | Bin .../lib/maven-dependency-tree-1.2.jar | Bin .../lib/maven-embedder-1.0-SNAPSHOT.jar | Bin 0 -> 24562 bytes .../lib/mercury-artifact-1.0-alpha-6.jar | Bin .../lib/nexus-indexer-1.2.3.jar | Bin .../lib/plexus-utils-1.5.5.jar | Bin .../maven/{ => facade-impl}/lib/wadl-core.jar | Bin .../maven/facade-impl/maven-facade-impl.iml | 185 ++++++ .../idea/maven/facade/MavenFacadeImpl.java | 113 ++++ .../maven/facade}/MavenFacadeLocator.java | 41 +- .../facade/MavenFacadeLoggerManager.java | 31 + .../idea/maven/facade}/RemoteMavenServer.java | 4 +- .../facade}/embedder/CustomArtifact.java | 6 +- .../embedder/CustomArtifactFactory.java | 2 +- .../embedder/CustomArtifactResolver.java | 17 +- .../embedder/CustomModelInterpolator.java | 2 +- .../facade}/embedder/CustomWagonManager.java | 2 +- .../facade/embedder/ExecutorManager.java | 27 + .../maven/facade}/embedder/FieldAccessor.java | 2 +- .../embedder/MavenFacadeConsoleWrapper.java} | 48 +- .../embedder/MavenFacadeEmbedderImpl.java | 626 ++++++++++++++++++ .../embedder/MavenFacadeIndexerImpl.java | 296 +++++++++ .../embedder/MavenFacadeLoggerWrapper.java | 56 ++ .../MavenFacadeProgressIndicatorWrapper.java | 80 +++ .../facade/embedder}/MavenIndexFetcher.java | 7 +- .../facade/embedder/MavenModelConverter.java | 525 +++++++++++++++ .../RemoteNativeMavenProjectHolder.java | 31 + .../embedder}/TransferListenerAdapter.java | 43 +- .../UnresolvedArtifactsCollector.java | 6 +- .../idea/maven/facade/nexus/ArtifactType.java | 338 ++++++++++ .../idea/maven/facade/nexus/Endpoint.java | 0 .../maven/facade/nexus/ObjectFactory.java | 7 +- .../idea/maven/facade/nexus/Repositories.java | 4 +- .../facade/nexus/RepositoryMetaData.java | 0 .../maven/facade/nexus/RepositoryType.java | 0 .../idea/maven/facade/nexus/SearchResult.java | 4 +- .../maven/facade/nexus/SearchResults.java | 6 +- .../idea/maven/facade/nexus/nexus.wadl | 0 .../idea/maven/facade/nexus/nexus.xsd | 0 .../embedder/MavenFacadeEmbedderTest.java} | 144 ++-- .../maven/embedder}/NexusIndexerTest.java | 28 +- .../idea/maven/facade/nexus/ArtifactType.java | 371 ----------- .../idea/maven/facade/remote/MavenFacade.java | 98 --- .../facade/remote/impl/MavenFacadeImpl.java | 393 ----------- .../impl/RemoteTransferListenerImpl.java | 28 - .../maven/lib/maven-embedder-1.0-SNAPSHOT.jar | Bin 25822 -> 0 bytes plugins/maven/maven-facade.iml | 103 --- plugins/maven/maven.iml | 107 +-- .../maven/project/JBMavenProjectHelper.java | 29 - .../maven/compiler/MavenResourceCompiler.java | 2 +- .../dom/MavenDomProjectProcessorUtils.java | 1 + .../idea/maven/dom/MavenDomUtil.java | 6 +- .../idea/maven/dom/MavenPropertyResolver.java | 21 +- .../dom/annotator/MavenDomAnnotator.java | 6 +- ...rtifactCoordinatesArtifactIdConverter.java | 2 +- .../MavenArtifactCoordinatesConverter.java | 2 +- ...enArtifactCoordinatesGroupIdConverter.java | 5 +- .../MavenArtifactCoordinatesHelper.java | 2 +- ...enArtifactCoordinatesVersionConverter.java | 2 +- .../MavenDependencyScopeConverter.java | 3 +- .../MavenParentRelativePathConverter.java | 5 +- .../MavenRepositoriesProvider.java | 6 - .../beans/RepositoryBeanInfo.java | 7 - .../GenerateAddManagedDependencyAction.java | 2 - .../generate/GenerateDependencyAction.java | 3 +- .../MavenDuplicateDependenciesInspection.java | 2 +- .../AddMavenDependencyQuickFix.java | 2 +- .../references/MavenModulePsiReference.java | 4 +- .../references/MavenPropertyPsiReference.java | 1 + .../maven/embedder/CustomLoggerManager.java | 62 -- .../maven/embedder/MavenConsoleHelper.java | 33 - .../maven/embedder/MavenEmbedderUtilEx.java | 138 ---- .../maven/embedder/MavenEmbedderWrapper.java | 446 ------------- .../embedder/MavenWrapperExecutionResult.java | 52 -- .../MavenWrapperResolutionResult.java | 40 -- .../MavenExecutionOptions.java | 46 +- .../idea/maven/execution/MavenExecutor.java | 9 +- .../execution/MavenExternalExecutor.java | 5 +- .../execution/MavenExternalParameters.java | 10 +- .../MavenJavaClasspathPolicyExtender.java | 4 +- .../execution/MavenRunConfiguration.java | 4 +- .../idea/maven/execution/MavenRunner.java | 7 +- .../MavenRunnerParametersConfigurable.java | 2 +- .../maven/execution/SoutMavenConsole.java | 3 +- .../maven/facade/MavenEmbedderWrapper.java | 208 ++++++ .../idea/maven/facade/MavenFacadeManager.java | 375 +++++++++++ .../maven/facade/MavenIndexerWrapper.java | 137 ++++ .../facade/remote/MavenFacadeManagerImpl.java | 175 ----- .../idea/maven/importing/FacetImporter.java | 2 +- .../idea/maven/importing/GroovyImporter.java | 1 + .../maven/importing/MavenFoldersImporter.java | 2 +- .../idea/maven/importing/MavenImporter.java | 8 +- .../maven/importing/MavenModuleImporter.java | 3 +- .../importing/MavenModuleNameMapper.java | 2 +- .../maven/importing/MavenProjectImporter.java | 2 +- .../importing/MavenRootModelAdapter.java | 10 +- .../indices/MavenArchetypesProvider.java | 3 +- .../indices/MavenArtifactSearchDialog.java | 2 +- .../indices/MavenArtifactSearchPanel.java | 30 +- .../indices/MavenArtifactSearchResult.java | 7 +- .../maven/indices/MavenArtifactSearcher.java | 28 +- .../maven/indices/MavenClassSearcher.java | 17 +- .../idea/maven/indices/MavenIndex.java | 249 ++----- .../idea/maven/indices/MavenIndices.java | 40 +- .../maven/indices/MavenIndicesManager.java | 110 +-- .../indices/MavenProjectIndicesManager.java | 12 +- .../idea/maven/indices/MavenSearcher.java | 39 +- .../maven/navigator/MavenNavigationUtil.java | 4 +- .../navigator/MavenProjectsNavigator.java | 3 +- .../MavenProjectsNavigatorPanel.java | 9 +- .../navigator/MavenProjectsStructure.java | 20 +- .../project/MavenArtifactDownloader.java | 10 +- .../{embedder => project}/MavenConsole.java | 108 +-- .../MavenConsoleImpl.java | 4 +- .../maven/project/MavenEmbeddersManager.java | 38 +- .../maven/project/MavenEnvironmentForm.form | 23 +- .../maven/project/MavenEnvironmentForm.java | 22 +- .../project/MavenGeneralConfigurable.java | 2 +- .../maven/project/MavenGeneralSettings.java | 44 +- .../idea/maven/project/MavenParentDesc.java | 1 + .../MavenParentProjectFileProcessor.java | 3 +- .../idea/maven/project/MavenProject.java | 250 ++----- .../maven/project/MavenProjectProblem.java | 81 --- .../maven/project/MavenProjectReader.java | 598 ++++++----------- .../MavenProjectReaderProjectLocator.java | 4 +- .../project/MavenProjectReaderResult.java | 37 +- .../maven/project/MavenProjectsManager.java | 19 +- .../project/MavenProjectsManagerWatcher.java | 3 +- .../maven/project/MavenProjectsProcessor.java | 1 - ...ectsProcessorArtifactsDownloadingTask.java | 2 +- .../MavenProjectsProcessorEmptyTask.java | 1 - ...ProjectsProcessorFoldersResolvingTask.java | 6 +- ...ProjectsProcessorPluginsResolvingTask.java | 8 +- .../MavenProjectsProcessorReadingTask.java | 1 - .../MavenProjectsProcessorResolvingTask.java | 1 - .../project/MavenProjectsProcessorTask.java | 1 - .../idea/maven/project/MavenProjectsTree.java | 68 +- .../maven/project/MavenRemoteRepository.java | 132 ---- .../DownloadSelectedSourcesAndDocsAction.java | 3 +- .../maven/tasks/MavenKeymapExtension.java | 7 +- .../maven/tasks/MavenShortcutsManager.java | 9 +- .../idea/maven/utils/FileFinder.java | 2 +- .../idea/maven/utils/MavenArtifactUtil.java | 2 +- .../utils/MavenAttachSourcesProvider.java | 2 + .../idea/maven/utils/MavenDataKeys.java | 2 +- .../utils/MavenEnvironmentRegistrar.java | 4 +- .../idea/maven/utils/MavenPluginInfo.java | 6 +- .../idea/maven/utils/MavenRehighlighter.java | 5 +- .../idea/maven/utils/MavenUIUtil.java | 13 +- .../jetbrains/idea/maven/utils/MavenUtil.java | 230 +++++-- .../maven/utils/RepositoryAttachDialog.java | 52 +- .../maven/utils/RepositoryAttachHandler.java | 452 ++++++------- .../maven/utils/actions/MavenActionUtil.java | 2 +- .../wizards/MavenAddArchetypeDialog.java | 6 +- .../MavenFrameworkSupportProvider.java | 4 +- .../maven/wizards/MavenModuleBuilder.java | 10 +- .../wizards/MavenModuleBuilderHelper.java | 10 +- .../maven/wizards/MavenModuleWizardStep.java | 56 +- .../maven/wizards/MavenProjectBuilder.java | 1 + .../wizards/MavenProjectOpenProcessor.java | 2 +- .../main/resources/IndicesBundle.properties | 1 - .../src/main/resources/META-INF/plugin.xml | 12 +- .../main/resources/ProjectBundle.properties | 3 - .../MavenCustomRepositoryHelper.java | 2 +- .../idea/maven/MavenImportingTestCase.java | 1 + .../jetbrains/idea/maven/MavenTestCase.java | 3 +- .../idea/maven/NullMavenConsole.java | 6 +- .../maven/importing/AddingDependencyTest.java | 6 +- .../importing/ArtifactsDownloadingTest.java | 6 +- .../importing/DependenciesImportingTest.java | 6 +- .../importing/DependenciesManagementTest.java | 4 +- .../maven/importing/FoldersImportingTest.java | 4 +- .../InvalidProjectImportingTest.java | 4 +- .../maven/importing/MiscImportingTest.java | 5 +- .../indices/MavenIndicesManagerTest.java | 7 +- .../maven/indices/MavenIndicesStressTest.java | 21 +- .../idea/maven/indices/MavenIndicesTest.java | 106 ++- .../indices/MavenIndicesTestFixture.java | 3 +- .../indices/MavenPluginInfoReaderTest.java | 3 +- .../idea/maven/indices/MavenSearcherTest.java | 10 +- .../project/MavenEmbeddersManagerTest.java | 30 +- .../maven/project/MavenProjectReaderTest.java | 295 ++++----- .../idea/maven/project/MavenProjectTest.java | 22 +- .../project/MavenProjectsManagerTest.java | 3 +- .../project/MavenProjectsTreeReadingTest.java | 30 +- .../maven/wizards/MavenModuleBuilderTest.java | 11 +- 236 files changed, 6485 insertions(+), 4744 deletions(-) rename platform/{platform-api/src/com/intellij/openapi/vfs => util/src/com/intellij/util/io/fs}/FilePath.java (97%) rename plugins/maven/{ => facade-api}/lib/lucene-core-2.3.0.jar (100%) create mode 100644 plugins/maven/facade-api/maven-facade-api.iml create mode 100644 plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacade.java create mode 100644 plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeConsole.java create mode 100644 plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeEmbedder.java create mode 100644 plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeIndexer.java rename plugins/maven/{src/main/java/org/jetbrains/idea/maven/facade/remote/MavenFacadeManager.java => facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeIndexerException.java} (64%) create mode 100644 plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeLogger.java create mode 100644 plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeProcessCanceledException.java create mode 100644 plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeProgressIndicator.java create mode 100644 plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeSettings.java rename plugins/maven/{facade/org/jetbrains/idea/maven/facade/remote/RemoteTransferListener.java => facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeTransferListener.java} (96%) create mode 100644 plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeUtil.java create mode 100644 plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenWrapperExecutionResult.java create mode 100644 plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/NativeMavenProjectHolder.java create mode 100644 plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/ProfileApplicationResult.java rename plugins/maven/{facade/org/jetbrains/idea/maven/facade/remote/impl/RemoteImpl.java => facade-api/src/org/jetbrains/idea/maven/facade/RemoteObject.java} (58%) rename plugins/maven/{src/main/java/org/jetbrains/idea/maven/indices/ArchetypeInfo.java => facade-api/src/org/jetbrains/idea/maven/model/MavenArchetype.java} (82%) rename plugins/maven/{src/main/java/org/jetbrains/idea/maven/project => facade-api/src/org/jetbrains/idea/maven/model}/MavenArtifact.java (64%) create mode 100644 plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenArtifactInfo.java rename plugins/maven/{src/main/java/org/jetbrains/idea/maven/project => facade-api/src/org/jetbrains/idea/maven/model}/MavenArtifactNode.java (82%) rename plugins/maven/{src/main/java/org/jetbrains/idea/maven/project => facade-api/src/org/jetbrains/idea/maven/model}/MavenArtifactState.java (94%) create mode 100644 plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenBuild.java create mode 100644 plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenBuildBase.java rename plugins/maven/{src/main/java/org/jetbrains/idea/maven/utils => facade-api/src/org/jetbrains/idea/maven/model}/MavenConstants.java (58%) rename plugins/maven/{src/main/java/org/jetbrains/idea/maven/project => facade-api/src/org/jetbrains/idea/maven/model}/MavenId.java (84%) create mode 100644 plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenModel.java create mode 100644 plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenModelBase.java create mode 100644 plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenParent.java rename plugins/maven/{src/main/java/org/jetbrains/idea/maven/project => facade-api/src/org/jetbrains/idea/maven/model}/MavenPlugin.java (63%) create mode 100644 plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenProfile.java create mode 100644 plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenProfileActivation.java create mode 100644 plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenProfileActivationFile.java create mode 100644 plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenProfileActivationOS.java create mode 100644 plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenProfileActivationProperty.java rename plugins/maven/{src/main/java/org/jetbrains/idea/maven/project/MavenProfileState.java => facade-api/src/org/jetbrains/idea/maven/model/MavenProfileKind.java} (83%) create mode 100644 plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenProjectProblem.java create mode 100644 plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenRemoteRepository.java rename plugins/maven/{src/main/java/org/jetbrains/idea/maven/project/MavenProjectModelProblem.java => facade-api/src/org/jetbrains/idea/maven/model/MavenRepositoryInfo.java} (51%) rename plugins/maven/{src/main/java/org/jetbrains/idea/maven/project => facade-api/src/org/jetbrains/idea/maven/model}/MavenResource.java (74%) rename plugins/maven/{ => facade-impl}/lib/activation-1.1.jar (100%) rename plugins/maven/{ => facade-impl}/lib/archetype-common-2.0-alpha-4-SNAPSHOT.jar (100%) rename plugins/maven/{ => facade-impl}/lib/classworlds-1.1.jar (100%) rename plugins/maven/{ => facade-impl}/lib/commons-beanutils.jar (100%) rename plugins/maven/{ => facade-impl}/lib/commons-logging-1.1.1.jar (100%) rename plugins/maven/{ => facade-impl}/lib/jaxb-api-2.1.jar (100%) rename plugins/maven/{ => facade-impl}/lib/jaxb-impl-2.1.10.jar (100%) rename plugins/maven/{ => facade-impl}/lib/maven-2.2.1-uber.jar (100%) rename plugins/maven/{ => facade-impl}/lib/maven-dependency-tree-1.2.jar (100%) create mode 100644 plugins/maven/facade-impl/lib/maven-embedder-1.0-SNAPSHOT.jar rename plugins/maven/{ => facade-impl}/lib/mercury-artifact-1.0-alpha-6.jar (100%) rename plugins/maven/{ => facade-impl}/lib/nexus-indexer-1.2.3.jar (100%) rename plugins/maven/{ => facade-impl}/lib/plexus-utils-1.5.5.jar (100%) rename plugins/maven/{ => facade-impl}/lib/wadl-core.jar (100%) create mode 100644 plugins/maven/facade-impl/maven-facade-impl.iml create mode 100644 plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/MavenFacadeImpl.java rename plugins/maven/{facade/org/jetbrains/idea/maven/facade/remote => facade-impl/src/org/jetbrains/idea/maven/facade}/MavenFacadeLocator.java (79%) create mode 100644 plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/MavenFacadeLoggerManager.java rename plugins/maven/{facade/org/jetbrains/idea/maven/facade/remote => facade-impl/src/org/jetbrains/idea/maven/facade}/RemoteMavenServer.java (93%) rename plugins/maven/{src/main/java/org/jetbrains/idea/maven => facade-impl/src/org/jetbrains/idea/maven/facade}/embedder/CustomArtifact.java (97%) rename plugins/maven/{src/main/java/org/jetbrains/idea/maven => facade-impl/src/org/jetbrains/idea/maven/facade}/embedder/CustomArtifactFactory.java (99%) rename plugins/maven/{src/main/java/org/jetbrains/idea/maven => facade-impl/src/org/jetbrains/idea/maven/facade}/embedder/CustomArtifactResolver.java (84%) rename plugins/maven/{src/main/java/org/jetbrains/idea/maven => facade-impl/src/org/jetbrains/idea/maven/facade}/embedder/CustomModelInterpolator.java (97%) rename plugins/maven/{src/main/java/org/jetbrains/idea/maven => facade-impl/src/org/jetbrains/idea/maven/facade}/embedder/CustomWagonManager.java (99%) create mode 100644 plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/ExecutorManager.java rename plugins/maven/{src/main/java/org/jetbrains/idea/maven => facade-impl/src/org/jetbrains/idea/maven/facade}/embedder/FieldAccessor.java (96%) rename plugins/maven/{src/main/java/org/jetbrains/idea/maven/embedder/MavenLogger.java => facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenFacadeConsoleWrapper.java} (61%) create mode 100644 plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenFacadeEmbedderImpl.java create mode 100644 plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenFacadeIndexerImpl.java create mode 100644 plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenFacadeLoggerWrapper.java create mode 100644 plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenFacadeProgressIndicatorWrapper.java rename plugins/maven/{src/main/java/org/jetbrains/idea/maven/indices => facade-impl/src/org/jetbrains/idea/maven/facade/embedder}/MavenIndexFetcher.java (95%) create mode 100644 plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenModelConverter.java create mode 100644 plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/RemoteNativeMavenProjectHolder.java rename plugins/maven/{src/main/java/org/jetbrains/idea/maven/project => facade-impl/src/org/jetbrains/idea/maven/facade/embedder}/TransferListenerAdapter.java (61%) rename plugins/maven/{src/main/java/org/jetbrains/idea/maven => facade-impl/src/org/jetbrains/idea/maven/facade}/embedder/UnresolvedArtifactsCollector.java (88%) create mode 100644 plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/nexus/ArtifactType.java rename plugins/maven/{facade => facade-impl/src}/org/jetbrains/idea/maven/facade/nexus/Endpoint.java (100%) rename plugins/maven/{facade => facade-impl/src}/org/jetbrains/idea/maven/facade/nexus/ObjectFactory.java (90%) rename plugins/maven/{facade => facade-impl/src}/org/jetbrains/idea/maven/facade/nexus/Repositories.java (97%) rename plugins/maven/{facade => facade-impl/src}/org/jetbrains/idea/maven/facade/nexus/RepositoryMetaData.java (100%) rename plugins/maven/{facade => facade-impl/src}/org/jetbrains/idea/maven/facade/nexus/RepositoryType.java (100%) rename plugins/maven/{facade => facade-impl/src}/org/jetbrains/idea/maven/facade/nexus/SearchResult.java (98%) rename plugins/maven/{facade => facade-impl/src}/org/jetbrains/idea/maven/facade/nexus/SearchResults.java (97%) rename plugins/maven/{facade => facade-impl/src}/org/jetbrains/idea/maven/facade/nexus/nexus.wadl (100%) rename plugins/maven/{facade => facade-impl/src}/org/jetbrains/idea/maven/facade/nexus/nexus.xsd (100%) rename plugins/maven/{src/test/java/org/jetbrains/idea/maven/embedder/MavenEmbedderWrapperTest.java => facade-impl/test/org/jetbrains/idea/maven/embedder/MavenFacadeEmbedderTest.java} (80%) rename plugins/maven/{src/test/java/org/jetbrains/idea/maven/indices => facade-impl/test/org/jetbrains/idea/maven/embedder}/NexusIndexerTest.java (91%) delete mode 100644 plugins/maven/facade/org/jetbrains/idea/maven/facade/nexus/ArtifactType.java delete mode 100644 plugins/maven/facade/org/jetbrains/idea/maven/facade/remote/MavenFacade.java delete mode 100644 plugins/maven/facade/org/jetbrains/idea/maven/facade/remote/impl/MavenFacadeImpl.java delete mode 100644 plugins/maven/facade/org/jetbrains/idea/maven/facade/remote/impl/RemoteTransferListenerImpl.java delete mode 100644 plugins/maven/lib/maven-embedder-1.0-SNAPSHOT.jar delete mode 100644 plugins/maven/maven-facade.iml delete mode 100644 plugins/maven/src/main/java/org/apache/maven/project/JBMavenProjectHelper.java delete mode 100644 plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/CustomLoggerManager.java delete mode 100644 plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/MavenConsoleHelper.java delete mode 100644 plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/MavenEmbedderUtilEx.java delete mode 100644 plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/MavenEmbedderWrapper.java delete mode 100644 plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/MavenWrapperExecutionResult.java delete mode 100644 plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/MavenWrapperResolutionResult.java rename plugins/maven/src/main/java/org/jetbrains/idea/maven/{embedder => execution}/MavenExecutionOptions.java (68%) create mode 100644 plugins/maven/src/main/java/org/jetbrains/idea/maven/facade/MavenEmbedderWrapper.java create mode 100644 plugins/maven/src/main/java/org/jetbrains/idea/maven/facade/MavenFacadeManager.java create mode 100644 plugins/maven/src/main/java/org/jetbrains/idea/maven/facade/MavenIndexerWrapper.java delete mode 100644 plugins/maven/src/main/java/org/jetbrains/idea/maven/facade/remote/MavenFacadeManagerImpl.java rename plugins/maven/src/main/java/org/jetbrains/idea/maven/{embedder => project}/MavenConsole.java (62%) rename plugins/maven/src/main/java/org/jetbrains/idea/maven/{embedder => project}/MavenConsoleImpl.java (97%) delete mode 100644 plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectProblem.java delete mode 100644 plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenRemoteRepository.java rename plugins/maven/src/test/java/org/jetbrains/idea/maven/{indices => }/MavenCustomRepositoryHelper.java (98%) diff --git a/platform/lang-impl/src/com/intellij/execution/rmi/RemoteProcessSupport.java b/platform/lang-impl/src/com/intellij/execution/rmi/RemoteProcessSupport.java index 9da838b8559e..6ae69943c34a 100644 --- a/platform/lang-impl/src/com/intellij/execution/rmi/RemoteProcessSupport.java +++ b/platform/lang-impl/src/com/intellij/execution/rmi/RemoteProcessSupport.java @@ -13,8 +13,8 @@ import com.intellij.execution.process.ProcessOutputTypes; import com.intellij.execution.runners.DefaultProgramRunner; import com.intellij.execution.runners.ProgramRunner; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressManager; -import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; @@ -34,20 +34,16 @@ import java.util.List; * @author Gregory.Shrago */ public abstract class RemoteProcessSupport { - private final Project myProject; + public static final Logger LOG = Logger.getInstance("#" + RemoteProcessSupport.class); + private final Class myValueClass; private final HashMap, Object> myProcMap = new HashMap, Object>(); - public RemoteProcessSupport(Project project, Class valueClass) { - myProject = project; + public RemoteProcessSupport(Class valueClass) { myValueClass = valueClass; } - public Project getProject() { - return myProject; - } - protected abstract void fireModificationCountChanged(); protected abstract String getName(Target target); @@ -55,7 +51,6 @@ public abstract class RemoteProcessSupport { protected void logText(Parameters configuration, ProcessEvent event, Key outputType, Object info) { } - public void stopAll() { final ArrayList allHandlers = new ArrayList(); synchronized (myProcMap) { @@ -166,7 +161,8 @@ public abstract class RemoteProcessSupport { } } - protected abstract RunProfileState getRunProfileState(Target target, Parameters configuration, Executor executor) throws ExecutionException; + protected abstract RunProfileState getRunProfileState(Target target, Parameters configuration, Executor executor) + throws ExecutionException; private boolean getExistingInfo(Ref ref, final Pair key) { Object info; @@ -214,7 +210,7 @@ public abstract class RemoteProcessSupport { } private static T narrowImpl(Remote remote, Class to) { - return (T) (to.isInstance(remote)? remote : PortableRemoteObject.narrow(remote, to)); + return (T)(to.isInstance(remote) ? remote : PortableRemoteObject.narrow(remote, to)); } private ProcessListener getProcessListener(final Pair key) { @@ -240,6 +236,13 @@ public abstract class RemoteProcessSupport { } public void onTextAvailable(ProcessEvent event, Key outputType) { + if (outputType == ProcessOutputTypes.STDERR) { + LOG.warn(event.getText()); + } + else { + LOG.info(event.getText()); + } + Info result = null; final PendingInfo info; synchronized (myProcMap) { @@ -262,7 +265,9 @@ public abstract class RemoteProcessSupport { info.stderr.append(event.getText()); } } - else info = null; + else { + info = null; + } } if (result != null) { synchronized (info.ref) { @@ -280,8 +285,8 @@ public abstract class RemoteProcessSupport { final PendingInfo pendingInfo; synchronized (myProcMap) { o = myProcMap.remove(key); - pendingInfo = o instanceof PendingInfo? (PendingInfo)o : null; - if (pendingInfo != null && (pendingInfo.stderr.length() > 0 || pendingInfo.ref.isNull())) { + pendingInfo = o instanceof PendingInfo ? (PendingInfo)o : null; + if (pendingInfo != null && (pendingInfo.stderr.length() > 0 || pendingInfo.ref.isNull())) { if (errorMessage != null) pendingInfo.stderr.append(errorMessage); pendingInfo.ref.set(new Info(null, -1, pendingInfo.stderr.toString())); } diff --git a/platform/platform-impl/src/com/intellij/openapi/command/impl/DocumentReferenceManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/command/impl/DocumentReferenceManagerImpl.java index 80e7c6a9bf2d..2fe3bdf3d4fa 100644 --- a/platform/platform-impl/src/com/intellij/openapi/command/impl/DocumentReferenceManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/command/impl/DocumentReferenceManagerImpl.java @@ -25,6 +25,7 @@ import com.intellij.openapi.util.Key; import com.intellij.openapi.vfs.*; import com.intellij.openapi.vfs.newvfs.NewVirtualFile; import com.intellij.util.containers.WeakValueHashMap; +import com.intellij.util.io.fs.FilePath; import org.jetbrains.annotations.NotNull; import java.lang.ref.Reference; diff --git a/platform/platform-api/src/com/intellij/openapi/vfs/FilePath.java b/platform/util/src/com/intellij/util/io/fs/FilePath.java similarity index 97% rename from platform/platform-api/src/com/intellij/openapi/vfs/FilePath.java rename to platform/util/src/com/intellij/util/io/fs/FilePath.java index 5a9c1c295b2e..dbf200971743 100644 --- a/platform/platform-api/src/com/intellij/openapi/vfs/FilePath.java +++ b/platform/util/src/com/intellij/util/io/fs/FilePath.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.openapi.vfs; +package com.intellij.util.io.fs; import com.intellij.openapi.util.io.FileUtil; diff --git a/plugins/maven/lib/lucene-core-2.3.0.jar b/plugins/maven/facade-api/lib/lucene-core-2.3.0.jar similarity index 100% rename from plugins/maven/lib/lucene-core-2.3.0.jar rename to plugins/maven/facade-api/lib/lucene-core-2.3.0.jar diff --git a/plugins/maven/facade-api/maven-facade-api.iml b/plugins/maven/facade-api/maven-facade-api.iml new file mode 100644 index 000000000000..8ba63b8dc7db --- /dev/null +++ b/plugins/maven/facade-api/maven-facade-api.iml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacade.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacade.java new file mode 100644 index 000000000000..20e57f894c1d --- /dev/null +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacade.java @@ -0,0 +1,47 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.maven.facade; + +import org.jetbrains.idea.maven.model.MavenArtifactInfo; +import org.jetbrains.idea.maven.model.MavenModel; +import org.jetbrains.idea.maven.model.MavenRepositoryInfo; + +import java.io.File; +import java.rmi.Remote; +import java.rmi.RemoteException; +import java.util.Collection; +import java.util.List; + +public interface MavenFacade extends Remote { + void setLogger(MavenFacadeLogger logger) throws RemoteException; + + MavenFacadeEmbedder createEmbedder(MavenFacadeSettings settings) throws RemoteException; + + MavenFacadeIndexer createIndexer() throws RemoteException; + + MavenModel interpolateAndAlignModel(MavenModel model, File basedir) throws RemoteException; + + MavenModel assembleInheritance(MavenModel model, MavenModel parentModel) throws RemoteException; + + ProfileApplicationResult applyProfiles(MavenModel model, + File basedir, + Collection explicitProfiles, + Collection alwaysOnProfiles) throws RemoteException; + + List getRepositories(String nexusUrl) throws RemoteException; + + List findArtifacts(MavenArtifactInfo template, String nexusUrl) throws RemoteException; +} diff --git a/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeConsole.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeConsole.java new file mode 100644 index 000000000000..84a3bafcf271 --- /dev/null +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeConsole.java @@ -0,0 +1,31 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.maven.facade; + +import java.rmi.Remote; +import java.rmi.RemoteException; + +public interface MavenFacadeConsole extends Remote { + // must be same as in org.codehaus.plexus.logging.Logger + int LEVEL_DEBUG = 0; + int LEVEL_INFO = 1; + int LEVEL_WARN = 2; + int LEVEL_ERROR = 3; + int LEVEL_FATAL = 4; + int LEVEL_DISABLED = 5; + + void printMessage(int level, String message, Throwable throwable) throws RemoteException; +} diff --git a/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeEmbedder.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeEmbedder.java new file mode 100644 index 000000000000..e697ade5ee6c --- /dev/null +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeEmbedder.java @@ -0,0 +1,74 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.maven.facade; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.maven.model.*; + +import java.io.File; +import java.rmi.Remote; +import java.rmi.RemoteException; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public interface MavenFacadeEmbedder extends Remote { + void customizeForResolve(MavenFacadeConsole console, MavenFacadeProgressIndicator process) throws RemoteException; + + void customizeForResolve(Map projectIdToFileMap, + MavenFacadeConsole console, + MavenFacadeProgressIndicator process) throws RemoteException; + + void customizeForStrictResolve(Map projectIdToFileMap, + MavenFacadeConsole console, + MavenFacadeProgressIndicator process) throws RemoteException; + + @NotNull + MavenWrapperExecutionResult resolveProject(@NotNull File file, + @NotNull Collection activeProfiles) throws RemoteException, + MavenFacadeProcessCanceledException; + + @NotNull + MavenArtifact resolve(@NotNull MavenArtifactInfo info, + @NotNull List remoteRepositories) throws RemoteException, + MavenFacadeProcessCanceledException; + + @NotNull + List resolveTransitively(@NotNull List artifacts, + @NotNull List remoteRepositories) throws RemoteException, + MavenFacadeProcessCanceledException; + + Collection resolvePlugin(@NotNull MavenPlugin plugin, + @NotNull List repositories, + int nativeMavenProjectId, + boolean transitive) throws RemoteException, MavenFacadeProcessCanceledException; + + @NotNull + MavenWrapperExecutionResult execute(@NotNull File file, + @NotNull Collection activeProfiles, + @NotNull List goals) throws RemoteException, + MavenFacadeProcessCanceledException; + + void reset() throws RemoteException; + + void release() throws RemoteException; + + void clearCaches() throws RemoteException; + + void clearCachesFor(MavenId projectId) throws RemoteException; +} diff --git a/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeIndexer.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeIndexer.java new file mode 100644 index 000000000000..99e1511f0076 --- /dev/null +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeIndexer.java @@ -0,0 +1,59 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.maven.facade; + +import org.apache.lucene.search.Query; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.maven.model.MavenArchetype; +import org.jetbrains.idea.maven.model.MavenArtifactInfo; +import org.jetbrains.idea.maven.model.MavenId; + +import java.io.File; +import java.rmi.Remote; +import java.rmi.RemoteException; +import java.util.Collection; +import java.util.List; +import java.util.Set; + +public interface MavenFacadeIndexer extends Remote { + String SEARCH_TERM_COORDINATES = "u"; // see org.sonatype.nexus.index.ArtifactInfo + String SEARCH_TERM_CLASS_NAMES = "c"; + + int createIndex(@NotNull String indexId, + @Nullable String repositoryId, + @Nullable File file, + @Nullable String url, + @NotNull File indexDir) throws RemoteException, MavenFacadeIndexerException; + + void releaseIndex(int id) throws RemoteException, MavenFacadeIndexerException; + + int getIndexCount() throws RemoteException; + + void updateIndex(int id, MavenFacadeSettings settings, MavenFacadeProgressIndicator indicator) throws RemoteException, + MavenFacadeIndexerException, + MavenFacadeProcessCanceledException; + + List getAllArtifacts(int indexId) throws RemoteException, MavenFacadeIndexerException; + + MavenId addArtifact(int indexId, File artifactFile) throws RemoteException, MavenFacadeIndexerException; + + Set search(int indexId, Query query, int maxResult) throws RemoteException, MavenFacadeIndexerException; + + Collection getArchetypes() throws RemoteException; + + void release() throws RemoteException; +} diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/facade/remote/MavenFacadeManager.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeIndexerException.java similarity index 64% rename from plugins/maven/src/main/java/org/jetbrains/idea/maven/facade/remote/MavenFacadeManager.java rename to plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeIndexerException.java index 315333403fa7..92ed5ad26499 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/facade/remote/MavenFacadeManager.java +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeIndexerException.java @@ -13,15 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.maven.facade.remote; +package org.jetbrains.idea.maven.facade; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +public class MavenFacadeIndexerException extends Exception { + public MavenFacadeIndexerException(String message) { + super(message); + } -/** - * @author Gregory.Shrago - */ -public interface MavenFacadeManager { - MavenFacade getMavenFacade(@NotNull final Object key) throws Exception; - void releaseMavenFacade(@NotNull Object key); + public MavenFacadeIndexerException(Exception cause) { + super(null, cause); + } } diff --git a/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeLogger.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeLogger.java new file mode 100644 index 000000000000..563492e56eed --- /dev/null +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeLogger.java @@ -0,0 +1,27 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.maven.facade; + +import java.rmi.Remote; +import java.rmi.RemoteException; + +public interface MavenFacadeLogger extends Remote { + void info(Throwable e) throws RemoteException; + + void warn(Throwable e) throws RemoteException; + + void error(Throwable e) throws RemoteException; +} diff --git a/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeProcessCanceledException.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeProcessCanceledException.java new file mode 100644 index 000000000000..f0d0d4a68dcb --- /dev/null +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeProcessCanceledException.java @@ -0,0 +1,21 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.maven.facade; + +import java.rmi.RemoteException; + +public class MavenFacadeProcessCanceledException extends Exception { +} diff --git a/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeProgressIndicator.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeProgressIndicator.java new file mode 100644 index 000000000000..48a400df6922 --- /dev/null +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeProgressIndicator.java @@ -0,0 +1,30 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.maven.facade; + +import java.rmi.Remote; +import java.rmi.RemoteException; + +public interface MavenFacadeProgressIndicator extends Remote { + void setText(String text) throws RemoteException; + void setText2(String text) throws RemoteException; + + boolean isCanceled() throws RemoteException; + + void setIndeterminate(boolean value) throws RemoteException; + + void setFraction(double fraction) throws RemoteException; +} diff --git a/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeSettings.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeSettings.java new file mode 100644 index 000000000000..0253ede5222c --- /dev/null +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeSettings.java @@ -0,0 +1,107 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.maven.facade; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.io.Serializable; + +public class MavenFacadeSettings implements Serializable { + public enum UpdatePolicy { + ALWAYS_UPDATE, DO_NOT_UPDATE + } + + private int myLoggingLevel; + @Nullable private File myMavenHome; + @Nullable private File myUserSettingsFile; + @Nullable private File myGlobalSettingsFile; + @Nullable private File myLocalRepository; + private boolean isOffline; + @NotNull private UpdatePolicy myPluginUpdatePolicy = UpdatePolicy.DO_NOT_UPDATE; + @NotNull private UpdatePolicy mySnapshotUpdatePolicy = UpdatePolicy.ALWAYS_UPDATE; + + public int getLoggingLevel() { + return myLoggingLevel; + } + + public void setLoggingLevel(int loggingLevel) { + myLoggingLevel = loggingLevel; + } + + @Nullable + public File getMavenHome() { + return myMavenHome; + } + + public void setMavenHome(@Nullable File mavenHome) { + myMavenHome = mavenHome; + } + + @Nullable + public File getUserSettingsFile() { + return myUserSettingsFile; + } + + public void setUserSettingsFile(@Nullable File userSettingsFile) { + myUserSettingsFile = userSettingsFile; + } + + @Nullable + public File getGlobalSettingsFile() { + return myGlobalSettingsFile; + } + + public void setGlobalSettingsFile(@Nullable File globalSettingsFile) { + myGlobalSettingsFile = globalSettingsFile; + } + + @Nullable + public File getLocalRepository() { + return myLocalRepository; + } + + public void setLocalRepository(@Nullable File localRepository) { + myLocalRepository = localRepository; + } + + public boolean isOffline() { + return isOffline; + } + + public void setOffline(boolean offline) { + isOffline = offline; + } + + @NotNull + public UpdatePolicy getPluginUpdatePolicy() { + return myPluginUpdatePolicy; + } + + public void setPluginUpdatePolicy(@NotNull UpdatePolicy pluginUpdatePolicy) { + myPluginUpdatePolicy = pluginUpdatePolicy; + } + + @NotNull + public UpdatePolicy getSnapshotUpdatePolicy() { + return mySnapshotUpdatePolicy; + } + + public void setSnapshotUpdatePolicy(@NotNull UpdatePolicy snapshotUpdatePolicy) { + mySnapshotUpdatePolicy = snapshotUpdatePolicy; + } +} diff --git a/plugins/maven/facade/org/jetbrains/idea/maven/facade/remote/RemoteTransferListener.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeTransferListener.java similarity index 96% rename from plugins/maven/facade/org/jetbrains/idea/maven/facade/remote/RemoteTransferListener.java rename to plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeTransferListener.java index 172c7a051476..42288d17f156 100644 --- a/plugins/maven/facade/org/jetbrains/idea/maven/facade/remote/RemoteTransferListener.java +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeTransferListener.java @@ -1,4 +1,4 @@ -package org.jetbrains.idea.maven.facade.remote; +package org.jetbrains.idea.maven.facade; import java.io.File; import java.io.Serializable; @@ -8,7 +8,7 @@ import java.rmi.RemoteException; /** * @author Gregory.Shrago */ -public interface RemoteTransferListener extends Remote { +public interface MavenFacadeTransferListener extends Remote { void transferInitiated(TransferEvent transferEvent) throws RemoteException; void transferStarted(TransferEvent transferEvent) throws RemoteException; @@ -21,9 +21,7 @@ public interface RemoteTransferListener extends Remote { void debug(String s) throws RemoteException; - class TransferEvent implements Serializable { - public enum EventType { INITIATED, STARTED, COMPLETED, PROGRESS, ERROR } public enum RequestType { PUT, GET } @@ -74,7 +72,6 @@ public interface RemoteTransferListener extends Remote { } class Resource implements Serializable { - private final String myResourceName; private final long myResourceLastModified; private final long myResourceContentLength; diff --git a/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeUtil.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeUtil.java new file mode 100644 index 000000000000..164bbe44aaa3 --- /dev/null +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeUtil.java @@ -0,0 +1,69 @@ +/* + * Copyright 2000-2009 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.maven.facade; + +import java.util.HashSet; +import java.util.Map; +import java.util.Properties; +import java.util.Set; + +public class MavenFacadeUtil { + private static volatile Properties mySystemPropertiesCache; + + public static Properties collectSystemProperties() { + + if (mySystemPropertiesCache == null) { + Properties result = new Properties(); + result.putAll(getSystemProperties()); + + Properties envVars = getEnvProperties(); + for (Map.Entry each : envVars.entrySet()) { + result.setProperty("env." + each.getKey().toString(), each.getValue().toString()); + } + mySystemPropertiesCache = result; + } + + return mySystemPropertiesCache; + } + + public static void resetSystemPropertiesCache() { + mySystemPropertiesCache = null; + } + + @SuppressWarnings({"unchecked"}) + private static Properties getSystemProperties() { + Properties result = (Properties)System.getProperties().clone(); + for (String each : new HashSet((Set)result.keySet())) { + if (each.startsWith("idea.")) { + result.remove(each); + } + } + return result; + } + + private static Properties getEnvProperties() { + Properties result = new Properties(); + for (Map.Entry each : System.getenv().entrySet()) { + if (isMagicalProperty(each.getKey())) continue; + result.put(each.getKey(), each.getValue()); + } + return result; + } + + private static boolean isMagicalProperty(String key) { + return key.startsWith("="); + } +} \ No newline at end of file diff --git a/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenWrapperExecutionResult.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenWrapperExecutionResult.java new file mode 100644 index 000000000000..c382aa546dc5 --- /dev/null +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenWrapperExecutionResult.java @@ -0,0 +1,59 @@ +/* + * Copyright 2000-2009 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.maven.facade; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.maven.model.MavenId; +import org.jetbrains.idea.maven.model.MavenModel; +import org.jetbrains.idea.maven.model.MavenProfile; +import org.jetbrains.idea.maven.model.MavenProjectProblem; + +import java.io.Serializable; +import java.util.Collection; +import java.util.Map; +import java.util.Set; + +public class MavenWrapperExecutionResult implements Serializable { + @Nullable public final ProjectData projectData; + @NotNull public final Collection problems; + @NotNull public final Set unresolvedArtifacts; + + public MavenWrapperExecutionResult(ProjectData projectData, + Collection problems, + Set unresolvedArtifacts) { + this.projectData = projectData; + this.problems = problems; + this.unresolvedArtifacts = unresolvedArtifacts; + } + + public static class ProjectData implements Serializable { + public final MavenModel mavenModel; + public final Map mavenModelMap; + public final NativeMavenProjectHolder nativeMavenProject; + public final Collection activatedProfiles; + + public ProjectData(MavenModel mavenModel, + Map mavenModelMap, + NativeMavenProjectHolder nativeMavenProject, + Collection activatedProfiles) { + this.mavenModel = mavenModel; + this.mavenModelMap = mavenModelMap; + this.nativeMavenProject = nativeMavenProject; + this.activatedProfiles = activatedProfiles; + } + } +} diff --git a/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/NativeMavenProjectHolder.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/NativeMavenProjectHolder.java new file mode 100644 index 000000000000..8569f96507a6 --- /dev/null +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/NativeMavenProjectHolder.java @@ -0,0 +1,8 @@ +package org.jetbrains.idea.maven.facade; + +import java.rmi.Remote; +import java.rmi.RemoteException; + +public interface NativeMavenProjectHolder extends Remote { + int getId() throws RemoteException; +} diff --git a/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/ProfileApplicationResult.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/ProfileApplicationResult.java new file mode 100644 index 000000000000..8297c26cebba --- /dev/null +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/ProfileApplicationResult.java @@ -0,0 +1,40 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.maven.facade; + +import org.jetbrains.idea.maven.model.MavenModel; +import org.jetbrains.idea.maven.model.MavenProfile; + +import java.io.Serializable; +import java.util.List; + +public class ProfileApplicationResult implements Serializable { + private final MavenModel myModel; + private final List myActivatedProfiles; + + public ProfileApplicationResult(MavenModel model, List activatedProfiles) { + myModel = model; + myActivatedProfiles = activatedProfiles; + } + + public MavenModel getModel() { + return myModel; + } + + public List getActivatedProfiles() { + return myActivatedProfiles; + } +} diff --git a/plugins/maven/facade/org/jetbrains/idea/maven/facade/remote/impl/RemoteImpl.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/RemoteObject.java similarity index 58% rename from plugins/maven/facade/org/jetbrains/idea/maven/facade/remote/impl/RemoteImpl.java rename to plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/RemoteObject.java index 4f5b944710cb..9b9531ea6c72 100644 --- a/plugins/maven/facade/org/jetbrains/idea/maven/facade/remote/impl/RemoteImpl.java +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/RemoteObject.java @@ -1,4 +1,4 @@ -package org.jetbrains.idea.maven.facade.remote.impl; +package org.jetbrains.idea.maven.facade; import com.intellij.util.containers.ContainerUtil; @@ -12,50 +12,43 @@ import java.util.Collection; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -/** - * @author Gregory.Shrago - */ -public class RemoteImpl implements Remote, Unreferenced { - private final Map myChildren = new ConcurrentHashMap(); - private final WeakReference myWeakRef; - private RemoteImpl myParent; +public abstract class RemoteObject implements Remote, Unreferenced { + private final Map myChildren = new ConcurrentHashMap(); + private final WeakReference myWeakRef; + private RemoteObject myParent; - public RemoteImpl() { - myWeakRef = new WeakReference(this); + public RemoteObject() { + myWeakRef = new WeakReference(this); } - public WeakReference getWeakRef() { + public WeakReference getWeakRef() { return myWeakRef; } protected T export(final T child) throws RemoteException { if (child == null) return null; final T result = (T)UnicastRemoteObject.exportObject(child, 0); - myChildren.put((RemoteImpl)child, result); - ((RemoteImpl)child).myParent = this; + myChildren.put((RemoteObject)child, result); + ((RemoteObject)child).myParent = this; return result; } - protected T export2(final T child) throws RemoteException { - return export(child); - } - public void unexportChildren() throws RemoteException { - final ArrayList childrenRefs = new ArrayList(myChildren.keySet()); + final ArrayList childrenRefs = new ArrayList(myChildren.keySet()); myChildren.clear(); - for (RemoteImpl child : childrenRefs) { + for (RemoteObject child : childrenRefs) { child.unreferenced(); } } - protected void unexportChildren(Collection> children) throws RemoteException { + protected void unexportChildren(Collection> children) throws RemoteException { if (children.isEmpty()) return; - final ArrayList list = new ArrayList(children.size()); - for (WeakReference child : children) { + final ArrayList list = new ArrayList(children.size()); + for (WeakReference child : children) { ContainerUtil.addIfNotNull(child.get(), list); } myChildren.keySet().removeAll(list); - for (RemoteImpl child : list) { + for (RemoteObject child : list) { child.unreferenced(); } } @@ -65,14 +58,19 @@ public class RemoteImpl implements Remote, Unreferenced { while (cause.getCause() != null) { cause = cause.getCause(); } - if (!cause.getClass().getName().startsWith("java")) { - final Throwable replaceWith = new RuntimeException(cause.toString()); - replaceWith.setStackTrace(cause.getStackTrace()); - cause = replaceWith; - } + cause = wrapException(cause); throw cause instanceof RuntimeException ? (RuntimeException)cause : new RuntimeException(cause); } + public static Throwable wrapException(Throwable ex) { + if (!ex.getClass().getName().startsWith("java")) { + final Throwable replaceWith = new RuntimeException(ex.toString()); + replaceWith.setStackTrace(ex.getStackTrace()); + ex = replaceWith; + } + return ex; + } + public Object wrapIfNeeded(Object o) throws RemoteException { if (o == null) return o; if (o.getClass().getClassLoader() == null || diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/ArchetypeInfo.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenArchetype.java similarity index 82% rename from plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/ArchetypeInfo.java rename to plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenArchetype.java index 1cde3f65f138..25736abe5ce5 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/ArchetypeInfo.java +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenArchetype.java @@ -13,29 +13,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.maven.indices; +package org.jetbrains.idea.maven.model; import com.intellij.openapi.util.text.StringUtil; -import org.apache.maven.archetype.catalog.Archetype; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class ArchetypeInfo { +import java.io.Serializable; + +public class MavenArchetype implements Serializable { public final String groupId; public final String artifactId; public final String version; public final String repository; public final String description; - public ArchetypeInfo(Archetype archetype) { - this(archetype.getGroupId(), - archetype.getArtifactId(), - archetype.getVersion(), - archetype.getRepository(), - archetype.getDescription()); - } - - public ArchetypeInfo(@NotNull String groupId, + public MavenArchetype(@NotNull String groupId, @NotNull String artifactId, @NotNull String version, @Nullable String repository, @@ -52,7 +45,7 @@ public class ArchetypeInfo { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - ArchetypeInfo that = (ArchetypeInfo)o; + MavenArchetype that = (MavenArchetype)o; if (groupId != null ? !groupId.equals(that.groupId) : that.groupId != null) return false; if (artifactId != null ? !artifactId.equals(that.artifactId) : that.artifactId != null) return false; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenArtifact.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenArtifact.java similarity index 64% rename from plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenArtifact.java rename to plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenArtifact.java index ba9f2b0c582d..a24d163340ed 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenArtifact.java +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenArtifact.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2010 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,95 +14,59 @@ * limitations under the License. */ -package org.jetbrains.idea.maven.project; +package org.jetbrains.idea.maven.model; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.JarFileSystem; -import com.intellij.openapi.vfs.VirtualFileManager; -import org.apache.maven.artifact.Artifact; -import org.apache.maven.artifact.handler.ArtifactHandler; -import org.codehaus.plexus.component.repository.ComponentDependency; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.maven.embedder.CustomArtifact; -import org.jetbrains.idea.maven.utils.MavenConstants; import java.io.File; import java.io.Serializable; import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.List; - -import static org.jetbrains.idea.maven.project.MavenId.append; public class MavenArtifact implements Serializable { - private String myGroupId; - private String myArtifactId; - private String myVersion; - private String myBaseVersion; - private String myType; - private String myClassifier; + private final String myGroupId; + private final String myArtifactId; + private final String myVersion; + private final String myBaseVersion; + private final String myType; + private final String myClassifier; private String myScope; - private boolean myOptional; + private final boolean myOptional; - private String myExtension; + private final String myExtension; - private File myFile; - private boolean myResolved; - private boolean myStubbed; - - protected MavenArtifact() { - } - - public MavenArtifact(Artifact artifact, File localRepository) { - myGroupId = artifact.getGroupId(); - myArtifactId = artifact.getArtifactId(); - myVersion = artifact.getVersion(); - myBaseVersion = artifact.getBaseVersion(); - myType = artifact.getType(); - myClassifier = artifact.getClassifier(); - - myScope = artifact.getScope(); - myOptional = artifact.isOptional(); - - myExtension = getExtension(artifact); - - myFile = artifact.getFile(); - if (myFile == null) { - myFile = new File(localRepository, getRelativePath()); - } - - myResolved = artifact.isResolved(); - myStubbed = artifact instanceof CustomArtifact && ((CustomArtifact)artifact).isStub(); - } - - public MavenArtifact(ComponentDependency dependency, File localRepository, String scope) { - myGroupId = dependency.getGroupId(); - myArtifactId = dependency.getArtifactId(); - myVersion = dependency.getVersion(); - myBaseVersion = null; - myType = dependency.getType(); - myClassifier = null; + private final File myFile; + private final boolean myResolved; + private final boolean myStubbed; + public MavenArtifact(String groupId, + String artifactId, + String version, + String baseVersion, + String type, + String classifier, + String scope, + boolean optional, + String extension, + @Nullable File file, + File localRepository, + boolean resolved, + boolean stubbed) { + myGroupId = groupId; + myArtifactId = artifactId; + myVersion = version; + myBaseVersion = baseVersion; + myType = type; + myClassifier = classifier; myScope = scope; - myOptional = false; - - myExtension = myType; - - myFile = new File(localRepository, getRelativePath()); - - myResolved = true; - myStubbed = false; - } - - private String getExtension(Artifact artifact) { - ArtifactHandler handler = artifact.getArtifactHandler(); - String result = null; - if (handler != null) result = handler.getExtension(); - if (result == null) result = artifact.getType(); - return result; + myOptional = optional; + myExtension = extension; + myFile = file != null ? file : new File(localRepository, getRelativePath()); + myResolved = resolved; + myStubbed = stubbed; } public String getGroupId() { @@ -143,7 +107,7 @@ public class MavenArtifact implements Serializable { public boolean isExportable() { if (myOptional) return false; - return Artifact.SCOPE_COMPILE.equals(myScope) || Artifact.SCOPE_RUNTIME.equals(myScope); + return MavenConstants.SCOPE_COMPILE.equals(myScope) || MavenConstants.SCOPE_RUNTIME.equals(myScope); } public String getExtension() { @@ -197,11 +161,7 @@ public class MavenArtifact implements Serializable { return result.toString(); } - public String getUrl() { - return getUrlForExtraArtifact(null, null); - } - - public String getUrlForExtraArtifact(@Nullable String extraArtifactClassifier, @Nullable String customExtension) { + public String getPathForExtraArtifact(@Nullable String extraArtifactClassifier, @Nullable String customExtension) { String path = getPath(); if (!StringUtil.isEmptyOrSpaces(extraArtifactClassifier)) { @@ -223,15 +183,15 @@ public class MavenArtifact implements Serializable { path = repoPath + getRelativePathForExtraArtifact(extraArtifactClassifier, customExtension); } } - return VirtualFileManager.constructUrl(JarFileSystem.PROTOCOL, path) + JarFileSystem.JAR_SEPARATOR; + return path; } public String getDisplayStringSimple() { StringBuilder builder = new StringBuilder(); - append(builder, myGroupId); - append(builder, myArtifactId); - append(builder, myVersion); + MavenId.append(builder, myGroupId); + MavenId.append(builder, myArtifactId); + MavenId.append(builder, myVersion); return builder.toString(); } @@ -239,10 +199,10 @@ public class MavenArtifact implements Serializable { public String getDisplayStringWithType() { StringBuilder builder = new StringBuilder(); - append(builder, myGroupId); - append(builder, myArtifactId); - append(builder, myType); - append(builder, myVersion); + MavenId.append(builder, myGroupId); + MavenId.append(builder, myArtifactId); + MavenId.append(builder, myType); + MavenId.append(builder, myVersion); return builder.toString(); } @@ -250,11 +210,11 @@ public class MavenArtifact implements Serializable { public String getDisplayStringWithTypeAndClassifier() { StringBuilder builder = new StringBuilder(); - append(builder, myGroupId); - append(builder, myArtifactId); - append(builder, myType); - if (!StringUtil.isEmptyOrSpaces(myClassifier)) append(builder, myClassifier); - append(builder, myVersion); + MavenId.append(builder, myGroupId); + MavenId.append(builder, myArtifactId); + MavenId.append(builder, myType); + if (!StringUtil.isEmptyOrSpaces(myClassifier)) MavenId.append(builder, myClassifier); + MavenId.append(builder, myVersion); return builder.toString(); } @@ -262,12 +222,12 @@ public class MavenArtifact implements Serializable { public String getDisplayStringFull() { StringBuilder builder = new StringBuilder(); - append(builder, myGroupId); - append(builder, myArtifactId); - append(builder, myType); - if (!StringUtil.isEmptyOrSpaces(myClassifier)) append(builder, myClassifier); - append(builder, myVersion); - if (!StringUtil.isEmptyOrSpaces(myScope)) append(builder, myScope); + MavenId.append(builder, myGroupId); + MavenId.append(builder, myArtifactId); + MavenId.append(builder, myType); + if (!StringUtil.isEmptyOrSpaces(myClassifier)) MavenId.append(builder, myClassifier); + MavenId.append(builder, myVersion); + if (!StringUtil.isEmptyOrSpaces(myScope)) MavenId.append(builder, myScope); return builder.toString(); } @@ -275,14 +235,14 @@ public class MavenArtifact implements Serializable { public String getDisplayStringForLibraryName() { StringBuilder builder = new StringBuilder(); - append(builder, myGroupId); - append(builder, myArtifactId); + MavenId.append(builder, myGroupId); + MavenId.append(builder, myArtifactId); - if (!StringUtil.isEmptyOrSpaces(myType) && !MavenConstants.TYPE_JAR.equals(myType)) append(builder, myType); - if (!StringUtil.isEmptyOrSpaces(myClassifier)) append(builder, myClassifier); + if (!StringUtil.isEmptyOrSpaces(myType) && !MavenConstants.TYPE_JAR.equals(myType)) MavenId.append(builder, myType); + if (!StringUtil.isEmptyOrSpaces(myClassifier)) MavenId.append(builder, myClassifier); String version = !StringUtil.isEmptyOrSpaces(myBaseVersion) ? myBaseVersion : myVersion; - if (!StringUtil.isEmptyOrSpaces(version)) append(builder, version); + if (!StringUtil.isEmptyOrSpaces(version)) MavenId.append(builder, version); return builder.toString(); } diff --git a/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenArtifactInfo.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenArtifactInfo.java new file mode 100644 index 000000000000..04a025867119 --- /dev/null +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenArtifactInfo.java @@ -0,0 +1,86 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.maven.model; + +import java.io.Serializable; + +public class MavenArtifactInfo implements Serializable { + private final String myGroupId; + private final String myArtifactId; + private final String myVersion; + private final String myPackaging; + private final String myClassifier; + private final String myClassNames; + private final String myRepositoryId; + + public MavenArtifactInfo(MavenId id, + String packaging, + String classifier) { + this(id.getGroupId(), id.getArtifactId(), id.getVersion(), packaging, classifier); + } + + public MavenArtifactInfo(String groupId, + String artifactId, + String version, + String packaging, + String classifier) { + this(groupId, artifactId, version, packaging, classifier, null, null); + } + + public MavenArtifactInfo(String groupId, + String artifactId, + String version, + String packaging, + String classifier, + String classNames, + String repositoryId) { + myGroupId = groupId; + myArtifactId = artifactId; + myVersion = version; + myPackaging = packaging; + myClassifier = classifier; + myClassNames = classNames; + myRepositoryId = repositoryId; + } + + public String getGroupId() { + return myGroupId; + } + + public String getArtifactId() { + return myArtifactId; + } + + public String getVersion() { + return myVersion; + } + + public String getPackaging() { + return myPackaging; + } + + public String getClassifier() { + return myClassifier; + } + + public String getClassNames() { + return myClassNames; + } + + public String getRepositoryId() { + return myRepositoryId; + } +} diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenArtifactNode.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenArtifactNode.java similarity index 82% rename from plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenArtifactNode.java rename to plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenArtifactNode.java index 27760ef3cf97..e7f87d623f69 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenArtifactNode.java +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenArtifactNode.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2010 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.maven.project; +package org.jetbrains.idea.maven.model; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.Function; @@ -23,23 +23,19 @@ import java.io.Serializable; import java.util.List; public class MavenArtifactNode implements Serializable { + private final MavenArtifactNode myParent; - private MavenArtifactNode myParent; + private final MavenArtifact myArtifact; + private final MavenArtifactState myState; + private final MavenArtifact myRelatedArtifact; - private MavenArtifact myArtifact; - private MavenArtifactState myState; - private MavenArtifact myRelatedArtifact; + private final String myOriginalScope; - private String myOriginalScope; - - private String myPremanagedVersion; - private String myPremanagedScope; + private final String myPremanagedVersion; + private final String myPremanagedScope; private List myDependencies; - protected MavenArtifactNode() { - } - public MavenArtifactNode(MavenArtifactNode parent, MavenArtifact artifact, MavenArtifactState state, @@ -62,7 +58,6 @@ public class MavenArtifactNode implements Serializable { } - public MavenArtifact getArtifact() { return myArtifact; } @@ -101,8 +96,10 @@ public class MavenArtifactNode implements Serializable { @Override public String toString() { - String result =myArtifact.getDisplayStringWithTypeAndClassifier(); - if (myState != MavenArtifactState.ADDED) result += "[" + myState + ":" + myRelatedArtifact.getDisplayStringWithTypeAndClassifier() + "]"; + String result = myArtifact.getDisplayStringWithTypeAndClassifier(); + if (myState != MavenArtifactState.ADDED) { + result += "[" + myState + ":" + myRelatedArtifact.getDisplayStringWithTypeAndClassifier() + "]"; + } return result += "->(" + formatNodesList(myDependencies) + ")"; } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenArtifactState.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenArtifactState.java similarity index 94% rename from plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenArtifactState.java rename to plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenArtifactState.java index aabf184d7000..6f519c809895 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenArtifactState.java +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenArtifactState.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.maven.project; +package org.jetbrains.idea.maven.model; /** * @author Konstantin Bulenkov diff --git a/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenBuild.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenBuild.java new file mode 100644 index 000000000000..e3143b3524f2 --- /dev/null +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenBuild.java @@ -0,0 +1,72 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.maven.model; + +import com.intellij.util.SmartList; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class MavenBuild extends MavenBuildBase implements Serializable { + private String myOutputDirectory; + private String myTestOutputDirectory; + private List mySources; + private List myTestSources; + + public String getOutputDirectory() { + return myOutputDirectory; + } + + public void setOutputDirectory(String outputDirectory) { + myOutputDirectory = outputDirectory; + } + + public String getTestOutputDirectory() { + return myTestOutputDirectory; + } + + public void setTestOutputDirectory(String testOutputDirectory) { + myTestOutputDirectory = testOutputDirectory; + } + + public List getSources() { + return mySources == null ? Collections.emptyList() : mySources; + } + + public void setSources(List sources) { + mySources = new ArrayList(sources); + } + + public void addSource(String source) { + if (mySources == null) mySources = new ArrayList(); + mySources.add(source); + } + + public List getTestSources() { + return myTestSources == null ? Collections.emptyList() : myTestSources; + } + + public void setTestSources(List testSources) { + myTestSources = new ArrayList(testSources); + } + + public void addTestSource(String source) { + if (myTestSources == null) myTestSources = new ArrayList(); + myTestSources.add(source); + } +} \ No newline at end of file diff --git a/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenBuildBase.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenBuildBase.java new file mode 100644 index 000000000000..c4bf944a947c --- /dev/null +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenBuildBase.java @@ -0,0 +1,77 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.maven.model; + +import java.io.Serializable; +import java.util.Collections; +import java.util.List; + +public class MavenBuildBase implements Serializable { + private String myFinalName; + private String myDefaultGoal; + private String myDirectory; + private List myResources; + private List myTestResources; + private List myFilters; + + public String getFinalName() { + return myFinalName; + } + + public void setFinalName(String finalName) { + myFinalName = finalName; + } + + public String getDefaultGoal() { + return myDefaultGoal; + } + + public void setDefaultGoal(String defaultGoal) { + myDefaultGoal = defaultGoal; + } + + public String getDirectory() { + return myDirectory; + } + + public void setDirectory(String directory) { + myDirectory = directory; + } + + public List getResources() { + return myResources == null ? Collections.emptyList() : myResources; + } + + public void setResources(List resources) { + myResources = resources; + } + + public List getTestResources() { + return myTestResources == null ? Collections.emptyList() : myTestResources; + } + + public void setTestResources(List testResources) { + myTestResources = testResources; + } + + public List getFilters() { + return myFilters == null ? Collections.emptyList() : myFilters; + } + + public void setFilters(List filters) { + myFilters = filters; + } +} \ No newline at end of file diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenConstants.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenConstants.java similarity index 58% rename from plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenConstants.java rename to plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenConstants.java index ec46dd7be7af..74e29dd5c1c4 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenConstants.java +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenConstants.java @@ -13,7 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.maven.utils; +package org.jetbrains.idea.maven.model; + +import java.util.Arrays; +import java.util.List; public class MavenConstants { public static final String POM_EXTENSION = "pom"; @@ -22,6 +25,10 @@ public class MavenConstants { public static final String PROFILES_XML = "profiles.xml"; public static final String SETTINGS_XML = "settings.xml"; + public static final String PROFILE_FROM_POM = "pom"; + public static final String PROFILE_FROM_PROFILES_XML = "profiles.xml"; + public static final String PROFILE_FROM_SETTINGS_XML = "settings.xml"; + public static final String TYPE_POM = "pom"; public static final String TYPE_JAR = "jar"; public static final String TYPE_TEST_JAR = "test-jar"; @@ -33,4 +40,16 @@ public class MavenConstants { public static final String SCOPE_TEST = "test"; public static final String SCOPE_SYSTEM = "system"; public static final String SCOPE_IMPORT = "import"; + + public static final List PHASES = + Arrays.asList("clean", "validate", "generate-sources", "process-sources", "generate-resources", + "process-resources", "compile", "process-classes", "generate-test-sources", "process-test-sources", + "generate-test-resources", + "process-test-resources", "test-compile", "test", "prepare-package", "package", "pre-integration-test", + "integration-test", + "post-integration-test", + "verify", "install", "site", "deploy"); + public static final List BASIC_PHASES = + Arrays.asList("clean", "validate", "compile", "test", "package", "install", "deploy", "site"); + } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenId.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenId.java similarity index 84% rename from plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenId.java rename to plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenId.java index cb38c558d66f..7b354ceb9f48 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenId.java +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenId.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2010 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,10 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.maven.project; - -import org.apache.maven.artifact.Artifact; -import org.apache.maven.model.Model; +package org.jetbrains.idea.maven.model; import java.io.Serializable; @@ -28,17 +25,9 @@ public class MavenId implements Serializable { private final String myVersion; public MavenId(String groupId, String artifactId, String version) { - this.myGroupId = groupId; - this.myArtifactId = artifactId; - this.myVersion = version; - } - - public MavenId(Model model) { - this(model.getGroupId(), model.getArtifactId(), model.getVersion()); - } - - public MavenId(Artifact artifact) { - this(artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion()); + myGroupId = groupId; + myArtifactId = artifactId; + myVersion = version; } public String getGroupId() { diff --git a/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenModel.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenModel.java new file mode 100644 index 000000000000..3eb8aa7d20d7 --- /dev/null +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenModel.java @@ -0,0 +1,73 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.maven.model; + +import java.util.List; + +public class MavenModel extends MavenModelBase { + private MavenId myMavenId; + private MavenParent myParent; + private String myPackaging; + private String myName; + + private List myProfiles; + + private final MavenBuild myBuild = new MavenBuild(); + + public MavenId getMavenId() { + return myMavenId; + } + + public void setMavenId(MavenId mavenId) { + myMavenId = mavenId; + } + + public MavenParent getParent() { + return myParent; + } + + public void setParent(MavenParent parent) { + myParent = parent; + } + + public String getPackaging() { + return myPackaging; + } + + public void setPackaging(String packaging) { + myPackaging = packaging; + } + + public String getName() { + return myName; + } + + public void setName(String name) { + myName = name; + } + + public List getProfiles() { + return myProfiles; + } + + public void setProfiles(List profiles) { + myProfiles = profiles; + } + + public MavenBuild getBuild() { + return myBuild; + } +} diff --git a/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenModelBase.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenModelBase.java new file mode 100644 index 000000000000..6296b2971bf5 --- /dev/null +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenModelBase.java @@ -0,0 +1,88 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.maven.model; + +import java.io.Serializable; +import java.util.List; +import java.util.Properties; + +public class MavenModelBase implements Serializable { + private Properties myProperties; + private List myPlugins; + private List myExtensions; + private List myDependencies; + private List myDependencyTree; + private List myRemoteRepositories; + + private List myModules; + + public Properties getProperties() { + if (myProperties == null) myProperties = new Properties(); + return myProperties; + } + + public void setProperties(Properties properties) { + myProperties = properties; + } + + public List getPlugins() { + return myPlugins; + } + + public void setPlugins(List plugins) { + myPlugins = plugins; + } + + public List getExtensions() { + return myExtensions; + } + + public void setExtensions(List extensions) { + myExtensions = extensions; + } + + public List getDependencies() { + return myDependencies; + } + + public void setDependencies(List dependencies) { + myDependencies = dependencies; + } + + public List getDependencyTree() { + return myDependencyTree; + } + + public void setDependencyTree(List dependencyTree) { + myDependencyTree = dependencyTree; + } + + public List getRemoteRepositories() { + return myRemoteRepositories; + } + + public void setRemoteRepositories(List remoteRepositories) { + myRemoteRepositories = remoteRepositories; + } + + public List getModules() { + return myModules; + } + + public void setModules(List modules) { + myModules = modules; + } +} diff --git a/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenParent.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenParent.java new file mode 100644 index 000000000000..b75d61e209f4 --- /dev/null +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenParent.java @@ -0,0 +1,36 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.maven.model; + +import java.io.Serializable; + +public class MavenParent implements Serializable { + private final MavenId myMavenId; + private final String myRelativePath; + + public MavenParent(MavenId id, String relativePath) { + myMavenId = id; + myRelativePath = relativePath; + } + + public MavenId getMavenId() { + return myMavenId; + } + + public String getRelativePath() { + return myRelativePath; + } +} diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenPlugin.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenPlugin.java similarity index 63% rename from plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenPlugin.java rename to plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenPlugin.java index 3f9245830bac..9f6c8efb1e84 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenPlugin.java +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenPlugin.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2010 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,80 +14,43 @@ * limitations under the License. */ -package org.jetbrains.idea.maven.project; +package org.jetbrains.idea.maven.model; import com.intellij.openapi.util.JDOMUtil; -import com.intellij.xml.util.XmlUtil; -import org.apache.maven.model.Dependency; -import org.apache.maven.model.Plugin; -import org.apache.maven.model.PluginExecution; -import org.codehaus.plexus.util.xml.Xpp3Dom; import org.jdom.Element; -import org.jdom.IllegalNameException; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.maven.utils.MavenLog; import java.io.Serializable; -import java.util.ArrayList; import java.util.List; -import static org.jetbrains.idea.maven.project.MavenId.append; +import static org.jetbrains.idea.maven.model.MavenId.append; public class MavenPlugin implements Serializable { - private String myGroupId; - private String myArtifactId; - private String myVersion; + private final String myGroupId; + private final String myArtifactId; + private final String myVersion; - private boolean myDefault; + private final boolean myDefault; - private Element myConfiguration; - private final List myExecutions = new ArrayList(); + private final Element myConfiguration; + private final List myExecutions; - private final List myDependencies = new ArrayList(); + private final List myDependencies; - protected MavenPlugin() { - } - - public MavenPlugin(Plugin plugin, boolean isDefault) { - myGroupId = plugin.getGroupId(); - myArtifactId = plugin.getArtifactId(); - myVersion = plugin.getVersion(); - - myDefault = isDefault; - - Xpp3Dom config = (Xpp3Dom)plugin.getConfiguration(); - myConfiguration = config == null ? null : xppToElement(config); - - for (PluginExecution each : plugin.getExecutions()) { - myExecutions.add(new Execution(each)); - } - - for (Dependency each : plugin.getDependencies()) { - myDependencies.add(new MavenId(each.getGroupId(), each.getArtifactId(), each.getVersion())); - } - } - - private static Element xppToElement(Xpp3Dom xpp) { - Element result = null; - try { - result = new Element(xpp.getName()); - } - catch (IllegalNameException e) { - MavenLog.LOG.warn("Cannot convert plugin configuration: " + xpp, e); - return null; - } - - Xpp3Dom[] children = xpp.getChildren(); - if (children == null || children.length == 0) { - result.setText(xpp.getValue()); - } - else { - for (Xpp3Dom each : children) { - Element child = xppToElement(each); - if (child != null) result.addContent(child); - } - } - return result; + public MavenPlugin(String groupId, + String artifactId, + String version, + boolean aDefault, + Element configuration, + List executions, + List dependencies) { + myGroupId = groupId; + myArtifactId = artifactId; + myVersion = version; + myDefault = aDefault; + myConfiguration = configuration; + myExecutions = executions; + myDependencies = dependencies; } public String getGroupId() { @@ -169,17 +132,12 @@ public class MavenPlugin implements Serializable { } public static class Execution implements Serializable { - private List myGoals; - private Element myConfiguration; + private final List myGoals; + private final Element myConfiguration; - public Execution() { - } - - public Execution(PluginExecution execution) { - myGoals = execution.getGoals(); - - Xpp3Dom config = (Xpp3Dom)execution.getConfiguration(); - myConfiguration = config == null ? null : xppToElement(config); + public Execution(List goals, Element configuration) { + myGoals = goals; + myConfiguration = configuration; } public List getGoals() { diff --git a/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenProfile.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenProfile.java new file mode 100644 index 000000000000..d4e08bf3cd61 --- /dev/null +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenProfile.java @@ -0,0 +1,54 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.maven.model; + +import org.jetbrains.annotations.NotNull; + +import java.io.Serializable; +import java.util.List; + +public class MavenProfile extends MavenModelBase implements Serializable { + private final String myId; + private final String mySource; + private MavenProfileActivation myActivation; + private final MavenBuildBase myBuild = new MavenBuildBase(); + + public MavenProfile(String id, String source) { + myId = id; + mySource = source; + } + + @NotNull + public String getId() { + return myId; + } + + public String getSource() { + return mySource; + } + + public void setActivation(MavenProfileActivation activation) { + myActivation = activation; + } + + public MavenProfileActivation getActivation() { + return myActivation; + } + + public MavenBuildBase getBuild() { + return myBuild; + } +} diff --git a/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenProfileActivation.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenProfileActivation.java new file mode 100644 index 000000000000..3643f3f20f86 --- /dev/null +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenProfileActivation.java @@ -0,0 +1,66 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.maven.model; + +import java.io.Serializable; + +public class MavenProfileActivation implements Serializable { + private boolean myActiveByDefault; + private MavenProfileActivationOS myOs; + private String myJdk; + private MavenProfileActivationProperty myProperty; + private MavenProfileActivationFile myFile; + + public boolean isActiveByDefault() { + return myActiveByDefault; + } + + public void setActiveByDefault(boolean activeByDefault) { + myActiveByDefault = activeByDefault; + } + + public MavenProfileActivationOS getOs() { + return myOs; + } + + public void setOs(MavenProfileActivationOS os) { + myOs = os; + } + + public String getJdk() { + return myJdk; + } + + public void setJdk(String jdk) { + myJdk = jdk; + } + + public MavenProfileActivationProperty getProperty() { + return myProperty; + } + + public void setProperty(MavenProfileActivationProperty property) { + myProperty = property; + } + + public MavenProfileActivationFile getFile() { + return myFile; + } + + public void setFile(MavenProfileActivationFile file) { + myFile = file; + } +} diff --git a/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenProfileActivationFile.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenProfileActivationFile.java new file mode 100644 index 000000000000..58ce8934cb1b --- /dev/null +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenProfileActivationFile.java @@ -0,0 +1,36 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.maven.model; + +import java.io.Serializable; + +public class MavenProfileActivationFile implements Serializable { + private final String myExists; + private final String myMissing; + + public MavenProfileActivationFile(String exists, String missing) { + myExists = exists; + myMissing = missing; + } + + public String getExists() { + return myExists; + } + + public String getMissing() { + return myMissing; + } +} diff --git a/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenProfileActivationOS.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenProfileActivationOS.java new file mode 100644 index 000000000000..155cf3630b3f --- /dev/null +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenProfileActivationOS.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.maven.model; + +import java.io.Serializable; + +public class MavenProfileActivationOS implements Serializable { + private final String myName; + private final String myFamily; + private final String myArch; + private final String myVersion; + + public MavenProfileActivationOS(String name, String family, String arch, String version) { + myName = name; + myFamily = family; + myArch = arch; + myVersion = version; + } + + public String getName() { + return myName; + } + + public String getFamily() { + return myFamily; + } + + public String getArch() { + return myArch; + } + + public String getVersion() { + return myVersion; + } +} diff --git a/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenProfileActivationProperty.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenProfileActivationProperty.java new file mode 100644 index 000000000000..1bd5aabef228 --- /dev/null +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenProfileActivationProperty.java @@ -0,0 +1,36 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.maven.model; + +import java.io.Serializable; + +public class MavenProfileActivationProperty implements Serializable { + private final String myName; + private final String myValue; + + public MavenProfileActivationProperty(String name, String value) { + myName = name; + myValue = value; + } + + public String getName() { + return myName; + } + + public String getValue() { + return myValue; + } +} diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProfileState.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenProfileKind.java similarity index 83% rename from plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProfileState.java rename to plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenProfileKind.java index a28e0361b402..d42ef7d89251 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProfileState.java +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenProfileKind.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2010 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,8 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.maven.project; +package org.jetbrains.idea.maven.model; -public enum MavenProfileState { +public enum MavenProfileKind { NONE, EXPLICIT, IMPLICIT } diff --git a/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenProjectProblem.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenProjectProblem.java new file mode 100644 index 000000000000..1511c142d9f2 --- /dev/null +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenProjectProblem.java @@ -0,0 +1,96 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.maven.model; + +import java.io.File; +import java.io.Serializable; +import java.text.MessageFormat; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashSet; + +public class MavenProjectProblem implements Serializable { + public enum ProblemType { + SYNTAX, STRUCTURE, DEPENDENCY, PARENT, SETTINGS_OR_PROFILES + } + + private final String myPath; + private final String myDescription; + private final ProblemType myType; + + public static MavenProjectProblem createStructureProblem(String path, String description) { + return createProblem(path, description, MavenProjectProblem.ProblemType.STRUCTURE); + } + + public static MavenProjectProblem createSyntaxProblem(String path, MavenProjectProblem.ProblemType type) { + return createProblem(path, MessageFormat.format("''{0}'' has syntax errors", new File(path).getName()) , type); + } + + public static MavenProjectProblem createProblem(String path, String description, MavenProjectProblem.ProblemType type) { + return new MavenProjectProblem(path, description, type); + } + + public static Collection createProblemsList() { + return createProblemsList(Collections.emptySet()); + } + + public static Collection createProblemsList(Collection copyThis) { + return new LinkedHashSet(copyThis); + } + + public MavenProjectProblem(String path, String description, ProblemType type) { + myPath = path; + myDescription = description; + myType = type; + } + + public String getPath() { + return myPath; + } + + public String getDescription() { + return myDescription; + } + + public ProblemType getType() { + return myType; + } + + @Override + public String toString() { + return myType + ":" + myDescription + ":" + myPath; + } + + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + MavenProjectProblem that = (MavenProjectProblem)o; + + if (!myDescription.equals(that.myDescription)) return false; + if (myType != that.myType) return false; + if (!myPath.equals(that.myPath)) return false; + + return true; + } + + public int hashCode() { + int result = myPath.hashCode(); + result = 31 * result + myDescription.hashCode(); + result = 31 * result + myType.hashCode(); + return result; + } +} diff --git a/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenRemoteRepository.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenRemoteRepository.java new file mode 100644 index 000000000000..ade0b15278bd --- /dev/null +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenRemoteRepository.java @@ -0,0 +1,115 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.maven.model; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.Serializable; + +public class MavenRemoteRepository implements Serializable { + private final String myId; + private final String myName; + private final String myUrl; + private final String myLayout; + private final Policy myReleasesPolicy; + private final Policy mySnapshotsPolicy; + + public MavenRemoteRepository(@NotNull String id, + @Nullable String name, + @NotNull String url, + @Nullable String layout, + @Nullable Policy releasesPolicy, + @Nullable Policy snapshotsPolicy) { + myId = id; + myName = name; + myUrl = url; + myLayout = layout; + myReleasesPolicy = releasesPolicy; + mySnapshotsPolicy = snapshotsPolicy; + } + + @NotNull + public String getId() { + return myId; + } + + @Nullable + public String getName() { + return myName; + } + + @NotNull + public String getUrl() { + return myUrl; + } + + @Nullable + public String getLayout() { + return myLayout; + } + + @Nullable + public Policy getReleasesPolicy() { + return myReleasesPolicy; + } + + @Nullable + public Policy getSnapshotsPolicy() { + return mySnapshotsPolicy; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + MavenRemoteRepository that = (MavenRemoteRepository)o; + + if (myId != null ? !myId.equals(that.myId) : that.myId != null) return false; + + return true; + } + + @Override + public int hashCode() { + return myId != null ? myId.hashCode() : 0; + } + + public static class Policy implements Serializable { + private final boolean myEnabled; + private final String myUpdatePolicy; + private final String myChecksumPolicy; + + public Policy(boolean enabled, String updatePolicy, String checksumPolicy) { + myEnabled = enabled; + myUpdatePolicy = updatePolicy; + myChecksumPolicy = checksumPolicy; + } + + public boolean isEnabled() { + return myEnabled; + } + + public String getUpdatePolicy() { + return myUpdatePolicy; + } + + public String getChecksumPolicy() { + return myChecksumPolicy; + } + } +} diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectModelProblem.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenRepositoryInfo.java similarity index 51% rename from plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectModelProblem.java rename to plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenRepositoryInfo.java index 64b378b79779..dd9fd21dc93b 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectModelProblem.java +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenRepositoryInfo.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2010 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,27 +13,30 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.maven.project; +package org.jetbrains.idea.maven.model; -public class MavenProjectModelProblem { - private final String myDescription; - private final boolean isCritical; +import java.io.Serializable; - public MavenProjectModelProblem(String description, boolean critical) { - myDescription = description; - isCritical = critical; +public class MavenRepositoryInfo implements Serializable { + private final String myId; + private final String myName; + private final String myUrl; + + public MavenRepositoryInfo(String id, String name, String url) { + myId = id; + myName = name; + myUrl = url; } - public String getDescription() { - return myDescription; + public String getId() { + return myId; } - public boolean isCritical() { - return isCritical; + public String getName() { + return myName; } - @Override - public String toString() { - return (isCritical ? "!!!" : "") + myDescription; + public String getUrl() { + return myUrl; } } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenResource.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenResource.java similarity index 74% rename from plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenResource.java rename to plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenResource.java index 07f139c7cf6a..2f1485934a88 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenResource.java +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/model/MavenResource.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2010 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,33 +13,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.maven.project; - -import org.apache.maven.model.Resource; +package org.jetbrains.idea.maven.model; import java.io.Serializable; -import java.util.Collections; import java.util.List; public class MavenResource implements Serializable { - private String myDirectory; - private boolean myFiltered; - private String myTargetPath; - private List myIncludes; - private List myExcludes; + private final String myDirectory; + private final boolean myFiltered; + private final String myTargetPath; + private final List myIncludes; + private final List myExcludes; - protected MavenResource() { - } - - public MavenResource(Resource resource) { - myDirectory = resource.getDirectory(); - myFiltered = resource.isFiltering(); - myTargetPath = resource.getTargetPath(); - myIncludes = resource.getIncludes(); - myExcludes = resource.getExcludes(); - - if (myIncludes == null) myIncludes = Collections.EMPTY_LIST; - if (myExcludes == null) myExcludes = Collections.EMPTY_LIST; + public MavenResource(String directory, boolean filtered, String targetPath, List includes, List excludes) { + myDirectory = directory; + myFiltered = filtered; + myTargetPath = targetPath; + myIncludes = includes; + myExcludes = excludes; } public String getDirectory() { diff --git a/plugins/maven/lib/activation-1.1.jar b/plugins/maven/facade-impl/lib/activation-1.1.jar similarity index 100% rename from plugins/maven/lib/activation-1.1.jar rename to plugins/maven/facade-impl/lib/activation-1.1.jar diff --git a/plugins/maven/lib/archetype-common-2.0-alpha-4-SNAPSHOT.jar b/plugins/maven/facade-impl/lib/archetype-common-2.0-alpha-4-SNAPSHOT.jar similarity index 100% rename from plugins/maven/lib/archetype-common-2.0-alpha-4-SNAPSHOT.jar rename to plugins/maven/facade-impl/lib/archetype-common-2.0-alpha-4-SNAPSHOT.jar diff --git a/plugins/maven/lib/classworlds-1.1.jar b/plugins/maven/facade-impl/lib/classworlds-1.1.jar similarity index 100% rename from plugins/maven/lib/classworlds-1.1.jar rename to plugins/maven/facade-impl/lib/classworlds-1.1.jar diff --git a/plugins/maven/lib/commons-beanutils.jar b/plugins/maven/facade-impl/lib/commons-beanutils.jar similarity index 100% rename from plugins/maven/lib/commons-beanutils.jar rename to plugins/maven/facade-impl/lib/commons-beanutils.jar diff --git a/plugins/maven/lib/commons-logging-1.1.1.jar b/plugins/maven/facade-impl/lib/commons-logging-1.1.1.jar similarity index 100% rename from plugins/maven/lib/commons-logging-1.1.1.jar rename to plugins/maven/facade-impl/lib/commons-logging-1.1.1.jar diff --git a/plugins/maven/lib/jaxb-api-2.1.jar b/plugins/maven/facade-impl/lib/jaxb-api-2.1.jar similarity index 100% rename from plugins/maven/lib/jaxb-api-2.1.jar rename to plugins/maven/facade-impl/lib/jaxb-api-2.1.jar diff --git a/plugins/maven/lib/jaxb-impl-2.1.10.jar b/plugins/maven/facade-impl/lib/jaxb-impl-2.1.10.jar similarity index 100% rename from plugins/maven/lib/jaxb-impl-2.1.10.jar rename to plugins/maven/facade-impl/lib/jaxb-impl-2.1.10.jar diff --git a/plugins/maven/lib/maven-2.2.1-uber.jar b/plugins/maven/facade-impl/lib/maven-2.2.1-uber.jar similarity index 100% rename from plugins/maven/lib/maven-2.2.1-uber.jar rename to plugins/maven/facade-impl/lib/maven-2.2.1-uber.jar diff --git a/plugins/maven/lib/maven-dependency-tree-1.2.jar b/plugins/maven/facade-impl/lib/maven-dependency-tree-1.2.jar similarity index 100% rename from plugins/maven/lib/maven-dependency-tree-1.2.jar rename to plugins/maven/facade-impl/lib/maven-dependency-tree-1.2.jar diff --git a/plugins/maven/facade-impl/lib/maven-embedder-1.0-SNAPSHOT.jar b/plugins/maven/facade-impl/lib/maven-embedder-1.0-SNAPSHOT.jar new file mode 100644 index 0000000000000000000000000000000000000000..259be18e5d66d3ee88b20209f23ca05f37cad339 GIT binary patch literal 24562 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%0AMYE$|Udivom*R8Z=ey5j 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 ejQ>qH4rz|EA3aSx{6jYzWWb_$8bgf literal 0 HcmV?d00001 diff --git a/plugins/maven/lib/mercury-artifact-1.0-alpha-6.jar b/plugins/maven/facade-impl/lib/mercury-artifact-1.0-alpha-6.jar similarity index 100% rename from plugins/maven/lib/mercury-artifact-1.0-alpha-6.jar rename to plugins/maven/facade-impl/lib/mercury-artifact-1.0-alpha-6.jar diff --git a/plugins/maven/lib/nexus-indexer-1.2.3.jar b/plugins/maven/facade-impl/lib/nexus-indexer-1.2.3.jar similarity index 100% rename from plugins/maven/lib/nexus-indexer-1.2.3.jar rename to plugins/maven/facade-impl/lib/nexus-indexer-1.2.3.jar diff --git a/plugins/maven/lib/plexus-utils-1.5.5.jar b/plugins/maven/facade-impl/lib/plexus-utils-1.5.5.jar similarity index 100% rename from plugins/maven/lib/plexus-utils-1.5.5.jar rename to plugins/maven/facade-impl/lib/plexus-utils-1.5.5.jar diff --git a/plugins/maven/lib/wadl-core.jar b/plugins/maven/facade-impl/lib/wadl-core.jar similarity index 100% rename from plugins/maven/lib/wadl-core.jar rename to plugins/maven/facade-impl/lib/wadl-core.jar diff --git a/plugins/maven/facade-impl/maven-facade-impl.iml b/plugins/maven/facade-impl/maven-facade-impl.iml new file mode 100644 index 000000000000..44f5bdc8b03c --- /dev/null +++ b/plugins/maven/facade-impl/maven-facade-impl.iml @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/MavenFacadeImpl.java b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/MavenFacadeImpl.java new file mode 100644 index 000000000000..457628449ae7 --- /dev/null +++ b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/MavenFacadeImpl.java @@ -0,0 +1,113 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.maven.facade; + +import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.maven.facade.embedder.MavenFacadeEmbedderImpl; +import org.jetbrains.idea.maven.facade.embedder.MavenFacadeIndexerImpl; +import org.jetbrains.idea.maven.facade.embedder.MavenModelConverter; +import org.jetbrains.idea.maven.facade.nexus.ArtifactType; +import org.jetbrains.idea.maven.facade.nexus.Endpoint; +import org.jetbrains.idea.maven.facade.nexus.RepositoryType; +import org.jetbrains.idea.maven.facade.nexus.SearchResults; +import org.jetbrains.idea.maven.model.MavenArtifactInfo; +import org.jetbrains.idea.maven.model.MavenModel; +import org.jetbrains.idea.maven.model.MavenRepositoryInfo; + +import java.io.File; +import java.math.BigInteger; +import java.rmi.RemoteException; +import java.rmi.server.UnicastRemoteObject; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; + +public class MavenFacadeImpl extends RemoteObject implements MavenFacade { + public void setLogger(MavenFacadeLogger logger) throws RemoteException { + MavenFacadeLoggerManager.setLogger(logger); + } + + public MavenFacadeEmbedder createEmbedder(MavenFacadeSettings settings) throws RemoteException { + MavenFacadeEmbedderImpl result = MavenFacadeEmbedderImpl.create(settings); + UnicastRemoteObject.exportObject(result, 0); + return result; + } + + public MavenFacadeIndexer createIndexer() throws RemoteException { + MavenFacadeIndexerImpl result = new MavenFacadeIndexerImpl(); + UnicastRemoteObject.exportObject(result, 0); + return result; + } + + public MavenModel interpolateAndAlignModel(MavenModel model, File basedir) { + return MavenFacadeEmbedderImpl.interpolateAndAlignModel(model, basedir); + } + + public MavenModel assembleInheritance(MavenModel model, MavenModel parentModel) { + return MavenFacadeEmbedderImpl.assembleInheritance(model, parentModel); + } + + public ProfileApplicationResult applyProfiles(MavenModel model, + File basedir, + Collection explicitProfiles, + Collection alwaysOnProfiles) { + return MavenFacadeEmbedderImpl.applyProfiles(model, basedir, explicitProfiles, alwaysOnProfiles); + } + + public List getRepositories(String nexusUrl) throws RemoteException { + try { + List repos = new Endpoint.Repositories(nexusUrl).getRepolistAsRepositories().getData().getRepositoriesItem(); + List result = new ArrayList(repos.size()); + for (RepositoryType repo : repos) { + if (!"maven2".equals(repo.getProvider())) continue; + result.add(MavenModelConverter.convertRepositoryInfo(repo)); + } + return result; + } + catch (Exception e) { + handleException(e); + throw new AssertionError(); + } + } + + @Nullable + public List findArtifacts(MavenArtifactInfo template, String nexusUrl) throws RemoteException { + try { + SearchResults results = new Endpoint.DataIndex(nexusUrl) + .getArtifactlistAsSearchResults(null, template.getGroupId(), template.getArtifactId(), template.getVersion(), + template.getClassifier(), template.getClassNames()); + final boolean canTrySwitchGAV = template.getArtifactId() == null && template.getGroupId() != null; + final boolean tooManyResults = results.isTooManyResults(); + if (canTrySwitchGAV && (tooManyResults || BigInteger.ZERO.equals(results.getTotalCount()))) { + results = new Endpoint.DataIndex(nexusUrl) + .getArtifactlistAsSearchResults(null, null, template.getGroupId(), template.getVersion(), + template.getClassifier(), template.getClassNames()); + } + if (tooManyResults || results.isTooManyResults()) return null; + + ArrayList result = new ArrayList(); + for (ArtifactType each : results.getData().getArtifact()) { + result.add(MavenModelConverter.convertArtifactInfo(each)); + } + return result; + } + catch (Exception ex) { + handleException(ex); + throw new AssertionError(); + } + } +} diff --git a/plugins/maven/facade/org/jetbrains/idea/maven/facade/remote/MavenFacadeLocator.java b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/MavenFacadeLocator.java similarity index 79% rename from plugins/maven/facade/org/jetbrains/idea/maven/facade/remote/MavenFacadeLocator.java rename to plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/MavenFacadeLocator.java index b6f8f052ea48..17a3c96670af 100644 --- a/plugins/maven/facade/org/jetbrains/idea/maven/facade/remote/MavenFacadeLocator.java +++ b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/MavenFacadeLocator.java @@ -1,14 +1,18 @@ -package org.jetbrains.idea.maven.facade.remote; +package org.jetbrains.idea.maven.facade; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; -import org.jetbrains.idea.maven.facade.nexus.ArtifactType; +import org.jetbrains.idea.maven.model.MavenArtifactInfo; -import java.io.*; +import java.io.File; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; import java.net.URL; import java.net.URLClassLoader; import java.nio.CharBuffer; import java.rmi.registry.LocateRegistry; +import java.util.Collections; import java.util.List; /** @@ -43,8 +47,12 @@ public class MavenFacadeLocator { result.wait(); } } - if (result.isNull()) throw new RuntimeException(); - else return Pair.create((MavenFacade)LocateRegistry.getRegistry(result.get().first).lookup(result.get().second), process); + if (result.isNull()) { + throw new RuntimeException(); + } + else { + return Pair.create((MavenFacade)LocateRegistry.getRegistry(result.get().first).lookup(result.get().second), process); + } } private static void eatOutStreams(Process process, Ref> result) throws Exception { @@ -125,26 +133,23 @@ public class MavenFacadeLocator { final Pair pair = acquireFacade(new String[]{"java", "-cp", systemPath, debug1, debug2, RemoteMavenServer.class.getName()}, null, null); final MavenFacade facade = pair.first; - final MavenFacade.MavenFacadeSettings settings = new MavenFacade.MavenFacadeSettings(); - facade.setMavenSettings(settings); final String lookup = args.length > 0 ? args[0] : "hibernate"; - System.out.println("Looking up: "+lookup); - final List result = facade.findArtifacts(createTemplate(lookup), "http://oss.sonatype.org/service/local/"); - int i=1; - for (ArtifactType type : result) { - System.out.println((++i)+". "+type.getGroupId()+":"+type.getArtifactId()+":"+type.getVersion()); + System.out.println("Looking up: " + lookup); + final List result = facade.findArtifacts(createTemplate(lookup), "http://repository.sonatype.org/service/local/"); + int i = 1; + for (MavenArtifactInfo type : result) { + System.out.println((++i) + ". " + type.getGroupId() + ":" + type.getArtifactId() + ":" + type.getVersion()); } pair.second.destroy(); System.exit(0); } - private static ArtifactType createTemplate(String coord) { - final ArtifactType template = new ArtifactType(); + private static MavenArtifactInfo createTemplate(String coord) { final String[] parts = coord.split(":"); - template.setGroupId(parts.length > 0 ? parts[0] : null); - template.setArtifactId(parts.length > 1 ? parts[1] : null); - template.setVersion(parts.length > 2 ? parts[2] : null); - return template; + return new MavenArtifactInfo(parts.length > 0 ? parts[0] : null, + parts.length > 1 ? parts[1] : null, + parts.length > 2 ? parts[2] : null, + null, null, null, null); } } diff --git a/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/MavenFacadeLoggerManager.java b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/MavenFacadeLoggerManager.java new file mode 100644 index 000000000000..6f43c766686a --- /dev/null +++ b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/MavenFacadeLoggerManager.java @@ -0,0 +1,31 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.maven.facade; + +import org.jetbrains.idea.maven.facade.embedder.MavenFacadeLoggerWrapper; + +public class MavenFacadeLoggerManager { + private static MavenFacadeLoggerWrapper myLogger; + + public static MavenFacadeLoggerWrapper getLogger() { + return myLogger; + } + + + public static void setLogger(MavenFacadeLogger logger) { + myLogger = new MavenFacadeLoggerWrapper(logger); + } +} diff --git a/plugins/maven/facade/org/jetbrains/idea/maven/facade/remote/RemoteMavenServer.java b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/RemoteMavenServer.java similarity index 93% rename from plugins/maven/facade/org/jetbrains/idea/maven/facade/remote/RemoteMavenServer.java rename to plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/RemoteMavenServer.java index bbb4223cdb72..dd53d5a269e4 100644 --- a/plugins/maven/facade/org/jetbrains/idea/maven/facade/remote/RemoteMavenServer.java +++ b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/RemoteMavenServer.java @@ -13,9 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.maven.facade.remote; - -import org.jetbrains.idea.maven.facade.remote.impl.MavenFacadeImpl; +package org.jetbrains.idea.maven.facade; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/CustomArtifact.java b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/CustomArtifact.java similarity index 97% rename from plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/CustomArtifact.java rename to plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/CustomArtifact.java index d474223b4a0b..a9ec34ca7a93 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/CustomArtifact.java +++ b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/CustomArtifact.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.maven.embedder; +package org.jetbrains.idea.maven.facade.embedder; import com.intellij.openapi.util.io.FileUtil; import gnu.trove.THashMap; @@ -25,7 +25,7 @@ import org.apache.maven.artifact.resolver.filter.ArtifactFilter; import org.apache.maven.artifact.versioning.ArtifactVersion; import org.apache.maven.artifact.versioning.OverConstrainedVersionException; import org.apache.maven.artifact.versioning.VersionRange; -import org.jetbrains.idea.maven.utils.MavenLog; +import org.jetbrains.idea.maven.facade.MavenFacadeLoggerManager; import java.io.File; import java.io.FileOutputStream; @@ -143,7 +143,7 @@ public class CustomArtifact implements Artifact { ourStubCache.put(getId(), f); } catch (IOException e) { - MavenLog.LOG.warn(e); + MavenFacadeLoggerManager.getLogger().warn(e); } finally { ourCacheWriteLock.unlock(); diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/CustomArtifactFactory.java b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/CustomArtifactFactory.java similarity index 99% rename from plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/CustomArtifactFactory.java rename to plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/CustomArtifactFactory.java index 2aacb9eda2a7..aaecc85738ab 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/CustomArtifactFactory.java +++ b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/CustomArtifactFactory.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.maven.embedder; +package org.jetbrains.idea.maven.facade.embedder; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.versioning.VersionRange; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/CustomArtifactResolver.java b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/CustomArtifactResolver.java similarity index 84% rename from plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/CustomArtifactResolver.java rename to plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/CustomArtifactResolver.java index 7e8f8d425379..c7b578cd4e7f 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/CustomArtifactResolver.java +++ b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/CustomArtifactResolver.java @@ -13,26 +13,25 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.maven.embedder; +package org.jetbrains.idea.maven.facade.embedder; -import com.intellij.openapi.vfs.VirtualFile; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.artifact.resolver.AbstractArtifactResolutionException; import org.apache.maven.artifact.resolver.ArtifactNotFoundException; import org.apache.maven.artifact.resolver.ArtifactResolutionException; import org.apache.maven.artifact.resolver.DefaultArtifactResolver; -import org.jetbrains.idea.maven.project.MavenId; +import org.jetbrains.idea.maven.model.MavenId; import java.io.File; import java.util.List; import java.util.Map; public class CustomArtifactResolver extends DefaultArtifactResolver { - private Map myProjectIdToFileMap; + private Map myProjectIdToFileMap; private UnresolvedArtifactsCollector myUnresolvedCollector; - public void customize(Map projectIdToFileMap, boolean failOnUnresolved) { + public void customize(Map projectIdToFileMap, boolean failOnUnresolved) { myProjectIdToFileMap = projectIdToFileMap; myUnresolvedCollector = new UnresolvedArtifactsCollector(failOnUnresolved); } @@ -71,15 +70,15 @@ public class CustomArtifactResolver extends DefaultArtifactResolver { } private boolean resolveAsModule(Artifact a) { - // method is called from different threads, so we have to copy the reference so ensure there is no race cconditions. - Map map = myProjectIdToFileMap; + // method is called from different threads, so we have to copy the reference so ensure there is no race conditions. + Map map = myProjectIdToFileMap; if (map == null) return false; - VirtualFile file = map.get(new MavenId(a)); + File file = map.get(MavenModelConverter.createMavenId(a)); if (file == null) return false; a.setResolved(true); - a.setFile(new File(file.getPath())); + a.setFile(file); return true; } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/CustomModelInterpolator.java b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/CustomModelInterpolator.java similarity index 97% rename from plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/CustomModelInterpolator.java rename to plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/CustomModelInterpolator.java index 154074a281d9..da173c05e560 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/CustomModelInterpolator.java +++ b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/CustomModelInterpolator.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.maven.embedder; +package org.jetbrains.idea.maven.facade.embedder; import org.apache.maven.model.Model; import org.apache.maven.project.ProjectBuilderConfiguration; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/CustomWagonManager.java b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/CustomWagonManager.java similarity index 99% rename from plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/CustomWagonManager.java rename to plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/CustomWagonManager.java index bfb89a87c51e..73d4d8f8289d 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/CustomWagonManager.java +++ b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/CustomWagonManager.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.maven.embedder; +package org.jetbrains.idea.maven.facade.embedder; import gnu.trove.THashMap; import org.apache.maven.artifact.Artifact; diff --git a/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/ExecutorManager.java b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/ExecutorManager.java new file mode 100644 index 000000000000..ad085bcb71de --- /dev/null +++ b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/ExecutorManager.java @@ -0,0 +1,27 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.maven.facade.embedder; + +import java.util.concurrent.*; + +public class ExecutorManager { + private final static ExecutorService myExecutor = new ThreadPoolExecutor(3, Integer.MAX_VALUE, 30 * 60L, TimeUnit.SECONDS, + new SynchronousQueue()); + + public static Future execute(Runnable r) { + return myExecutor.submit(r); + } +} diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/FieldAccessor.java b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/FieldAccessor.java similarity index 96% rename from plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/FieldAccessor.java rename to plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/FieldAccessor.java index 72ad744ea383..5514a2fd9c5d 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/FieldAccessor.java +++ b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/FieldAccessor.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.maven.embedder; +package org.jetbrains.idea.maven.facade.embedder; import java.lang.reflect.Field; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/MavenLogger.java b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenFacadeConsoleWrapper.java similarity index 61% rename from plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/MavenLogger.java rename to plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenFacadeConsoleWrapper.java index 10e869b059f1..c57d9fae1d56 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/MavenLogger.java +++ b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenFacadeConsoleWrapper.java @@ -15,48 +15,58 @@ * ========================================================================= */ -package org.jetbrains.idea.maven.embedder; +package org.jetbrains.idea.maven.facade.embedder; import org.codehaus.plexus.logging.Logger; +import org.jetbrains.idea.maven.facade.MavenFacadeConsole; -public class MavenLogger implements Logger { - private MavenConsole myConsole; +import java.rmi.RemoteException; + +public class MavenFacadeConsoleWrapper implements Logger { + private static final String LINE_SEPARATOR = System.getProperty("line.separator"); + + private MavenFacadeConsole myWrappee; private int myThreshold; void doPrint(int level, String message, Throwable throwable) { if (level < myThreshold) return; - if (!message.endsWith(MavenConsole.LINE_SEPARATOR)) { - message += MavenConsole.LINE_SEPARATOR; + if (!message.endsWith(LINE_SEPARATOR)) { + message += LINE_SEPARATOR; } - if (myConsole != null) { - myConsole.printMessage(level, message, throwable); + if (myWrappee != null) { + try { + myWrappee.printMessage(level, message, throwable); + } + catch (RemoteException e) { + throw new RuntimeException(e); + } } } - public void setConsole(MavenConsole console) { - myConsole = console; + public void setWrappee(MavenFacadeConsole wrappee) { + myWrappee = wrappee; } public void debug(String string, Throwable throwable) { - doPrint(MavenConsole.LEVEL_DEBUG, string, throwable); + doPrint(MavenFacadeConsole.LEVEL_DEBUG, string, throwable); } public void info(String string, Throwable throwable) { - doPrint(MavenConsole.LEVEL_INFO, string, throwable); + doPrint(MavenFacadeConsole.LEVEL_INFO, string, throwable); } public void warn(String string, Throwable throwable) { - doPrint(MavenConsole.LEVEL_WARN, string, throwable); + doPrint(MavenFacadeConsole.LEVEL_WARN, string, throwable); } public void error(String string, Throwable throwable) { - doPrint(MavenConsole.LEVEL_ERROR, string, throwable); + doPrint(MavenFacadeConsole.LEVEL_ERROR, string, throwable); } public void fatalError(String string, Throwable throwable) { - doPrint(MavenConsole.LEVEL_FATAL, string, throwable); + doPrint(MavenFacadeConsole.LEVEL_FATAL, string, throwable); } public void debug(String message) { @@ -64,7 +74,7 @@ public class MavenLogger implements Logger { } public boolean isDebugEnabled() { - return getThreshold() <= MavenConsole.LEVEL_DEBUG; + return getThreshold() <= MavenFacadeConsole.LEVEL_DEBUG; } public void info(String message) { @@ -72,7 +82,7 @@ public class MavenLogger implements Logger { } public boolean isInfoEnabled() { - return getThreshold() <= MavenConsole.LEVEL_INFO; + return getThreshold() <= MavenFacadeConsole.LEVEL_INFO; } public void warn(String message) { @@ -80,7 +90,7 @@ public class MavenLogger implements Logger { } public boolean isWarnEnabled() { - return getThreshold() <= MavenConsole.LEVEL_WARN; + return getThreshold() <= MavenFacadeConsole.LEVEL_WARN; } public void error(String message) { @@ -88,7 +98,7 @@ public class MavenLogger implements Logger { } public boolean isErrorEnabled() { - return getThreshold() <= MavenConsole.LEVEL_ERROR; + return getThreshold() <= MavenFacadeConsole.LEVEL_ERROR; } public void fatalError(String message) { @@ -96,7 +106,7 @@ public class MavenLogger implements Logger { } public boolean isFatalErrorEnabled() { - return getThreshold() <= MavenConsole.LEVEL_FATAL; + return getThreshold() <= MavenFacadeConsole.LEVEL_FATAL; } public void setThreshold(int threshold) { diff --git a/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenFacadeEmbedderImpl.java b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenFacadeEmbedderImpl.java new file mode 100644 index 000000000000..c900a0a13d12 --- /dev/null +++ b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenFacadeEmbedderImpl.java @@ -0,0 +1,626 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.maven.facade.embedder; + +import com.intellij.openapi.progress.ProcessCanceledException; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.Ref; +import com.intellij.util.Function; +import gnu.trove.THashMap; +import gnu.trove.THashSet; +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.InvalidRepositoryException; +import org.apache.maven.artifact.factory.ArtifactFactory; +import org.apache.maven.artifact.manager.WagonManager; +import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.artifact.repository.ArtifactRepositoryFactory; +import org.apache.maven.artifact.resolver.ArtifactNotFoundException; +import org.apache.maven.artifact.resolver.ArtifactResolutionException; +import org.apache.maven.artifact.resolver.ArtifactResolver; +import org.apache.maven.artifact.resolver.ResolutionListener; +import org.apache.maven.model.Activation; +import org.apache.maven.model.Model; +import org.apache.maven.model.Plugin; +import org.apache.maven.model.Profile; +import org.apache.maven.plugin.PluginManager; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.profiles.activation.*; +import org.apache.maven.project.*; +import org.apache.maven.project.artifact.ProjectArtifactFactory; +import org.apache.maven.project.inheritance.DefaultModelInheritanceAssembler; +import org.apache.maven.project.injection.DefaultProfileInjector; +import org.apache.maven.project.interpolation.AbstractStringBasedModelInterpolator; +import org.apache.maven.project.interpolation.ModelInterpolationException; +import org.apache.maven.project.interpolation.ModelInterpolator; +import org.apache.maven.project.path.DefaultPathTranslator; +import org.apache.maven.project.path.PathTranslator; +import org.apache.maven.project.validation.ModelValidationResult; +import org.apache.maven.shared.dependency.tree.DependencyNode; +import org.apache.maven.shared.dependency.tree.DependencyTreeResolutionListener; +import org.codehaus.plexus.PlexusContainer; +import org.codehaus.plexus.component.repository.ComponentDependency; +import org.codehaus.plexus.context.ContextException; +import org.codehaus.plexus.context.DefaultContext; +import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.maven.facade.*; +import org.jetbrains.idea.maven.model.*; +import org.jetbrains.maven.embedder.MavenEmbedder; +import org.jetbrains.maven.embedder.MavenEmbedderSettings; +import org.jetbrains.maven.embedder.MavenExecutionResult; +import org.jetbrains.maven.embedder.PlexusComponentConfigurator; + +import java.io.File; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.rmi.RemoteException; +import java.rmi.server.RemoteObject; +import java.rmi.server.UnicastRemoteObject; +import java.util.*; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class MavenFacadeEmbedderImpl extends RemoteObject implements MavenFacadeEmbedder { + private final MavenEmbedder myImpl; + private final MavenFacadeConsoleWrapper myConsoleWrapper; + private volatile MavenFacadeProgressIndicator myCurrentIndicator; + + public static MavenFacadeEmbedderImpl create(MavenFacadeSettings facadeSettings) { + MavenEmbedderSettings settings = new MavenEmbedderSettings(); + + settings.setConfigurator(new PlexusComponentConfigurator() { + public void configureComponents(@NotNull PlexusContainer c) { + setupContainer(c); + } + }); + MavenFacadeConsoleWrapper consoleWrapper = new MavenFacadeConsoleWrapper(); + consoleWrapper.setThreshold(facadeSettings.getLoggingLevel()); + settings.setLogger(consoleWrapper); + settings.setRecursive(false); + + settings.setWorkOffline(facadeSettings.isOffline()); + settings.setUsePluginRegistry(false); + + settings.setMavenHome(facadeSettings.getMavenHome()); + settings.setUserSettingsFile(facadeSettings.getUserSettingsFile()); + settings.setGlobalSettingsFile(facadeSettings.getGlobalSettingsFile()); + settings.setLocalRepository(facadeSettings.getLocalRepository()); + + settings.setSnapshotUpdatePolicy(convertUpdatePolicy(facadeSettings.getSnapshotUpdatePolicy())); + settings.setPluginUpdatePolicy(convertUpdatePolicy(facadeSettings.getPluginUpdatePolicy())); + settings.setProperties(MavenFacadeUtil.collectSystemProperties()); + + return new MavenFacadeEmbedderImpl(MavenEmbedder.create(settings), consoleWrapper); + } + + private static MavenEmbedderSettings.UpdatePolicy convertUpdatePolicy(MavenFacadeSettings.UpdatePolicy policy) { + switch (policy) { + case ALWAYS_UPDATE: + return MavenEmbedderSettings.UpdatePolicy.ALWAYS_UPDATE; + case DO_NOT_UPDATE: + return MavenEmbedderSettings.UpdatePolicy.DO_NOT_UPDATE; + default: + MavenFacadeLoggerManager.getLogger().error(new Throwable("unexpected update policy")); + } + return MavenEmbedderSettings.UpdatePolicy.DO_NOT_UPDATE; + } + + private MavenFacadeEmbedderImpl(MavenEmbedder impl, MavenFacadeConsoleWrapper consoleWrapper) { + myImpl = impl; + myConsoleWrapper = consoleWrapper; + } + + @NotNull + public MavenWrapperExecutionResult resolveProject(@NotNull final File file, + @NotNull final Collection activeProfiles) + throws MavenFacadeProcessCanceledException { + return doExecute(new Executor() { + public MavenWrapperExecutionResult execute() throws Exception { + DependencyTreeResolutionListener listener = new DependencyTreeResolutionListener(myConsoleWrapper); + MavenExecutionResult result = myImpl.resolveProject(file, + new ArrayList(activeProfiles), + Arrays.asList(listener)); + return createExecutionResult(file, result, listener.getRootNode()); + } + }); + } + + @NotNull + private MavenWrapperExecutionResult createExecutionResult(File file, MavenExecutionResult result, DependencyNode rootNode) { + Collection problems = MavenProjectProblem.createProblemsList(); + THashSet unresolvedArtifacts = new THashSet(); + + validate(file, result.getExceptions(), problems, unresolvedArtifacts); + + MavenProject mavenProject = result.getMavenProject(); + if (mavenProject == null) return new MavenWrapperExecutionResult(null, problems, unresolvedArtifacts); + + MavenModel model = MavenModelConverter.convertModel(mavenProject.getModel(), + mavenProject.getCompileSourceRoots(), + mavenProject.getTestCompileSourceRoots(), + mavenProject.getArtifacts(), + (rootNode == null ? Collections.emptyList() : rootNode.getChildren()), + mavenProject.getExtensionArtifacts(), + getLocalRepositoryFile()); + + Collection activatedProfiles = MavenModelConverter.convertProfiles(mavenProject.getActiveProfiles()); + + RemoteNativeMavenProjectHolder holder = new RemoteNativeMavenProjectHolder(mavenProject); + try { + UnicastRemoteObject.exportObject(holder, 0); + } + catch (RemoteException e) { + throw new RuntimeException(e); + } + + MavenWrapperExecutionResult.ProjectData data = new MavenWrapperExecutionResult.ProjectData( + model, MavenModelConverter.convertToMap(mavenProject.getModel()), holder, activatedProfiles); + return new MavenWrapperExecutionResult(data, problems, unresolvedArtifacts); + } + + @NotNull + public MavenArtifact resolve(@NotNull final MavenArtifactInfo info, + @NotNull final List remoteRepositories) throws MavenFacadeProcessCanceledException { + return doExecute(new Executor() { + public MavenArtifact execute() throws Exception { + return doResolve(info, remoteRepositories); + } + }); + } + + @NotNull + public List resolveTransitively( + @NotNull final List artifacts, + @NotNull final List remoteRepositories) { + + Set toResolve = new LinkedHashSet(); + for (MavenArtifactInfo each : artifacts) { + toResolve.add(createArtifact(each)); + } + try { + return MavenModelConverter.convertArtifacts(myImpl.resolveTransitively(toResolve, convertRepositories(remoteRepositories)), + new THashMap(), getLocalRepositoryFile()); + } + catch (ArtifactResolutionException e) { + MavenFacadeLoggerManager.getLogger().info(e); + } + catch (ArtifactNotFoundException e) { + MavenFacadeLoggerManager.getLogger().info(e); + } + return Collections.emptyList(); + } + + private MavenArtifact doResolve(MavenArtifactInfo info, List remoteRepositories) { + Artifact resolved = doResolve(createArtifact(info), convertRepositories(remoteRepositories)); + return MavenModelConverter.convertArtifact(resolved, getLocalRepositoryFile()); + } + + private Artifact createArtifact(MavenArtifactInfo info) { + return getComponent(ArtifactFactory.class).createArtifactWithClassifier(info.getGroupId(), + info.getArtifactId(), + info.getVersion(), + info.getPackaging(), + info.getClassifier()); + } + + private Artifact doResolve(Artifact artifact, List remoteRepositories) { + try { + myImpl.resolve(artifact, remoteRepositories); + return artifact; + } + catch (Exception e) { + MavenFacadeLoggerManager.getLogger().info(e); + } + return artifact; + } + + private List convertRepositories(List repositories) { + List result = new ArrayList(); + for (MavenRemoteRepository each : repositories) { + try { + ArtifactRepositoryFactory factory = getComponent(ArtifactRepositoryFactory.class); + result.add(ProjectUtils.buildArtifactRepository(MavenModelConverter.toNativeRepository(each), factory, getContainer())); + } + catch (InvalidRepositoryException e) { + MavenFacadeLoggerManager.getLogger().warn(e); + } + } + return result; + } + + public Collection resolvePlugin(@NotNull final MavenPlugin plugin, + @NotNull final List repositories, + final int nativeMavenProjectId, + final boolean transitive) throws MavenFacadeProcessCanceledException { + return doExecute(new Executor>() { + public Collection execute() throws Exception { + try { + Plugin mavenPlugin = new Plugin(); + mavenPlugin.setGroupId(plugin.getGroupId()); + mavenPlugin.setArtifactId(plugin.getArtifactId()); + mavenPlugin.setVersion(plugin.getVersion()); + MavenProject project = RemoteNativeMavenProjectHolder.findprojectById(nativeMavenProjectId); + PluginDescriptor result = getComponent(PluginManager.class).verifyPlugin(mavenPlugin, project, + myImpl.getSettings(), myImpl.getLocalRepository()); + if (!transitive) return Collections.emptyList(); + + // todo try to use parallel downloading + + Map resolvedArtifacts = new THashMap(); + for (Artifact each : (Iterable)result.getIntroducedDependencyArtifacts()) { + resolveIfNecessary(new MavenArtifactInfo(each.getGroupId(), each.getArtifactId(), each.getVersion(), each.getType(), null), + repositories, resolvedArtifacts); + } + for (ComponentDependency each : (List)result.getDependencies()) { + resolveIfNecessary(new MavenArtifactInfo(each.getGroupId(), each.getArtifactId(), each.getVersion(), each.getType(), null), + repositories, resolvedArtifacts); + } + return new THashSet(resolvedArtifacts.values()); + } + catch (Exception e) { + MavenFacadeLoggerManager.getLogger().info(e); + return Collections.emptyList(); + } + } + }); + } + + private void resolveIfNecessary(MavenArtifactInfo info, + List repos, + Map resolvedArtifacts) { + if (resolvedArtifacts.containsKey(info)) return; + resolvedArtifacts.put(info, doResolve(info, repos)); + } + + @NotNull + public MavenWrapperExecutionResult execute(@NotNull final File file, + @NotNull final Collection activeProfiles, + @NotNull final List goals) + throws MavenFacadeProcessCanceledException { + return doExecute(new Executor() { + public MavenWrapperExecutionResult execute() throws Exception { + MavenExecutionResult result = myImpl.execute(file, new ArrayList(activeProfiles), goals); + return createExecutionResult(file, result, null); + } + }); + } + + private void validate(File file, + Collection exceptions, + Collection problems, + Collection unresolvedArtifacts) { + for (Exception each : exceptions) { + MavenFacadeLoggerManager.getLogger().info(each); + + if (each instanceof InvalidProjectModelException) { + ModelValidationResult modelValidationResult = ((InvalidProjectModelException)each).getValidationResult(); + if (modelValidationResult != null) { + for (Object eachValidationProblem : modelValidationResult.getMessages()) { + problems.add(MavenProjectProblem.createStructureProblem(file.getPath(), (String)eachValidationProblem)); + } + } + else { + problems.add(MavenProjectProblem.createStructureProblem(file.getPath(), each.getCause().getMessage())); + } + } + else if (each instanceof ProjectBuildingException) { + String causeMessage = each.getCause() != null ? each.getCause().getMessage() : each.getMessage(); + problems.add(MavenProjectProblem.createStructureProblem(file.getPath(), causeMessage)); + } + else { + problems.add(MavenProjectProblem.createStructureProblem(file.getPath(), each.getMessage())); + } + } + unresolvedArtifacts.addAll(retrieveUnresolvedArtifactIds()); + } + + private Set retrieveUnresolvedArtifactIds() { + Set result = new THashSet(); + ((CustomWagonManager)getComponent(WagonManager.class)).getUnresolvedCollector().retrieveUnresolvedIds(result); + ((CustomArtifactResolver)getComponent(ArtifactResolver.class)).getUnresolvedCollector().retrieveUnresolvedIds(result); + return result; + } + + public static MavenModel interpolateAndAlignModel(MavenModel model, File basedir) { + Model result = MavenModelConverter.toNativeModel(model); + result = doInterpolate(result, basedir); + + PathTranslator pathTranslator = new DefaultPathTranslator(); + pathTranslator.alignToBaseDirectory(result, basedir); + + return MavenModelConverter.convertModel(result, null); + } + + private static Model doInterpolate(Model result, File basedir) { + try { + AbstractStringBasedModelInterpolator interpolator = new CustomModelInterpolator(new DefaultPathTranslator()); + interpolator.initialize(); + + Properties props = MavenFacadeUtil.collectSystemProperties(); + ProjectBuilderConfiguration config = new DefaultProjectBuilderConfiguration().setExecutionProperties(props); + result = interpolator.interpolate(result, basedir, config, false); + } + catch (ModelInterpolationException e) { + MavenFacadeLoggerManager.getLogger().warn(e); + } + catch (InitializationException e) { + MavenFacadeLoggerManager.getLogger().error(e); + } + return result; + } + + public static MavenModel assembleInheritance(MavenModel model, MavenModel parentModel) { + Model result = MavenModelConverter.toNativeModel(model); + new DefaultModelInheritanceAssembler().assembleModelInheritance(result, MavenModelConverter.toNativeModel(parentModel)); + return MavenModelConverter.convertModel(result, null); + } + + public static ProfileApplicationResult applyProfiles(MavenModel model, + File basedir, + Collection explicitProfiles, + Collection alwaysOnProfiles) { + Model nativeModel = MavenModelConverter.toNativeModel(model); + + List activatedPom = new ArrayList(); + List activatedExternal = new ArrayList(); + List activeByDefault = new ArrayList(); + + List rawProfiles = nativeModel.getProfiles(); + List expandedProfilesCache = null; + + for (int i = 0; i < rawProfiles.size(); i++) { + Profile eachRawProfile = rawProfiles.get(i); + + boolean shouldAdd = explicitProfiles.contains(eachRawProfile.getId()) || alwaysOnProfiles.contains(eachRawProfile.getId()); + + Activation activation = eachRawProfile.getActivation(); + if (activation != null) { + if (activation.isActiveByDefault()) { + activeByDefault.add(eachRawProfile); + } + + // expand only if necessary + if (expandedProfilesCache == null) expandedProfilesCache = doInterpolate(nativeModel, basedir).getProfiles(); + Profile eachExpandedProfile = expandedProfilesCache.get(i); + + for (ProfileActivator eachActivator : getProfileActivators()) { + try { + if (eachActivator.canDetermineActivation(eachExpandedProfile) && eachActivator.isActive(eachExpandedProfile)) { + shouldAdd = true; + break; + } + } + catch (ProfileActivationException e) { + MavenFacadeLoggerManager.getLogger().warn(e); + } + } + } + + if (shouldAdd) { + if (MavenConstants.PROFILE_FROM_POM.equals(eachRawProfile.getSource())) { + activatedPom.add(eachRawProfile); + } + else { + activatedExternal.add(eachRawProfile); + } + } + } + + List activatedProfiles = new ArrayList(activatedPom.isEmpty() ? activeByDefault : activatedPom); + activatedProfiles.addAll(activatedExternal); + + for (Profile each : activatedProfiles) { + new DefaultProfileInjector().inject(each, nativeModel); + } + + return new ProfileApplicationResult(MavenModelConverter.convertModel(nativeModel, null), + MavenModelConverter.convertProfiles(activatedProfiles)); + } + + private static ProfileActivator[] getProfileActivators() { + SystemPropertyProfileActivator sysPropertyActivator = new SystemPropertyProfileActivator(); + DefaultContext context = new DefaultContext(); + context.put("SystemProperties", MavenFacadeUtil.collectSystemProperties()); + try { + sysPropertyActivator.contextualize(context); + } + catch (ContextException e) { + MavenFacadeLoggerManager.getLogger().error(e); + return new ProfileActivator[0]; + } + + return new ProfileActivator[]{new FileProfileActivator(), + sysPropertyActivator, + new JdkPrefixProfileActivator(), + new OperatingSystemProfileActivator()}; + } + + @NotNull + public File getLocalRepositoryFile() { + return myImpl.getLocalRepositoryFile(); + } + + public T getComponent(Class clazz) { + return myImpl.getComponent(clazz); + } + + public T getComponent(Class clazz, String roleHint) { + return myImpl.getComponent(clazz, roleHint); + } + + public PlexusContainer getContainer() { + return myImpl.getContainer(); + } + + private interface Executor { + T execute() throws Exception; + + } + + private T doExecute(final Executor executor) throws MavenFacadeProcessCanceledException { + final Ref result = new Ref(); + final boolean[] cancelled = new boolean[1]; + final Throwable[] exception = new Throwable[1]; + + Future future = ExecutorManager.execute(new Runnable() { + public void run() { + try { + result.set(executor.execute()); + } + catch (ProcessCanceledException e) { + cancelled[0] = true; + } + catch (Throwable e) { + exception[0] = e; + } + } + }); + + MavenFacadeProgressIndicator indicator = myCurrentIndicator; + while (true) { + boolean canceled = false; + try { + canceled = indicator.isCanceled(); + } + catch (RemoteException e) { + throw new RuntimeException(e); + } + if (canceled) throw new MavenFacadeProcessCanceledException(); + try { + future.get(50, TimeUnit.MILLISECONDS); + } + catch (TimeoutException ignore) { + } + catch (ExecutionException e) { + throw new RuntimeException(e.getCause()); + } + catch (InterruptedException e) { + throw new MavenFacadeProcessCanceledException(); + } + + if (future.isDone()) break; + } + + if (cancelled[0]) throw new MavenFacadeProcessCanceledException(); + if (exception[0] != null) { + throw getRethrowable(exception[0]); + } + + return result.get(); + } + + private RuntimeException getRethrowable(Throwable throwable) { + if (throwable instanceof InvocationTargetException) throwable = throwable.getCause(); + if (throwable instanceof RuntimeException) return (RuntimeException)throwable; + return new RuntimeException(throwable); + } + + private static void setupContainer(PlexusContainer c) { + MavenEmbedder.setImplementation(c, ArtifactFactory.class, CustomArtifactFactory.class); + MavenEmbedder.setImplementation(c, ProjectArtifactFactory.class, CustomArtifactFactory.class); + MavenEmbedder.setImplementation(c, ArtifactResolver.class, CustomArtifactResolver.class); + MavenEmbedder.setImplementation(c, WagonManager.class, CustomWagonManager.class); + MavenEmbedder.setImplementation(c, ModelInterpolator.class, CustomModelInterpolator.class); + } + + public void customizeForResolve(MavenFacadeConsole console, MavenFacadeProgressIndicator process) { + doCustomize(null, false, console, process); + } + + public void customizeForResolve(Map projectIdToFileMap, MavenFacadeConsole console, MavenFacadeProgressIndicator process) { + doCustomize(projectIdToFileMap, false, console, process); + } + + public void customizeForStrictResolve(Map projectIdToFileMap, + MavenFacadeConsole console, + MavenFacadeProgressIndicator process) { + doCustomize(projectIdToFileMap, true, console, process); + } + + private void doCustomize(Map projectIdToFileMap, + boolean strict, + MavenFacadeConsole logger, + MavenFacadeProgressIndicator process) { + ((CustomArtifactFactory)getComponent(ArtifactFactory.class)).customize(); + ((CustomArtifactFactory)getComponent(ProjectArtifactFactory.class)).customize(); + ((CustomArtifactResolver)getComponent(ArtifactResolver.class)).customize(projectIdToFileMap, strict); + ((CustomWagonManager)getComponent(WagonManager.class)).customize(strict); + + setConsoleAndLogger(logger, process); + } + + private void setConsoleAndLogger(MavenFacadeConsole logger, MavenFacadeProgressIndicator process) { + myCurrentIndicator = process; + myConsoleWrapper.setWrappee(logger); + + WagonManager wagon = getComponent(WagonManager.class); + wagon.setDownloadMonitor(process == null ? null : new TransferListenerAdapter(new MavenFacadeProgressIndicatorWrapper(process))); + } + + public void reset() { + setConsoleAndLogger(null, null); + + ((CustomArtifactFactory)getComponent(ProjectArtifactFactory.class)).reset(); + ((CustomArtifactFactory)getComponent(ArtifactFactory.class)).reset(); + ((CustomArtifactResolver)getComponent(ArtifactResolver.class)).reset(); + ((CustomWagonManager)getComponent(WagonManager.class)).reset(); + } + + public void release() { + myImpl.release(); + } + + public void clearCaches() { + withProjectCachesDo(new Function() { + public Object fun(Map map) { + map.clear(); + return null; + } + }); + } + + public void clearCachesFor(final MavenId projectId) { + withProjectCachesDo(new Function() { + public Object fun(Map map) { + map.remove(projectId.getKey()); + return null; + } + }); + } + + private void withProjectCachesDo(Function func) { + MavenProjectBuilder builder = myImpl.getComponent(MavenProjectBuilder.class); + Field field; + try { + field = builder.getClass().getDeclaredField("rawProjectCache"); + field.setAccessible(true); + func.fun(((Map)field.get(builder))); + + field = builder.getClass().getDeclaredField("processedProjectCache"); + field.setAccessible(true); + func.fun(((Map)field.get(builder))); + } + catch (NoSuchFieldException e) { + MavenFacadeLoggerManager.getLogger().info(e); + } + catch (IllegalAccessException e) { + MavenFacadeLoggerManager.getLogger().info(e); + } + } +} + diff --git a/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenFacadeIndexerImpl.java b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenFacadeIndexerImpl.java new file mode 100644 index 000000000000..a67c97653f1a --- /dev/null +++ b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenFacadeIndexerImpl.java @@ -0,0 +1,296 @@ +/* +* Copyright 2000-2010 JetBrains s.r.o. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package org.jetbrains.idea.maven.facade.embedder; + +import com.intellij.openapi.util.text.StringUtil; +import gnu.trove.THashSet; +import gnu.trove.TIntObjectHashMap; +import org.apache.lucene.document.Document; +import org.apache.lucene.index.IndexReader; +import org.apache.lucene.search.BooleanQuery; +import org.apache.lucene.search.Query; +import org.apache.lucene.search.TopDocs; +import org.apache.maven.archetype.catalog.Archetype; +import org.apache.maven.archetype.catalog.ArchetypeCatalog; +import org.apache.maven.archetype.source.ArchetypeDataSource; +import org.apache.maven.archetype.source.ArchetypeDataSourceException; +import org.apache.maven.artifact.manager.WagonManager; +import org.apache.maven.wagon.events.TransferEvent; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.maven.facade.*; +import org.jetbrains.idea.maven.facade.RemoteObject; +import org.jetbrains.idea.maven.model.MavenArchetype; +import org.jetbrains.idea.maven.model.MavenArtifactInfo; +import org.jetbrains.idea.maven.model.MavenId; +import org.sonatype.nexus.index.*; +import org.sonatype.nexus.index.context.IndexUtils; +import org.sonatype.nexus.index.context.IndexingContext; +import org.sonatype.nexus.index.context.UnsupportedExistingLuceneIndexException; +import org.sonatype.nexus.index.updater.IndexUpdateRequest; +import org.sonatype.nexus.index.updater.IndexUpdater; + +import java.io.File; +import java.io.IOException; +import java.util.*; + +public class MavenFacadeIndexerImpl extends RemoteObject implements MavenFacadeIndexer { + private MavenFacadeEmbedderImpl myEmbedder; + private final NexusIndexer myIndexer; + private final IndexUpdater myUpdater; + private final ArtifactContextProducer myArtifactContextProducer; + + private final TIntObjectHashMap myIndices = new TIntObjectHashMap(); + + public MavenFacadeIndexerImpl() { + myEmbedder = MavenFacadeEmbedderImpl.create(new MavenFacadeSettings()); + + myIndexer = myEmbedder.getComponent(NexusIndexer.class); + myUpdater = myEmbedder.getComponent(IndexUpdater.class); + myArtifactContextProducer = myEmbedder.getComponent(ArtifactContextProducer.class); + } + + public int createIndex(@NotNull String indexId, + @Nullable String repositoryId, + @Nullable File file, + @Nullable String url, + @NotNull File indexDir) throws MavenFacadeIndexerException { + try { + IndexingContext context = myIndexer.addIndexingContext(indexId, + repositoryId, + file, + indexDir, + url, + null, // repo update url + NexusIndexer.FULL_INDEX); + int id = System.identityHashCode(context); + myIndices.put(id, context); + return id; + } + catch (IOException e) { + throw new MavenFacadeIndexerException(e); + } + catch (UnsupportedExistingLuceneIndexException e) { + throw new MavenFacadeIndexerException(e.getMessage()); + } + } + + public void releaseIndex(int id) throws MavenFacadeIndexerException { + try { + myIndexer.removeIndexingContext(getIndex(id), false); + } + catch (IOException e) { + throw new MavenFacadeIndexerException(e); + } + } + + @NotNull + private IndexingContext getIndex(int id) { + IndexingContext index = myIndices.get(id); + if (index == null) throw new RuntimeException("Index not found for id: " + id); + return index; + } + + private String getRepositoryPathOrUrl(IndexingContext index) { + File file = index.getRepository(); + return file == null ? index.getRepositoryUrl() : file.getPath(); + } + + private boolean isLocal(IndexingContext index) { + return index.getRepository() != null; + } + + public int getIndexCount() { + return myIndexer.getIndexingContexts().size(); + } + + public void updateIndex(int id, MavenFacadeSettings settings, MavenFacadeProgressIndicator indicator) throws + MavenFacadeIndexerException, + MavenFacadeProcessCanceledException { + IndexingContext index = getIndex(id); + MavenFacadeProgressIndicatorWrapper indicatorWrapper = new MavenFacadeProgressIndicatorWrapper(indicator); + + try { + if (isLocal(index)) { + indicatorWrapper.setIndeterminate(true); + try { + myIndexer.scan(index, new MyScanningListener(indicatorWrapper), false); + } + finally { + indicatorWrapper.setIndeterminate(false); + } + } + else { + IndexUpdateRequest request = new IndexUpdateRequest(index); + MavenFacadeEmbedderImpl embedder = MavenFacadeEmbedderImpl.create(settings); + try { + request.setResourceFetcher(new MavenIndexFetcher(index.getRepositoryId(), + index.getRepositoryUrl(), + embedder.getComponent(WagonManager.class), + new TransferListenerAdapter(indicatorWrapper) { + @Override + protected void doUpdateProgress(long downloaded, long total) { + super.doUpdateProgress(downloaded, total); + myIndicator.setFraction(((double)downloaded) / total); + } + + @Override + public void transferCompleted(TransferEvent event) { + super.transferCompleted(event); + myIndicator.setText2("Processing indices..."); + } + })); + myUpdater.fetchAndUpdateIndex(request); + } + finally { + embedder.release(); + } + } + } + catch (MavenFacadeProgressIndicatorWrapper.RuntimeCanceledException e) { + throw new MavenFacadeProcessCanceledException(); + } + catch (IOException e) { + throw new MavenFacadeIndexerException(e); + } + } + + public List getAllArtifacts(int indexId) throws MavenFacadeIndexerException { + try { + List result = new ArrayList(); + IndexReader r = getIndex(indexId).getIndexReader(); + int total = r.numDocs(); + for (int i = 0; i < total; i++) { + if (r.isDeleted(i)) continue; + + Document doc = r.document(i); + String uinfo = doc.get(SEARCH_TERM_COORDINATES); + if (uinfo == null) continue; + List parts = StringUtil.split(uinfo, "|"); + String groupId = parts.get(0); + String artifactId = parts.get(1); + String version = parts.get(2); + if (groupId == null || artifactId == null || version == null) continue; + + result.add(new MavenId(groupId, artifactId, version)); + } + return result; + } + catch (IOException e) { + throw new MavenFacadeIndexerException(e); + } + } + + public MavenId addArtifact(int indexId, File artifactFile) throws MavenFacadeIndexerException { + try { + IndexingContext index = getIndex(indexId); + ArtifactContext artifactContext = myArtifactContextProducer.getArtifactContext(index, artifactFile); + if (artifactContext == null) return null; + + myIndexer.addArtifactToIndex(artifactContext, index); + + org.sonatype.nexus.index.ArtifactInfo a = artifactContext.getArtifactInfo(); + return new MavenId(a.groupId, a.artifactId, a.version); + } + catch (IOException e) { + throw new MavenFacadeIndexerException(e); + } + } + + public Set search(int indexId, Query query, int maxResult) throws MavenFacadeIndexerException { + try { + IndexingContext index = getIndex(indexId); + + TopDocs docs = null; + try { + BooleanQuery.setMaxClauseCount(Integer.MAX_VALUE); + docs = index.getIndexSearcher().search(query, null, maxResult); + } + catch (BooleanQuery.TooManyClauses ignore) { + // this exception occurs when too wide wildcard is used on too big data. + } + + if (docs == null || docs.scoreDocs.length == 0) return Collections.emptySet(); + + Set result = new THashSet(); + + for (int i = 0; i < docs.scoreDocs.length; i++) { + int docIndex = docs.scoreDocs[i].doc; + Document doc = index.getIndexReader().document(docIndex); + ArtifactInfo a = IndexUtils.constructArtifactInfo(doc, index); + if (a == null) continue; + + a.repository = getRepositoryPathOrUrl(index); + result.add(MavenModelConverter.convertArtifactInfo(a)); + } + return result; + } + catch (IOException e) { + throw new MavenFacadeIndexerException(e); + } + } + + public Collection getArchetypes() { + Set result = new THashSet(); + doCollectArchetypes("internal-catalog", result); + doCollectArchetypes("nexus", result); + return result; + } + + private void doCollectArchetypes(String roleHint, Set result) { + try { + ArchetypeDataSource source = myEmbedder.getComponent(ArchetypeDataSource.class, roleHint); + ArchetypeCatalog catalog = source.getArchetypeCatalog(new Properties()); + + for (Archetype each : (Iterable)catalog.getArchetypes()) { + result.add(MavenModelConverter.convertArchetype(each)); + } + } + catch (ArchetypeDataSourceException e) { + MavenFacadeLoggerManager.getLogger().warn(e); + } + } + + public void release() { + myEmbedder.release(); + } + + + private static class MyScanningListener implements ArtifactScanningListener { + private final MavenFacadeProgressIndicatorWrapper p; + + public MyScanningListener(MavenFacadeProgressIndicatorWrapper indicator) { + p = indicator; + } + + public void scanningStarted(IndexingContext ctx) { + p.checkCanceled(); + } + + public void scanningFinished(IndexingContext ctx, ScanningResult result) { + p.checkCanceled(); + } + + public void artifactError(ArtifactContext ac, Exception e) { + } + + public void artifactDiscovered(ArtifactContext ac) { + p.checkCanceled(); + ArtifactInfo info = ac.getArtifactInfo(); + p.setText2(info.groupId + ":" + info.artifactId + ":" + info.version); + } + } +} diff --git a/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenFacadeLoggerWrapper.java b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenFacadeLoggerWrapper.java new file mode 100644 index 000000000000..1fdff7a724e5 --- /dev/null +++ b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenFacadeLoggerWrapper.java @@ -0,0 +1,56 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.maven.facade.embedder; + +import org.jetbrains.idea.maven.facade.MavenFacadeLogger; +import org.jetbrains.idea.maven.facade.RemoteObject; + +import java.rmi.RemoteException; + +public class MavenFacadeLoggerWrapper { + MavenFacadeLogger myWrappee; + + public MavenFacadeLoggerWrapper(MavenFacadeLogger wrappee) { + myWrappee = wrappee; + } + + public void info(Throwable e) { + try { + myWrappee.info(RemoteObject.wrapException(e)); + } + catch (RemoteException e1) { + throw new RuntimeException(e1); + } + } + + public void warn(Throwable e) { + try { + myWrappee.warn(RemoteObject.wrapException(e)); + } + catch (RemoteException e1) { + throw new RuntimeException(e1); + } + } + + public void error(Throwable e) { + try { + myWrappee.error(RemoteObject.wrapException(e)); + } + catch (RemoteException e1) { + throw new RuntimeException(e1); + } + } +} diff --git a/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenFacadeProgressIndicatorWrapper.java b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenFacadeProgressIndicatorWrapper.java new file mode 100644 index 000000000000..a4e0a06eb718 --- /dev/null +++ b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenFacadeProgressIndicatorWrapper.java @@ -0,0 +1,80 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.maven.facade.embedder; + +import org.jetbrains.idea.maven.facade.MavenFacadeProgressIndicator; + +import java.rmi.RemoteException; + +public class MavenFacadeProgressIndicatorWrapper { + private final MavenFacadeProgressIndicator myWrappee; + + public MavenFacadeProgressIndicatorWrapper(MavenFacadeProgressIndicator wrappee) { + myWrappee = wrappee; + } + + public void setText(String text) { + try { + myWrappee.setText(text); + } + catch (RemoteException e) { + throw new RuntimeException(e); + } + } + + public void setText2(String text) { + try { + myWrappee.setText2(text); + } + catch (RemoteException e) { + throw new RuntimeException(e); + } + } + + public boolean isCanceled() { + try { + return myWrappee.isCanceled(); + } + catch (RemoteException e) { + throw new RuntimeException(e); + } + } + + public void checkCanceled() { + if (isCanceled()) throw new RuntimeCanceledException(); + } + + public void setIndeterminate(boolean value) { + try { + myWrappee.setIndeterminate(value); + } + catch (RemoteException e) { + throw new RuntimeException(e); + } + } + + public void setFraction(double fraction) { + try { + myWrappee.setFraction(fraction); + } + catch (RemoteException e) { + throw new RuntimeException(e); + } + } + + public static class RuntimeCanceledException extends RuntimeException { + } +} diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndexFetcher.java b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenIndexFetcher.java similarity index 95% rename from plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndexFetcher.java rename to plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenIndexFetcher.java index 341972ae56dc..1535cecf05c1 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndexFetcher.java +++ b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenIndexFetcher.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.maven.indices; +package org.jetbrains.idea.maven.facade.embedder; import org.apache.maven.artifact.manager.WagonManager; import org.apache.maven.artifact.repository.DefaultArtifactRepository; @@ -25,12 +25,13 @@ import org.apache.maven.wagon.authentication.AuthenticationException; import org.apache.maven.wagon.authorization.AuthorizationException; import org.apache.maven.wagon.events.TransferListener; import org.apache.maven.wagon.repository.Repository; -import org.jetbrains.idea.maven.utils.MavenLog; +import org.jetbrains.idea.maven.facade.MavenFacadeLoggerManager; import org.sonatype.nexus.index.updater.ResourceFetcher; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.rmi.RemoteException; public class MavenIndexFetcher implements ResourceFetcher { private final String myOriginalRepositoryId; @@ -80,7 +81,7 @@ public class MavenIndexFetcher implements ResourceFetcher { myWagon.disconnect(); } catch (ConnectionException ex) { - MavenLog.LOG.warn(ex); + MavenFacadeLoggerManager.getLogger().warn(ex); } } diff --git a/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenModelConverter.java b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenModelConverter.java new file mode 100644 index 000000000000..65557c7a7101 --- /dev/null +++ b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenModelConverter.java @@ -0,0 +1,525 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.maven.facade.embedder; + +import com.intellij.util.ReflectionUtil; +import gnu.trove.THashMap; +import gnu.trove.THashSet; +import org.apache.maven.archetype.catalog.Archetype; +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.handler.ArtifactHandler; +import org.apache.maven.model.*; +import org.apache.maven.shared.dependency.tree.DependencyNode; +import org.codehaus.plexus.util.xml.Xpp3Dom; +import org.jdom.Element; +import org.jdom.IllegalNameException; +import org.jetbrains.idea.maven.facade.MavenFacadeLoggerManager; +import org.jetbrains.idea.maven.facade.nexus.ArtifactType; +import org.jetbrains.idea.maven.facade.nexus.RepositoryType; +import org.jetbrains.idea.maven.model.*; +import org.sonatype.nexus.index.ArtifactInfo; + +import java.io.File; +import java.lang.reflect.Field; +import java.util.*; + +public class MavenModelConverter { + public static MavenModel convertModel(Model model, File localRepository) { + Build build = model.getBuild(); + return convertModel(model, + asSourcesList(build.getSourceDirectory()), + asSourcesList(build.getTestSourceDirectory()), + Collections.emptyList(), + Collections.emptyList(), + Collections.emptyList(), + localRepository); + } + + private static List asSourcesList(String directory) { + return directory == null ? Collections.emptyList() : Collections.singletonList(directory); + } + + public static MavenModel convertModel(Model model, + List sources, + List testSources, + Collection dependencies, + Collection dependencyTree, + Collection extensions, + File localRepository) { + MavenModel result = new MavenModel(); + result.setMavenId(new MavenId(model.getGroupId(), model.getArtifactId(), model.getVersion())); + + Parent parent = model.getParent(); + if (parent != null) { + result.setParent(new MavenParent(new MavenId(parent.getGroupId(), parent.getArtifactId(), parent.getVersion()), + parent.getRelativePath())); + } + result.setPackaging(model.getPackaging()); + result.setName(model.getName()); + result.setProperties(model.getProperties() == null ? new Properties() : model.getProperties()); + result.setPlugins(convertPlugins(model)); + + Map convertedArtifacts = new THashMap(); + result.setExtensions(convertArtifacts(extensions, convertedArtifacts, localRepository)); + result.setDependencies(convertArtifacts(dependencies, convertedArtifacts, localRepository)); + result.setDependencyTree(convertDependencyNodes(null, dependencyTree, convertedArtifacts, localRepository)); + + result.setRemoteRepositories(convertRepositories(model.getRepositories())); + result.setProfiles(convertProfiles(model.getProfiles())); + result.setModules(model.getModules()); + + convertBuild(result.getBuild(), model.getBuild(), sources, testSources); + return result; + } + + private static void convertBuild(MavenBuild result, Build build, List sources, List testSources) { + convertBuildBase(result, build); + result.setOutputDirectory(build.getOutputDirectory()); + result.setTestOutputDirectory(build.getTestOutputDirectory()); + result.setSources(sources); + result.setTestSources(testSources); + } + + private static void convertBuildBase(MavenBuildBase result, BuildBase build) { + result.setFinalName(build.getFinalName()); + result.setDefaultGoal(build.getDefaultGoal()); + result.setDirectory(build.getDirectory()); + result.setResources(convertResources(build.getResources())); + result.setTestResources(convertResources(build.getTestResources())); + result.setFilters(build.getFilters() == null ? Collections.emptyList() : build.getFilters()); + } + + public static MavenId createMavenId(Artifact artifact) { + return new MavenId(artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion()); + } + + private static List convertResources(List resources) { + if (resources == null) return new ArrayList(); + + List result = new ArrayList(resources.size()); + for (Resource each : resources) { + result.add(new MavenResource(each.getDirectory(), + each.isFiltering(), + each.getTargetPath(), + ensurePatterns(each.getIncludes()), + ensurePatterns(each.getExcludes()))); + } + return result; + } + + private static List ensurePatterns(List patterns) { + return patterns == null ? Collections.EMPTY_LIST : patterns; + } + + private static List convertRepositories(List repositories) { + if (repositories == null) return new ArrayList(); + + List result = new ArrayList(repositories.size()); + for (Repository each : repositories) { + result.add(new MavenRemoteRepository(each.getId(), + each.getName(), + each.getUrl(), + each.getLayout(), + convertPolicy(each.getReleases()), + convertPolicy(each.getSnapshots()))); + } + return result; + } + + private static MavenRemoteRepository.Policy convertPolicy(RepositoryPolicy policy) { + return policy != null + ? new MavenRemoteRepository.Policy(policy.isEnabled(), policy.getUpdatePolicy(), policy.getChecksumPolicy()) + : null; + } + + public static List convertArtifacts(Collection artifacts, + Map nativeToConvertedMap, + File localRepository) { + if (artifacts == null) return new ArrayList(); + + List result = new ArrayList(artifacts.size()); + for (Artifact each : artifacts) { + result.add(convertArtifact(each, nativeToConvertedMap, localRepository)); + } + return result; + } + + public static List convertDependencyNodes(MavenArtifactNode parent, + Collection nodes, + Map nativeToConvertedMap, + File localRepository) { + List result = new ArrayList(nodes.size()); + for (DependencyNode each : nodes) { + Artifact a = each.getArtifact(); + MavenArtifact ma = convertArtifact(a, nativeToConvertedMap, localRepository); + + MavenArtifactState state = MavenArtifactState.ADDED; + switch (each.getState()) { + case DependencyNode.INCLUDED: + break; + case DependencyNode.OMITTED_FOR_CONFLICT: + state = MavenArtifactState.CONFLICT; + break; + case DependencyNode.OMITTED_FOR_DUPLICATE: + state = MavenArtifactState.DUPLICATE; + break; + case DependencyNode.OMITTED_FOR_CYCLE: + state = MavenArtifactState.CYCLE; + break; + default: + assert false : "unknown dependency node state: " + each.getState(); + } + MavenArtifact relatedMA = each.getRelatedArtifact() == null ? null + : convertArtifact(each.getRelatedArtifact(), nativeToConvertedMap, + localRepository); + MavenArtifactNode newNode = new MavenArtifactNode(parent, ma, state, relatedMA, each.getOriginalScope(), + each.getPremanagedVersion(), each.getPremanagedScope()); + newNode.setDependencies(convertDependencyNodes(newNode, each.getChildren(), nativeToConvertedMap, localRepository)); + result.add(newNode); + } + return result; + } + + private static MavenArtifact convertArtifact(Artifact artifact, Map nativeToConvertedMap, File localRepository) { + MavenArtifact result = nativeToConvertedMap.get(artifact); + if (result == null) { + result = convertArtifact(artifact, localRepository); + nativeToConvertedMap.put(artifact, result); + } + return result; + } + + public static MavenArtifact convertArtifact(Artifact artifact, File localRepository) { + return new MavenArtifact(artifact.getGroupId(), artifact.getArtifactId(), + artifact.getVersion(), + artifact.getBaseVersion(), + artifact.getType(), + artifact.getClassifier(), + + artifact.getScope(), + artifact.isOptional(), + + convertExtension(artifact), + + artifact.getFile(), + localRepository, + + artifact.isResolved(), + artifact instanceof CustomArtifact && ((CustomArtifact)artifact).isStub()); + } + + private static String convertExtension(Artifact artifact) { + ArtifactHandler handler = artifact.getArtifactHandler(); + String result = null; + if (handler != null) result = handler.getExtension(); + if (result == null) result = artifact.getType(); + return result; + } + + private static List convertPlugins(Model mavenModel) { + List result = new ArrayList(); + Set pluginKeys = new THashSet(); + Build build = mavenModel.getBuild(); + doConvertPlugins(build, false, result, pluginKeys); + if (build != null) doConvertPlugins(build.getPluginManagement(), true, result, pluginKeys); + return result; + } + + private static void doConvertPlugins(PluginContainer container, + boolean management, + List result, + Set pluginKeys) { + if (container == null) return; + + List plugins = container.getPlugins(); + if (plugins == null) return; + + for (Plugin each : plugins) { + String key = each.getGroupId() + ":" + each.getArtifactId(); + result.add(convertPlugin(management, each)); + pluginKeys.add(key); + } + } + + private static MavenPlugin convertPlugin(boolean isDefault, Plugin plugin) { + List executions = new ArrayList(plugin.getExecutions().size()); + for (PluginExecution each : plugin.getExecutions()) { + executions.add(convertExecution(each)); + } + + List deps = new ArrayList(plugin.getDependencies().size()); + for (Dependency each : plugin.getDependencies()) { + deps.add(new MavenId(each.getGroupId(), each.getArtifactId(), each.getVersion())); + } + + return new MavenPlugin(plugin.getGroupId(), + plugin.getArtifactId(), + plugin.getVersion(), + isDefault, + convertConfiguration(plugin.getConfiguration()), + executions, deps); + } + + public static MavenPlugin.Execution convertExecution(PluginExecution execution) { + return new MavenPlugin.Execution(execution.getGoals(), convertConfiguration(execution.getConfiguration())); + } + + private static Element convertConfiguration(Object config) { + return config == null ? null : xppToElement((Xpp3Dom)config); + } + + private static Element xppToElement(Xpp3Dom xpp) { + Element result = null; + try { + result = new Element(xpp.getName()); + } + catch (IllegalNameException e) { + MavenFacadeLoggerManager.getLogger().error(e); + return null; + } + + Xpp3Dom[] children = xpp.getChildren(); + if (children == null || children.length == 0) { + result.setText(xpp.getValue()); + } + else { + for (Xpp3Dom each : children) { + Element child = xppToElement(each); + if (child != null) result.addContent(child); + } + } + return result; + } + + public static List convertProfiles(Collection profiles) { + if (profiles == null) return Collections.emptyList(); + List result = new ArrayList(); + for (Profile each : profiles) { + String id = each.getId(); + if (id == null) continue; + MavenProfile profile = new MavenProfile(id, each.getSource()); + List modules = each.getModules(); + profile.setModules(modules == null ? Collections.emptyList() : modules); + if (each.getBuild() != null) convertBuildBase(profile.getBuild(), each.getBuild()); + result.add(profile); + } + return result; + } + + public static Map convertToMap(Object object) { + try { + Map result = new THashMap(); + doConvert(object, "", result); + return result; + } + catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + private static void doConvert(Object object, String prefix, Map result) throws IllegalAccessException { + for (Field each : ReflectionUtil.collectFields(object.getClass())) { + Class type = each.getType(); + if (shouldSkip(type)) continue; + + each.setAccessible(true); + Object value = each.get(object); + + String name = prefix + each.getName(); + result.put(name, String.valueOf(value)); + if (value != null) { + Package pack = type.getPackage(); + if (pack != null && Model.class.getPackage().getName().equals(pack.getName())) { + doConvert(value, name + ".", result); + } + } + } + } + + public static boolean shouldSkip(Class clazz) { + return clazz.isArray() + || Collection.class.isAssignableFrom(clazz) + || Map.class.isAssignableFrom(clazz) + || Xpp3Dom.class.isAssignableFrom(clazz); + } + + public static MavenArchetype convertArchetype(Archetype archetype) { + return new MavenArchetype(archetype.getGroupId(), + archetype.getArtifactId(), + archetype.getVersion(), + archetype.getRepository(), + archetype.getDescription()); + } + + public static Model toNativeModel(MavenModel model) { + Model result = new Model(); + result.setArtifactId(model.getMavenId().getArtifactId()); + result.setGroupId(model.getMavenId().getGroupId()); + result.setVersion(model.getMavenId().getVersion()); + result.setPackaging(model.getPackaging()); + result.setName(model.getName()); + + if (model.getParent() != null) { + Parent parent = new Parent(); + parent.setArtifactId(model.getParent().getMavenId().getArtifactId()); + parent.setGroupId(model.getParent().getMavenId().getGroupId()); + parent.setVersion(model.getParent().getMavenId().getVersion()); + parent.setRelativePath(model.getParent().getRelativePath()); + result.setParent(parent); + } + toNativeModelBase(model, result); + + result.setBuild(new Build()); + MavenBuild modelBuild = model.getBuild(); + toNativeBuildBase(modelBuild, result.getBuild()); + result.getBuild().setOutputDirectory(modelBuild.getOutputDirectory()); + result.getBuild().setTestOutputDirectory(modelBuild.getTestOutputDirectory()); + + if (modelBuild.getSources().size() > 1) throw new RuntimeException("too many source directories: " + modelBuild.getSources()); + if (modelBuild.getTestSources().size() > 1) throw new RuntimeException("too many test directories: " + modelBuild.getTestSources()); + + if (modelBuild.getSources().size() == 1) { + result.getBuild().setSourceDirectory(modelBuild.getSources().get(0)); + } + if (modelBuild.getTestSources().size() == 1) { + result.getBuild().setTestSourceDirectory(modelBuild.getTestSources().get(0)); + } + + result.setProfiles(toNativeProfiles(model.getProfiles())); + + return result; + } + + private static List toNativeProfiles(List profiles) { + List result = new ArrayList(profiles.size()); + for (MavenProfile each : profiles) { + Profile p = new Profile(); + p.setId(each.getId()); + p.setSource(each.getSource()); + p.setBuild(new Build()); + p.setActivation(toNativeActivation(each.getActivation())); + toNativeModelBase(each, p); + toNativeBuildBase(each.getBuild(), p.getBuild()); + result.add(p); + } + return result; + } + + private static Activation toNativeActivation(MavenProfileActivation activation) { + if (activation == null) return null; + Activation result = new Activation(); + result.setActiveByDefault(activation.isActiveByDefault()); + result.setJdk(activation.getJdk()); + result.setOs(toNativeOsActivation(activation.getOs())); + result.setFile(toNativeFileActivation(activation.getFile())); + result.setProperty(toNativePropertyActivation(activation.getProperty())); + return result; + } + + private static ActivationOS toNativeOsActivation(MavenProfileActivationOS os) { + if (os == null) return null; + ActivationOS result = new ActivationOS(); + result.setArch(os.getArch()); + result.setFamily(os.getFamily()); + result.setName(os.getName()); + result.setVersion(os.getVersion()); + return result; + } + + private static ActivationFile toNativeFileActivation(MavenProfileActivationFile file) { + if (file == null) return null; + ActivationFile result = new ActivationFile(); + result.setExists(file.getExists()); + result.setMissing(file.getMissing()); + return result; + } + + private static ActivationProperty toNativePropertyActivation(MavenProfileActivationProperty property) { + if (property == null) return null; + ActivationProperty result = new ActivationProperty(); + result.setName(property.getName()); + result.setValue(property.getValue()); + return result; + } + + private static void toNativeModelBase(MavenModelBase from, ModelBase to) { + to.setModules(from.getModules()); + to.setProperties(from.getProperties()); + } + + private static void toNativeBuildBase(MavenBuildBase from, BuildBase to) { + to.setFinalName(from.getFinalName()); + to.setDefaultGoal(from.getDefaultGoal()); + to.setDirectory(from.getDirectory()); + to.setFilters(from.getFilters()); + to.setResources(toNativeResources(from.getResources())); + to.setTestResources(toNativeResources(from.getTestResources())); + } + + private static List toNativeResources(List resources) { + List result = new ArrayList(resources.size()); + for (MavenResource each : resources) { + Resource r = new Resource(); + r.setDirectory(each.getDirectory()); + r.setTargetPath(each.getTargetPath()); + r.setFiltering(each.isFiltered()); + r.setIncludes(each.getIncludes()); + r.setExcludes(each.getExcludes()); + result.add(r); + } + return result; + } + + public static Repository toNativeRepository(MavenRemoteRepository r) { + Repository result = new Repository(); + result.setId(r.getId()); + result.setName(r.getName()); + result.setUrl(r.getUrl()); + result.setLayout(r.getLayout()); + + if (r.getReleasesPolicy() != null) result.setReleases(toNativePolicy(r.getReleasesPolicy())); + if (r.getSnapshotsPolicy() != null) result.setSnapshots(toNativePolicy(r.getSnapshotsPolicy())); + + return result; + } + + private static RepositoryPolicy toNativePolicy(MavenRemoteRepository.Policy policy) { + RepositoryPolicy result = new RepositoryPolicy(); + result.setEnabled(policy.isEnabled()); + result.setUpdatePolicy(policy.getUpdatePolicy()); + result.setChecksumPolicy(policy.getChecksumPolicy()); + return result; + } + + public static MavenArtifactInfo convertArtifactInfo(ArtifactInfo a) { + return new MavenArtifactInfo(a.groupId, a.artifactId, a.version, a.packaging, a.classifier, a.classNames, a.repository); + } + + public static MavenArtifactInfo convertArtifactInfo(ArtifactType t) { + return new MavenArtifactInfo(t.getGroupId(), + t.getArtifactId(), + t.getVersion(), + t.getPackaging(), + t.getClassifier(), + t.getClassNames(), + t.getRepoId()); + } + + public static MavenRepositoryInfo convertRepositoryInfo(RepositoryType repo) { + return new MavenRepositoryInfo(repo.getId(), repo.getName(), repo.getContentResourceURI()); + } +} + diff --git a/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/RemoteNativeMavenProjectHolder.java b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/RemoteNativeMavenProjectHolder.java new file mode 100644 index 000000000000..8b99bedf99e6 --- /dev/null +++ b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/RemoteNativeMavenProjectHolder.java @@ -0,0 +1,31 @@ +package org.jetbrains.idea.maven.facade.embedder; + +import com.intellij.util.containers.WeakValueHashMap; +import org.apache.maven.project.MavenProject; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.maven.facade.NativeMavenProjectHolder; + +public class RemoteNativeMavenProjectHolder implements NativeMavenProjectHolder { + private static final WeakValueHashMap myMap = + new WeakValueHashMap(); + + private final MavenProject myMavenProject; + + public RemoteNativeMavenProjectHolder(@NotNull MavenProject mavenProject) { + myMavenProject = mavenProject; + myMap.put(getId(), this); + } + + public int getId() { + return System.identityHashCode(this); + } + + @NotNull + public static MavenProject findprojectById(int id) { + RemoteNativeMavenProjectHolder result = myMap.get(id); + if (result == null) { + throw new RuntimeException("NativeMavenProjectHolder not found for id: " + id); + } + return result.myMavenProject; + } +} diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/TransferListenerAdapter.java b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/TransferListenerAdapter.java similarity index 61% rename from plugins/maven/src/main/java/org/jetbrains/idea/maven/project/TransferListenerAdapter.java rename to plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/TransferListenerAdapter.java index 12008224ecca..e585869b5c0a 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/TransferListenerAdapter.java +++ b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/TransferListenerAdapter.java @@ -13,30 +13,31 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.maven.project; +package org.jetbrains.idea.maven.facade.embedder; import org.apache.maven.wagon.events.TransferEvent; import org.apache.maven.wagon.events.TransferListener; -import org.jetbrains.idea.maven.indices.MavenIndicesManager; -import org.jetbrains.idea.maven.utils.MavenProgressIndicator; + +import java.text.MessageFormat; public class TransferListenerAdapter implements TransferListener { - protected final MavenProgressIndicator myIndicator; + protected final MavenFacadeProgressIndicatorWrapper myIndicator; private String myRepository; private String myResource; private long mySize; private long myProgress; - //private static long total; - //private long started; - - public TransferListenerAdapter(MavenProgressIndicator indicator) { + public TransferListenerAdapter(MavenFacadeProgressIndicatorWrapper indicator) { myIndicator = indicator; } public void transferInitiated(TransferEvent event) { - myIndicator.checkCanceledNative(); + checkCanceled(); + } + + private void checkCanceled() { + myIndicator.checkCanceled(); } public void transferStarted(TransferEvent event) { @@ -53,39 +54,31 @@ public class TransferListenerAdapter implements TransferListener { } protected void doUpdateProgress(long downloaded, long total) { - myIndicator.setText2(ProjectBundle.message("maven.transfer.progress", downloaded, total == 0 ? "?" : total, myRepository, myResource)); + myIndicator.setText2(MessageFormat.format("{0}/{1}Kb [{2}] {3}", downloaded, total == 0 ? "?" : total, myRepository, myResource)); } public void transferProgress(TransferEvent event, byte[] bytes, int i) { - myIndicator.checkCanceledNative(); + checkCanceled(); myProgress += i; updateProgress(); } public void transferCompleted(TransferEvent event) { addArtifactToIndex(event); - myIndicator.checkCanceledNative(); - updateTiming(true); + checkCanceled(); } public void transferError(TransferEvent event) { - myIndicator.checkCanceledNative(); - updateTiming(false); + checkCanceled(); } public void debug(String s) { - myIndicator.checkCanceledNative(); - } - - private void updateTiming(boolean ok) { - //long finished = System.currentTimeMillis(); - //long time = finished - started; - //total += time; - //System.out.println((ok ? "OK: " : "ERROR: ") + time + " (" + total + ")"); + checkCanceled(); } private void addArtifactToIndex(TransferEvent event) { - MavenIndicesManager.getInstance().addArtifact(event.getLocalFile(), - event.getResource().getName()); + // todo + //MavenIndicesManager.getInstance().addArtifact(event.getLocalFile(), + // event.getResource().getName()); } } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/UnresolvedArtifactsCollector.java b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/UnresolvedArtifactsCollector.java similarity index 88% rename from plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/UnresolvedArtifactsCollector.java rename to plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/UnresolvedArtifactsCollector.java index aab5d047aad9..99b65bf3c0d5 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/UnresolvedArtifactsCollector.java +++ b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/UnresolvedArtifactsCollector.java @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.maven.embedder; +package org.jetbrains.idea.maven.facade.embedder; import gnu.trove.THashSet; import org.apache.maven.artifact.Artifact; -import org.jetbrains.idea.maven.project.MavenId; +import org.jetbrains.idea.maven.model.MavenId; import java.util.Set; @@ -39,7 +39,7 @@ public class UnresolvedArtifactsCollector { public void collectAndSetResolved(Artifact artifact) { if (!artifact.isResolved()) { synchronized (myUnresolvedIds) { - myUnresolvedIds.add(new MavenId(artifact)); + myUnresolvedIds.add(MavenModelConverter.createMavenId(artifact)); } } if (!myFailOnUnresolved) artifact.setResolved(true); diff --git a/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/nexus/ArtifactType.java b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/nexus/ArtifactType.java new file mode 100644 index 000000000000..ca9fc8a040c7 --- /dev/null +++ b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/nexus/ArtifactType.java @@ -0,0 +1,338 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.maven.facade.nexus; + +import org.jetbrains.annotations.Nullable; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; +import java.io.Serializable; + + +/** + *

    Java class for artifactType complex type. + *

    + *

    The following schema fragment specifies the expected content contained within this class. + *

    + *

    + * <complexType name="artifactType">
    + *   <complexContent>
    + *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
    + *       <sequence>
    + *         <element name="resourceUri" type="{http://www.w3.org/2001/XMLSchema}string"/>
    + *         <element name="groupId" type="{http://www.w3.org/2001/XMLSchema}string"/>
    + *         <element name="artifactId" type="{http://www.w3.org/2001/XMLSchema}string"/>
    + *         <element name="version" type="{http://www.w3.org/2001/XMLSchema}string"/>
    + *         <element name="classifier" type="{http://www.w3.org/2001/XMLSchema}string"/>
    + *         <element name="packaging" type="{http://www.w3.org/2001/XMLSchema}string"/>
    + *         <element name="extension" type="{http://www.w3.org/2001/XMLSchema}string"/>
    + *         <element name="repoId" type="{http://www.w3.org/2001/XMLSchema}string"/>
    + *         <element name="contextId" type="{http://www.w3.org/2001/XMLSchema}string"/>
    + *         <element name="pomLink" type="{http://www.w3.org/2001/XMLSchema}string"/>
    + *         <element name="artifactLink" type="{http://www.w3.org/2001/XMLSchema}string"/>
    + *       </sequence>
    + *     </restriction>
    + *   </complexContent>
    + * </complexType>
    + * 
    + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "artifactType", propOrder = { + "resourceUri", + "groupId", + "artifactId", + "version", + "classifier", + "packaging", + "extension", + "repoId", + "contextId", + "pomLink", + "artifactLink" +}) +public class ArtifactType implements Serializable { + + @XmlElement(required = true) + protected String resourceUri; + @XmlElement(required = true) + protected String groupId; + @XmlElement(required = true) + protected String artifactId; + @XmlElement(required = true) + protected String version; + @XmlElement(required = true) + protected String classifier; + @XmlElement(required = true) + protected String packaging; + @XmlElement(required = true) + protected String extension; + @XmlElement(required = true) + protected String repoId; + @XmlElement(required = true) + protected String contextId; + @XmlElement(required = true) + protected String pomLink; + @XmlElement(required = true) + protected String artifactLink; + + protected String classNames; + + public ArtifactType() { + + } + + public ArtifactType(String groupId, String artifactId, String version) { + this.groupId = groupId; + this.artifactId = artifactId; + this.version = version; + } + + /** + * Gets the value of the resourceUri property. + * + * @return possible object is + * {@link String } + */ + public String getResourceUri() { + return resourceUri; + } + + /** + * Sets the value of the resourceUri property. + * + * @param value allowed object is + * {@link String } + */ + public void setResourceUri(String value) { + this.resourceUri = value; + } + + /** + * Gets the value of the groupId property. + * + * @return possible object is + * {@link String } + */ + public String getGroupId() { + return groupId; + } + + /** + * Sets the value of the groupId property. + * + * @param value allowed object is + * {@link String } + */ + public void setGroupId(String value) { + this.groupId = value; + } + + /** + * Gets the value of the artifactId property. + * + * @return possible object is + * {@link String } + */ + public String getArtifactId() { + return artifactId; + } + + /** + * Sets the value of the artifactId property. + * + * @param value allowed object is + * {@link String } + */ + public void setArtifactId(String value) { + this.artifactId = value; + } + + /** + * Gets the value of the version property. + * + * @return possible object is + * {@link String } + */ + public String getVersion() { + return version; + } + + /** + * Sets the value of the version property. + * + * @param value allowed object is + * {@link String } + */ + public void setVersion(String value) { + this.version = value; + } + + /** + * Gets the value of the classifier property. + * + * @return possible object is + * {@link String } + */ + public String getClassifier() { + return classifier; + } + + /** + * Sets the value of the classifier property. + * + * @param value allowed object is + * {@link String } + */ + public void setClassifier(String value) { + this.classifier = value; + } + + /** + * Gets the value of the packaging property. + * + * @return possible object is + * {@link String } + */ + public String getPackaging() { + return packaging; + } + + /** + * Sets the value of the packaging property. + * + * @param value allowed object is + * {@link String } + */ + public void setPackaging(String value) { + this.packaging = value; + } + + /** + * Gets the value of the extension property. + * + * @return possible object is + * {@link String } + */ + public String getExtension() { + return extension; + } + + /** + * Sets the value of the extension property. + * + * @param value allowed object is + * {@link String } + */ + public void setExtension(String value) { + this.extension = value; + } + + /** + * Gets the value of the repoId property. + * + * @return possible object is + * {@link String } + */ + public String getRepoId() { + return repoId; + } + + /** + * Sets the value of the repoId property. + * + * @param value allowed object is + * {@link String } + */ + public void setRepoId(String value) { + this.repoId = value; + } + + /** + * Gets the value of the contextId property. + * + * @return possible object is + * {@link String } + */ + public String getContextId() { + return contextId; + } + + /** + * Sets the value of the contextId property. + * + * @param value allowed object is + * {@link String } + */ + public void setContextId(String value) { + this.contextId = value; + } + + /** + * Gets the value of the pomLink property. + * + * @return possible object is + * {@link String } + */ + public String getPomLink() { + return pomLink; + } + + /** + * Sets the value of the pomLink property. + * + * @param value allowed object is + * {@link String } + */ + public void setPomLink(String value) { + this.pomLink = value; + } + + /** + * Gets the value of the artifactLink property. + * + * @return possible object is + * {@link String } + */ + public String getArtifactLink() { + return artifactLink; + } + + /** + * Sets the value of the artifactLink property. + * + * @param value allowed object is + * {@link String } + */ + public void setArtifactLink(String value) { + this.artifactLink = value; + } + + @Nullable + public String getClassNames() { + return classNames; + } + + public void setClassNames(@Nullable String classNames) { + this.classNames = classNames; + } + + @Override + public String toString() { + return groupId + ":" + artifactId + ":" + version; + } +} diff --git a/plugins/maven/facade/org/jetbrains/idea/maven/facade/nexus/Endpoint.java b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/nexus/Endpoint.java similarity index 100% rename from plugins/maven/facade/org/jetbrains/idea/maven/facade/nexus/Endpoint.java rename to plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/nexus/Endpoint.java diff --git a/plugins/maven/facade/org/jetbrains/idea/maven/facade/nexus/ObjectFactory.java b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/nexus/ObjectFactory.java similarity index 90% rename from plugins/maven/facade/org/jetbrains/idea/maven/facade/nexus/ObjectFactory.java rename to plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/nexus/ObjectFactory.java index cd6d3df8eba7..ac8b88c44420 100644 --- a/plugins/maven/facade/org/jetbrains/idea/maven/facade/nexus/ObjectFactory.java +++ b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/nexus/ObjectFactory.java @@ -16,6 +16,9 @@ */ package org.jetbrains.idea.maven.facade.nexus; +import org.jetbrains.idea.maven.model.MavenArtifactInfo; +import org.jetbrains.idea.maven.model.MavenRepositoryInfo; + import javax.xml.bind.annotation.XmlRegistry; @@ -69,7 +72,7 @@ public class ObjectFactory { } /** - * Create an instance of {@link RepositoryType } + * Create an instance of {@link MavenRepositoryInfo } * */ public RepositoryType createRepositoryType() { @@ -77,7 +80,7 @@ public class ObjectFactory { } /** - * Create an instance of {@link ArtifactType } + * Create an instance of {@link org.jetbrains.idea.maven.model.MavenArtifactInfo } * */ public ArtifactType createArtifactType() { diff --git a/plugins/maven/facade/org/jetbrains/idea/maven/facade/nexus/Repositories.java b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/nexus/Repositories.java similarity index 97% rename from plugins/maven/facade/org/jetbrains/idea/maven/facade/nexus/Repositories.java rename to plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/nexus/Repositories.java index 178e258a0512..ef5f063d86ad 100644 --- a/plugins/maven/facade/org/jetbrains/idea/maven/facade/nexus/Repositories.java +++ b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/nexus/Repositories.java @@ -16,6 +16,8 @@ */ package org.jetbrains.idea.maven.facade.nexus; +import org.jetbrains.idea.maven.model.MavenRepositoryInfo; + import java.util.ArrayList; import java.util.List; import javax.xml.bind.annotation.XmlAccessType; @@ -135,7 +137,7 @@ public class Repositories { * *

    * Objects of the following type(s) are allowed in the list - * {@link RepositoryType } + * {@link MavenRepositoryInfo } * * */ diff --git a/plugins/maven/facade/org/jetbrains/idea/maven/facade/nexus/RepositoryMetaData.java b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/nexus/RepositoryMetaData.java similarity index 100% rename from plugins/maven/facade/org/jetbrains/idea/maven/facade/nexus/RepositoryMetaData.java rename to plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/nexus/RepositoryMetaData.java diff --git a/plugins/maven/facade/org/jetbrains/idea/maven/facade/nexus/RepositoryType.java b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/nexus/RepositoryType.java similarity index 100% rename from plugins/maven/facade/org/jetbrains/idea/maven/facade/nexus/RepositoryType.java rename to plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/nexus/RepositoryType.java diff --git a/plugins/maven/facade/org/jetbrains/idea/maven/facade/nexus/SearchResult.java b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/nexus/SearchResult.java similarity index 98% rename from plugins/maven/facade/org/jetbrains/idea/maven/facade/nexus/SearchResult.java rename to plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/nexus/SearchResult.java index 7e1c447f5f3c..acb063297260 100644 --- a/plugins/maven/facade/org/jetbrains/idea/maven/facade/nexus/SearchResult.java +++ b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/nexus/SearchResult.java @@ -16,6 +16,8 @@ */ package org.jetbrains.idea.maven.facade.nexus; +import org.jetbrains.idea.maven.model.MavenArtifactInfo; + import java.math.BigInteger; import java.util.ArrayList; import java.util.List; @@ -238,7 +240,7 @@ public class SearchResult { * *

    * Objects of the following type(s) are allowed in the list - * {@link ArtifactType } + * {@link org.jetbrains.idea.maven.model.MavenArtifactInfo } * * */ diff --git a/plugins/maven/facade/org/jetbrains/idea/maven/facade/nexus/SearchResults.java b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/nexus/SearchResults.java similarity index 97% rename from plugins/maven/facade/org/jetbrains/idea/maven/facade/nexus/SearchResults.java rename to plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/nexus/SearchResults.java index 6cfe85d0c162..c2a03fa81e87 100644 --- a/plugins/maven/facade/org/jetbrains/idea/maven/facade/nexus/SearchResults.java +++ b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/nexus/SearchResults.java @@ -16,6 +16,8 @@ */ package org.jetbrains.idea.maven.facade.nexus; +import org.jetbrains.idea.maven.model.MavenArtifactInfo; + import java.math.BigInteger; import java.util.ArrayList; import java.util.List; @@ -217,7 +219,7 @@ public class SearchResults { }) public static class Data { - protected List artifact; + protected ArrayList artifact; /** * Gets the value of the artifact property. @@ -237,7 +239,7 @@ public class SearchResults { * *

    * Objects of the following type(s) are allowed in the list - * {@link ArtifactType } + * {@link org.jetbrains.idea.maven.model.MavenArtifactInfo } * * */ diff --git a/plugins/maven/facade/org/jetbrains/idea/maven/facade/nexus/nexus.wadl b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/nexus/nexus.wadl similarity index 100% rename from plugins/maven/facade/org/jetbrains/idea/maven/facade/nexus/nexus.wadl rename to plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/nexus/nexus.wadl diff --git a/plugins/maven/facade/org/jetbrains/idea/maven/facade/nexus/nexus.xsd b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/nexus/nexus.xsd similarity index 100% rename from plugins/maven/facade/org/jetbrains/idea/maven/facade/nexus/nexus.xsd rename to plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/nexus/nexus.xsd diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/embedder/MavenEmbedderWrapperTest.java b/plugins/maven/facade-impl/test/org/jetbrains/idea/maven/embedder/MavenFacadeEmbedderTest.java similarity index 80% rename from plugins/maven/src/test/java/org/jetbrains/idea/maven/embedder/MavenEmbedderWrapperTest.java rename to plugins/maven/facade-impl/test/org/jetbrains/idea/maven/embedder/MavenFacadeEmbedderTest.java index 04d256c8d721..c622d30d69bd 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/embedder/MavenEmbedderWrapperTest.java +++ b/plugins/maven/facade-impl/test/org/jetbrains/idea/maven/embedder/MavenFacadeEmbedderTest.java @@ -17,20 +17,24 @@ package org.jetbrains.idea.maven.embedder; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; -import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.handler.ArtifactHandler; -import org.apache.maven.project.MavenProject; import org.codehaus.plexus.component.repository.ComponentDescriptor; import org.jetbrains.idea.maven.MavenImportingTestCase; -import org.jetbrains.idea.maven.project.MavenId; +import org.jetbrains.idea.maven.facade.MavenEmbedderWrapper; +import org.jetbrains.idea.maven.facade.MavenFacadeManager; +import org.jetbrains.idea.maven.facade.MavenWrapperExecutionResult; +import org.jetbrains.idea.maven.facade.embedder.MavenFacadeEmbedderImpl; +import org.jetbrains.idea.maven.model.MavenId; import org.jetbrains.idea.maven.execution.SoutMavenConsole; +import org.jetbrains.idea.maven.model.MavenModel; import java.io.File; import java.util.Arrays; import java.util.Collections; -public class MavenEmbedderWrapperTest extends MavenImportingTestCase { +public class MavenFacadeEmbedderTest extends MavenImportingTestCase { private MavenEmbedderWrapper myEmbedder; + private MavenFacadeEmbedderImpl myEmbedderImpl; @Override protected void setUp() throws Exception { @@ -46,7 +50,9 @@ public class MavenEmbedderWrapperTest extends MavenImportingTestCase { private void initEmbedder() { if (myEmbedder != null) releaseEmbedder(); - myEmbedder = MavenEmbedderWrapper.create(getMavenGeneralSettings()); + + myEmbedderImpl = MavenFacadeEmbedderImpl.create(MavenFacadeManager.convertSettings(getMavenGeneralSettings())); + myEmbedder = new MavenEmbedderWrapper(myEmbedderImpl); } private void releaseEmbedder() { @@ -55,7 +61,13 @@ public class MavenEmbedderWrapperTest extends MavenImportingTestCase { } public void testSettingLocalRepository() throws Exception { - assertEquals(getRepositoryFile(), myEmbedder.getLocalRepositoryFile()); + assertEquals(getRepositoryFile(), myEmbedderImpl.getLocalRepositoryFile()); + + File repo = new File(myDir, "/repo"); + setRepositoryPath(repo.getPath()); + + initEmbedder(); + assertEquals(getRepositoryFile(), myEmbedderImpl.getLocalRepositoryFile()); } public void testReleasingTwice() throws Exception { @@ -73,14 +85,13 @@ public class MavenEmbedderWrapperTest extends MavenImportingTestCase { myEmbedder.customizeForResolve(new SoutMavenConsole(), EMPTY_MAVEN_PROCESS); MavenWrapperExecutionResult result = myEmbedder.execute(myProjectPom, Collections.EMPTY_LIST, Arrays.asList("compile")); + assertNotNull(result.projectData); assertNotNull(new File(getProjectPath(), "target").exists()); + assertOrderedElementsAreEqual(result.unresolvedArtifacts); - assertOrderedElementsAreEqual(result.getExceptions()); - assertOrderedElementsAreEqual(result.getUnresolvedArtifactIds()); - - MavenProject project = result.getMavenProject(); + MavenModel project = result.projectData.mavenModel; assertNotNull(project); - assertEquals("project", project.getArtifactId()); + assertEquals("project", project.getMavenId().getArtifactId()); } public void testResolvingProject() throws Exception { @@ -98,14 +109,13 @@ public class MavenEmbedderWrapperTest extends MavenImportingTestCase { myEmbedder.customizeForResolve(new SoutMavenConsole(), EMPTY_MAVEN_PROCESS); MavenWrapperExecutionResult result = myEmbedder.resolveProject(myProjectPom, Collections.EMPTY_LIST); + assertNotNull(result.projectData); + assertOrderedElementsAreEqual(result.unresolvedArtifacts); - assertOrderedElementsAreEqual(result.getExceptions()); - assertOrderedElementsAreEqual(result.getUnresolvedArtifactIds()); - - MavenProject project = result.getMavenProject(); + MavenModel project = result.projectData.mavenModel; assertNotNull(project); - assertEquals("project", project.getArtifactId()); - assertEquals(1, project.getArtifacts().size()); + assertEquals("project", project.getMavenId().getArtifactId()); + assertEquals(1, project.getDependencies().size()); } public void testResolvingProjectPropertiesInFolders() throws Exception { @@ -116,11 +126,11 @@ public class MavenEmbedderWrapperTest extends MavenImportingTestCase { myEmbedder.customizeForResolve(new SoutMavenConsole(), EMPTY_MAVEN_PROCESS); MavenWrapperExecutionResult result = myEmbedder.resolveProject(myProjectPom, Collections.EMPTY_LIST); - MavenProject project = result.getMavenProject(); + MavenModel project = result.projectData.mavenModel; assertNotNull(project); - assertEquals("project", project.getArtifactId()); + assertEquals("project", project.getMavenId().getArtifactId()); assertPathEquals(myProjectRoot.getPath() + "/target", project.getBuild().getDirectory()); - assertPathEquals(myProjectRoot.getPath() + "/src/main/java", (String)project.getCompileSourceRoots().get(0)); + assertPathEquals(myProjectRoot.getPath() + "/src/main/java", project.getBuild().getSources().get(0)); } public void testResolvingProjectWithExtensions() throws Exception { @@ -152,10 +162,12 @@ public class MavenEmbedderWrapperTest extends MavenImportingTestCase { myEmbedder.customizeForResolve(new SoutMavenConsole(), EMPTY_MAVEN_PROCESS); MavenWrapperExecutionResult result = myEmbedder.resolveProject(myProjectPom, Collections.EMPTY_LIST); - assertOrderedElementsAreEqual(result.getExceptions()); + assertNotNull(result.projectData); + assertOrderedElementsAreEqual(result.unresolvedArtifacts); - assertEquals(1, result.getMavenProject().getArtifacts().size()); - assertEquals("rb.swc", ((Artifact)result.getMavenProject().getArtifacts().iterator().next()).getArtifactHandler().getExtension()); + MavenModel p = result.projectData.mavenModel; + assertEquals(1, p.getDependencies().size()); + assertEquals("rb.swc", p.getDependencies().get(0).getExtension()); } public void testResolvingProjectWithRegisteredExtensions() throws Exception { @@ -163,7 +175,7 @@ public class MavenEmbedderWrapperTest extends MavenImportingTestCase { desc.setRole(ArtifactHandler.ROLE); desc.setRoleHint("foo"); desc.setImplementation(MyArtifactHandler.class.getName()); - myEmbedder.getContainer().addComponentDescriptor(desc); + myEmbedderImpl.getContainer().addComponentDescriptor(desc); createProjectPom("test" + "project" + @@ -182,11 +194,41 @@ public class MavenEmbedderWrapperTest extends MavenImportingTestCase { myEmbedder.customizeForResolve(new SoutMavenConsole(), EMPTY_MAVEN_PROCESS); MavenWrapperExecutionResult result = myEmbedder.resolveProject(myProjectPom, Collections.EMPTY_LIST); - assertOrderedElementsAreEqual(result.getExceptions()); - assertOrderedElementsAreEqual(result.getUnresolvedArtifactIds()); + assertNotNull(result.projectData); + assertOrderedElementsAreEqual(result.unresolvedArtifacts); - assertEquals(1, result.getMavenProject().getArtifacts().size()); - assertEquals("pom", ((Artifact)result.getMavenProject().getArtifacts().iterator().next()).getArtifactHandler().getExtension()); + MavenModel p = result.projectData.mavenModel; + assertEquals(1, p.getDependencies().size()); + assertEquals("pom", p.getDependencies().get(0).getExtension()); + } + public static class MyArtifactHandler implements ArtifactHandler { + public String getExtension() { + return "pom"; + } + + public String getDirectory() { + throw new UnsupportedOperationException(); + } + + public String getClassifier() { + return null; + } + + public String getPackaging() { + return "foo"; + } + + public boolean isIncludesDependencies() { + return false; + } + + public String getLanguage() { + return "java"; + } + + public boolean isAddedToClasspath() { + return true; + } } public void testUnresolvedArtifacts() throws Exception { @@ -205,8 +247,8 @@ public class MavenEmbedderWrapperTest extends MavenImportingTestCase { myEmbedder.customizeForResolve(new SoutMavenConsole(), EMPTY_MAVEN_PROCESS); MavenWrapperExecutionResult result = myEmbedder.resolveProject(myProjectPom, Collections.EMPTY_LIST); - assertOrderedElementsAreEqual(result.getExceptions()); - assertOrderedElementsAreEqual(result.getUnresolvedArtifactIds(), new MavenId("fff", "zzz", "666")); + assertNotNull(result.projectData); + assertOrderedElementsAreEqual(result.unresolvedArtifacts, new MavenId("fff", "zzz", "666")); } public void testUnresolvedSystemArtifacts() throws Exception { @@ -227,8 +269,8 @@ public class MavenEmbedderWrapperTest extends MavenImportingTestCase { myEmbedder.customizeForResolve(new SoutMavenConsole(), EMPTY_MAVEN_PROCESS); MavenWrapperExecutionResult result = myEmbedder.resolveProject(myProjectPom, Collections.EMPTY_LIST); - assertOrderedElementsAreEqual(result.getExceptions()); - assertOrderedElementsAreEqual(result.getUnresolvedArtifactIds(), new MavenId("fff", "zzz", "666")); + assertNotNull(result.projectData); + assertOrderedElementsAreEqual(result.unresolvedArtifacts, new MavenId("fff", "zzz", "666")); } public void testDependencyWithUnresolvedParent() throws Exception { @@ -280,8 +322,8 @@ public class MavenEmbedderWrapperTest extends MavenImportingTestCase { myEmbedder.customizeForResolve(new SoutMavenConsole(), EMPTY_MAVEN_PROCESS); MavenWrapperExecutionResult result = myEmbedder.resolveProject(myProjectPom, Collections.EMPTY_LIST); - assertOrderedElementsAreEqual(result.getExceptions()); - assertOrderedElementsAreEqual(result.getUnresolvedArtifactIds(), new MavenId("test", "foo-parent", "1")); + assertNotNull(result.projectData); + assertOrderedElementsAreEqual(result.unresolvedArtifacts, new MavenId("test", "foo-parent", "1")); } public void testUnresolvedSystemArtifactsWithoutPath() throws Exception { @@ -302,37 +344,7 @@ public class MavenEmbedderWrapperTest extends MavenImportingTestCase { myEmbedder.customizeForResolve(new SoutMavenConsole(), EMPTY_MAVEN_PROCESS); MavenWrapperExecutionResult result = myEmbedder.resolveProject(myProjectPom, Collections.EMPTY_LIST); - assertOrderedElementsAreEqual(result.getExceptions()); - assertOrderedElementsAreEqual(result.getUnresolvedArtifactIds(), new MavenId("fff", "zzz", "666")); - } - - public static class MyArtifactHandler implements ArtifactHandler { - public String getExtension() { - return "pom"; - } - - public String getDirectory() { - throw new UnsupportedOperationException(); - } - - public String getClassifier() { - return null; - } - - public String getPackaging() { - return "foo"; - } - - public boolean isIncludesDependencies() { - return false; - } - - public String getLanguage() { - return "java"; - } - - public boolean isAddedToClasspath() { - return true; - } + assertNotNull(result); + assertOrderedElementsAreEqual(result.unresolvedArtifacts, new MavenId("fff", "zzz", "666")); } } diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/NexusIndexerTest.java b/plugins/maven/facade-impl/test/org/jetbrains/idea/maven/embedder/NexusIndexerTest.java similarity index 91% rename from plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/NexusIndexerTest.java rename to plugins/maven/facade-impl/test/org/jetbrains/idea/maven/embedder/NexusIndexerTest.java index 4f3c1f68ca46..e2eaad4c3edd 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/NexusIndexerTest.java +++ b/plugins/maven/facade-impl/test/org/jetbrains/idea/maven/embedder/NexusIndexerTest.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.maven.indices; +package org.jetbrains.idea.maven.embedder; import org.apache.lucene.document.Document; import org.apache.lucene.index.IndexReader; @@ -22,7 +22,11 @@ import org.apache.lucene.search.*; import org.apache.maven.artifact.manager.WagonManager; import org.apache.maven.wagon.events.TransferEvent; import org.apache.maven.wagon.events.TransferListener; -import org.jetbrains.idea.maven.embedder.MavenEmbedderWrapper; +import org.jetbrains.idea.maven.MavenCustomRepositoryHelper; +import org.jetbrains.idea.maven.facade.MavenFacadeManager; +import org.jetbrains.idea.maven.facade.embedder.MavenFacadeEmbedderImpl; +import org.jetbrains.idea.maven.facade.embedder.MavenIndexFetcher; +import org.jetbrains.idea.maven.indices.MavenIndicesTestCase; import org.sonatype.nexus.index.*; import org.sonatype.nexus.index.context.IndexingContext; import org.sonatype.nexus.index.updater.IndexUpdateRequest; @@ -35,8 +39,8 @@ import java.util.Collection; import java.util.List; public class NexusIndexerTest extends MavenIndicesTestCase { + private MavenFacadeEmbedderImpl myEmbedder; private MavenCustomRepositoryHelper myRepositoryHelper; - private MavenEmbedderWrapper myEmbedder; private NexusIndexer myIndexer; private IndexUpdater myUpdater; private File myIndexDir; @@ -46,7 +50,7 @@ public class NexusIndexerTest extends MavenIndicesTestCase { super.setUp(); myRepositoryHelper = new MavenCustomRepositoryHelper(myDir, "local1_index", "local1", "remote"); - myEmbedder = MavenEmbedderWrapper.create(getMavenGeneralSettings()); + myEmbedder = MavenFacadeEmbedderImpl.create(MavenFacadeManager.convertSettings(getMavenGeneralSettings())); myIndexer = myEmbedder.getComponent(NexusIndexer.class); myUpdater = myEmbedder.getComponent(IndexUpdater.class); @@ -153,7 +157,7 @@ public class NexusIndexerTest extends MavenIndicesTestCase { myIndexer.removeIndexingContext(i1, false); myIndexer.removeIndexingContext(i2, false); - + addContext("id", new File(myIndexDir, "one"), null, null); addContext("id", new File(myIndexDir, "two"), null, null); } @@ -171,13 +175,13 @@ public class NexusIndexerTest extends MavenIndicesTestCase { private IndexingContext addContext(String id, File indexDir, File repoDir, String repoUrl) throws Exception { return myIndexer.addIndexingContext( - id, - id, - repoDir, - indexDir, - repoUrl, - null, // repo update url - NexusIndexer.FULL_INDEX); + id, + id, + repoDir, + indexDir, + repoUrl, + null, // repo update url + NexusIndexer.FULL_INDEX); } private void assertSearchWorks() throws IOException { diff --git a/plugins/maven/facade/org/jetbrains/idea/maven/facade/nexus/ArtifactType.java b/plugins/maven/facade/org/jetbrains/idea/maven/facade/nexus/ArtifactType.java deleted file mode 100644 index 70ff84eaf0cf..000000000000 --- a/plugins/maven/facade/org/jetbrains/idea/maven/facade/nexus/ArtifactType.java +++ /dev/null @@ -1,371 +0,0 @@ - -/* - * Copyright 2000-2010 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.idea.maven.facade.nexus; - -import com.intellij.util.xmlb.annotations.Transient; - -import javax.xml.bind.annotation.*; -import java.io.Serializable; - - -/** - *

    Java class for artifactType complex type. - * - *

    The following schema fragment specifies the expected content contained within this class. - * - *

    - * <complexType name="artifactType">
    - *   <complexContent>
    - *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
    - *       <sequence>
    - *         <element name="resourceUri" type="{http://www.w3.org/2001/XMLSchema}string"/>
    - *         <element name="groupId" type="{http://www.w3.org/2001/XMLSchema}string"/>
    - *         <element name="artifactId" type="{http://www.w3.org/2001/XMLSchema}string"/>
    - *         <element name="version" type="{http://www.w3.org/2001/XMLSchema}string"/>
    - *         <element name="classifier" type="{http://www.w3.org/2001/XMLSchema}string"/>
    - *         <element name="packaging" type="{http://www.w3.org/2001/XMLSchema}string"/>
    - *         <element name="extension" type="{http://www.w3.org/2001/XMLSchema}string"/>
    - *         <element name="repoId" type="{http://www.w3.org/2001/XMLSchema}string"/>
    - *         <element name="contextId" type="{http://www.w3.org/2001/XMLSchema}string"/>
    - *         <element name="pomLink" type="{http://www.w3.org/2001/XMLSchema}string"/>
    - *         <element name="artifactLink" type="{http://www.w3.org/2001/XMLSchema}string"/>
    - *       </sequence>
    - *     </restriction>
    - *   </complexContent>
    - * </complexType>
    - * 
    - * - * - */ -@XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "artifactType", propOrder = { - "resourceUri", - "groupId", - "artifactId", - "version", - "classifier", - "packaging", - "extension", - "repoId", - "contextId", - "pomLink", - "artifactLink" -}) -public class ArtifactType implements Serializable { - - @XmlElement(required = true) - protected String resourceUri; - @XmlElement(required = true) - protected String groupId; - @XmlElement(required = true) - protected String artifactId; - @XmlElement(required = true) - protected String version; - @XmlElement(required = true) - protected String classifier; - @XmlElement(required = true) - protected String packaging; - @XmlElement(required = true) - protected String extension; - @XmlElement(required = true) - protected String repoId; - @XmlElement(required = true) - protected String contextId; - @XmlElement(required = true) - protected String pomLink; - @XmlElement(required = true) - protected String artifactLink; - - public ArtifactType() { - - } - - public ArtifactType(String groupId, String artifactId, String version) { - this.groupId = groupId; - this.artifactId = artifactId; - this.version = version; - } - - /** - * Gets the value of the resourceUri property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getResourceUri() { - return resourceUri; - } - - /** - * Sets the value of the resourceUri property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setResourceUri(String value) { - this.resourceUri = value; - } - - /** - * Gets the value of the groupId property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getGroupId() { - return groupId; - } - - /** - * Sets the value of the groupId property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setGroupId(String value) { - this.groupId = value; - } - - /** - * Gets the value of the artifactId property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getArtifactId() { - return artifactId; - } - - /** - * Sets the value of the artifactId property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setArtifactId(String value) { - this.artifactId = value; - } - - /** - * Gets the value of the version property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getVersion() { - return version; - } - - /** - * Sets the value of the version property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setVersion(String value) { - this.version = value; - } - - /** - * Gets the value of the classifier property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getClassifier() { - return classifier; - } - - /** - * Sets the value of the classifier property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setClassifier(String value) { - this.classifier = value; - } - - /** - * Gets the value of the packaging property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getPackaging() { - return packaging; - } - - /** - * Sets the value of the packaging property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setPackaging(String value) { - this.packaging = value; - } - - /** - * Gets the value of the extension property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getExtension() { - return extension; - } - - /** - * Sets the value of the extension property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setExtension(String value) { - this.extension = value; - } - - /** - * Gets the value of the repoId property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getRepoId() { - return repoId; - } - - /** - * Sets the value of the repoId property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setRepoId(String value) { - this.repoId = value; - } - - /** - * Gets the value of the contextId property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getContextId() { - return contextId; - } - - /** - * Sets the value of the contextId property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setContextId(String value) { - this.contextId = value; - } - - /** - * Gets the value of the pomLink property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getPomLink() { - return pomLink; - } - - /** - * Sets the value of the pomLink property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setPomLink(String value) { - this.pomLink = value; - } - - /** - * Gets the value of the artifactLink property. - * - * @return - * possible object is - * {@link String } - * - */ - public String getArtifactLink() { - return artifactLink; - } - - /** - * Sets the value of the artifactLink property. - * - * @param value - * allowed object is - * {@link String } - * - */ - public void setArtifactLink(String value) { - this.artifactLink = value; - } - - @Override - public String toString() { - return groupId +":"+artifactId+":"+version; - } -} diff --git a/plugins/maven/facade/org/jetbrains/idea/maven/facade/remote/MavenFacade.java b/plugins/maven/facade/org/jetbrains/idea/maven/facade/remote/MavenFacade.java deleted file mode 100644 index 77f698a89f4f..000000000000 --- a/plugins/maven/facade/org/jetbrains/idea/maven/facade/remote/MavenFacade.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2000-2010 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.idea.maven.facade.remote; - -import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.maven.facade.nexus.ArtifactType; -import org.jetbrains.idea.maven.facade.nexus.RepositoryType; - -import java.io.Serializable; -import java.rmi.Remote; -import java.rmi.RemoteException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * @author Gregory.Shrago - */ -public interface MavenFacade extends Remote { - - List getRepositories(String nexusUrl) throws RemoteException; - - @Nullable - List findArtifacts(ArtifactType template, String nexusUrl) throws RemoteException; - - Map> resolveDependencies(List artifacts) throws RemoteException; - - void setTransferListener(RemoteTransferListener listener) throws RemoteException; - - void setMavenSettings(MavenFacadeSettings settings) throws RemoteException; - - class MavenFacadeSettings implements Serializable { - private Repository myLocalRepository; - private final List myRemoteRepositories = new ArrayList(); - - public Repository getLocalRepository() { - return myLocalRepository; - } - - public void setLocalRepository(Repository localRepository) { - myLocalRepository = localRepository; - } - - public List getRemoteRepositories() { - return myRemoteRepositories; - } - } - - class Repository implements Serializable { - private String myId; - private String myUrl; - private String myLayout; - - public Repository(String id, String url, String layout) { - myUrl = url; - myId = id; - myLayout = layout; - } - - public String getId() { - return myId; - } - - public void setId(String id) { - myId = id; - } - - public String getUrl() { - return myUrl; - } - - public void setUrl(String url) { - myUrl = url; - } - - public String getLayout() { - return myLayout; - } - - public void setLayout(String layout) { - myLayout = layout; - } - } - -} diff --git a/plugins/maven/facade/org/jetbrains/idea/maven/facade/remote/impl/MavenFacadeImpl.java b/plugins/maven/facade/org/jetbrains/idea/maven/facade/remote/impl/MavenFacadeImpl.java deleted file mode 100644 index 90389f53cf7d..000000000000 --- a/plugins/maven/facade/org/jetbrains/idea/maven/facade/remote/impl/MavenFacadeImpl.java +++ /dev/null @@ -1,393 +0,0 @@ -/* - * Copyright 2000-2010 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.idea.maven.facade.remote.impl; - -import org.apache.maven.artifact.Artifact; -import org.apache.maven.artifact.DefaultArtifact; -import org.apache.maven.artifact.factory.ArtifactFactory; -import org.apache.maven.artifact.manager.WagonManager; -import org.apache.maven.artifact.metadata.ArtifactMetadataSource; -import org.apache.maven.artifact.repository.ArtifactRepository; -import org.apache.maven.artifact.repository.DefaultArtifactRepository; -import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout; -import org.apache.maven.artifact.resolver.*; -import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter; -import org.apache.maven.artifact.versioning.VersionRange; -import org.apache.maven.settings.MavenSettingsBuilder; -import org.apache.maven.settings.RuntimeInfo; -import org.apache.maven.settings.Settings; -import org.apache.maven.artifact.versioning.ArtifactVersion; -import org.apache.maven.wagon.events.TransferEvent; -import org.apache.maven.wagon.events.TransferListener; -import org.codehaus.classworlds.ClassWorld; -import org.codehaus.plexus.DefaultPlexusContainer; -import org.codehaus.plexus.PlexusContainerException; -import org.codehaus.plexus.component.repository.exception.ComponentLookupException; -import org.codehaus.plexus.util.xml.pull.XmlPullParserException; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.maven.facade.nexus.ArtifactType; -import org.jetbrains.idea.maven.facade.nexus.Endpoint; -import org.jetbrains.idea.maven.facade.nexus.RepositoryType; -import org.jetbrains.idea.maven.facade.nexus.SearchResults; -import org.jetbrains.idea.maven.facade.remote.MavenFacade; -import org.jetbrains.idea.maven.facade.remote.RemoteTransferListener; - -import java.io.IOException; -import java.math.BigInteger; -import java.net.MalformedURLException; -import java.rmi.RemoteException; -import java.util.*; - -/** - * @author Gregory.Shrago - */ -public class MavenFacadeImpl extends RemoteImpl implements MavenFacade { - - private static final DefaultPlexusContainer ourContainer = initializeMaven(); - private MavenFacadeSettings mySettings; - - public static DefaultPlexusContainer initializeMaven() { - DefaultPlexusContainer container; - try { - container = new DefaultPlexusContainer(); - } - catch (RuntimeException e) { - String s = "Cannot initialize Maven. Please make sure that your IDEA installation is correct and has no old libraries."; - throw new RuntimeException(s, e); - } - - container.setClassWorld(new ClassWorld("plexus.core", Thread.currentThread().getContextClassLoader())); -// CustomLoggerManager loggerManager = new CustomLoggerManager(generalSettings.getLoggingLevel()); -// container.setLoggerManager(loggerManager); - - try { - container.initialize(); - container.start(); - } - catch (PlexusContainerException e) { - throw new RuntimeException(e); - } - -// System.setProperty("maven.home", "<...>"); -// System.setProperty(MavenSettingsBuilder.ALT_GLOBAL_SETTINGS_XML_LOCATION, "<..>"); - - Settings settings = null; - - try { - MavenSettingsBuilder builder = (MavenSettingsBuilder)container.lookup(MavenSettingsBuilder.ROLE); -// File userSettingsFile = generalSettings.getEffectiveUserSettingsIoFile(); -// if (userSettingsFile != null && userSettingsFile.exists() && !userSettingsFile.isDirectory()) { -// settings = builder.buildSettings(userSettingsFile, false); -// } - if (settings == null) { - settings = builder.buildSettings(); - } - } - catch (ComponentLookupException e) { - e.printStackTrace(); - } - catch (IOException e) { - e.printStackTrace(); - } - catch (XmlPullParserException e) { - e.printStackTrace(); - } - - if (settings == null) { - settings = new Settings(); - } - -// settings.setLocalRepository("<...>"); - - settings.setOffline(false); - settings.setInteractiveMode(false); - settings.setUsePluginRegistry(false); - - RuntimeInfo runtimeInfo = new RuntimeInfo(settings); -// runtimeInfo.setPluginUpdateOverride(generalSettings.getPluginUpdatePolicy() == MavenExecutionOptions.PluginUpdatePolicy.UPDATE); - settings.setRuntimeInfo(runtimeInfo); - - return container; - - } - - public List getRepositories(String nexusUrl) throws RemoteException { - try { - return new Endpoint.Repositories(nexusUrl).getRepolistAsRepositories().getData().getRepositoriesItem(); - } - catch (Exception ex) { - handleException(ex); - throw new AssertionError(); - } - } - - @Nullable - public List findArtifacts(ArtifactType template, String nexusUrl) throws RemoteException { - try { - SearchResults results = new Endpoint.DataIndex(nexusUrl) - .getArtifactlistAsSearchResults(null, template.getGroupId(), template.getArtifactId(), template.getVersion(), - template.getClassifier(), template.getContextId()); - final boolean canTrySwitchGAV = template.getArtifactId() == null && template.getGroupId() != null; - final boolean tooManyResults = results.isTooManyResults(); - if (canTrySwitchGAV && (tooManyResults || BigInteger.ZERO.equals(results.getTotalCount()))) { - results = new Endpoint.DataIndex(nexusUrl) - .getArtifactlistAsSearchResults(null, null, template.getGroupId(), template.getVersion(), - template.getClassifier(), template.getContextId()); - } - if (tooManyResults || results.isTooManyResults()) return null; - return new ArrayList(results.getData().getArtifact()); - } - catch (Exception ex) { - handleException(ex); - throw new AssertionError(); - } - } - - private void addMissingVersions(final Map result) { - try { - final ArtifactMetadataSource metadataSource = (ArtifactMetadataSource)ourContainer.lookup(ArtifactMetadataSource.ROLE); - final ArtifactFactory artifactFactory = (ArtifactFactory)ourContainer.lookup(ArtifactFactory.ROLE); - final ArtifactRepository localRepo = getRepository(mySettings.getLocalRepository()); - final List remoteRepos = new ArrayList(); - for (Repository repository : mySettings.getRemoteRepositories()) { - remoteRepos.add(getRepository(repository)); - } - final HashSet visitedIds = new HashSet(); - for (ArtifactType artifactType : result.values()) { - if (!visitedIds.add(artifactType.getGroupId()+":"+artifactType.getArtifactId())) continue; - if (artifactType.getPackaging() == null) continue; - final Artifact artifact = createArtifact(artifactFactory, artifactType); - try { - final List list = metadataSource.retrieveAvailableVersions(artifact, localRepo, remoteRepos); - for (ArtifactVersion version : list) { - final String coord = artifact.getGroupId() + ":" + artifact.getArtifactId() + ":" + version; - if (!result.containsKey(coord)) { - final ArtifactType type = new ArtifactType(artifactType.getGroupId(), artifactType.getArtifactId(), version.toString()); - type.setPackaging(artifact.getType()); - result.put(coord, type); - } - } - } - catch (Exception ex) { - ex.printStackTrace(); - } - } - } - catch (Exception e) { - handleException(e); - throw new AssertionError(); - } - } - - public Map> resolveDependencies(List artifacts) throws RemoteException { - try { - return resolveDependenciesInner(artifacts); - } - catch (Exception e) { - handleException(e); - throw new AssertionError(); - } - } - - public void setTransferListener(final RemoteTransferListener listener) throws RemoteException { - try { - final WagonManager wagonManager = (WagonManager)ourContainer.lookup(WagonManager.ROLE); - if (listener == null) { - wagonManager.setDownloadMonitor(null); - return; - } - wagonManager.setDownloadMonitor(new TransferListener() { - public void transferInitiated(TransferEvent transferEvent) { - try { - listener.transferInitiated(convert(transferEvent)); - } - catch (RemoteException ignored) { } - } - - public void transferStarted(TransferEvent transferEvent) { - try { - listener.transferStarted(convert(transferEvent)); - } - catch (RemoteException ignored) { - } - } - - public void transferProgress(TransferEvent transferEvent, byte[] bytes, int i) { - try { - listener.transferProgress(convert(transferEvent), i); - } - catch (RemoteException ignored) { - } - } - - public void transferCompleted(TransferEvent transferEvent) { - try { - listener.transferCompleted(convert(transferEvent)); - } - catch (RemoteException ignored) { - } - } - - public void transferError(TransferEvent transferEvent) { - try { - listener.transferError(convert(transferEvent)); - } - catch (RemoteException ignored) { - } - } - - public void debug(String s) { - try { - listener.debug(s); - } - catch (RemoteException ignored) { - } - } - }); - } - catch (Exception e) { - handleException(e); - throw new AssertionError(); - } - } - - public void setMavenSettings(MavenFacadeSettings settings) throws RemoteException { - mySettings = settings; - } - - private static RemoteTransferListener.TransferEvent convert(TransferEvent transferEvent) { - final RemoteTransferListener.TransferEvent.EventType et; - switch (transferEvent.getEventType()) { - case TransferEvent.TRANSFER_INITIATED: et = RemoteTransferListener.TransferEvent.EventType.INITIATED; break; - case TransferEvent.TRANSFER_STARTED: et = RemoteTransferListener.TransferEvent.EventType.STARTED; break; - case TransferEvent.TRANSFER_PROGRESS: et = RemoteTransferListener.TransferEvent.EventType.PROGRESS; break; - case TransferEvent.TRANSFER_COMPLETED: et = RemoteTransferListener.TransferEvent.EventType.COMPLETED; break; - case TransferEvent.TRANSFER_ERROR: et = RemoteTransferListener.TransferEvent.EventType.ERROR; break; - default: throw new AssertionError(transferEvent.getEventType()); - } - final RemoteTransferListener.TransferEvent.RequestType reqType = transferEvent.getRequestType() == TransferEvent.REQUEST_GET - ? RemoteTransferListener.TransferEvent.RequestType.GET - : RemoteTransferListener.TransferEvent.RequestType.PUT; - final RemoteTransferListener.Resource resource = new RemoteTransferListener.Resource(transferEvent.getResource().getName(), - transferEvent.getResource().getLastModified(), - transferEvent.getResource().getContentLength()); - return new RemoteTransferListener.TransferEvent(transferEvent.getLocalFile(), et, reqType, resource, transferEvent.getException(), transferEvent.getWagon().getRepository().getUrl()); - } - - - private Map> resolveDependenciesInner(List artifactsToResolve) throws Exception { - final ArtifactResolver resolver = (ArtifactResolver)ourContainer.lookup(ArtifactResolver.ROLE); - final ArtifactFactory artifactFactory = (ArtifactFactory)ourContainer.lookup(ArtifactFactory.ROLE); - final ArtifactMetadataSource metadataSource = (ArtifactMetadataSource)ourContainer.lookup(ArtifactMetadataSource.ROLE); - - final ArtifactRepository localRepo = getRepository(mySettings.getLocalRepository()); - final List remoteRepos = new ArrayList(); - for (Repository repository : mySettings.getRemoteRepositories()) { - remoteRepos.add(getRepository(repository)); - } - - - final Artifact project = artifactFactory.createBuildArtifact("local", "project", "1.0", "pom"); - final Set toResolve = new HashSet(); - for (ArtifactType template : artifactsToResolve) { - toResolve.add(createArtifact(artifactFactory, template)); - } - - final Map> resultMap = new HashMap>(); - for (Artifact artifact : toResolve) { - try { - final ArtifactResolutionResult result = resolver.resolveTransitively( - Collections.singleton(artifact), project, Collections.EMPTY_MAP, localRepo, remoteRepos, - metadataSource, new ScopeArtifactFilter(DefaultArtifact.SCOPE_RUNTIME)); - resultMap.put(getCoordinate(artifact), toArtifactTypeList(result.getArtifacts())); - } - catch (MultipleArtifactsNotFoundException e) { - resultMap.put(getCoordinate(artifact), toArtifactTypeList(e.getResolvedArtifacts())); - //System.out.println("Missing: -------------------"); - //toArtifactTypeList(e.getMissingArtifacts()); - } - catch (ArtifactResolutionException e) { - //throw e; - } - catch (ArtifactNotFoundException e) { - //throw e; - //System.out.println("Missing: -------------------"); - //toArtifactTypeList(Collections.singletonList(e.getArtifact())); - } - } - return resultMap; - } - - private Artifact createArtifact(ArtifactFactory artifactFactory, ArtifactType template) { - return artifactFactory.createDependencyArtifact( - template.getGroupId(), - template.getArtifactId(), - template.getVersion() == null? null : VersionRange.createFromVersion(template.getVersion()), - template.getPackaging(), - null, - "runtime"); - } - - private static ArtifactRepository getRepository(Repository r) throws ComponentLookupException { - final ArtifactRepositoryLayout repoLayout = (ArtifactRepositoryLayout)ourContainer.lookup(ArtifactRepositoryLayout.ROLE, r.getLayout()); - return new DefaultArtifactRepository(r.getId(), r.getUrl(), repoLayout); - } - - private static Map> toArtifactTypeMap(Collection toResolve, Collection resolvedArtifacts) { - final Map> result = new HashMap>(); - final Map idMap = new HashMap(); - for (Artifact artifact : toResolve) { - idMap.put(artifact.getId(), getCoordinate(artifact)); - result.put(getCoordinate(artifact), new ArrayList()); - } - for (Artifact artifact : resolvedArtifacts) { - List list = null; - for (String s : artifact.getDependencyTrail()) { - list = result.get(idMap.get(s)); - if (list != null) { - list.add(toArtifactType(artifact)); - break; - } - } - if (list == null) { - throw new AssertionError(getCoordinate(artifact)); - } - } - return result; - } - - private static String getCoordinate(Artifact artifact) { - return artifact.getGroupId()+":"+artifact.getArtifactId()+":"+artifact.getVersion(); - } - - private static List toArtifactTypeList(Collection artifacts) throws MalformedURLException { - final ArrayList result = new ArrayList(artifacts.size()); - for (Artifact artifact : artifacts) { - result.add(toArtifactType(artifact)); - } - return result; - } - - private static ArtifactType toArtifactType(Artifact artifact) { - final ArtifactType type = new ArtifactType(); - type.setGroupId(artifact.getGroupId()); - type.setArtifactId(artifact.getArtifactId()); - type.setVersion(artifact.getVersion()); - type.setClassifier(artifact.getClassifier()); - type.setResourceUri(artifact.getFile().toURI().toASCIIString()); - return type; - } -} diff --git a/plugins/maven/facade/org/jetbrains/idea/maven/facade/remote/impl/RemoteTransferListenerImpl.java b/plugins/maven/facade/org/jetbrains/idea/maven/facade/remote/impl/RemoteTransferListenerImpl.java deleted file mode 100644 index d418cc5ed90d..000000000000 --- a/plugins/maven/facade/org/jetbrains/idea/maven/facade/remote/impl/RemoteTransferListenerImpl.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.jetbrains.idea.maven.facade.remote.impl; - -import org.jetbrains.idea.maven.facade.remote.RemoteTransferListener; - -/** - * @author Gregory.Shrago - */ -public class RemoteTransferListenerImpl extends RemoteImpl implements RemoteTransferListener { - - public void transferInitiated(TransferEvent transferEvent) { - } - - public void transferStarted(TransferEvent transferEvent) { - } - - public void transferProgress(TransferEvent transferEvent, int length) { - } - - public void transferCompleted(TransferEvent transferEvent) { - } - - public void transferError(TransferEvent transferEvent) { - } - - public void debug(String s) { - } - -} diff --git a/plugins/maven/lib/maven-embedder-1.0-SNAPSHOT.jar b/plugins/maven/lib/maven-embedder-1.0-SNAPSHOT.jar deleted file mode 100644 index 0670771f4a8d42a3f9bebf011236b385e75c6dc1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25822 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 diff --git a/plugins/maven/maven-facade.iml b/plugins/maven/maven-facade.iml deleted file mode 100644 index c7e166df27e9..000000000000 --- a/plugins/maven/maven-facade.iml +++ /dev/null @@ -1,103 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/plugins/maven/maven.iml b/plugins/maven/maven.iml index 714f1b53190b..276526c316bf 100644 --- a/plugins/maven/maven.iml +++ b/plugins/maven/maven.iml @@ -10,110 +10,12 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + @@ -121,14 +23,13 @@ - + + - - diff --git a/plugins/maven/src/main/java/org/apache/maven/project/JBMavenProjectHelper.java b/plugins/maven/src/main/java/org/apache/maven/project/JBMavenProjectHelper.java deleted file mode 100644 index b771720203a7..000000000000 --- a/plugins/maven/src/main/java/org/apache/maven/project/JBMavenProjectHelper.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.maven.project; - -import java.util.List; - -public class JBMavenProjectHelper { - public static void setSourceRoots(MavenProject project, - List compileSourceRoots, - List testCompileSourceRoots, - List scriptSourceRoots) { - project.setCompileSourceRoots(compileSourceRoots); - project.setTestCompileSourceRoots(testCompileSourceRoots); - project.setScriptSourceRoots(scriptSourceRoots); - } -} diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/compiler/MavenResourceCompiler.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/compiler/MavenResourceCompiler.java index f674f9c1444e..55e25132e819 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/compiler/MavenResourceCompiler.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/compiler/MavenResourceCompiler.java @@ -44,7 +44,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.maven.dom.MavenPropertyResolver; import org.jetbrains.idea.maven.project.MavenProject; import org.jetbrains.idea.maven.project.MavenProjectsManager; -import org.jetbrains.idea.maven.project.MavenResource; +import org.jetbrains.idea.maven.model.MavenResource; import org.jetbrains.idea.maven.utils.MavenJDOMUtil; import org.jetbrains.idea.maven.utils.MavenLog; import org.jetbrains.idea.maven.utils.MavenUtil; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenDomProjectProcessorUtils.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenDomProjectProcessorUtils.java index 72fe08125678..75d2cc0fae74 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenDomProjectProcessorUtils.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenDomProjectProcessorUtils.java @@ -26,6 +26,7 @@ import com.intellij.util.xml.DomUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.maven.dom.model.*; +import org.jetbrains.idea.maven.model.MavenId; import org.jetbrains.idea.maven.project.*; import org.jetbrains.idea.maven.utils.MavenUtil; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenDomUtil.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenDomUtil.java index ef805034e20b..1bf3b6815219 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenDomUtil.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenDomUtil.java @@ -28,7 +28,6 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.vfs.VirtualFileSystem; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; @@ -42,8 +41,11 @@ import com.intellij.util.xml.reflect.DomCollectionChildDescription; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.maven.dom.model.*; +import org.jetbrains.idea.maven.model.MavenArtifact; +import org.jetbrains.idea.maven.model.MavenConstants; +import org.jetbrains.idea.maven.model.MavenId; +import org.jetbrains.idea.maven.model.MavenResource; import org.jetbrains.idea.maven.project.*; -import org.jetbrains.idea.maven.utils.MavenConstants; import org.jetbrains.idea.maven.utils.MavenLog; import org.jetbrains.idea.maven.vfs.MavenPropertiesVirtualFileSystem; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPropertyResolver.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPropertyResolver.java index 385ac14d8797..060067ba2cda 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPropertyResolver.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPropertyResolver.java @@ -18,16 +18,13 @@ package org.jetbrains.idea.maven.dom; import com.intellij.openapi.module.Module; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.xml.XmlTag; -import org.apache.commons.beanutils.BeanAccessLanguageException; -import org.apache.commons.beanutils.BeanUtils; import org.jetbrains.idea.maven.dom.model.MavenDomProfile; import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel; import org.jetbrains.idea.maven.dom.model.MavenDomProperties; -import org.jetbrains.idea.maven.embedder.MavenEmbedderWrapper; +import org.jetbrains.idea.maven.facade.MavenFacadeUtil; import org.jetbrains.idea.maven.project.MavenProject; import org.jetbrains.idea.maven.project.MavenProjectsManager; -import java.lang.reflect.InvocationTargetException; import java.util.Collection; import java.util.Properties; import java.util.Stack; @@ -137,7 +134,7 @@ public class MavenPropertyResolver { private static String doResolveProperty(String propName, MavenProject project, Properties additionalProperties) { String result; - result = MavenEmbedderWrapper.collectSystemProperties().getProperty(propName); + result = MavenFacadeUtil.collectSystemProperties().getProperty(propName); if (result != null) return result; if (propName.startsWith("project.") || propName.startsWith("pom.")) { @@ -151,19 +148,7 @@ public class MavenPropertyResolver { if (propName.equals("basedir")) return project.getDirectory(); - try { - result = BeanUtils.getNestedProperty(project.getMavenModel(), propName); - } - catch (IllegalAccessException e) { - } - catch (BeanAccessLanguageException e) { - } - catch (InvocationTargetException e) { - } - catch (NoSuchMethodException e) { - } - catch (IllegalArgumentException e) { - } + result = project.getModelMap().get(propName); if (result != null) return result; result = additionalProperties.getProperty(propName); diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/annotator/MavenDomAnnotator.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/annotator/MavenDomAnnotator.java index 6314cd034ae7..1227c5e913bc 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/annotator/MavenDomAnnotator.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/annotator/MavenDomAnnotator.java @@ -20,8 +20,8 @@ import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.lang.annotation.HighlightSeverity; import com.intellij.openapi.fileEditor.OpenFileDescriptor; import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.ArrayUtil; import com.intellij.util.xml.DomElement; import com.intellij.util.xml.DomUtil; import com.intellij.util.xml.highlighting.DomElementAnnotationHolder; @@ -31,8 +31,8 @@ import org.jetbrains.idea.maven.dom.MavenDomBundle; import org.jetbrains.idea.maven.dom.MavenDomUtil; import org.jetbrains.idea.maven.dom.model.MavenDomParent; import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel; +import org.jetbrains.idea.maven.model.MavenProjectProblem; import org.jetbrains.idea.maven.project.MavenProject; -import org.jetbrains.idea.maven.project.MavenProjectProblem; import java.util.Arrays; @@ -56,7 +56,7 @@ public class MavenDomAnnotator implements DomElementsAnnotator { for (MavenProjectProblem each : mavenProject.getProblems()) { MavenProjectProblem.ProblemType type = each.getType(); if (!Arrays.asList(types).contains(type)) continue; - VirtualFile problemFile = each.findFile(); + VirtualFile problemFile = LocalFileSystem.getInstance().findFileByPath(each.getPath()); LocalQuickFix[] fixes = LocalQuickFix.EMPTY_ARRAY; if (problemFile != null && mavenProject.getFile() != problemFile) { diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenArtifactCoordinatesArtifactIdConverter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenArtifactCoordinatesArtifactIdConverter.java index b0af15571625..ed8cc955fc80 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenArtifactCoordinatesArtifactIdConverter.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenArtifactCoordinatesArtifactIdConverter.java @@ -18,7 +18,7 @@ package org.jetbrains.idea.maven.dom.converters; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.xml.ConvertContext; import org.jetbrains.idea.maven.indices.MavenProjectIndicesManager; -import org.jetbrains.idea.maven.project.MavenId; +import org.jetbrains.idea.maven.model.MavenId; import java.util.Set; import java.util.Collections; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenArtifactCoordinatesConverter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenArtifactCoordinatesConverter.java index 06164dc2818d..2d2b055af365 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenArtifactCoordinatesConverter.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenArtifactCoordinatesConverter.java @@ -36,7 +36,7 @@ import org.jetbrains.idea.maven.dom.model.*; import org.jetbrains.idea.maven.dom.MavenDomUtil; import org.jetbrains.idea.maven.dom.MavenDomBundle; import org.jetbrains.idea.maven.indices.MavenProjectIndicesManager; -import org.jetbrains.idea.maven.project.MavenId; +import org.jetbrains.idea.maven.model.MavenId; import org.jetbrains.idea.maven.project.MavenProject; import org.jetbrains.idea.maven.project.MavenProjectsManager; import org.jetbrains.idea.maven.utils.MavenArtifactUtil; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenArtifactCoordinatesGroupIdConverter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenArtifactCoordinatesGroupIdConverter.java index ada8abd01195..6a471d5b7f53 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenArtifactCoordinatesGroupIdConverter.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenArtifactCoordinatesGroupIdConverter.java @@ -3,13 +3,10 @@ package org.jetbrains.idea.maven.dom.converters; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.containers.hash.HashSet; import com.intellij.util.xml.ConvertContext; -import com.intellij.util.xml.impl.ConvertContextImpl; -import org.jetbrains.idea.maven.dom.model.MavenDomShortArtifactCoordinates; import org.jetbrains.idea.maven.indices.MavenProjectIndicesManager; -import org.jetbrains.idea.maven.project.MavenId; +import org.jetbrains.idea.maven.model.MavenId; import java.util.Collection; -import java.util.Collections; import java.util.Set; public class MavenArtifactCoordinatesGroupIdConverter extends MavenArtifactCoordinatesConverter { diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenArtifactCoordinatesHelper.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenArtifactCoordinatesHelper.java index 7429a956ad35..9867a927256a 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenArtifactCoordinatesHelper.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenArtifactCoordinatesHelper.java @@ -19,7 +19,7 @@ import com.intellij.util.xml.ConvertContext; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.maven.dom.model.MavenDomArtifactCoordinates; import org.jetbrains.idea.maven.dom.model.MavenDomShortArtifactCoordinates; -import org.jetbrains.idea.maven.project.MavenId; +import org.jetbrains.idea.maven.model.MavenId; public class MavenArtifactCoordinatesHelper { public static MavenId getId(ConvertContext context) { diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenArtifactCoordinatesVersionConverter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenArtifactCoordinatesVersionConverter.java index 9812834abde7..22194e67adeb 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenArtifactCoordinatesVersionConverter.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenArtifactCoordinatesVersionConverter.java @@ -18,7 +18,7 @@ package org.jetbrains.idea.maven.dom.converters; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.xml.ConvertContext; import org.jetbrains.idea.maven.indices.MavenProjectIndicesManager; -import org.jetbrains.idea.maven.project.MavenId; +import org.jetbrains.idea.maven.model.MavenId; import java.util.Collections; import java.util.Set; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenDependencyScopeConverter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenDependencyScopeConverter.java index 92d2ebac7cdf..a37b2a0d6ba1 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenDependencyScopeConverter.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenDependencyScopeConverter.java @@ -16,9 +16,8 @@ package org.jetbrains.idea.maven.dom.converters; import com.intellij.util.xml.ConvertContext; -import com.intellij.util.xml.DomManager; import org.jetbrains.idea.maven.dom.model.MavenDomDependencyManagement; -import org.jetbrains.idea.maven.utils.MavenConstants; +import org.jetbrains.idea.maven.model.MavenConstants; import java.util.Arrays; import java.util.List; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenParentRelativePathConverter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenParentRelativePathConverter.java index 8833a4c11af5..99e83a9809d4 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenParentRelativePathConverter.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenParentRelativePathConverter.java @@ -30,13 +30,12 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel; -import org.jetbrains.idea.maven.dom.converters.MavenArtifactCoordinatesHelper; import org.jetbrains.idea.maven.dom.MavenDomUtil; import org.jetbrains.idea.maven.dom.MavenDomBundle; +import org.jetbrains.idea.maven.model.MavenId; import org.jetbrains.idea.maven.project.MavenProject; import org.jetbrains.idea.maven.project.MavenProjectsManager; -import org.jetbrains.idea.maven.utils.MavenConstants; -import org.jetbrains.idea.maven.project.MavenId; +import org.jetbrains.idea.maven.model.MavenConstants; import java.util.ArrayList; import java.util.Collection; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/repositories/MavenRepositoriesProvider.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/repositories/MavenRepositoriesProvider.java index eb1250fcc0f3..73f1dfa9c3b3 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/repositories/MavenRepositoriesProvider.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/repositories/MavenRepositoriesProvider.java @@ -69,10 +69,4 @@ public class MavenRepositoriesProvider { RepositoryBeanInfo pair = myRepositoriesMap.get(id); return pair != null ? pair.getUrl() : null; } - - @Nullable - public String getRepositoryLayout(@Nullable String id) { - RepositoryBeanInfo pair = myRepositoriesMap.get(id); - return pair != null ? pair.getLayout() : null; - } } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/repositories/beans/RepositoryBeanInfo.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/repositories/beans/RepositoryBeanInfo.java index e3767bbfac57..96f918b3e937 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/repositories/beans/RepositoryBeanInfo.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/repositories/beans/RepositoryBeanInfo.java @@ -32,9 +32,6 @@ public class RepositoryBeanInfo { @Attribute("url") public String myUrl; - @Attribute("layout") - public String myLayout; - public String getId() { return myId; } @@ -46,8 +43,4 @@ public class RepositoryBeanInfo { public String getUrl() { return myUrl; } - - public String getLayout() { - return myLayout; - } } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/generate/GenerateAddManagedDependencyAction.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/generate/GenerateAddManagedDependencyAction.java index 8124b2118b9e..479896edef4d 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/generate/GenerateAddManagedDependencyAction.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/generate/GenerateAddManagedDependencyAction.java @@ -29,8 +29,6 @@ import org.jetbrains.idea.maven.dom.MavenDomUtil; import org.jetbrains.idea.maven.dom.model.MavenDomDependencies; import org.jetbrains.idea.maven.dom.model.MavenDomDependency; import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel; -import org.jetbrains.idea.maven.project.MavenId; -import org.jetbrains.idea.maven.project.MavenProjectsManager; import org.jetbrains.idea.maven.utils.MavenIcons; import java.util.List; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/generate/GenerateDependencyAction.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/generate/GenerateDependencyAction.java index 313848c9281c..c0a3647a023f 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/generate/GenerateDependencyAction.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/generate/GenerateDependencyAction.java @@ -19,8 +19,7 @@ import com.intellij.openapi.editor.Editor; import com.intellij.psi.PsiDocumentManager; import com.intellij.util.xml.ui.actions.generate.GenerateDomElementAction; import org.jetbrains.idea.maven.dom.MavenDomBundle; -import org.jetbrains.idea.maven.dom.model.MavenDomBuild; -import org.jetbrains.idea.maven.project.MavenId; +import org.jetbrains.idea.maven.model.MavenId; import org.jetbrains.idea.maven.dom.model.MavenDomDependency; import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel; import org.jetbrains.idea.maven.indices.MavenArtifactSearchDialog; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/inspections/MavenDuplicateDependenciesInspection.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/inspections/MavenDuplicateDependenciesInspection.java index 7579c0e46897..694a384e69f1 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/inspections/MavenDuplicateDependenciesInspection.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/inspections/MavenDuplicateDependenciesInspection.java @@ -34,7 +34,7 @@ import org.jetbrains.idea.maven.dom.MavenDomUtil; import org.jetbrains.idea.maven.dom.model.MavenDomArtifactCoordinates; import org.jetbrains.idea.maven.dom.model.MavenDomDependency; import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel; -import org.jetbrains.idea.maven.project.MavenId; +import org.jetbrains.idea.maven.model.MavenId; import org.jetbrains.idea.maven.project.MavenProject; import java.util.HashMap; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/intentions/AddMavenDependencyQuickFix.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/intentions/AddMavenDependencyQuickFix.java index 88ed35d1064c..f54784386e4d 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/intentions/AddMavenDependencyQuickFix.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/intentions/AddMavenDependencyQuickFix.java @@ -27,9 +27,9 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.maven.dom.MavenDomBundle; import org.jetbrains.idea.maven.dom.MavenDomUtil; import org.jetbrains.idea.maven.indices.MavenArtifactSearchDialog; +import org.jetbrains.idea.maven.model.MavenId; import org.jetbrains.idea.maven.project.MavenProject; import org.jetbrains.idea.maven.project.MavenProjectsManager; -import org.jetbrains.idea.maven.project.MavenId; public class AddMavenDependencyQuickFix implements IntentionAction, LowPriorityAction { private final PsiJavaCodeReferenceElement myRef; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/references/MavenModulePsiReference.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/references/MavenModulePsiReference.java index 48fde73e1ec1..5e94047a700e 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/references/MavenModulePsiReference.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/references/MavenModulePsiReference.java @@ -33,8 +33,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.maven.dom.MavenDomBundle; import org.jetbrains.idea.maven.dom.MavenDomUtil; import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel; -import org.jetbrains.idea.maven.project.MavenId; -import org.jetbrains.idea.maven.utils.MavenConstants; +import org.jetbrains.idea.maven.model.MavenConstants; +import org.jetbrains.idea.maven.model.MavenId; import org.jetbrains.idea.maven.utils.MavenUtil; import java.io.IOException; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/references/MavenPropertyPsiReference.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/references/MavenPropertyPsiReference.java index 9921ceb0cc14..d9d441333e65 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/references/MavenPropertyPsiReference.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/references/MavenPropertyPsiReference.java @@ -44,6 +44,7 @@ import org.jetbrains.idea.maven.dom.MavenDomProjectProcessorUtils; import org.jetbrains.idea.maven.dom.MavenDomUtil; import org.jetbrains.idea.maven.dom.MavenSchemaProvider; import org.jetbrains.idea.maven.dom.model.*; +import org.jetbrains.idea.maven.model.MavenId; import org.jetbrains.idea.maven.project.*; import org.jetbrains.idea.maven.utils.MavenIcons; import org.jetbrains.idea.maven.vfs.MavenPropertiesVirtualFileSystem; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/CustomLoggerManager.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/CustomLoggerManager.java deleted file mode 100644 index a6b533b783fa..000000000000 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/CustomLoggerManager.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.idea.maven.embedder; - -import org.codehaus.plexus.logging.AbstractLoggerManager; -import org.codehaus.plexus.logging.Logger; - -public class CustomLoggerManager extends AbstractLoggerManager { - private final MavenLogger myLogger; - - - - public CustomLoggerManager(MavenExecutionOptions.LoggingLevel loggingLevel) { - myLogger = new MavenLogger(); - myLogger.setThreshold(loggingLevel.getLevel()); - } - - public MavenLogger getLogger() { - return myLogger; - } - - public void setThreshold(int i) { - } - - public int getThreshold() { - return myLogger.getThreshold(); - } - - public void setThresholds(int i) { - } - - public void setThreshold(String s, String s1, int i) { - } - - public int getThreshold(String s, String s1) { - return myLogger.getThreshold(); - } - - public Logger getLoggerForComponent(String s, String s1) { - return myLogger; - } - - public void returnComponentLogger(String s, String s1) { - } - - public int getActiveLoggerCount() { - return 1; - } -} diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/MavenConsoleHelper.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/MavenConsoleHelper.java deleted file mode 100644 index ee064e97da09..000000000000 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/MavenConsoleHelper.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.idea.maven.embedder; - -import org.jetbrains.idea.maven.execution.RunnerBundle; - -import java.util.List; - -public class MavenConsoleHelper { - public static void printException(MavenConsole console, Throwable throwable) { - console.systemMessage(MavenConsole.LEVEL_ERROR, RunnerBundle.message("embedded.build.failed"), throwable); - } - - public static void printExecutionExceptions(MavenConsole console, MavenWrapperExecutionResult result) { - for (Exception each : (List)result.getExceptions()) { - Throwable cause = each.getCause(); - printException(console, cause == null ? each : cause); - } - } -} diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/MavenEmbedderUtilEx.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/MavenEmbedderUtilEx.java deleted file mode 100644 index 56265d1f313b..000000000000 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/MavenEmbedderUtilEx.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.idea.maven.embedder; - -import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.JarFileSystem; -import com.intellij.openapi.vfs.LocalFileSystem; -import com.intellij.openapi.vfs.VfsUtil; -import com.intellij.openapi.vfs.VirtualFile; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.maven.utils.MavenConstants; -import org.jetbrains.idea.maven.utils.MavenJDOMUtil; -import org.jetbrains.maven.embedder.MavenEmbedderUtil; - -import java.io.File; -import java.io.IOException; -import java.net.URL; -import java.util.*; -import java.util.regex.Pattern; - -public class MavenEmbedderUtilEx extends MavenEmbedderUtil { - private static final String REPOSITORY_DIR = "repository"; - - private static final String LIB_DIR = "lib"; - private static final String SUPER_POM_PATH = "org/apache/maven/project/" + MavenConstants.SUPER_POM_XML; - - @NotNull - public static VirtualFile resolveSuperPomFile(@Nullable String overrideMavenHome) { - VirtualFile result = doResolveSuperPomFile(overrideMavenHome); - if (result == null) { - URL resource = MavenEmbedderUtilEx.class.getResource("/" + SUPER_POM_PATH); - return VfsUtil.findFileByURL(resource); - } - return result; - } - - @Nullable - private static VirtualFile doResolveSuperPomFile(String overrideMavenHome) { - File lib = resolveMavenLib(overrideMavenHome); - if (lib == null) return null; - - VirtualFile file = LocalFileSystem.getInstance().findFileByIoFile(lib); - if (file == null) return null; - - VirtualFile root = JarFileSystem.getInstance().getJarRootForLocalFile(file); - if (root == null) return null; - - return root.findFileByRelativePath(SUPER_POM_PATH); - } - - @Nullable - private static File resolveMavenLib(String overrideMavenHome) { - File directory = resolveMavenHomeDirectory(overrideMavenHome); - if (directory == null) return null; - File libs = new File(directory, LIB_DIR); - File[] files = libs.listFiles(); - if (files != null) { - Pattern pattern = Pattern.compile("maven-\\d+\\.\\d+\\.\\d+-uber\\.jar"); - for (File each : files) { - if (pattern.matcher(each.getName()).matches()) { - return each; - } - } - } - return null; - } - - @NotNull - public static File resolveLocalRepository(@Nullable String mavenHome, @Nullable String userSettings, @Nullable String override) { - File result = doResolveLocalRepository(mavenHome, userSettings, override); - try { - return result.getCanonicalFile(); - } - catch (IOException e) { - return result; - } - } - - @NotNull - private static File doResolveLocalRepository(String mavenHome, String userSettings, String override) { - if (!StringUtil.isEmpty(override)) { - return new File(override); - } - - final File userSettingsFile = resolveUserSettingsFile(userSettings); - if (userSettingsFile != null) { - final String fromUserSettings = getRepositoryFromSettings(userSettingsFile); - if (!StringUtil.isEmpty(fromUserSettings)) { - return new File(fromUserSettings); - } - } - - final File globalSettingsFile = resolveGlobalSettingsFile(mavenHome); - if (globalSettingsFile != null) { - final String fromGlobalSettings = getRepositoryFromSettings(globalSettingsFile); - if (!StringUtil.isEmpty(fromGlobalSettings)) { - return new File(fromGlobalSettings); - } - } - - return new File(resolveM2Dir(), REPOSITORY_DIR); - } - - @Nullable - private static String getRepositoryFromSettings(final File file) { - try { - byte[] bytes = FileUtil.loadFileBytes(file); - return expandProperties(MavenJDOMUtil.findChildValueByPath(MavenJDOMUtil.read(bytes, null), "localRepository", null)); - } - catch (IOException e) { - return null; - } - } - - private static String expandProperties(String text) { - if (StringUtil.isEmptyOrSpaces(text)) return text; - Properties props = MavenEmbedderWrapper.collectSystemProperties(); - for (Map.Entry each : props.entrySet()) { - text = text.replace("${" + each.getKey() + "}", (CharSequence)each.getValue()); - } - return text; - } -} \ No newline at end of file diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/MavenEmbedderWrapper.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/MavenEmbedderWrapper.java deleted file mode 100644 index 9e2bf2a1ee3c..000000000000 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/MavenEmbedderWrapper.java +++ /dev/null @@ -1,446 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.idea.maven.embedder; - -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.progress.ProcessCanceledException; -import com.intellij.openapi.util.Ref; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.Function; -import gnu.trove.THashSet; -import org.apache.maven.artifact.Artifact; -import org.apache.maven.artifact.InvalidRepositoryException; -import org.apache.maven.artifact.factory.ArtifactFactory; -import org.apache.maven.artifact.manager.WagonManager; -import org.apache.maven.artifact.repository.ArtifactRepository; -import org.apache.maven.artifact.repository.ArtifactRepositoryFactory; -import org.apache.maven.artifact.resolver.ArtifactResolver; -import org.apache.maven.artifact.resolver.ResolutionListener; -import org.apache.maven.model.Build; -import org.apache.maven.model.Model; -import org.apache.maven.model.Plugin; -import org.apache.maven.plugin.PluginManager; -import org.apache.maven.plugin.descriptor.PluginDescriptor; -import org.apache.maven.project.*; -import org.apache.maven.project.MavenProject; -import org.apache.maven.project.artifact.ProjectArtifactFactory; -import org.apache.maven.project.interpolation.AbstractStringBasedModelInterpolator; -import org.apache.maven.project.interpolation.ModelInterpolationException; -import org.apache.maven.project.interpolation.ModelInterpolator; -import org.apache.maven.project.path.DefaultPathTranslator; -import org.apache.maven.project.path.PathTranslator; -import org.apache.maven.shared.dependency.tree.DependencyNode; -import org.apache.maven.shared.dependency.tree.DependencyTreeResolutionListener; -import org.codehaus.plexus.PlexusContainer; -import org.codehaus.plexus.component.repository.ComponentDependency; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.maven.project.*; -import org.jetbrains.idea.maven.utils.MavenLog; -import org.jetbrains.idea.maven.utils.MavenProcessCanceledException; -import org.jetbrains.idea.maven.utils.MavenProgressIndicator; -import org.jetbrains.maven.embedder.MavenEmbedder; -import org.jetbrains.maven.embedder.MavenEmbedderSettings; -import org.jetbrains.maven.embedder.MavenExecutionResult; -import org.jetbrains.maven.embedder.PlexusComponentConfigurator; - -import java.io.File; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.util.*; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -public class MavenEmbedderWrapper { - public static final List PHASES = - Arrays.asList("clean", "validate", "generate-sources", "process-sources", "generate-resources", - "process-resources", "compile", "process-classes", "generate-test-sources", "process-test-sources", - "generate-test-resources", - "process-test-resources", "test-compile", "test", "prepare-package", "package", "pre-integration-test", - "integration-test", - "post-integration-test", - "verify", "install", "site", "deploy"); - public static final List BASIC_PHASES = - Arrays.asList("clean", "validate", "compile", "test", "package", "install", "deploy", "site"); - - private final MavenEmbedder myImpl; - private final MavenLogger myLogger; - private volatile MavenProgressIndicator myCurrentIndicator; - - public static MavenEmbedderWrapper create(MavenGeneralSettings generalSettings) { - MavenEmbedderSettings settings = new MavenEmbedderSettings(); - - settings.setConfigurator(new PlexusComponentConfigurator() { - public void configureComponents(@NotNull PlexusContainer c) { - setupContainer(c); - } - }); - MavenLogger logger = new MavenLogger(); - logger.setThreshold(generalSettings.getLoggingLevel().getLevel()); - settings.setLogger(logger); - settings.setRecursive(false); - - settings.setWorkOffline(generalSettings.isWorkOffline()); - settings.setUsePluginRegistry(generalSettings.isUsePluginRegistry()); - - settings.setMavenHome(generalSettings.getMavenHome()); - settings.setMavenSettingsFile(generalSettings.getMavenSettingsFile()); - settings.setLocalRepository(generalSettings.getEffectiveLocalRepository().getPath()); - - settings.setSnapshotUpdatePolicy(generalSettings.getSnapshotUpdatePolicy().getEmbedderPolicy()); - settings.setPluginUpdatePolicy(generalSettings.getPluginUpdatePolicy().getEmbedderPolicy()); - - return new MavenEmbedderWrapper(MavenEmbedder.create(settings), logger); - } - - private MavenEmbedderWrapper(MavenEmbedder impl, MavenLogger logger) { - myImpl = impl; - myLogger = logger; - } - - public MavenWrapperResolutionResult resolveProject(@NotNull final VirtualFile file, - @NotNull final Collection activeProfiles) - throws MavenProcessCanceledException { - return doExecute(new Executor() { - public MavenWrapperResolutionResult execute() throws Exception { - DependencyTreeResolutionListener listener = new DependencyTreeResolutionListener(myLogger); - - MavenExecutionResult result = myImpl.resolveProject(new File(file.getPath()), - new ArrayList(activeProfiles), - Arrays.asList(listener)); - - DependencyNode rootNode = listener.getRootNode(); - Collection depsTree = rootNode == null ? Collections.emptyList() : rootNode.getChildren(); - return new MavenWrapperResolutionResult(result.getMavenProject(), - depsTree, retrieveUnresolvedArtifactIds(), result.getExceptions()); - } - }); - } - - public void resolve(@NotNull final Artifact artifact, @NotNull final List remoteRepositories) - throws MavenProcessCanceledException { - doExecute(new Executor() { - public Object execute() throws Exception { - doResolve(artifact, convertRepositories(remoteRepositories)); - return null; - } - }); - } - - public MavenArtifact resolve(@NotNull final MavenId id, - @NotNull final String type, - @Nullable final String classifier, - @NotNull final List remoteRepositories) - throws MavenProcessCanceledException { - return doExecute(new Executor() { - public MavenArtifact execute() throws Exception { - return new MavenArtifact(doResolve(id, type, classifier, convertRepositories(remoteRepositories)), getLocalRepositoryFile()); - } - }); - } - - private Artifact doResolve(MavenId id, String type, String classifier, List remoteRepositories) { - Artifact artifact = getComponent(ArtifactFactory.class).createArtifactWithClassifier(id.getGroupId(), - id.getArtifactId(), - id.getVersion(), - type, - classifier); - return doResolve(artifact, remoteRepositories); - } - - private Artifact doResolve(Artifact artifact, List remoteRepositories) { - try { - myImpl.resolve(artifact, remoteRepositories); - return artifact; - } - catch (Exception e) { - MavenLog.LOG.info(e); - } - return artifact; - } - - private List convertRepositories(List repositories) { - List result = new ArrayList(); - for (MavenRemoteRepository each : repositories) { - try { - ArtifactRepositoryFactory factory = getComponent(ArtifactRepositoryFactory.class); - result.add(ProjectUtils.buildArtifactRepository(each.toRepository(), factory, getContainer())); - } - catch (InvalidRepositoryException e) { - MavenLog.LOG.warn(e); - } - } - return result; - } - - public boolean resolvePlugin(@NotNull final MavenPlugin plugin, @NotNull final MavenProject nativeMavenProject, final boolean transitive) - throws MavenProcessCanceledException { - return doExecute(new Executor() { - public Boolean execute() throws Exception { - try { - Plugin mavenPlugin = new Plugin(); - mavenPlugin.setGroupId(plugin.getGroupId()); - mavenPlugin.setArtifactId(plugin.getArtifactId()); - mavenPlugin.setVersion(plugin.getVersion()); - PluginDescriptor result = - getComponent(PluginManager.class).verifyPlugin(mavenPlugin, nativeMavenProject, - myImpl.getSettings(), myImpl.getLocalRepository()); - if (!transitive) return true; - - // todo try to use parallel downloading - - List repos = nativeMavenProject.getRemoteArtifactRepositories(); - for (Artifact each : (Iterable)result.getIntroducedDependencyArtifacts()) { - doResolve(new MavenId(each.getGroupId(), each.getArtifactId(), each.getVersion()), each.getType(), null, repos); - } - for (ComponentDependency each : (List)result.getDependencies()) { - doResolve(new MavenId(each.getGroupId(), each.getArtifactId(), each.getVersion()), each.getType(), null, repos); - } - } - catch (Exception e) { - MavenLog.LOG.info(e); - return false; - } - return true; - } - }); - } - - @NotNull - public MavenWrapperExecutionResult execute(@NotNull final VirtualFile file, - @NotNull final Collection activeProfiles, - @NotNull final List goals) - throws MavenProcessCanceledException { - return doExecute(new Executor() { - public MavenWrapperExecutionResult execute() throws Exception { - MavenExecutionResult result = myImpl.execute(new File(file.getPath()), new ArrayList(activeProfiles), goals); - return new MavenWrapperExecutionResult(result.getMavenProject(), retrieveUnresolvedArtifactIds(), result.getExceptions()); - } - }); - } - - private Set retrieveUnresolvedArtifactIds() { - Set result = new THashSet(); - ((CustomWagonManager)getComponent(WagonManager.class)).getUnresolvedCollector().retrieveUnresolvedIds(result); - ((CustomArtifactResolver)getComponent(ArtifactResolver.class)).getUnresolvedCollector().retrieveUnresolvedIds(result); - return result; - } - - public static Model interpolate(Model model, File basedir) { - try { - AbstractStringBasedModelInterpolator interpolator = new CustomModelInterpolator(new DefaultPathTranslator()); - interpolator.initialize(); - - Properties context = collectSystemProperties(); - - ProjectBuilderConfiguration config = new DefaultProjectBuilderConfiguration().setExecutionProperties(context); - model = interpolator.interpolate(ModelUtils.cloneModel(model), basedir, config, false); - } - catch (ModelInterpolationException e) { - MavenLog.LOG.warn(e); - } - catch (InitializationException e) { - MavenLog.LOG.error(e); - } - - return model; - } - - public static void alignModel(Model model, File basedir) { - PathTranslator pathTranslator = new DefaultPathTranslator(); - pathTranslator.alignToBaseDirectory(model, basedir); - Build build = model.getBuild(); - build.setScriptSourceDirectory(pathTranslator.alignToBaseDirectory(build.getScriptSourceDirectory(), basedir)); - } - - @NotNull - public File getLocalRepositoryFile() { - return myImpl.getLocalRepositoryFile(); - } - - public T getComponent(Class clazz) { - return myImpl.getComponent(clazz); - } - - public T getComponent(Class clazz, String roleHint) { - return myImpl.getComponent(clazz, roleHint); - } - - public PlexusContainer getContainer() { - return myImpl.getContainer(); - } - - private interface Executor { - T execute() throws Exception; - } - - private T doExecute(final Executor executor) throws MavenProcessCanceledException { - final Ref result = new Ref(); - final boolean[] cancelled = new boolean[1]; - final Throwable[] exception = new Throwable[1]; - - Future future = ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { - public void run() { - try { - result.set(executor.execute()); - } - catch (ProcessCanceledException e) { - cancelled[0] = true; - } - catch (Throwable e) { - exception[0] = e; - } - } - }); - - MavenProgressIndicator indicator = myCurrentIndicator; - while (true) { - indicator.checkCanceled(); - try { - future.get(50, TimeUnit.MILLISECONDS); - } - catch (TimeoutException ignore) { - } - catch (ExecutionException e) { - throw new RuntimeException(e.getCause()); - } - catch (InterruptedException e) { - throw new MavenProcessCanceledException(); - } - - if (future.isDone()) break; - } - - if (cancelled[0]) throw new MavenProcessCanceledException(); - if (exception[0] != null) { - throw getRethrowable(exception[0]); - } - - return result.get(); - } - - private RuntimeException getRethrowable(Throwable throwable) { - if (throwable instanceof InvocationTargetException) throwable = throwable.getCause(); - if (throwable instanceof RuntimeException) return (RuntimeException)throwable; - return new RuntimeException(throwable); - } - - private static void setupContainer(PlexusContainer c) { - MavenEmbedder.setImplementation(c, ArtifactFactory.class, CustomArtifactFactory.class); - MavenEmbedder.setImplementation(c, ProjectArtifactFactory.class, CustomArtifactFactory.class); - MavenEmbedder.setImplementation(c, ArtifactResolver.class, CustomArtifactResolver.class); - MavenEmbedder.setImplementation(c, WagonManager.class, CustomWagonManager.class); - MavenEmbedder.setImplementation(c, ModelInterpolator.class, CustomModelInterpolator.class); - } - - public void customizeForResolve(MavenConsole console, MavenProgressIndicator process) { - doCustomize(null, false, console, process); - } - - public void customizeForResolve(Map projectIdToFileMap, MavenConsole console, MavenProgressIndicator process) { - doCustomize(projectIdToFileMap, false, console, process); - } - - public void customizeForStrictResolve(Map projectIdToFileMap, - MavenConsole console, - MavenProgressIndicator process) { - doCustomize(projectIdToFileMap, true, console, process); - } - - private void doCustomize(Map projectIdToFileMap, - boolean strict, - MavenConsole console, - MavenProgressIndicator process) { - ((CustomArtifactFactory)getComponent(ArtifactFactory.class)).customize(); - ((CustomArtifactFactory)getComponent(ProjectArtifactFactory.class)).customize(); - ((CustomArtifactResolver)getComponent(ArtifactResolver.class)).customize(projectIdToFileMap, strict); - ((CustomWagonManager)getComponent(WagonManager.class)).customize(strict); - - setConsoleAndLogger(console, process); - } - - private void setConsoleAndLogger(MavenConsole console, MavenProgressIndicator process) { - myCurrentIndicator = process; - myLogger.setConsole(console); - - WagonManager wagon = getComponent(WagonManager.class); - wagon.setDownloadMonitor(process == null ? null : new TransferListenerAdapter(process)); - } - - public void reset() { - setConsoleAndLogger(null, null); - - ((CustomArtifactFactory)getComponent(ProjectArtifactFactory.class)).reset(); - ((CustomArtifactFactory)getComponent(ArtifactFactory.class)).reset(); - ((CustomArtifactResolver)getComponent(ArtifactResolver.class)).reset(); - ((CustomWagonManager)getComponent(WagonManager.class)).reset(); - } - - public void release() { - myImpl.release(); - } - - public void clearCaches() { - withProjectCachesDo(new Function() { - public Object fun(Map map) { - map.clear(); - return null; - } - }); - } - - public void clearCachesFor(final MavenId projectId) { - withProjectCachesDo(new Function() { - public Object fun(Map map) { - map.remove(projectId.getKey()); - return null; - } - }); - } - - private void withProjectCachesDo(Function func) { - MavenProjectBuilder builder = myImpl.getComponent(MavenProjectBuilder.class); - Field field; - try { - field = builder.getClass().getDeclaredField("rawProjectCache"); - field.setAccessible(true); - func.fun(((Map)field.get(builder))); - - field = builder.getClass().getDeclaredField("processedProjectCache"); - field.setAccessible(true); - func.fun(((Map)field.get(builder))); - } - catch (NoSuchFieldException e) { - MavenLog.LOG.error(e); - } - catch (IllegalAccessException e) { - MavenLog.LOG.error(e); - } - } - - public static Properties collectSystemProperties() { - return MavenEmbedder.collectSystemProperties(); - } - - public static void resetSystemPropertiesCacheInTests() { - MavenEmbedder.resetSystemPropertiesCache(); - } - -} - diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/MavenWrapperExecutionResult.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/MavenWrapperExecutionResult.java deleted file mode 100644 index a9232e87aa2a..000000000000 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/MavenWrapperExecutionResult.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.idea.maven.embedder; - -import org.apache.maven.project.MavenProject; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.maven.project.MavenId; - -import java.util.List; -import java.util.Set; - -public class MavenWrapperExecutionResult { - private final MavenProject myMavenProject; - private final Set myUnresolvedArtifactIds; - private final List myExceptions; - - public MavenWrapperExecutionResult(MavenProject mavenProject, Set unresolvedArtifactIds, List exceptions) { - myMavenProject = mavenProject; - myUnresolvedArtifactIds = unresolvedArtifactIds; - myExceptions = exceptions; - } - - @Nullable - public MavenProject getMavenProject() { - return myMavenProject; - } - - public Set getUnresolvedArtifactIds() { - return myUnresolvedArtifactIds; - } - - public List getExceptions() { - return myExceptions; - } - - public boolean hasExceptions() { - return !myExceptions.isEmpty(); - } -} diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/MavenWrapperResolutionResult.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/MavenWrapperResolutionResult.java deleted file mode 100644 index 78ccf27a1ae1..000000000000 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/MavenWrapperResolutionResult.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2000-2010 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.idea.maven.embedder; - -import org.apache.maven.project.MavenProject; -import org.apache.maven.shared.dependency.tree.DependencyNode; -import org.jetbrains.idea.maven.project.MavenId; - -import java.util.Collection; -import java.util.List; -import java.util.Set; - -public class MavenWrapperResolutionResult extends MavenWrapperExecutionResult { - private final Collection myOriginalDependencyTree; - - public MavenWrapperResolutionResult(MavenProject mavenProject, - Collection originalDependencyTree, - Set unresolvedArtifactIds, - List exceptions) { - super(mavenProject, unresolvedArtifactIds, exceptions); - myOriginalDependencyTree = originalDependencyTree; - } - - public Collection getOriginalDependencyTree() { - return myOriginalDependencyTree; - } -} diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/MavenExecutionOptions.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExecutionOptions.java similarity index 68% rename from plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/MavenExecutionOptions.java rename to plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExecutionOptions.java index 05c4a909aa82..ffe9f3e31652 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/MavenExecutionOptions.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExecutionOptions.java @@ -13,19 +13,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.maven.embedder; +package org.jetbrains.idea.maven.execution; -import org.codehaus.plexus.logging.Logger; -import org.jetbrains.maven.embedder.MavenEmbedderSettings; +import org.jetbrains.idea.maven.facade.MavenFacadeConsole; +import org.jetbrains.idea.maven.facade.MavenFacadeSettings; public class MavenExecutionOptions { public enum LoggingLevel { - DEBUG("Debug", Logger.LEVEL_DEBUG), - INFO("Info", Logger.LEVEL_INFO), - WARN("Warn", Logger.LEVEL_WARN), - ERROR("Error", Logger.LEVEL_ERROR), - FATAL("Fatal", Logger.LEVEL_FATAL), - DISABLED("Disabled", Logger.LEVEL_DISABLED); + DEBUG("Debug", MavenFacadeConsole.LEVEL_DEBUG), + INFO("Info", MavenFacadeConsole.LEVEL_INFO), + WARN("Warn", MavenFacadeConsole.LEVEL_WARN), + ERROR("Error", MavenFacadeConsole.LEVEL_ERROR), + FATAL("Fatal", MavenFacadeConsole.LEVEL_FATAL), + DISABLED("Disabled", MavenFacadeConsole.LEVEL_DISABLED); private final String myDisplayString; private final int myLevel; @@ -87,17 +87,17 @@ public class MavenExecutionOptions { } public enum SnapshotUpdatePolicy { - ALWAYS_UPDATE("Always Update", "--update-snapshots", MavenEmbedderSettings.SnapshotUpdatePolicy.ALWAYS_UPDATE), - DO_NOT_UPDATE("Do Not Update", "", MavenEmbedderSettings.SnapshotUpdatePolicy.DO_NOT_UPDATE); + ALWAYS_UPDATE("Always Update", "--update-snapshots", MavenFacadeSettings.UpdatePolicy.ALWAYS_UPDATE), + DO_NOT_UPDATE("Do Not Update", "", MavenFacadeSettings.UpdatePolicy.DO_NOT_UPDATE); private final String myDisplayString; private final String myCommandLineOption; - private final MavenEmbedderSettings.SnapshotUpdatePolicy myEmbedderPolicy; + private final MavenFacadeSettings.UpdatePolicy myFacadePolicy; - private SnapshotUpdatePolicy(String displayString, String commandLineOption, MavenEmbedderSettings.SnapshotUpdatePolicy policy) { + private SnapshotUpdatePolicy(String displayString, String commandLineOption, MavenFacadeSettings.UpdatePolicy policy) { myDisplayString = displayString; myCommandLineOption = commandLineOption; - myEmbedderPolicy = policy; + myFacadePolicy = policy; } public String getDisplayString() { @@ -108,23 +108,23 @@ public class MavenExecutionOptions { return myCommandLineOption; } - public MavenEmbedderSettings.SnapshotUpdatePolicy getEmbedderPolicy() { - return myEmbedderPolicy; + public MavenFacadeSettings.UpdatePolicy getFacadePolicy() { + return myFacadePolicy; } } public enum PluginUpdatePolicy { - UPDATE("Check For Updates", "--check-plugin-updates", MavenEmbedderSettings.PluginUpdatePolicy.UPDATE), - DO_NOT_UPDATE("Do Not Update", "--no-plugin-updates", MavenEmbedderSettings.PluginUpdatePolicy.DO_NOT_UPDATE); + UPDATE("Check For Updates", "--check-plugin-updates", MavenFacadeSettings.UpdatePolicy.ALWAYS_UPDATE), + DO_NOT_UPDATE("Do Not Update", "--no-plugin-updates", MavenFacadeSettings.UpdatePolicy.DO_NOT_UPDATE); private final String myDisplayString; private final String myCommandLineOption; - private final MavenEmbedderSettings.PluginUpdatePolicy myEmbedderPolicy; + private final MavenFacadeSettings.UpdatePolicy myFacadePolicy; - private PluginUpdatePolicy(String displayString, String commandLineOption, MavenEmbedderSettings.PluginUpdatePolicy policy) { + private PluginUpdatePolicy(String displayString, String commandLineOption, MavenFacadeSettings.UpdatePolicy policy) { myDisplayString = displayString; myCommandLineOption = commandLineOption; - myEmbedderPolicy = policy; + myFacadePolicy = policy; } public String getDisplayString() { @@ -135,8 +135,8 @@ public class MavenExecutionOptions { return myCommandLineOption; } - public MavenEmbedderSettings.PluginUpdatePolicy getEmbedderPolicy() { - return myEmbedderPolicy; + public MavenFacadeSettings.UpdatePolicy getFacadePolicy() { + return myFacadePolicy; } } } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExecutor.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExecutor.java index 3861e55616ff..41f0ec94040d 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExecutor.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExecutor.java @@ -20,7 +20,8 @@ package org.jetbrains.idea.maven.execution; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; -import org.jetbrains.idea.maven.embedder.MavenConsole; +import org.jetbrains.idea.maven.facade.MavenFacadeConsole; +import org.jetbrains.idea.maven.project.MavenConsole; import org.jetbrains.idea.maven.project.MavenGeneralSettings; import java.text.MessageFormat; @@ -98,15 +99,15 @@ public abstract class MavenExecutor { protected boolean printExitSummary() { if (isCancelled()) { - myConsole.systemMessage(MavenConsole.LEVEL_INFO, RunnerBundle.message("maven.execution.aborted"), null); + myConsole.systemMessage(MavenFacadeConsole.LEVEL_INFO, RunnerBundle.message("maven.execution.aborted"), null); return false; } else if (exitCode == 0) { - myConsole.systemMessage(MavenConsole.LEVEL_INFO, RunnerBundle.message("maven.execution.finished"), null); + myConsole.systemMessage(MavenFacadeConsole.LEVEL_INFO, RunnerBundle.message("maven.execution.finished"), null); return true; } else { - myConsole.systemMessage(MavenConsole.LEVEL_ERROR, RunnerBundle.message("maven.execution.terminated.abnormally", exitCode), null); + myConsole.systemMessage(MavenFacadeConsole.LEVEL_ERROR, RunnerBundle.message("maven.execution.terminated.abnormally", exitCode), null); return false; } } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExternalExecutor.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExternalExecutor.java index aeaefbd5cadb..34001b661226 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExternalExecutor.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExternalExecutor.java @@ -25,8 +25,9 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.util.Key; import org.jetbrains.annotations.NonNls; +import org.jetbrains.idea.maven.facade.MavenFacadeConsole; +import org.jetbrains.idea.maven.project.MavenConsole; import org.jetbrains.idea.maven.project.MavenGeneralSettings; -import org.jetbrains.idea.maven.embedder.MavenConsole; public class MavenExternalExecutor extends MavenExecutor { @@ -60,7 +61,7 @@ public class MavenExternalExecutor extends MavenExecutor { myConsole.attachToProcess(myProcessHandler); } catch (ExecutionException e) { - myConsole.systemMessage(MavenConsole.LEVEL_FATAL, RunnerBundle.message("external.startup.failed", e.getMessage()), null); + myConsole.systemMessage(MavenFacadeConsole.LEVEL_FATAL, RunnerBundle.message("external.startup.failed", e.getMessage()), null); return false; } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExternalParameters.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExternalParameters.java index b80689fda03b..9abf973de823 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExternalParameters.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExternalParameters.java @@ -28,9 +28,9 @@ import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl; import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; -import org.jetbrains.idea.maven.embedder.MavenEmbedderUtilEx; -import org.jetbrains.idea.maven.embedder.MavenExecutionOptions; +import org.jetbrains.idea.maven.facade.MavenFacadeUtil; import org.jetbrains.idea.maven.project.MavenGeneralSettings; +import org.jetbrains.idea.maven.utils.MavenUtil; import java.io.File; import java.io.IOException; @@ -123,7 +123,7 @@ public class MavenExternalParameters { addParameters(list, StringUtil.notNullize(System.getenv(MAVEN_OPTS))); - addProperty(list, "classworlds.conf", MavenEmbedderUtilEx.getMavenConfFile(new File(mavenHome)).getPath()); + addProperty(list, "classworlds.conf", MavenUtil.getMavenConfFile(new File(mavenHome)).getPath()); addProperty(list, "maven.home", mavenHome); @@ -180,7 +180,7 @@ public class MavenExternalParameters { } private static String resolveMavenHome(@NotNull MavenGeneralSettings coreSettings) throws ExecutionException { - final File file = MavenEmbedderUtilEx.resolveMavenHomeDirectory(coreSettings.getMavenHome()); + final File file = MavenUtil.resolveMavenHomeDirectory(coreSettings.getMavenHome()); if (file == null) { throw new ExecutionException(RunnerBundle.message("external.maven.home.no.default")); @@ -190,7 +190,7 @@ public class MavenExternalParameters { throw new ExecutionException(RunnerBundle.message("external.maven.home.does.not.exist", file.getPath())); } - if (!MavenEmbedderUtilEx.isValidMavenHome(file)) { + if (!MavenUtil.isValidMavenHome(file)) { throw new ExecutionException(RunnerBundle.message("external.maven.home.invalid", file.getPath())); } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenJavaClasspathPolicyExtender.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenJavaClasspathPolicyExtender.java index 586f55bb7318..04ae3b1f4b9e 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenJavaClasspathPolicyExtender.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenJavaClasspathPolicyExtender.java @@ -20,10 +20,10 @@ import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.*; import org.jetbrains.annotations.NotNull; -import org.jetbrains.idea.maven.project.MavenArtifact; +import org.jetbrains.idea.maven.model.MavenArtifact; +import org.jetbrains.idea.maven.model.MavenConstants; import org.jetbrains.idea.maven.project.MavenProject; import org.jetbrains.idea.maven.project.MavenProjectsManager; -import org.jetbrains.idea.maven.utils.MavenConstants; import java.util.Collections; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunConfiguration.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunConfiguration.java index 4bcb75c40891..6b66d051ddca 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunConfiguration.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunConfiguration.java @@ -33,10 +33,10 @@ import com.intellij.openapi.util.WriteExternalException; import com.intellij.util.xmlb.XmlSerializer; import org.jdom.Element; import org.jetbrains.annotations.NotNull; -import org.jetbrains.idea.maven.embedder.MavenConsoleImpl; +import org.jetbrains.idea.maven.model.MavenConstants; +import org.jetbrains.idea.maven.project.MavenConsoleImpl; import org.jetbrains.idea.maven.project.MavenGeneralSettings; import org.jetbrains.idea.maven.project.MavenProjectsManager; -import org.jetbrains.idea.maven.utils.MavenConstants; import java.io.File; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunner.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunner.java index 94b9de4e86ba..50e13af90540 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunner.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunner.java @@ -28,9 +28,8 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.maven.embedder.MavenConsole; -import org.jetbrains.idea.maven.embedder.MavenConsoleHelper; -import org.jetbrains.idea.maven.embedder.MavenConsoleImpl; +import org.jetbrains.idea.maven.project.MavenConsole; +import org.jetbrains.idea.maven.project.MavenConsoleImpl; import org.jetbrains.idea.maven.project.MavenGeneralSettings; import org.jetbrains.idea.maven.project.MavenProjectsManager; import org.jetbrains.idea.maven.utils.SimpleProjectComponent; @@ -108,7 +107,7 @@ public class MavenRunner extends SimpleProjectComponent implements PersistentSta }); } catch (Exception e) { - MavenConsoleHelper.printException(console, e); + console.printException(e); console.finish(); MavenLog.LOG.warn(e); } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunnerParametersConfigurable.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunnerParametersConfigurable.java index 68fa448b7b3c..1857b7433e6f 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunnerParametersConfigurable.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunnerParametersConfigurable.java @@ -24,7 +24,7 @@ import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.maven.utils.Strings; -import org.jetbrains.idea.maven.utils.MavenConstants; +import org.jetbrains.idea.maven.model.MavenConstants; import javax.swing.*; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/SoutMavenConsole.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/SoutMavenConsole.java index a8ca698fd075..f2bde943581b 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/SoutMavenConsole.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/SoutMavenConsole.java @@ -19,8 +19,7 @@ import com.intellij.execution.process.ProcessAdapter; import com.intellij.execution.process.ProcessEvent; import com.intellij.execution.process.ProcessHandler; import com.intellij.openapi.util.Key; -import org.jetbrains.idea.maven.embedder.MavenConsole; -import org.jetbrains.idea.maven.embedder.MavenExecutionOptions; +import org.jetbrains.idea.maven.project.MavenConsole; public class SoutMavenConsole extends MavenConsole { public SoutMavenConsole() { diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/facade/MavenEmbedderWrapper.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/facade/MavenEmbedderWrapper.java new file mode 100644 index 000000000000..9957dc3c7532 --- /dev/null +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/facade/MavenEmbedderWrapper.java @@ -0,0 +1,208 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.maven.facade; + +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.maven.model.*; +import org.jetbrains.idea.maven.project.MavenConsole; +import org.jetbrains.idea.maven.utils.MavenProcessCanceledException; +import org.jetbrains.idea.maven.utils.MavenProgressIndicator; + +import java.io.File; +import java.rmi.NoSuchObjectException; +import java.rmi.RemoteException; +import java.rmi.server.UnicastRemoteObject; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +public class MavenEmbedderWrapper { + private final MavenFacadeEmbedder myWrappee; + + private MavenFacadeConsole myConsole; + private MavenFacadeProgressIndicator myIndicator; + + public MavenEmbedderWrapper(MavenFacadeEmbedder wrappee) { + myWrappee = wrappee; + } + + public void customizeForResolve(MavenConsole console, MavenProgressIndicator indicator) { + try { + resetConsole(MavenFacadeManager.wrapandExport(console)); + resetIndicator(MavenFacadeManager.wrapAndExport(indicator)); + + myWrappee.customizeForResolve(myConsole, myIndicator); + } + catch (RemoteException e) { + throw new RuntimeException(e); + } + } + + public void customizeForResolve(Map projectIdToFileMap, MavenConsole console, MavenProgressIndicator indicator) { + try { + resetConsole(MavenFacadeManager.wrapandExport(console)); + resetIndicator(MavenFacadeManager.wrapAndExport(indicator)); + + myWrappee.customizeForResolve(projectIdToFileMap, myConsole, myIndicator); + } + catch (RemoteException e) { + throw new RuntimeException(e); + } + } + + public void customizeForStrictResolve(Map projectIdToFileMap, + MavenConsole console, + MavenProgressIndicator indicator) { + try { + resetConsole(MavenFacadeManager.wrapandExport(console)); + resetIndicator(MavenFacadeManager.wrapAndExport(indicator)); + + myWrappee.customizeForStrictResolve(projectIdToFileMap, myConsole, myIndicator); + } + catch (RemoteException e) { + throw new RuntimeException(e); + } + } + + @NotNull + public MavenWrapperExecutionResult resolveProject(@NotNull VirtualFile file, + @NotNull Collection activeProfiles) throws MavenProcessCanceledException { + try { + return myWrappee.resolveProject(new File(file.getPath()), activeProfiles); + } + catch (MavenFacadeProcessCanceledException e) { + throw new MavenProcessCanceledException(); + } + catch (RemoteException e) { + throw new RuntimeException(e); + } + } + + @NotNull + public MavenArtifact resolve(@NotNull MavenArtifactInfo info, + @NotNull List remoteRepositories) throws MavenProcessCanceledException { + try { + return myWrappee.resolve(info, remoteRepositories); + } + catch (MavenFacadeProcessCanceledException e) { + throw new MavenProcessCanceledException(); + } + catch (RemoteException e) { + throw new RuntimeException(e); + } + } + + @NotNull + public List resolveTransitively( + @NotNull List artifacts, + @NotNull List remoteRepositories) throws MavenProcessCanceledException { + try { + return myWrappee.resolveTransitively(artifacts, remoteRepositories); + } + catch (MavenFacadeProcessCanceledException e) { + throw new MavenProcessCanceledException(); + } + catch (RemoteException e) { + throw new RuntimeException(e); + } + } + + public Collection resolvePlugin(@NotNull MavenPlugin plugin, + @NotNull List repositories, + @NotNull NativeMavenProjectHolder nativeMavenProject, + boolean transitive) throws MavenProcessCanceledException { + try { + return myWrappee.resolvePlugin(plugin, repositories, nativeMavenProject.getId(), transitive); + } + catch (MavenFacadeProcessCanceledException e) { + throw new MavenProcessCanceledException(); + } + catch (RemoteException e) { + throw new RuntimeException(e); + } + } + + @NotNull + public MavenWrapperExecutionResult execute(@NotNull VirtualFile file, + @NotNull Collection activeProfiles, + @NotNull List goals) throws MavenProcessCanceledException { + try { + return myWrappee.execute(new File(file.getPath()), activeProfiles, goals); + } + catch (MavenFacadeProcessCanceledException e) { + throw new MavenProcessCanceledException(); + } + catch (RemoteException e) { + throw new RuntimeException(e); + } + } + + public void reset() { + try { + myWrappee.reset(); + resetConsole(null); + resetIndicator(null); + } + catch (RemoteException e) { + throw new RuntimeException(e); + } + } + + private void resetConsole(MavenFacadeConsole console) throws NoSuchObjectException { + if (myConsole != null) { + UnicastRemoteObject.unexportObject(myConsole, true); + } + myConsole = console; + } + + private void resetIndicator(MavenFacadeProgressIndicator indicator) throws NoSuchObjectException { + if (myIndicator != null) { + UnicastRemoteObject.unexportObject(myIndicator, true); + } + myIndicator = indicator; + } + + public void release() { + try { + myWrappee.release(); + resetConsole(null); + resetIndicator(null); + } + catch (RemoteException e) { + throw new RuntimeException(e); + } + } + + public void clearCaches() { + try { + myWrappee.clearCaches(); + } + catch (RemoteException e) { + throw new RuntimeException(e); + } + } + + public void clearCachesFor(MavenId projectId) { + try { + myWrappee.clearCachesFor(projectId); + } + catch (RemoteException e) { + throw new RuntimeException(e); + } + } +} diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/facade/MavenFacadeManager.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/facade/MavenFacadeManager.java new file mode 100644 index 000000000000..9a7cab28c6d9 --- /dev/null +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/facade/MavenFacadeManager.java @@ -0,0 +1,375 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.maven.facade; + +import com.intellij.execution.DefaultExecutionResult; +import com.intellij.execution.ExecutionException; +import com.intellij.execution.ExecutionResult; +import com.intellij.execution.Executor; +import com.intellij.execution.configurations.CommandLineState; +import com.intellij.execution.configurations.GeneralCommandLine; +import com.intellij.execution.configurations.RunProfileState; +import com.intellij.execution.configurations.SimpleJavaParameters; +import com.intellij.execution.process.OSProcessHandler; +import com.intellij.execution.process.ProcessHandler; +import com.intellij.execution.process.ProcessTerminatedListener; +import com.intellij.execution.rmi.RemoteProcessSupport; +import com.intellij.execution.runners.ProgramRunner; +import com.intellij.ide.DataManager; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.PlatformDataKeys; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.PathManager; +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.projectRoots.JavaSdkType; +import com.intellij.openapi.projectRoots.JdkUtil; +import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.projectRoots.SimpleJavaSdkType; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.CommonClassNames; +import com.intellij.util.PathUtil; +import com.intellij.util.PathsList; +import com.intellij.util.SystemProperties; +import com.intellij.util.containers.ContainerUtil; +import gnu.trove.THashSet; +import org.apache.lucene.search.Query; +import org.jdom.Element; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.maven.model.MavenArtifactInfo; +import org.jetbrains.idea.maven.model.MavenModel; +import org.jetbrains.idea.maven.model.MavenRepositoryInfo; +import org.jetbrains.idea.maven.project.MavenConsole; +import org.jetbrains.idea.maven.project.MavenGeneralSettings; +import org.jetbrains.idea.maven.project.MavenProjectsManager; +import org.jetbrains.idea.maven.utils.MavenLog; +import org.jetbrains.idea.maven.utils.MavenProgressIndicator; + +import java.io.File; +import java.nio.charset.Charset; +import java.rmi.RemoteException; +import java.rmi.server.UnicastRemoteObject; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class MavenFacadeManager { + @NonNls private static final String MAIN_CLASS = "org.jetbrains.idea.maven.facade.RemoteMavenServer"; + private final RemoteProcessSupport mySupport; + private MavenFacade myFacade; + private RemoteMavenFacadeLogger myLogger; + + public static MavenFacadeManager getInstance() { + return ServiceManager.getService(MavenFacadeManager.class); + } + + public MavenFacadeManager() throws RemoteException { + mySupport = new RemoteProcessSupport(MavenFacade.class) { + @Override + protected void fireModificationCountChanged() { + } + + @Override + protected String getName(Object file) { + return MavenFacadeManager.class.getSimpleName(); + } + + @Override + protected RunProfileState getRunProfileState(Object target, Object configuration, Executor executor) throws ExecutionException { + return createRunProfileState(); + } + }; + + Disposer.register(ApplicationManager.getApplication(), new Disposable() { + public void dispose() { + mySupport.stopAll(); + + if (myLogger != null) { + try { + UnicastRemoteObject.unexportObject(myLogger, true); + } + catch (RemoteException e) { + MavenLog.LOG.error(e); + } + } + } + }); + } + + private synchronized MavenFacade getFacade() { + if (myFacade == null) { + try { + myFacade = mySupport.acquire(this, ""); + + myLogger = new RemoteMavenFacadeLogger(); + UnicastRemoteObject.exportObject(myLogger, 0); + myFacade.setLogger(myLogger); + } + catch (Exception e) { + // todo + throw new RuntimeException(e); + } + } + return myFacade; + } + + + private RunProfileState createRunProfileState() { + return new CommandLineState(null) { + private SimpleJavaParameters createJavaParameters() throws ExecutionException { + final SimpleJavaParameters params = new SimpleJavaParameters(); + + final Sdk ideaJdk = new SimpleJavaSdkType().createJdk("tmp", SystemProperties.getJavaHome()); + params.setJdk(ideaJdk); + + params.setWorkingDirectory(PathManager.getBinPath()); + final ArrayList classPath = new ArrayList(); + ContainerUtil.addIfNotNull(PathUtil.getJarPathForClass(NotNull.class), classPath); + ContainerUtil.addIfNotNull(PathUtil.getJarPathForClass(StringUtil.class), classPath); + ContainerUtil.addIfNotNull(PathUtil.getJarPathForClass(THashSet.class), classPath); + ContainerUtil.addIfNotNull(PathUtil.getJarPathForClass(Element.class), classPath); + ContainerUtil.addIfNotNull(PathUtil.getJarPathForClass(Query.class), classPath); + params.getClassPath().addAll(classPath); + addPluginLibraries(params.getClassPath()); + + params.setMainClass(MAIN_CLASS); + params.getVMParametersList().add("-Xmx512m -agentlib:yjpagent=disablej2ee"); + return params; + } + + @Override + public ExecutionResult execute(@NotNull Executor executor, @NotNull ProgramRunner runner) throws ExecutionException { + ProcessHandler processHandler = startProcess(); + return new DefaultExecutionResult(null, processHandler, AnAction.EMPTY_ARRAY); + } + + protected OSProcessHandler startProcess() throws ExecutionException { + SimpleJavaParameters params = createJavaParameters(); + Sdk sdk = params.getJdk(); + + final GeneralCommandLine commandLine = JdkUtil.setupJVMCommandLine(((JavaSdkType)sdk.getSdkType()).getVMExecutablePath(sdk), params, + JdkUtil.useDynamicClasspath(PlatformDataKeys + .PROJECT.getData( + DataManager.getInstance().getDataContext()))); + final OSProcessHandler processHandler = new OSProcessHandler(commandLine.createProcess(), commandLine.getCommandLineString()) { + @Override + public Charset getCharset() { + return commandLine.getCharset(); + } + }; + ProcessTerminatedListener.attach(processHandler); + return processHandler; + } + + }; + } + + private void addPluginLibraries(PathsList classPath) { + File pluginFileOrDir = new File(PathUtil.getJarPathForClass(this.getClass())); + + File libDir; + + if (pluginFileOrDir.isDirectory()) { + classPath.add(new File(pluginFileOrDir.getParent(), "maven-facade-api")); + classPath.add(new File(pluginFileOrDir.getParent(), "maven-facade-impl")); + File luceneLib = new File(PathUtil.getJarPathForClass(Query.class)); + libDir = new File(luceneLib.getParentFile().getParentFile().getParentFile(), "facade-impl/lib"); + } + else { + libDir = pluginFileOrDir; + } + MavenLog.LOG.assertTrue(libDir.exists() && libDir.isDirectory(), "Maven Facade libraries dir not found: " + libDir); + + File[] files = libDir.listFiles(); + for (File jar : files) { + if (jar.isFile() && jar.getName().endsWith(".jar") && !jar.equals(pluginFileOrDir)) { + classPath.add(jar.getPath()); + } + } + } + + public static String getJarPath(@NotNull final Class context, @NotNull final String mainClassName) { + final String s = PathManager.getResourceRoot(context, "/" + mainClassName.replace('.', '/') + CommonClassNames.CLASS_FILE_EXTENSION); + return new File(s).getAbsoluteFile().getAbsolutePath(); + } + + public MavenEmbedderWrapper createEmbedder(Project project) { + MavenFacade facade = getFacade(); + MavenGeneralSettings settings = MavenProjectsManager.getInstance(project).getGeneralSettings(); + try { + return new MavenEmbedderWrapper(facade.createEmbedder(convertSettings(settings))); + } + catch (RemoteException e) { + // todo + throw new RuntimeException(e); + } + } + + public MavenIndexerWrapper createIndexer() { + try { + return new MavenIndexerWrapper(getFacade().createIndexer()); + } + catch (RemoteException e) { + //todo + throw new RuntimeException(e); + } + } + + public List getRepositories(String nexusUrl) { + try { + return getFacade().getRepositories(nexusUrl); + } + catch (RemoteException e) { + // todo + throw new RuntimeException(e); + } + } + + public List findArtifacts(MavenArtifactInfo template, String nexusUrl) { + try { + return getFacade().findArtifacts(template, nexusUrl); + } + catch (RemoteException e) { + // todo + throw new RuntimeException(e); + } + } + + public MavenModel interpolateAndAlignModel(MavenModel model, File basedir) { + try { + return getFacade().interpolateAndAlignModel(model, basedir); + } + catch (RemoteException e) { + // todo + throw new RuntimeException(e); + } + } + + public MavenModel assembleInheritance(MavenModel model, MavenModel parentModel) { + try { + return getFacade().assembleInheritance(model, parentModel); + } + catch (RemoteException e) { + // todo + throw new RuntimeException(e); + } + } + + public ProfileApplicationResult applyProfiles(MavenModel model, + File basedir, + Collection explicitProfiles, + Collection alwaysOnProfiles) { + try { + return getFacade().applyProfiles(model, basedir, explicitProfiles, alwaysOnProfiles); + } + catch (RemoteException e) { + // todo + throw new RuntimeException(e); + } + } + + public static MavenFacadeSettings convertSettings(MavenGeneralSettings settings) { + MavenFacadeSettings result = new MavenFacadeSettings(); + result.setLoggingLevel(settings.getLoggingLevel().getLevel()); + result.setOffline(settings.isWorkOffline()); + result.setMavenHome(settings.getEffectiveMavenHome()); + result.setUserSettingsFile(settings.getEffectiveUserSettingsIoFile()); + result.setGlobalSettingsFile(settings.getEffectiveGlobalSettingsIoFile()); + result.setLocalRepository(settings.getEffectiveLocalRepository()); + result.setPluginUpdatePolicy(settings.getPluginUpdatePolicy().getFacadePolicy()); + result.setSnapshotUpdatePolicy(settings.getSnapshotUpdatePolicy().getFacadePolicy()); + return result; + } + + public static MavenFacadeConsole wrapandExport(final MavenConsole console) { + try { + RemoteMavenFacadeConsole result = new RemoteMavenFacadeConsole(console); + UnicastRemoteObject.exportObject(result, 0); + return result; + } + catch (RemoteException e) { + throw new RuntimeException(e); + } + } + + public static MavenFacadeProgressIndicator wrapAndExport(final MavenProgressIndicator process) { + try { + RemoteMavenFacadeProgressIndicator result = new RemoteMavenFacadeProgressIndicator(process); + UnicastRemoteObject.exportObject(result, 0); + return result; + } + catch (RemoteException e) { + throw new RuntimeException(e); + } + } + + private static class RemoteMavenFacadeLogger extends RemoteObject implements MavenFacadeLogger { + public void info(Throwable e) { + MavenLog.LOG.info(e); + } + + public void warn(Throwable e) { + MavenLog.LOG.warn(e); + } + + public void error(Throwable e) { + MavenLog.LOG.error(e); + } + } + + private static class RemoteMavenFacadeProgressIndicator extends RemoteObject implements MavenFacadeProgressIndicator { + private final MavenProgressIndicator myProcess; + + public RemoteMavenFacadeProgressIndicator(MavenProgressIndicator process) { + myProcess = process; + } + + public void setText(String text) { + myProcess.setText(text); + } + + public void setText2(String text) { + myProcess.setText2(text); + } + + public boolean isCanceled() { + return myProcess.isCanceled(); + } + + public void setIndeterminate(boolean value) { + myProcess.getIndicator().setIndeterminate(value); + } + + public void setFraction(double fraction) { + myProcess.setFraction(fraction); + } + } + + private static class RemoteMavenFacadeConsole extends RemoteObject implements MavenFacadeConsole { + private final MavenConsole myConsole; + + public RemoteMavenFacadeConsole(MavenConsole console) { + myConsole = console; + } + + public void printMessage(int level, String message, Throwable throwable) { + myConsole.printMessage(level, message, throwable); + } + } +} diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/facade/MavenIndexerWrapper.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/facade/MavenIndexerWrapper.java new file mode 100644 index 000000000000..22d518fe1cb0 --- /dev/null +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/facade/MavenIndexerWrapper.java @@ -0,0 +1,137 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.maven.facade; + +import org.apache.lucene.search.Query; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.maven.model.MavenArchetype; +import org.jetbrains.idea.maven.model.MavenArtifactInfo; +import org.jetbrains.idea.maven.model.MavenId; +import org.jetbrains.idea.maven.project.MavenGeneralSettings; +import org.jetbrains.idea.maven.utils.MavenProcessCanceledException; +import org.jetbrains.idea.maven.utils.MavenProgressIndicator; + +import java.io.File; +import java.rmi.RemoteException; +import java.rmi.server.UnicastRemoteObject; +import java.util.Collection; +import java.util.List; +import java.util.Set; + +public class MavenIndexerWrapper { + private final MavenFacadeIndexer myWrappee; + + public MavenIndexerWrapper(MavenFacadeIndexer wrappee) { + myWrappee = wrappee; + } + + public int createIndex(@NotNull String indexId, + @Nullable String repositoryId, + @Nullable File file, + @Nullable String url, + @NotNull File indexDir) throws MavenFacadeIndexerException { + try { + return myWrappee.createIndex(indexId, repositoryId, file, url, indexDir); + } + catch (RemoteException e) { + throw new RuntimeException(e); + } + } + + public void releaseIndex(int id) throws MavenFacadeIndexerException { + try { + myWrappee.releaseIndex(id); + } + catch (RemoteException e) { + throw new RuntimeException(e); + } + } + + public int getIndexCount() { + try { + return myWrappee.getIndexCount(); + } + catch (RemoteException e) { + throw new RuntimeException(e); + } + } + + public void updateIndex(int id, MavenGeneralSettings settings, MavenProgressIndicator indicator) throws MavenProcessCanceledException, + MavenFacadeIndexerException { + try { + MavenFacadeProgressIndicator indicatorWrapper = MavenFacadeManager.wrapAndExport(indicator); + try { + myWrappee.updateIndex(id, MavenFacadeManager.convertSettings(settings), indicatorWrapper); + } + finally { + UnicastRemoteObject.unexportObject(indicatorWrapper, true); + } + } + catch (MavenFacadeProcessCanceledException e) { + throw new MavenProcessCanceledException(); + } + catch (RemoteException e) { + throw new RuntimeException(e); + } + } + + public List getAllArtifacts(int indexId) throws MavenFacadeIndexerException { + try { + return myWrappee.getAllArtifacts(indexId); + } + catch (RemoteException e) { + throw new RuntimeException(e); + } + } + + public MavenId addArtifact(int indexId, File artifactFile) throws MavenFacadeIndexerException { + try { + return myWrappee.addArtifact(indexId, artifactFile); + } + catch (RemoteException e) { + throw new RuntimeException(e); + } + } + + public Set search(int indexId, Query query, int maxResult) throws MavenFacadeIndexerException { + try { + return myWrappee.search(indexId, query, maxResult); + } + catch (RemoteException e) { + throw new RuntimeException(e); + } + } + + public Collection getArchetypes() { + try { + return myWrappee.getArchetypes(); + } + catch (RemoteException e) { + throw new RuntimeException(e); + } + } + + public void release() { + try { + myWrappee.release(); + } + catch (RemoteException e) { + throw new RuntimeException(e); + } + } +} + diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/facade/remote/MavenFacadeManagerImpl.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/facade/remote/MavenFacadeManagerImpl.java deleted file mode 100644 index 87186c62a9ac..000000000000 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/facade/remote/MavenFacadeManagerImpl.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright 2000-2010 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.idea.maven.facade.remote; - -import com.intellij.execution.DefaultExecutionResult; -import com.intellij.execution.ExecutionException; -import com.intellij.execution.ExecutionResult; -import com.intellij.execution.Executor; -import com.intellij.execution.configurations.*; -import com.intellij.execution.process.OSProcessHandler; -import com.intellij.execution.process.ProcessHandler; -import com.intellij.execution.process.ProcessTerminatedListener; -import com.intellij.execution.rmi.RemoteProcessSupport; -import com.intellij.execution.runners.ProgramRunner; -import com.intellij.ide.DataManager; -import com.intellij.openapi.Disposable; -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.PlatformDataKeys; -import com.intellij.openapi.application.PathManager; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.projectRoots.JavaSdkType; -import com.intellij.openapi.projectRoots.JdkUtil; -import com.intellij.openapi.projectRoots.Sdk; -import com.intellij.openapi.projectRoots.SimpleJavaSdkType; -import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.encoding.EncodingProjectManager; -import com.intellij.psi.CommonClassNames; -import com.intellij.util.PathUtil; -import com.intellij.util.SystemProperties; -import com.intellij.util.containers.ContainerUtil; -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.idea.maven.execution.MavenExternalParameters; -import org.jetbrains.idea.maven.execution.MavenRunner; -import org.jetbrains.idea.maven.execution.MavenRunnerParameters; -import org.jetbrains.idea.maven.execution.MavenRunnerSettings; -import org.jetbrains.idea.maven.project.MavenProjectsManager; - -import javax.xml.stream.XMLStreamException; -import java.io.File; -import java.nio.charset.Charset; -import java.util.ArrayList; - -/** - * @author Gregory.Shrago - */ -public class MavenFacadeManagerImpl implements MavenFacadeManager { - @NonNls private static final String MAIN_CLASS = "org.jetbrains.idea.maven.facade.remote.RemoteMavenServer"; - - private final RemoteProcessSupport mySupport; - - public MavenFacadeManagerImpl(final Project project) { - mySupport = new RemoteProcessSupport(project, MavenFacade.class) { - @Override - protected void fireModificationCountChanged() { - } - - @Override - protected String getName(Object file) { - return file.toString(); - } - - @Override - protected RunProfileState getRunProfileState(Object project, Object configuration, Executor executor) throws ExecutionException { - return createRunProfileState(); - } - }; - Disposer.register(project, new Disposable() { - public void dispose() { - mySupport.stopAll(); - } - }); - } - - public MavenFacade getMavenFacade(@NotNull final Object key) throws Exception { - return mySupport.acquire(key, ""); - } - - public void releaseMavenFacade(@NotNull Object key) { - mySupport.release(key, ""); - } - - private RunProfileState createRunProfileState() { - final CommandLineState state = new CommandLineState(null) { - private SimpleJavaParameters createJavaParameters() throws ExecutionException { - final SimpleJavaParameters params = new SimpleJavaParameters(); - - final Project project = mySupport.getProject(); - params.setCharset(EncodingProjectManager.getInstance(project).getDefaultCharset()); - - final MavenRunnerSettings runnerSettings = MavenRunner.getInstance(project).getState(); - MavenExternalParameters.configureSimpleJavaParameters(params, new MavenRunnerParameters(), - MavenProjectsManager.getInstance(project).getGeneralSettings(), - runnerSettings); - - - final Sdk ideaJdk = new SimpleJavaSdkType().createJdk("tmp", SystemProperties.getJavaHome()); - params.setJdk(ideaJdk); - - params.setWorkingDirectory(PathManager.getBinPath()); - final ArrayList classPath = new ArrayList(); - ContainerUtil.addIfNotNull(PathUtil.getJarPathForClass(StringUtil.class), classPath); - ContainerUtil.addIfNotNull(PathUtil.getJarPathForClass(NotNull.class), classPath); - ContainerUtil.addIfNotNull(PathUtil.getJarPathForClass(XMLStreamException.class), classPath); - - params.getClassPath().addAll(classPath); - params.setMainClass(MAIN_CLASS); - params.getClassPath().addFirst(getJarPath(MavenFacadeManagerImpl.this.getClass(), MAIN_CLASS)); - tuneParams(params); - return params; - } - - @Override - public ExecutionResult execute(@NotNull final Executor executor, @NotNull final ProgramRunner runner) throws ExecutionException { - final ProcessHandler processHandler = startProcess(); - return new DefaultExecutionResult(null, processHandler, AnAction.EMPTY_ARRAY); - } - - protected OSProcessHandler startProcess() throws ExecutionException { - final SimpleJavaParameters params = createJavaParameters(); - final Sdk sdk = params.getJdk(); - final GeneralCommandLine commandLine = JdkUtil.setupJVMCommandLine(((JavaSdkType)sdk.getSdkType()).getVMExecutablePath(sdk), params, - JdkUtil.useDynamicClasspath(PlatformDataKeys - .PROJECT.getData(DataManager.getInstance().getDataContext()))); - final OSProcessHandler processHandler = new OSProcessHandler(commandLine.createProcess(), commandLine.getCommandLineString()) { - @Override - public Charset getCharset() { - return commandLine.getCharset(); - } - }; - ProcessTerminatedListener.attach(processHandler); - return processHandler; - } - - }; - return state; - } - - private void tuneParams(SimpleJavaParameters params) { - final String path = getJarPath(getClass(), MAIN_CLASS); - File file = new File(path); - if (file.isDirectory()) { - params.getClassPath().add(file.getPath()); - file = new File(getJarPath(getClass(), "org.apache.maven.artifact.resolver.ArtifactNotFoundException")); - } - - if (file.isFile()) { - final File[] files = file.getParentFile().listFiles(); - for (File jar : files) { - if (jar.isFile() && jar.getName().endsWith(".jar") && !jar.getName().equals("maven.jar")) { - params.getClassPath().add(jar.getPath()); - } - } - } - } - - public static String getJarPath(@NotNull final Class context, @NotNull final String mainClassName) { - final String s = PathManager.getResourceRoot(context, "/" + mainClassName.replace('.', '/') + CommonClassNames.CLASS_FILE_EXTENSION); - return new File(s).getAbsoluteFile().getAbsolutePath(); - } -} diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/FacetImporter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/FacetImporter.java index c7f0db91e427..f18e551e7bae 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/FacetImporter.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/FacetImporter.java @@ -21,7 +21,7 @@ import com.intellij.openapi.module.Module; import com.intellij.openapi.util.io.FileUtil; import com.intellij.util.ArrayUtil; import com.intellij.util.PathUtil; -import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.maven.model.MavenArtifact; import org.jetbrains.idea.maven.project.*; import java.io.File; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/GroovyImporter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/GroovyImporter.java index 47c884a902c9..159cf0c7f581 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/GroovyImporter.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/GroovyImporter.java @@ -2,6 +2,7 @@ package org.jetbrains.idea.maven.importing; import com.intellij.openapi.module.Module; import org.jdom.Element; +import org.jetbrains.idea.maven.model.MavenArtifact; import org.jetbrains.idea.maven.project.*; import org.jetbrains.idea.maven.utils.MavenJDOMUtil; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenFoldersImporter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenFoldersImporter.java index e6ca55c6dc73..7c006e43f603 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenFoldersImporter.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenFoldersImporter.java @@ -21,10 +21,10 @@ import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.ProjectRootManager; +import org.jetbrains.idea.maven.model.MavenResource; import org.jetbrains.idea.maven.project.MavenImportingSettings; import org.jetbrains.idea.maven.project.MavenProject; import org.jetbrains.idea.maven.project.MavenProjectsManager; -import org.jetbrains.idea.maven.project.MavenResource; import java.io.File; import java.util.ArrayList; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenImporter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenImporter.java index 9f0b9704a58c..880f46cd217e 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenImporter.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenImporter.java @@ -18,12 +18,12 @@ package org.jetbrains.idea.maven.importing; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.module.Module; import com.intellij.openapi.util.Pair; -import org.apache.maven.project.*; import org.jdom.Element; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.maven.embedder.MavenEmbedderWrapper; +import org.jetbrains.idea.maven.facade.MavenEmbedderWrapper; +import org.jetbrains.idea.maven.facade.NativeMavenProjectHolder; +import org.jetbrains.idea.maven.model.MavenArtifact; import org.jetbrains.idea.maven.project.*; -import org.jetbrains.idea.maven.project.MavenProject; import org.jetbrains.idea.maven.utils.MavenJDOMUtil; import org.jetbrains.idea.maven.utils.MavenProcessCanceledException; @@ -65,7 +65,7 @@ public abstract class MavenImporter { return null; } - public void resolve(MavenProject project, org.apache.maven.project.MavenProject nativeMavenProject, MavenEmbedderWrapper embedder) + public void resolve(MavenProject project, NativeMavenProjectHolder nativeMavenProject, MavenEmbedderWrapper embedder) throws MavenProcessCanceledException { } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java index 0161d147559a..1b4e3e54ed60 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java @@ -21,8 +21,9 @@ import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.util.Pair; import com.intellij.pom.java.LanguageLevel; import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.maven.model.MavenArtifact; +import org.jetbrains.idea.maven.model.MavenConstants; import org.jetbrains.idea.maven.project.*; -import org.jetbrains.idea.maven.utils.MavenConstants; import org.jetbrains.idea.maven.utils.MavenUtil; import java.util.List; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleNameMapper.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleNameMapper.java index 14836bc6fc94..90429eb9e831 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleNameMapper.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleNameMapper.java @@ -18,7 +18,7 @@ package org.jetbrains.idea.maven.importing; import com.intellij.ide.highlighter.ModuleFileType; import com.intellij.openapi.module.Module; import com.intellij.openapi.util.text.StringUtil; -import org.jetbrains.idea.maven.project.MavenId; +import org.jetbrains.idea.maven.model.MavenId; import org.jetbrains.idea.maven.project.MavenProject; import java.io.File; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenProjectImporter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenProjectImporter.java index 58cb185187d0..b0ffdf219a63 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenProjectImporter.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenProjectImporter.java @@ -37,7 +37,7 @@ import com.intellij.util.Function; import com.intellij.util.containers.Stack; import gnu.trove.THashMap; import gnu.trove.THashSet; -import org.jetbrains.idea.maven.embedder.MavenConsole; +import org.jetbrains.idea.maven.model.MavenArtifact; import org.jetbrains.idea.maven.project.*; import org.jetbrains.idea.maven.utils.MavenLog; import org.jetbrains.idea.maven.utils.MavenProcessCanceledException; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenRootModelAdapter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenRootModelAdapter.java index 5ebda0447bf8..e678d1a840b0 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenRootModelAdapter.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenRootModelAdapter.java @@ -23,17 +23,17 @@ import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.JarFileSystem; +import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.pom.java.LanguageLevel; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.maven.project.MavenArtifact; +import org.jetbrains.idea.maven.model.MavenArtifact; import org.jetbrains.idea.maven.project.MavenProject; import org.jetbrains.idea.maven.project.MavenProjectsManager; -import org.jetbrains.idea.maven.utils.MavenConstants; +import org.jetbrains.idea.maven.model.MavenConstants; import org.jetbrains.idea.maven.utils.Path; import org.jetbrains.idea.maven.utils.Url; import java.io.File; -import java.util.List; public class MavenRootModelAdapter { private static final String MAVEN_LIB_PREFIX = "Maven: "; @@ -250,7 +250,9 @@ public class MavenRootModelAdapter { extension = result.second; } - String newUrl = artifact.getUrlForExtraArtifact(classifier, extension); + + String newPath = artifact.getPathForExtraArtifact(classifier, extension); + String newUrl = VirtualFileManager.constructUrl(JarFileSystem.PROTOCOL, newPath) + JarFileSystem.JAR_SEPARATOR; for (String url : library.getUrls(type)) { if (newUrl.equals(url)) return; if (clearAll || isRepositoryUrl(artifact, url, classifier, extension)) { diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenArchetypesProvider.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenArchetypesProvider.java index db8dde2246d4..adafd0b80517 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenArchetypesProvider.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenArchetypesProvider.java @@ -16,11 +16,12 @@ package org.jetbrains.idea.maven.indices; import com.intellij.openapi.extensions.ExtensionPointName; +import org.jetbrains.idea.maven.model.MavenArchetype; import java.util.Collection; public interface MavenArchetypesProvider { ExtensionPointName EP_NAME = ExtensionPointName.create("org.jetbrains.idea.maven.archetypesProvider"); - Collection getArchetypes(); + Collection getArchetypes(); } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenArtifactSearchDialog.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenArtifactSearchDialog.java index ea7ebf7ddd60..034a16e657da 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenArtifactSearchDialog.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenArtifactSearchDialog.java @@ -18,7 +18,7 @@ package org.jetbrains.idea.maven.indices; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import gnu.trove.THashMap; -import org.jetbrains.idea.maven.project.MavenId; +import org.jetbrains.idea.maven.model.MavenId; import javax.swing.*; import javax.swing.event.ChangeEvent; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenArtifactSearchPanel.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenArtifactSearchPanel.java index 7c1b3d290b7d..dd69617045b4 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenArtifactSearchPanel.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenArtifactSearchPanel.java @@ -24,9 +24,9 @@ import com.intellij.ui.treeStructure.Tree; import com.intellij.util.Alarm; import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.tree.TreeUtil; -import org.jetbrains.idea.maven.project.MavenId; +import org.jetbrains.idea.maven.model.MavenArtifactInfo; +import org.jetbrains.idea.maven.model.MavenId; import org.jetbrains.idea.maven.utils.MavenLog; -import org.sonatype.nexus.index.ArtifactInfo; import javax.swing.*; import javax.swing.event.DocumentEvent; @@ -171,15 +171,15 @@ public class MavenArtifactSearchPanel extends JPanel { public MavenId getResult() { Object sel = myResultList.getLastSelectedPathComponent(); - ArtifactInfo info; - if (sel instanceof ArtifactInfo) { - info = (ArtifactInfo)sel; + MavenArtifactInfo info; + if (sel instanceof MavenArtifactInfo) { + info = (MavenArtifactInfo)sel; } else { info = ((MavenArtifactSearchResult)sel).versions.get(0); } - return new MavenId(info.groupId, info.artifactId, info.version); + return new MavenId(info.getGroupId(), info.getArtifactId(), info.getVersion()); } private static class MyTreeModel implements TreeModel { @@ -260,9 +260,9 @@ public class MavenArtifactSearchPanel extends JPanel { else if (value instanceof MavenArtifactSearchResult) { formatSearchResult(tree, (MavenArtifactSearchResult)value); } - else if (value instanceof ArtifactInfo) { - ArtifactInfo info = (ArtifactInfo)value; - myLeftComponent.append(info.groupId + ":" + info.artifactId + ":" + info.version, + else if (value instanceof MavenArtifactInfo) { + MavenArtifactInfo info = (MavenArtifactInfo)value; + myLeftComponent.append(info.getGroupId() + ":" + info.getArtifactId() + ":" + info.getVersion(), SimpleTextAttributes.GRAY_ATTRIBUTES); } @@ -277,10 +277,10 @@ public class MavenArtifactSearchPanel extends JPanel { } protected void formatSearchResult(JTree tree, MavenArtifactSearchResult searchResult) { - ArtifactInfo first = searchResult.versions.get(0); - ArtifactInfo last = searchResult.versions.get(searchResult.versions.size() - 1); - myLeftComponent.append(first.groupId + ":" + first.artifactId, SimpleTextAttributes.REGULAR_ATTRIBUTES); - myLeftComponent.append(":" + last.version + "-" + first.version, SimpleTextAttributes.GRAY_ATTRIBUTES); + MavenArtifactInfo first = searchResult.versions.get(0); + MavenArtifactInfo last = searchResult.versions.get(searchResult.versions.size() - 1); + myLeftComponent.append(first.getGroupId() + ":" + first.getArtifactId(), SimpleTextAttributes.REGULAR_ATTRIBUTES); + myLeftComponent.append(":" + last.getVersion() + "-" + first.getVersion(), SimpleTextAttributes.GRAY_ATTRIBUTES); } } @@ -288,12 +288,12 @@ public class MavenArtifactSearchPanel extends JPanel { @Override protected void formatSearchResult(JTree tree, MavenArtifactSearchResult searchResult) { MavenClassSearchResult classResult = (MavenClassSearchResult)searchResult; - ArtifactInfo info = searchResult.versions.get(0); + MavenArtifactInfo info = searchResult.versions.get(0); myLeftComponent.append(classResult.className, SimpleTextAttributes.REGULAR_ATTRIBUTES); myLeftComponent.append(" (" + classResult.packageName + ")", SimpleTextAttributes.GRAY_ATTRIBUTES); - myRightComponent.append(" " + info.groupId + ":" + info.artifactId, + myRightComponent.append(" " + info.getGroupId() + ":" + info.getArtifactId(), SimpleTextAttributes.GRAY_ATTRIBUTES); } } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenArtifactSearchResult.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenArtifactSearchResult.java index 574bcc1907fb..93b2c328b0f2 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenArtifactSearchResult.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenArtifactSearchResult.java @@ -15,11 +15,12 @@ */ package org.jetbrains.idea.maven.indices; -import org.sonatype.nexus.index.ArtifactInfo; -import java.util.List; +import org.jetbrains.idea.maven.model.MavenArtifactInfo; + import java.util.ArrayList; +import java.util.List; public class MavenArtifactSearchResult { - public List versions = new ArrayList(); + public List versions = new ArrayList(); } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenArtifactSearcher.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenArtifactSearcher.java index 3e28e44396c3..dd8893f3bb8d 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenArtifactSearcher.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenArtifactSearcher.java @@ -20,11 +20,14 @@ import com.intellij.openapi.util.text.StringUtil; import gnu.trove.THashMap; import org.apache.lucene.index.Term; import org.apache.lucene.search.*; -import org.sonatype.nexus.index.ArtifactInfo; +import org.jetbrains.idea.maven.facade.MavenFacadeIndexer; +import org.jetbrains.idea.maven.model.MavenArtifactInfo; import java.util.*; public class MavenArtifactSearcher extends MavenSearcher { + public static final String TERM = MavenFacadeIndexer.SEARCH_TERM_COORDINATES; + protected Pair preparePatternAndQuery(String pattern) { pattern = pattern.toLowerCase(); if (pattern.trim().length() == 0) return Pair.create(pattern, (Query)new MatchAllDocsQuery()); @@ -37,31 +40,28 @@ public class MavenArtifactSearcher extends MavenSearcher= 3) { String s = "*" + parts.get(0) + "*|*" + parts.get(1) + "*|" + parts.get(2) + "*|*"; - query.add(new WildcardQuery(new Term(ArtifactInfo.UINFO, s)), BooleanClause.Occur.MUST); + query.add(new WildcardQuery(new Term(TERM, s)), BooleanClause.Occur.MUST); } return Pair.create(pattern, (Query)query); } - protected Collection processResults(Set infos, String pattern, int maxResult) { + protected Collection processResults(Set infos, String pattern, int maxResult) { Map result = new THashMap(); - for (ArtifactInfo each : infos) { - if (!StringUtil.isEmptyOrSpaces(each.classifier)) continue; // todo skip for now - + for (MavenArtifactInfo each : infos) { + if (!StringUtil.isEmptyOrSpaces(each.getClassifier())) continue; // todo skip for now + String key = makeKey(each); MavenArtifactSearchResult searchResult = result.get(key); if (searchResult == null) { diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenClassSearcher.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenClassSearcher.java index 231e6afc5586..805d1a7166b4 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenClassSearcher.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenClassSearcher.java @@ -22,7 +22,8 @@ import org.apache.lucene.index.Term; import org.apache.lucene.search.MatchAllDocsQuery; import org.apache.lucene.search.Query; import org.apache.lucene.search.WildcardQuery; -import org.sonatype.nexus.index.ArtifactInfo; +import org.jetbrains.idea.maven.facade.MavenFacadeIndexer; +import org.jetbrains.idea.maven.model.MavenArtifactInfo; import java.util.*; import java.util.regex.Matcher; @@ -30,6 +31,8 @@ import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; public class MavenClassSearcher extends MavenSearcher { + public static final String TERM = MavenFacadeIndexer.SEARCH_TERM_CLASS_NAMES; + protected Pair preparePatternAndQuery(String pattern) { pattern = pattern.toLowerCase(); if (pattern.trim().length() == 0) { @@ -53,10 +56,10 @@ public class MavenClassSearcher extends MavenSearcher { pattern = newPattern.toString(); String queryPattern = "*/" + pattern.replaceAll("\\.", "/"); - return new Pair(pattern, new WildcardQuery(new Term(ArtifactInfo.NAMES, queryPattern))); + return new Pair(pattern, new WildcardQuery(new Term(TERM, queryPattern))); } - protected Collection processResults(Set infos, String pattern, int maxResult) { + protected Collection processResults(Set infos, String pattern, int maxResult) { if (pattern.length() == 0 || pattern.equals("*")) { pattern = "^/(.*)$"; } @@ -84,10 +87,10 @@ public class MavenClassSearcher extends MavenSearcher { } Map result = new THashMap(); - for (ArtifactInfo each : infos) { - if (each.classNames == null) continue; + for (MavenArtifactInfo each : infos) { + if (each.getClassNames() == null) continue; - Matcher matcher = p.matcher(each.classNames); + Matcher matcher = p.matcher(each.getClassNames()); while (matcher.find()) { String classFQName = matcher.group(1); classFQName = classFQName.replace("/", "."); @@ -124,7 +127,7 @@ public class MavenClassSearcher extends MavenSearcher { return makeKey(result.className, result.versions.get(0)); } - private String makeKey(String className, ArtifactInfo info) { + private String makeKey(String className, MavenArtifactInfo info) { return className + " " + super.makeKey(info); } } \ No newline at end of file diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndex.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndex.java index 0931a02e86b7..f20318243e41 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndex.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndex.java @@ -15,35 +15,22 @@ */ package org.jetbrains.idea.maven.indices; -import com.intellij.openapi.progress.EmptyProgressIndicator; -import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.io.*; import gnu.trove.THashMap; import gnu.trove.THashSet; -import org.apache.lucene.document.Document; -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.search.BooleanQuery; -import org.apache.lucene.search.Filter; import org.apache.lucene.search.Query; -import org.apache.lucene.search.TopDocs; -import org.apache.maven.artifact.manager.WagonManager; -import org.apache.maven.wagon.events.TransferEvent; import org.jetbrains.annotations.TestOnly; -import org.jetbrains.idea.maven.embedder.MavenEmbedderWrapper; -import org.jetbrains.idea.maven.project.TransferListenerAdapter; +import org.jetbrains.idea.maven.facade.MavenFacadeIndexerException; +import org.jetbrains.idea.maven.facade.MavenIndexerWrapper; +import org.jetbrains.idea.maven.model.MavenArtifactInfo; +import org.jetbrains.idea.maven.model.MavenId; +import org.jetbrains.idea.maven.project.MavenGeneralSettings; import org.jetbrains.idea.maven.utils.MavenLog; +import org.jetbrains.idea.maven.utils.MavenProcessCanceledException; import org.jetbrains.idea.maven.utils.MavenProgressIndicator; -import org.sonatype.nexus.index.*; -import org.sonatype.nexus.index.context.IndexUtils; -import org.sonatype.nexus.index.context.IndexingContext; -import org.sonatype.nexus.index.context.UnsupportedExistingLuceneIndexException; -import org.sonatype.nexus.index.updater.IndexUpdateRequest; -import org.sonatype.nexus.index.updater.IndexUpdater; import java.io.*; import java.util.*; @@ -75,8 +62,7 @@ public class MavenIndex { LOCAL, REMOTE } - private final NexusIndexer myIndexer; - private final ArtifactContextProducer myArtifactContextProducer; + private final MavenIndexerWrapper myIndexer; private final File myDir; private final String myRepositoryId; @@ -92,15 +78,13 @@ public class MavenIndex { private volatile boolean isBroken; private final IndexListener myListener; - public MavenIndex(NexusIndexer indexer, - ArtifactContextProducer artifactContextProducer, + public MavenIndex(MavenIndexerWrapper indexer, File dir, String repositoryId, String repositoryPathOrUrl, Kind kind, IndexListener listener) throws MavenIndexException { myIndexer = indexer; - myArtifactContextProducer = artifactContextProducer; myDir = dir; myRepositoryId = repositoryId; myRepositoryPathOrUrl = normalizePathOrUrl(repositoryPathOrUrl); @@ -110,12 +94,10 @@ public class MavenIndex { open(); } - public MavenIndex(NexusIndexer indexer, - ArtifactContextProducer artifactContextProducer, + public MavenIndex(MavenIndexerWrapper indexer, File dir, IndexListener listener) throws MavenIndexException { myIndexer = indexer; - myArtifactContextProducer = artifactContextProducer; myDir = dir; myListener = listener; @@ -211,7 +193,7 @@ public class MavenIndex { try { if (myData != null) myData.close(); } - catch (IOException e) { + catch (MavenIndexException e) { MavenLog.LOG.warn(e); } myData = null; @@ -278,19 +260,17 @@ public class MavenIndex { return myFailureMessage; } - public void updateOrRepair(MavenEmbedderWrapper embedderToUse, - IndexUpdater updater, - boolean fullUpdate, - ProgressIndicator progress) { + public void updateOrRepair(boolean fullUpdate, MavenGeneralSettings settings, MavenProgressIndicator progress) + throws MavenProcessCanceledException { try { if (fullUpdate) { if (myKind == Kind.LOCAL) FileUtil.delete(getUpdateDir()); - IndexingContext context = createContext(getUpdateDir(), "update"); + int context = createContext(getUpdateDir(), "update"); try { - updateContext(embedderToUse, context, updater, progress); + updateContext(context, settings, progress); } finally { - myIndexer.removeIndexingContext(context, false); + myIndexer.releaseIndex(context); } } updateData(progress); @@ -298,10 +278,10 @@ public class MavenIndex { isBroken = false; myFailureMessage = null; } - catch (IOException e) { - handleUpdateException(e); + catch (MavenProcessCanceledException e) { + throw e; } - catch (UnsupportedExistingLuceneIndexException e) { + catch (Exception e) { handleUpdateException(e); } @@ -313,64 +293,37 @@ public class MavenIndex { MavenLog.LOG.info("Failed to update Maven indices for: [" + myRepositoryId + "] " + myRepositoryPathOrUrl, e); } - private IndexingContext createContext(File contextDir, String suffix) throws IOException, UnsupportedExistingLuceneIndexException { + private int createContext(File contextDir, String suffix) throws MavenFacadeIndexerException { String indexId = myDir.getName() + "-" + suffix; // Nexus cannot update index if the id does not equal to the stored one. String repoId = contextDir.exists() ? null : myDir.getName(); - return myIndexer.addIndexingContext(indexId, - repoId, - getRepositoryFile(), - contextDir, - getRepositoryUrl(), - null, // repo update url - NexusIndexer.FULL_INDEX); + return myIndexer.createIndex(indexId, + repoId, + getRepositoryFile(), + getRepositoryUrl(), + contextDir); } private File getUpdateDir() { return new File(myDir, UPDATE_DIR); } - private void updateContext(MavenEmbedderWrapper embedder, - IndexingContext context, - IndexUpdater updater, - ProgressIndicator progress) throws IOException, UnsupportedExistingLuceneIndexException { - if (Kind.LOCAL == myKind) { - progress.setIndeterminate(true); - try { - myIndexer.scan(context, new MyScanningListener(), false); - } - finally { - progress.setIndeterminate(false); - } - } - else { - IndexUpdateRequest request = new IndexUpdateRequest(context); - request.setResourceFetcher(new MavenIndexFetcher(myRepositoryId, - getRepositoryUrl(), - embedder.getComponent(WagonManager.class), - new TransferListenerAdapter(new MavenProgressIndicator(progress)) { - @Override - protected void doUpdateProgress(long downloaded, long total) { - super.doUpdateProgress(downloaded, total); - myIndicator.setFraction(((double)downloaded) / total); - } - - @Override - public void transferCompleted(TransferEvent event) { - super.transferCompleted(event); - myIndicator.setText2(IndicesBundle.message("maven.indices.updating.processing")); - } - })); - updater.fetchAndUpdateIndex(request); - } + private void updateContext(int indexId, MavenGeneralSettings settings, MavenProgressIndicator progress) + throws MavenFacadeIndexerException, MavenProcessCanceledException { + myIndexer.updateIndex(indexId, settings, progress); } - private void updateData(ProgressIndicator progress) throws IOException, UnsupportedExistingLuceneIndexException { + private void updateData(MavenProgressIndicator progress) throws MavenIndexException { String newDataDirName; IndexData newData; newDataDirName = findAvailableDataDirName(); - FileUtil.copyDir(getUpdateDir(), getDataContextDir(getDataDir(newDataDirName))); + try { + FileUtil.copyDir(getUpdateDir(), getDataContextDir(getDataDir(newDataDirName))); + } + catch (IOException e) { + throw new MavenIndexException(e); + } newData = openData(newDataDirName); try { @@ -381,7 +334,8 @@ public class MavenIndex { newData.close(); FileUtil.delete(getDataDir(newDataDirName)); - if (e instanceof IOException) throw (IOException)e; + if (e instanceof MavenFacadeIndexerException) throw new MavenIndexException(e); + if (e instanceof IOException) throw new MavenIndexException(e); throw new RuntimeException(e); } @@ -402,7 +356,7 @@ public class MavenIndex { } private void doUpdateIndexData(IndexData data, - ProgressIndicator progress) throws IOException { + MavenProgressIndicator progress) throws IOException, MavenFacadeIndexerException { Set groups = new THashSet(); Set groupsWithArtifacts = new THashSet(); Set groupsWithArtifactsWithVersions = new THashSet(); @@ -410,23 +364,15 @@ public class MavenIndex { Map> groupToArtifactMap = new THashMap>(); Map> groupWithArtifactToVersionMap = new THashMap>(); - IndexReader r = data.context.getIndexReader(); - int total = r.numDocs(); + List artifacts = myIndexer.getAllArtifacts(data.indexId); + int total = artifacts.size(); for (int i = 0; i < total; i++) { progress.setFraction(i / total); + MavenId each = artifacts.get(i); - if (r.isDeleted(i)) continue; - - Document doc = r.document(i); - String uinfo = doc.get(ArtifactInfo.UINFO); - if (uinfo == null) continue; - - List parts = StringUtil.split(uinfo, "|"); - String groupId = parts.get(0); - String artifactId = parts.get(1); - String version = parts.get(2); - - if (groupId == null || artifactId == null || version == null) continue; + String groupId = each.getGroupId(); + String artifactId = each.getArtifactId(); + String version = each.getVersion(); groups.add(groupId); groupsWithArtifacts.add(groupId + ":" + artifactId); @@ -465,7 +411,7 @@ public class MavenIndex { } } - private IndexData openData(String dataDir) throws IOException, UnsupportedExistingLuceneIndexException { + private IndexData openData(String dataDir) throws MavenIndexException { File dir = getDataDir(dataDir); dir.mkdirs(); return new IndexData(dir); @@ -506,18 +452,11 @@ public class MavenIndex { public synchronized void addArtifact(final File artifactFile) { doIndexTask(new IndexTask() { public Object doTask() throws Exception { - ArtifactContext artifactContext = myArtifactContextProducer.getArtifactContext(myData.context, artifactFile); - if (artifactContext == null) return null; + MavenId id = myIndexer.addArtifact(myData.indexId, artifactFile); - myIndexer.addArtifactToIndex(artifactContext, myData.context); - - ArtifactInfo artifactInfo = artifactContext.getArtifactInfo(); - - String groupId = artifactInfo.groupId; - String artifactId = artifactInfo.artifactId; - String version = artifactInfo.version; - - if (groupId == null || artifactId == null || version == null) return null; + String groupId = id.getGroupId(); + String artifactId = id.getArtifactId(); + String version = id.getVersion(); myData.groups.enumerate(groupId); myData.hasGroupCache.put(groupId, true); @@ -615,36 +554,12 @@ public class MavenIndex { return result; } - public synchronized Set search(final Query query, final int maxResult) { - return doIndexTask(new IndexTask>() { - public Set doTask() throws Exception { - TopDocs docs = null; - - try { - BooleanQuery.setMaxClauseCount(Integer.MAX_VALUE); - docs = myData.context.getIndexSearcher().search(query, (Filter)null, maxResult); - } - catch (BooleanQuery.TooManyClauses ignore) { - // this exception occurs when too wide wildcard is used on too big data. - } - - if (docs.scoreDocs.length == 0) return Collections.emptySet(); - - Set result = new THashSet(); - - for (int i = 0; i < docs.scoreDocs.length; i++) { - int docIndex = docs.scoreDocs[i].doc; - Document doc = myData.context.getIndexReader().document(docIndex); - ArtifactInfo artifactInfo = IndexUtils.constructArtifactInfo(doc, myData.context); - - if (artifactInfo == null) continue; - - artifactInfo.repository = myRepositoryPathOrUrl; - result.add(artifactInfo); - } - return result; + public synchronized Set search(final Query query, final int maxResult) { + return doIndexTask(new IndexTask>() { + public Set doTask() throws Exception { + return myIndexer.search(myData.indexId, query, maxResult); } - }, Collections.emptySet()); + }, Collections.emptySet()); } private T doIndexTask(IndexTask task, T defaultValue) { @@ -672,7 +587,7 @@ public class MavenIndex { return defaultValue; } - private static interface IndexTask { + private interface IndexTask { T doTask() throws Exception; } @@ -688,9 +603,9 @@ public class MavenIndex { final Map hasArtifactCache = new THashMap(); final Map hasVersionCache = new THashMap(); - final IndexingContext context; + final int indexId; - public IndexData(File dir) throws IOException, UnsupportedExistingLuceneIndexException { + public IndexData(File dir) throws MavenIndexException { try { groups = new PersistentStringEnumerator(new File(dir, GROUP_IDS_FILE)); groupsWithArtifacts = new PersistentStringEnumerator(new File(dir, ARTIFACT_IDS_FILE)); @@ -699,15 +614,15 @@ public class MavenIndex { groupToArtifactMap = createPersistentMap(new File(dir, ARTIFACT_IDS_MAP_FILE)); groupWithArtifactToVersionMap = createPersistentMap(new File(dir, VERSIONS_MAP_FILE)); - context = createContext(getDataContextDir(dir), dir.getName()); + indexId = createContext(getDataContextDir(dir), dir.getName()); } catch (IOException e) { close(); - throw e; + throw new MavenIndexException(e); } - catch (UnsupportedExistingLuceneIndexException e) { + catch (MavenFacadeIndexerException e) { close(); - throw e; + throw new MavenIndexException(e); } } @@ -715,15 +630,15 @@ public class MavenIndex { return new PersistentHashMap>(f, new EnumeratorStringDescriptor(), new SetDescriptor()); } - public void close() throws IOException { - IOException[] exceptions = new IOException[1]; + public void close() throws MavenIndexException { + MavenIndexException[] exceptions = new MavenIndexException[1]; try { - if (context!= null) myIndexer.removeIndexingContext(context, false); + if (indexId != 0) myIndexer.releaseIndex(indexId); } - catch (IOException e) { + catch (MavenFacadeIndexerException e) { MavenLog.LOG.info(e); - if (exceptions[0] == null) exceptions[0] = e; + if (exceptions[0] == null) exceptions[0] = new MavenIndexException(e); } safeClose(groups, exceptions); @@ -736,13 +651,13 @@ public class MavenIndex { if (exceptions[0] != null) throw exceptions[0]; } - private void safeClose(PersistentEnumerator enumerator, IOException[] exceptions) throws IOException { + private void safeClose(PersistentEnumerator enumerator, MavenIndexException[] exceptions) { try { if (enumerator != null) enumerator.close(); } catch (IOException e) { MavenLog.LOG.info(e); - if (exceptions[0] == null) exceptions[0] = e; + if (exceptions[0] == null) exceptions[0] = new MavenIndexException(e); } } @@ -774,35 +689,7 @@ public class MavenIndex { } } - private static class MyScanningListener implements ArtifactScanningListener { - private final ProgressIndicator p; - - public MyScanningListener() { - ProgressIndicator p = ProgressManager.getInstance().getProgressIndicator(); - if (p == null) p = new EmptyProgressIndicator(); - this.p = p; - } - - public void scanningStarted(IndexingContext ctx) { - p.checkCanceled(); - } - - public void scanningFinished(IndexingContext ctx, ScanningResult result) { - p.checkCanceled(); - } - - public void artifactError(ArtifactContext ac, Exception e) { - } - - public void artifactDiscovered(ArtifactContext ac) { - p.checkCanceled(); - ArtifactInfo info = ac.getArtifactInfo(); - String artifact = info.groupId + ":" + info.artifactId + ":" + info.version; - p.setText2(artifact); - } - } - - public static interface IndexListener { + public interface IndexListener { void indexIsBroken(MavenIndex index); } } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndices.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndices.java index 2517688fb621..62ea3dd5282c 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndices.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndices.java @@ -16,24 +16,19 @@ package org.jetbrains.idea.maven.indices; import com.intellij.openapi.progress.ProcessCanceledException; -import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.util.io.FileUtil; -import org.jetbrains.annotations.TestOnly; -import org.jetbrains.idea.maven.embedder.MavenEmbedderWrapper; +import org.jetbrains.idea.maven.facade.MavenIndexerWrapper; +import org.jetbrains.idea.maven.project.MavenGeneralSettings; import org.jetbrains.idea.maven.utils.MavenLog; -import org.sonatype.nexus.index.ArtifactContextProducer; -import org.sonatype.nexus.index.NexusIndexer; -import org.sonatype.nexus.index.updater.IndexUpdater; +import org.jetbrains.idea.maven.utils.MavenProcessCanceledException; +import org.jetbrains.idea.maven.utils.MavenProgressIndicator; import java.io.File; import java.util.ArrayList; import java.util.List; public class MavenIndices { - private final MavenEmbedderWrapper myEmbedder; - private final NexusIndexer myIndexer; - private final IndexUpdater myUpdater; - private final ArtifactContextProducer myArtifactContextProducer; + private final MavenIndexerWrapper myIndexer; private final File myIndicesDir; private final MavenIndex.IndexListener myListener; @@ -41,15 +36,11 @@ public class MavenIndices { private final List myIndices = new ArrayList(); private static final Object ourDirectoryLock = new Object(); - public MavenIndices(MavenEmbedderWrapper embedder, File indicesDir, MavenIndex.IndexListener listener) { - myEmbedder = embedder; + public MavenIndices(MavenIndexerWrapper indexer, File indicesDir, MavenIndex.IndexListener listener) { + myIndexer = indexer; myIndicesDir = indicesDir; myListener = listener; - myIndexer = myEmbedder.getComponent(NexusIndexer.class); - myUpdater = myEmbedder.getComponent(IndexUpdater.class); - myArtifactContextProducer = myEmbedder.getComponent(ArtifactContextProducer.class); - load(); } @@ -62,7 +53,7 @@ public class MavenIndices { if (!each.isDirectory()) continue; try { - MavenIndex index = new MavenIndex(myIndexer, myArtifactContextProducer, each, myListener); + MavenIndex index = new MavenIndex(myIndexer, each, myListener); if (find(index.getRepositoryId(), index.getRepositoryPathOrUrl(), index.getKind()) != null) { index.close(); FileUtil.delete(each); @@ -77,11 +68,6 @@ public class MavenIndices { } } - @TestOnly - public NexusIndexer getIndexer() { - return myIndexer; - } - public synchronized void close() { for (MavenIndex each : myIndices) { each.close(); @@ -98,7 +84,7 @@ public class MavenIndices { if (index != null) return index; File dir = getAvailableIndexDir(); - index = new MavenIndex(myIndexer, myArtifactContextProducer, dir, repositoryId, repositoryPathOrUrl, kind, myListener); + index = new MavenIndex(myIndexer, dir, repositoryId, repositoryPathOrUrl, kind, myListener); myIndices.add(index); return index; } @@ -129,10 +115,8 @@ public class MavenIndices { } } - public void updateOrRepair(MavenIndex index, - MavenEmbedderWrapper embedderToUse, - boolean fullUpdate, - ProgressIndicator progress)throws ProcessCanceledException { - index.updateOrRepair(embedderToUse, myUpdater, fullUpdate, progress); + public void updateOrRepair(MavenIndex index, boolean fullUpdate, MavenGeneralSettings settings, MavenProgressIndicator progress) + throws MavenProcessCanceledException { + index.updateOrRepair(fullUpdate, settings, progress); } } \ No newline at end of file diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndicesManager.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndicesManager.java index 859381cbb4f2..272ae3852f30 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndicesManager.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndicesManager.java @@ -16,8 +16,6 @@ package org.jetbrains.idea.maven.indices; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ReadAction; -import com.intellij.openapi.application.Result; import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.progress.BackgroundTaskQueue; @@ -25,27 +23,25 @@ import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.ShutDownTracker; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import gnu.trove.THashSet; -import org.apache.maven.archetype.catalog.Archetype; -import org.apache.maven.archetype.catalog.ArchetypeCatalog; -import org.apache.maven.archetype.source.ArchetypeDataSource; -import org.apache.maven.archetype.source.ArchetypeDataSourceException; import org.jdom.Document; import org.jdom.Element; import org.jdom.JDOMException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.TestOnly; -import org.jetbrains.idea.maven.utils.MavenRehighlighter; -import org.jetbrains.idea.maven.embedder.MavenEmbedderWrapper; +import org.jetbrains.idea.maven.facade.MavenFacadeIndexer; +import org.jetbrains.idea.maven.facade.MavenFacadeManager; +import org.jetbrains.idea.maven.facade.MavenIndexerWrapper; +import org.jetbrains.idea.maven.model.MavenArchetype; import org.jetbrains.idea.maven.project.MavenGeneralSettings; import org.jetbrains.idea.maven.project.MavenProjectsManager; -import org.jetbrains.idea.maven.utils.MavenLog; -import org.jetbrains.idea.maven.utils.MavenUtil; +import org.jetbrains.idea.maven.utils.*; import java.io.File; import java.io.IOException; @@ -68,7 +64,7 @@ public class MavenIndicesManager implements ApplicationComponent { private volatile File myTestIndicesDir; - private volatile MavenEmbedderWrapper myEmbedder; + private volatile MavenIndexerWrapper myIndexer = MavenFacadeManager.getInstance().createIndexer(); private volatile MavenIndices myIndices; private final Object myUpdatingIndicesLock = new Object(); @@ -76,7 +72,7 @@ public class MavenIndicesManager implements ApplicationComponent { private volatile MavenIndex myUpdatingIndex; private final BackgroundTaskQueue myUpdatingQueue = new BackgroundTaskQueue(IndicesBundle.message("maven.indices.updating")); - private volatile List myUserArchetypes = new ArrayList(); + private volatile List myUserArchetypes = new ArrayList(); public static MavenIndicesManager getInstance() { return ApplicationManager.getApplication().getComponent(MavenIndicesManager.class); @@ -103,9 +99,9 @@ public class MavenIndicesManager implements ApplicationComponent { private synchronized void ensureInitialized() { if (myIndices != null) return; - MavenGeneralSettings defaultSettings = new MavenGeneralSettings(); - myEmbedder = MavenEmbedderWrapper.create(defaultSettings); - myIndices = new MavenIndices(myEmbedder, getIndicesDir(), new MavenIndex.IndexListener() { + // todo remove defaultProject + myIndexer = MavenFacadeManager.getInstance().createIndexer(); + myIndices = new MavenIndices(myIndexer, getIndicesDir(), new MavenIndex.IndexListener() { public void indexIsBroken(MavenIndex index) { scheduleUpdate(null, Collections.singletonList(index), false); } @@ -144,14 +140,14 @@ public class MavenIndicesManager implements ApplicationComponent { myIndices = null; } - if (myEmbedder != null) { + if (myIndexer != null) { try { - myEmbedder.release(); + myIndexer.release(); } catch (Exception e) { MavenLog.LOG.error("", e); } - myEmbedder = null; + myIndexer = null; } } @@ -236,12 +232,19 @@ public class MavenIndicesManager implements ApplicationComponent { myUpdatingQueue.run(new Task.Backgroundable(projectOrNull, IndicesBundle.message("maven.indices.updating"), true) { public void run(@NotNull ProgressIndicator indicator) { - doUpdateIndices(projectOrNull, toSchedule, fullUpdate, indicator); + try { + doUpdateIndices(projectOrNull, toSchedule, fullUpdate, new MavenProgressIndicator(indicator)); + } + catch (MavenProcessCanceledException ignore) { + } } }); } - private void doUpdateIndices(final Project projectOrNull, List indices, boolean fullUpdate, ProgressIndicator indicator) { + private void doUpdateIndices(final Project projectOrNull, List indices, boolean fullUpdate, MavenProgressIndicator indicator) + throws MavenProcessCanceledException { + MavenLog.LOG.assertTrue(!fullUpdate || projectOrNull != null); + List remainingWaiting = new ArrayList(indices); try { @@ -259,28 +262,8 @@ public class MavenIndicesManager implements ApplicationComponent { } try { - MavenEmbedderWrapper embedderToUse = null; - if (fullUpdate) { - embedderToUse = new ReadAction() { - @Override - protected void run(Result result) throws Throwable { - if (!projectOrNull.isDisposed()) { - MavenGeneralSettings settings = MavenProjectsManager.getInstance(projectOrNull).getGeneralSettings(); - result.setResult(MavenEmbedderWrapper.create(settings)); - } - } - }.execute().getResultObject(); - if (embedderToUse == null /* project disposed */) throw new ProcessCanceledException(); - } - - try { - getIndicesObject().updateOrRepair(each, embedderToUse, fullUpdate, indicator); - } - finally { - if (embedderToUse != null) embedderToUse.release(); - } - - scheduleRehighlightAllPoms(projectOrNull); + getIndicesObject().updateOrRepair(each, fullUpdate, fullUpdate ? getMavenSettings(projectOrNull) : null, indicator); + if (projectOrNull != null) MavenRehighlighter.rehighlight(projectOrNull); } finally { synchronized (myUpdatingIndicesLock) { @@ -289,8 +272,6 @@ public class MavenIndicesManager implements ApplicationComponent { } } } - catch (ProcessCanceledException ignore) { - } finally { synchronized (myUpdatingIndicesLock) { myWaitingIndices.removeAll(remainingWaiting); @@ -298,6 +279,10 @@ public class MavenIndicesManager implements ApplicationComponent { } } + private MavenGeneralSettings getMavenSettings(Project project) { + return MavenProjectsManager.getInstance(project).getGeneralSettings(); + } + public IndexUpdatingState getUpdatingState(MavenIndex index) { synchronized (myUpdatingIndicesLock) { if (myUpdatingIndex == index) return IndexUpdatingState.UPDATING; @@ -306,16 +291,9 @@ public class MavenIndicesManager implements ApplicationComponent { } } - private void scheduleRehighlightAllPoms(final Project projectOrNull) { - if (projectOrNull == null) return; - MavenRehighlighter.rehighlight(projectOrNull); - } - - public synchronized Set getArchetypes() { + public synchronized Set getArchetypes() { ensureInitialized(); - Set result = new THashSet(); - result.addAll(getArchetypesFrom("internal-catalog")); - result.addAll(getArchetypesFrom("nexus")); + Set result = new THashSet(myIndexer.getArchetypes()); result.addAll(myUserArchetypes); for (MavenArchetypesProvider each : Extensions.getExtensions(MavenArchetypesProvider.EP_NAME)) { @@ -324,7 +302,7 @@ public class MavenIndicesManager implements ApplicationComponent { return result; } - public synchronized void addArchetype(ArchetypeInfo archetype) { + public synchronized void addArchetype(MavenArchetype archetype) { ensureInitialized(); myUserArchetypes.add(archetype); saveUserArchetypes(); @@ -338,7 +316,7 @@ public class MavenIndicesManager implements ApplicationComponent { Document doc = JDOMUtil.loadDocument(file); Element root = doc.getRootElement(); if (root == null) return; - List result = new ArrayList(); + List result = new ArrayList(); for (Element each : (Iterable)root.getChildren(ELEMENT_ARCHETYPE)) { String groupId = each.getAttributeValue(ELEMENT_GROUP_ID); String artifactId = each.getAttributeValue(ELEMENT_ARTIFACT_ID); @@ -352,7 +330,7 @@ public class MavenIndicesManager implements ApplicationComponent { continue; } - result.add(new ArchetypeInfo(groupId, artifactId, version, repository, description)); + result.add(new MavenArchetype(groupId, artifactId, version, repository, description)); } myUserArchetypes = result; @@ -367,7 +345,7 @@ public class MavenIndicesManager implements ApplicationComponent { private void saveUserArchetypes() { Element root = new Element(ELEMENT_ARCHETYPES); - for (ArchetypeInfo each : myUserArchetypes) { + for (MavenArchetype each : myUserArchetypes) { Element childElement = new Element(ELEMENT_ARCHETYPE); childElement.setAttribute(ELEMENT_GROUP_ID, each.groupId); childElement.setAttribute(ELEMENT_ARTIFACT_ID, each.artifactId); @@ -393,22 +371,4 @@ public class MavenIndicesManager implements ApplicationComponent { private File getUserArchetypesFile() { return new File(getIndicesDir(), "UserArchetypes.xml"); } - - private List getArchetypesFrom(String roleHint) { - try { - ArchetypeDataSource source = myEmbedder.getComponent(ArchetypeDataSource.class, roleHint); - ArchetypeCatalog catalog = source.getArchetypeCatalog(new Properties()); - - List result = new ArrayList(); - for (Archetype each : (Iterable)catalog.getArchetypes()) { - result.add(new ArchetypeInfo(each)); - } - - return result; - } - catch (ArchetypeDataSourceException e) { - MavenLog.LOG.warn(e); - } - return Collections.emptyList(); - } } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenProjectIndicesManager.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenProjectIndicesManager.java index 05c197ae05ea..5d9434c6fd0b 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenProjectIndicesManager.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenProjectIndicesManager.java @@ -23,11 +23,13 @@ import com.intellij.util.ui.update.MergingUpdateQueue; import com.intellij.util.ui.update.Update; import gnu.trove.THashSet; import org.apache.lucene.search.Query; +import org.jetbrains.idea.maven.facade.NativeMavenProjectHolder; +import org.jetbrains.idea.maven.model.MavenArtifactInfo; +import org.jetbrains.idea.maven.model.MavenId; +import org.jetbrains.idea.maven.model.MavenRemoteRepository; import org.jetbrains.idea.maven.project.*; -import org.jetbrains.idea.maven.project.MavenProject; import org.jetbrains.idea.maven.utils.MavenMergingUpdateQueue; import org.jetbrains.idea.maven.utils.SimpleProjectComponent; -import org.sonatype.nexus.index.ArtifactInfo; import java.io.File; import java.util.ArrayList; @@ -75,7 +77,7 @@ public class MavenProjectIndicesManager extends SimpleProjectComponent { @Override public void projectResolved(Pair projectWithChanges, - org.apache.maven.project.MavenProject nativeMavenProject, + NativeMavenProjectHolder nativeMavenProject, Object message) { scheduleUpdateIndicesList(); } @@ -191,8 +193,8 @@ public class MavenProjectIndicesManager extends SimpleProjectComponent { return checkLocalRepository(groupId, artifactId, version); } - public Set search(Query query, int maxResult) { - Set result = new THashSet(); + public Set search(Query query, int maxResult) { + Set result = new THashSet(); for (MavenIndex each : myProjectIndices) { int remained = maxResult - result.size(); diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenSearcher.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenSearcher.java index d1a0d030408a..7b9771eaa048 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenSearcher.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenSearcher.java @@ -16,18 +16,21 @@ package org.jetbrains.idea.maven.indices; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Pair; import org.apache.lucene.search.Query; -import org.sonatype.nexus.index.ArtifactInfo; +import org.jetbrains.idea.maven.model.MavenArtifactInfo; import java.util.*; public abstract class MavenSearcher { + public static final VersionComparator COMPARATOR = new VersionComparator(); + public List search(Project project, String pattern, int maxResult) { Pair patternAndQuery = preparePatternAndQuery(pattern); MavenProjectIndicesManager m = MavenProjectIndicesManager.getInstance(project); - Set infos = m.search(patternAndQuery.second, maxResult); + Set infos = m.search(patternAndQuery.second, maxResult); List result = new ArrayList(processResults(infos, patternAndQuery.first, maxResult)); sort(result); @@ -35,11 +38,12 @@ public abstract class MavenSearcher preparePatternAndQuery(String pattern); - protected abstract Collection processResults(Set infos, String pattern, int maxResult); + + protected abstract Collection processResults(Set infos, String pattern, int maxResult); private void sort(List result) { - for (RESULT_TYPE each : result) { - Collections.sort(each.versions, ArtifactInfo.VERSION_COMPARATOR); + for (RESULT_TYPE each : result) { + Collections.sort(each.versions, COMPARATOR); } Collections.sort(result, new Comparator() { @@ -53,7 +57,28 @@ public abstract class MavenSearcher { + public int compare(MavenArtifactInfo f1, MavenArtifactInfo f2) { + int result = f1.getGroupId().compareTo(f2.getGroupId()); + if (result != 0) return result; + + result = f1.getArtifactId().compareTo(f2.getArtifactId()); + if (result != 0) return result; + + result = f2.getVersion().compareTo(f1.getVersion()); + if (result != 0) return result; + + result = Comparing.compare(f1.getClassifier(), f2. getClassifier()); + if (result != 0) return result; + + result = Comparing.compare(f1.getPackaging(), f2.getPackaging()); + if (result != 0) return result; + + return Comparing.compare(f1.getRepositoryId(), f2.getGroupId()); + } } } \ No newline at end of file diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenNavigationUtil.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenNavigationUtil.java index 0977a7c4e440..e8bdb82fbace 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenNavigationUtil.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenNavigationUtil.java @@ -25,8 +25,8 @@ import com.intellij.psi.xml.XmlDocument; import com.intellij.psi.xml.XmlFile; import com.intellij.psi.xml.XmlTag; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.maven.project.MavenArtifact; -import org.jetbrains.idea.maven.project.MavenId; +import org.jetbrains.idea.maven.model.MavenArtifact; +import org.jetbrains.idea.maven.model.MavenId; import org.jetbrains.idea.maven.project.MavenProjectsManager; import org.jetbrains.idea.maven.utils.MavenArtifactUtil; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenProjectsNavigator.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenProjectsNavigator.java index 2f9497a9ac23..2fed5ca3415d 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenProjectsNavigator.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenProjectsNavigator.java @@ -37,6 +37,7 @@ import com.intellij.ui.treeStructure.SimpleTree; import com.intellij.util.containers.ContainerUtil; import org.jdom.Element; import org.jetbrains.annotations.TestOnly; +import org.jetbrains.idea.maven.facade.NativeMavenProjectHolder; import org.jetbrains.idea.maven.project.*; import org.jetbrains.idea.maven.tasks.MavenShortcutsManager; import org.jetbrains.idea.maven.tasks.MavenTasksManager; @@ -348,7 +349,7 @@ public class MavenProjectsNavigator extends SimpleProjectComponent implements Pe } public void projectResolved(Pair projectWithChanges, - org.apache.maven.project.MavenProject nativeMavenProject, + NativeMavenProjectHolder nativeMavenProject, Object message) { scheduleUpdateProjects(Collections.singletonList(projectWithChanges.first), Collections.EMPTY_LIST); } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenProjectsNavigatorPanel.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenProjectsNavigatorPanel.java index a746dc289a89..95252e187fab 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenProjectsNavigatorPanel.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenProjectsNavigatorPanel.java @@ -29,9 +29,9 @@ import gnu.trove.THashMap; import gnu.trove.THashSet; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.maven.embedder.MavenEmbedderWrapper; import org.jetbrains.idea.maven.execution.MavenGoalLocation; -import org.jetbrains.idea.maven.project.MavenArtifact; +import org.jetbrains.idea.maven.model.MavenArtifact; +import org.jetbrains.idea.maven.model.MavenConstants; import org.jetbrains.idea.maven.project.MavenProject; import org.jetbrains.idea.maven.utils.MavenDataKeys; @@ -210,7 +210,8 @@ public class MavenProjectsNavigatorPanel extends SimpleToolWindowPanel implement for (MavenProjectsStructure.BaseDependenciesNode each : nodes) { if (each instanceof MavenProjectsStructure.DependenciesNode) { result.addAll(each.getMavenProject().getDependencies()); - } else { + } + else { result.add(((MavenProjectsStructure.DependencyNode)each).getArtifact()); } } @@ -242,7 +243,7 @@ public class MavenProjectsNavigatorPanel extends SimpleToolWindowPanel implement if (standardGoalOrder == null) { standardGoalOrder = new THashMap(); int i = 0; - for (String aGoal : MavenEmbedderWrapper.PHASES) { + for (String aGoal : MavenConstants.PHASES) { standardGoalOrder.put(aGoal, i++); } } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenProjectsStructure.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenProjectsStructure.java index fc0b30bd0703..366428862934 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenProjectsStructure.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenProjectsStructure.java @@ -30,7 +30,9 @@ import gnu.trove.THashMap; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; -import org.jetbrains.idea.maven.embedder.MavenEmbedderWrapper; +import org.jetbrains.idea.maven.facade.MavenEmbedderWrapper; +import org.jetbrains.idea.maven.importing.MavenRootModelAdapter; +import org.jetbrains.idea.maven.model.*; import org.jetbrains.idea.maven.project.*; import org.jetbrains.idea.maven.tasks.MavenShortcutsManager; import org.jetbrains.idea.maven.tasks.MavenTasksManager; @@ -48,8 +50,8 @@ import static org.jetbrains.idea.maven.project.ProjectBundle.message; public class MavenProjectsStructure extends SimpleTreeStructure { private static final URL ERROR_ICON_URL = MavenProjectsStructure.class.getResource("/images/error.png"); - private static final Collection BASIC_PHASES = MavenEmbedderWrapper.BASIC_PHASES; - private static final Collection PHASES = MavenEmbedderWrapper.PHASES; + private static final Collection BASIC_PHASES = MavenConstants.BASIC_PHASES; + private static final Collection PHASES = MavenConstants.PHASES; private static final Comparator NODE_COMPARATOR = new Comparator() { public int compare(MavenSimpleNode o1, MavenSimpleNode o2) { @@ -106,7 +108,7 @@ public class MavenProjectsStructure extends SimpleTreeStructure { } public MavenUIUtil.CheckBoxState getState(Object userObject) { - MavenProfileState state = ((ProfileNode)userObject).getState(); + MavenProfileKind state = ((ProfileNode)userObject).getState(); switch (state) { case NONE: return MavenUIUtil.CheckBoxState.UNCHECKED; case EXPLICIT: return MavenUIUtil.CheckBoxState.CHECKED; @@ -563,10 +565,10 @@ public class MavenProjectsStructure extends SimpleTreeStructure { } public void updateProfiles() { - Collection> profiles = myProjectsManager.getProfilesWithStates(); + Collection> profiles = myProjectsManager.getProfilesWithStates(); List newNodes = new ArrayList(profiles.size()); - for (Pair each : profiles) { + for (Pair each : profiles) { ProfileNode node = findOrCreateNodeFor(each.first); node.setState(each.second); newNodes.add(node); @@ -587,7 +589,7 @@ public class MavenProjectsStructure extends SimpleTreeStructure { public class ProfileNode extends MavenSimpleNode { private final String myProfileName; - private MavenProfileState myState; + private MavenProfileKind myState; public ProfileNode(ProfilesNode parent, String profileName) { super(parent); @@ -603,11 +605,11 @@ public class MavenProjectsStructure extends SimpleTreeStructure { return myProfileName; } - public MavenProfileState getState() { + public MavenProfileKind getState() { return myState; } - private void setState(MavenProfileState state) { + private void setState(MavenProfileKind state) { myState = state; } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenArtifactDownloader.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenArtifactDownloader.java index 05d8ba911168..cf5399ad8dec 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenArtifactDownloader.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenArtifactDownloader.java @@ -20,10 +20,10 @@ import com.intellij.openapi.util.Pair; import com.intellij.openapi.vfs.LocalFileSystem; import gnu.trove.THashMap; import gnu.trove.THashSet; -import org.apache.maven.artifact.Artifact; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.maven.embedder.MavenEmbedderWrapper; +import org.jetbrains.idea.maven.facade.MavenEmbedderWrapper; import org.jetbrains.idea.maven.importing.MavenExtraArtifactType; +import org.jetbrains.idea.maven.model.*; import org.jetbrains.idea.maven.utils.MavenLog; import org.jetbrains.idea.maven.utils.MavenProcessCanceledException; import org.jetbrains.idea.maven.utils.MavenProgressIndicator; @@ -115,7 +115,7 @@ public class MavenArtifactDownloader { for (MavenArtifact eachDependency : eachProject.getDependencies()) { if (myArtifacts != null && !myArtifacts.contains(eachDependency)) continue; - if (Artifact.SCOPE_SYSTEM.equalsIgnoreCase(eachDependency.getScope())) continue; + if (MavenConstants.SCOPE_SYSTEM.equalsIgnoreCase(eachDependency.getScope())) continue; if (myProjectsTree.findProject(eachDependency.getMavenId()) != null) continue; if (!eachProject.isSupportedDependency(eachDependency)) continue; @@ -164,8 +164,8 @@ public class MavenArtifactDownloader { myProgress.checkCanceled(); myProgress.setFraction(((double)downloaded.getAndIncrement()) / finalTotal); - MavenArtifact a = myEmbedder.resolve(id, eachElement.extension, eachElement.classifier, - new ArrayList(data.repositories)); + MavenArtifact a = myEmbedder.resolve(new MavenArtifactInfo(id, eachElement.extension, eachElement.classifier), + new ArrayList(data.repositories)); File file = a.getFile(); if (file.exists()) { synchronized (downloadedFiles) { diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/MavenConsole.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenConsole.java similarity index 62% rename from plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/MavenConsole.java rename to plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenConsole.java index 3aee5c9e4126..46fe999eff04 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/MavenConsole.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenConsole.java @@ -13,45 +13,37 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.maven.embedder; +package org.jetbrains.idea.maven.project; import com.intellij.execution.process.ProcessHandler; import com.intellij.openapi.util.text.StringUtil; import gnu.trove.THashMap; -import org.apache.maven.plugin.AbstractMojoExecutionException; +import org.jetbrains.idea.maven.execution.MavenExecutionOptions; +import org.jetbrains.idea.maven.execution.RunnerBundle; +import org.jetbrains.idea.maven.facade.MavenFacadeConsole; import java.text.MessageFormat; import java.util.Map; public abstract class MavenConsole { - public static final int LEVEL_AUTO = -1; - public static final int LEVEL_DEBUG = 0; - public static final int LEVEL_INFO = 1; - public static final int LEVEL_WARN = 2; - public static final int LEVEL_ERROR = 3; - public static final int LEVEL_FATAL = 4; - public static final int LEVEL_DISABLED = 5; - public static final int LEVEL_ALWAYS = 6; - - public static final String LINE_SEPARATOR = System.getProperty("line.separator"); + private static final String LINE_SEPARATOR = System.getProperty("line.separator"); public enum OutputType { NORMAL, SYSTEM, ERROR } private final int myOutputLevel; - private final boolean myPrintStrackTrace; private boolean isFinished; private static final Map PREFIX_TO_LEVEL = new THashMap(); private static final Map LEVEL_TO_PREFIX = new THashMap(); static { - map("DEBUG", LEVEL_DEBUG); - map("INFO", LEVEL_INFO); - map("WARNING", LEVEL_WARN); - map("ERROR", LEVEL_ERROR); - map("FATAL_ERROR", LEVEL_FATAL); + map("DEBUG", MavenFacadeConsole.LEVEL_DEBUG); + map("INFO", MavenFacadeConsole.LEVEL_INFO); + map("WARNING", MavenFacadeConsole.LEVEL_WARN); + map("ERROR", MavenFacadeConsole.LEVEL_ERROR); + map("FATAL_ERROR", MavenFacadeConsole.LEVEL_FATAL); } private static void map(String prefix, int level) { @@ -61,7 +53,6 @@ public abstract class MavenConsole { public MavenConsole(MavenExecutionOptions.LoggingLevel outputLevel, boolean printStrackTrace) { myOutputLevel = outputLevel.getLevel(); - myPrintStrackTrace = printStrackTrace; } public boolean isSuppressed(int level) { @@ -88,6 +79,10 @@ public abstract class MavenConsole { public abstract void attachToProcess(ProcessHandler processHandler); + public void printException(Throwable throwable) { + systemMessage(MavenFacadeConsole.LEVEL_ERROR, RunnerBundle.message("embedded.build.failed"), throwable); + } + public void systemMessage(int level, String string, Throwable throwable) { printMessage(level, string, throwable); } @@ -96,51 +91,62 @@ public abstract class MavenConsole { if (isSuppressed(level)) return; OutputType type = OutputType.NORMAL; - if (throwable != null || level == LEVEL_WARN || level == LEVEL_ERROR || level == LEVEL_FATAL) { + if (throwable != null + || level == MavenFacadeConsole.LEVEL_WARN + || level == MavenFacadeConsole.LEVEL_ERROR + || level == MavenFacadeConsole.LEVEL_FATAL) { type = OutputType.ERROR; } doPrint(composeLine(level, string), type); - if (level == LEVEL_FATAL) { + if (level == MavenFacadeConsole.LEVEL_FATAL) { setOutputPaused(false); } if (throwable != null) { - String message = null; - - Throwable temp = throwable; - while (temp != null) { - if (temp instanceof AbstractMojoExecutionException) { - message = appendExecutionFailureMessage(message, temp.getMessage()); - message = appendExecutionFailureMessage(message, ((AbstractMojoExecutionException)temp).getLongMessage()); - - if (temp.getCause() != null) { - message = appendExecutionFailureMessage(message, temp.getCause().getMessage()); - } - break; - } - temp = temp.getCause(); - } - - if (message == null) message = throwable.getMessage(); - + String message = throwable.getMessage(); if (message != null) { message += LINE_SEPARATOR; - doPrint(LINE_SEPARATOR + composeLine(LEVEL_ERROR, message), type); - } - - if (myPrintStrackTrace) { - doPrint(LINE_SEPARATOR + StringUtil.getThrowableText(throwable), OutputType.ERROR); - } - else { - doPrint(LINE_SEPARATOR + - "To view full stack traces, please go to the Settings->Maven and check the 'Print Exception Stack Traces' box." + - LINE_SEPARATOR, - type); + doPrint(LINE_SEPARATOR + composeLine(MavenFacadeConsole.LEVEL_ERROR, message), type); } } } + // todo + // if (throwable != null) { + // String message = null; + // + // Throwable temp = throwable; + // while (temp != null) { + // if (temp instanceof AbstractMojoExecutionException) { + // message = appendExecutionFailureMessage(message, temp.getMessage()); + // message = appendExecutionFailureMessage(message, ((AbstractMojoExecutionException)temp).getLongMessage()); + // + // if (temp.getCause() != null) { + // message = appendExecutionFailureMessage(message, temp.getCause().getMessage()); + // } + // break; + // } + // temp = temp.getCause(); + // } + // + // if (message == null) message = throwable.getMessage(); + // + // if (message != null) { + // message += LINE_SEPARATOR; + // doPrint(LINE_SEPARATOR + composeLine(LEVEL_ERROR, message), type); + // } + // + // if (myPrintStrackTrace) { + // doPrint(LINE_SEPARATOR + StringUtil.getThrowableText(throwable), OutputType.ERROR); + // } + // else { + // doPrint(LINE_SEPARATOR + + // "To view full stack traces, please go to the Settings->Maven and check the 'Print Exception Stack Traces' box." + + // LINE_SEPARATOR, + // type); + // } + //} private String appendExecutionFailureMessage(String message, String newMessage) { if (message == null) return newMessage; @@ -166,7 +172,7 @@ public abstract class MavenConsole { private static int getLevelByPrefix(String prefix) { Integer level = PREFIX_TO_LEVEL.get(prefix); - return level != null ? level : LEVEL_ALWAYS; + return level != null ? level : MavenFacadeConsole.LEVEL_WARN; } private static String composeLine(int level, String message) { diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/MavenConsoleImpl.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenConsoleImpl.java similarity index 97% rename from plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/MavenConsoleImpl.java rename to plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenConsoleImpl.java index f14e66faf49d..7d04d8dba13b 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/embedder/MavenConsoleImpl.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenConsoleImpl.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.maven.embedder; +package org.jetbrains.idea.maven.project; import com.intellij.execution.filters.*; import com.intellij.execution.process.ProcessAdapter; @@ -30,8 +30,6 @@ import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.ui.content.Content; import com.intellij.ui.content.ContentFactory; import com.intellij.ui.content.MessageView; -import org.jetbrains.idea.maven.project.MavenGeneralSettings; -import org.jetbrains.idea.maven.project.MavenProjectsManager; import org.jetbrains.idea.maven.execution.MavenRunnerParameters; import org.jetbrains.idea.maven.execution.MavenRunnerSettings; import org.jetbrains.idea.maven.utils.MavenUtil; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenEmbeddersManager.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenEmbeddersManager.java index a187b202b565..cf00a48dacad 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenEmbeddersManager.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenEmbeddersManager.java @@ -15,32 +15,36 @@ */ package org.jetbrains.idea.maven.project; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.Key; import com.intellij.util.Function; import com.intellij.util.containers.SoftValueHashMap; import gnu.trove.THashSet; -import org.jetbrains.idea.maven.embedder.MavenEmbedderWrapper; +import org.jetbrains.idea.maven.facade.MavenEmbedderWrapper; +import org.jetbrains.idea.maven.facade.MavenFacadeManager; import org.jetbrains.idea.maven.utils.MavenLog; import java.util.Map; import java.util.Set; public class MavenEmbeddersManager { - public enum EmbedderKind { - FOR_DEPENDENCIES_RESOLVE, - FOR_PLUGINS_RESOLVE, - FOR_FOLDERS_RESOLVE, - FOR_DOWNLOAD, - FOR_POST_PROCESSING, - } + public static final Key FOR_DEPENDENCIES_RESOLVE = Key.create(MavenEmbeddersManager.class + ".FOR_DEPENDENCIES_RESOLVE"); + public static final Key FOR_PLUGINS_RESOLVE = Key.create(MavenEmbeddersManager.class + ".FOR_PLUGINS_RESOLVE"); + public static final Key FOR_FOLDERS_RESOLVE = Key.create(MavenEmbeddersManager.class + ".FOR_FOLDERS_RESOLVE"); + public static final Key FOR_DOWNLOAD = Key.create(MavenEmbeddersManager.class + ".FOR_DOWNLOAD"); + public static final Key FOR_POST_PROCESSING = Key.create(MavenEmbeddersManager.class + ".FOR_POST_PROCESSING"); - private final MavenGeneralSettings myGeneralSettings; + private final Project myProject; - private final Map myPool = new SoftValueHashMap(); + private final Map myPool = new SoftValueHashMap(); private final Set myEmbeddersInUse = new THashSet(); private final Set myEmbeddersToClear = new THashSet(); - public MavenEmbeddersManager(MavenGeneralSettings generalSettings) { - myGeneralSettings = generalSettings; + public MavenEmbeddersManager(Project project) { + myProject = project; } public synchronized void reset() { @@ -57,16 +61,16 @@ public class MavenEmbeddersManager { myEmbeddersToClear.addAll(myEmbeddersInUse); } - public synchronized MavenEmbedderWrapper getEmbedder(EmbedderKind kind) { + public synchronized MavenEmbedderWrapper getEmbedder(Key kind) { MavenEmbedderWrapper result = myPool.get(kind); if (result == null) { - result = MavenEmbedderWrapper.create(myGeneralSettings); + result = MavenFacadeManager.getInstance().createEmbedder(myProject); myPool.put(kind, result); } if (myEmbeddersInUse.contains(result)) { MavenLog.LOG.warn("embedder " + kind + " is already used"); - return MavenEmbedderWrapper.create(myGeneralSettings); + return MavenFacadeManager.getInstance().createEmbedder(myProject); } myEmbeddersInUse.add(result); @@ -80,7 +84,9 @@ public class MavenEmbeddersManager { return; } + embedder.reset(); myEmbeddersInUse.remove(embedder); + if (myEmbeddersToClear.contains(embedder)) { embedder.clearCaches(); myEmbeddersToClear.remove(embedder); @@ -111,7 +117,7 @@ public class MavenEmbeddersManager { } private void forEachPooled(boolean includeInUse, Function func) { - for (EmbedderKind each : myPool.keySet()) { + for (Key each : myPool.keySet()) { MavenEmbedderWrapper embedder = myPool.get(each); if (embedder == null) continue; // collected if (!includeInUse && myEmbeddersInUse.contains(embedder)) continue; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenEnvironmentForm.form b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenEnvironmentForm.form index fd0eca592c95..f972ad1dd8c4 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenEnvironmentForm.form +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenEnvironmentForm.form @@ -1,9 +1,9 @@ - + - + @@ -42,26 +42,9 @@ - - - - - - - - - - - - - - - - - - + diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenEnvironmentForm.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenEnvironmentForm.java index 90e727fc62dc..7faa4c0da883 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenEnvironmentForm.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenEnvironmentForm.java @@ -17,12 +17,12 @@ package org.jetbrains.idea.maven.project; +import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.ui.LabeledComponent; import com.intellij.openapi.ui.TextFieldWithBrowseButton; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.fileChooser.FileChooserDescriptor; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.maven.embedder.MavenEmbedderUtilEx; +import org.jetbrains.idea.maven.utils.MavenUtil; import javax.swing.*; import java.awt.event.ActionEvent; @@ -36,17 +36,15 @@ public class MavenEnvironmentForm { private LabeledComponent mavenSettingsFileComponent; private JCheckBox mavenHomeOverrideCheckBox; private JCheckBox mavenSettingsFileOverrideCheckBox; - private JCheckBox localRepositoryOverrideCheckBox; private final PathOverrider mavenHomeOverrider; private final PathOverrider mavenSettingsFileOverrider; - private final PathOverrider localRepositoryOverrider; public MavenEnvironmentForm() { mavenHomeOverrider = new PathOverrider(mavenHomeComponent, mavenHomeOverrideCheckBox, new PathOverrider.PathProvider() { @Nullable protected File getFile() { - return MavenEmbedderUtilEx.resolveMavenHomeDirectory(""); + return MavenUtil.resolveMavenHomeDirectory(""); } }); @@ -54,17 +52,7 @@ public class MavenEnvironmentForm { new PathOverrider(mavenSettingsFileComponent, mavenSettingsFileOverrideCheckBox, new PathOverrider.PathProvider() { @Nullable protected File getFile() { - return MavenEmbedderUtilEx.resolveUserSettingsFile(""); - } - }); - - localRepositoryOverrider = - new PathOverrider(localRepositoryComponent, localRepositoryOverrideCheckBox, new PathOverrider.PathProvider() { - @Nullable - protected File getFile() { - return MavenEmbedderUtilEx.resolveLocalRepository(mavenHomeOverrider.getText(), - mavenSettingsFileOverrider.getText(), - ""); + return MavenUtil.resolveUserSettingsFile(""); } }); } @@ -78,13 +66,11 @@ public class MavenEnvironmentForm { public void setData(MavenGeneralSettings data) { data.setMavenHome(mavenHomeOverrider.getText()); data.setMavenSettingsFile(mavenSettingsFileOverrider.getText()); - data.setLocalRepository(localRepositoryOverrider.getText()); } public void getData(MavenGeneralSettings data) { mavenHomeOverrider.setText(data.getMavenHome()); mavenSettingsFileOverrider.setText(data.getMavenSettingsFile()); - localRepositoryOverrider.setText(data.getLocalRepository()); } public JComponent createComponent() { diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenGeneralConfigurable.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenGeneralConfigurable.java index f20b862ef215..a2857989698e 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenGeneralConfigurable.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenGeneralConfigurable.java @@ -23,7 +23,7 @@ import com.intellij.util.Function; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.maven.embedder.MavenExecutionOptions; +import org.jetbrains.idea.maven.execution.MavenExecutionOptions; import org.jetbrains.idea.maven.utils.ComboBoxUtil; import javax.swing.*; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenGeneralSettings.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenGeneralSettings.java index d3ab6ad2d966..8294bbeec711 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenGeneralSettings.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenGeneralSettings.java @@ -23,9 +23,9 @@ import gnu.trove.THashSet; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.maven.embedder.MavenEmbedderUtilEx; -import org.jetbrains.idea.maven.embedder.MavenExecutionOptions; +import org.jetbrains.idea.maven.execution.MavenExecutionOptions; import org.jetbrains.idea.maven.utils.MavenJDOMUtil; +import org.jetbrains.idea.maven.utils.MavenUtil; import java.io.File; import java.util.ArrayList; @@ -37,7 +37,7 @@ public class MavenGeneralSettings implements Cloneable { private boolean workOffline = false; private String mavenHome = ""; private String mavenSettingsFile = ""; - private String localRepository = ""; + private String overridenLocalRepository = ""; private boolean printErrorStackTraces = false; private boolean usePluginRegistry = false; private boolean nonRecursive = false; @@ -52,7 +52,9 @@ public class MavenGeneralSettings implements Cloneable { private List myListeners = ContainerUtil.createEmptyCOWList(); - public @NotNull MavenExecutionOptions.PluginUpdatePolicy getPluginUpdatePolicy() { + public + @NotNull + MavenExecutionOptions.PluginUpdatePolicy getPluginUpdatePolicy() { return pluginUpdatePolicy; } @@ -81,7 +83,9 @@ public class MavenGeneralSettings implements Cloneable { this.failureBehavior = value; } - public @NotNull MavenExecutionOptions.LoggingLevel getLoggingLevel() { + public + @NotNull + MavenExecutionOptions.LoggingLevel getLoggingLevel() { return outputLevel; } @@ -90,7 +94,9 @@ public class MavenGeneralSettings implements Cloneable { this.outputLevel = value; } - public @NotNull MavenExecutionOptions.SnapshotUpdatePolicy getSnapshotUpdatePolicy() { + public + @NotNull + MavenExecutionOptions.SnapshotUpdatePolicy getSnapshotUpdatePolicy() { return snapshotUpdatePolicy; } @@ -108,23 +114,23 @@ public class MavenGeneralSettings implements Cloneable { } @NotNull - public String getLocalRepository() { - return localRepository; + public String getOverridenLocalRepository() { + return overridenLocalRepository; } public File getEffectiveLocalRepository() { File result = myEffectiveLocalRepositoryCache; if (result != null) return result; - result = MavenEmbedderUtilEx.resolveLocalRepository(mavenHome, mavenSettingsFile, localRepository); + result = MavenUtil.resolveLocalRepository(overridenLocalRepository, mavenHome, mavenSettingsFile); myEffectiveLocalRepositoryCache = result; return result; } - public void setLocalRepository(final @Nullable String localRepository) { - if (localRepository != null) { - if (!Comparing.equal(this.localRepository, localRepository)) { - this.localRepository = localRepository; + public void setOverridenLocalRepository(final @Nullable String overridenLocalRepository) { + if (overridenLocalRepository != null) { + if (!Comparing.equal(this.overridenLocalRepository, overridenLocalRepository)) { + this.overridenLocalRepository = overridenLocalRepository; localRepositoryChanged(); } @@ -147,7 +153,7 @@ public class MavenGeneralSettings implements Cloneable { @Nullable public File getEffectiveMavenHome() { - return MavenEmbedderUtilEx.resolveMavenHomeDirectory(getMavenHome()); + return MavenUtil.resolveMavenHomeDirectory(getMavenHome()); } @NotNull @@ -175,12 +181,12 @@ public class MavenGeneralSettings implements Cloneable { @Nullable public File getEffectiveUserSettingsIoFile() { - return MavenEmbedderUtilEx.resolveUserSettingsFile(getMavenSettingsFile()); + return MavenUtil.resolveUserSettingsFile(getMavenSettingsFile()); } @Nullable public File getEffectiveGlobalSettingsIoFile() { - return MavenEmbedderUtilEx.resolveGlobalSettingsFile(getMavenHome()); + return MavenUtil.resolveGlobalSettingsFile(getMavenHome()); } @Nullable @@ -206,7 +212,7 @@ public class MavenGeneralSettings implements Cloneable { @NotNull public VirtualFile getEffectiveSuperPom() { - return MavenEmbedderUtilEx.resolveSuperPomFile(getMavenHome()); + return MavenUtil.resolveSuperPomFile(getEffectiveMavenHome()); } public boolean isDefaultPlugin(String groupId, String artifactId) { @@ -269,7 +275,7 @@ public class MavenGeneralSettings implements Cloneable { if (workOffline != that.workOffline) return false; if (!checksumPolicy.equals(that.checksumPolicy)) return false; if (!failureBehavior.equals(that.failureBehavior)) return false; - if (!localRepository.equals(that.localRepository)) return false; + if (!overridenLocalRepository.equals(that.overridenLocalRepository)) return false; if (!mavenHome.equals(that.mavenHome)) return false; if (!mavenSettingsFile.equals(that.mavenSettingsFile)) return false; @@ -281,7 +287,7 @@ public class MavenGeneralSettings implements Cloneable { result = (workOffline ? 1 : 0); result = 31 * result + mavenHome.hashCode(); result = 31 * result + mavenSettingsFile.hashCode(); - result = 31 * result + localRepository.hashCode(); + result = 31 * result + overridenLocalRepository.hashCode(); result = 31 * result + (printErrorStackTraces ? 1 : 0); result = 31 * result + (usePluginRegistry ? 1 : 0); result = 31 * result + (nonRecursive ? 1 : 0); diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenParentDesc.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenParentDesc.java index 8080ce11ff7f..4a497b4fd8ca 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenParentDesc.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenParentDesc.java @@ -16,6 +16,7 @@ package org.jetbrains.idea.maven.project; import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.maven.model.MavenId; public class MavenParentDesc { private final MavenId myParentId; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenParentProjectFileProcessor.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenParentProjectFileProcessor.java index 543b71d587d9..6c243cbaa20d 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenParentProjectFileProcessor.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenParentProjectFileProcessor.java @@ -19,8 +19,9 @@ import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.maven.model.MavenConstants; +import org.jetbrains.idea.maven.model.MavenId; import org.jetbrains.idea.maven.utils.MavenArtifactUtil; -import org.jetbrains.idea.maven.utils.MavenConstants; import java.io.File; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java index b16a233d3891..e418cf3d073c 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java @@ -26,17 +26,14 @@ import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashMap; import gnu.trove.THashSet; -import gnu.trove.TObjectIdentityHashingStrategy; -import org.apache.maven.artifact.Artifact; -import org.apache.maven.model.*; -import org.apache.maven.shared.dependency.tree.DependencyNode; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.maven.embedder.MavenConsole; -import org.jetbrains.idea.maven.embedder.MavenEmbedderWrapper; +import org.jetbrains.idea.maven.facade.MavenEmbedderWrapper; +import org.jetbrains.idea.maven.facade.NativeMavenProjectHolder; import org.jetbrains.idea.maven.importing.MavenExtraArtifactType; import org.jetbrains.idea.maven.importing.MavenImporter; +import org.jetbrains.idea.maven.model.*; import org.jetbrains.idea.maven.utils.*; import java.io.*; @@ -100,51 +97,44 @@ public class MavenProject { } private MavenProjectChanges set(MavenProjectReaderResult readerResult, + MavenGeneralSettings settings, boolean updateLastReadStamp, boolean resetArtifacts, boolean resetProfiles) { State newState = myState.clone(); - if (updateLastReadStamp) newState.myLastReadStamp++; - - org.apache.maven.project.MavenProject nativeMavenProject = readerResult.nativeMavenProject; + if (updateLastReadStamp) newState.myLastReadStamp = myState.myLastReadStamp + 1; newState.myReadingProblems = readerResult.readingProblems; - newState.myLocalRepository = readerResult.localRepository; + newState.myLocalRepository = settings.getEffectiveLocalRepository(); - Collection activeProfiles = collectActivateProfiles(nativeMavenProject); + Collection activeProfiles = readerResult.activatedProfiles; newState.myActiveProfilesIds = collectProfilesIds(activeProfiles); - Model model = nativeMavenProject.getModel(); + MavenModel model = readerResult.mavenModel; - newState.myMavenId = new MavenId(model.getGroupId(), - model.getArtifactId(), - model.getVersion()); - - Parent parent = model.getParent(); - newState.myParentId = parent != null - ? new MavenId(parent.getGroupId(), parent.getArtifactId(), parent.getVersion()) - : null; + newState.myMavenId = model.getMavenId(); + if (model.getParent() != null) { + newState.myParentId = model.getParent().getMavenId(); + } newState.myPackaging = model.getPackaging(); newState.myName = model.getName(); - Build build = model.getBuild(); + newState.myFinalName = model.getBuild().getFinalName(); + newState.myDefaultGoal = model.getBuild().getDefaultGoal(); - newState.myFinalName = build.getFinalName(); - newState.myDefaultGoal = build.getDefaultGoal(); - - newState.myBuildDirectory = build.getDirectory(); - newState.myOutputDirectory = build.getOutputDirectory(); - newState.myTestOutputDirectory = build.getTestOutputDirectory(); + newState.myBuildDirectory = model.getBuild().getDirectory(); + newState.myOutputDirectory = model.getBuild().getOutputDirectory(); + newState.myTestOutputDirectory = model.getBuild().getTestOutputDirectory(); doSetFolders(newState, readerResult); - newState.myFilters = build.getFilters() == null ? Collections.EMPTY_LIST : build.getFilters(); - newState.myProperties = model.getProperties() != null ? model.getProperties() : new Properties(); + newState.myFilters = model.getBuild().getFilters(); + newState.myProperties = model.getProperties(); - doSetResolvedAttributes(newState, readerResult, resetArtifacts); + doSetResolvedAttributes(newState, readerResult, settings, resetArtifacts); newState.myModulesPathsAndNames = collectModulePathsAndNames(model, getDirectory(), activeProfiles); Collection newProfiles = collectProfilesIds(model.getProfiles()); @@ -157,8 +147,7 @@ public class MavenProject { newState.myProfilesIds = new ArrayList(mergedProfiles); } - newState.myStrippedMavenModel = MavenUtil.cloneObject(model); - MavenUtil.stripDown(newState.myStrippedMavenModel); + newState.myModelMap = readerResult.nativeModelMap; return setState(newState); } @@ -169,9 +158,11 @@ public class MavenProject { return changes; } - private static void doSetResolvedAttributes(State state, MavenProjectReaderResult readerResult, boolean reset) { - org.apache.maven.project.MavenProject nativeMavenProject = readerResult.nativeMavenProject; - Model model = nativeMavenProject.getModel(); + private static void doSetResolvedAttributes(State state, + MavenProjectReaderResult readerResult, + MavenGeneralSettings settings, + boolean reset) { + MavenModel model = readerResult.mavenModel; Set newUnresolvedArtifacts = new THashSet(); LinkedHashSet newRepositories = new LinkedHashSet(); @@ -190,15 +181,11 @@ public class MavenProject { } newUnresolvedArtifacts.addAll(readerResult.unresolvedArtifactIds); - newRepositories.addAll(convertRepositories(model.getRepositories())); - - Map nativeToConvertedMap = - new THashMap(new TObjectIdentityHashingStrategy()); - newDependencyTree.addAll(convertDependencyNodes(null, readerResult.dependencyTree, nativeToConvertedMap, state.myLocalRepository)); - newDependencies.addAll(convertArtifacts(nativeMavenProject.getArtifacts(), nativeToConvertedMap, state.myLocalRepository)); - - newPlugins.addAll(collectPlugins(readerResult.settings, model)); - newExtensions.addAll(convertArtifacts(nativeMavenProject.getExtensionArtifacts(), nativeToConvertedMap, state.myLocalRepository)); + newRepositories.addAll(model.getRemoteRepositories()); + newDependencyTree.addAll(model.getDependencyTree()); + newDependencies.addAll(model.getDependencies()); + newPlugins.addAll(model.getPlugins()); + newExtensions.addAll(model.getExtensions()); state.myUnresolvedArtifactIds = newUnresolvedArtifacts; state.myRemoteRepositories = new ArrayList(newRepositories); @@ -206,6 +193,8 @@ public class MavenProject { state.myDependencyTree = new ArrayList(newDependencyTree); state.myPlugins = new ArrayList(newPlugins); state.myExtensions = new ArrayList(newExtensions); + + // todo remove non-default managed plugins } private MavenProjectChanges setFolders(MavenProjectReaderResult readerResult) { @@ -215,123 +204,17 @@ public class MavenProject { } private static void doSetFolders(State newState, MavenProjectReaderResult readerResult) { - org.apache.maven.project.MavenProject nativeMavenProject = readerResult.nativeMavenProject; + MavenModel model = readerResult.mavenModel; + newState.mySources = model.getBuild().getSources(); + newState.myTestSources = model.getBuild().getTestSources(); - newState.mySources = new ArrayList(nativeMavenProject.getCompileSourceRoots()); - newState.myTestSources = new ArrayList(nativeMavenProject.getTestCompileSourceRoots()); - - newState.myResources = convertResources(nativeMavenProject.getResources()); - newState.myTestResources = convertResources(nativeMavenProject.getTestResources()); + newState.myResources = model.getBuild().getResources(); + newState.myTestResources = model.getBuild().getTestResources(); } - private static List convertResources(List resources) { - if (resources == null) return new ArrayList(); - - List result = new ArrayList(resources.size()); - for (Resource each : resources) { - result.add(new MavenResource(each)); - } - return result; - } - - private static List convertRepositories(List repositories) { - if (repositories == null) return new ArrayList(); - - List result = new ArrayList(repositories.size()); - for (Repository each : repositories) { - result.add(new MavenRemoteRepository(each)); - } - return result; - } - - private static List convertArtifacts(Collection artifacts, - Map nativeToConvertedMap, - File localRepository) { - if (artifacts == null) return new ArrayList(); - - List result = new ArrayList(artifacts.size()); - for (Artifact each : artifacts) { - result.add(convertArtifact(each, nativeToConvertedMap, localRepository)); - } - return result; - } - - private static List convertDependencyNodes(MavenArtifactNode parent, - Collection nodes, - Map nativeToConvertedMap, - File localRepository) { - List result = new ArrayList(nodes.size()); - for (DependencyNode each : nodes) { - Artifact a = each.getArtifact(); - MavenArtifact ma = convertArtifact(a, nativeToConvertedMap, localRepository); - - MavenArtifactState state = MavenArtifactState.ADDED; - switch (each.getState()) { - case DependencyNode.INCLUDED: - break; - case DependencyNode.OMITTED_FOR_CONFLICT: - state = MavenArtifactState.CONFLICT; - break; - case DependencyNode.OMITTED_FOR_DUPLICATE: - state = MavenArtifactState.DUPLICATE; - break; - case DependencyNode.OMITTED_FOR_CYCLE: - state = MavenArtifactState.CYCLE; - break; - default: - MavenLog.LOG.error("unknown dependency node state: " + each.getState()); - } - MavenArtifact relatedMA = each.getRelatedArtifact() == null ? null - : convertArtifact(each.getRelatedArtifact(), nativeToConvertedMap, localRepository); - MavenArtifactNode newNode = new MavenArtifactNode(parent, ma, state, relatedMA, each.getOriginalScope(), - each.getPremanagedVersion(), each.getPremanagedScope()); - newNode.setDependencies(convertDependencyNodes(newNode, each.getChildren(), nativeToConvertedMap, localRepository)); - result.add(newNode); - } - return result; - } - - private static MavenArtifact convertArtifact(Artifact artifact, Map nativeToConvertedMap, File localRepository) { - MavenArtifact ma = nativeToConvertedMap.get(artifact); - if (ma == null) { - ma = new MavenArtifact(artifact, localRepository); - nativeToConvertedMap.put(artifact, ma); - } - return ma; - } - - private static List collectPlugins(MavenGeneralSettings settings, Model mavenModel) { - List result = new ArrayList(); - Set pluginKeys = new THashSet(); - Build build = mavenModel.getBuild(); - doCollectPlugins(settings, build, false, result, pluginKeys); - if (build != null) doCollectPlugins(settings, build.getPluginManagement(), true, result, pluginKeys); - return result; - } - - private static void doCollectPlugins(MavenGeneralSettings settings, - PluginContainer container, - boolean management, - List result, - Set pluginKeys) { - if (container == null) return; - - List plugins = container.getPlugins(); - if (plugins == null) return; - - for (Plugin each : plugins) { - String key = each.getGroupId() + ":" + each.getArtifactId(); - if (management && (!isDefaultPlugin(settings, each) || pluginKeys.contains(key))) continue; - result.add(new MavenPlugin(each, management)); - pluginKeys.add(key); - } - } - - private static boolean isDefaultPlugin(MavenGeneralSettings settings, Plugin plugin) { - return settings.isDefaultPlugin(plugin.getGroupId(), plugin.getArtifactId()); - } - - private static Map collectModulePathsAndNames(Model mavenModel, String baseDir, Collection activeProfiles) { + private static Map collectModulePathsAndNames(MavenModel mavenModel, + String baseDir, + Collection activeProfiles) { String basePath = baseDir + "/"; Map result = new LinkedHashMap(); for (Map.Entry each : collectModulesRelativePathsAndNames(mavenModel, activeProfiles).entrySet()) { @@ -340,17 +223,17 @@ public class MavenProject { return result; } - private static Map collectModulesRelativePathsAndNames(Model mavenModel, Collection activeProfiles) { + private static Map collectModulesRelativePathsAndNames(MavenModel mavenModel, Collection activeProfiles) { LinkedHashMap result = new LinkedHashMap(); addModulesToList(mavenModel.getModules(), result); - for (Profile profile : activeProfiles) { + for (MavenProfile profile : activeProfiles) { addModulesToList(profile.getModules(), result); } return result; } - private static void addModulesToList(List moduleNames, LinkedHashMap result) { - for (String name : (List)moduleNames) { + private static void addModulesToList(List moduleNames, LinkedHashMap result) { + for (String name : moduleNames) { if (name.trim().length() == 0) continue; String originalName = name; @@ -364,18 +247,12 @@ public class MavenProject { } } - private static Collection collectActivateProfiles(org.apache.maven.project.MavenProject nativeMavenProject) { - Collection activatedProfiles = nativeMavenProject.getActiveProfiles(); - return activatedProfiles == null ? Collections.emptySet() : activatedProfiles; - } - - private static Collection collectProfilesIds(Collection profiles) { + private static Collection collectProfilesIds(Collection profiles) { if (profiles == null) return Collections.emptyList(); Set result = new THashSet(profiles.size()); - for (Profile each : profiles) { - String id = each.getId(); - if (id != null) result.add(id); + for (MavenProfile each : profiles) { + result.add(each.getId()); } return result; } @@ -427,8 +304,8 @@ public class MavenProject { return state.myName; } - public Model getMavenModel() { - return myState.myStrippedMavenModel; + public Map getModelMap() { + return myState.myModelMap; } public MavenId getMavenId() { @@ -491,34 +368,34 @@ public class MavenProject { Collection profiles, MavenProjectReader reader, MavenProjectReaderProjectLocator locator) { - return set(reader.readProject(generalSettings, myFile, profiles, locator), true, false, true); + return set(reader.readProject(generalSettings, myFile, profiles, locator), generalSettings, true, false, true); } - public Pair resolve(MavenGeneralSettings generalSettings, - MavenEmbedderWrapper embedder, - MavenProjectReader reader, - MavenProjectReaderProjectLocator locator) + public Pair resolve(MavenGeneralSettings generalSettings, + MavenEmbedderWrapper embedder, + MavenProjectReader reader, + MavenProjectReaderProjectLocator locator) throws MavenProcessCanceledException { MavenProjectReaderResult result = reader.resolveProject(generalSettings, embedder, getFile(), getActiveProfilesIds(), locator); - MavenProjectChanges changes = set(result, false, result.readingProblems.isEmpty(), false); + MavenProjectChanges changes = set(result, generalSettings, false, result.readingProblems.isEmpty(), false); - for (MavenImporter eachImporter : getSuitableImporters()) { - eachImporter.resolve(this, result.nativeMavenProject, embedder); + if (result.nativeMavenProject != null) { + for (MavenImporter eachImporter : getSuitableImporters()) { + eachImporter.resolve(this, result.nativeMavenProject, embedder); + } } return Pair.create(changes, result.nativeMavenProject); } public Pair resolveFolders(MavenEmbedderWrapper embedder, - MavenGeneralSettings generalSettings, MavenImportingSettings importingSettings, MavenProjectReader reader, MavenConsole console) throws MavenProcessCanceledException { MavenProjectReaderResult result = reader.generateSources(embedder, - generalSettings, importingSettings, getFile(), getActiveProfilesIds(), @@ -597,7 +474,7 @@ public class MavenProject { } private static MavenProjectProblem createDependencyProblem(VirtualFile file, String description) { - return new MavenProjectProblem(file, description, MavenProjectProblem.ProblemType.DEPENDENCY); + return new MavenProjectProblem(file.getPath(), description, MavenProjectProblem.ProblemType.DEPENDENCY); } private static boolean isParentResolved(State state) { @@ -892,12 +769,13 @@ public class MavenProject { List myDependencies; List myDependencyTree; + List myRemoteRepositories; + Map myModulesPathsAndNames; Collection myProfilesIds; - Model myStrippedMavenModel; - List myRemoteRepositories; + Map myModelMap; Collection myActiveProfilesIds; Collection myReadingProblems; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectProblem.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectProblem.java deleted file mode 100644 index 1c6636d9530b..000000000000 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectProblem.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.idea.maven.project; - -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.vfs.VirtualFileManager; - -import java.io.Serializable; - -public class MavenProjectProblem implements Serializable { - public enum ProblemType { - SYNTAX, STRUCTURE, DEPENDENCY, PARENT, SETTINGS_OR_PROFILES; - } - - private String myUrl; - private String myDescription; - private ProblemType myType; - - protected MavenProjectProblem() { - } - - public MavenProjectProblem(VirtualFile file, String description, ProblemType type) { - myUrl = file.getUrl(); - myDescription = description; - myType = type; - } - - public String getUrl() { - return myUrl; - } - - public String getDescription() { - return myDescription; - } - - public ProblemType getType() { - return myType; - } - - public VirtualFile findFile() { - return VirtualFileManager.getInstance().findFileByUrl(myUrl); - } - - @Override - public String toString() { - return myType + ":" + myDescription + ":" + myUrl; - } - - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - MavenProjectProblem that = (MavenProjectProblem)o; - - if (!myDescription.equals(that.myDescription)) return false; - if (myType != that.myType) return false; - if (!myUrl.equals(that.myUrl)) return false; - - return true; - } - - public int hashCode() { - int result = myUrl.hashCode(); - result = 31 * result + myDescription.hashCode(); - result = 31 * result + myType.hashCode(); - return result; - } -} diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReader.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReader.java index b9c5c1d5dcf6..928855b590e4 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReader.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReader.java @@ -21,22 +21,14 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import gnu.trove.THashMap; import gnu.trove.THashSet; -import org.apache.maven.model.*; -import org.apache.maven.profiles.activation.*; -import org.apache.maven.project.InvalidProjectModelException; -import org.apache.maven.project.JBMavenProjectHelper; -import org.apache.maven.project.MavenProject; -import org.apache.maven.project.ProjectBuildingException; -import org.apache.maven.project.inheritance.DefaultModelInheritanceAssembler; -import org.apache.maven.project.injection.DefaultProfileInjector; -import org.apache.maven.project.validation.ModelValidationResult; -import org.apache.maven.shared.dependency.tree.DependencyNode; -import org.codehaus.plexus.context.ContextException; -import org.codehaus.plexus.context.DefaultContext; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.maven.embedder.*; +import org.jetbrains.idea.maven.facade.MavenEmbedderWrapper; +import org.jetbrains.idea.maven.facade.MavenFacadeManager; +import org.jetbrains.idea.maven.facade.MavenWrapperExecutionResult; +import org.jetbrains.idea.maven.facade.ProfileApplicationResult; +import org.jetbrains.idea.maven.model.*; import org.jetbrains.idea.maven.utils.MavenJDOMUtil; import org.jetbrains.idea.maven.utils.MavenLog; import org.jetbrains.idea.maven.utils.MavenProcessCanceledException; @@ -56,46 +48,35 @@ public class MavenProjectReader { private static final String PROFILE_FROM_SETTINGS_XML = "settings.xml"; private final Map myRawModelsCache = new THashMap(); - private Pair, Collection> mySettingsProfilesWithProblemsCache; + private Pair, Collection> mySettingsProfilesWithProblemsCache; public MavenProjectReaderResult readProject(MavenGeneralSettings generalSettings, VirtualFile file, Collection explicitProfiles, MavenProjectReaderProjectLocator locator) { - Pair> readResult = + Pair> readResult = doReadProjectModel(generalSettings, file, explicitProfiles, new THashSet(), locator); File basedir = getBaseDir(file); - Model model = expandProperties(readResult.first.model, basedir); - alignModel(model, basedir); + MavenModel model = MavenFacadeManager.getInstance().interpolateAndAlignModel(readResult.first.model, basedir); - Collection activeProfiles = readResult.second; - - MavenProject mavenProject = new MavenProject(model); - mavenProject.setFile(new File(file.getPath())); - mavenProject.setActiveProfiles(new ArrayList(activeProfiles)); - JBMavenProjectHelper.setSourceRoots(mavenProject, - Collections.singletonList(model.getBuild().getSourceDirectory()), - Collections.singletonList(model.getBuild().getTestSourceDirectory()), - Collections.singletonList(model.getBuild().getScriptSourceDirectory())); - - return new MavenProjectReaderResult(generalSettings, - mavenProject, - Collections.emptyList(), + return new MavenProjectReaderResult(model, + Collections.emptyMap(), + readResult.second, + null, readResult.first.problems, - Collections.emptySet(), - generalSettings.getEffectiveLocalRepository()); + new THashSet()); } private File getBaseDir(VirtualFile file) { return new File(file.getParent().getPath()); } - private Pair> doReadProjectModel(MavenGeneralSettings generalSettings, - VirtualFile file, - Collection explicitProfiles, - Set recursionGuard, - MavenProjectReaderProjectLocator locator) { + private Pair> doReadProjectModel(MavenGeneralSettings generalSettings, + VirtualFile file, + Collection explicitProfiles, + Set recursionGuard, + MavenProjectReaderProjectLocator locator) { RawModelReadResult cachedModel = myRawModelsCache.get(file); if (cachedModel == null) { cachedModel = doReadProjectModel(file, false); @@ -103,24 +84,25 @@ public class MavenProjectReader { } // todo modifying cached model and problems here?????? - Model model = cachedModel.model; - Collection alwaysOnProfiles = cachedModel.alwaysOnProfiles; + MavenModel model = cachedModel.model; + Set alwaysOnProfiles = cachedModel.alwaysOnProfiles; Collection problems = cachedModel.problems; - repairModelHeader(model); - resolveInheritance(generalSettings, model, file, explicitProfiles, recursionGuard, locator, problems); + model = resolveInheritance(generalSettings, model, file, explicitProfiles, recursionGuard, locator, problems); addSettingsProfiles(generalSettings, model, alwaysOnProfiles, problems); - Collection activatedProfiles = applyProfiles(model, getBaseDir(file), explicitProfiles, alwaysOnProfiles); + ProfileApplicationResult applied = applyProfiles(model, getBaseDir(file), explicitProfiles, alwaysOnProfiles); + model = applied.getModel(); repairModelBody(model); - return Pair.create(cachedModel, activatedProfiles); + return new Pair>(new RawModelReadResult(model, problems, alwaysOnProfiles), + applied.getActivatedProfiles()); } private RawModelReadResult doReadProjectModel(VirtualFile file, boolean headerOnly) { - Model result = new Model(); - LinkedHashSet problems = createProblemsList(); + MavenModel result = new MavenModel(); + Collection problems = MavenProjectProblem.createProblemsList(); Set alwaysOnProfiles = new THashSet(); Element xmlProject = readXml(file, problems, MavenProjectProblem.ProblemType.SYNTAX); @@ -128,43 +110,35 @@ public class MavenProjectReader { return new RawModelReadResult(result, problems, alwaysOnProfiles); } - result.setModelVersion(MavenJDOMUtil.findChildValueByPath(xmlProject, "modelVersion")); - result.setGroupId(MavenJDOMUtil.findChildValueByPath(xmlProject, "groupId")); - result.setArtifactId(MavenJDOMUtil.findChildValueByPath(xmlProject, "artifactId")); - result.setVersion(MavenJDOMUtil.findChildValueByPath(xmlProject, "version")); + MavenParent parent = new MavenParent(new MavenId(UNKNOWN, UNKNOWN, UNKNOWN), "../pom.xml"); + if (MavenJDOMUtil.hasChildByPath(xmlProject, "parent")) { + parent = new MavenParent(new MavenId(MavenJDOMUtil.findChildValueByPath(xmlProject, "parent.groupId", UNKNOWN), + MavenJDOMUtil.findChildValueByPath(xmlProject, "parent.artifactId", UNKNOWN), + MavenJDOMUtil.findChildValueByPath(xmlProject, "parent.version", UNKNOWN)), + MavenJDOMUtil.findChildValueByPath(xmlProject, "parent.relativePath", "../pom.xml")); + result.setParent(parent); + } + + result.setMavenId(new MavenId(MavenJDOMUtil.findChildValueByPath(xmlProject, "groupId", parent.getMavenId().getGroupId()), + MavenJDOMUtil.findChildValueByPath(xmlProject, "artifactId", UNKNOWN), + MavenJDOMUtil.findChildValueByPath(xmlProject, "version", parent.getMavenId().getVersion()))); if (headerOnly) return new RawModelReadResult(result, problems, alwaysOnProfiles); - result.setPackaging(MavenJDOMUtil.findChildValueByPath(xmlProject, "packaging")); + result.setPackaging(MavenJDOMUtil.findChildValueByPath(xmlProject, "packaging", "jar")); result.setName(MavenJDOMUtil.findChildValueByPath(xmlProject, "name")); - if (MavenJDOMUtil.hasChildByPath(xmlProject, "parent")) { - Parent parent = new Parent(); - - String groupId = MavenJDOMUtil.findChildValueByPath(xmlProject, "parent.groupId"); - String artifactId = MavenJDOMUtil.findChildValueByPath(xmlProject, "parent.artifactId"); - String version = MavenJDOMUtil.findChildValueByPath(xmlProject, "parent.version"); - - parent.setGroupId(groupId); - parent.setArtifactId(artifactId); - parent.setVersion(version); - parent.setRelativePath(MavenJDOMUtil.findChildValueByPath(xmlProject, "parent.relativePath")); - - result.setParent(parent); - } - result.setBuild(new Build()); - readModelAndBuild(result, result.getBuild(), xmlProject); + readModelBody(result, result.getBuild(), xmlProject); result.setProfiles(collectProfiles(file, xmlProject, problems, alwaysOnProfiles)); return new RawModelReadResult(result, problems, alwaysOnProfiles); } - private void readModelAndBuild(ModelBase mavenModelBase, BuildBase mavenBuildBase, Element xmlModel) { + private void readModelBody(MavenModelBase mavenModelBase, MavenBuildBase mavenBuildBase, Element xmlModel) { mavenModelBase.setModules(MavenJDOMUtil.findChildrenValuesByPath(xmlModel, "modules", "module")); collectProperties(MavenJDOMUtil.findChildByPath(xmlModel, "properties"), mavenModelBase); Element xmlBuild = MavenJDOMUtil.findChildByPath(xmlModel, "build"); - if (xmlBuild == null) return; mavenBuildBase.setFinalName(MavenJDOMUtil.findChildValueByPath(xmlBuild, "finalName")); mavenBuildBase.setDefaultGoal(MavenJDOMUtil.findChildValueByPath(xmlBuild, "defaultGoal")); @@ -172,36 +146,74 @@ public class MavenProjectReader { mavenBuildBase.setResources(collectResources(MavenJDOMUtil.findChildrenByPath(xmlBuild, "resources", "resource"))); mavenBuildBase.setTestResources(collectResources(MavenJDOMUtil.findChildrenByPath(xmlBuild, "testResources", "testResource"))); - if (mavenBuildBase instanceof Build) { - Build mavenBuild = (Build)mavenBuildBase; + if (mavenBuildBase instanceof MavenBuild) { + MavenBuild mavenBuild = (MavenBuild)mavenBuildBase; + + String source = MavenJDOMUtil.findChildValueByPath(xmlBuild, "sourceDirectory"); + if (!isEmptyOrSpaces(source)) mavenBuild.addSource(source); + String testSource = MavenJDOMUtil.findChildValueByPath(xmlBuild, "testSourceDirectory"); + if (!isEmptyOrSpaces(testSource)) mavenBuild.addTestSource(testSource); - mavenBuild.setSourceDirectory(MavenJDOMUtil.findChildValueByPath(xmlBuild, "sourceDirectory")); - mavenBuild.setTestSourceDirectory(MavenJDOMUtil.findChildValueByPath(xmlBuild, "testSourceDirectory")); - mavenBuild.setScriptSourceDirectory(MavenJDOMUtil.findChildValueByPath(xmlBuild, "scriptSourceDirectory")); mavenBuild.setOutputDirectory(MavenJDOMUtil.findChildValueByPath(xmlBuild, "outputDirectory")); mavenBuild.setTestOutputDirectory(MavenJDOMUtil.findChildValueByPath(xmlBuild, "testOutputDirectory")); } } - private List collectResources(List xmlResources) { - List result = new ArrayList(); + private List collectResources(List xmlResources) { + List result = new ArrayList(); for (Element each : xmlResources) { - Resource r = new Resource(); - r.setDirectory(MavenJDOMUtil.findChildValueByPath(each, "directory")); - r.setFiltering("true".equals(MavenJDOMUtil.findChildValueByPath(each, "filtering"))); - r.setTargetPath(MavenJDOMUtil.findChildValueByPath(each, "targetPath")); - r.setIncludes(MavenJDOMUtil.findChildrenValuesByPath(each, "includes", "include")); - r.setExcludes(MavenJDOMUtil.findChildrenValuesByPath(each, "excludes", "exclude")); - result.add(r); + result.add(new MavenResource(MavenJDOMUtil.findChildValueByPath(each, "directory"), + "true".equals(MavenJDOMUtil.findChildValueByPath(each, "filtering")), + MavenJDOMUtil.findChildValueByPath(each, "targetPath"), + MavenJDOMUtil.findChildrenValuesByPath(each, "includes", "include"), + MavenJDOMUtil.findChildrenValuesByPath(each, "excludes", "exclude"))); } return result; } - private List collectProfiles(VirtualFile projectFile, - Element xmlProject, - Collection problems, - Collection alwaysOnProfiles) { - List result = new ArrayList(); + private void repairModelBody(MavenModel model) { + MavenBuild build = model.getBuild(); + + if (isEmptyOrSpaces(build.getFinalName())) { + build.setFinalName("${project.artifactId}-${project.version}"); + } + + if (build.getSources().isEmpty()) build.addSource("src/main/java"); + if (build.getTestSources().isEmpty()) build.addTestSource("src/test/java"); + + build.setResources(repairResources(build.getResources(), "src/main/resources")); + build.setTestResources(repairResources(build.getTestResources(), "src/test/resources")); + + build.setDirectory(isEmptyOrSpaces(build.getDirectory()) ? "target" : build.getDirectory()); + build.setOutputDirectory(isEmptyOrSpaces(build.getOutputDirectory()) + ? "${project.build.directory}/classes" : build.getOutputDirectory()); + build.setTestOutputDirectory(isEmptyOrSpaces(build.getTestOutputDirectory()) + ? "${project.build.directory}/test-classes" : build.getTestOutputDirectory()); + } + + private List repairResources(List resources, String defaultDir) { + List result = new ArrayList(); + if (resources.isEmpty()) { + result.add(createResource(defaultDir)); + return result; + } + + for (MavenResource each : resources) { + if (isEmptyOrSpaces(each.getDirectory())) continue; + result.add(each); + } + return result; + } + + private MavenResource createResource(String directory) { + return new MavenResource(directory, false, null, Collections.emptyList(), Collections.emptyList()); + } + + private List collectProfiles(VirtualFile projectFile, + Element xmlProject, + Collection problems, + Collection alwaysOnProfiles) { + List result = new ArrayList(); collectProfiles(MavenJDOMUtil.findChildrenByPath(xmlProject, "profiles", "profile"), result, PROFILE_FROM_POM); VirtualFile profilesFile = MavenUtil.findProfilesXmlFile(projectFile); @@ -219,13 +231,13 @@ public class MavenProjectReader { } private void addSettingsProfiles(MavenGeneralSettings generalSettings, - Model model, + MavenModel model, Collection alwaysOnProfiles, Collection problems) { if (mySettingsProfilesWithProblemsCache == null) { - List settingsProfiles = new ArrayList(); - Collection settingsProblems = createProblemsList(); + List settingsProfiles = new ArrayList(); + Collection settingsProblems = MavenProjectProblem.createProblemsList(); for (VirtualFile each : generalSettings.getEffectiveSettingsFiles()) { collectProfilesFromSettingsXmlOrProfilesXml(each, @@ -239,8 +251,8 @@ public class MavenProjectReader { mySettingsProfilesWithProblemsCache = Pair.create(settingsProfiles, settingsProblems); } - List modelProfiles = model.getProfiles(); - for (Profile each : mySettingsProfilesWithProblemsCache.first) { + List modelProfiles = model.getProfiles(); + for (MavenProfile each : mySettingsProfilesWithProblemsCache.first) { addProfileIfDoesNotExist(each, modelProfiles); } problems.addAll(mySettingsProfilesWithProblemsCache.second); @@ -250,7 +262,7 @@ public class MavenProjectReader { String rootElementName, boolean wrapRootIfNecessary, String profilesSource, - List result, + List result, Collection alwaysOnProfiles, Collection problems) { Element rootElement = readXml(profilesFile, problems, MavenProjectProblem.ProblemType.SETTINGS_OR_PROFILES); @@ -268,66 +280,60 @@ public class MavenProjectReader { alwaysOnProfiles.addAll(MavenJDOMUtil.findChildrenValuesByPath(rootElement, "activeProfiles", "activeProfile")); } - private void collectProfiles(List xmlProfiles, List result, String source) { + private void collectProfiles(List xmlProfiles, List result, String source) { for (Element each : xmlProfiles) { String id = MavenJDOMUtil.findChildValueByPath(each, "id"); if (isEmptyOrSpaces(id)) continue; - Profile profile = new Profile(); - profile.setId(id); - profile.setSource(source); + MavenProfile profile = new MavenProfile(id, source); if (!addProfileIfDoesNotExist(profile, result)) continue; Element xmlActivation = MavenJDOMUtil.findChildByPath(each, "activation"); if (xmlActivation != null) { - Activation activation = new Activation(); + MavenProfileActivation activation = new MavenProfileActivation(); activation.setActiveByDefault("true".equals(MavenJDOMUtil.findChildValueByPath(xmlActivation, "activeByDefault"))); Element xmlOS = MavenJDOMUtil.findChildByPath(xmlActivation, "os"); if (xmlOS != null) { - ActivationOS activationOS = new ActivationOS(); - activationOS.setName(MavenJDOMUtil.findChildValueByPath(xmlOS, "name")); - activationOS.setFamily(MavenJDOMUtil.findChildValueByPath(xmlOS, "family")); - activationOS.setArch(MavenJDOMUtil.findChildValueByPath(xmlOS, "arch")); - activationOS.setVersion(MavenJDOMUtil.findChildValueByPath(xmlOS, "version")); - activation.setOs(activationOS); + activation.setOs(new MavenProfileActivationOS( + MavenJDOMUtil.findChildValueByPath(xmlOS, "name"), + MavenJDOMUtil.findChildValueByPath(xmlOS, "family"), + MavenJDOMUtil.findChildValueByPath(xmlOS, "arch"), + MavenJDOMUtil.findChildValueByPath(xmlOS, "version"))); } activation.setJdk(MavenJDOMUtil.findChildValueByPath(xmlActivation, "jdk")); Element xmlProperty = MavenJDOMUtil.findChildByPath(xmlActivation, "property"); if (xmlProperty != null) { - ActivationProperty activationProperty = new ActivationProperty(); - activationProperty.setName(MavenJDOMUtil.findChildValueByPath(xmlProperty, "name")); - activationProperty.setValue(MavenJDOMUtil.findChildValueByPath(xmlProperty, "value")); - activation.setProperty(activationProperty); + activation.setProperty(new MavenProfileActivationProperty( + MavenJDOMUtil.findChildValueByPath(xmlProperty, "name"), + MavenJDOMUtil.findChildValueByPath(xmlProperty, "value"))); } Element xmlFile = MavenJDOMUtil.findChildByPath(xmlActivation, "file"); if (xmlFile != null) { - ActivationFile activationFile = new ActivationFile(); - activationFile.setExists(MavenJDOMUtil.findChildValueByPath(xmlFile, "exists")); - activationFile.setMissing(MavenJDOMUtil.findChildValueByPath(xmlFile, "missing")); - activation.setFile(activationFile); + activation.setFile(new MavenProfileActivationFile( + MavenJDOMUtil.findChildValueByPath(xmlFile, "exists"), + MavenJDOMUtil.findChildValueByPath(xmlFile, "missing"))); } profile.setActivation(activation); } - profile.setBuild(new BuildBase()); - readModelAndBuild(profile, profile.getBuild(), each); + readModelBody(profile, profile.getBuild(), each); } } - private boolean addProfileIfDoesNotExist(Profile profile, List result) { - for (Profile each : result) { + private boolean addProfileIfDoesNotExist(MavenProfile profile, List result) { + for (MavenProfile each : result) { if (Comparing.equal(each.getId(), profile.getId())) return false; } result.add(profile); return true; } - private void collectProperties(Element xmlProperties, ModelBase mavenModelBase) { + private void collectProperties(Element xmlProperties, MavenModelBase mavenModelBase) { if (xmlProperties == null) return; Properties props = mavenModelBase.getProperties(); @@ -341,181 +347,37 @@ public class MavenProjectReader { } } - private List applyProfiles(Model model, File basedir, Collection explicitProfiles, Collection alwaysOnProfiles) { - List activatedPom = new ArrayList(); - List activatedExternal = new ArrayList(); - List activeByDefault = new ArrayList(); - - List rawProfiles = model.getProfiles(); - List expandedProfilesCache = null; - - for (int i = 0; i < rawProfiles.size(); i++) { - Profile eachRawProfile = rawProfiles.get(i); - - boolean shouldAdd = explicitProfiles.contains(eachRawProfile.getId()) || alwaysOnProfiles.contains(eachRawProfile.getId()); - - Activation activation = eachRawProfile.getActivation(); - if (activation != null) { - if (activation.isActiveByDefault()) { - activeByDefault.add(eachRawProfile); - } - - // expand only if necessary - if (expandedProfilesCache == null) expandedProfilesCache = expandProperties(model, basedir).getProfiles(); - Profile eachExpandedProfile = expandedProfilesCache.get(i); - - for (ProfileActivator eachActivator : getProfileActivators()) { - try { - if (eachActivator.canDetermineActivation(eachExpandedProfile) && eachActivator.isActive(eachExpandedProfile)) { - shouldAdd = true; - break; - } - } - catch (ProfileActivationException e) { - MavenLog.LOG.warn(e); - } - } - } - - if (shouldAdd) { - if (PROFILE_FROM_POM.equals(eachRawProfile.getSource())) { - activatedPom.add(eachRawProfile); - } - else { - activatedExternal.add(eachRawProfile); - } - } - } - - List activatedProfiles = new ArrayList(activatedPom.isEmpty() ? activeByDefault : activatedPom); - activatedProfiles.addAll(activatedExternal); - - for (Profile each : activatedProfiles) { - new DefaultProfileInjector().inject(each, model); - } - - return activatedProfiles; + private ProfileApplicationResult applyProfiles(MavenModel model, + File basedir, + Collection explicitProfiles, + Collection alwaysOnProfiles) { + return MavenFacadeManager.getInstance().applyProfiles(model, basedir, explicitProfiles, alwaysOnProfiles); } - private ProfileActivator[] getProfileActivators() { - SystemPropertyProfileActivator sysPropertyActivator = new SystemPropertyProfileActivator(); - DefaultContext context = new DefaultContext(); - context.put("SystemProperties", MavenEmbedderWrapper.collectSystemProperties()); - try { - sysPropertyActivator.contextualize(context); - } - catch (ContextException e) { - MavenLog.LOG.error(e); - return new ProfileActivator[0]; - } - - return new ProfileActivator[]{new FileProfileActivator(), sysPropertyActivator, new JdkPrefixProfileActivator(), - new OperatingSystemProfileActivator()}; - } - - private void repairModelHeader(Model model) { - if (isEmptyOrSpaces(model.getModelVersion())) model.setModelVersion("4.0.0"); - - Parent parent = model.getParent(); - if (parent != null) { - if (isEmptyOrSpaces(parent.getGroupId())) parent.setGroupId(UNKNOWN); - if (isEmptyOrSpaces(parent.getArtifactId())) parent.setArtifactId(UNKNOWN); - if (isEmptyOrSpaces(parent.getVersion())) parent.setVersion(UNKNOWN); - if (isEmptyOrSpaces(parent.getRelativePath())) parent.setRelativePath("../pom.xml"); - } - - if (isEmptyOrSpaces(model.getGroupId())) { - if (parent != null) { - model.setGroupId(parent.getGroupId()); - } - else { - model.setGroupId(UNKNOWN); - } - } - if (isEmptyOrSpaces(model.getArtifactId())) model.setArtifactId(UNKNOWN); - if (isEmptyOrSpaces(model.getVersion())) { - if (parent != null) { - model.setVersion(parent.getVersion()); - } - else { - model.setVersion(UNKNOWN); - } - } - - if (isEmptyOrSpaces(model.getPackaging())) model.setPackaging("jar"); - } - - private void repairModelBody(Model model) { - if (model.getBuild() == null) { - model.setBuild(new Build()); - } - Build build = model.getBuild(); - - if (isEmptyOrSpaces(build.getFinalName())) { - build.setFinalName("${project.artifactId}-${project.version}"); - } - - build.setSourceDirectory(isEmptyOrSpaces(build.getSourceDirectory()) ? "src/main/java" : build.getSourceDirectory()); - build.setTestSourceDirectory(isEmptyOrSpaces(build.getTestSourceDirectory()) ? "src/test/java" : build.getTestSourceDirectory()); - build - .setScriptSourceDirectory(isEmptyOrSpaces(build.getScriptSourceDirectory()) ? "src/main/scripts" : build.getScriptSourceDirectory()); - - build.setResources(repairResources(build.getResources(), "src/main/resources")); - build.setTestResources(repairResources(build.getTestResources(), "src/test/resources")); - - build.setDirectory(isEmptyOrSpaces(build.getDirectory()) ? "target" : build.getDirectory()); - build - .setOutputDirectory(isEmptyOrSpaces(build.getOutputDirectory()) ? "${project.build.directory}/classes" : build.getOutputDirectory()); - build.setTestOutputDirectory( - isEmptyOrSpaces(build.getTestOutputDirectory()) ? "${project.build.directory}/test-classes" : build.getTestOutputDirectory()); - } - - private List repairResources(List resources, String defaultDir) { - List result = new ArrayList(); - if (resources.isEmpty()) { - result.add(createResource(defaultDir)); - return result; - } - - for (Resource each : resources) { - if (isEmptyOrSpaces(each.getDirectory())) continue; - each.setDirectory(each.getDirectory()); - result.add(each); - } - return result; - } - - private Resource createResource(String directory) { - Resource result = new Resource(); - result.setDirectory(directory); - return result; - } - - private void resolveInheritance(final MavenGeneralSettings generalSettings, - final Model model, - final VirtualFile file, - final Collection explicitProfiles, - final Set recursionGuard, - final MavenProjectReaderProjectLocator locator, - Collection problems) { + private MavenModel resolveInheritance(final MavenGeneralSettings generalSettings, + MavenModel model, + final VirtualFile file, + final Collection explicitProfiles, + final Set recursionGuard, + final MavenProjectReaderProjectLocator locator, + Collection problems) { if (recursionGuard.contains(file)) { - problems.add(createProblem(file, ProjectBundle.message("maven.project.problem.recursiveInheritance"), - MavenProjectProblem.ProblemType.PARENT)); - return; + problems.add(MavenProjectProblem.createProblem(file.getPath(), ProjectBundle.message("maven.project.problem.recursiveInheritance"), + MavenProjectProblem.ProblemType.PARENT)); + return model; } recursionGuard.add(file); try { - Parent parent = model.getParent(); final MavenParentDesc[] parentDesc = new MavenParentDesc[1]; + MavenParent parent = model.getParent(); if (parent != null) { - MavenId parentId = new MavenId(parent.getGroupId(), parent.getArtifactId(), parent.getVersion()); - if (parentId.equals(model.getGroupId(), model.getArtifactId(), model.getVersion())) { - problems.add(createProblem(file, ProjectBundle.message("maven.project.problem.selfInheritance"), - MavenProjectProblem.ProblemType.PARENT)); - return; + if (model.getMavenId().equals(parent.getMavenId())) { + problems.add(MavenProjectProblem.createProblem(file.getPath(), ProjectBundle.message("maven.project.problem.selfInheritance"), + MavenProjectProblem.ProblemType.PARENT)); + return model; } - parentDesc[0] = new MavenParentDesc(parentId, parent.getRelativePath()); + parentDesc[0] = new MavenParentDesc(parent.getMavenId(), parent.getRelativePath()); } Pair parentModelWithProblems = @@ -528,9 +390,9 @@ public class MavenProjectReader { @Override @Nullable protected Pair processRelativeParent(VirtualFile parentFile) { - Model parentModel = doReadProjectModel(parentFile, true).model; + MavenModel parentModel = doReadProjectModel(parentFile, true).model; MavenId parentId = parentDesc[0].getParentId(); - if (!parentId.equals(new MavenId(parentModel))) return null; + if (!parentId.equals(parentModel.getMavenId())) return null; return super.processRelativeParent(parentFile); } @@ -547,165 +409,89 @@ public class MavenProjectReader { } }.process(generalSettings, file, parentDesc[0]); - if (parentModelWithProblems == null) return; // no parent or parent not found; + if (parentModelWithProblems == null) return model; // no parent or parent not found; - Model parentModel = parentModelWithProblems.second.model; + MavenModel parentModel = parentModelWithProblems.second.model; if (!parentModelWithProblems.second.problems.isEmpty()) { - problems.add(createProblem(parentModelWithProblems.first, - ProjectBundle.message("maven.project.problem.parentHasProblems", new MavenId(parentModel)), - MavenProjectProblem.ProblemType.PARENT)); + problems.add(MavenProjectProblem.createProblem(parentModelWithProblems.first.getPath(), + ProjectBundle.message("maven.project.problem.parentHasProblems", + parentModel.getMavenId()), + MavenProjectProblem.ProblemType.PARENT)); } - new DefaultModelInheritanceAssembler().assembleModelInheritance(model, parentModel); - - List profiles = model.getProfiles(); - for (Profile each : parentModel.getProfiles()) { + model = MavenFacadeManager.getInstance().assembleInheritance(model, parentModel); + List profiles = model.getProfiles(); + for (MavenProfile each : parentModel.getProfiles()) { addProfileIfDoesNotExist(each, profiles); } + return model; } finally { recursionGuard.remove(file); } } - private Model expandProperties(Model model, File basedir) { - return MavenEmbedderWrapper.interpolate(model, basedir); - } - - private void alignModel(Model model, File basedir) { - MavenEmbedderWrapper.alignModel(model, basedir); - } - - private MavenProjectProblem createStructureProblem(VirtualFile file, String description) { - return createProblem(file, description, MavenProjectProblem.ProblemType.STRUCTURE); - } - - private MavenProjectProblem createSyntaxProblem(VirtualFile file, MavenProjectProblem.ProblemType type) { - return createProblem(file, ProjectBundle.message("maven.project.problem.syntaxError", file.getName()), type); - } - - private MavenProjectProblem createProblem(VirtualFile file, String description, MavenProjectProblem.ProblemType type) { - return new MavenProjectProblem(file, description, type); - } - - private LinkedHashSet createProblemsList() { - return createProblemsList(Collections.emptySet()); - } - - private LinkedHashSet createProblemsList(Collection copyThis) { - return new LinkedHashSet(copyThis); - } - public MavenProjectReaderResult resolveProject(MavenGeneralSettings generalSettings, MavenEmbedderWrapper embedder, VirtualFile file, Collection explicitProfiles, MavenProjectReaderProjectLocator locator) throws MavenProcessCanceledException { - MavenProject mavenProject = null; - Collection problems = createProblemsList(); - Set unresolvedArtifactsIds = new THashSet(); - Collection dependencyTree = Collections.emptyList(); - try { - MavenWrapperResolutionResult result = doResolveProject(embedder, file, explicitProfiles, problems); - mavenProject = result.getMavenProject(); - unresolvedArtifactsIds = result.getUnresolvedArtifactIds(); - dependencyTree = result.getOriginalDependencyTree(); + MavenWrapperExecutionResult result = embedder.resolveProject(file, explicitProfiles); + if (result.projectData == null) { + MavenProjectReaderResult temp = readProject(generalSettings, file, explicitProfiles, locator); + temp.readingProblems.addAll(result.problems); + temp.unresolvedArtifactIds.addAll(result.unresolvedArtifacts); + return temp; + } + + return new MavenProjectReaderResult(result.projectData.mavenModel, + result.projectData.mavenModelMap, + result.projectData.activatedProfiles, + result.projectData.nativeMavenProject, + result.problems, + result.unresolvedArtifacts); } catch (MavenProcessCanceledException e) { throw e; } catch (Throwable e) { - String message = e.getMessage(); - - if (e instanceof RuntimeException && e.getCause() != null) { - message = e.getCause().getMessage(); - } - - if (message != null) { - problems.add(createStructureProblem(file, message)); - } MavenLog.LOG.info(e); MavenLog.printInTests(e); // print exception since we need to know if something wrong with our logic - } - if (mavenProject == null) { - if (problems.isEmpty()) { - problems.add(createSyntaxProblem(file, MavenProjectProblem.ProblemType.SYNTAX)); - } - mavenProject = readProject(generalSettings, file, explicitProfiles, locator).nativeMavenProject; - } - - return new MavenProjectReaderResult(generalSettings, mavenProject, dependencyTree, problems, unresolvedArtifactsIds, embedder.getLocalRepositoryFile()); - } - - private MavenWrapperResolutionResult doResolveProject(MavenEmbedderWrapper embedder, - VirtualFile file, - Collection profiles, - Collection problems) throws MavenProcessCanceledException { - MavenWrapperResolutionResult result = embedder.resolveProject(file, profiles); - validate(file, result, problems); - return result; - } - - private boolean validate(VirtualFile file, MavenWrapperExecutionResult r, Collection problems) { - for (Exception each : r.getExceptions()) { - MavenLog.LOG.info(each); - - if (each instanceof InvalidProjectModelException) { - ModelValidationResult modelValidationResult = ((InvalidProjectModelException)each).getValidationResult(); - if (modelValidationResult != null) { - for (Object eachValidationProblem : modelValidationResult.getMessages()) { - problems.add(createStructureProblem(file, (String)eachValidationProblem)); - } - } - else { - problems.add(createStructureProblem(file, each.getCause().getMessage())); - } - } - else if (each instanceof ProjectBuildingException) { - String causeMessage = each.getCause() != null ? each.getCause().getMessage() : each.getMessage(); - problems.add(createStructureProblem(file, causeMessage)); + MavenProjectReaderResult result = readProject(generalSettings, file, explicitProfiles, locator); + String message = e.getMessage(); + if (message != null) { + result.readingProblems.add(MavenProjectProblem.createStructureProblem(file.getPath(), message)); } else { - problems.add(createStructureProblem(file, each.getMessage())); + result.readingProblems.add(MavenProjectProblem.createSyntaxProblem(file.getPath(), MavenProjectProblem.ProblemType.SYNTAX)); } + return result; } - - return problems.isEmpty(); } public MavenProjectReaderResult generateSources(MavenEmbedderWrapper embedder, - MavenGeneralSettings generalSettings, MavenImportingSettings importingSettings, VirtualFile file, Collection profiles, MavenConsole console) throws MavenProcessCanceledException { try { - MavenWrapperExecutionResult result = embedder.execute(file, profiles, Arrays.asList(importingSettings.getUpdateFoldersOnImportPhase())); + List goals = Arrays.asList(importingSettings.getUpdateFoldersOnImportPhase()); + Collection problems = MavenProjectProblem.createProblemsList(); + Set unresolvedArtifacts = new THashSet(); + MavenWrapperExecutionResult result = embedder.execute(file, profiles, goals); + if (result.projectData == null) return null; - if (result.hasExceptions()) { - MavenConsoleHelper.printExecutionExceptions(console, result); - } - - Collection problems = createProblemsList(); - if (!validate(file, result, problems)) return null; - - MavenProject project = result.getMavenProject(); - if (project == null) return null; - - return new MavenProjectReaderResult(generalSettings, - project, - Collections.emptyList(), - problems, - result.getUnresolvedArtifactIds(), - embedder.getLocalRepositoryFile()); - } - catch (MavenProcessCanceledException e) { - throw e; + return new MavenProjectReaderResult(result.projectData.mavenModel, + result.projectData.mavenModelMap, + result.projectData.activatedProfiles, + result.projectData.nativeMavenProject, + result.problems, + result.unresolvedArtifacts); } catch (Throwable e) { - MavenConsoleHelper.printException(console, e); + console.printException(e); MavenLog.LOG.warn(e); return null; } @@ -717,21 +503,21 @@ public class MavenProjectReader { return MavenJDOMUtil.read(file, new MavenJDOMUtil.ErrorHandler() { public void onReadError(IOException e) { MavenLog.LOG.warn("Cannot read the pom file: " + e); - problems.add(createProblem(file, e.getMessage(), type)); + problems.add(MavenProjectProblem.createProblem(file.getPath(), e.getMessage(), type)); } public void onSyntaxError() { - problems.add(createSyntaxProblem(file, type)); + problems.add(MavenProjectProblem.createSyntaxProblem(file.getPath(), type)); } }); } private static class RawModelReadResult { - public Model model; + public MavenModel model; public Collection problems; public Set alwaysOnProfiles; - private RawModelReadResult(Model model, Collection problems, Set alwaysOnProfiles) { + private RawModelReadResult(MavenModel model, Collection problems, Set alwaysOnProfiles) { this.model = model; this.problems = problems; this.alwaysOnProfiles = alwaysOnProfiles; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReaderProjectLocator.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReaderProjectLocator.java index 08927dfbcbeb..3d88e3445d8d 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReaderProjectLocator.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReaderProjectLocator.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2010 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,7 @@ package org.jetbrains.idea.maven.project; import com.intellij.openapi.vfs.VirtualFile; -import org.jetbrains.idea.maven.project.MavenId; +import org.jetbrains.idea.maven.model.MavenId; public interface MavenProjectReaderProjectLocator { VirtualFile findProjectFile(MavenId coordinates); diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReaderResult.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReaderResult.java index aae7c5bc70be..c9af6eaf11b8 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReaderResult.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReaderResult.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2010 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,32 +15,33 @@ */ package org.jetbrains.idea.maven.project; -import org.apache.maven.project.MavenProject; -import org.apache.maven.shared.dependency.tree.DependencyNode; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.maven.facade.NativeMavenProjectHolder; +import org.jetbrains.idea.maven.model.*; -import java.io.File; import java.util.Collection; +import java.util.Map; import java.util.Set; public class MavenProjectReaderResult { - final public MavenGeneralSettings settings; - final public MavenProject nativeMavenProject; - final public Collection dependencyTree; - final public Collection readingProblems; - final public Set unresolvedArtifactIds; - final public File localRepository; + public final MavenModel mavenModel; + public final Map nativeModelMap; + public final Collection activatedProfiles; + @Nullable public final NativeMavenProjectHolder nativeMavenProject; + public final Collection readingProblems; + public final Set unresolvedArtifactIds; - public MavenProjectReaderResult(MavenGeneralSettings settings, - MavenProject nativeMavenProject, - Collection dependencyTree, + public MavenProjectReaderResult(MavenModel mavenModel, + Map nativeModelMap, + Collection activatedProfiles, + @Nullable NativeMavenProjectHolder nativeMavenProject, Collection readingProblems, - Set unresolvedArtifactIds, - File localRepository) { - this.settings = settings; + Set unresolvedArtifactIds) { + this.mavenModel = mavenModel; + this.nativeModelMap = nativeModelMap; + this.activatedProfiles = activatedProfiles; this.nativeMavenProject = nativeMavenProject; - this.dependencyTree = dependencyTree; this.readingProblems = readingProblems; this.unresolvedArtifactIds = unresolvedArtifactIds; - this.localRepository = localRepository; } } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java index 592b40514ed6..043196f086ee 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java @@ -49,10 +49,12 @@ import org.jetbrains.idea.maven.dom.MavenDomUtil; import org.jetbrains.idea.maven.dom.model.MavenDomDependency; import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel; import org.jetbrains.idea.maven.execution.SoutMavenConsole; +import org.jetbrains.idea.maven.facade.NativeMavenProjectHolder; import org.jetbrains.idea.maven.importing.MavenDefaultModifiableModelsProvider; import org.jetbrains.idea.maven.importing.MavenFoldersImporter; import org.jetbrains.idea.maven.importing.MavenModifiableModelsProvider; import org.jetbrains.idea.maven.importing.MavenProjectImporter; +import org.jetbrains.idea.maven.model.*; import org.jetbrains.idea.maven.utils.*; import java.io.File; @@ -237,7 +239,7 @@ public class MavenProjectsManager extends SimpleProjectComponent } private void initWorkers() { - myEmbeddersManager = new MavenEmbeddersManager(getGeneralSettings()); + myEmbeddersManager = new MavenEmbeddersManager(myProject); myReadingProcessor = new MavenProjectsProcessor(myProject, ProjectBundle.message("maven.reading"), false, myEmbeddersManager); myResolvingProcessor = new MavenProjectsProcessor(myProject, ProjectBundle.message("maven.resolving"), true, myEmbeddersManager); @@ -330,9 +332,9 @@ public class MavenProjectsManager extends SimpleProjectComponent @Override public void projectResolved(Pair projectWithChanges, - org.apache.maven.project.MavenProject nativeMavenProject, + @Nullable NativeMavenProjectHolder nativeMavenProject, Object message) { - if (shouldScheduleProject(projectWithChanges)) { + if (nativeMavenProject != null && shouldScheduleProject(projectWithChanges)) { if (projectWithChanges.first.hasUnresolvedPlugins()) { schedulePluginsResolving(projectWithChanges.first, nativeMavenProject); } @@ -392,16 +394,13 @@ public class MavenProjectsManager extends SimpleProjectComponent myArtifactsDownloadingProcessor.stop(); myPostProcessor.stop(); - myEmbeddersManager.release(); - if (isUnitTestMode()) { FileUtil.delete(getProjectsTreesDir()); } } } - @TestOnly - public MavenEmbeddersManager getEmbeddersManagerInTests() { + public MavenEmbeddersManager getEmbeddersManager() { return myEmbeddersManager; } @@ -478,7 +477,7 @@ public class MavenProjectsManager extends SimpleProjectComponent return myProjectsTree.getAvailableProfiles(); } - public Collection> getProfilesWithStates() { + public Collection> getProfilesWithStates() { if (!isInitialized()) return Collections.emptyList(); return myProjectsTree.getProfilesWithStates(); } @@ -679,7 +678,7 @@ public class MavenProjectsManager extends SimpleProjectComponent MavenProject each = it.next(); Object message = it.hasNext() ? null : FORCE_IMPORT_MESSAGE; myFoldersResolvingProcessor.scheduleTask( - new MavenProjectsProcessorFoldersResolvingTask(each, getGeneralSettings(), getImportingSettings(), myProjectsTree, message)); + new MavenProjectsProcessorFoldersResolvingTask(each, getImportingSettings(), myProjectsTree, message)); } } }); @@ -689,7 +688,7 @@ public class MavenProjectsManager extends SimpleProjectComponent scheduleFoldersResolving(getProjects()); } - private void schedulePluginsResolving(final MavenProject project, final org.apache.maven.project.MavenProject nativeMavenProject) { + private void schedulePluginsResolving(final MavenProject project, final NativeMavenProjectHolder nativeMavenProject) { runWhenFullyOpen(new Runnable() { public void run() { myPluginsResolvingProcessor diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManagerWatcher.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManagerWatcher.java index e7124afe2cb8..9ef1ca9b7de6 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManagerWatcher.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManagerWatcher.java @@ -36,7 +36,6 @@ import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.openapi.vfs.newvfs.BulkFileListener; import com.intellij.openapi.vfs.newvfs.NewVirtualFile; import com.intellij.openapi.vfs.newvfs.events.*; -import com.intellij.openapi.vfs.newvfs.impl.NullVirtualFile; import com.intellij.openapi.vfs.pointers.VirtualFilePointer; import com.intellij.openapi.vfs.pointers.VirtualFilePointerListener; import com.intellij.openapi.vfs.pointers.VirtualFilePointerManager; @@ -47,7 +46,7 @@ import com.intellij.util.messages.MessageBusConnection; import com.intellij.util.ui.update.Update; import gnu.trove.THashSet; import org.jetbrains.annotations.TestOnly; -import org.jetbrains.idea.maven.utils.MavenConstants; +import org.jetbrains.idea.maven.model.MavenConstants; import org.jetbrains.idea.maven.utils.MavenMergingUpdateQueue; import org.jetbrains.idea.maven.utils.MavenUtil; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsProcessor.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsProcessor.java index 2b0e4e505010..7d807fa7c2eb 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsProcessor.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsProcessor.java @@ -19,7 +19,6 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; import com.intellij.util.concurrency.Semaphore; -import org.jetbrains.idea.maven.embedder.MavenConsole; import org.jetbrains.idea.maven.execution.SoutMavenConsole; import org.jetbrains.idea.maven.utils.*; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsProcessorArtifactsDownloadingTask.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsProcessorArtifactsDownloadingTask.java index 53460c30b4a1..d03b3763de5b 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsProcessorArtifactsDownloadingTask.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsProcessorArtifactsDownloadingTask.java @@ -20,7 +20,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ex.ProjectRootManagerEx; import com.intellij.openapi.util.AsyncResult; import com.intellij.openapi.util.EmptyRunnable; -import org.jetbrains.idea.maven.embedder.MavenConsole; +import org.jetbrains.idea.maven.model.MavenArtifact; import org.jetbrains.idea.maven.utils.MavenProcessCanceledException; import org.jetbrains.idea.maven.utils.MavenProgressIndicator; import org.jetbrains.idea.maven.utils.MavenUtil; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsProcessorEmptyTask.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsProcessorEmptyTask.java index b3217db42598..5361ad0e6234 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsProcessorEmptyTask.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsProcessorEmptyTask.java @@ -15,7 +15,6 @@ */ package org.jetbrains.idea.maven.project; -import org.jetbrains.idea.maven.embedder.MavenConsole; import org.jetbrains.idea.maven.utils.MavenProgressIndicator; import org.jetbrains.idea.maven.utils.MavenProcessCanceledException; import com.intellij.openapi.project.Project; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsProcessorFoldersResolvingTask.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsProcessorFoldersResolvingTask.java index 6700f041d23e..784709d26815 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsProcessorFoldersResolvingTask.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsProcessorFoldersResolvingTask.java @@ -16,28 +16,24 @@ package org.jetbrains.idea.maven.project; import com.intellij.openapi.project.Project; -import org.jetbrains.idea.maven.embedder.MavenConsole; import org.jetbrains.idea.maven.utils.MavenProcessCanceledException; import org.jetbrains.idea.maven.utils.MavenProgressIndicator; public class MavenProjectsProcessorFoldersResolvingTask extends MavenProjectsProcessorBasicTask { - private final MavenGeneralSettings myGeneralSettings; private final MavenImportingSettings myImportingSettings; private final Object myMessage; public MavenProjectsProcessorFoldersResolvingTask(MavenProject project, - MavenGeneralSettings generalSettings, MavenImportingSettings importingSettings, MavenProjectsTree tree, Object message) { super(project, tree); - myGeneralSettings = generalSettings; myImportingSettings = importingSettings; myMessage = message; } public void perform(Project project, MavenEmbeddersManager embeddersManager, MavenConsole console, MavenProgressIndicator indicator) throws MavenProcessCanceledException { - myTree.resolveFolders(myMavenProject, myGeneralSettings, myImportingSettings, embeddersManager, console, indicator, myMessage); + myTree.resolveFolders(myMavenProject, myImportingSettings, embeddersManager, console, indicator, myMessage); } } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsProcessorPluginsResolvingTask.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsProcessorPluginsResolvingTask.java index e62349522b6f..32d79f792ee3 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsProcessorPluginsResolvingTask.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsProcessorPluginsResolvingTask.java @@ -16,15 +16,15 @@ package org.jetbrains.idea.maven.project; import com.intellij.openapi.project.Project; -import org.jetbrains.idea.maven.embedder.MavenConsole; -import org.jetbrains.idea.maven.utils.MavenProgressIndicator; +import org.jetbrains.idea.maven.facade.NativeMavenProjectHolder; import org.jetbrains.idea.maven.utils.MavenProcessCanceledException; +import org.jetbrains.idea.maven.utils.MavenProgressIndicator; public class MavenProjectsProcessorPluginsResolvingTask extends MavenProjectsProcessorBasicTask { - private final org.apache.maven.project.MavenProject myNativeMavenProject; + private final NativeMavenProjectHolder myNativeMavenProject; public MavenProjectsProcessorPluginsResolvingTask(MavenProject project, - org.apache.maven.project.MavenProject nativeMavenProject, + NativeMavenProjectHolder nativeMavenProject, MavenProjectsTree tree) { super(project, tree); myNativeMavenProject = nativeMavenProject; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsProcessorReadingTask.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsProcessorReadingTask.java index 01b229f9501b..d896351bc87c 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsProcessorReadingTask.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsProcessorReadingTask.java @@ -17,7 +17,6 @@ package org.jetbrains.idea.maven.project; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; -import org.jetbrains.idea.maven.embedder.MavenConsole; import org.jetbrains.idea.maven.utils.MavenProcessCanceledException; import org.jetbrains.idea.maven.utils.MavenProgressIndicator; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsProcessorResolvingTask.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsProcessorResolvingTask.java index de1e98c1ef5a..08a45a7ce1ff 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsProcessorResolvingTask.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsProcessorResolvingTask.java @@ -16,7 +16,6 @@ package org.jetbrains.idea.maven.project; import com.intellij.openapi.project.Project; -import org.jetbrains.idea.maven.embedder.MavenConsole; import org.jetbrains.idea.maven.utils.MavenProcessCanceledException; import org.jetbrains.idea.maven.utils.MavenProgressIndicator; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsProcessorTask.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsProcessorTask.java index 7fbe3b0592cf..65f43c85beae 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsProcessorTask.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsProcessorTask.java @@ -16,7 +16,6 @@ package org.jetbrains.idea.maven.project; import com.intellij.openapi.project.Project; -import org.jetbrains.idea.maven.embedder.MavenConsole; import org.jetbrains.idea.maven.utils.MavenProcessCanceledException; import org.jetbrains.idea.maven.utils.MavenProgressIndicator; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsTree.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsTree.java index 5cc178611a5d..8bfb6b6ea0c3 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsTree.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsTree.java @@ -18,6 +18,7 @@ package org.jetbrains.idea.maven.project; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.LocalFileSystem; @@ -29,11 +30,11 @@ import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.Stack; import gnu.trove.THashMap; import gnu.trove.THashSet; -import org.apache.maven.artifact.Artifact; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; -import org.jetbrains.idea.maven.embedder.MavenConsole; -import org.jetbrains.idea.maven.embedder.MavenEmbedderWrapper; +import org.jetbrains.idea.maven.facade.MavenEmbedderWrapper; +import org.jetbrains.idea.maven.facade.NativeMavenProjectHolder; +import org.jetbrains.idea.maven.model.*; import org.jetbrains.idea.maven.utils.*; import java.io.*; @@ -64,7 +65,7 @@ public class MavenProjectsTree { private final Map myTimestamps = new THashMap(); private final Map myVirtualFileToProjectMapping = new THashMap(); private final Map myMavenIdToProjectMapping = new THashMap(); - private final Map myMavenIdToFileMapping = new THashMap(); + private final Map myMavenIdToFileMapping = new THashMap(); private final Map> myAggregatorToModuleMapping = new THashMap>(); private final Map myModuleToAggregatorMapping = new THashMap(); @@ -138,7 +139,7 @@ public class MavenProjectsTree { tree.myTimestamps.put(project, timestamp); tree.myVirtualFileToProjectMapping.put(project.getFile(), project); tree.myMavenIdToProjectMapping.put(project.getMavenId(), project); - tree.myMavenIdToFileMapping.put(project.getMavenId(), project.getFile()); + tree.myMavenIdToFileMapping.put(project.getMavenId(), new File(project.getFile().getPath())); tree.myAggregatorToModuleMapping.put(project, modules); for (MavenProject eachModule : modules) { tree.myModuleToAggregatorMapping.put(eachModule, project); @@ -387,8 +388,8 @@ public class MavenProjectsTree { return Pair.create(available, active); } - public Collection> getProfilesWithStates() { - Collection> result = new ArrayListSet>(); + public Collection> getProfilesWithStates() { + Collection> result = new ArrayListSet>(); Pair, Collection> profiles = getAvailableAndActiveProfiles(true, true); Collection available = profiles.first; @@ -396,11 +397,11 @@ public class MavenProjectsTree { Collection explicitProfiles = getExplicitProfiles(); for (String each : available) { - MavenProfileState state = MavenProfileState.NONE; + MavenProfileKind state = MavenProfileKind.NONE; if (explicitProfiles.contains(each)) { - state = MavenProfileState.EXPLICIT; + state = MavenProfileKind.EXPLICIT; } - else if (active.contains(each)) state = MavenProfileState.IMPLICIT; + else if (active.contains(each)) state = MavenProfileKind.IMPLICIT; result.add(Pair.create(each, state)); } return result; @@ -541,7 +542,7 @@ public class MavenProjectsTree { try { myVirtualFileToProjectMapping.put(mavenProject.getFile(), mavenProject); myMavenIdToProjectMapping.put(mavenProject.getMavenId(), mavenProject); - myMavenIdToFileMapping.put(mavenProject.getMavenId(), mavenProject.getFile()); + myMavenIdToFileMapping.put(mavenProject.getMavenId(), new File(mavenProject.getFile().getPath())); } finally { writeUnlock(); @@ -891,14 +892,10 @@ public class MavenProjectsTree { return findProject(artifact.getMavenId()); } - public MavenProject findProject(Artifact artifact) { - return findProject(new MavenId(artifact)); - } - - private Map getProjectIdToFileMapping() { + private Map getProjectIdToFileMapping() { readLock(); try { - return new THashMap(myMavenIdToFileMapping); + return new THashMap(myMavenIdToFileMapping); } finally { readUnlock(); @@ -990,17 +987,17 @@ public class MavenProjectsTree { MavenConsole console, MavenProgressIndicator process, Object message) throws MavenProcessCanceledException { - MavenEmbedderWrapper embedder = embeddersManager.getEmbedder(MavenEmbeddersManager.EmbedderKind.FOR_DEPENDENCIES_RESOLVE); + MavenEmbedderWrapper embedder = embeddersManager.getEmbedder(MavenEmbeddersManager.FOR_DEPENDENCIES_RESOLVE); embedder.customizeForResolve(getProjectIdToFileMapping(), console, process); try { process.checkCanceled(); process.setText(ProjectBundle.message("maven.resolving.pom", mavenProject.getDisplayName())); process.setText2(""); - Pair resolveResult = mavenProject.resolve(generalSettings, - embedder, - new MavenProjectReader(), - myProjectLocator); + Pair resolveResult = mavenProject.resolve(generalSettings, + embedder, + new MavenProjectReader(), + myProjectLocator); fireProjectResolved(Pair.create(mavenProject, resolveResult.first), resolveResult.second, message); } @@ -1010,11 +1007,11 @@ public class MavenProjectsTree { } public void resolvePlugins(MavenProject mavenProject, - org.apache.maven.project.MavenProject nativeMavenProject, + NativeMavenProjectHolder nativeMavenProject, MavenEmbeddersManager embeddersManager, MavenConsole console, MavenProgressIndicator process) throws MavenProcessCanceledException { - MavenEmbedderWrapper embedder = embeddersManager.getEmbedder(MavenEmbeddersManager.EmbedderKind.FOR_PLUGINS_RESOLVE); + MavenEmbedderWrapper embedder = embeddersManager.getEmbedder(MavenEmbeddersManager.FOR_PLUGINS_RESOLVE); embedder.customizeForResolve(console, process); embedder.clearCachesFor(mavenProject.getMavenId()); @@ -1022,7 +1019,7 @@ public class MavenProjectsTree { for (MavenPlugin each : mavenProject.getDeclaredPlugins()) { process.checkCanceled(); process.setText(ProjectBundle.message("maven.downloading.pom.plugins", mavenProject.getDisplayName())); - embedder.resolvePlugin(each, nativeMavenProject, false); + embedder.resolvePlugin(each, mavenProject.getRemoteRepositories(), nativeMavenProject, false); } mavenProject.resetCache(); firePluginsResolved(mavenProject); @@ -1033,7 +1030,6 @@ public class MavenProjectsTree { } public void resolveFolders(final MavenProject mavenProject, - final MavenGeneralSettings generalSettings, final MavenImportingSettings importingSettings, final MavenEmbeddersManager embeddersManager, final MavenConsole console, @@ -1041,7 +1037,7 @@ public class MavenProjectsTree { final Object message) throws MavenProcessCanceledException { executeWithEmbedder(mavenProject, embeddersManager, - MavenEmbeddersManager.EmbedderKind.FOR_FOLDERS_RESOLVE, + MavenEmbeddersManager.FOR_FOLDERS_RESOLVE, console, process, new EmbedderTask() { @@ -1051,7 +1047,6 @@ public class MavenProjectsTree { process.setText2(""); Pair resolveResult = mavenProject.resolveFolders(embedder, - generalSettings, importingSettings, new MavenProjectReader(), console); @@ -1073,7 +1068,7 @@ public class MavenProjectsTree { MavenConsole console, MavenProgressIndicator process) throws MavenProcessCanceledException { - MavenEmbedderWrapper embedder = embeddersManager.getEmbedder(MavenEmbeddersManager.EmbedderKind.FOR_DOWNLOAD); + MavenEmbedderWrapper embedder = embeddersManager.getEmbedder(MavenEmbeddersManager.FOR_DOWNLOAD); embedder.customizeForResolve(console, process); try { @@ -1095,12 +1090,13 @@ public class MavenProjectsTree { MavenEmbeddersManager embeddersManager, MavenConsole console, MavenProgressIndicator process) throws MavenProcessCanceledException { - MavenEmbedderWrapper embedder = embeddersManager.getEmbedder(MavenEmbeddersManager.EmbedderKind.FOR_DOWNLOAD); + MavenEmbedderWrapper embedder = embeddersManager.getEmbedder(MavenEmbeddersManager.FOR_DOWNLOAD); embedder.customizeForResolve(console, process); try { - MavenArtifact result = embedder.resolve(id, MavenConstants.TYPE_JAR, null, mavenProject.getRemoteRepositories()); - result.setScope(Artifact.SCOPE_COMPILE); + MavenArtifact result = embedder.resolve(new MavenArtifactInfo(id, MavenConstants.TYPE_JAR, null), + mavenProject.getRemoteRepositories()); + result.setScope(MavenConstants.SCOPE_COMPILE); return result; } finally { @@ -1110,7 +1106,7 @@ public class MavenProjectsTree { public void executeWithEmbedder(MavenProject mavenProject, MavenEmbeddersManager embeddersManager, - MavenEmbeddersManager.EmbedderKind embedderKind, + Key embedderKind, MavenConsole console, MavenProgressIndicator process, EmbedderTask task) throws MavenProcessCanceledException { @@ -1183,7 +1179,7 @@ public class MavenProjectsTree { } private void fireProjectResolved(Pair projectWithChanges, - org.apache.maven.project.MavenProject nativeMavenProject, + NativeMavenProjectHolder nativeMavenProject, Object message) { for (Listener each : myListeners) { each.projectResolved(projectWithChanges, nativeMavenProject, message); @@ -1360,7 +1356,7 @@ public class MavenProjectsTree { void projectsUpdated(List> updated, List deleted, Object message); void projectResolved(Pair projectWithChanges, - org.apache.maven.project.MavenProject nativeMavenProject, + @Nullable NativeMavenProjectHolder nativeMavenProject, Object message); void pluginsResolved(MavenProject project); @@ -1381,7 +1377,7 @@ public class MavenProjectsTree { } public void projectResolved(Pair projectWithChanges, - org.apache.maven.project.MavenProject nativeMavenProject, + @Nullable NativeMavenProjectHolder nativeMavenProject, Object message) { } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenRemoteRepository.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenRemoteRepository.java deleted file mode 100644 index 1c530bbfcf34..000000000000 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenRemoteRepository.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.idea.maven.project; - -import org.apache.maven.model.Repository; -import org.apache.maven.model.RepositoryPolicy; - -import java.io.Serializable; - -public class MavenRemoteRepository implements Serializable { - private String myId; - private String myName; - private String myUrl; - private String myLayout; - private Policy myReleasesPolicy; - private Policy mySnapshotsPolicy; - - protected MavenRemoteRepository() { - } - - public MavenRemoteRepository(Repository repository) { - myId = repository.getId(); - myName = repository.getName(); - myUrl = repository.getUrl(); - myLayout = repository.getLayout(); - - if (repository.getReleases()!= null) myReleasesPolicy = new Policy(repository.getReleases()); - if (repository.getSnapshots() != null) mySnapshotsPolicy = new Policy(repository.getSnapshots()); - } - - public String getId() { - return myId; - } - - public String getName() { - return myName; - } - - public String getUrl() { - return myUrl; - } - - public String getLayout() { - return myLayout; - } - - public Policy getReleasesPolicy() { - return myReleasesPolicy; - } - - public Policy getSnapshotsPolicy() { - return mySnapshotsPolicy; - } - - public Repository toRepository() { - Repository result = new Repository(); - result.setId(myId); - result.setName(myName); - result.setUrl(myUrl); - result.setLayout(myLayout); - - if (myReleasesPolicy != null) result.setReleases(myReleasesPolicy.toRepositoryPolicy()); - if (mySnapshotsPolicy != null) result.setSnapshots(mySnapshotsPolicy.toRepositoryPolicy()); - - return result; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - MavenRemoteRepository that = (MavenRemoteRepository)o; - - if (myId != null ? !myId.equals(that.myId) : that.myId != null) return false; - - return true; - } - - @Override - public int hashCode() { - return myId != null ? myId.hashCode() : 0; - } - - public static class Policy implements Serializable { - private boolean myEnabled; - private String myUpdatePolicy; - private String myChecksumPolicy; - - protected Policy() { - } - - public Policy(RepositoryPolicy policy) { - myEnabled = policy.isEnabled(); - myUpdatePolicy = policy.getUpdatePolicy(); - myChecksumPolicy = policy.getChecksumPolicy(); - } - - public boolean isEnabled() { - return myEnabled; - } - - public String getUpdatePolicy() { - return myUpdatePolicy; - } - - public String getChecksumPolicy() { - return myChecksumPolicy; - } - - public RepositoryPolicy toRepositoryPolicy() { - RepositoryPolicy result =new RepositoryPolicy(); - result.setEnabled(myEnabled); - result.setUpdatePolicy(myUpdatePolicy); - result.setChecksumPolicy(myChecksumPolicy); - return result; - } - } -} diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/DownloadSelectedSourcesAndDocsAction.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/DownloadSelectedSourcesAndDocsAction.java index 33fb94ef3d27..696dd13120be 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/DownloadSelectedSourcesAndDocsAction.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/DownloadSelectedSourcesAndDocsAction.java @@ -16,12 +16,11 @@ package org.jetbrains.idea.maven.project.actions; import com.intellij.openapi.actionSystem.AnActionEvent; -import org.jetbrains.idea.maven.project.MavenArtifact; +import org.jetbrains.idea.maven.model.MavenArtifact; import org.jetbrains.idea.maven.project.MavenProject; import org.jetbrains.idea.maven.project.MavenProjectsManager; import org.jetbrains.idea.maven.utils.MavenDataKeys; -import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenKeymapExtension.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenKeymapExtension.java index 015d402bab32..8dd291d5e59b 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenKeymapExtension.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenKeymapExtension.java @@ -23,10 +23,11 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Pair; import org.jetbrains.annotations.TestOnly; -import org.jetbrains.idea.maven.embedder.MavenEmbedderWrapper; import org.jetbrains.idea.maven.execution.MavenRunConfigurationType; import org.jetbrains.idea.maven.execution.MavenRunnerParameters; -import org.jetbrains.idea.maven.project.MavenPlugin; +import org.jetbrains.idea.maven.facade.MavenEmbedderWrapper; +import org.jetbrains.idea.maven.model.MavenConstants; +import org.jetbrains.idea.maven.model.MavenPlugin; import org.jetbrains.idea.maven.project.MavenProject; import org.jetbrains.idea.maven.project.MavenProjectsManager; import org.jetbrains.idea.maven.utils.MavenArtifactUtil; @@ -142,7 +143,7 @@ public class MavenKeymapExtension implements KeymapExtension { private static List collectGoals(MavenProject project) { LinkedHashSet result = new LinkedHashSet(); // may contains similar plugins or somethig - result.addAll(MavenEmbedderWrapper.PHASES); + result.addAll(MavenConstants.PHASES); for (MavenPlugin each : project.getDeclaredPlugins()) { collectGoals(project.getLocalRepository(), each, result); diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenShortcutsManager.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenShortcutsManager.java index e670fe2ff671..4a0d284b1f23 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenShortcutsManager.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenShortcutsManager.java @@ -23,8 +23,8 @@ import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.keymap.ex.KeymapManagerEx; import com.intellij.openapi.project.DumbAwareRunnable; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.io.FileUtil; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.update.MergingUpdateQueue; @@ -32,9 +32,12 @@ import com.intellij.util.ui.update.Update; import gnu.trove.THashMap; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; -import org.jetbrains.idea.maven.project.*; import org.jetbrains.idea.maven.execution.MavenRunner; +import org.jetbrains.idea.maven.facade.NativeMavenProjectHolder; import org.jetbrains.idea.maven.project.MavenProject; +import org.jetbrains.idea.maven.project.MavenProjectChanges; +import org.jetbrains.idea.maven.project.MavenProjectsManager; +import org.jetbrains.idea.maven.project.MavenProjectsTree; import org.jetbrains.idea.maven.utils.MavenMergingUpdateQueue; import org.jetbrains.idea.maven.utils.MavenUtil; import org.jetbrains.idea.maven.utils.SimpleProjectComponent; @@ -195,7 +198,7 @@ public class MavenShortcutsManager extends SimpleProjectComponent { @Override public void projectResolved(Pair projectWithChanges, - org.apache.maven.project.MavenProject nativeMavenProject, + NativeMavenProjectHolder nativeMavenProject, Object message) { scheduleKeymapUpdate(Collections.singletonList(projectWithChanges.first), true); } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/FileFinder.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/FileFinder.java index 0e968753e55e..da81dba739fe 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/FileFinder.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/FileFinder.java @@ -20,7 +20,7 @@ import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.util.Computable; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; -import org.jetbrains.idea.maven.utils.MavenConstants; +import org.jetbrains.idea.maven.model.MavenConstants; import java.util.List; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenArtifactUtil.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenArtifactUtil.java index 5a269c709a6a..fdac7e4a6313 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenArtifactUtil.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenArtifactUtil.java @@ -21,7 +21,7 @@ import gnu.trove.THashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.maven.indices.IndicesBundle; -import org.jetbrains.idea.maven.project.MavenId; +import org.jetbrains.idea.maven.model.MavenId; import java.io.File; import java.io.IOException; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenAttachSourcesProvider.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenAttachSourcesProvider.java index 49467a4918ba..ab0ecace6d5f 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenAttachSourcesProvider.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenAttachSourcesProvider.java @@ -28,6 +28,8 @@ import com.intellij.openapi.util.AsyncResult; import com.intellij.psi.PsiFile; import gnu.trove.THashSet; import org.jetbrains.idea.maven.importing.MavenRootModelAdapter; +import org.jetbrains.idea.maven.model.MavenArtifact; +import org.jetbrains.idea.maven.model.MavenId; import org.jetbrains.idea.maven.project.*; import javax.swing.*; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenDataKeys.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenDataKeys.java index ee25e4f33ecc..70ea789a65aa 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenDataKeys.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenDataKeys.java @@ -16,7 +16,7 @@ package org.jetbrains.idea.maven.utils; import com.intellij.openapi.actionSystem.DataKey; -import org.jetbrains.idea.maven.project.MavenArtifact; +import org.jetbrains.idea.maven.model.MavenArtifact; import javax.swing.*; import java.util.Collection; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenEnvironmentRegistrar.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenEnvironmentRegistrar.java index 9fea46867b53..134029336e6e 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenEnvironmentRegistrar.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenEnvironmentRegistrar.java @@ -22,7 +22,7 @@ import com.intellij.openapi.application.PathMacros; import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.fileTypes.FileTypeManager; import org.jetbrains.annotations.NotNull; -import org.jetbrains.idea.maven.embedder.MavenEmbedderUtilEx; +import org.jetbrains.idea.maven.model.MavenConstants; import java.io.File; @@ -46,7 +46,7 @@ public class MavenEnvironmentRegistrar implements ApplicationComponent { } private void registerPathVariable() { - File repository = MavenEmbedderUtilEx.resolveLocalRepository(null, null, null); + File repository = MavenUtil.resolveLocalRepository(null, null, null); PathMacros macros = PathMacros.getInstance(); for (String each : macros.getAllMacroNames()) { diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenPluginInfo.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenPluginInfo.java index 662f836c7c7b..e829725506d7 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenPluginInfo.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenPluginInfo.java @@ -16,9 +16,9 @@ package org.jetbrains.idea.maven.utils; import org.jdom.Element; -import org.jetbrains.idea.maven.project.MavenId; +import org.jetbrains.idea.maven.model.MavenId; -import static org.jetbrains.idea.maven.project.MavenId.append; +import static org.jetbrains.idea.maven.model.MavenId.append; import java.util.Collection; import java.util.LinkedHashMap; @@ -35,7 +35,7 @@ public class MavenPluginInfo { Element plugin = MavenJDOMUtil.read(text, null); myGroupId = MavenJDOMUtil.findChildValueByPath(plugin, "groupId", MavenId.UNKNOWN_VALUE); - myArtifactId = MavenJDOMUtil.findChildValueByPath(plugin, "artifactId",MavenId.UNKNOWN_VALUE); + myArtifactId = MavenJDOMUtil.findChildValueByPath(plugin, "artifactId", MavenId.UNKNOWN_VALUE); myVersion = MavenJDOMUtil.findChildValueByPath(plugin, "version", MavenId.UNKNOWN_VALUE); myGoalPrefix = MavenJDOMUtil.findChildValueByPath(plugin, "goalPrefix", "unknown"); diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenRehighlighter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenRehighlighter.java index f319b0cf4f8d..f10ae32a24fd 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenRehighlighter.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenRehighlighter.java @@ -21,12 +21,11 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; import com.intellij.psi.PsiManager; import com.intellij.psi.impl.PsiModificationTrackerImpl; +import org.jetbrains.idea.maven.facade.NativeMavenProjectHolder; import org.jetbrains.idea.maven.project.MavenProject; import org.jetbrains.idea.maven.project.MavenProjectChanges; import org.jetbrains.idea.maven.project.MavenProjectsManager; import org.jetbrains.idea.maven.project.MavenProjectsTree; -import org.jetbrains.idea.maven.utils.MavenUtil; -import org.jetbrains.idea.maven.utils.SimpleProjectComponent; import java.util.List; @@ -51,7 +50,7 @@ public class MavenRehighlighter extends SimpleProjectComponent { } public void projectResolved(Pair projectWithChanges, - org.apache.maven.project.MavenProject nativeMavenProject, + NativeMavenProjectHolder nativeMavenProject, Object message) { rehighlight(myProject); } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenUIUtil.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenUIUtil.java index 41db66be556a..0fb0d4f53d39 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenUIUtil.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenUIUtil.java @@ -30,7 +30,9 @@ import javax.swing.tree.TreeCellRenderer; import javax.swing.tree.TreePath; import java.awt.*; import java.awt.event.*; -import java.util.*; +import java.util.Collection; +import java.util.Comparator; +import java.util.TreeSet; public class MavenUIUtil { public static void executeAction(final String actionId, final InputEvent e) { @@ -38,7 +40,8 @@ public class MavenUIUtil { final AnAction action = actionManager.getAction(actionId); if (action != null) { final Presentation presentation = new Presentation(); - final AnActionEvent event = new AnActionEvent(e, DataManager.getInstance().getDataContext(e.getComponent()), "", presentation, actionManager, 0); + final AnActionEvent event = + new AnActionEvent(e, DataManager.getInstance().getDataContext(e.getComponent()), "", presentation, actionManager, 0); action.update(event); if (presentation.isEnabled()) { action.actionPerformed(event); @@ -46,13 +49,13 @@ public class MavenUIUtil { } } - public static void setElements(ElementsChooser chooser, Collection all, Collection selected, Comparator comparator){ + public static void setElements(ElementsChooser chooser, Collection all, Collection selected, Comparator comparator) { java.util.List selection = chooser.getSelectedElements(); chooser.clear(); Collection sorted = new TreeSet(comparator); sorted.addAll(all); for (E element : sorted) { - chooser.addElement( element, selected.contains(element)); + chooser.addElement(element, selected.contains(element)); } chooser.selectElements(selection); } @@ -86,7 +89,7 @@ public class MavenUIUtil { panel.setForeground(foreground); CheckBoxState state = handler.getState(userObject); - checkbox.setSelected(state != CheckBoxState.UNCHECKED); + checkbox.setSelected(state != CheckBoxState.UNCHECKED); checkbox.setEnabled(state != CheckBoxState.PARTIAL); checkbox.setBackground(UIUtil.getTreeTextBackground()); checkbox.setForeground(foreground); diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenUtil.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenUtil.java index 478a4d484da3..4a09a8aaa039 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenUtil.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenUtil.java @@ -39,24 +39,23 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.startup.StartupManager; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.JarFileSystem; +import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Function; -import com.intellij.util.ReflectionUtil; import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashSet; -import org.apache.commons.beanutils.BeanUtils; -import org.apache.maven.model.Model; -import org.codehaus.plexus.util.xml.Xpp3Dom; import org.jetbrains.annotations.NotNull; -import org.jetbrains.idea.maven.project.MavenId; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.maven.facade.MavenFacadeUtil; +import org.jetbrains.idea.maven.model.MavenConstants; +import org.jetbrains.idea.maven.model.MavenId; import org.jetbrains.idea.maven.project.MavenProject; import java.io.File; import java.io.IOException; -import java.io.Serializable; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; import java.net.URL; import java.util.*; import java.util.concurrent.ExecutionException; @@ -67,6 +66,17 @@ import java.util.regex.PatternSyntaxException; public class MavenUtil { public static final String MAVEN_NOTIFICATION_GROUP = "Maven"; + public static final String SETTINGS_XML = "settings.xml"; + public static final String DOT_M2_DIR = ".m2"; + public static final String PROP_USER_HOME = "user.home"; + public static final String ENV_M2_HOME = "M2_HOME"; + public static final String M2_DIR = "m2"; + public static final String BIN_DIR = "bin"; + public static final String CONF_DIR = "conf"; + public static final String M2_CONF_FILE = "m2.conf"; + public static final String REPOSITORY_DIR = "repository"; + public static final String LIB_DIR = "lib"; + public static final String SUPER_POM_PATH = "org/apache/maven/project/" + MavenConstants.SUPER_POM_XML; public static void invokeLater(Project p, Runnable r) { invokeLater(p, ModalityState.defaultModalityState(), r); @@ -342,56 +352,6 @@ public class MavenUtil { return true; } - public static T cloneObject(T object) { - try { - return (T)BeanUtils.cloneBean(object); - } - catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - catch (InstantiationException e) { - throw new RuntimeException(e); - } - catch (InvocationTargetException e) { - throw new RuntimeException(e); - } - catch (NoSuchMethodException e) { - throw new RuntimeException(e); - } - } - - public static void stripDown(Object object) { - try { - for (Field each : ReflectionUtil.collectFields(object.getClass())) { - Class type = each.getType(); - each.setAccessible(true); - Object value = each.get(object); - if (shouldStrip(value)) { - each.set(object, null); - } - else { - if (value != null) { - Package pack = type.getPackage(); - if (pack != null && Model.class.getPackage().getName().equals(pack.getName())) { - stripDown(value); - } - } - } - } - } - catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - } - - public static boolean shouldStrip(Object value) { - if (value == null) return false; - return value.getClass().isArray() - || value instanceof Collection - || value instanceof Map - || value instanceof Xpp3Dom; - } - public static void run(Project project, String title, final MavenTask task) throws MavenProcessCanceledException { final Exception[] canceledEx = new Exception[1]; @@ -469,6 +429,160 @@ public class MavenUtil { } } + @Nullable + public static File resolveMavenHomeDirectory(@Nullable String overrideMavenHome) { + if (!isEmptyOrSpaces(overrideMavenHome)) { + return new File(overrideMavenHome); + } + + String m2home = System.getenv(ENV_M2_HOME); + if (!isEmptyOrSpaces(m2home)) { + final File homeFromEnv = new File(m2home); + if (isValidMavenHome(homeFromEnv)) { + return homeFromEnv; + } + } + + String userHome = System.getProperty(PROP_USER_HOME); + if (!isEmptyOrSpaces(userHome)) { + final File underUserHome = new File(userHome, M2_DIR); + if (isValidMavenHome(underUserHome)) { + return underUserHome; + } + } + + return null; + } + + public static boolean isEmptyOrSpaces(@Nullable String str) { + return str == null || str.length() == 0 || str.trim().length() == 0; + } + + public static boolean isValidMavenHome(File home) { + return getMavenConfFile(home).exists(); + } + + public static File getMavenConfFile(File mavenHome) { + return new File(new File(mavenHome, BIN_DIR), M2_CONF_FILE); + } + + @Nullable + public static File resolveGlobalSettingsFile(@Nullable String overriddenMavenHome) { + File directory = resolveMavenHomeDirectory(overriddenMavenHome); + if (directory == null) return null; + + return new File(new File(directory, CONF_DIR), SETTINGS_XML); + } + + @NotNull + public static File resolveUserSettingsFile(@Nullable String overriddenUserSettingsFile) { + if (!isEmptyOrSpaces(overriddenUserSettingsFile)) return new File(overriddenUserSettingsFile); + return new File(resolveM2Dir(), SETTINGS_XML); + } + + @NotNull + public static File resolveM2Dir() { + return new File(System.getProperty(PROP_USER_HOME), DOT_M2_DIR); + } + + @NotNull + public static File resolveLocalRepository(@Nullable String overridenLocalRepository, + @Nullable String overridenMavenHome, + @Nullable String overriddenUserSettingsFile) { + File result = null; + if (!isEmptyOrSpaces(overridenLocalRepository)) result = new File(overridenLocalRepository); + if (result == null) { + result = doResolveLocalRepository(resolveUserSettingsFile(overriddenUserSettingsFile), + resolveGlobalSettingsFile(overridenMavenHome)); + } + try { + return result.getCanonicalFile(); + } + catch (IOException e) { + return result; + } + } + + @NotNull + public static File doResolveLocalRepository(@Nullable File userSettingsFile, @Nullable File globalSettingsFile) { + if (userSettingsFile != null) { + final String fromUserSettings = getRepositoryFromSettings(userSettingsFile); + if (!StringUtil.isEmpty(fromUserSettings)) { + return new File(fromUserSettings); + } + } + + if (globalSettingsFile != null) { + final String fromGlobalSettings = getRepositoryFromSettings(globalSettingsFile); + if (!StringUtil.isEmpty(fromGlobalSettings)) { + return new File(fromGlobalSettings); + } + } + + return new File(resolveM2Dir(), REPOSITORY_DIR); + } + + @Nullable + public static String getRepositoryFromSettings(final File file) { + try { + byte[] bytes = FileUtil.loadFileBytes(file); + return expandProperties(MavenJDOMUtil.findChildValueByPath(MavenJDOMUtil.read(bytes, null), "localRepository", null)); + } + catch (IOException e) { + return null; + } + } + + public static String expandProperties(String text) { + if (StringUtil.isEmptyOrSpaces(text)) return text; + Properties props = MavenFacadeUtil.collectSystemProperties(); + for (Map.Entry each : props.entrySet()) { + text = text.replace("${" + each.getKey() + "}", (CharSequence)each.getValue()); + } + return text; + } + + @NotNull + public static VirtualFile resolveSuperPomFile(@Nullable File mavenHome) { + VirtualFile result = doResolveSuperPomFile(mavenHome); + if (result == null) { + URL resource = MavenFacadeUtil.class.getResource("/" + SUPER_POM_PATH); + return VfsUtil.findFileByURL(resource); + } + return result; + } + + @Nullable + public static VirtualFile doResolveSuperPomFile(@Nullable File mavenHome) { + File lib = resolveMavenLib(mavenHome); + if (lib == null) return null; + + VirtualFile file = LocalFileSystem.getInstance().findFileByIoFile(lib); + if (file == null) return null; + + VirtualFile root = JarFileSystem.getInstance().getJarRootForLocalFile(file); + if (root == null) return null; + + return root.findFileByRelativePath(SUPER_POM_PATH); + } + + @Nullable + public static File resolveMavenLib(@Nullable File mavenHome) { + if (mavenHome == null) return null; + + File libs = new File(mavenHome, LIB_DIR); + File[] files = libs.listFiles(); + if (files != null) { + Pattern pattern = Pattern.compile("maven-\\d+\\.\\d+\\.\\d+-uber\\.jar"); + for (File each : files) { + if (pattern.matcher(each.getName()).matches()) { + return each; + } + } + } + return null; + } + public interface MavenTaskHandler { void waitFor(); } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/RepositoryAttachDialog.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/RepositoryAttachDialog.java index 91820747dfcb..5760713137b4 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/RepositoryAttachDialog.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/RepositoryAttachDialog.java @@ -41,9 +41,8 @@ import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.AsyncProcessIcon; import gnu.trove.THashMap; import org.jetbrains.annotations.NotNull; -import org.jetbrains.idea.maven.facade.nexus.ArtifactType; -import org.jetbrains.idea.maven.facade.nexus.RepositoryType; -import org.jetbrains.idea.maven.facade.remote.MavenFacade; +import org.jetbrains.idea.maven.model.MavenArtifactInfo; +import org.jetbrains.idea.maven.model.MavenRepositoryInfo; import javax.swing.*; import javax.swing.event.DocumentEvent; @@ -63,8 +62,8 @@ public class RepositoryAttachDialog extends DialogWrapper { private final Project myProject; private final boolean myManaged; private final AsyncProcessIcon myProgressIcon; - private final THashMap myCoordinates = new THashMap(); - private final Map myRepositories = new TreeMap(); + private final THashMap myCoordinates = new THashMap(); + private final Map myRepositories = new TreeMap(); private final ArrayList myShownItems = new ArrayList(); private final JComboBox myCombobox = new JComboBox(new CollectionComboBoxModel(myShownItems, null)); @@ -171,15 +170,16 @@ public class RepositoryAttachDialog extends DialogWrapper { if (myProgressIcon.isVisible()) return false; myProgressIcon.setVisible(true); myProgressIcon.resume(); - RepositoryAttachHandler.searchArtifacts(myProject, text, new PairProcessor, Boolean>() { - public boolean process(Collection artifactTypes, Boolean tooMany) { + RepositoryAttachHandler.searchArtifacts(myProject, text, new PairProcessor, Boolean>() { + public boolean process(Collection artifacts, Boolean tooMany) { if (myProgressIcon.isDisposed()) return true; myProgressIcon.suspend(); myProgressIcon.setVisible(false); final int prevSize = myCoordinates.size(); - for (ArtifactType artifactType : artifactTypes) { - myCoordinates.put(artifactType.getGroupId() + ":" + artifactType.getArtifactId() + ":" + artifactType.getVersion(), artifactType); + for (MavenArtifactInfo each : artifacts) { + myCoordinates.put(each.getGroupId() + ":" + each.getArtifactId() + ":" + each.getVersion(), each); } + myRepositoryUrl.setModel(new CollectionComboBoxModel(new ArrayList(myRepositories.keySet()), myRepositoryUrl.getEditor().getItem())); if (Boolean.TRUE.equals(tooMany)) { final Point point = new Point(myCombobox.getWidth() / 2, 0); @@ -190,13 +190,11 @@ public class RepositoryAttachDialog extends DialogWrapper { updateComboboxSelection(prevSize != myCoordinates.size()); return true; } - }, new Processor>() { - public boolean process(Collection repositoryTypes) { - for (RepositoryType repositoryType : repositoryTypes) { - if (!myRepositories.containsKey(repositoryType.getContentResourceURI())) { - myRepositories.put( - repositoryType.getContentResourceURI(), - new MavenFacade.Repository(repositoryType.getId(), repositoryType.getContentResourceURI(), "default")); + }, new Processor>() { + public boolean process(Collection repos) { + for (MavenRepositoryInfo each : repos) { + if (!myRepositories.containsKey(each.getUrl())) { + myRepositories.put(each.getUrl(), each); } } return true; @@ -274,7 +272,7 @@ public class RepositoryAttachDialog extends DialogWrapper { final LabeledComponent repository = new LabeledComponent(); repository.getLabel().setText("Repository URL to Download From:"); myRepositories.put(DEFAULT_REPOSITORY, null); - for (MavenFacade.Repository repo : RepositoryAttachHandler.getDefaultRepositories()) { + for (MavenRepositoryInfo repo : RepositoryAttachHandler.getDefaultRepositories()) { myRepositories.put(repo.getUrl(), repo); } myRepositoryUrl = new JComboBox(new CollectionComboBoxModel(new ArrayList(myRepositories.keySet()), DEFAULT_REPOSITORY)); @@ -324,19 +322,29 @@ public class RepositoryAttachDialog extends DialogWrapper { } @NotNull - public List getRepositories() { + public List getRepositories() { final String selectedRepository = (String)myRepositoryUrl.getEditor().getItem(); if (StringUtil.isNotEmpty(selectedRepository) && !DEFAULT_REPOSITORY.equals(selectedRepository) && !myRepositories.containsKey(selectedRepository)) { - return Collections.singletonList(new MavenFacade.Repository("custom", selectedRepository, "default")); + return Collections.singletonList(new MavenRepositoryInfo("custom", null, selectedRepository)); } else { - final ArtifactType artifact = myCoordinates.get(getCoordinateText()); - final MavenFacade.Repository repository = - artifact != null && artifact.getResourceUri() != null ? myRepositories.get(artifact.getResourceUri()) : null; + final MavenArtifactInfo artifact = myCoordinates.get(getCoordinateText()); + final MavenRepositoryInfo repository = + artifact != null ? findRepositoryFor(artifact) : null; return repository != null? Collections.singletonList(repository) : ContainerUtil.findAll(myRepositories.values(), Condition.NOT_NULL); } } + private MavenRepositoryInfo findRepositoryFor(MavenArtifactInfo artifact) { + String soughtFor = artifact.getRepositoryId(); + if (soughtFor == null) return null; + + for (MavenRepositoryInfo each : myRepositories.values()) { + if (each.getId().equals(soughtFor)) return each; + } + return null; + } + private boolean isValidCoordinateSelected() { final String text = getCoordinateText(); if (myCombobox.getModel().getSelectedItem() == null) return false; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/RepositoryAttachHandler.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/RepositoryAttachHandler.java index fd8d0c66bacb..4d4fd0a55239 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/RepositoryAttachHandler.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/RepositoryAttachHandler.java @@ -21,7 +21,6 @@ import com.intellij.notification.NotificationType; import com.intellij.notification.Notifications; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; -import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.PerformInBackgroundOption; import com.intellij.openapi.progress.ProgressIndicator; @@ -37,29 +36,27 @@ import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.NullableComputable; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.util.PairProcessor; import com.intellij.util.Processor; +import com.intellij.util.SmartList; import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.maven.dom.converters.repositories.MavenRepositoriesProvider; -import org.jetbrains.idea.maven.facade.nexus.ArtifactType; -import org.jetbrains.idea.maven.facade.nexus.RepositoryType; -import org.jetbrains.idea.maven.facade.remote.MavenFacade; -import org.jetbrains.idea.maven.facade.remote.MavenFacadeManager; -import org.jetbrains.idea.maven.facade.remote.RemoteTransferListener; -import org.jetbrains.idea.maven.facade.remote.impl.RemoteTransferListenerImpl; -import org.jetbrains.idea.maven.project.MavenGeneralSettings; +import org.jetbrains.idea.maven.execution.SoutMavenConsole; +import org.jetbrains.idea.maven.facade.MavenEmbedderWrapper; +import org.jetbrains.idea.maven.facade.MavenFacadeManager; +import org.jetbrains.idea.maven.model.MavenArtifact; +import org.jetbrains.idea.maven.model.MavenArtifactInfo; +import org.jetbrains.idea.maven.model.MavenRemoteRepository; +import org.jetbrains.idea.maven.model.MavenRepositoryInfo; +import org.jetbrains.idea.maven.project.MavenEmbeddersManager; import org.jetbrains.idea.maven.project.MavenProjectsManager; import javax.swing.*; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; -import java.net.URL; -import java.rmi.server.UnicastRemoteObject; import java.util.*; -import java.util.concurrent.ConcurrentHashMap; /** * @author Gregory.Shrago @@ -88,31 +85,31 @@ public class RepositoryAttachHandler implements LibraryTableAttachHandler { final ActionCallback callback = new ActionCallback(); final String copyTo = dialog.getDirectoryPath(); final String coord = dialog.getCoordinateText(); - resolveLibrary(project, Collections.singleton(coord), dialog.getRepositories(), false, new Processor>>() { - public boolean process(final Map> stringListMap) { - final List result = stringListMap.get(coord); + resolveLibrary(project, coord, dialog.getRepositories(), false, new Processor>() { + public boolean process(final List artifacts) { ApplicationManager.getApplication().runWriteAction(new Runnable() { public void run() { final Library.ModifiableModel modifiableModel = modelProvider.compute(); - if (modifiableModel == null || result == null) { + if (modifiableModel == null) { callback.setRejected(); } else { - replaceLibraryData(project, modifiableModel, result, copyTo); + replaceLibraryData(project, modifiableModel, artifacts, copyTo); callback.setDone(); } } }); - final boolean nothingRetrieved = result == null || result.isEmpty(); + final boolean nothingRetrieved = artifacts.isEmpty(); final StringBuilder sb = new StringBuilder(); - if (nothingRetrieved) sb.append("No files were downloaded for ").append(coord); + if (nothingRetrieved) { + sb.append("No files were downloaded for ").append(coord); + } else { sb.append("The following files were downloaded:
    "); sb.append("
      "); - for (ArtifactType artifactType : result) { + for (MavenArtifact each : artifacts) { sb.append("
    1. "); - final String file = artifactType.getResourceUri(); - sb.append(file.substring(file.lastIndexOf('/') + 1)); + sb.append(each.getFile().getName()); sb.append("
    2. "); } sb.append("
    "); @@ -123,7 +120,8 @@ public class RepositoryAttachHandler implements LibraryTableAttachHandler { } else { Notifications.Bus.notify(new Notification("Repository", sb.toString(), title, - nothingRetrieved? NotificationType.WARNING : NotificationType.INFORMATION), NotificationDisplayType.STICKY_BALLOON, project); + nothingRetrieved ? NotificationType.WARNING : NotificationType.INFORMATION), + NotificationDisplayType.STICKY_BALLOON, project); } return true; } @@ -140,11 +138,11 @@ public class RepositoryAttachHandler implements LibraryTableAttachHandler { public ActionCallback refreshLibrary(final Project project, final Library.ModifiableModel library) { final ActionCallback result = new ActionCallback(); final String coord = getMavenCoordinate(library.getName()); - resolveLibrary(project, Collections.singleton(coord), getDefaultRepositories(), true, new Processor>>() { - public boolean process(final Map> artifactTypes) { + resolveLibrary(project, coord, getDefaultRepositories(), true, new Processor>() { + public boolean process(final List artifacts) { ApplicationManager.getApplication().runWriteAction(new Runnable() { public void run() { - replaceLibraryData(project, library, artifactTypes.get(coord), null); + replaceLibraryData(project, library, artifacts, null); result.setDone(); } }); @@ -156,9 +154,9 @@ public class RepositoryAttachHandler implements LibraryTableAttachHandler { private static void replaceLibraryData(Project project, Library.ModifiableModel library, - Collection artifactTypes, + Collection artifacts, String copyTo) { - final String repoUrl = VfsUtil.pathToUrl(MavenProjectsManager.getInstance(project).getGeneralSettings().getEffectiveLocalRepository().getPath()); + final String repoUrl = getLocalRepositoryUrl(project); for (OrderRootType type : OrderRootType.getAllTypes()) { for (String url : library.getUrls(type)) { if (url.startsWith(repoUrl)) { @@ -166,20 +164,18 @@ public class RepositoryAttachHandler implements LibraryTableAttachHandler { } } } - for (ArtifactType type : artifactTypes) { + for (MavenArtifact each : artifacts) { try { - final String url = VfsUtil.convertFromUrl(new URL(type.getResourceUri())); - final String targetUrl; + File repoFile = each.getFile(); + File toFile = repoFile; if (copyTo != null) { - final File repoFile = new File(FileUtil.toSystemDependentName(VfsUtil.urlToPath(url))); - final File toFile = new File(copyTo, repoFile.getName()); + toFile = new File(copyTo, repoFile.getName()); if (repoFile.exists()) { FileUtil.copy(repoFile, toFile); } - targetUrl = VfsUtil.pathToUrl(FileUtil.toSystemIndependentName(toFile.getPath())); } - else targetUrl = url; - library.addRoot(targetUrl, OrderRootType.CLASSES); + String url = VfsUtil.pathToUrl(FileUtil.toSystemIndependentName(toFile.getPath())); + library.addRoot(url, OrderRootType.CLASSES); } catch (MalformedURLException e) { LOG.warn(e); @@ -190,44 +186,42 @@ public class RepositoryAttachHandler implements LibraryTableAttachHandler { } } - public static void searchArtifacts(final Project project, String coord, final PairProcessor, Boolean> resultProcessor, final Processor> repoProcessor) { + private static String getLocalRepositoryUrl(Project project) { + File file = MavenProjectsManager.getInstance(project).getGeneralSettings().getEffectiveLocalRepository(); + return VfsUtil.pathToUrl(FileUtil.toSystemIndependentName(file.getPath())); + } + + public static void searchArtifacts(final Project project, String coord, + final PairProcessor, Boolean> resultProcessor, + final Processor> repoProcessor) { if (coord == null) return; - final ArtifactType template = createTemplate(coord); + final MavenArtifactInfo template = createTemplate(coord, null); ProgressManager.getInstance().run(new Task.Backgroundable(project, "Maven", false) { public void run(@NotNull ProgressIndicator indicator) { - final MavenFacadeManager mavenManager = ServiceManager.getService(project, MavenFacadeManager.class); - final Ref> result = Ref.create(Collections.emptyList()); - final Ref> result2 = Ref.create(Collections.emptyList()); + final Ref> result = Ref.create(Collections.emptyList()); + final Ref> result2 = Ref.create(Collections.emptyList()); final Ref tooManyRef = Ref.create(Boolean.FALSE); try { - final MavenFacade mavenFacade = mavenManager.getMavenFacade(project); + MavenFacadeManager facade = MavenFacadeManager.getInstance(); + final String[] nexusUrls = getDefaultNexusUrls(); - final List resultList = new ArrayList(); - final List result2List = new ArrayList(); + final List resultList = new ArrayList(); + final List result2List = new ArrayList(); for (String nexusUrl : nexusUrls) { - final List artifacts; + final List artifacts; try { - artifacts = mavenFacade.findArtifacts(template, nexusUrl); + artifacts = facade.findArtifacts(template, nexusUrl); } catch (Exception ex) { - LOG.warn("Accessing Nexus at: "+nexusUrl, ex); + LOG.warn("Accessing Nexus at: " + nexusUrl, ex); continue; } if (artifacts == null) { tooManyRef.set(Boolean.TRUE); } else if (!artifacts.isEmpty()) { - final List repositories = mavenFacade.getRepositories(nexusUrl); - final HashMap map = new HashMap(); - for (RepositoryType repository : repositories) { - map.put(repository.getId(), repository); - } - result2List.addAll(repositories); - for (ArtifactType artifact : artifacts) { - final RepositoryType repoType = map.get(artifact.getRepoId()); - artifact.setResourceUri(repoType == null? null: repoType.getContentResourceURI()); - } + result2List.addAll(facade.getRepositories(nexusUrl)); resultList.addAll(artifacts); } } @@ -249,20 +243,19 @@ public class RepositoryAttachHandler implements LibraryTableAttachHandler { }); } - public static void searchRepositories(final Project project, final Processor> resultProcessor) { + public static void searchRepositories(final Project project, final Processor> resultProcessor) { ProgressManager.getInstance().run(new Task.Backgroundable(project, "Maven", false) { public void run(@NotNull ProgressIndicator indicator) { - final MavenFacadeManager mavenManager = ServiceManager.getService(project, MavenFacadeManager.class); - final Ref> result = Ref.create(Collections.emptyList()); + final Ref> result = Ref.create(Collections.emptyList()); try { final String[] nexusUrls = getDefaultNexusUrls(); - final MavenFacade mavenFacade = mavenManager.getMavenFacade(project); - final ArrayList repoList = new ArrayList(); + final MavenFacadeManager manager = MavenFacadeManager.getInstance(); + final ArrayList repoList = new ArrayList(); for (String nexusUrl : nexusUrls) { - final List repositories; + final List repositories; try { - repositories = mavenFacade.getRepositories(nexusUrl); + repositories = manager.getRepositories(nexusUrl); } catch (Exception ex) { LOG.warn("Accessing Nexus at: " + nexusUrl, ex); @@ -286,38 +279,18 @@ public class RepositoryAttachHandler implements LibraryTableAttachHandler { }); } - private static String[] getDefaultNexusUrls() { - return new String[] { - "http://oss.sonatype.org/service/local/", - "http://repository.sonatype.org/service/local/", - //"http://maven.labs.intellij.net:8081/nexus/service/local/" - }; - } - - public static List getDefaultRepositories() { - final List list = new ArrayList(); - final Set visited = new HashSet(); - final MavenRepositoriesProvider provider = MavenRepositoriesProvider.getInstance(); - for (String id : provider.getRepositoryIds()) { - final String url = provider.getRepositoryUrl(id); - if (!visited.add(url)) continue; - list.add(new MavenFacade.Repository(id, url, StringUtil.notNullize(provider.getRepositoryLayout(id), "default"))); - } - return list; - } - - private static ArtifactType createTemplate(String coord) { - final ArtifactType template = new ArtifactType(); + private static MavenArtifactInfo createTemplate(String coord, String packaging) { final String[] parts = coord.split(":"); if (parts.length == 1 && parts[0].length() > 0 && Character.isUpperCase(parts[0].charAt(0))) { - template.setContextId(parts[0]); + return new MavenArtifactInfo(null, null, null, packaging, null, parts[0], null); } else { - template.setGroupId(parts.length > 0 ? parts[0] : null); - template.setArtifactId(parts.length > 1 ? parts[1] : null); - template.setVersion(parts.length > 2 ? parts[2] : null); + return new MavenArtifactInfo(parts.length > 0 ? parts[0] : null, + parts.length > 1 ? parts[1] : null, + parts.length > 2 ? parts[2] : null, + null, + null); } - return template; } private static void handleError(String message, Exception e) { @@ -325,61 +298,51 @@ public class RepositoryAttachHandler implements LibraryTableAttachHandler { } public static void resolveLibrary(final Project project, - Collection libNames, - final Collection repositories, boolean modal, - final Processor>> resultProcessor) { - if (libNames.isEmpty()) return; - final ArrayList parameters = new ArrayList(); - for (String s : libNames) { - final ArtifactType template = createTemplate(s); - template.setPackaging("jar"); - parameters.add(template); + final String libName, + Collection repositories, + boolean modal, + final Processor> resultProcessor) { + Task task; + if (modal) { + task = new Task.Modal(project, "Maven", false) { + public void run(@NotNull ProgressIndicator indicator) { + doResolveInner(project, Collections.singletonList(createTemplate(libName, "jar")), resultProcessor, indicator); + } + }; } - ProgressManager.getInstance().run(modal ? new Task.Modal(project, "Maven", false) { + else { + task = new Task.Backgroundable(project, "Maven", false, PerformInBackgroundOption.DEAF) { + public void run(@NotNull ProgressIndicator indicator) { + doResolveInner(project, Collections.singletonList(createTemplate(libName, "jar")), resultProcessor, indicator); + } - public void run(@NotNull ProgressIndicator indicator) { - doResolveInner(project, parameters, repositories, resultProcessor, indicator); - } - } : new Task.Backgroundable(project, "Maven", false, PerformInBackgroundOption.DEAF) { - - public void run(@NotNull ProgressIndicator indicator) { - doResolveInner(project, parameters, repositories, resultProcessor, indicator); - } + @Override + public boolean shouldStartInBackground() { + return false; + } + }; + } - @Override - public boolean shouldStartInBackground() { - return false; - } - }); + ProgressManager.getInstance().run(task); } private static void doResolveInner(Project project, - final ArrayList artifacts, - Collection repositories, - final Processor>> resultProcessor, + List artifacts, + final Processor> resultProcessor, ProgressIndicator indicator) { - final Ref>> result = Ref.create(Collections.>emptyMap()); - final MavenFacadeManager mavenManager = ServiceManager.getService(project, MavenFacadeManager.class); + final Ref> result = new Ref>(); + + MavenEmbeddersManager manager = MavenProjectsManager.getInstance(project).getEmbeddersManager(); + MavenEmbedderWrapper embedder = manager.getEmbedder(MavenEmbeddersManager.FOR_DOWNLOAD); try { - final MavenFacade mavenFacade = mavenManager.getMavenFacade(project); - final MavenFacade.MavenFacadeSettings settings = createMavenFacadeSettings(project); - settings.getRemoteRepositories().addAll(repositories); - mavenFacade.setMavenSettings(settings); - final RemoteTransferListener transferListener = fromProgressIndicator(indicator); - UnicastRemoteObject.exportObject(transferListener, 0); - mavenFacade.setTransferListener(transferListener); - try { - result.set(mavenFacade.resolveDependencies(artifacts)); - } - finally { - UnicastRemoteObject.unexportObject(transferListener, true); - mavenFacade.setTransferListener(null); - } + embedder.customizeForResolve(new SoutMavenConsole(), new MavenProgressIndicator(indicator)); + result.set(embedder.resolveTransitively(artifacts, convertRepositories(getDefaultRepositories()))); } - catch (Exception e) { - handleError("Error resolving: " + artifacts, e); + catch (MavenProcessCanceledException e) { + return; } finally { + manager.release(embedder); ApplicationManager.getApplication().invokeLater(new Runnable() { public void run() { resultProcessor.process(result.get()); @@ -388,6 +351,34 @@ public class RepositoryAttachHandler implements LibraryTableAttachHandler { } } + private static List convertRepositories(List infos) { + List result = new ArrayList(infos.size()); + for (MavenRepositoryInfo each : infos) { + result.add(new MavenRemoteRepository(each.getId(), each.getName(), each.getUrl(), null, null, null)); + } + return result; + } + + private static String[] getDefaultNexusUrls() { + return new String[]{ + "http://oss.sonatype.org/service/local/", + "http://repository.sonatype.org/service/local/", + //"http://maven.labs.intellij.net:8081/nexus/service/local/" + }; + } + + public static List getDefaultRepositories() { + List result = new SmartList(); + final MavenRepositoriesProvider provider = MavenRepositoriesProvider.getInstance(); + for (String id : provider.getRepositoryIds()) { + final String url = provider.getRepositoryUrl(id); + if (url != null) { + result.add(new MavenRepositoryInfo(id, provider.getRepositoryName(id), url)); + } + } + return result; + } + //public static void registerLibraryWatcher(final Project project) { // final Alarm alarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD, project); // final Runnable syncRunnable = new Runnable() { @@ -458,7 +449,7 @@ public class RepositoryAttachHandler implements LibraryTableAttachHandler { // syncRunnable.run(); //} - private void refreshLibraries(final Project project, final Map> map) { + private void refreshLibraries(final Project project, final Map> map) { ApplicationManager.getApplication().runWriteAction(new Runnable() { public void run() { for (Library library : map.keySet()) { @@ -470,102 +461,95 @@ public class RepositoryAttachHandler implements LibraryTableAttachHandler { }); } - private static MavenFacade.MavenFacadeSettings createMavenFacadeSettings(Project project) { - final MavenFacade.MavenFacadeSettings settings = new MavenFacade.MavenFacadeSettings(); - final MavenGeneralSettings generalSettings = MavenProjectsManager.getInstance(project).getGeneralSettings(); - settings.setLocalRepository(new MavenFacade.Repository("local", VfsUtil.pathToUrl(generalSettings.getEffectiveLocalRepository().getPath()), "default")); - return settings; - } - - public static RemoteTransferListener fromProgressIndicator(final ProgressIndicator indicator) { - return new RemoteTransferListenerImpl() { - - final Map myDownloads = new ConcurrentHashMap(); - @Override - public void transferInitiated(TransferEvent transferEvent) { - final String message = transferEvent.getRequestType() == TransferEvent.RequestType.PUT ? "Uploading" : "Downloading"; - final String url = transferEvent.getRepositoryUrl(); - indicator.setText(message + ": " + url + "/" + transferEvent.getResource().getResourceName()); - } - - @Override - public void transferStarted(TransferEvent transferEvent) { - // nothing - } - - @Override - public void transferProgress(TransferEvent transferEvent, int length) { - final Resource resource = transferEvent.getResource(); - final long curComplete; - if (!myDownloads.containsKey(resource)) { - curComplete = length; - } - else { - final long complete = myDownloads.get(resource).longValue(); - curComplete = complete + length; - } - myDownloads.put(resource, new Long(curComplete)); - - long curTotal = 0; - long curProgress = 0; - boolean unknown = false; - for (Resource res : myDownloads.keySet()) { - final long total = res.getResourceContentLength(); - final long complete = myDownloads.get(res).longValue(); - if (total == -1) unknown = true; - else curTotal += total; - curProgress += complete; - } - - final StringBuilder sb = new StringBuilder(); - if (curTotal >= 1024) { - sb.append((curProgress / 1024) + "/" + (curTotal == -1 ? "?" : (curTotal / 1024) + "K")); - } - else { - sb.append(curProgress + "/" + (curTotal == -1 ? "?" : curTotal + "b")); - } - if (unknown) { - indicator.setIndeterminate(true); - } - else { - indicator.setIndeterminate(false); - indicator.setFraction((double)curProgress / curTotal); - } - indicator.setText(sb.toString()); - indicator.setText2(transferEvent.getResource().getResourceName()); - } - - @Override - public void transferCompleted(TransferEvent transferEvent) { - transferProgress(transferEvent, 0); - if (true) return; - final StringBuilder sb = new StringBuilder(); - final long contentLength = transferEvent.getResource().getResourceContentLength(); - if (contentLength != -1) { - String type = - (transferEvent.getRequestType() == TransferEvent.RequestType.PUT ? "uploaded" : "downloaded"); - sb.append(contentLength >= 1024 ? (contentLength / 1024) + "K" : contentLength + "b"); - String name = transferEvent.getResource().getResourceName(); - name = name.substring(name.lastIndexOf('/') + 1, name.length()); - sb.append(" "); - sb.append(type); - sb.append(" ("); - sb.append(name); - sb.append(")"); - } - indicator.setText(sb.toString()); - //myDownloads.remove(transferEvent.getResource()); - } - - @Override - public void transferError(TransferEvent transferEvent) { - indicator.setText2(transferEvent.getException().getMessage()); - } - - @Override - public void debug(String s) { - indicator.setText2(s); - } - }; - } + //public static RemoteTransferListener fromProgressIndicator(final ProgressIndicator indicator) { + // return new RemoteTransferListenerImpl() { + // + // final Map myDownloads = new ConcurrentHashMap(); + // @Override + // public void transferInitiated(TransferEvent transferEvent) { + // final String message = transferEvent.getRequestType() == TransferEvent.RequestType.PUT ? "Uploading" : "Downloading"; + // final String url = transferEvent.getRepositoryUrl(); + // indicator.setText(message + ": " + url + "/" + transferEvent.getResource().getResourceName()); + // } + // + // @Override + // public void transferStarted(TransferEvent transferEvent) { + // // nothing + // } + // + // @Override + // public void transferProgress(TransferEvent transferEvent, int length) { + // final Resource resource = transferEvent.getResource(); + // final long curComplete; + // if (!myDownloads.containsKey(resource)) { + // curComplete = length; + // } + // else { + // final long complete = myDownloads.get(resource).longValue(); + // curComplete = complete + length; + // } + // myDownloads.put(resource, new Long(curComplete)); + // + // long curTotal = 0; + // long curProgress = 0; + // boolean unknown = false; + // for (Resource res : myDownloads.keySet()) { + // final long total = res.getResourceContentLength(); + // final long complete = myDownloads.get(res).longValue(); + // if (total == -1) unknown = true; + // else curTotal += total; + // curProgress += complete; + // } + // + // final StringBuilder sb = new StringBuilder(); + // if (curTotal >= 1024) { + // sb.append((curProgress / 1024) + "/" + (curTotal == -1 ? "?" : (curTotal / 1024) + "K")); + // } + // else { + // sb.append(curProgress + "/" + (curTotal == -1 ? "?" : curTotal + "b")); + // } + // if (unknown) { + // indicator.setIndeterminate(true); + // } + // else { + // indicator.setIndeterminate(false); + // indicator.setFraction((double)curProgress / curTotal); + // } + // indicator.setText(sb.toString()); + // indicator.setText2(transferEvent.getResource().getResourceName()); + // } + // + // @Override + // public void transferCompleted(TransferEvent transferEvent) { + // transferProgress(transferEvent, 0); + // if (true) return; + // final StringBuilder sb = new StringBuilder(); + // final long contentLength = transferEvent.getResource().getResourceContentLength(); + // if (contentLength != -1) { + // String type = + // (transferEvent.getRequestType() == TransferEvent.RequestType.PUT ? "uploaded" : "downloaded"); + // sb.append(contentLength >= 1024 ? (contentLength / 1024) + "K" : contentLength + "b"); + // String name = transferEvent.getResource().getResourceName(); + // name = name.substring(name.lastIndexOf('/') + 1, name.length()); + // sb.append(" "); + // sb.append(type); + // sb.append(" ("); + // sb.append(name); + // sb.append(")"); + // } + // indicator.setText(sb.toString()); + // //myDownloads.remove(transferEvent.getResource()); + // } + // + // @Override + // public void transferError(TransferEvent transferEvent) { + // indicator.setText2(transferEvent.getException().getMessage()); + // } + // + // @Override + // public void debug(String s) { + // indicator.setText2(s); + // } + // }; + //} } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/actions/MavenActionUtil.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/actions/MavenActionUtil.java index 1e41626f63a0..7a9557ff4d65 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/actions/MavenActionUtil.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/actions/MavenActionUtil.java @@ -24,7 +24,7 @@ import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.maven.project.MavenProject; import org.jetbrains.idea.maven.project.MavenProjectsManager; -import org.jetbrains.idea.maven.utils.MavenConstants; +import org.jetbrains.idea.maven.model.MavenConstants; import org.jetbrains.idea.maven.utils.MavenUtil; import java.util.*; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenAddArchetypeDialog.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenAddArchetypeDialog.java index 671eb6d3493c..128c4f078846 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenAddArchetypeDialog.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenAddArchetypeDialog.java @@ -18,7 +18,7 @@ package org.jetbrains.idea.maven.wizards; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.DocumentAdapter; -import org.jetbrains.idea.maven.indices.ArchetypeInfo; +import org.jetbrains.idea.maven.model.MavenArchetype; import javax.swing.*; import javax.swing.event.DocumentEvent; @@ -80,8 +80,8 @@ public class MavenAddArchetypeDialog extends DialogWrapper { getRootPane().revalidate(); } - public ArchetypeInfo getArchetype() { - return new ArchetypeInfo(myGroupIdField.getText(), + public MavenArchetype getArchetype() { + return new MavenArchetype(myGroupIdField.getText(), myArtifactIdField.getText(), myVersionField.getText(), myRepositoryField.getText(), diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenFrameworkSupportProvider.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenFrameworkSupportProvider.java index 8425493a4826..c02460547a75 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenFrameworkSupportProvider.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenFrameworkSupportProvider.java @@ -27,9 +27,9 @@ import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.maven.project.MavenId; +import org.jetbrains.idea.maven.model.MavenId; import org.jetbrains.idea.maven.project.MavenProjectsManager; -import org.jetbrains.idea.maven.utils.MavenConstants; +import org.jetbrains.idea.maven.model.MavenConstants; import org.jetbrains.idea.maven.utils.MavenIcons; import javax.swing.*; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleBuilder.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleBuilder.java index 7e360866bf68..14c53b6175ef 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleBuilder.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleBuilder.java @@ -31,8 +31,8 @@ import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; -import org.jetbrains.idea.maven.indices.ArchetypeInfo; -import org.jetbrains.idea.maven.project.MavenId; +import org.jetbrains.idea.maven.model.MavenArchetype; +import org.jetbrains.idea.maven.model.MavenId; import org.jetbrains.idea.maven.project.MavenProject; import org.jetbrains.idea.maven.project.MavenProjectsManager; import org.jetbrains.idea.maven.utils.MavenUtil; @@ -54,7 +54,7 @@ public class MavenModuleBuilder extends ModuleBuilder implements SourcePathsBuil private boolean myInheritVersion; private MavenId myProjectId; - private ArchetypeInfo myArchetype; + private MavenArchetype myArchetype; public void setupRootModel(ModifiableRootModel rootModel) throws ConfigurationException { final Project project = rootModel.getProject(); @@ -173,11 +173,11 @@ public class MavenModuleBuilder extends ModuleBuilder implements SourcePathsBuil return myProjectId; } - public void setArchetype(ArchetypeInfo archetype) { + public void setArchetype(MavenArchetype archetype) { myArchetype = archetype; } - public ArchetypeInfo getArchetype() { + public MavenArchetype getArchetype() { return myArchetype; } } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleBuilderHelper.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleBuilderHelper.java index 0d49b15e446a..4493fb80522b 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleBuilderHelper.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleBuilderHelper.java @@ -34,11 +34,11 @@ import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel; import org.jetbrains.idea.maven.execution.MavenRunner; import org.jetbrains.idea.maven.execution.MavenRunnerParameters; import org.jetbrains.idea.maven.execution.MavenRunnerSettings; -import org.jetbrains.idea.maven.indices.ArchetypeInfo; -import org.jetbrains.idea.maven.project.MavenId; +import org.jetbrains.idea.maven.model.MavenArchetype; +import org.jetbrains.idea.maven.model.MavenConstants; +import org.jetbrains.idea.maven.model.MavenId; import org.jetbrains.idea.maven.project.MavenProject; import org.jetbrains.idea.maven.project.MavenProjectsManager; -import org.jetbrains.idea.maven.utils.MavenConstants; import org.jetbrains.idea.maven.utils.MavenLog; import org.jetbrains.idea.maven.utils.MavenUtil; @@ -56,7 +56,7 @@ public class MavenModuleBuilderHelper { private final boolean myInheritGroupId; private final boolean myInheritVersion; - private final ArchetypeInfo myArchetype; + private final MavenArchetype myArchetype; private final String myCommandName; @@ -65,7 +65,7 @@ public class MavenModuleBuilderHelper { MavenProject parentProject, boolean inheritGroupId, boolean inheritVersion, - ArchetypeInfo archetype, + MavenArchetype archetype, String commaneName) { myProjectId = projectId; myAggregatorProject = aggregatorProject; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleWizardStep.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleWizardStep.java index c0c4f1c5eceb..7ea7c3e6546d 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleWizardStep.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleWizardStep.java @@ -18,7 +18,6 @@ package org.jetbrains.idea.maven.wizards; import com.intellij.ide.util.PropertiesComponent; import com.intellij.ide.util.projectWizard.ModuleWizardStep; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.text.StringUtil; @@ -30,13 +29,12 @@ import com.intellij.util.ui.AsyncProcessIcon; import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.tree.TreeUtil; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.maven.indices.ArchetypeInfo; +import org.jetbrains.idea.maven.model.MavenArchetype; import org.jetbrains.idea.maven.indices.MavenIndicesManager; import org.jetbrains.idea.maven.navigator.SelectMavenProjectDialog; import org.jetbrains.idea.maven.project.MavenProject; import org.jetbrains.idea.maven.project.MavenProjectsManager; -import org.jetbrains.idea.maven.project.MavenId; -import org.jetbrains.idea.maven.utils.MavenUtil; +import org.jetbrains.idea.maven.model.MavenId; import javax.swing.*; import javax.swing.event.TreeSelectionEvent; @@ -156,7 +154,7 @@ public class MavenModuleWizardStep extends ModuleWizardStep { new TreeSpeedSearch(myArchetypesTree, new Convertor() { public String convert(TreePath path) { - ArchetypeInfo info = getArchetypeInfoFromPathComponent(path.getLastPathComponent()); + MavenArchetype info = getArchetypeInfoFromPathComponent(path.getLastPathComponent()); return info.groupId + ":" + info.artifactId + ":" + info.version; } }).setComparator(new SpeedSearchBase.SpeedSearchComparator(false) { @@ -194,7 +192,7 @@ public class MavenModuleWizardStep extends ModuleWizardStep { dialog.show(); if (!dialog.isOK()) return; - ArchetypeInfo archetype = dialog.getArchetype(); + MavenArchetype archetype = dialog.getArchetype(); MavenIndicesManager.getInstance().addArchetype(archetype); updateArchetypesList(archetype); } @@ -222,7 +220,7 @@ public class MavenModuleWizardStep extends ModuleWizardStep { myBuilder.setArchetype(null); } else { - myBuilder.setArchetype(new ArchetypeInfo(archGroupId, archArtifactId, archVersion, null, null)); + myBuilder.setArchetype(new MavenArchetype(archGroupId, archArtifactId, archVersion, null, null)); } } @@ -230,7 +228,7 @@ public class MavenModuleWizardStep extends ModuleWizardStep { saveValue(INHERIT_GROUP_ID_KEY, myInheritGroupIdCheckBox.isSelected()); saveValue(INHERIT_VERSION_KEY, myInheritVersionCheckBox.isSelected()); - ArchetypeInfo arch = getSelectedArchetype(); + MavenArchetype arch = getSelectedArchetype(); saveValue(ARCHETYPE_GROUP_ID_KEY, arch == null ? null : arch.groupId); saveValue(ARCHETYPE_ARTIFACT_ID_KEY, arch == null ? null : arch.artifactId); saveValue(ARCHETYPE_VERSION_KEY, arch == null ? null : arch.version); @@ -273,7 +271,7 @@ public class MavenModuleWizardStep extends ModuleWizardStep { myInheritGroupIdCheckBox.setSelected(myBuilder.isInheritGroupId()); myInheritVersionCheckBox.setSelected(myBuilder.isInheritVersion()); - ArchetypeInfo selectedArch = getSelectedArchetype(); + MavenArchetype selectedArch = getSelectedArchetype(); if (selectedArch == null) { selectedArch = myBuilder.getArchetype(); } @@ -283,7 +281,7 @@ public class MavenModuleWizardStep extends ModuleWizardStep { updateComponents(); } - private void updateArchetypesList(final ArchetypeInfo selected) { + private void updateArchetypesList(final MavenArchetype selected) { myLoadingCancelled.set(true); myLoadingCancelled = new AtomicBoolean(); final AtomicBoolean currentStatus = myLoadingCancelled; @@ -298,7 +296,7 @@ public class MavenModuleWizardStep extends ModuleWizardStep { catch (InterruptedException e) { throw new RuntimeException(e); } - final Set archetypes = MavenIndicesManager.getInstance().getArchetypes(); + final Set archetypes = MavenIndicesManager.getInstance().getArchetypes(); SwingUtilities.invokeLater(new Runnable() { public void run() { @@ -325,7 +323,7 @@ public class MavenModuleWizardStep extends ModuleWizardStep { } private void updateArchetypeDescription() { - ArchetypeInfo sel = getSelectedArchetype(); + MavenArchetype sel = getSelectedArchetype(); String desc = sel == null ? null : sel.description; if (StringUtil.isEmptyOrSpaces(desc)) { myArchetypeDescriptionScrollPane.setVisible(false); @@ -336,7 +334,7 @@ public class MavenModuleWizardStep extends ModuleWizardStep { myMainPanel.revalidate(); } - private TreePath findNodePath(ArchetypeInfo object, TreeModel model, Object parent) { + private TreePath findNodePath(MavenArchetype object, TreeModel model, Object parent) { for (int i = 0; i < model.getChildCount(parent); i++) { DefaultMutableTreeNode each = (DefaultMutableTreeNode)model.getChild(parent, i); if (each.getUserObject().equals(object)) return new TreePath(each.getPath()); @@ -347,11 +345,11 @@ public class MavenModuleWizardStep extends ModuleWizardStep { return null; } - private TreeNode groupAndSortArchetypes(Set archetypes) { - List list = new ArrayList(archetypes); + private TreeNode groupAndSortArchetypes(Set archetypes) { + List list = new ArrayList(archetypes); - Collections.sort(list, new Comparator() { - public int compare(ArchetypeInfo o1, ArchetypeInfo o2) { + Collections.sort(list, new Comparator() { + public int compare(MavenArchetype o1, MavenArchetype o2) { String key1 = o1.groupId + ":" + o1.artifactId; String key2 = o2.groupId + ":" + o2.artifactId; @@ -362,23 +360,23 @@ public class MavenModuleWizardStep extends ModuleWizardStep { } }); - Map> map = new TreeMap>(); + Map> map = new TreeMap>(); - for (ArchetypeInfo each : list) { + for (MavenArchetype each : list) { String key = each.groupId + ":" + each.artifactId; - List versions = map.get(key); + List versions = map.get(key); if (versions == null) { - versions = new ArrayList(); + versions = new ArrayList(); map.put(key, versions); } versions.add(each); } DefaultMutableTreeNode result = new DefaultMutableTreeNode("root", true); - for (List each : map.values()) { - ArchetypeInfo eachArchetype = each.get(0); + for (List each : map.values()) { + MavenArchetype eachArchetype = each.get(0); DefaultMutableTreeNode node = new DefaultMutableTreeNode(eachArchetype, true); - for (ArchetypeInfo eachVersion : each) { + for (MavenArchetype eachVersion : each) { DefaultMutableTreeNode versionNode = new DefaultMutableTreeNode(eachVersion, false); node.add(versionNode); } @@ -455,13 +453,13 @@ public class MavenModuleWizardStep extends ModuleWizardStep { myBuilder.setArchetype(getSelectedArchetype()); } - private ArchetypeInfo getSelectedArchetype() { + private MavenArchetype getSelectedArchetype() { if (!myUseArchetypeCheckBox.isSelected() || myArchetypesTree.isSelectionEmpty()) return null; return getArchetypeInfoFromPathComponent(myArchetypesTree.getLastSelectedPathComponent()); } - private ArchetypeInfo getArchetypeInfoFromPathComponent(Object sel) { - return (ArchetypeInfo)((DefaultMutableTreeNode)sel).getUserObject(); + private MavenArchetype getArchetypeInfoFromPathComponent(Object sel) { + return (MavenArchetype)((DefaultMutableTreeNode)sel).getUserObject(); } @Override @@ -478,9 +476,9 @@ public class MavenModuleWizardStep extends ModuleWizardStep { int row, boolean hasFocus) { Object userObject = ((DefaultMutableTreeNode)value).getUserObject(); - if (!(userObject instanceof ArchetypeInfo)) return; + if (!(userObject instanceof MavenArchetype)) return; - ArchetypeInfo info = (ArchetypeInfo)userObject; + MavenArchetype info = (MavenArchetype)userObject; if (leaf) { append(info.artifactId, SimpleTextAttributes.GRAY_ATTRIBUTES); diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenProjectBuilder.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenProjectBuilder.java index 981e2f1b1e8c..4bf5503461f5 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenProjectBuilder.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenProjectBuilder.java @@ -31,6 +31,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.maven.importing.MavenDefaultModifiableModelsProvider; import org.jetbrains.idea.maven.importing.MavenUIModifiableModelsProvider; +import org.jetbrains.idea.maven.model.MavenId; import org.jetbrains.idea.maven.project.*; import org.jetbrains.idea.maven.utils.*; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenProjectOpenProcessor.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenProjectOpenProcessor.java index 1d0032c1a862..bff0d17a768b 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenProjectOpenProcessor.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenProjectOpenProcessor.java @@ -25,7 +25,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.projectImport.ProjectOpenProcessorBase; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.maven.project.MavenProject; -import org.jetbrains.idea.maven.utils.MavenConstants; +import org.jetbrains.idea.maven.model.MavenConstants; import java.util.ArrayList; import java.util.Arrays; diff --git a/plugins/maven/src/main/resources/IndicesBundle.properties b/plugins/maven/src/main/resources/IndicesBundle.properties index b239f68af9b7..a0e6b9e678b4 100644 --- a/plugins/maven/src/main/resources/IndicesBundle.properties +++ b/plugins/maven/src/main/resources/IndicesBundle.properties @@ -6,6 +6,5 @@ maven.index.updated.never=Never maven.index.updated.error=Error maven.indices.updating=Updating Maven Repository Indices... maven.indices.updating.index=Updating [{0}] {1} -maven.indices.updating.processing=Processing indices... repository.plugin.corrupt={0} not a Maven 2 plugin file repository.plugin.title=Opening Maven plugin file \ No newline at end of file diff --git a/plugins/maven/src/main/resources/META-INF/plugin.xml b/plugins/maven/src/main/resources/META-INF/plugin.xml index 7709f41d6afa..13f14ad673c2 100644 --- a/plugins/maven/src/main/resources/META-INF/plugin.xml +++ b/plugins/maven/src/main/resources/META-INF/plugin.xml @@ -11,7 +11,7 @@ com.intellij.properties - org.intellij.groovy + org.intellij.groovy @@ -20,6 +20,9 @@ + + @@ -73,9 +76,6 @@ - - @@ -399,10 +399,10 @@ + use-shortcut-of="IntroduceVariable"/> + class="org.jetbrains.idea.maven.dom.refactorings.extract.ExtractDependenciesAction"> diff --git a/plugins/maven/src/main/resources/ProjectBundle.properties b/plugins/maven/src/main/resources/ProjectBundle.properties index b1eb46f0898e..3a5fda1e6ab7 100644 --- a/plugins/maven/src/main/resources/ProjectBundle.properties +++ b/plugins/maven/src/main/resources/ProjectBundle.properties @@ -16,8 +16,6 @@ maven.downloading=Downloading Maven sources and documentation... maven.downloading.sources=Downloading Maven sources... maven.downloading.docs=Downloading Maven documentation... maven.downloading.finished=Finished downloading -maven.transfer.progress={0}/{1}K [{2}] {3} -maven.transfer.start=Checking [{0}] {1} maven.action.download.sources=Download Sources maven.action.download.sources.busy.text=Download sources... @@ -69,7 +67,6 @@ maven.ignore.edit=Edit Ignored Files... maven.profile.activate=Activate maven.profile.deactivate=Deactivate -maven.project.problem.syntaxError=''{0}'' has syntax errors maven.project.problem.recursiveInheritance=Recursive inheritance found maven.project.problem.selfInheritance=Self-inheritance found maven.project.problem.parentHasProblems=Parent ''{0}'' has problems diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenCustomRepositoryHelper.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenCustomRepositoryHelper.java similarity index 98% rename from plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenCustomRepositoryHelper.java rename to plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenCustomRepositoryHelper.java index 0c432d998727..191bbb1539fc 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenCustomRepositoryHelper.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenCustomRepositoryHelper.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.maven.indices; +package org.jetbrains.idea.maven; import com.intellij.openapi.application.PluginPathManager; import com.intellij.openapi.util.io.FileUtil; diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenImportingTestCase.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenImportingTestCase.java index fda2567350e4..4d3b982135f4 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenImportingTestCase.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenImportingTestCase.java @@ -38,6 +38,7 @@ import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.ArrayUtil; import com.intellij.util.PathUtil; +import org.jetbrains.idea.maven.model.MavenArtifact; import org.jetbrains.idea.maven.project.*; import org.jetbrains.idea.maven.execution.*; diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenTestCase.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenTestCase.java index 838e9ca5f258..6b05726cdc30 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenTestCase.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenTestCase.java @@ -33,7 +33,6 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.testFramework.UsefulTestCase; import com.intellij.testFramework.fixtures.IdeaProjectTestFixture; import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory; -import org.jetbrains.idea.maven.embedder.MavenConsole; import org.jetbrains.idea.maven.project.*; import org.jetbrains.idea.maven.utils.MavenProgressIndicator; @@ -202,7 +201,7 @@ public abstract class MavenTestCase extends UsefulTestCase { } protected void setRepositoryPath(String path) { - getMavenGeneralSettings().setLocalRepository(path); + getMavenGeneralSettings().setOverridenLocalRepository(path); } protected String getProjectPath() { diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/NullMavenConsole.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/NullMavenConsole.java index 1975b8da15b5..2bd3950452e8 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/NullMavenConsole.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/NullMavenConsole.java @@ -15,9 +15,9 @@ */ package org.jetbrains.idea.maven; -import org.jetbrains.idea.maven.embedder.MavenConsole; -import org.jetbrains.idea.maven.embedder.MavenExecutionOptions; import com.intellij.execution.process.ProcessHandler; +import org.jetbrains.idea.maven.execution.MavenExecutionOptions; +import org.jetbrains.idea.maven.project.MavenConsole; public class NullMavenConsole extends MavenConsole { public NullMavenConsole() { @@ -38,6 +38,6 @@ public class NullMavenConsole extends MavenConsole { public void attachToProcess(ProcessHandler processHandler) { } - protected void doPrint(String text, OutputType type) { + protected void doPrint(String text, MavenConsole.OutputType type) { } } diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/AddingDependencyTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/AddingDependencyTest.java index 9ca0a037b7cc..8e6a55766770 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/AddingDependencyTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/AddingDependencyTest.java @@ -16,10 +16,10 @@ package org.jetbrains.idea.maven.importing; import com.intellij.util.io.ReadOnlyAttributeUtil; +import org.jetbrains.idea.maven.MavenCustomRepositoryHelper; import org.jetbrains.idea.maven.MavenImportingTestCase; -import org.jetbrains.idea.maven.indices.MavenCustomRepositoryHelper; -import org.jetbrains.idea.maven.project.MavenArtifact; -import org.jetbrains.idea.maven.project.MavenId; +import org.jetbrains.idea.maven.model.MavenArtifact; +import org.jetbrains.idea.maven.model.MavenId; import java.io.File; import java.util.List; diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/ArtifactsDownloadingTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/ArtifactsDownloadingTest.java index f2bdd1982bf0..6eeba7af237d 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/ArtifactsDownloadingTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/ArtifactsDownloadingTest.java @@ -17,11 +17,11 @@ package org.jetbrains.idea.maven.importing; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VfsUtil; +import org.jetbrains.idea.maven.MavenCustomRepositoryHelper; import org.jetbrains.idea.maven.MavenImportingTestCase; -import org.jetbrains.idea.maven.indices.MavenCustomRepositoryHelper; -import org.jetbrains.idea.maven.project.MavenArtifact; +import org.jetbrains.idea.maven.model.MavenArtifact; +import org.jetbrains.idea.maven.model.MavenId; import org.jetbrains.idea.maven.project.MavenArtifactDownloader; -import org.jetbrains.idea.maven.project.MavenId; import org.jetbrains.idea.maven.project.MavenProject; import java.io.File; diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/DependenciesImportingTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/DependenciesImportingTest.java index 0fa9553d59e7..3f94e53655f2 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/DependenciesImportingTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/DependenciesImportingTest.java @@ -23,8 +23,8 @@ import com.intellij.openapi.roots.libraries.LibraryTable; import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.idea.maven.MavenCustomRepositoryHelper; import org.jetbrains.idea.maven.MavenImportingTestCase; -import org.jetbrains.idea.maven.indices.MavenCustomRepositoryHelper; import org.jetbrains.idea.maven.project.MavenProject; import java.io.File; @@ -1352,7 +1352,7 @@ public class DependenciesImportingTest extends MavenImportingTestCase { "jar://" + getRepositoryPath() + "/junit/junit/4.0/junit-4.0-javadoc.jar!/"); setRepositoryPath(new File(myDir, "__repo").getPath()); - myProjectsManager.getEmbeddersManagerInTests().reset(); // to recognize repository change + myProjectsManager.getEmbeddersManager().reset(); // to recognize repository change scheduleResolveAll(); resolveDependenciesAndImport(); @@ -1384,7 +1384,7 @@ public class DependenciesImportingTest extends MavenImportingTestCase { "jar://" + getRepositoryPath() + "/org/testng/testng/5.8/testng-5.8-javadoc.jar!/"); setRepositoryPath(new File(myDir, "__repo").getPath()); - myProjectsManager.getEmbeddersManagerInTests().reset(); // to recognize repository change + myProjectsManager.getEmbeddersManager().reset(); // to recognize repository change scheduleResolveAll(); diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/DependenciesManagementTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/DependenciesManagementTest.java index dd7d576b11e6..c886494cc88c 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/DependenciesManagementTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/DependenciesManagementTest.java @@ -122,7 +122,7 @@ public class DependenciesManagementTest extends MavenImportingTestCase { // reset embedders and try to resolve project from scratch in specific order - imported one goes first // to make maven cache it. we have to ensure that dependent project will be resolved correctly after that - myProjectsManager.getEmbeddersManagerInTests().releaseForcefullyInTests(); + myProjectsManager.getEmbeddersManager().releaseForcefullyInTests(); myProjectsManager.scheduleResolveInTests(Arrays.asList(myProjectsManager.findProject(bom), myProjectsManager.findProject(project))); myProjectsManager.waitForResolvingCompletion(); @@ -181,7 +181,7 @@ public class DependenciesManagementTest extends MavenImportingTestCase { assertModuleLibDeps("project", "Maven: junit:junit:4.0"); - myProjectsManager.getEmbeddersManagerInTests().reset(); + myProjectsManager.getEmbeddersManager().reset(); myProjectsManager.scheduleResolveInTests(Arrays.asList(myProjectsManager.findProject(parent), myProjectsManager.findProject(project))); myProjectsManager.waitForResolvingCompletion(); diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/FoldersImportingTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/FoldersImportingTest.java index e2e8c0fe4ae4..dc553b513a9b 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/FoldersImportingTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/FoldersImportingTest.java @@ -19,9 +19,7 @@ import com.intellij.openapi.roots.CompilerModuleExtension; import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.idea.maven.MavenImportingTestCase; -import org.jetbrains.idea.maven.importing.MavenDefaultModifiableModelsProvider; -import org.jetbrains.idea.maven.importing.MavenRootModelAdapter; -import org.jetbrains.idea.maven.indices.MavenCustomRepositoryHelper; +import org.jetbrains.idea.maven.MavenCustomRepositoryHelper; import org.jetbrains.idea.maven.utils.Path; import java.io.File; diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/InvalidProjectImportingTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/InvalidProjectImportingTest.java index 5189db5dd78c..d35a13b1f4a8 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/InvalidProjectImportingTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/InvalidProjectImportingTest.java @@ -15,10 +15,10 @@ */ package org.jetbrains.idea.maven.importing; +import org.jetbrains.idea.maven.MavenCustomRepositoryHelper; import org.jetbrains.idea.maven.MavenImportingTestCase; -import org.jetbrains.idea.maven.indices.MavenCustomRepositoryHelper; import org.jetbrains.idea.maven.project.MavenProject; -import org.jetbrains.idea.maven.project.MavenProjectProblem; +import org.jetbrains.idea.maven.model.MavenProjectProblem; import java.util.ArrayList; import java.util.List; diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/MiscImportingTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/MiscImportingTest.java index 6f18da54b66e..a81fb83caeb4 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/MiscImportingTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/MiscImportingTest.java @@ -21,10 +21,9 @@ import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.roots.ModuleRootEvent; import com.intellij.openapi.roots.ModuleRootListener; +import org.jetbrains.idea.maven.MavenCustomRepositoryHelper; import org.jetbrains.idea.maven.MavenImportingTestCase; -import org.jetbrains.idea.maven.importing.MavenDefaultModifiableModelsProvider; -import org.jetbrains.idea.maven.indices.MavenCustomRepositoryHelper; -import org.jetbrains.idea.maven.project.MavenProjectProblem; +import org.jetbrains.idea.maven.model.MavenProjectProblem; import java.io.File; import java.util.List; diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenIndicesManagerTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenIndicesManagerTest.java index 8c111a958d0b..ad4c0e9a93e2 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenIndicesManagerTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenIndicesManagerTest.java @@ -16,6 +16,7 @@ package org.jetbrains.idea.maven.indices; import com.intellij.openapi.util.Pair; +import org.jetbrains.idea.maven.model.MavenArchetype; import java.io.File; import java.util.ArrayList; @@ -98,7 +99,7 @@ public class MavenIndicesManagerTest extends MavenIndicesTestCase { } public void testAddingArchetypes() throws Exception { - myIndicesFixture.getIndicesManager().addArchetype(new ArchetypeInfo("myGroup", + myIndicesFixture.getIndicesManager().addArchetype(new MavenArchetype("myGroup", "myArtifact", "666", null, @@ -113,9 +114,9 @@ public class MavenIndicesManagerTest extends MavenIndicesTestCase { } private void assertArchetypeExists(String archetypeId) { - Set achetypes = myIndicesFixture.getIndicesManager().getArchetypes(); + Set achetypes = myIndicesFixture.getIndicesManager().getArchetypes(); List actualNames = new ArrayList(); - for (ArchetypeInfo each : achetypes) { + for (MavenArchetype each : achetypes) { actualNames.add(each.groupId + ":" + each.artifactId + ":" + each.version); } assertTrue(actualNames.toString(), actualNames.contains(archetypeId)); diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenIndicesStressTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenIndicesStressTest.java index b51c2eaa5af6..3386520b7bef 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenIndicesStressTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenIndicesStressTest.java @@ -17,7 +17,10 @@ package org.jetbrains.idea.maven.indices; import com.intellij.openapi.progress.EmptyProgressIndicator; import com.intellij.openapi.progress.ProcessCanceledException; -import org.jetbrains.idea.maven.embedder.MavenEmbedderWrapper; +import org.jetbrains.idea.maven.MavenCustomRepositoryHelper; +import org.jetbrains.idea.maven.facade.MavenFacadeManager; +import org.jetbrains.idea.maven.facade.MavenIndexerWrapper; +import org.jetbrains.idea.maven.utils.MavenProcessCanceledException; import java.io.File; import java.util.Random; @@ -33,10 +36,10 @@ public abstract class MavenIndicesStressTest extends MavenIndicesTestCase implem helper.copy("local2", "local1"); //setRepositoryPath(fixture.getTestDataPath("local1")); - final MavenEmbedderWrapper embedder = MavenEmbedderWrapper.create(getMavenGeneralSettings()); + final MavenIndexerWrapper indexer = MavenFacadeManager.getInstance().createIndexer(); File indicesDir = new File(myDir, "indices"); - final MavenIndices indices = new MavenIndices(embedder, indicesDir, this); + final MavenIndices indices = new MavenIndices(indexer, indicesDir, this); final MavenIndex index = indices.add("id", getRepositoryPath(), MavenIndex.Kind.LOCAL); final AtomicBoolean isFinished = new AtomicBoolean(false); @@ -46,10 +49,10 @@ public abstract class MavenIndicesStressTest extends MavenIndicesTestCase implem try { for (int i = 0; i < 3; i++) { System.out.println("INDEXING #" + i); - indices.updateOrRepair(index, embedder, true, new EmptyProgressIndicator()); + indices.updateOrRepair(index, true, getMavenGeneralSettings(), EMPTY_MAVEN_PROCESS); } } - catch (ProcessCanceledException e) { + catch (MavenProcessCanceledException e) { throw new RuntimeException(e); } finally { @@ -93,18 +96,18 @@ public abstract class MavenIndicesStressTest extends MavenIndicesTestCase implem helper.copy("local2", "local1"); setRepositoryPath(helper.getTestDataPath("local1")); - MavenEmbedderWrapper embedder = MavenEmbedderWrapper.create(getMavenGeneralSettings()); + final MavenIndexerWrapper indexer = MavenFacadeManager.getInstance().createIndexer(); File indicesDir = new File(myDir, "indices"); - MavenIndices indices = new MavenIndices(embedder, indicesDir, this); + MavenIndices indices = new MavenIndices(indexer, indicesDir, this); MavenIndex index = indices.add("id", getRepositoryPath(), MavenIndex.Kind.LOCAL); //index.addArtifact(new MavenId("group1", "artifact1", "1")); fail(); indices.close(); - MavenIndices indices1 = new MavenIndices(embedder, indicesDir, this); - MavenIndices indices2 = new MavenIndices(embedder, indicesDir, this); + MavenIndices indices1 = new MavenIndices(indexer, indicesDir, this); + MavenIndices indices2 = new MavenIndices(indexer, indicesDir, this); AtomicInteger finishedCount = new AtomicInteger(0); diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenIndicesTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenIndicesTest.java index 2ef5eaee4ee1..5b95798475fa 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenIndicesTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenIndicesTest.java @@ -19,10 +19,12 @@ import com.intellij.openapi.progress.EmptyProgressIndicator; import com.intellij.openapi.util.io.FileUtil; import org.apache.lucene.index.Term; import org.apache.lucene.search.Query; -import org.apache.lucene.search.TermQuery; import org.apache.lucene.search.WildcardQuery; -import org.jetbrains.idea.maven.embedder.MavenEmbedderWrapper; -import org.sonatype.nexus.index.ArtifactInfo; +import org.jetbrains.idea.maven.MavenCustomRepositoryHelper; +import org.jetbrains.idea.maven.facade.MavenFacadeIndexer; +import org.jetbrains.idea.maven.facade.MavenFacadeManager; +import org.jetbrains.idea.maven.facade.MavenIndexerWrapper; +import org.jetbrains.idea.maven.model.MavenArtifactInfo; import java.io.File; import java.io.FileWriter; @@ -33,7 +35,7 @@ import java.util.List; public class MavenIndicesTest extends MavenIndicesTestCase { private MavenCustomRepositoryHelper myRepositoryHelper; private MavenIndices myIndices; - private MavenEmbedderWrapper myEmbedder; + private MavenIndexerWrapper myIndexer; private File myIndicesDir; private boolean isBroken; @@ -55,9 +57,9 @@ public class MavenIndicesTest extends MavenIndicesTestCase { } private void initIndices(String relativeDir) { - myEmbedder = MavenEmbedderWrapper.create(getMavenGeneralSettings()); + myIndexer = MavenFacadeManager.getInstance().createIndexer(); myIndicesDir = new File(myDir, relativeDir); - myIndices = new MavenIndices(myEmbedder, myIndicesDir, new MavenIndex.IndexListener() { + myIndices = new MavenIndices(myIndexer, myIndicesDir, new MavenIndex.IndexListener() { public void indexIsBroken(MavenIndex index) { isBroken = true; } @@ -66,12 +68,12 @@ public class MavenIndicesTest extends MavenIndicesTestCase { private void shutdownIndices() throws Exception { myIndices.close(); - myEmbedder.release(); + myIndexer.release(); } public void testCreatingAndUpdatingLocal() throws Exception { MavenIndex i = myIndices.add("id", myRepositoryHelper.getTestDataPath("local1"), MavenIndex.Kind.LOCAL); - myIndices.updateOrRepair(i, myEmbedder, true, new EmptyProgressIndicator()); + myIndices.updateOrRepair(i, true, getMavenGeneralSettings(), EMPTY_MAVEN_PROCESS); assertUnorderedElementsAreEqual(i.getGroupIds(), "junit"); } @@ -79,8 +81,8 @@ public class MavenIndicesTest extends MavenIndicesTestCase { public void testCreatingSeveral() throws Exception { MavenIndex i1 = myIndices.add("id1", myRepositoryHelper.getTestDataPath("local1"), MavenIndex.Kind.LOCAL); MavenIndex i2 = myIndices.add("id2", myRepositoryHelper.getTestDataPath("local2"), MavenIndex.Kind.LOCAL); - myIndices.updateOrRepair(i1, myEmbedder, true, new EmptyProgressIndicator()); - myIndices.updateOrRepair(i2, myEmbedder, true, new EmptyProgressIndicator()); + myIndices.updateOrRepair(i1, true, getMavenGeneralSettings(), EMPTY_MAVEN_PROCESS); + myIndices.updateOrRepair(i2, true, getMavenGeneralSettings(), EMPTY_MAVEN_PROCESS); assertUnorderedElementsAreEqual(i1.getGroupIds(), "junit"); assertUnorderedElementsAreEqual(i2.getGroupIds(), "jmock"); @@ -90,8 +92,8 @@ public class MavenIndicesTest extends MavenIndicesTestCase { MavenIndex i1 = myIndices.add("id", myRepositoryHelper.getTestDataPath("local1"), MavenIndex.Kind.LOCAL); MavenIndex i2 = myIndices.add("id", myRepositoryHelper.getTestDataPath("local2"), MavenIndex.Kind.LOCAL); assertNotSame(i1, i2); - myIndices.updateOrRepair(i1, myEmbedder, true, new EmptyProgressIndicator()); - myIndices.updateOrRepair(i2, myEmbedder, true, new EmptyProgressIndicator()); + myIndices.updateOrRepair(i1, true, getMavenGeneralSettings(), EMPTY_MAVEN_PROCESS); + myIndices.updateOrRepair(i2, true, getMavenGeneralSettings(), EMPTY_MAVEN_PROCESS); assertUnorderedElementsAreEqual(i1.getGroupIds(), "junit"); assertUnorderedElementsAreEqual(i2.getGroupIds(), "jmock"); @@ -101,9 +103,9 @@ public class MavenIndicesTest extends MavenIndicesTestCase { MavenIndex i1 = myIndices.add("id1", myRepositoryHelper.getTestDataPath("local1"), MavenIndex.Kind.LOCAL); MavenIndex i2 = myIndices.add("id2", myRepositoryHelper.getTestDataPath("local1"), MavenIndex.Kind.LOCAL); assertNotSame(i1, i2); - myIndices.updateOrRepair(i1, myEmbedder, true, new EmptyProgressIndicator()); - myIndices.updateOrRepair(i2, myEmbedder, true, new EmptyProgressIndicator()); - + myIndices.updateOrRepair(i1, true, getMavenGeneralSettings(), EMPTY_MAVEN_PROCESS); + myIndices.updateOrRepair(i2, true, getMavenGeneralSettings(), EMPTY_MAVEN_PROCESS); + assertUnorderedElementsAreEqual(i1.getGroupIds(), "junit"); assertUnorderedElementsAreEqual(i2.getGroupIds(), "junit"); } @@ -116,13 +118,13 @@ public class MavenIndicesTest extends MavenIndicesTestCase { public void testUpdatingLocalClearsPreviousIndex() throws Exception { MavenIndex i = myIndices.add("id", myRepositoryHelper.getTestDataPath("local1"), MavenIndex.Kind.LOCAL); - myIndices.updateOrRepair(i, myEmbedder, true, new EmptyProgressIndicator()); + myIndices.updateOrRepair(i, true, getMavenGeneralSettings(), EMPTY_MAVEN_PROCESS); assertUnorderedElementsAreEqual(i.getGroupIds(), "junit"); myRepositoryHelper.delete("local1"); myRepositoryHelper.copy("local2", "local1"); - myIndices.updateOrRepair(i, myEmbedder, true, new EmptyProgressIndicator()); + myIndices.updateOrRepair(i, true, getMavenGeneralSettings(), EMPTY_MAVEN_PROCESS); assertUnorderedElementsAreEqual(i.getGroupIds(), "jmock"); } @@ -138,17 +140,17 @@ public class MavenIndicesTest extends MavenIndicesTestCase { public void testAddingRemote() throws Exception { MavenIndex i = myIndices.add("id", "file:///" + myRepositoryHelper.getTestDataPath("remote"), MavenIndex.Kind.REMOTE); - myIndices.updateOrRepair(i, myEmbedder, true, new EmptyProgressIndicator()); + myIndices.updateOrRepair(i, true, getMavenGeneralSettings(), EMPTY_MAVEN_PROCESS); assertUnorderedElementsAreEqual(i.getGroupIds(), "junit"); } public void testUpdatingRemote() throws Exception { MavenIndex i = myIndices.add("id", "file:///" + myRepositoryHelper.getTestDataPath("remote"), MavenIndex.Kind.REMOTE); - myIndices.updateOrRepair(i, myEmbedder, true, new EmptyProgressIndicator()); + myIndices.updateOrRepair(i, true, getMavenGeneralSettings(), EMPTY_MAVEN_PROCESS); //shouldn't throw 'The existing index is for repository [remote] and not for repository [xxx]' - myIndices.updateOrRepair(i, myEmbedder, true, new EmptyProgressIndicator()); + myIndices.updateOrRepair(i, true, getMavenGeneralSettings(), EMPTY_MAVEN_PROCESS); assertUnorderedElementsAreEqual(i.getGroupIds(), "junit"); } @@ -173,19 +175,19 @@ public class MavenIndicesTest extends MavenIndicesTestCase { } public void testAddingCorrectlyToIndexer() throws Exception { - assertEquals(0, myIndices.getIndexer().getIndexingContexts().size()); + assertEquals(0, myIndexer.getIndexCount()); MavenIndex i1 = myIndices.add("local", myRepositoryHelper.getTestDataPath("local1"), MavenIndex.Kind.LOCAL); - assertEquals(1, myIndices.getIndexer().getIndexingContexts().size()); + assertEquals(1, myIndexer.getIndexCount()); MavenIndex i2 = myIndices.add("local", myRepositoryHelper.getTestDataPath("local2"), MavenIndex.Kind.LOCAL); - assertEquals(2, myIndices.getIndexer().getIndexingContexts().size()); + assertEquals(2, myIndexer.getIndexCount()); - myIndices.updateOrRepair(i1, myEmbedder, true, new EmptyProgressIndicator()); - assertEquals(2, myIndices.getIndexer().getIndexingContexts().size()); + myIndices.updateOrRepair(i1, true, getMavenGeneralSettings(), EMPTY_MAVEN_PROCESS); + assertEquals(2, myIndexer.getIndexCount()); - myIndices.updateOrRepair(i2, myEmbedder, true, new EmptyProgressIndicator()); - assertEquals(2, myIndices.getIndexer().getIndexingContexts().size()); + myIndices.updateOrRepair(i2, true, getMavenGeneralSettings(), EMPTY_MAVEN_PROCESS); + assertEquals(2, myIndexer.getIndexCount()); } public void testClearingIndexDirOnLoadError() throws Exception { @@ -220,8 +222,8 @@ public class MavenIndicesTest extends MavenIndicesTestCase { public void testLoadingIndexIfCachesAreBroken() throws Exception { MavenIndex i1 = myIndices.add("id", myRepositoryHelper.getTestDataPath("local1"), MavenIndex.Kind.LOCAL); MavenIndex i2 = myIndices.add("id", myRepositoryHelper.getTestDataPath("local2"), MavenIndex.Kind.LOCAL); - myIndices.updateOrRepair(i1, myEmbedder, true, new EmptyProgressIndicator()); - myIndices.updateOrRepair(i2, myEmbedder, true, new EmptyProgressIndicator()); + myIndices.updateOrRepair(i1, true, getMavenGeneralSettings(), EMPTY_MAVEN_PROCESS); + myIndices.updateOrRepair(i2, true, getMavenGeneralSettings(), EMPTY_MAVEN_PROCESS); assertUnorderedElementsAreEqual(i1.getGroupIds(), "junit"); assertUnorderedElementsAreEqual(i2.getGroupIds(), "jmock"); @@ -235,7 +237,7 @@ public class MavenIndicesTest extends MavenIndicesTestCase { assertTrue(myIndices.getIndices().get(0).getGroupIds().isEmpty()); assertUnorderedElementsAreEqual(myIndices.getIndices().get(1).getGroupIds(), "jmock"); - myIndices.updateOrRepair(myIndices.getIndices().get(0), myEmbedder, false, new EmptyProgressIndicator()); + myIndices.updateOrRepair(myIndices.getIndices().get(0), false, getMavenGeneralSettings(), EMPTY_MAVEN_PROCESS); assertUnorderedElementsAreEqual(myIndices.getIndices().get(0).getGroupIds(), "junit"); } @@ -255,18 +257,18 @@ public class MavenIndicesTest extends MavenIndicesTestCase { public void testAddingIndexWithExistingDirectoryDoesNotThrowException() throws Exception { MavenIndex i = myIndices.add("id", myRepositoryHelper.getTestDataPath("local1"), MavenIndex.Kind.LOCAL); - myIndices.updateOrRepair(i, myEmbedder, true, new EmptyProgressIndicator()); + myIndices.updateOrRepair(i, true, getMavenGeneralSettings(), EMPTY_MAVEN_PROCESS); shutdownIndices(); initIndices(); i = myIndices.add("id", myRepositoryHelper.getTestDataPath("local1"), MavenIndex.Kind.LOCAL); - myIndices.updateOrRepair(i, myEmbedder, true, new EmptyProgressIndicator()); + myIndices.updateOrRepair(i, true, getMavenGeneralSettings(), EMPTY_MAVEN_PROCESS); } public void testSavingFailureMessage() throws Exception { MavenIndex i = myIndices.add("id", "xxx", MavenIndex.Kind.REMOTE); - myIndices.updateOrRepair(i, myEmbedder, true, new EmptyProgressIndicator()); + myIndices.updateOrRepair(i, true, getMavenGeneralSettings(), EMPTY_MAVEN_PROCESS); String message = i.getFailureMessage(); assertNotNull(message); @@ -279,7 +281,7 @@ public class MavenIndicesTest extends MavenIndicesTestCase { public void testRepairingIndicesOnReadError() throws Exception { MavenIndex index = myIndices.add("id", myRepositoryHelper.getTestDataPath("local1"), MavenIndex.Kind.LOCAL); - myIndices.updateOrRepair(index, myEmbedder, true, new EmptyProgressIndicator()); + myIndices.updateOrRepair(index, true, getMavenGeneralSettings(), EMPTY_MAVEN_PROCESS); shutdownIndices(); damageFile(index, "groupIds.dat", false); @@ -292,13 +294,13 @@ public class MavenIndicesTest extends MavenIndicesTestCase { assertTrue(index.getGroupIds().isEmpty()); - myIndices.updateOrRepair(myIndices.getIndices().get(0), myEmbedder, false, new EmptyProgressIndicator()); + myIndices.updateOrRepair(myIndices.getIndices().get(0), false, getMavenGeneralSettings(), EMPTY_MAVEN_PROCESS); assertUnorderedElementsAreEqual(index.getGroupIds(), "junit"); } public void testRepairingIndicesOnReadWhileAddingArtifact() throws Exception { MavenIndex index = myIndices.add("id", myRepositoryHelper.getTestDataPath("local1"), MavenIndex.Kind.LOCAL); - myIndices.updateOrRepair(index, myEmbedder, true, new EmptyProgressIndicator()); + myIndices.updateOrRepair(index, true, getMavenGeneralSettings(), EMPTY_MAVEN_PROCESS); shutdownIndices(); damageFile(index, "artifactIds-map.dat", false); @@ -311,7 +313,7 @@ public class MavenIndicesTest extends MavenIndicesTestCase { assertTrue(index.getGroupIds().isEmpty()); - myIndices.updateOrRepair(myIndices.getIndices().get(0), myEmbedder, false, new EmptyProgressIndicator()); + myIndices.updateOrRepair(myIndices.getIndices().get(0), false, getMavenGeneralSettings(), EMPTY_MAVEN_PROCESS); assertUnorderedElementsAreEqual(index.getGroupIds(), "junit"); } @@ -337,7 +339,7 @@ public class MavenIndicesTest extends MavenIndicesTestCase { public void testGettingArtifactInfos() throws Exception { myRepositoryHelper.copy("local2", "local1"); MavenIndex i = myIndices.add("id", myRepositoryHelper.getTestDataPath("local1"), MavenIndex.Kind.LOCAL); - myIndices.updateOrRepair(i, myEmbedder, true, new EmptyProgressIndicator()); + myIndices.updateOrRepair(i, true, getMavenGeneralSettings(), EMPTY_MAVEN_PROCESS); assertUnorderedElementsAreEqual(i.getGroupIds(), "junit", "jmock"); @@ -357,9 +359,8 @@ public class MavenIndicesTest extends MavenIndicesTestCase { public void testGettingArtifactInfosAfterReload() throws Exception { myIndices.updateOrRepair(myIndices.add("id", myRepositoryHelper.getTestDataPath("local1"), MavenIndex.Kind.LOCAL), - myEmbedder, true, - new EmptyProgressIndicator()); + getMavenGeneralSettings(), EMPTY_MAVEN_PROCESS); shutdownIndices(); initIndices(); @@ -370,7 +371,7 @@ public class MavenIndicesTest extends MavenIndicesTestCase { public void testHasArtifactInfo() throws Exception { myRepositoryHelper.copy("local2", "local1"); MavenIndex i = myIndices.add("id", myRepositoryHelper.getTestDataPath("local1"), MavenIndex.Kind.LOCAL); - myIndices.updateOrRepair(i, myEmbedder, true, new EmptyProgressIndicator()); + myIndices.updateOrRepair(i, true, getMavenGeneralSettings(), EMPTY_MAVEN_PROCESS); assertTrue(i.hasGroupId("junit")); assertTrue(i.hasGroupId("jmock")); @@ -387,45 +388,42 @@ public class MavenIndicesTest extends MavenIndicesTestCase { public void testSearching() throws Exception { MavenIndex i = myIndices.add("id", myRepositoryHelper.getTestDataPath("local1"), MavenIndex.Kind.LOCAL); - myIndices.updateOrRepair(i, myEmbedder, true, new EmptyProgressIndicator()); + myIndices.updateOrRepair(i, true, getMavenGeneralSettings(), EMPTY_MAVEN_PROCESS); - assertSearchResults(i, new TermQuery(new Term(ArtifactInfo.GROUP_ID, "junit")), + assertSearchResults(i, new WildcardQuery(new Term(MavenFacadeIndexer.SEARCH_TERM_COORDINATES, "*junit*")), "junit:junit:3.8.1", "junit:junit:3.8.2", "junit:junit:4.0"); } public void testSearchingAfterArtifactAddition() throws Exception { MavenIndex i = myIndices.add("id", myRepositoryHelper.getTestDataPath("local1"), MavenIndex.Kind.LOCAL); - myIndices.updateOrRepair(i, myEmbedder, true, new EmptyProgressIndicator()); + myIndices.updateOrRepair(i, true, getMavenGeneralSettings(), EMPTY_MAVEN_PROCESS); i.addArtifact(new File(myRepositoryHelper.getTestDataPath("local2/jmock/jmock/1.0.0/jmock-1.0.0.jar"))); - assertSearchResults(i, new TermQuery(new Term(ArtifactInfo.GROUP_ID, "jmock")), - "jmock:jmock:1.0.0"); + assertSearchResults(i, new WildcardQuery(new Term(MavenFacadeIndexer.SEARCH_TERM_COORDINATES, "*jmock*")), "jmock:jmock:1.0.0"); } private void assertSearchResults(MavenIndex i, Query query, String... expectedArtifacts) { List actualArtifacts = new ArrayList(); - for (ArtifactInfo each : i.search(query, 100)) { - actualArtifacts.add(each.groupId + ":" + each.artifactId + ":" + each.version); + for (MavenArtifactInfo each : i.search(query, 100)) { + actualArtifacts.add(each.getGroupId() + ":" + each.getArtifactId() + ":" + each.getVersion()); } assertUnorderedElementsAreEqual(actualArtifacts, expectedArtifacts); } public void testSearchingForClasses() throws Exception { MavenIndex i = myIndices.add("id", myRepositoryHelper.getTestDataPath("local1"), MavenIndex.Kind.LOCAL); - myIndices.updateOrRepair(i, myEmbedder, true, new EmptyProgressIndicator()); + myIndices.updateOrRepair(i, true, getMavenGeneralSettings(), EMPTY_MAVEN_PROCESS); - assertSearchResults(i, new WildcardQuery(new Term(ArtifactInfo.NAMES, "*runwith*")), - "junit:junit:4.0"); + assertSearchResults(i, new WildcardQuery(new Term(MavenFacadeIndexer.SEARCH_TERM_CLASS_NAMES, "*runwith*")), "junit:junit:4.0"); } public void testSearchingForClassesAfterArtifactAddition() throws Exception { MavenIndex i = myIndices.add("id", myRepositoryHelper.getTestDataPath("local1"), MavenIndex.Kind.LOCAL); - myIndices.updateOrRepair(i, myEmbedder, true, new EmptyProgressIndicator()); + myIndices.updateOrRepair(i, true, getMavenGeneralSettings(), EMPTY_MAVEN_PROCESS); i.addArtifact(new File(myRepositoryHelper.getTestDataPath("local2/jmock/jmock/1.0.0/jmock-1.0.0.jar"))); - assertSearchResults(i, new WildcardQuery(new Term(ArtifactInfo.NAMES, "*mock*")), - "jmock:jmock:1.0.0"); + assertSearchResults(i, new WildcardQuery(new Term(MavenFacadeIndexer.SEARCH_TERM_CLASS_NAMES, "*mock*")), "jmock:jmock:1.0.0"); } } diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenIndicesTestFixture.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenIndicesTestFixture.java index bb99d5dcfcbd..32acbc98daa2 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenIndicesTestFixture.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenIndicesTestFixture.java @@ -17,6 +17,7 @@ package org.jetbrains.idea.maven.indices; import com.intellij.openapi.project.Project; import com.intellij.util.ArrayUtil; +import org.jetbrains.idea.maven.MavenCustomRepositoryHelper; import org.jetbrains.idea.maven.project.MavenProjectsManager; import java.io.File; @@ -49,7 +50,7 @@ public class MavenIndicesTestFixture { addToRepository(each); } - MavenProjectsManager.getInstance(myProject).getGeneralSettings().setLocalRepository(myRepositoryHelper.getTestDataPath(myLocalRepoDir)); + MavenProjectsManager.getInstance(myProject).getGeneralSettings().setOverridenLocalRepository(myRepositoryHelper.getTestDataPath(myLocalRepoDir)); getIndicesManager().setTestIndexDir(new File(myDir, "MavenIndices")); myIndicesManager = MavenProjectIndicesManager.getInstance(myProject); diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenPluginInfoReaderTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenPluginInfoReaderTest.java index 8dfc5ed8f59f..f397347e4e64 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenPluginInfoReaderTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenPluginInfoReaderTest.java @@ -15,8 +15,9 @@ */ package org.jetbrains.idea.maven.indices; +import org.jetbrains.idea.maven.MavenCustomRepositoryHelper; import org.jetbrains.idea.maven.MavenTestCase; -import org.jetbrains.idea.maven.project.MavenId; +import org.jetbrains.idea.maven.model.MavenId; import org.jetbrains.idea.maven.utils.MavenPluginInfo; import org.jetbrains.idea.maven.utils.MavenArtifactUtil; diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenSearcherTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenSearcherTest.java index 2aef5165cab6..8ee0e5599192 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenSearcherTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/indices/MavenSearcherTest.java @@ -15,7 +15,7 @@ */ package org.jetbrains.idea.maven.indices; -import org.sonatype.nexus.index.ArtifactInfo; +import org.jetbrains.idea.maven.model.MavenArtifactInfo; import java.util.ArrayList; import java.util.List; @@ -114,9 +114,9 @@ public class MavenSearcherTest extends MavenIndicesTestCase { List actualArtifacts = new ArrayList(); for (MavenClassSearchResult eachResult : new MavenClassSearcher().search(myProject, pattern, 100)) { String s = eachResult.className + "(" + eachResult.packageName + ")"; - for (ArtifactInfo eachVersion : eachResult.versions) { + for (MavenArtifactInfo eachVersion : eachResult.versions) { if (s.length() > 0) s += " "; - s += eachVersion.groupId + ":" + eachVersion.artifactId + ":" + eachVersion.version; + s += eachVersion.getGroupId() + ":" + eachVersion.getArtifactId()+ ":" + eachVersion.getVersion(); } actualArtifacts.add(s); } @@ -127,9 +127,9 @@ public class MavenSearcherTest extends MavenIndicesTestCase { List actual = new ArrayList(); for (MavenArtifactSearchResult eachResult : new MavenArtifactSearcher().search(myProject, pattern, 100)) { String s = ""; - for (ArtifactInfo eachVersion : eachResult.versions) { + for (MavenArtifactInfo eachVersion : eachResult.versions) { if (s.length() > 0) s += " "; - s += eachVersion.groupId + ":" + eachVersion.artifactId + ":" + eachVersion.version; + s += eachVersion.getGroupId() + ":" + eachVersion.getArtifactId()+ ":" + eachVersion.getVersion(); } actual.add(s); } diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenEmbeddersManagerTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenEmbeddersManagerTest.java index a7b2bc63c3cf..fa95be7dc646 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenEmbeddersManagerTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenEmbeddersManagerTest.java @@ -16,7 +16,7 @@ package org.jetbrains.idea.maven.project; import org.jetbrains.idea.maven.MavenTestCase; -import org.jetbrains.idea.maven.embedder.MavenEmbedderWrapper; +import org.jetbrains.idea.maven.facade.MavenEmbedderWrapper; public class MavenEmbeddersManagerTest extends MavenTestCase { private MavenEmbeddersManager myManager; @@ -24,7 +24,7 @@ public class MavenEmbeddersManagerTest extends MavenTestCase { @Override protected void setUp() throws Exception { super.setUp(); - myManager = new MavenEmbeddersManager(getMavenGeneralSettings()); + myManager = new MavenEmbeddersManager(myProject); } @Override @@ -34,52 +34,52 @@ public class MavenEmbeddersManagerTest extends MavenTestCase { } public void testBasics() throws Exception { - MavenEmbedderWrapper one = myManager.getEmbedder(MavenEmbeddersManager.EmbedderKind.FOR_FOLDERS_RESOLVE); - MavenEmbedderWrapper two = myManager.getEmbedder(MavenEmbeddersManager.EmbedderKind.FOR_DEPENDENCIES_RESOLVE); + MavenEmbedderWrapper one = myManager.getEmbedder(MavenEmbeddersManager.FOR_FOLDERS_RESOLVE); + MavenEmbedderWrapper two = myManager.getEmbedder(MavenEmbeddersManager.FOR_DEPENDENCIES_RESOLVE); assertNotSame(one, two); } public void testForSameId() throws Exception { - MavenEmbedderWrapper one1 = myManager.getEmbedder(MavenEmbeddersManager.EmbedderKind.FOR_DEPENDENCIES_RESOLVE); - MavenEmbedderWrapper one2 = myManager.getEmbedder(MavenEmbeddersManager.EmbedderKind.FOR_DEPENDENCIES_RESOLVE); + MavenEmbedderWrapper one1 = myManager.getEmbedder(MavenEmbeddersManager.FOR_DEPENDENCIES_RESOLVE); + MavenEmbedderWrapper one2 = myManager.getEmbedder(MavenEmbeddersManager.FOR_DEPENDENCIES_RESOLVE); assertNotSame(one1, one2); myManager.release(one1); - MavenEmbedderWrapper one3 = myManager.getEmbedder(MavenEmbeddersManager.EmbedderKind.FOR_DEPENDENCIES_RESOLVE); + MavenEmbedderWrapper one3 = myManager.getEmbedder(MavenEmbeddersManager.FOR_DEPENDENCIES_RESOLVE); assertSame(one1, one3); } public void testCachingOnlyOne() throws Exception { - MavenEmbedderWrapper one1 = myManager.getEmbedder(MavenEmbeddersManager.EmbedderKind.FOR_DEPENDENCIES_RESOLVE); - MavenEmbedderWrapper one2 = myManager.getEmbedder(MavenEmbeddersManager.EmbedderKind.FOR_DEPENDENCIES_RESOLVE); + MavenEmbedderWrapper one1 = myManager.getEmbedder(MavenEmbeddersManager.FOR_DEPENDENCIES_RESOLVE); + MavenEmbedderWrapper one2 = myManager.getEmbedder(MavenEmbeddersManager.FOR_DEPENDENCIES_RESOLVE); assertNotSame(one1, one2); myManager.release(one1); myManager.release(one2); - MavenEmbedderWrapper one11 = myManager.getEmbedder(MavenEmbeddersManager.EmbedderKind.FOR_DEPENDENCIES_RESOLVE); - MavenEmbedderWrapper one22 = myManager.getEmbedder(MavenEmbeddersManager.EmbedderKind.FOR_DEPENDENCIES_RESOLVE); + MavenEmbedderWrapper one11 = myManager.getEmbedder(MavenEmbeddersManager.FOR_DEPENDENCIES_RESOLVE); + MavenEmbedderWrapper one22 = myManager.getEmbedder(MavenEmbeddersManager.FOR_DEPENDENCIES_RESOLVE); assertSame(one1, one11); assertNotSame(one2, one22); } public void testResettingAllCachedAndInUse() throws Exception { - MavenEmbedderWrapper one1 = myManager.getEmbedder(MavenEmbeddersManager.EmbedderKind.FOR_DEPENDENCIES_RESOLVE); - MavenEmbedderWrapper one2 = myManager.getEmbedder(MavenEmbeddersManager.EmbedderKind.FOR_FOLDERS_RESOLVE); + MavenEmbedderWrapper one1 = myManager.getEmbedder(MavenEmbeddersManager.FOR_DEPENDENCIES_RESOLVE); + MavenEmbedderWrapper one2 = myManager.getEmbedder(MavenEmbeddersManager.FOR_FOLDERS_RESOLVE); myManager.release(one1); myManager.reset(); myManager.release(one2); - MavenEmbedderWrapper one11 = myManager.getEmbedder(MavenEmbeddersManager.EmbedderKind.FOR_DEPENDENCIES_RESOLVE); - MavenEmbedderWrapper one22 = myManager.getEmbedder(MavenEmbeddersManager.EmbedderKind.FOR_FOLDERS_RESOLVE); + MavenEmbedderWrapper one11 = myManager.getEmbedder(MavenEmbeddersManager.FOR_DEPENDENCIES_RESOLVE); + MavenEmbedderWrapper one22 = myManager.getEmbedder(MavenEmbeddersManager.FOR_FOLDERS_RESOLVE); assertNotSame(one1, one11); assertNotSame(one2, one22); diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectReaderTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectReaderTest.java index efd4e6bf6b91..1bb850520a86 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectReaderTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectReaderTest.java @@ -21,12 +21,9 @@ import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; -import org.apache.maven.model.Build; -import org.apache.maven.model.Parent; -import org.apache.maven.model.Profile; -import org.apache.maven.model.Resource; import org.jetbrains.idea.maven.MavenTestCase; -import org.jetbrains.idea.maven.embedder.MavenEmbedderWrapper; +import org.jetbrains.idea.maven.facade.MavenFacadeUtil; +import org.jetbrains.idea.maven.model.*; import org.jetbrains.idea.maven.utils.MavenUtil; import java.io.File; @@ -41,10 +38,7 @@ public class MavenProjectReaderTest extends MavenTestCase { "project" + "1"); - org.apache.maven.project.MavenProject p = readProject(myProjectPom); - - assertEquals(new File(myProjectPom.getPath()), p.getFile()); - assertEquals(new File(myProjectRoot.getPath()), p.getBasedir()); + MavenId p = readProject(myProjectPom).getMavenId(); assertEquals("test", p.getGroupId()); assertEquals("project", p.getArtifactId()); @@ -67,10 +61,7 @@ public class MavenProjectReaderTest extends MavenTestCase { MavenProjectReaderResult result = readProject(myProjectPom, new NullProjectLocator()); assertProblems(result, "'pom.xml' has syntax errors"); - org.apache.maven.project.MavenProject p = result.nativeMavenProject; - - assertEquals(new File(myProjectPom.getPath()), p.getFile()); - assertEquals(new File(myProjectRoot.getPath()), p.getBasedir()); + MavenId p = result.mavenModel.getMavenId(); assertEquals("test", p.getGroupId()); assertEquals("project", p.getArtifactId()); @@ -88,7 +79,7 @@ public class MavenProjectReaderTest extends MavenTestCase { MavenProjectReaderResult result = readProject(myProjectPom, new NullProjectLocator()); assertProblems(result, "'pom.xml' has syntax errors"); - org.apache.maven.project.MavenProject p = result.nativeMavenProject; + MavenModel p = result.mavenModel; assertEquals("a0x0a", p.getName()); } @@ -158,14 +149,11 @@ public class MavenProjectReaderTest extends MavenTestCase { MavenProjectReaderResult readResult = readProject(myProjectPom, new NullProjectLocator()); assertProblems(readResult, "'pom.xml' has syntax errors"); - org.apache.maven.project.MavenProject p = readResult.nativeMavenProject; + MavenModel p = readResult.mavenModel; - assertEquals(new File(myProjectPom.getPath()), p.getFile()); - assertEquals(new File(myProjectRoot.getPath()), p.getBasedir()); - - assertEquals("test", p.getGroupId()); - assertEquals("project", p.getArtifactId()); - assertEquals("Unknown", p.getVersion()); + assertEquals("test", p.getMavenId().getGroupId()); + assertEquals("project", p.getMavenId().getArtifactId()); + assertEquals("Unknown", p.getMavenId().getVersion()); assertEquals("foo", p.getName()); } @@ -179,38 +167,35 @@ public class MavenProjectReaderTest extends MavenTestCase { MavenProjectReaderResult readResult = readProject(myProjectPom, new NullProjectLocator()); assertProblems(readResult, "'pom.xml' has syntax errors"); - org.apache.maven.project.MavenProject p = readResult.nativeMavenProject; + MavenModel p = readResult.mavenModel; - assertEquals(new File(myProjectPom.getPath()), p.getFile()); - assertEquals(new File(myProjectRoot.getPath()), p.getBasedir()); - - assertEquals("test", p.getGroupId()); - assertEquals("project", p.getArtifactId()); - assertEquals("1", p.getVersion()); + assertEquals("test", p.getMavenId().getGroupId()); + assertEquals("project", p.getMavenId().getArtifactId()); + assertEquals("1", p.getMavenId().getVersion()); assertEquals("foo", p.getName()); } public void testEmpty() throws Exception { createProjectPom(""); - org.apache.maven.project.MavenProject p = readProject(myProjectPom); + MavenModel p = readProject(myProjectPom); - assertEquals("Unknown", p.getGroupId()); - assertEquals("Unknown", p.getArtifactId()); - assertEquals("Unknown", p.getVersion()); + assertEquals("Unknown", p.getMavenId().getGroupId()); + assertEquals("Unknown", p.getMavenId().getArtifactId()); + assertEquals("Unknown", p.getMavenId().getVersion()); } public void testSpacesInTest() throws Exception { createProjectPom("foo bar"); - org.apache.maven.project.MavenProject p = readProject(myProjectPom); + MavenModel p = readProject(myProjectPom); assertEquals("foo bar", p.getName()); } public void testTextInContainerTag() throws Exception { createProjectPom("foo name bar"); - org.apache.maven.project.MavenProject p = readProject(myProjectPom); + MavenModel p = readProject(myProjectPom); assertEquals("name", p.getName()); } @@ -222,30 +207,27 @@ public class MavenProjectReaderTest extends MavenTestCase { " 1" + ""); - org.apache.maven.project.MavenProject p = readProject(file); + MavenModel p = readProject(file); - assertEquals("4.0.0", p.getModelVersion()); assertEquals("jar", p.getPackaging()); - assertNull(p.getModel().getName()); + assertNull(p.getName()); assertNull(p.getParent()); - assertNull(p.getParentArtifact()); - Build build = p.getBuild(); - assertNotNull(build); - assertEquals("project-1", build.getFinalName()); - assertEquals(null, build.getDefaultGoal()); - assertPathEquals(pathFromBasedir("src/main/java"), build.getSourceDirectory()); - assertPathEquals(pathFromBasedir("src/test/java"), build.getTestSourceDirectory()); - assertPathEquals(pathFromBasedir("src/main/scripts"), build.getScriptSourceDirectory()); - assertEquals(1, build.getResources().size()); - assertResource((Resource)build.getResources().get(0), pathFromBasedir("src/main/resources"), + assertEquals("project-1", p.getBuild().getFinalName()); + assertEquals(null, p.getBuild().getDefaultGoal()); + assertSize(1, p.getBuild().getSources()); + assertPathEquals(pathFromBasedir("src/main/java"), p.getBuild().getSources().get(0)); + assertSize(1, p.getBuild().getTestSources()); + assertPathEquals(pathFromBasedir("src/test/java"), p.getBuild().getTestSources().get(0)); + assertEquals(1, p.getBuild().getResources().size()); + assertResource(p.getBuild().getResources().get(0), pathFromBasedir("src/main/resources"), false, null, Collections.EMPTY_LIST, Collections.EMPTY_LIST); - assertEquals(1, build.getTestResources().size()); - assertResource((Resource)build.getTestResources().get(0), pathFromBasedir("src/test/resources"), + assertEquals(1, p.getBuild().getTestResources().size()); + assertResource(p.getBuild().getTestResources().get(0), pathFromBasedir("src/test/resources"), false, null, Collections.EMPTY_LIST, Collections.EMPTY_LIST); - assertPathEquals(pathFromBasedir("target"), build.getDirectory()); - assertPathEquals(pathFromBasedir("target/classes"), build.getOutputDirectory()); - assertPathEquals(pathFromBasedir("target/test-classes"), build.getTestOutputDirectory()); + assertPathEquals(pathFromBasedir("target"), p.getBuild().getDirectory()); + assertPathEquals(pathFromBasedir("target/classes"), p.getBuild().getOutputDirectory()); + assertPathEquals(pathFromBasedir("target/test-classes"), p.getBuild().getTestOutputDirectory()); } public void testDefaultsForParent() throws Exception { @@ -257,9 +239,9 @@ public class MavenProjectReaderTest extends MavenTestCase { " dummy" + ""); - org.apache.maven.project.MavenProject p = readProject(myProjectPom); + MavenModel p = readProject(myProjectPom); - assertParent(p, "Unknown", "Unknown", "Unknown", "../pom.xml"); + assertParent(p, "Unknown", "Unknown", "Unknown"); } public void testTakingCoordinatesFromParent() throws Exception { @@ -269,11 +251,11 @@ public class MavenProjectReaderTest extends MavenTestCase { " 1" + ""); - org.apache.maven.project.MavenProject p = readProject(myProjectPom); + MavenId id = readProject(myProjectPom).getMavenId(); - assertEquals("test", p.getGroupId()); - assertEquals("Unknown", p.getArtifactId()); - assertEquals("1", p.getVersion()); + assertEquals("test", id.getGroupId()); + assertEquals("Unknown", id.getArtifactId()); + assertEquals("1", id.getVersion()); } public void testCustomSettings() throws Exception { @@ -320,30 +302,28 @@ public class MavenProjectReaderTest extends MavenTestCase { " " + ""); - org.apache.maven.project.MavenProject p = readProject(file); + MavenModel p = readProject(file); - assertEquals("1.2.3", p.getModelVersion()); assertEquals("pom", p.getPackaging()); assertEquals("foo", p.getName()); - assertParent(p, "testParent", "projectParent", "2", "../parent/pom.xml"); + assertParent(p, "testParent", "projectParent", "2"); - Build build = p.getBuild(); - assertNotNull(build); - assertEquals("xxx", build.getFinalName()); - assertEquals("someGoal", build.getDefaultGoal()); - assertPathEquals(pathFromBasedir("mySrc"), build.getSourceDirectory()); - assertPathEquals(pathFromBasedir("myTestSrc"), build.getTestSourceDirectory()); - assertPathEquals(pathFromBasedir("myScriptSrc"), build.getScriptSourceDirectory()); - assertEquals(1, build.getResources().size()); - assertResource((Resource)build.getResources().get(0), pathFromBasedir("myRes"), + assertEquals("xxx", p.getBuild().getFinalName()); + assertEquals("someGoal", p.getBuild().getDefaultGoal()); + assertSize(1, p.getBuild().getSources()); + assertPathEquals(pathFromBasedir("mySrc"), p.getBuild().getSources().get(0)); + assertSize(1, p.getBuild().getTestSources()); + assertPathEquals(pathFromBasedir("myTestSrc"), p.getBuild().getTestSources().get(0)); + assertEquals(1, p.getBuild().getResources().size()); + assertResource(p.getBuild().getResources().get(0), pathFromBasedir("myRes"), true, "dir", Collections.singletonList("**.properties"), Collections.singletonList("**.xml")); - assertEquals(1, build.getTestResources().size()); - assertResource((Resource)build.getTestResources().get(0), pathFromBasedir("myTestRes"), + assertEquals(1, p.getBuild().getTestResources().size()); + assertResource(p.getBuild().getTestResources().get(0), pathFromBasedir("myTestRes"), false, null, Collections.singletonList("**.properties"), Collections.EMPTY_LIST); - assertPathEquals(pathFromBasedir("myOutput"), build.getDirectory()); - assertPathEquals(pathFromBasedir("myClasses"), build.getOutputDirectory()); - assertPathEquals(pathFromBasedir("myTestClasses"), build.getTestOutputDirectory()); + assertPathEquals(pathFromBasedir("myOutput"), p.getBuild().getDirectory()); + assertPathEquals(pathFromBasedir("myClasses"), p.getBuild().getOutputDirectory()); + assertPathEquals(pathFromBasedir("myTestClasses"), p.getBuild().getTestOutputDirectory()); } public void testOutputPathsAreBasedOnTargetPath() throws Exception { @@ -354,13 +334,11 @@ public class MavenProjectReaderTest extends MavenTestCase { " my-target" + ""); - org.apache.maven.project.MavenProject p = readProject(myProjectPom); + MavenModel p = readProject(myProjectPom); - Build build = p.getBuild(); - assertNotNull(build); - assertPathEquals(pathFromBasedir("my-target"), build.getDirectory()); - assertPathEquals(pathFromBasedir("my-target/classes"), build.getOutputDirectory()); - assertPathEquals(pathFromBasedir("my-target/test-classes"), build.getTestOutputDirectory()); + assertPathEquals(pathFromBasedir("my-target"), p.getBuild().getDirectory()); + assertPathEquals(pathFromBasedir("my-target/classes"), p.getBuild().getOutputDirectory()); + assertPathEquals(pathFromBasedir("my-target/test-classes"), p.getBuild().getTestOutputDirectory()); } public void testDoesNotIncludeResourcesWithoutDirectory() throws Exception { @@ -377,11 +355,10 @@ public class MavenProjectReaderTest extends MavenTestCase { " " + ""); - org.apache.maven.project.MavenProject p = readProject(myProjectPom); + MavenModel p = readProject(myProjectPom); - Build build = p.getBuild(); - assertEquals(0, build.getResources().size()); - assertEquals(0, build.getTestResources().size()); + assertEquals(0, p.getBuild().getResources().size()); + assertEquals(0, p.getBuild().getTestResources().size()); } public void testPathsWithProperties() throws Exception { @@ -407,21 +384,21 @@ public class MavenProjectReaderTest extends MavenTestCase { " ${foo}/myTestClasses" + ""); - org.apache.maven.project.MavenProject p = readProject(myProjectPom); + MavenModel p = readProject(myProjectPom); - Build build = p.getBuild(); - assertPathEquals(pathFromBasedir("subDir/mySrc"), build.getSourceDirectory()); - assertPathEquals(pathFromBasedir("subDir/myTestSrc"), build.getTestSourceDirectory()); - assertPathEquals(pathFromBasedir("subDir/myScriptSrc"), build.getScriptSourceDirectory()); - assertEquals(1, build.getResources().size()); - assertResource((Resource)build.getResources().get(0), pathFromBasedir("subDir/myRes"), + assertSize(1, p.getBuild().getSources()); + assertPathEquals(pathFromBasedir("subDir/mySrc"), p.getBuild().getSources().get(0)); + assertSize(1, p.getBuild().getTestSources()); + assertPathEquals(pathFromBasedir("subDir/myTestSrc"), p.getBuild().getTestSources().get(0)); + assertEquals(1, p.getBuild().getResources().size()); + assertResource(p.getBuild().getResources().get(0), pathFromBasedir("subDir/myRes"), false, null, Collections.EMPTY_LIST, Collections.EMPTY_LIST); - assertEquals(1, build.getTestResources().size()); - assertResource((Resource)build.getTestResources().get(0), pathFromBasedir("subDir/myTestRes"), + assertEquals(1, p.getBuild().getTestResources().size()); + assertResource(p.getBuild().getTestResources().get(0), pathFromBasedir("subDir/myTestRes"), false, null, Collections.EMPTY_LIST, Collections.EMPTY_LIST); - assertPathEquals(pathFromBasedir("subDir/myOutput"), build.getDirectory()); - assertPathEquals(pathFromBasedir("subDir/myClasses"), build.getOutputDirectory()); - assertPathEquals(pathFromBasedir("subDir/myTestClasses"), build.getTestOutputDirectory()); + assertPathEquals(pathFromBasedir("subDir/myOutput"), p.getBuild().getDirectory()); + assertPathEquals(pathFromBasedir("subDir/myClasses"), p.getBuild().getOutputDirectory()); + assertPathEquals(pathFromBasedir("subDir/myTestClasses"), p.getBuild().getTestOutputDirectory()); } public void testExpandingProperties() throws Exception { @@ -432,7 +409,7 @@ public class MavenProjectReaderTest extends MavenTestCase { "${prop1}" + "${prop2}"); - org.apache.maven.project.MavenProject p = readProject(myProjectPom); + MavenModel p = readProject(myProjectPom); assertEquals("value1", p.getName()); assertEquals("value2", p.getPackaging()); @@ -446,7 +423,7 @@ public class MavenProjectReaderTest extends MavenTestCase { "${prop1}" + "${prop2}"); - org.apache.maven.project.MavenProject p = readProject(myProjectPom); + MavenModel p = readProject(myProjectPom); assertEquals("value1", p.getName()); assertEquals("value12", p.getPackaging()); @@ -460,7 +437,7 @@ public class MavenProjectReaderTest extends MavenTestCase { "${prop1}" + "${prop2}"); - org.apache.maven.project.MavenProject p = readProject(myProjectPom); + MavenModel p = readProject(myProjectPom); assertEquals("${prop1}", p.getName()); assertEquals("${prop2}", p.getPackaging()); @@ -532,7 +509,7 @@ public class MavenProjectReaderTest extends MavenTestCase { createProjectPom("${java.home}" + "${env." + getEnvVar() + "}"); - org.apache.maven.project.MavenProject p = readProject(myProjectPom); + MavenModel p = readProject(myProjectPom); assertEquals(System.getProperty("java.home"), p.getName()); assertEquals(System.getenv(getEnvVar()), p.getPackaging()); } @@ -559,7 +536,7 @@ public class MavenProjectReaderTest extends MavenTestCase { "
    " + ""); - org.apache.maven.project.MavenProject p = readProject(myProjectPom); + MavenModel p = readProject(myProjectPom); assertEquals("value1", p.getName()); assertEquals("${prop2}", p.getPackaging()); } @@ -586,7 +563,7 @@ public class MavenProjectReaderTest extends MavenTestCase { "
    " + ""); - org.apache.maven.project.MavenProject p = readProject(myProjectPom, "two"); + MavenModel p = readProject(myProjectPom, "two"); assertEquals("${prop1}", p.getName()); assertEquals("value2", p.getPackaging()); } @@ -608,7 +585,7 @@ public class MavenProjectReaderTest extends MavenTestCase { "" + "${prop}"); - org.apache.maven.project.MavenProject p = readProject(module); + MavenModel p = readProject(module); assertEquals("value", p.getName()); } @@ -629,7 +606,7 @@ public class MavenProjectReaderTest extends MavenTestCase { "" + "${prop}"); - org.apache.maven.project.MavenProject p = readProject(module); + MavenModel p = readProject(module); assertEquals("${prop}", p.getName()); } @@ -651,7 +628,7 @@ public class MavenProjectReaderTest extends MavenTestCase { "" + "${prop}"); - org.apache.maven.project.MavenProject p = readProject(module); + MavenModel p = readProject(module); assertEquals("value", p.getName()); } @@ -683,7 +660,7 @@ public class MavenProjectReaderTest extends MavenTestCase { "" + "${prop}"); - org.apache.maven.project.MavenProject p = readProject(subModule); + MavenModel p = readProject(subModule); assertEquals("value", p.getName()); } @@ -706,7 +683,7 @@ public class MavenProjectReaderTest extends MavenTestCase { "" + "${prop}"); - org.apache.maven.project.MavenProject p = readProject(module); + MavenModel p = readProject(module); assertEquals("value", p.getName()); } @@ -729,7 +706,7 @@ public class MavenProjectReaderTest extends MavenTestCase { "" + "${prop}"); - org.apache.maven.project.MavenProject p = readProject(module); + MavenModel p = readProject(module); assertEquals("value", p.getName()); } @@ -755,7 +732,7 @@ public class MavenProjectReaderTest extends MavenTestCase { "" + "${prop}"); - org.apache.maven.project.MavenProject p = readProject(myProjectPom); + MavenModel p = readProject(myProjectPom); assertEquals("value", p.getName()); } @@ -777,11 +754,11 @@ public class MavenProjectReaderTest extends MavenTestCase { "" + "${prop}"); - org.apache.maven.project.MavenProject p = readProject(module, new MavenProjectReaderProjectLocator() { + MavenModel p = readProject(module, new MavenProjectReaderProjectLocator() { public VirtualFile findProjectFile(MavenId coordinates) { return new MavenId("test", "parent", "1").equals(coordinates) ? parent : null; } - }).nativeMavenProject; + }).mavenModel; assertEquals("value", p.getName()); } @@ -803,8 +780,8 @@ public class MavenProjectReaderTest extends MavenTestCase { "" + "module"); - org.apache.maven.project.MavenProject p = readProject(module); - assertEquals("test:module:1", p.getGroupId() + ":" + p.getArtifactId() + ":" + p.getVersion()); + MavenId id = readProject(module).getMavenId(); + assertEquals("test:module:1", id.getGroupId() + ":" + id.getArtifactId() + ":" + id.getVersion()); } public void testInheritingSettingsFromParentAndAlignCorrectly() throws Exception { @@ -822,7 +799,7 @@ public class MavenProjectReaderTest extends MavenTestCase { " 1" + ""); - org.apache.maven.project.MavenProject p = readProject(module); + MavenModel p = readProject(module); assertPathEquals(pathFromBasedir(module.getParent(), "custom"), p.getBuild().getDirectory()); } @@ -845,7 +822,7 @@ public class MavenProjectReaderTest extends MavenTestCase { " 1" + ""); - org.apache.maven.project.MavenProject p = readProject(module); + MavenModel p = readProject(module); assertPathEquals(pathFromBasedir(module.getParent(), "subDir/custom"), p.getBuild().getDirectory()); } @@ -873,7 +850,7 @@ public class MavenProjectReaderTest extends MavenTestCase { " 1" + ""); - org.apache.maven.project.MavenProject p = readProject(module, "one"); + MavenModel p = readProject(module, "one"); assertPathEquals(pathFromBasedir(module.getParent(), "subDir/custom"), p.getBuild().getDirectory()); } @@ -886,7 +863,7 @@ public class MavenProjectReaderTest extends MavenTestCase { " " + "
    "); - org.apache.maven.project.MavenProject mavenProject = readProject(myProjectPom); + MavenModel mavenProject = readProject(myProjectPom); assertEquals("${prop}", mavenProject.getName()); mavenProject = readProject(myProjectPom, "one"); @@ -902,7 +879,7 @@ public class MavenProjectReaderTest extends MavenTestCase { " " + "
    "); - org.apache.maven.project.MavenProject mavenProject = readProject(myProjectPom); + MavenModel mavenProject = readProject(myProjectPom); assertEquals("${prop}", mavenProject.getName()); mavenProject = readProject(myProjectPom, "one"); @@ -920,7 +897,7 @@ public class MavenProjectReaderTest extends MavenTestCase { "
    " + ""); - org.apache.maven.project.MavenProject mavenProject = readProject(myProjectPom); + MavenModel mavenProject = readProject(myProjectPom); assertEquals("${prop}", mavenProject.getName()); mavenProject = readProject(myProjectPom, "one"); @@ -943,7 +920,7 @@ public class MavenProjectReaderTest extends MavenTestCase { " 1" + ""); - org.apache.maven.project.MavenProject p = readProject(module, "one"); + MavenModel p = readProject(module, "one"); assertEquals("module-2", p.getBuild().getFinalName()); } @@ -967,7 +944,7 @@ public class MavenProjectReaderTest extends MavenTestCase { " 1" + ""); - org.apache.maven.project.MavenProject p = readProject(module, "one"); + MavenModel p = readProject(module, "one"); assertEquals("xxx", p.getBuild().getFinalName()); } @@ -1000,9 +977,9 @@ public class MavenProjectReaderTest extends MavenTestCase { "
    " + ""); - org.apache.maven.project.MavenProject p = readProject(module); - assertOrderedElementsAreEqual(ContainerUtil.map(p.getModel().getProfiles(), new Function() { - public Object fun(Profile profile) { + MavenModel p = readProject(module); + assertOrderedElementsAreEqual(ContainerUtil.map(p.getProfiles(), new Function() { + public Object fun(MavenProfile profile) { return profile.getId(); } }), "profileFromChild", "profileFromParent"); @@ -1016,13 +993,13 @@ public class MavenProjectReaderTest extends MavenTestCase { "" + " " + " profile" + - " parent" + + " parent" + " " + ""); VirtualFile parentProfiles = createProfilesXml("" + " profile" + - " parentProfiles" + + " parentProfiles" + ""); VirtualFile module = createModulePom("module", @@ -1039,27 +1016,27 @@ public class MavenProjectReaderTest extends MavenTestCase { "" + " " + " profile" + - " pom" + + " pom" + " " + ""); updateSettingsXml("" + " " + " profile" + - " settings" + + " settings" + " " + ""); VirtualFile profiles = createProfilesXml("module", "" + " profile" + - " profiles" + + " profiles" + ""); - org.apache.maven.project.MavenProject p = readProject(module); - assertEquals(1, p.getModel().getProfiles().size()); - assertEquals("pom", p.getModel().getProfiles().get(0).getProperties().getProperty("prop")); - assertEquals("pom", p.getModel().getProfiles().get(0).getSource()); + MavenModel p = readProject(module); + assertEquals(1, p.getProfiles().size()); + assertEquals("pom", p.getProfiles().get(0).getModules().get(0)); + assertEquals("pom", p.getProfiles().get(0).getSource()); createModulePom("module", "test" + @@ -1073,32 +1050,32 @@ public class MavenProjectReaderTest extends MavenTestCase { ""); p = readProject(module); - assertEquals(1, p.getModel().getProfiles().size()); - assertEquals("profiles", p.getModel().getProfiles().get(0).getProperties().getProperty("prop")); - assertEquals("profiles.xml", p.getModel().getProfiles().get(0).getSource()); + assertEquals(1, p.getProfiles().size()); + assertEquals("profiles", p.getProfiles().get(0).getModules().get(0)); + assertEquals("profiles.xml", p.getProfiles().get(0).getSource()); profiles.delete(this); p = readProject(module); - assertEquals(1, p.getModel().getProfiles().size()); - assertEquals("parent", p.getModel().getProfiles().get(0).getProperties().getProperty("prop")); - assertEquals("pom", p.getModel().getProfiles().get(0).getSource()); + assertEquals(1, p.getProfiles().size()); + assertEquals("parent", p.getProfiles().get(0).getModules().get(0)); + assertEquals("pom", p.getProfiles().get(0).getSource()); createProjectPom("test" + "parent" + "1"); p = readProject(module); - assertEquals(1, p.getModel().getProfiles().size()); - assertEquals("parentProfiles", p.getModel().getProfiles().get(0).getProperties().getProperty("prop")); - assertEquals("profiles.xml", p.getModel().getProfiles().get(0).getSource()); + assertEquals(1, p.getProfiles().size()); + assertEquals("parentProfiles", p.getProfiles().get(0).getModules().get(0)); + assertEquals("profiles.xml", p.getProfiles().get(0).getSource()); parentProfiles.delete(null); p = readProject(module); - assertEquals(1, p.getModel().getProfiles().size()); - assertEquals("settings", p.getModel().getProfiles().get(0).getProperties().getProperty("prop")); - assertEquals("settings.xml", p.getModel().getProfiles().get(0).getSource()); + assertEquals(1, p.getProfiles().size()); + assertEquals("settings", p.getProfiles().get(0).getModules().get(0)); + assertEquals("settings.xml", p.getProfiles().get(0).getSource()); } public void testActivatingProfilesByOS() throws Exception { @@ -1156,7 +1133,7 @@ public class MavenProjectReaderTest extends MavenTestCase { public void testActivatingProfilesByProperty() throws Exception { System.setProperty("maven.test.property", "foo"); - MavenEmbedderWrapper.resetSystemPropertiesCacheInTests(); + MavenFacadeUtil.resetSystemPropertiesCache(); createProjectPom("" + " " + @@ -1411,10 +1388,10 @@ public class MavenProjectReaderTest extends MavenTestCase { assertActiveProfiles("default", "profiles"); } - private org.apache.maven.project.MavenProject readProject(VirtualFile file, String... profiles) { + private MavenModel readProject(VirtualFile file, String... profiles) { MavenProjectReaderResult readResult = readProject(file, new NullProjectLocator(), profiles); assertProblems(readResult); - return readResult.nativeMavenProject; + return readResult.mavenModel; } private MavenProjectReaderResult readProject(VirtualFile file, @@ -1427,27 +1404,24 @@ public class MavenProjectReaderTest extends MavenTestCase { return result; } - private void assertParent(org.apache.maven.project.MavenProject p, + private void assertParent(MavenModel p, String groupId, String artifactId, - String version, - String relativePath) { - Parent parent = p.getModel().getParent(); - assertNotNull(parent); + String version) { + MavenId parent = p.getParent().getMavenId(); assertEquals(groupId, parent.getGroupId()); assertEquals(artifactId, parent.getArtifactId()); assertEquals(version, parent.getVersion()); - assertEquals(relativePath, parent.getRelativePath()); } - private void assertResource(Resource resource, + private void assertResource(MavenResource resource, String dir, boolean filtered, String targetPath, List includes, List excludes) { assertPathEquals(dir, resource.getDirectory()); - assertEquals(filtered, resource.isFiltering()); + assertEquals(filtered, resource.isFiltered()); assertPathEquals(targetPath, resource.getTargetPath()); assertOrderedElementsAreEqual(resource.getIncludes(), includes); assertOrderedElementsAreEqual(resource.getExcludes(), excludes); @@ -1466,9 +1440,10 @@ public class MavenProjectReaderTest extends MavenTestCase { } private void assertActiveProfiles(List explicitProfiles, String... expected) { - org.apache.maven.project.MavenProject p = readProject(myProjectPom, explicitProfiles.toArray(new String[explicitProfiles.size()])); - assertUnorderedElementsAreEqual(ContainerUtil.map((List)p.getActiveProfiles(), new Function() { - public String fun(Profile profile) { + MavenProjectReaderResult result = + readProject(myProjectPom, new NullProjectLocator(), explicitProfiles.toArray(new String[explicitProfiles.size()])); + assertUnorderedElementsAreEqual(ContainerUtil.map(result.activatedProfiles, new Function() { + public String fun(MavenProfile profile) { return profile.getId(); } }), expected); diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectTest.java index 700ee3a1a070..a393b9b226df 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectTest.java @@ -18,11 +18,15 @@ package org.jetbrains.idea.maven.project; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; -import org.jdom.Element; import org.jetbrains.idea.maven.MavenImportingTestCase; +import org.jetbrains.idea.maven.model.MavenArtifactNode; +import org.jetbrains.idea.maven.model.MavenPlugin; +import org.jetbrains.idea.maven.model.MavenRemoteRepository; import org.jetbrains.idea.maven.utils.MavenJDOMUtil; +import java.io.File; import java.util.List; +import java.util.Map; public class MavenProjectTest extends MavenImportingTestCase { public void testCollectingPlugins() throws Exception { @@ -51,7 +55,7 @@ public class MavenProjectTest extends MavenImportingTestCase { assertDeclaredPlugins(p("group1", "id1"), p("group1", "id2"), p("group2", "id1")); } - + public void testPluginsContainDefaultPlugins() throws Exception { importProject("test" + "project" + @@ -616,11 +620,12 @@ public class MavenProjectTest extends MavenImportingTestCase { assertEquals("central", result.get(2).getId()); } - public void testStrippingDownMavenModel() throws Exception { + public void testMavenModelMap() throws Exception { importProject("test" + "project" + "1" + "" + + " foo" + " " + " " + " group1" + @@ -630,8 +635,15 @@ public class MavenProjectTest extends MavenImportingTestCase { " " + ""); - assertTrue(getMavenProject().getMavenModel().getBuild().getPlugins().isEmpty()); - assertTrue(getMavenProject().getMavenModel().getBuild().getPluginsAsMap().isEmpty()); + MavenProject p = getMavenProject(); + Map map = p.getModelMap(); + + assertEquals("test", map.get("groupId")); + assertTrue(map.get("build"), map.get("build").startsWith("org.apache.maven.model.Build@")); + assertEquals("foo", map.get("build.finalName")); + assertEquals(new File(p.getDirectory(), "target").toString(), map.get("build.directory")); + assertEquals(null, map.get("build.plugins")); + assertEquals(null, map.get("build.pluginMap")); } public void testDependenciesTree() throws Exception { diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectsManagerTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectsManagerTest.java index 4d759370bde5..2e7b7544fc6d 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectsManagerTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectsManagerTest.java @@ -23,6 +23,7 @@ import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.idea.maven.MavenImportingTestCase; +import org.jetbrains.idea.maven.facade.NativeMavenProjectHolder; import org.jetbrains.idea.maven.importing.MavenRootModelAdapter; import java.io.File; @@ -816,7 +817,7 @@ public class MavenProjectsManagerTest extends MavenImportingTestCase { myProjectsManager.addProjectsTreeListener(new MavenProjectsTree.ListenerAdapter() { @Override public void projectResolved(Pair projectWithChanges, - org.apache.maven.project.MavenProject nativeMavenProject, Object message) { + NativeMavenProjectHolder nativeMavenProject, Object message) { called[0] = true; } }); diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectsTreeReadingTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectsTreeReadingTest.java index 48f9ae4e156a..2f06395edd15 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectsTreeReadingTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectsTreeReadingTest.java @@ -20,9 +20,11 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Function; +import org.jetbrains.idea.maven.facade.NativeMavenProjectHolder; import org.jetbrains.idea.maven.utils.MavenUtil; import java.io.File; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -582,14 +584,14 @@ public class MavenProjectsTreeReadingTest extends MavenProjectsTreeTestCase { myTree.addListener(listener); MavenProject project = myTree.findProject(myProjectPom); - MavenEmbeddersManager embeddersManager = new MavenEmbeddersManager(getMavenGeneralSettings()); - final org.apache.maven.project.MavenProject[] nativeProject = new org.apache.maven.project.MavenProject[1]; + MavenEmbeddersManager embeddersManager = new MavenEmbeddersManager(myProject); + final List nativeProject = new ArrayList(); try { myTree.addListener(new MavenProjectsTree.ListenerAdapter() { @Override public void projectResolved(Pair projectWithChanges, - org.apache.maven.project.MavenProject nativeMavenProject, Object message) { - nativeProject[0] = nativeMavenProject; + NativeMavenProjectHolder nativeMavenProject, Object message) { + nativeProject.add(nativeMavenProject); } }); myTree.resolve(project, @@ -604,8 +606,9 @@ public class MavenProjectsTreeReadingTest extends MavenProjectsTreeTestCase { } assertEquals("resolved: project ", listener.log); - assertNotNull(nativeProject[0]); assertTrue(project.hasReadingProblems()); + assertSize(1, nativeProject); + assertNull(nativeProject.get(0)); } public void testDoNotUpdateChildAfterParentWasResolved() throws Exception { @@ -631,13 +634,13 @@ public class MavenProjectsTreeReadingTest extends MavenProjectsTreeTestCase { MavenProject parentProject = myTree.findProject(myProjectPom); - MavenEmbeddersManager embeddersManager = new MavenEmbeddersManager(getMavenGeneralSettings()); + MavenEmbeddersManager embeddersManager = new MavenEmbeddersManager(myProject); try { - final org.apache.maven.project.MavenProject[] nativeProject = new org.apache.maven.project.MavenProject[1]; + final NativeMavenProjectHolder[] nativeProject = new NativeMavenProjectHolder[1]; myTree.addListener(new MavenProjectsTree.ListenerAdapter() { @Override public void projectResolved(Pair projectWithChanges, - org.apache.maven.project.MavenProject nativeMavenProject, + NativeMavenProjectHolder nativeMavenProject, Object message) { nativeProject[0] = nativeMavenProject; } @@ -649,8 +652,7 @@ public class MavenProjectsTreeReadingTest extends MavenProjectsTreeTestCase { EMPTY_MAVEN_PROCESS, null); myTree.resolvePlugins(parentProject, nativeProject[0], embeddersManager, NULL_MAVEN_CONSOLE, EMPTY_MAVEN_PROCESS); - myTree.resolveFolders(parentProject, getMavenGeneralSettings(), getMavenImporterSettings(), embeddersManager, NULL_MAVEN_CONSOLE, - EMPTY_MAVEN_PROCESS, null); + myTree.resolveFolders(parentProject, getMavenImporterSettings(), embeddersManager, NULL_MAVEN_CONSOLE, EMPTY_MAVEN_PROCESS, null); } finally { embeddersManager.release(); @@ -1821,7 +1823,7 @@ public class MavenProjectsTreeReadingTest extends MavenProjectsTreeTestCase { MavenProject parentProject = myTree.findProject(myProjectPom); - MavenEmbeddersManager embeddersManager = new MavenEmbeddersManager(getMavenGeneralSettings()); + MavenEmbeddersManager embeddersManager = new MavenEmbeddersManager(myProject); try { myTree.resolve(parentProject, getMavenGeneralSettings(), embeddersManager, NULL_MAVEN_CONSOLE, EMPTY_MAVEN_PROCESS, null); } @@ -1894,7 +1896,7 @@ public class MavenProjectsTreeReadingTest extends MavenProjectsTreeTestCase { updateAll(myProjectPom); - MavenEmbeddersManager embeddersManager = new MavenEmbeddersManager(getMavenGeneralSettings()); + MavenEmbeddersManager embeddersManager = new MavenEmbeddersManager(myProject); try { myTree.resolve(myTree.getRootProjects().get(0), getMavenGeneralSettings(), @@ -2019,7 +2021,7 @@ public class MavenProjectsTreeReadingTest extends MavenProjectsTreeTestCase { assertPathEquals(pathFromBasedir("my-target/classes"), project.getOutputDirectory()); assertPathEquals(pathFromBasedir("my-target/test-classes"), project.getTestOutputDirectory()); - MavenEmbeddersManager embeddersManager = new MavenEmbeddersManager(getMavenGeneralSettings()); + MavenEmbeddersManager embeddersManager = new MavenEmbeddersManager(myProject); try { myTree.resolve(project, getMavenGeneralSettings(), embeddersManager, NULL_MAVEN_CONSOLE, EMPTY_MAVEN_PROCESS, null); } @@ -2056,7 +2058,7 @@ public class MavenProjectsTreeReadingTest extends MavenProjectsTreeTestCase { @Override public void projectResolved(Pair projectWithChanges, - org.apache.maven.project.MavenProject nativeMavenProject, + NativeMavenProjectHolder nativeMavenProject, Object message) { log += "resolved: " + projectWithChanges.first.getMavenId().getArtifactId() + " "; } diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/wizards/MavenModuleBuilderTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/wizards/MavenModuleBuilderTest.java index 0bc3bf083d10..f2cde0eb915d 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/wizards/MavenModuleBuilderTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/wizards/MavenModuleBuilderTest.java @@ -23,12 +23,11 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.idea.maven.MavenImportingTestCase; +import org.jetbrains.idea.maven.model.MavenArchetype; +import org.jetbrains.idea.maven.model.MavenId; import org.jetbrains.idea.maven.project.MavenProjectsManager; -import org.jetbrains.idea.maven.indices.ArchetypeInfo; import org.jetbrains.idea.maven.project.MavenProject; -import org.jetbrains.idea.maven.project.MavenId; -import java.io.File; import java.util.List; public class MavenModuleBuilderTest extends MavenImportingTestCase { @@ -77,7 +76,7 @@ public class MavenModuleBuilderTest extends MavenImportingTestCase { public void testCreatingFromArchetype() throws Exception { if (!hasMavenInstallation()) return; - setArchetype(new ArchetypeInfo("org.apache.maven.archetypes", "maven-archetype-quickstart", "1.0", null, null)); + setArchetype(new MavenArchetype("org.apache.maven.archetypes", "maven-archetype-quickstart", "1.0", null, null)); MavenId id = new MavenId("org.foo", "module", "1.0"); createNewModule(id); @@ -220,7 +219,7 @@ public class MavenModuleBuilderTest extends MavenImportingTestCase { setModuleNameAndRoot("module", getProjectPath() + "/module"); setParentProject(myProjectPom); setInheritedOptions(true, true); - setArchetype(new ArchetypeInfo("org.apache.maven.archetypes", "maven-archetype-quickstart", "1.0", null, null)); + setArchetype(new MavenArchetype("org.apache.maven.archetypes", "maven-archetype-quickstart", "1.0", null, null)); createNewModule(new MavenId("org.foo", "module", "1.0")); assertEquals(" Date: Tue, 1 Jun 2010 11:10:50 +0400 Subject: [PATCH 061/212] Maven: Add Library from Repository fixes --- build/scripts/layouts.gant | 10 ++- .../facade/MavenFacadeIndexerException.java | 2 +- .../idea/maven/facade/MavenFacadeUtil.java | 5 -- .../idea/maven/facade/RemoteObject.java | 35 ++++---- .../idea/maven/facade/MavenFacadeImpl.java | 58 +++++++++---- .../embedder/MavenFacadeEmbedderImpl.java | 84 +++++++++++-------- .../embedder/MavenFacadeIndexerImpl.java | 35 ++++---- .../facade/embedder/MavenModelConverter.java | 4 +- .../idea/maven/facade/nexus/ArtifactType.java | 11 --- .../idea/maven/facade/MavenFacadeManager.java | 19 ++--- .../maven/indices/MavenIndicesManager.java | 14 +--- .../maven/utils/RepositoryAttachDialog.java | 27 ++---- .../maven/utils/RepositoryAttachHandler.java | 45 ++++++---- .../src/main/resources/META-INF/plugin.xml | 18 ++-- .../maven/project/MavenProjectReaderTest.java | 11 +-- 15 files changed, 191 insertions(+), 187 deletions(-) diff --git a/build/scripts/layouts.gant b/build/scripts/layouts.gant index 0ef5893a72fc..cd56346c2752 100644 --- a/build/scripts/layouts.gant +++ b/build/scripts/layouts.gant @@ -174,10 +174,14 @@ def layoutFull(String home, String targetDirectory) { layoutPlugin("maven") { - jar("maven-facade.jar") { - module("maven-facade") + jar("maven-facade-api.jar") { + module("maven-facade-api") } - fileset(dir: "$home/plugins/maven/lib") + jar("maven-facade-impl.jar") { + module("maven-facade-impl") + } + fileset(dir: "$home/plugins/maven/facade-impl/lib") + fileset(dir: "$home/plugins/maven/facade-api/lib") } diff --git a/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeIndexerException.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeIndexerException.java index 92ed5ad26499..a0cd581f5cee 100644 --- a/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeIndexerException.java +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeIndexerException.java @@ -20,7 +20,7 @@ public class MavenFacadeIndexerException extends Exception { super(message); } - public MavenFacadeIndexerException(Exception cause) { + public MavenFacadeIndexerException(Throwable cause) { super(null, cause); } } diff --git a/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeUtil.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeUtil.java index 164bbe44aaa3..77964fbfb34d 100644 --- a/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeUtil.java +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenFacadeUtil.java @@ -24,7 +24,6 @@ public class MavenFacadeUtil { private static volatile Properties mySystemPropertiesCache; public static Properties collectSystemProperties() { - if (mySystemPropertiesCache == null) { Properties result = new Properties(); result.putAll(getSystemProperties()); @@ -39,10 +38,6 @@ public class MavenFacadeUtil { return mySystemPropertiesCache; } - public static void resetSystemPropertiesCache() { - mySystemPropertiesCache = null; - } - @SuppressWarnings({"unchecked"}) private static Properties getSystemProperties() { Properties result = (Properties)System.getProperties().clone(); diff --git a/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/RemoteObject.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/RemoteObject.java index 9b9531ea6c72..753532d18cfa 100644 --- a/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/RemoteObject.java +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/RemoteObject.java @@ -53,31 +53,26 @@ public abstract class RemoteObject implements Remote, Unreferenced { } } - protected static void handleException(Exception e) { - Throwable cause = e; - while (cause.getCause() != null) { - cause = cause.getCause(); - } - cause = wrapException(cause); - throw cause instanceof RuntimeException ? (RuntimeException)cause : new RuntimeException(cause); - } - public static Throwable wrapException(Throwable ex) { - if (!ex.getClass().getName().startsWith("java")) { - final Throwable replaceWith = new RuntimeException(ex.toString()); - replaceWith.setStackTrace(ex.getStackTrace()); - ex = replaceWith; + boolean foreignException = false; + Throwable each = ex; + while(each != null) { + String name = each.getClass().getName(); + if (!name.startsWith("java") && !name.startsWith(RemoteObject.class.getPackage().getName())) { + foreignException = true; + break; + } + each = each.getCause(); + } + + if (foreignException) { + Throwable wrapper = new Throwable(ex.toString()); + wrapper.setStackTrace(ex.getStackTrace()); + ex = wrapper; } return ex; } - public Object wrapIfNeeded(Object o) throws RemoteException { - if (o == null) return o; - if (o.getClass().getClassLoader() == null || - o.getClass().getName().startsWith("com.intellij")) return o; - return o.toString(); - } - public void unreferenced() { if (myParent != null) { myParent.myChildren.remove(this); diff --git a/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/MavenFacadeImpl.java b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/MavenFacadeImpl.java index 457628449ae7..a490b3cafbf2 100644 --- a/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/MavenFacadeImpl.java +++ b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/MavenFacadeImpl.java @@ -38,34 +38,64 @@ import java.util.List; public class MavenFacadeImpl extends RemoteObject implements MavenFacade { public void setLogger(MavenFacadeLogger logger) throws RemoteException { - MavenFacadeLoggerManager.setLogger(logger); + try { + MavenFacadeLoggerManager.setLogger(logger); + } + catch (Exception e) { + throw new RuntimeException(wrapException(e)); + } } public MavenFacadeEmbedder createEmbedder(MavenFacadeSettings settings) throws RemoteException { - MavenFacadeEmbedderImpl result = MavenFacadeEmbedderImpl.create(settings); - UnicastRemoteObject.exportObject(result, 0); - return result; + try { + MavenFacadeEmbedderImpl result = MavenFacadeEmbedderImpl.create(settings); + UnicastRemoteObject.exportObject(result, 0); + return result; + } + catch (RemoteException e) { + throw new RuntimeException(wrapException(e)); + } } public MavenFacadeIndexer createIndexer() throws RemoteException { - MavenFacadeIndexerImpl result = new MavenFacadeIndexerImpl(); - UnicastRemoteObject.exportObject(result, 0); - return result; + try { + MavenFacadeIndexerImpl result = new MavenFacadeIndexerImpl(); + UnicastRemoteObject.exportObject(result, 0); + return result; + } + catch (RemoteException e) { + throw new RuntimeException(wrapException(e)); + } } public MavenModel interpolateAndAlignModel(MavenModel model, File basedir) { - return MavenFacadeEmbedderImpl.interpolateAndAlignModel(model, basedir); + try { + return MavenFacadeEmbedderImpl.interpolateAndAlignModel(model, basedir); + } + catch (Exception e) { + throw new RuntimeException(wrapException(e)); + } } public MavenModel assembleInheritance(MavenModel model, MavenModel parentModel) { - return MavenFacadeEmbedderImpl.assembleInheritance(model, parentModel); + try { + return MavenFacadeEmbedderImpl.assembleInheritance(model, parentModel); + } + catch (Exception e) { + throw new RuntimeException(wrapException(e)); + } } public ProfileApplicationResult applyProfiles(MavenModel model, File basedir, Collection explicitProfiles, Collection alwaysOnProfiles) { - return MavenFacadeEmbedderImpl.applyProfiles(model, basedir, explicitProfiles, alwaysOnProfiles); + try { + return MavenFacadeEmbedderImpl.applyProfiles(model, basedir, explicitProfiles, alwaysOnProfiles); + } + catch (Exception e) { + throw new RuntimeException(wrapException(e)); + } } public List getRepositories(String nexusUrl) throws RemoteException { @@ -79,8 +109,7 @@ public class MavenFacadeImpl extends RemoteObject implements MavenFacade { return result; } catch (Exception e) { - handleException(e); - throw new AssertionError(); + throw new RuntimeException(wrapException(e)); } } @@ -105,9 +134,8 @@ public class MavenFacadeImpl extends RemoteObject implements MavenFacade { } return result; } - catch (Exception ex) { - handleException(ex); - throw new AssertionError(); + catch (Exception e) { + throw new RuntimeException(wrapException(e)); } } } diff --git a/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenFacadeEmbedderImpl.java b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenFacadeEmbedderImpl.java index c900a0a13d12..c4de158707c5 100644 --- a/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenFacadeEmbedderImpl.java +++ b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenFacadeEmbedderImpl.java @@ -16,7 +16,6 @@ package org.jetbrains.idea.maven.facade.embedder; import com.intellij.openapi.progress.ProcessCanceledException; -import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; import com.intellij.util.Function; import gnu.trove.THashMap; @@ -75,10 +74,12 @@ import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import static org.jetbrains.idea.maven.facade.RemoteObject.wrapException; + public class MavenFacadeEmbedderImpl extends RemoteObject implements MavenFacadeEmbedder { private final MavenEmbedder myImpl; private final MavenFacadeConsoleWrapper myConsoleWrapper; - private volatile MavenFacadeProgressIndicator myCurrentIndicator; + private volatile MavenFacadeProgressIndicatorWrapper myCurrentIndicatorWrapper; public static MavenFacadeEmbedderImpl create(MavenFacadeSettings facadeSettings) { MavenEmbedderSettings settings = new MavenEmbedderSettings(); @@ -184,15 +185,14 @@ public class MavenFacadeEmbedderImpl extends RemoteObject implements MavenFacade } @NotNull - public List resolveTransitively( - @NotNull final List artifacts, - @NotNull final List remoteRepositories) { - - Set toResolve = new LinkedHashSet(); - for (MavenArtifactInfo each : artifacts) { - toResolve.add(createArtifact(each)); - } + public List resolveTransitively(@NotNull final List artifacts, + @NotNull final List remoteRepositories) { try { + Set toResolve = new LinkedHashSet(); + for (MavenArtifactInfo each : artifacts) { + toResolve.add(createArtifact(each)); + } + return MavenModelConverter.convertArtifacts(myImpl.resolveTransitively(toResolve, convertRepositories(remoteRepositories)), new THashMap(), getLocalRepositoryFile()); } @@ -202,6 +202,10 @@ public class MavenFacadeEmbedderImpl extends RemoteObject implements MavenFacade catch (ArtifactNotFoundException e) { MavenFacadeLoggerManager.getLogger().info(e); } + catch (Exception e) { + throw new RuntimeException(wrapException(e)); + + } return Collections.emptyList(); } @@ -469,7 +473,6 @@ public class MavenFacadeEmbedderImpl extends RemoteObject implements MavenFacade private interface Executor { T execute() throws Exception; - } private T doExecute(final Executor executor) throws MavenFacadeProcessCanceledException { @@ -491,23 +494,17 @@ public class MavenFacadeEmbedderImpl extends RemoteObject implements MavenFacade } }); - MavenFacadeProgressIndicator indicator = myCurrentIndicator; + MavenFacadeProgressIndicatorWrapper indicator = myCurrentIndicatorWrapper; while (true) { - boolean canceled = false; - try { - canceled = indicator.isCanceled(); - } - catch (RemoteException e) { - throw new RuntimeException(e); - } - if (canceled) throw new MavenFacadeProcessCanceledException(); + if (indicator.isCanceled()) throw new MavenFacadeProcessCanceledException(); + try { future.get(50, TimeUnit.MILLISECONDS); } catch (TimeoutException ignore) { } catch (ExecutionException e) { - throw new RuntimeException(e.getCause()); + throw new RuntimeException(wrapException(e.getCause())); } catch (InterruptedException e) { throw new MavenFacadeProcessCanceledException(); @@ -526,8 +523,7 @@ public class MavenFacadeEmbedderImpl extends RemoteObject implements MavenFacade private RuntimeException getRethrowable(Throwable throwable) { if (throwable instanceof InvocationTargetException) throwable = throwable.getCause(); - if (throwable instanceof RuntimeException) return (RuntimeException)throwable; - return new RuntimeException(throwable); + return new RuntimeException(wrapException(throwable)); } private static void setupContainer(PlexusContainer c) { @@ -556,16 +552,21 @@ public class MavenFacadeEmbedderImpl extends RemoteObject implements MavenFacade boolean strict, MavenFacadeConsole logger, MavenFacadeProgressIndicator process) { - ((CustomArtifactFactory)getComponent(ArtifactFactory.class)).customize(); - ((CustomArtifactFactory)getComponent(ProjectArtifactFactory.class)).customize(); - ((CustomArtifactResolver)getComponent(ArtifactResolver.class)).customize(projectIdToFileMap, strict); - ((CustomWagonManager)getComponent(WagonManager.class)).customize(strict); + try { + ((CustomArtifactFactory)getComponent(ArtifactFactory.class)).customize(); + ((CustomArtifactFactory)getComponent(ProjectArtifactFactory.class)).customize(); + ((CustomArtifactResolver)getComponent(ArtifactResolver.class)).customize(projectIdToFileMap, strict); + ((CustomWagonManager)getComponent(WagonManager.class)).customize(strict); - setConsoleAndLogger(logger, process); + setConsoleAndLogger(logger, process); + } + catch (Exception e) { + throw new RuntimeException(wrapException(e)); + } } private void setConsoleAndLogger(MavenFacadeConsole logger, MavenFacadeProgressIndicator process) { - myCurrentIndicator = process; + myCurrentIndicatorWrapper = new MavenFacadeProgressIndicatorWrapper(process); myConsoleWrapper.setWrappee(logger); WagonManager wagon = getComponent(WagonManager.class); @@ -573,16 +574,26 @@ public class MavenFacadeEmbedderImpl extends RemoteObject implements MavenFacade } public void reset() { - setConsoleAndLogger(null, null); + try { + setConsoleAndLogger(null, null); - ((CustomArtifactFactory)getComponent(ProjectArtifactFactory.class)).reset(); - ((CustomArtifactFactory)getComponent(ArtifactFactory.class)).reset(); - ((CustomArtifactResolver)getComponent(ArtifactResolver.class)).reset(); - ((CustomWagonManager)getComponent(WagonManager.class)).reset(); + ((CustomArtifactFactory)getComponent(ProjectArtifactFactory.class)).reset(); + ((CustomArtifactFactory)getComponent(ArtifactFactory.class)).reset(); + ((CustomArtifactResolver)getComponent(ArtifactResolver.class)).reset(); + ((CustomWagonManager)getComponent(WagonManager.class)).reset(); + } + catch (Exception e) { + throw new RuntimeException(wrapException(e)); + } } public void release() { - myImpl.release(); + try { + myImpl.release(); + } + catch (Exception e) { + throw new RuntimeException(wrapException(e)); + } } public void clearCaches() { @@ -621,6 +632,9 @@ public class MavenFacadeEmbedderImpl extends RemoteObject implements MavenFacade catch (IllegalAccessException e) { MavenFacadeLoggerManager.getLogger().info(e); } + catch(Exception e) { + throw new RuntimeException(wrapException(e)); + } } } diff --git a/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenFacadeIndexerImpl.java b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenFacadeIndexerImpl.java index a67c97653f1a..4fb55e106bf8 100644 --- a/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenFacadeIndexerImpl.java +++ b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenFacadeIndexerImpl.java @@ -80,11 +80,8 @@ public class MavenFacadeIndexerImpl extends RemoteObject implements MavenFacadeI myIndices.put(id, context); return id; } - catch (IOException e) { - throw new MavenFacadeIndexerException(e); - } - catch (UnsupportedExistingLuceneIndexException e) { - throw new MavenFacadeIndexerException(e.getMessage()); + catch (Exception e) { + throw new MavenFacadeIndexerException(wrapException(e)); } } @@ -92,8 +89,8 @@ public class MavenFacadeIndexerImpl extends RemoteObject implements MavenFacadeI try { myIndexer.removeIndexingContext(getIndex(id), false); } - catch (IOException e) { - throw new MavenFacadeIndexerException(e); + catch (Exception e) { + throw new MavenFacadeIndexerException(wrapException(e)); } } @@ -163,8 +160,8 @@ public class MavenFacadeIndexerImpl extends RemoteObject implements MavenFacadeI catch (MavenFacadeProgressIndicatorWrapper.RuntimeCanceledException e) { throw new MavenFacadeProcessCanceledException(); } - catch (IOException e) { - throw new MavenFacadeIndexerException(e); + catch (Exception e) { + throw new MavenFacadeIndexerException(wrapException(e)); } } @@ -189,8 +186,8 @@ public class MavenFacadeIndexerImpl extends RemoteObject implements MavenFacadeI } return result; } - catch (IOException e) { - throw new MavenFacadeIndexerException(e); + catch (Exception e) { + throw new MavenFacadeIndexerException(wrapException(e)); } } @@ -205,8 +202,8 @@ public class MavenFacadeIndexerImpl extends RemoteObject implements MavenFacadeI org.sonatype.nexus.index.ArtifactInfo a = artifactContext.getArtifactInfo(); return new MavenId(a.groupId, a.artifactId, a.version); } - catch (IOException e) { - throw new MavenFacadeIndexerException(e); + catch (Exception e) { + throw new MavenFacadeIndexerException(wrapException(e)); } } @@ -238,8 +235,8 @@ public class MavenFacadeIndexerImpl extends RemoteObject implements MavenFacadeI } return result; } - catch (IOException e) { - throw new MavenFacadeIndexerException(e); + catch (Exception e) { + throw new MavenFacadeIndexerException(wrapException(e)); } } @@ -265,10 +262,14 @@ public class MavenFacadeIndexerImpl extends RemoteObject implements MavenFacadeI } public void release() { - myEmbedder.release(); + try { + myEmbedder.release(); + } + catch (Exception e) { + throw new RuntimeException(wrapException(e)); + } } - private static class MyScanningListener implements ArtifactScanningListener { private final MavenFacadeProgressIndicatorWrapper p; diff --git a/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenModelConverter.java b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenModelConverter.java index 65557c7a7101..709df7b09d10 100644 --- a/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenModelConverter.java +++ b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/embedder/MavenModelConverter.java @@ -488,7 +488,7 @@ public class MavenModelConverter { result.setId(r.getId()); result.setName(r.getName()); result.setUrl(r.getUrl()); - result.setLayout(r.getLayout()); + result.setLayout(r.getLayout() == null ? "default" : r.getLayout()); if (r.getReleasesPolicy() != null) result.setReleases(toNativePolicy(r.getReleasesPolicy())); if (r.getSnapshotsPolicy() != null) result.setSnapshots(toNativePolicy(r.getSnapshotsPolicy())); @@ -514,7 +514,7 @@ public class MavenModelConverter { t.getVersion(), t.getPackaging(), t.getClassifier(), - t.getClassNames(), + null, t.getRepoId()); } diff --git a/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/nexus/ArtifactType.java b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/nexus/ArtifactType.java index ca9fc8a040c7..545cc617fb2f 100644 --- a/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/nexus/ArtifactType.java +++ b/plugins/maven/facade-impl/src/org/jetbrains/idea/maven/facade/nexus/ArtifactType.java @@ -90,8 +90,6 @@ public class ArtifactType implements Serializable { @XmlElement(required = true) protected String artifactLink; - protected String classNames; - public ArtifactType() { } @@ -322,15 +320,6 @@ public class ArtifactType implements Serializable { this.artifactLink = value; } - @Nullable - public String getClassNames() { - return classNames; - } - - public void setClassNames(@Nullable String classNames) { - this.classNames = classNames; - } - @Override public String toString() { return groupId + ":" + artifactId + ":" + version; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/facade/MavenFacadeManager.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/facade/MavenFacadeManager.java index 9a7cab28c6d9..e16d96c71154 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/facade/MavenFacadeManager.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/facade/MavenFacadeManager.java @@ -29,10 +29,8 @@ import com.intellij.execution.process.ProcessTerminatedListener; import com.intellij.execution.rmi.RemoteProcessSupport; import com.intellij.execution.runners.ProgramRunner; import com.intellij.ide.DataManager; -import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.PlatformDataKeys; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.project.Project; @@ -40,9 +38,8 @@ import com.intellij.openapi.projectRoots.JavaSdkType; import com.intellij.openapi.projectRoots.JdkUtil; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.projectRoots.SimpleJavaSdkType; -import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.ShutDownTracker; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.psi.CommonClassNames; import com.intellij.util.PathUtil; import com.intellij.util.PathsList; import com.intellij.util.SystemProperties; @@ -96,8 +93,8 @@ public class MavenFacadeManager { } }; - Disposer.register(ApplicationManager.getApplication(), new Disposable() { - public void dispose() { + ShutDownTracker.getInstance().registerShutdownTask(new Runnable() { + public void run() { mySupport.stopAll(); if (myLogger != null) { @@ -149,7 +146,7 @@ public class MavenFacadeManager { addPluginLibraries(params.getClassPath()); params.setMainClass(MAIN_CLASS); - params.getVMParametersList().add("-Xmx512m -agentlib:yjpagent=disablej2ee"); + params.getVMParametersList().addParametersString("-d32 -Xmx512m"); return params; } @@ -176,7 +173,6 @@ public class MavenFacadeManager { ProcessTerminatedListener.attach(processHandler); return processHandler; } - }; } @@ -192,7 +188,7 @@ public class MavenFacadeManager { libDir = new File(luceneLib.getParentFile().getParentFile().getParentFile(), "facade-impl/lib"); } else { - libDir = pluginFileOrDir; + libDir = pluginFileOrDir.getParentFile(); } MavenLog.LOG.assertTrue(libDir.exists() && libDir.isDirectory(), "Maven Facade libraries dir not found: " + libDir); @@ -204,11 +200,6 @@ public class MavenFacadeManager { } } - public static String getJarPath(@NotNull final Class context, @NotNull final String mainClassName) { - final String s = PathManager.getResourceRoot(context, "/" + mainClassName.replace('.', '/') + CommonClassNames.CLASS_FILE_EXTENSION); - return new File(s).getAbsoluteFile().getAbsolutePath(); - } - public MavenEmbedderWrapper createEmbedder(Project project) { MavenFacade facade = getFacade(); MavenGeneralSettings settings = MavenProjectsManager.getInstance(project).getGeneralSettings(); diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndicesManager.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndicesManager.java index 272ae3852f30..df4ff90b3d8d 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndicesManager.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndicesManager.java @@ -17,6 +17,7 @@ package org.jetbrains.idea.maven.indices; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ApplicationComponent; +import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.progress.BackgroundTaskQueue; import com.intellij.openapi.progress.ProcessCanceledException; @@ -47,7 +48,7 @@ import java.io.File; import java.io.IOException; import java.util.*; -public class MavenIndicesManager implements ApplicationComponent { +public class MavenIndicesManager { private static final String ELEMENT_ARCHETYPES = "archetypes"; private static final String ELEMENT_ARCHETYPE = "archetype"; private static final String ELEMENT_GROUP_ID = "groupId"; @@ -75,15 +76,7 @@ public class MavenIndicesManager implements ApplicationComponent { private volatile List myUserArchetypes = new ArrayList(); public static MavenIndicesManager getInstance() { - return ApplicationManager.getApplication().getComponent(MavenIndicesManager.class); - } - - @NotNull - public String getComponentName() { - return getClass().getSimpleName(); - } - - public void initComponent() { + return ServiceManager.getService(MavenIndicesManager.class); } @TestOnly @@ -99,7 +92,6 @@ public class MavenIndicesManager implements ApplicationComponent { private synchronized void ensureInitialized() { if (myIndices != null) return; - // todo remove defaultProject myIndexer = MavenFacadeManager.getInstance().createIndexer(); myIndices = new MavenIndices(myIndexer, getIndicesDir(), new MavenIndex.IndexListener() { public void indexIsBroken(MavenIndex index) { diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/RepositoryAttachDialog.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/RepositoryAttachDialog.java index 5760713137b4..4362c507b2db 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/RepositoryAttachDialog.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/RepositoryAttachDialog.java @@ -25,6 +25,7 @@ import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; @@ -62,7 +63,8 @@ public class RepositoryAttachDialog extends DialogWrapper { private final Project myProject; private final boolean myManaged; private final AsyncProcessIcon myProgressIcon; - private final THashMap myCoordinates = new THashMap(); + private final THashMap> myCoordinates + = new THashMap>(); private final Map myRepositories = new TreeMap(); private final ArrayList myShownItems = new ArrayList(); private final JComboBox myCombobox = new JComboBox(new CollectionComboBoxModel(myShownItems, null)); @@ -170,14 +172,14 @@ public class RepositoryAttachDialog extends DialogWrapper { if (myProgressIcon.isVisible()) return false; myProgressIcon.setVisible(true); myProgressIcon.resume(); - RepositoryAttachHandler.searchArtifacts(myProject, text, new PairProcessor, Boolean>() { - public boolean process(Collection artifacts, Boolean tooMany) { + RepositoryAttachHandler.searchArtifacts(myProject, text, new PairProcessor>, Boolean>() { + public boolean process(Collection> artifacts, Boolean tooMany) { if (myProgressIcon.isDisposed()) return true; myProgressIcon.suspend(); myProgressIcon.setVisible(false); final int prevSize = myCoordinates.size(); - for (MavenArtifactInfo each : artifacts) { - myCoordinates.put(each.getGroupId() + ":" + each.getArtifactId() + ":" + each.getVersion(), each); + for (Pair each : artifacts) { + myCoordinates.put(each.first.getGroupId() + ":" + each.first.getArtifactId() + ":" + each.first.getVersion(), each); } myRepositoryUrl.setModel(new CollectionComboBoxModel(new ArrayList(myRepositories.keySet()), myRepositoryUrl.getEditor().getItem())); @@ -328,23 +330,12 @@ public class RepositoryAttachDialog extends DialogWrapper { return Collections.singletonList(new MavenRepositoryInfo("custom", null, selectedRepository)); } else { - final MavenArtifactInfo artifact = myCoordinates.get(getCoordinateText()); - final MavenRepositoryInfo repository = - artifact != null ? findRepositoryFor(artifact) : null; + final Pair artifactAndRepo = myCoordinates.get(getCoordinateText()); + final MavenRepositoryInfo repository = artifactAndRepo.second; return repository != null? Collections.singletonList(repository) : ContainerUtil.findAll(myRepositories.values(), Condition.NOT_NULL); } } - private MavenRepositoryInfo findRepositoryFor(MavenArtifactInfo artifact) { - String soughtFor = artifact.getRepositoryId(); - if (soughtFor == null) return null; - - for (MavenRepositoryInfo each : myRepositories.values()) { - if (each.getId().equals(soughtFor)) return each; - } - return null; - } - private boolean isValidCoordinateSelected() { final String text = getCoordinateText(); if (myCombobox.getModel().getSelectedItem() == null) return false; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/RepositoryAttachHandler.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/RepositoryAttachHandler.java index 4d4fd0a55239..20d95c1d4a0e 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/RepositoryAttachHandler.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/RepositoryAttachHandler.java @@ -32,14 +32,13 @@ import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.roots.ui.configuration.libraryEditor.LibraryTableAttachHandler; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.util.ActionCallback; -import com.intellij.openapi.util.NullableComputable; -import com.intellij.openapi.util.Ref; +import com.intellij.openapi.util.*; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.util.PairProcessor; import com.intellij.util.Processor; import com.intellij.util.SmartList; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.maven.dom.converters.repositories.MavenRepositoriesProvider; import org.jetbrains.idea.maven.execution.SoutMavenConsole; @@ -192,21 +191,23 @@ public class RepositoryAttachHandler implements LibraryTableAttachHandler { } public static void searchArtifacts(final Project project, String coord, - final PairProcessor, Boolean> resultProcessor, + final PairProcessor>, Boolean> resultProcessor, final Processor> repoProcessor) { if (coord == null) return; final MavenArtifactInfo template = createTemplate(coord, null); ProgressManager.getInstance().run(new Task.Backgroundable(project, "Maven", false) { public void run(@NotNull ProgressIndicator indicator) { - final Ref> result = Ref.create(Collections.emptyList()); + final Ref>> result + = Ref.create(Collections.>emptyList()); final Ref> result2 = Ref.create(Collections.emptyList()); final Ref tooManyRef = Ref.create(Boolean.FALSE); try { MavenFacadeManager facade = MavenFacadeManager.getInstance(); final String[] nexusUrls = getDefaultNexusUrls(); - final List resultList = new ArrayList(); + final List> resultList + = new ArrayList>(); final List result2List = new ArrayList(); for (String nexusUrl : nexusUrls) { final List artifacts; @@ -221,8 +222,15 @@ public class RepositoryAttachHandler implements LibraryTableAttachHandler { tooManyRef.set(Boolean.TRUE); } else if (!artifacts.isEmpty()) { - result2List.addAll(facade.getRepositories(nexusUrl)); - resultList.addAll(artifacts); + final List repositories = facade.getRepositories(nexusUrl); + final HashMap map = new HashMap(); + for (MavenRepositoryInfo repository : repositories) { + map.put(repository.getId(), repository); + } + result2List.addAll(repositories); + for (MavenArtifactInfo artifact : artifacts) { + resultList.add(Pair.create(artifact, map.get(artifact.getRepositoryId()))); + } } } result.set(resultList); @@ -288,7 +296,7 @@ public class RepositoryAttachHandler implements LibraryTableAttachHandler { return new MavenArtifactInfo(parts.length > 0 ? parts[0] : null, parts.length > 1 ? parts[1] : null, parts.length > 2 ? parts[2] : null, - null, + packaging, null); } } @@ -299,21 +307,21 @@ public class RepositoryAttachHandler implements LibraryTableAttachHandler { public static void resolveLibrary(final Project project, final String libName, - Collection repositories, + final Collection repositories, boolean modal, final Processor> resultProcessor) { Task task; if (modal) { task = new Task.Modal(project, "Maven", false) { public void run(@NotNull ProgressIndicator indicator) { - doResolveInner(project, Collections.singletonList(createTemplate(libName, "jar")), resultProcessor, indicator); + doResolveInner(project, createTemplate(libName, "jar"), repositories, resultProcessor, indicator); } }; } else { task = new Task.Backgroundable(project, "Maven", false, PerformInBackgroundOption.DEAF) { public void run(@NotNull ProgressIndicator indicator) { - doResolveInner(project, Collections.singletonList(createTemplate(libName, "jar")), resultProcessor, indicator); + doResolveInner(project, createTemplate(libName, "jar"), repositories, resultProcessor, indicator); } @Override @@ -327,7 +335,8 @@ public class RepositoryAttachHandler implements LibraryTableAttachHandler { } private static void doResolveInner(Project project, - List artifacts, + MavenArtifactInfo artifact, + Collection repositories, final Processor> resultProcessor, ProgressIndicator indicator) { final Ref> result = new Ref>(); @@ -336,7 +345,13 @@ public class RepositoryAttachHandler implements LibraryTableAttachHandler { MavenEmbedderWrapper embedder = manager.getEmbedder(MavenEmbeddersManager.FOR_DOWNLOAD); try { embedder.customizeForResolve(new SoutMavenConsole(), new MavenProgressIndicator(indicator)); - result.set(embedder.resolveTransitively(artifacts, convertRepositories(getDefaultRepositories()))); + List resolved = embedder.resolveTransitively(Collections.singletonList(artifact), + convertRepositories(repositories)); + result.set(ContainerUtil.findAll(resolved, new Condition() { + public boolean value(MavenArtifact mavenArtifact) { + return mavenArtifact.isResolved(); + } + })); } catch (MavenProcessCanceledException e) { return; @@ -351,7 +366,7 @@ public class RepositoryAttachHandler implements LibraryTableAttachHandler { } } - private static List convertRepositories(List infos) { + private static List convertRepositories(Collection infos) { List result = new ArrayList(infos.size()); for (MavenRepositoryInfo each : infos) { result.add(new MavenRemoteRepository(each.getId(), each.getName(), each.getUrl(), null, null, null)); diff --git a/plugins/maven/src/main/resources/META-INF/plugin.xml b/plugins/maven/src/main/resources/META-INF/plugin.xml index 13f14ad673c2..e5ee12fc523f 100644 --- a/plugins/maven/src/main/resources/META-INF/plugin.xml +++ b/plugins/maven/src/main/resources/META-INF/plugin.xml @@ -20,8 +20,8 @@ - + + @@ -73,14 +73,9 @@ - - - - - + + + @@ -103,9 +98,6 @@ - - org.jetbrains.idea.maven.indices.MavenIndicesManager - org.jetbrains.idea.maven.utils.MavenEnvironmentRegistrar diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectReaderTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectReaderTest.java index 1bb850520a86..639a61f6926e 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectReaderTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectReaderTest.java @@ -1132,16 +1132,13 @@ public class MavenProjectReaderTest extends MavenTestCase { } public void testActivatingProfilesByProperty() throws Exception { - System.setProperty("maven.test.property", "foo"); - MavenFacadeUtil.resetSystemPropertiesCache(); - createProjectPom("" + " " + " one" + " " + " " + - " maven.test.property" + - " foo" + + " os.name" + + " " + System.getProperty("os.name") + "" + " " + " " + " " + @@ -1149,8 +1146,8 @@ public class MavenProjectReaderTest extends MavenTestCase { " two" + " " + " " + - " maven.test.property" + - " bar" + + " os.name" + + " xxx" + " " + " " + " " + From be35b620f90d8e582828dce3c250e16caf59ceb6 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 1 Jun 2010 09:30:54 +0100 Subject: [PATCH 062/212] fix tests broken by package classes caching --- .../src/com/intellij/psi/impl/file/PsiPackageImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java b/java/java-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java index bd7885956600..94422d944b9c 100644 --- a/java/java-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java @@ -497,7 +497,8 @@ public class PsiPackageImpl extends PsiElementBase implements PsiPackage, Querya NameHint nameHint = processor.getHint(NameHint.KEY); if (nameHint != null) { final String shortName = nameHint.getName(state); - if (containsClassNamed(shortName) && processClassesByName(processor, state, place, scope, shortName)) return false; + if ((migration != null || containsClassNamed(shortName)) + && processClassesByName(processor, state, place, scope, shortName)) return false; } else if (prefixMatcher != null && migration == null) { for (String className : getClassNamesCache()) { From 768db6edeb53ac5940e1f5aaba76df575e546507 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Mon, 31 May 2010 18:22:16 +0400 Subject: [PATCH 063/212] running tests on module's classpath: SMTest --- .../testframework/sm/FileUrlProvider.java | 21 ++++++----- .../testframework/sm/FileUrlLocationTest.java | 37 ++++--------------- .../sm/SMLightFixtureTestCase.java | 6 +++ .../sm/runner/BaseSMTRunnerTestCase.java | 5 +++ 4 files changed, 29 insertions(+), 40 deletions(-) diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/FileUrlProvider.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/FileUrlProvider.java index f559ede447d5..33764f466176 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/FileUrlProvider.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/FileUrlProvider.java @@ -104,24 +104,25 @@ public class FileUrlProvider implements TestLocationProvider { final int lineCount = doc.getLineCount(); final int lineStartOffset; + final int endOffset; if (lineNum <= lineCount) { lineStartOffset = doc.getLineStartOffset(lineNum - 1); + endOffset = doc.getLineEndOffset(lineNum - 1); } else { // unknown line lineStartOffset = 0; + endOffset = doc.getTextLength(); } - PsiElement elementAtLine = psiFile.findElementAt(lineStartOffset); - if (elementAtLine != null) { - // skip whitespaces - while (elementAtLine instanceof PsiWhiteSpace) { - elementAtLine = elementAtLine.getNextSibling(); - } + int offset = lineStartOffset; + PsiElement elementAtLine = null; + while (offset <= endOffset) { + elementAtLine = psiFile.findElementAt(offset); + if (!(elementAtLine instanceof PsiWhiteSpace)) break; + int length = elementAtLine.getTextLength(); + offset += length > 1 ? length - 1 : 1; } - final PsiElement leafPsiElementAtLine = elementAtLine == null - ? null - : psiFile.findElementAt(elementAtLine.getTextOffset()); - return PsiLocation.fromPsiElement(project, leafPsiElementAtLine != null ? leafPsiElementAtLine : psiFile); + return PsiLocation.fromPsiElement(project, elementAtLine != null ? elementAtLine : psiFile); } } diff --git a/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/FileUrlLocationTest.java b/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/FileUrlLocationTest.java index 7a45329efef9..dc9b834fcea3 100644 --- a/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/FileUrlLocationTest.java +++ b/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/FileUrlLocationTest.java @@ -29,39 +29,16 @@ public class FileUrlLocationTest extends SMLightFixtureTestCase { } public void testSpecNavigation() throws Throwable { - createAndAddFile("my_example_spec.rb", + createAndAddFile("my_example_spec.xml", "\n" + - "require \"spec\"\n" + - "\n" + - "describe \"Blabla\" do\n" + - "\n" + - " # Called before each example.\n" + - " before(:each) do\n" + - " # Do nothing\n" + - " end\n" + - "\n" + - " # Called after each example.\n" + - " after(:each) do\n" + - " # Do nothing\n" + - " end\n" + - "\n" + - " it \"should fail\" do\n" + - "\n" + - " #should pass\n" + - " true.should == false\n" + - " end\n" + - "\n" + - " it \"should pass\" do\n" + - "\n" + - " #should pass\n" + - " true.should == true\n" + - " end\n" + - "end"); + "\n" + + " \n" + + "\n" + + "\n"); final String path = myFixture.getFile().getVirtualFile().getPath(); - doTest(17, "describe", path, 4); - doTest(189, "it", path, 16); - doTest(261, "it", path, 22); + doTest(1, "<", path, 2); + doTest(16, "<", path, 3); } private void doTest(final int expectedOffset, final String expectedStartsWith, diff --git a/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/SMLightFixtureTestCase.java b/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/SMLightFixtureTestCase.java index 2cda3fa48c0f..660550647287 100644 --- a/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/SMLightFixtureTestCase.java +++ b/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/SMLightFixtureTestCase.java @@ -23,6 +23,7 @@ import com.intellij.openapi.roots.ContentEntry; import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.psi.PsiFile; import com.intellij.testFramework.LightProjectDescriptor; +import com.intellij.testFramework.PlatformTestCase; import com.intellij.testFramework.UsefulTestCase; import com.intellij.testFramework.fixtures.CodeInsightTestFixture; import com.intellij.testFramework.fixtures.IdeaProjectTestFixture; @@ -37,6 +38,11 @@ import java.io.IOException; * @author Roman.Chernyatchik */ public abstract class SMLightFixtureTestCase extends UsefulTestCase { + + protected SMLightFixtureTestCase() { + PlatformTestCase.initPlatformLangPrefix(); + } + protected static final LightProjectDescriptor ourDescriptor = new LightProjectDescriptor() { public ModuleType getModuleType() { return ModuleType.EMPTY; diff --git a/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/BaseSMTRunnerTestCase.java b/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/BaseSMTRunnerTestCase.java index e6552e9b9f61..607e32a8a2de 100644 --- a/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/BaseSMTRunnerTestCase.java +++ b/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/BaseSMTRunnerTestCase.java @@ -18,6 +18,7 @@ package com.intellij.execution.testframework.sm.runner; import com.intellij.execution.configurations.RuntimeConfiguration; import com.intellij.execution.testframework.TestConsoleProperties; import com.intellij.testFramework.LightPlatformTestCase; +import com.intellij.testFramework.PlatformTestCase; /** * @author Roman Chernyatchik @@ -26,6 +27,10 @@ public abstract class BaseSMTRunnerTestCase extends LightPlatformTestCase { protected SMTestProxy mySuite; protected SMTestProxy mySimpleTest; + protected BaseSMTRunnerTestCase() { + PlatformTestCase.initPlatformLangPrefix(); + } + @Override protected void setUp() throws Exception { super.setUp(); From ba9e9bfb1c37f1b47cad9d8b625b378aa2fed37b Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 31 May 2010 18:00:30 +0400 Subject: [PATCH 064/212] diagnostics --- .../com/intellij/ide/fileTemplates/FileTemplateUtil.java | 9 +++++---- .../util/properties/EncodingAwareProperties.java | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/fileTemplates/FileTemplateUtil.java b/platform/lang-impl/src/com/intellij/ide/fileTemplates/FileTemplateUtil.java index 2bfc43b57dc4..9f763221b164 100644 --- a/platform/lang-impl/src/com/intellij/ide/fileTemplates/FileTemplateUtil.java +++ b/platform/lang-impl/src/com/intellij/ide/fileTemplates/FileTemplateUtil.java @@ -213,7 +213,7 @@ public class FileTemplateUtil{ }; Velocity.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM, emptyLogSystem); Velocity.setProperty(RuntimeConstants.RESOURCE_LOADER, "file,class"); - //todo[myakovlev] implement my oun Loader, with ability to load templates from classpath + //todo[myakovlev] implement my own Loader, with ability to load templates from classpath Velocity.setProperty("file.resource.loader.class", MyFileResourceLoader.class.getName()); Velocity.setProperty("class.resource.loader.class", MyClasspathResourceLoader.class.getName()); Velocity.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, modifiedPatternsPath.getAbsolutePath()); @@ -321,7 +321,7 @@ public class FileTemplateUtil{ File modifiedPatternsPath = new File(PathManager.getConfigPath()); modifiedPatternsPath = new File(modifiedPatternsPath, INCLUDES_PATH); - try{ + try { Field pathsField = FileResourceLoader.class.getDeclaredField("paths"); pathsField.setAccessible(true); Collection paths = (Collection)pathsField.get(this); @@ -333,12 +333,13 @@ public class FileTemplateUtil{ paths.add(testsDir.getAbsolutePath()); } } - catch (Exception e){ + catch (Exception e) { + LOG.error(e); throw new RuntimeException(e); } } } - + public static boolean canCreateFromTemplate (PsiDirectory[] dirs, FileTemplate template) { FileType fileType = FileTypeManagerEx.getInstanceEx().getFileTypeByExtension(template.getExtension()); if (fileType.equals(FileTypes.UNKNOWN)) return false; diff --git a/platform/util/src/com/intellij/util/properties/EncodingAwareProperties.java b/platform/util/src/com/intellij/util/properties/EncodingAwareProperties.java index ab2457748cbe..064833aee51a 100644 --- a/platform/util/src/com/intellij/util/properties/EncodingAwareProperties.java +++ b/platform/util/src/com/intellij/util/properties/EncodingAwareProperties.java @@ -33,7 +33,7 @@ public class EncodingAwareProperties extends java.util.Properties{ propText = StringUtil.convertLineSeparators(propText); StringTokenizer stringTokenizer = new StringTokenizer(propText, "\n"); while (stringTokenizer.hasMoreElements()){ - String line = (String)stringTokenizer.nextElement(); + String line = stringTokenizer.nextElement(); int i = line.indexOf('='); String propName = i == -1 ? line : line.substring(0,i); String propValue = i == -1 ? "" : line.substring(i+1); From bb0854d2ccc6812832cd18820c19f5ea991bd33b Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 31 May 2010 18:31:04 +0400 Subject: [PATCH 065/212] cleanup --- .../problems/WolfTheProblemSolverImpl.java | 50 ++++++++----------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/problems/WolfTheProblemSolverImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/problems/WolfTheProblemSolverImpl.java index 4318a65a2cb6..69624d0e7bb4 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/problems/WolfTheProblemSolverImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/problems/WolfTheProblemSolverImpl.java @@ -73,25 +73,6 @@ public class WolfTheProblemSolverImpl extends WolfTheProblemSolver { } }; - private final VirtualFileListener myVirtualFileListener = new VirtualFileAdapter() { - public void fileDeleted(final VirtualFileEvent event) { - onDeleted(event.getFile()); - } - - public void fileMoved(final VirtualFileMoveEvent event) { - onDeleted(event.getFile()); - } - - private void onDeleted(final VirtualFile file) { - if (file.isDirectory()) { - clearInvalidFiles(); - } - else { - doRemove(file); - } - } - }; - private void doRemove(VirtualFile problemFile) { ProblemFileInfo old; synchronized (myProblems) { @@ -106,8 +87,6 @@ public class WolfTheProblemSolverImpl extends WolfTheProblemSolver { } } - private final PsiTreeChangeListener myChangeListener; - private static class ProblemFileInfo { private final Collection problems = new THashSet(); private boolean hasSyntaxErrors; @@ -118,10 +97,7 @@ public class WolfTheProblemSolverImpl extends WolfTheProblemSolver { final ProblemFileInfo that = (ProblemFileInfo)o; - if (hasSyntaxErrors != that.hasSyntaxErrors) return false; - if (!problems.equals(that.problems)) return false; - - return true; + return hasSyntaxErrors == that.hasSyntaxErrors && problems.equals(that.problems); } public int hashCode() { @@ -133,7 +109,7 @@ public class WolfTheProblemSolverImpl extends WolfTheProblemSolver { public WolfTheProblemSolverImpl(Project project, PsiManager psiManager, VirtualFileManager virtualFileManager) { myProject = project; - myChangeListener = new PsiTreeChangeAdapter() { + PsiTreeChangeListener changeListener = new PsiTreeChangeAdapter() { public void childAdded(PsiTreeChangeEvent event) { childrenChanged(event); } @@ -158,8 +134,26 @@ public class WolfTheProblemSolverImpl extends WolfTheProblemSolver { clearSyntaxErrorFlag(event); } }; - psiManager.addPsiTreeChangeListener(myChangeListener); - virtualFileManager.addVirtualFileListener(myVirtualFileListener, myProject); + psiManager.addPsiTreeChangeListener(changeListener); + VirtualFileListener virtualFileListener = new VirtualFileAdapter() { + public void fileDeleted(final VirtualFileEvent event) { + onDeleted(event.getFile()); + } + + public void fileMoved(final VirtualFileMoveEvent event) { + onDeleted(event.getFile()); + } + + private void onDeleted(final VirtualFile file) { + if (file.isDirectory()) { + clearInvalidFiles(); + } + else { + doRemove(file); + } + } + }; + virtualFileManager.addVirtualFileListener(virtualFileListener, myProject); FileStatusManager fileStatusManager = FileStatusManager.getInstance(myProject); if (fileStatusManager != null) { //tests? fileStatusManager.addFileStatusListener(new FileStatusListener() { From 75d46088033d7113a59d2a53639dd0b9595ce23e Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 31 May 2010 18:33:56 +0400 Subject: [PATCH 066/212] useless work eliminated --- .../daemon/impl/analysis/HighlightVisitorImpl.java | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java index a5f75d1b6229..02c587c440d0 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java @@ -109,20 +109,8 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh LOG.assertTrue(element.isValid()); } element.accept(this); - - if (myRefCountHolder != null) { - instantiateInjections(element); - } } - private void instantiateInjections(final PsiElement element) { - InjectedLanguageUtil.enumerate(element, myFile, new PsiLanguageInjectionHost.InjectedPsiVisitor() { - public void visit(@NotNull final PsiFile injectedPsi, @NotNull final List places) { - // no op - } - }, false); - } - private void registerReferencesFromInjectedFragments(final PsiElement element) { InjectedLanguageUtil.enumerate(element, myFile, new PsiLanguageInjectionHost.InjectedPsiVisitor() { public void visit(@NotNull final PsiFile injectedPsi, @NotNull final List places) { From 0f093b0487cb0495d91065f2a4ecf4eddd690b2e Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 1 Jun 2010 10:09:56 +0400 Subject: [PATCH 067/212] NPE --- .../com/intellij/psi/impl/source/PsiClassReferenceType.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/psi/impl/source/PsiClassReferenceType.java b/java/java-impl/src/com/intellij/psi/impl/source/PsiClassReferenceType.java index be09f49c2670..0022b749bf5d 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/PsiClassReferenceType.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/PsiClassReferenceType.java @@ -138,7 +138,9 @@ public class PsiClassReferenceType extends PsiClassType { return factory.createType(aClass, rawSubstitutor, getLanguageLevel(), getAnnotations()); } String qualifiedName = myReference.getQualifiedName(); - LightClassReference reference = new LightClassReference(myReference.getManager(), myReference.getReferenceName(), qualifiedName, myReference.getResolveScope()); + String name = myReference.getReferenceName(); + if (name==null) name=""; + LightClassReference reference = new LightClassReference(myReference.getManager(), name, qualifiedName, myReference.getResolveScope()); return new PsiClassReferenceType(reference, null,getAnnotations()); } From fa1569b01299804b564c7fa67f13b09d12cb9635 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 1 Jun 2010 10:11:22 +0400 Subject: [PATCH 068/212] cleanup --- .../daemon/impl/CollectHighlightsUtil.java | 110 +++++++++--------- 1 file changed, 53 insertions(+), 57 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/CollectHighlightsUtil.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/CollectHighlightsUtil.java index 6afc04842402..59f11b128a57 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/CollectHighlightsUtil.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/CollectHighlightsUtil.java @@ -26,10 +26,13 @@ import com.intellij.openapi.roots.ProjectFileIndex; import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.util.Condition; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.*; +import com.intellij.psi.PsiCodeFragment; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtilBase; -import gnu.trove.TIntArrayList; +import com.intellij.util.containers.Stack; +import gnu.trove.TIntStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -37,7 +40,7 @@ import java.util.ArrayList; import java.util.List; public class CollectHighlightsUtil { - private static final ExtensionPointName> EP_NAME = ExtensionPointName.create("com.intellij.elementsToHighlightFilter"); + public static final ExtensionPointName> EP_NAME = ExtensionPointName.create("com.intellij.elementsToHighlightFilter"); private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.CollectHighlightsUtil"); @@ -76,65 +79,58 @@ public class CollectHighlightsUtil { final int currentOffset = commonParent.getTextRange().getStartOffset(); final Condition[] filters = Extensions.getExtensions(EP_NAME); - final PsiElementVisitor visitor = new PsiElementVisitor() { - int offset = currentOffset; - - final TIntArrayList starts = new TIntArrayList(STARTING_TREE_HEIGHT); - final List elements = new ArrayList(STARTING_TREE_HEIGHT); - final List children = new ArrayList(STARTING_TREE_HEIGHT); - - @Override public void visitElement(PsiElement element) { - children.add(PsiUtilBase.NULL_PSI_ELEMENT); - - while (true) { - ProgressManager.checkCanceled(); - - PsiElement child = children.remove(children.size() - 1); + int offset = currentOffset; - for (Condition filter : filters) { - if (!filter.value(element)) { - assert child == PsiUtilBase.NULL_PSI_ELEMENT; - child = null; // do not want to process children - break; - } - } + final TIntStack starts = new TIntStack(STARTING_TREE_HEIGHT); + final Stack elements = new Stack(STARTING_TREE_HEIGHT); + final Stack children = new Stack(STARTING_TREE_HEIGHT); + PsiElement element = commonParent; - boolean startChildrenVisiting = false; + PsiElement child = PsiUtilBase.NULL_PSI_ELEMENT; + while (true) { + ProgressManager.checkCanceled(); - if (child == PsiUtilBase.NULL_PSI_ELEMENT) { - startChildrenVisiting = true; - child = element.getFirstChild(); - } - - if (child == null) { - if (startChildrenVisiting) { - // leaf element - offset += element.getTextLength(); - } - - if (elements.size() == 0) break; - int start = starts.remove(starts.size() - 1); - if (startOffset <= start && offset <= endOffset) result.add(element); - - element = elements.remove(elements.size() - 1); - } - else { - // composite element - if (offset <= endOffset) { - starts.add(offset); - children.add(child.getNextSibling()); - children.add(PsiUtilBase.NULL_PSI_ELEMENT); - elements.add(element); - element = child; - } else { - break; - } - } + for (Condition filter : filters) { + if (!filter.value(element)) { + assert child == PsiUtilBase.NULL_PSI_ELEMENT; + child = null; // do not want to process children + break; } } - }; - commonParent.accept(visitor); - + + 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(); + } + + if (elements.isEmpty()) break; + int start = starts.pop(); + if (startOffset <= start && offset <= endOffset) result.add(element); + + 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; + } + } + return result; } From 720c574df7fdd75fe1c90c73c855823c853cb728 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 1 Jun 2010 10:14:20 +0400 Subject: [PATCH 069/212] NPE --- .../intellij/ide/projectView/impl/GroupByTypeComparator.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/GroupByTypeComparator.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/GroupByTypeComparator.java index 605c41bc52d5..f28ba06f9ea2 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/GroupByTypeComparator.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/GroupByTypeComparator.java @@ -97,7 +97,8 @@ public class GroupByTypeComparator implements Comparator { } } } - + if (descriptor1 == null) return -1; + if (descriptor2 == null) return 1; return AlphaComparator.INSTANCE.compare(descriptor1, descriptor2); } From db6202c39af355d5330db65d6c7fa27414399359 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 1 Jun 2010 10:29:06 +0400 Subject: [PATCH 070/212] cleanup --- .../com/intellij/psi/util/PropertyUtil.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/java/openapi/src/com/intellij/psi/util/PropertyUtil.java b/java/openapi/src/com/intellij/psi/util/PropertyUtil.java index 615dce0ebb35..ec4cb396e9a4 100644 --- a/java/openapi/src/com/intellij/psi/util/PropertyUtil.java +++ b/java/openapi/src/com/intellij/psi/util/PropertyUtil.java @@ -54,16 +54,17 @@ public class PropertyUtil { String methodName = method.getName(); PsiType returnType = method.getReturnType(); - if (methodName.startsWith("get") && methodName.length() > "get".length()) { + int methodNameLength = methodName.length(); + if (methodName.startsWith("get") && methodNameLength > "get".length()) { if (Character.isLowerCase(methodName.charAt("get".length())) - && (methodName.length() == "get".length() + 1 || Character.isLowerCase(methodName.charAt("get".length() + 1)))) { + && (methodNameLength == "get".length() + 1 || Character.isLowerCase(methodName.charAt("get".length() + 1)))) { return false; } if (returnType != null && PsiType.VOID.equals(returnType)) return false; } - else if (methodName.startsWith("is") && methodName.length() > "is".length()) { + else if (methodName.startsWith("is") && methodNameLength > "is".length()) { if (Character.isLowerCase(methodName.charAt("is".length())) - && (methodName.length() == "is".length() + 1 || Character.isLowerCase(methodName.charAt("is".length() + 1)))) { + && (methodNameLength == "is".length() + 1 || Character.isLowerCase(methodName.charAt("is".length() + 1)))) { return false; } return isBoolean(returnType); @@ -209,7 +210,8 @@ public class PropertyUtil { return null; } - @Nullable public static PsiMethod findPropertyGetterWithType(String propertyName, boolean isStatic, PsiType type, Iterator methods) { + @Nullable + public static PsiMethod findPropertyGetterWithType(String propertyName, boolean isStatic, PsiType type, Iterator methods) { while (methods.hasNext()) { PsiMethod method = methods.next(); if (method.hasModifierProperty(PsiModifier.STATIC) != isStatic) continue; @@ -252,7 +254,8 @@ public class PropertyUtil { return null; } - @Nullable public static PsiMethod findPropertySetterWithType(String propertyName, boolean isStatic, PsiType type, Iterator methods) { + @Nullable + public static PsiMethod findPropertySetterWithType(String propertyName, boolean isStatic, PsiType type, Iterator methods) { while (methods.hasNext()) { PsiMethod method = methods.next(); if (method.hasModifierProperty(PsiModifier.STATIC) != isStatic) continue; @@ -500,7 +503,8 @@ public class PropertyUtil { /** * "xxx", "void setMyProperty(String pp)" -> "setXxx" */ - @Nullable public static String suggestPropertyAccessor(String name, PsiMethod accessorTemplate) { + @Nullable + public static String suggestPropertyAccessor(String name, PsiMethod accessorTemplate) { if (isSimplePropertyGetter(accessorTemplate)) { PsiType type = accessorTemplate.getReturnType(); return suggestGetterName(name, type, accessorTemplate.getName()); From f1fba9c5433be5fe354f47ef30c7160f1789c9d9 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 1 Jun 2010 10:33:38 +0400 Subject: [PATCH 071/212] NPE --- .../src/com/intellij/psi/impl/PsiDocumentManagerImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java index b2151518a7b1..accd3020209a 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java @@ -170,7 +170,7 @@ public class PsiDocumentManagerImpl extends PsiDocumentManager implements Projec if (!file.getViewProvider().isEventSystemEnabled()) return null; document = FileDocumentManager.getInstance().getDocument(file.getViewProvider().getVirtualFile()); - if (!file.getViewProvider().isPhysical()) { + if (document != null && !file.getViewProvider().isPhysical()) { cachePsi(document, file); } From e4f87ccaaa0b70d87ad3307a6b7326de061606ca Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 1 Jun 2010 10:47:04 +0400 Subject: [PATCH 072/212] EA-19847 --- .../openapi/actionSystem/Presentation.java | 16 +++++++++------- .../intellij/openapi/util/text/StringUtil.java | 2 +- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/Presentation.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/Presentation.java index 715a325a8c4c..54535d714467 100644 --- a/platform/platform-api/src/com/intellij/openapi/actionSystem/Presentation.java +++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/Presentation.java @@ -18,6 +18,7 @@ package com.intellij.openapi.actionSystem; import com.intellij.util.ui.UIUtil; import gnu.trove.THashMap; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.beans.PropertyChangeListener; @@ -174,13 +175,14 @@ public final class Presentation implements Cloneable { setText(presentation.getTextWithMnemonic()); } - public static String restoreTextWithMnemonic(final String text, final int mnemonic) { - if (text != null) { - for (int i = 0; i < text.length(); i++) { - if (Character.toUpperCase(text.charAt(i)) == mnemonic) { - return text.replaceFirst(String.valueOf(text.charAt(i)), "_" + text.charAt(i)); - } - } + public static String restoreTextWithMnemonic(@Nullable String text, final int mnemonic) { + if (text == null) { + return null; + } + for (int i = 0; i < text.length(); i++) { + if (Character.toUpperCase(text.charAt(i)) == mnemonic) { + return text.substring(0, i) + "_" + text.substring(i); + } } return text; } diff --git a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java index ed99449c231a..19faf3c99e3f 100644 --- a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java +++ b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java @@ -1172,7 +1172,7 @@ public class StringUtil { } @NotNull public static String replaceSubstring(@NotNull String string, @NotNull TextRange range, @NotNull String replacement) { - return string.substring(0, range.getStartOffset()) + replacement + string.substring(range.getEndOffset()); + return range.replace(string, replacement); } public static boolean startsWith(@NotNull CharSequence text, @NotNull CharSequence prefix) { From 09d7a4d1693a766c7925bf4c727a9ff5ec5e865f Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 1 Jun 2010 10:49:28 +0400 Subject: [PATCH 073/212] EA-19798 --- .../daemon/impl/quickfix/RemoveUnusedVariableFix.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RemoveUnusedVariableFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RemoveUnusedVariableFix.java index 6d12e5e69805..cf9505c1b85c 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RemoveUnusedVariableFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RemoveUnusedVariableFix.java @@ -39,8 +39,6 @@ import java.util.*; public class RemoveUnusedVariableFix implements IntentionAction { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.quickfix.RemoveUnusedVariableFix"); private final PsiVariable myVariable; - @NonNls private static final String JAVA_LANG_PCKG = "java.lang"; - @NonNls private static final String JAVA_IO_PCKG = "java.io"; public RemoveUnusedVariableFix(PsiVariable variable) { myVariable = variable; @@ -356,10 +354,10 @@ public class RemoveUnusedVariableFix implements IntentionAction { PsiFile file = aClass.getContainingFile(); PsiDirectory directory = file.getContainingDirectory(); PsiPackage classPackage = JavaDirectoryService.getInstance().getPackage(directory); - String packageName = classPackage.getQualifiedName(); + String packageName = classPackage == null ? null : classPackage.getQualifiedName(); // all Throwable descendants from java.lang are side effects free - if (JAVA_LANG_PCKG.equals(packageName) || JAVA_IO_PCKG.equals(packageName)) { + if ("java.lang".equals(packageName) || "java.io".equals(packageName)) { PsiClass throwableClass = JavaPsiFacade.getInstance(aClass.getProject()).findClass("java.lang.Throwable", aClass.getResolveScope()); if (throwableClass != null && InheritanceUtil.isInheritorOrSelf(aClass, throwableClass, true)) { return true; From 01610e66f00677d91817b6a66db6f27da1c56d49 Mon Sep 17 00:00:00 2001 From: Kirill Kalishev Date: Tue, 1 Jun 2010 13:37:55 +0400 Subject: [PATCH 074/212] TreeUi doesnt paint selection while busy and adjusting selected paths --- .../util/treeView/AbstractTreeBuilder.java | 5 ++ .../ide/util/treeView/AbstractTreeUi.java | 20 ++++++++ .../com/intellij/ui/treeStructure/Tree.java | 48 +++++++++++++++++-- .../util/src/com/intellij/util/ui/UIUtil.java | 26 +++++++--- 4 files changed, 87 insertions(+), 12 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeBuilder.java b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeBuilder.java index 1190f882346a..55d3cb0827c4 100644 --- a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeBuilder.java +++ b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeBuilder.java @@ -492,4 +492,9 @@ public class AbstractTreeBuilder implements Disposable { return app != null && app.isUnitTestMode(); } + public static boolean isToPaintSelection(JTree tree) { + AbstractTreeBuilder builder = getBuilderFor(tree); + return builder == null ? true : builder.getUi().isToPaintSelection(); + } + } diff --git a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java index 8d6d33e9c7f5..8f872a3dd310 100644 --- a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java +++ b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java @@ -172,6 +172,8 @@ public class AbstractTreeUi { private Map myCancelledBuild = new WeakHashMap(); + private boolean mySelectionIsAdjusted; + protected void init(AbstractTreeBuilder builder, JTree tree, DefaultTreeModel treeModel, @@ -1825,6 +1827,17 @@ public class AbstractTreeUi { if (myInitialized.isDone()) { myBusyObject.onReady(); } + + TreePath[] selection = getTree().getSelectionPaths(); + Rectangle visible = getTree().getVisibleRect(); + if (selection != null) { + for (TreePath each : selection) { + Rectangle bounds = getTree().getPathBounds(each); + if (bounds != null && (visible.contains(bounds) || visible.intersects(bounds))) { + getTree().repaint(bounds); + } + } + } } } @@ -2153,6 +2166,10 @@ public class AbstractTreeUi { return myCancelRequest.get() || myResettingToReadyNow.get(); } + public boolean isToPaintSelection() { + return isReady() || !mySelectionIsAdjusted; + } + static class ElementNode extends DefaultMutableTreeNode { Set myElements = new HashSet(); @@ -2766,6 +2783,8 @@ public class AbstractTreeUi { } if (toSelect != null) { + mySelectionIsAdjusted = isAdjustedSelection; + myTree.addSelectionPath(toSelect); if (isAdjustedSelection && myUpdaterState != null) { @@ -3948,6 +3967,7 @@ public class AbstractTreeUi { if (!isInnerChange()) { clearUpdaterState(); myAutoExpandRoots.clear(); + mySelectionIsAdjusted = false; } } diff --git a/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java b/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java index 3989ac967ec8..744a92eb4ead 100644 --- a/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java +++ b/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java @@ -29,6 +29,7 @@ import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import javax.swing.event.TreeSelectionEvent; import javax.swing.plaf.TreeUI; import javax.swing.plaf.basic.BasicTreeUI; import javax.swing.text.Position; @@ -48,6 +49,7 @@ public class Tree extends JTree implements ComponentWithEmptyText, Autoscroll, Q private Rectangle myLastVisibleRec; private Dimension myHoldSize; + private MySelectionModel mySelectionModel = new MySelectionModel(); public Tree() { initTree_(); @@ -80,6 +82,8 @@ public class Tree extends JTree implements ComponentWithEmptyText, Autoscroll, Q } setCellRenderer(new NodeRenderer()); + + setSelectionModel(mySelectionModel); } @Override @@ -161,15 +165,25 @@ public class Tree extends JTree implements ComponentWithEmptyText, Autoscroll, Q @Override public void paint(Graphics g) { - super.paint(g); - + Rectangle clip = g.getClipBounds(); final Rectangle visible = getVisibleRect(); - if (!visible.equals(myLastVisibleRec)) { - updateBusyIconLocation(); + if (!AbstractTreeBuilder.isToPaintSelection(this)) { + mySelectionModel.holdSelection(); } - myLastVisibleRec = visible; + try { + super.paint(g); + + if (!visible.equals(myLastVisibleRec)) { + updateBusyIconLocation(); + } + + myLastVisibleRec = visible; + } + finally { + mySelectionModel.unholdSelection(); + } } public void setPaintBusy(boolean paintBusy) { @@ -453,6 +467,30 @@ public class Tree extends JTree implements ComponentWithEmptyText, Autoscroll, Q return treeNode != null ? new TreePath(treeNode.getPath()) : new TreePath(node); } + private static class MySelectionModel extends DefaultTreeSelectionModel { + + private TreePath[] myHeldSelection; + + @Override + protected void fireValueChanged(TreeSelectionEvent e) { + if (myHeldSelection == null) { + super.fireValueChanged(e); + } + } + + public void holdSelection() { + myHeldSelection = getSelectionPaths(); + clearSelection(); + } + + public void unholdSelection() { + if (myHeldSelection != null) { + setSelectionPaths(myHeldSelection); + myHeldSelection = null; + } + } + } + private class MyMouseListener extends MouseAdapter { public void mousePressed(MouseEvent mouseevent) { if (!SwingUtilities.isLeftMouseButton(mouseevent) && diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index e7403bfde54e..65d33a10054f 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -1213,7 +1213,9 @@ public class UIUtil { final int containerWidth = tree.getParent() instanceof JViewport ? tree.getParent().getWidth() : tree.getWidth(); final int xOffset = tree.getParent() instanceof JViewport ? ((JViewport)tree.getParent()).getViewPosition().x : 0; - if (path != null && tree.isPathSelected(path)) { + boolean selected = false; + if (path != null) { + selected = tree.isPathSelected(path); Graphics2D rowGraphics = (Graphics2D)g.create(); if (clipBounds.height >= bounds.height) { // fill the row only if clip bounds intersects actual node bounds @@ -1226,14 +1228,24 @@ public class UIUtil { final Object sourceList = tree.getClientProperty(SOURCE_LIST_CLIENT_PROPERTY); if (sourceList != null && ((Boolean)sourceList)) { - if (tree.hasFocus()) { - LIST_FOCUSED_SELECTION_BACKGROUND_PAINTER.paintBorder(tree, rowGraphics, xOffset, bounds.y, containerWidth, bounds.height); - } - else { - LIST_SELECTION_BACKGROUND_PAINTER.paintBorder(tree, rowGraphics, xOffset, bounds.y, containerWidth, bounds.height); + if (selected) { + if (tree.hasFocus()) { + LIST_FOCUSED_SELECTION_BACKGROUND_PAINTER.paintBorder(tree, rowGraphics, xOffset, bounds.y, containerWidth, bounds.height); + } + else { + LIST_SELECTION_BACKGROUND_PAINTER.paintBorder(tree, rowGraphics, xOffset, bounds.y, containerWidth, bounds.height); + } + } else { + rowGraphics.setColor(tree.getBackground()); + rowGraphics.fillRect(xOffset, bounds.y, containerWidth, bounds.height); } } else { - rowGraphics.setColor(tree.hasFocus() ? getTreeSelectionBackground() : UNFOCUSED_SELECTION_COLOR); + Color bg = tree.hasFocus() ? getTreeSelectionBackground() : UNFOCUSED_SELECTION_COLOR; + if (!selected) { + bg = tree.getBackground(); + } + + rowGraphics.setColor(bg); rowGraphics.fillRect(xOffset, bounds.y, containerWidth, bounds.height - 1); } From 653e42934ac795652482e0f501f75413b7b7c23d Mon Sep 17 00:00:00 2001 From: Kirill Kalishev Date: Tue, 1 Jun 2010 13:46:39 +0400 Subject: [PATCH 075/212] maven modules added to the community project --- .idea/modules.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.idea/modules.xml b/.idea/modules.xml index e177cad44135..617580da14c0 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -59,6 +59,8 @@ + + From bd80cd8b201469ebf9bcda2d5dbf67ac7b75dd0a Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Tue, 1 Jun 2010 13:46:19 +0400 Subject: [PATCH 076/212] Maven: deadlock fix + cleanup --- .../execution/rmi/RemoteProcessSupport.java | 2 +- plugins/maven/maven-plugin.iml | 78 --- plugins/maven/maven-plugin.ipr | 445 ------------------ .../MavenParentRelativePathConverter.java | 1 - .../maven/facade/MavenEmbedderWrapper.java | 7 +- .../idea/maven/facade/MavenFacadeManager.java | 11 +- .../idea/maven/project/MavenProject.java | 2 - .../maven/utils/RepositoryAttachHandler.java | 1 + 8 files changed, 7 insertions(+), 540 deletions(-) delete mode 100644 plugins/maven/maven-plugin.iml delete mode 100644 plugins/maven/maven-plugin.ipr diff --git a/platform/lang-impl/src/com/intellij/execution/rmi/RemoteProcessSupport.java b/platform/lang-impl/src/com/intellij/execution/rmi/RemoteProcessSupport.java index 6ae69943c34a..bac4210beea1 100644 --- a/platform/lang-impl/src/com/intellij/execution/rmi/RemoteProcessSupport.java +++ b/platform/lang-impl/src/com/intellij/execution/rmi/RemoteProcessSupport.java @@ -90,7 +90,7 @@ public abstract class RemoteProcessSupport { runnable.run(); } else { - ApplicationManager.getApplication().invokeLater(runnable); + ApplicationManager.getApplication().executeOnPooledThread(runnable); } if (ref.isNull()) { try { diff --git a/plugins/maven/maven-plugin.iml b/plugins/maven/maven-plugin.iml deleted file mode 100644 index 3e0fe892aeb3..000000000000 --- a/plugins/maven/maven-plugin.iml +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/plugins/maven/maven-plugin.ipr b/plugins/maven/maven-plugin.ipr deleted file mode 100644 index d2c4eae9a682..000000000000 --- a/plugins/maven/maven-plugin.ipr +++ /dev/null @@ -1,445 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenParentRelativePathConverter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenParentRelativePathConverter.java index 99e83a9809d4..5401ea9a1104 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenParentRelativePathConverter.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenParentRelativePathConverter.java @@ -46,7 +46,6 @@ public class MavenParentRelativePathConverter extends ResolvingConverter projectIdToFileMap, MavenConsole console, MavenProgressIndicator indicator) { try { - resetConsole(MavenFacadeManager.wrapandExport(console)); + resetConsole(MavenFacadeManager.wrapAndExport(console)); resetIndicator(MavenFacadeManager.wrapAndExport(indicator)); myWrappee.customizeForResolve(projectIdToFileMap, myConsole, myIndicator); @@ -69,7 +68,7 @@ public class MavenEmbedderWrapper { MavenConsole console, MavenProgressIndicator indicator) { try { - resetConsole(MavenFacadeManager.wrapandExport(console)); + resetConsole(MavenFacadeManager.wrapAndExport(console)); resetIndicator(MavenFacadeManager.wrapAndExport(indicator)); myWrappee.customizeForStrictResolve(projectIdToFileMap, myConsole, myIndicator); diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/facade/MavenFacadeManager.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/facade/MavenFacadeManager.java index e16d96c71154..05efd4ebba47 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/facade/MavenFacadeManager.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/facade/MavenFacadeManager.java @@ -119,7 +119,6 @@ public class MavenFacadeManager { myFacade.setLogger(myLogger); } catch (Exception e) { - // todo throw new RuntimeException(e); } } @@ -146,6 +145,7 @@ public class MavenFacadeManager { addPluginLibraries(params.getClassPath()); params.setMainClass(MAIN_CLASS); + // todo pass sensible parameters, MAVEN_OPTS? params.getVMParametersList().addParametersString("-d32 -Xmx512m"); return params; } @@ -207,7 +207,6 @@ public class MavenFacadeManager { return new MavenEmbedderWrapper(facade.createEmbedder(convertSettings(settings))); } catch (RemoteException e) { - // todo throw new RuntimeException(e); } } @@ -217,7 +216,6 @@ public class MavenFacadeManager { return new MavenIndexerWrapper(getFacade().createIndexer()); } catch (RemoteException e) { - //todo throw new RuntimeException(e); } } @@ -227,7 +225,6 @@ public class MavenFacadeManager { return getFacade().getRepositories(nexusUrl); } catch (RemoteException e) { - // todo throw new RuntimeException(e); } } @@ -237,7 +234,6 @@ public class MavenFacadeManager { return getFacade().findArtifacts(template, nexusUrl); } catch (RemoteException e) { - // todo throw new RuntimeException(e); } } @@ -247,7 +243,6 @@ public class MavenFacadeManager { return getFacade().interpolateAndAlignModel(model, basedir); } catch (RemoteException e) { - // todo throw new RuntimeException(e); } } @@ -257,7 +252,6 @@ public class MavenFacadeManager { return getFacade().assembleInheritance(model, parentModel); } catch (RemoteException e) { - // todo throw new RuntimeException(e); } } @@ -270,7 +264,6 @@ public class MavenFacadeManager { return getFacade().applyProfiles(model, basedir, explicitProfiles, alwaysOnProfiles); } catch (RemoteException e) { - // todo throw new RuntimeException(e); } } @@ -288,7 +281,7 @@ public class MavenFacadeManager { return result; } - public static MavenFacadeConsole wrapandExport(final MavenConsole console) { + public static MavenFacadeConsole wrapAndExport(final MavenConsole console) { try { RemoteMavenFacadeConsole result = new RemoteMavenFacadeConsole(console); UnicastRemoteObject.exportObject(result, 0); diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java index e418cf3d073c..92a679924f80 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java @@ -193,8 +193,6 @@ public class MavenProject { state.myDependencyTree = new ArrayList(newDependencyTree); state.myPlugins = new ArrayList(newPlugins); state.myExtensions = new ArrayList(newExtensions); - - // todo remove non-default managed plugins } private MavenProjectChanges setFolders(MavenProjectReaderResult readerResult) { diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/RepositoryAttachHandler.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/RepositoryAttachHandler.java index 20d95c1d4a0e..8b1dd138cff9 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/RepositoryAttachHandler.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/RepositoryAttachHandler.java @@ -476,6 +476,7 @@ public class RepositoryAttachHandler implements LibraryTableAttachHandler { }); } + // todo //public static RemoteTransferListener fromProgressIndicator(final ProgressIndicator indicator) { // return new RemoteTransferListenerImpl() { // From d958a329966574c7119f1ca93d787f07576e02ab Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 1 Jun 2010 13:34:53 +0400 Subject: [PATCH 077/212] running tests on module's classpath: svn --- .../testSource/org/jetbrains/idea/svn/SvnTestCase.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnTestCase.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnTestCase.java index 16acb4db96ab..fb12e414c72f 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnTestCase.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnTestCase.java @@ -19,6 +19,7 @@ import com.intellij.openapi.vcs.changes.*; import com.intellij.openapi.vcs.changes.pending.MockChangeListManagerGate; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.testFramework.AbstractVcsTestCase; +import com.intellij.testFramework.PlatformTestCase; import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory; import com.intellij.testFramework.fixtures.TempDirTestFixture; import com.intellij.testFramework.vcs.MockChangelistBuilder; @@ -40,6 +41,10 @@ public abstract class SvnTestCase extends AbstractVcsTestCase { private ChangeListManagerGate myGate; protected AtomicSectionsAware myRefreshCopiesStub; + protected SvnTestCase() { + PlatformTestCase.initPlatformLangPrefix(); + } + @Before public void setUp() throws Exception { final IdeaTestFixtureFactory fixtureFactory = IdeaTestFixtureFactory.getFixtureFactory(); From 77bf589751060aa81413db092e079944b2acf287 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Tue, 1 Jun 2010 14:05:47 +0400 Subject: [PATCH 078/212] [Mercurial] one more merge of previous changes. --- .../org/zmlx/hg4idea/HgVcsMessages.properties | 7 +- .../org/zmlx/hg4idea/HgIdeConfigurable.java | 13 +-- .../zmlx/hg4idea/HgProjectConfigurable.java | 10 +- .../hg4idea/ui/HgConfigurationIdePanel.form | 2 +- .../hg4idea/ui/HgConfigurationIdePanel.java | 62 +----------- .../hg4idea/ui/HgSetExecutableDialog.form | 18 +--- .../hg4idea/ui/HgSetExecutableDialog.java | 95 ++++--------------- 7 files changed, 45 insertions(+), 162 deletions(-) diff --git a/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties b/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties index dd0c21cc4651..acd0c6cce8f3 100644 --- a/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties +++ b/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties @@ -1,5 +1,5 @@ group.hg4idea.global.menu.text=Mercurial -group.hg4idea.global.submenu.text=Mercurial +group.hg4idea.global.submenu.text=Mercurial Actions group.hg4idea.file.menu.text=Mercurial action.hg4idea.tag.text=Tag Repository action.hg4idea.tag.description=Create a tag for current revision @@ -21,6 +21,11 @@ hg4idea.error=Error hg4idea.revert=Revert hg4idea.commit=Commit +hg4idea.init.destination.directory.description=Select directory where the new Mercurial repository will be created. +hg4idea.init.destination.directory.title=Select directory for hg init +hg4idea.init.error.already.under.hg=The selected directory {0} is already under hg. +hg4idea.init.error.title=hg init Error + hg4idea.clone.title=Clone Mercurial Repostiroy hg4idea.clone.button.clone=Clone hg4idea.clone.button.test=&Test Repository diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgIdeConfigurable.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgIdeConfigurable.java index 861d0301ff36..07cc5989f4ee 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgIdeConfigurable.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgIdeConfigurable.java @@ -19,7 +19,7 @@ import org.zmlx.hg4idea.ui.*; import javax.swing.*; -public class HgIdeConfigurable implements ApplicationComponent, Configurable { +public class HgIdeConfigurable implements SearchableConfigurable { private final HgConfigurationIdePanel panel; @@ -60,14 +60,11 @@ public class HgIdeConfigurable implements ApplicationComponent, Configurable { public void disposeUIResources() { } - @NotNull - public String getComponentName() { - return getClass().getName(); + public String getId() { + return "Mercurial"; } - public void initComponent() { - } - - public void disposeComponent() { + public Runnable enableSearch(String option) { + return null; } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgProjectConfigurable.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgProjectConfigurable.java index 5ccba0456b07..18197c9b130e 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgProjectConfigurable.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgProjectConfigurable.java @@ -18,7 +18,7 @@ import org.zmlx.hg4idea.ui.*; import javax.swing.*; -public class HgProjectConfigurable implements Configurable { +public class HgProjectConfigurable implements SearchableConfigurable { private final HgConfigurationProjectPanel hgConfigurationProjectPanel; @@ -58,4 +58,12 @@ public class HgProjectConfigurable implements Configurable { public void disposeUIResources() { } + public String getId() { + return "Mercurial.Project"; + } + + public Runnable enableSearch(String option) { + return null; + } + } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationIdePanel.form b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationIdePanel.form index 79ffd1b867bb..4dcb91491827 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationIdePanel.form +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationIdePanel.form @@ -34,7 +34,7 @@ - + diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationIdePanel.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationIdePanel.java index cbad294a253f..3125be974af6 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationIdePanel.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationIdePanel.java @@ -12,16 +12,13 @@ // limitations under the License. package org.zmlx.hg4idea.ui; -import com.intellij.openapi.fileChooser.*; import com.intellij.openapi.options.*; import com.intellij.openapi.ui.*; -import com.intellij.uiDesigner.core.*; import org.apache.commons.lang.*; import org.zmlx.hg4idea.*; import org.zmlx.hg4idea.command.*; import javax.swing.*; -import java.awt.*; import java.awt.event.*; public class HgConfigurationIdePanel { @@ -36,14 +33,6 @@ public class HgConfigurationIdePanel { this.globalSettings = globalSettings; loadSettings(); - String title = HgVcsMessages.message("hg4idea.configuration.title"); - String description = HgVcsMessages.message("hg4idea.configuration.description"); - - pathSelector.addBrowseFolderListener( - title, description, null, - new FileChooserDescriptor(true, false, false, false, false, false) - ); - final ActionListener listener = new ActionListener() { public void actionPerformed(ActionEvent e) { pathSelector.setEnabled(selectRadioButton.isSelected()); @@ -100,54 +89,7 @@ public class HgConfigurationIdePanel { } } - { -// GUI initializer generated by IntelliJ IDEA GUI Designer -// >>> IMPORTANT!! <<< -// DO NOT EDIT OR ADD ANY CODE HERE! - $$$setupUI$$$(); - } - - /** - * Method generated by IntelliJ IDEA GUI Designer - * >>> IMPORTANT!! <<< - * DO NOT edit this method OR call it in your code! - * - * @noinspection ALL - */ - private void $$$setupUI$$$() { - basePanel = new JPanel(); - basePanel.setLayout(new GridLayoutManager(2, 1, new Insets(0, 0, 0, 0), -1, -1)); - final JPanel panel1 = new JPanel(); - panel1.setLayout(new GridLayoutManager(2, 2, new Insets(0, 0, 0, 0), -1, -1)); - basePanel.add(panel1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, false)); - panel1.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Path to hg executable")); - autoRadioButton = new JRadioButton(); - autoRadioButton.setSelected(true); - autoRadioButton.setText("Autodetect hg in PATH"); - autoRadioButton.setMnemonic('A'); - autoRadioButton.setDisplayedMnemonicIndex(0); - panel1.add(autoRadioButton, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); - selectRadioButton = new JRadioButton(); - selectRadioButton.setEnabled(true); - selectRadioButton.setText("Specify executable path"); - selectRadioButton.setMnemonic('S'); - selectRadioButton.setDisplayedMnemonicIndex(0); - panel1.add(selectRadioButton, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); - pathSelector = new TextFieldWithBrowseButton(); - pathSelector.setEnabled(false); - panel1.add(pathSelector, new GridConstraints(1, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, new Dimension(100, -1), null, null, 0, false)); - final Spacer spacer1 = new Spacer(); - basePanel.add(spacer1, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); - ButtonGroup buttonGroup; - buttonGroup = new ButtonGroup(); - buttonGroup.add(autoRadioButton); - buttonGroup.add(selectRadioButton); - } - - /** - * @noinspection ALL - */ - public JComponent $$$getRootComponent$$$() { - return basePanel; + private void createUIComponents() { + pathSelector = new HgSetExecutablePathPanel(); } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgSetExecutableDialog.form b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgSetExecutableDialog.form index 2a0505454315..21934fd9a881 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgSetExecutableDialog.form +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgSetExecutableDialog.form @@ -1,6 +1,6 @@ - + @@ -8,7 +8,7 @@ - + @@ -16,7 +16,7 @@ - + @@ -24,19 +24,9 @@ - - - - - - - - - - - + diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgSetExecutableDialog.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgSetExecutableDialog.java index 6b9530eb03c5..915ed8000f75 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgSetExecutableDialog.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgSetExecutableDialog.java @@ -12,20 +12,18 @@ // limitations under the License. package org.zmlx.hg4idea.ui; -import com.intellij.openapi.project.*; -import com.intellij.openapi.ui.*; -import com.intellij.uiDesigner.core.*; -import org.zmlx.hg4idea.*; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.DialogWrapper; +import org.zmlx.hg4idea.HgVcsMessages; import javax.swing.*; -import java.awt.*; -import java.util.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; public class HgSetExecutableDialog extends DialogWrapper { - private JPanel centerPanel; - private TextFieldWithBrowseButton hgExecutablePath; - private JLabel infoLabel; - private JLabel errorLabel; + private JPanel myCenterPanel; + private HgSetExecutablePathPanel myHgExecutablePath; + private JLabel myInfoLabel; public HgSetExecutableDialog(Project project) { super(project, false); @@ -34,81 +32,24 @@ public class HgSetExecutableDialog extends DialogWrapper { @Override protected JComponent createCenterPanel() { - return centerPanel; + return myCenterPanel; } public void setBadHgPath(String hgPath) { - hgExecutablePath.setText(hgPath); - errorLabel.setText(HgVcsMessages.message("hg4idea.error.invalidExecutable", hgPath)); + myHgExecutablePath.setText(hgPath); + setErrorText(HgVcsMessages.message("hg4idea.configuration.executable.error", hgPath)); } public String getNewHgPath() { - return hgExecutablePath.getText(); + return myHgExecutablePath.getText(); } - - { -// GUI initializer generated by IntelliJ IDEA GUI Designer -// >>> IMPORTANT!! <<< -// DO NOT EDIT OR ADD ANY CODE HERE! - $$$setupUI$$$(); - } - - /** - * Method generated by IntelliJ IDEA GUI Designer - * >>> IMPORTANT!! <<< - * DO NOT edit this method OR call it in your code! - * - * @noinspection ALL - */ - private void $$$setupUI$$$() { - centerPanel = new JPanel(); - centerPanel.setLayout(new GridLayoutManager(4, 1, new Insets(0, 0, 0, 0), -1, -1)); - hgExecutablePath = new TextFieldWithBrowseButton(); - centerPanel.add(hgExecutablePath, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_NORTHWEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, new Dimension(400, -1), null, 0, false)); - infoLabel = new JLabel(); - infoLabel.setText("Full path to hg executable or 'hg' if PATH has it:"); - centerPanel.add(infoLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); - errorLabel = new JLabel(); - errorLabel.setFont(new Font(errorLabel.getFont().getName(), Font.ITALIC, errorLabel.getFont().getSize())); - errorLabel.setForeground(Color.red); - this.$$$loadLabelText$$$(errorLabel, ResourceBundle.getBundle("org/zmlx/hg4idea/HgVcsMessages").getString("hg4idea.error.invalidExecutable")); - centerPanel.add(errorLabel, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); - final Spacer spacer1 = new Spacer(); - centerPanel.add(spacer1, new GridConstraints(3, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); - } - - /** - * @noinspection ALL - */ - private void $$$loadLabelText$$$(JLabel component, String text) { - StringBuffer result = new StringBuffer(); - boolean haveMnemonic = false; - char mnemonic = '\0'; - int mnemonicIndex = -1; - for (int i = 0; i < text.length(); i++) { - if (text.charAt(i) == '&') { - i++; - if (i == text.length()) break; - if (!haveMnemonic && text.charAt(i) != '&') { - haveMnemonic = true; - mnemonic = text.charAt(i); - mnemonicIndex = result.length(); - } + private void createUIComponents() { + myHgExecutablePath = new HgSetExecutablePathPanel(); + myHgExecutablePath.addOKListener(new ActionListener() { + public void actionPerformed(ActionEvent event) { + setErrorText(""); } - result.append(text.charAt(i)); - } - component.setText(result.toString()); - if (haveMnemonic) { - component.setDisplayedMnemonic(mnemonic); - component.setDisplayedMnemonicIndex(mnemonicIndex); - } - } - - /** - * @noinspection ALL - */ - public JComponent $$$getRootComponent$$$() { - return centerPanel; + }); } } From bd1722dd3729c46378f1f72d49cd07069de8d9d3 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Tue, 1 Jun 2010 15:30:09 +0400 Subject: [PATCH 079/212] Maven: npe & deadlock fix --- .../execution/rmi/RemoteProcessSupport.java | 2 +- .../idea/maven/facade/MavenFacadeManager.java | 16 ++++++++++------ .../idea/maven/project/MavenEnvironmentForm.java | 4 ---- .../jetbrains/idea/maven/utils/MavenUtil.java | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/rmi/RemoteProcessSupport.java b/platform/lang-impl/src/com/intellij/execution/rmi/RemoteProcessSupport.java index bac4210beea1..3583d5e1a7c5 100644 --- a/platform/lang-impl/src/com/intellij/execution/rmi/RemoteProcessSupport.java +++ b/platform/lang-impl/src/com/intellij/execution/rmi/RemoteProcessSupport.java @@ -86,7 +86,7 @@ public abstract class RemoteProcessSupport { startProcess(target, configuration, key); } }; - if (ApplicationManager.getApplication().isDispatchThread()) { + if (ApplicationManager.getApplication().isWriteAccessAllowed()) { runnable.run(); } else { diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/facade/MavenFacadeManager.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/facade/MavenFacadeManager.java index 05efd4ebba47..cbd3664a1046 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/facade/MavenFacadeManager.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/facade/MavenFacadeManager.java @@ -38,10 +38,12 @@ import com.intellij.openapi.projectRoots.JavaSdkType; import com.intellij.openapi.projectRoots.JdkUtil; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.projectRoots.SimpleJavaSdkType; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.ShutDownTracker; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.PathUtil; import com.intellij.util.PathsList; +import com.intellij.util.SmartList; import com.intellij.util.SystemProperties; import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashSet; @@ -142,7 +144,7 @@ public class MavenFacadeManager { ContainerUtil.addIfNotNull(PathUtil.getJarPathForClass(Element.class), classPath); ContainerUtil.addIfNotNull(PathUtil.getJarPathForClass(Query.class), classPath); params.getClassPath().addAll(classPath); - addPluginLibraries(params.getClassPath()); + params.getClassPath().addAllFiles(collectClassPathAndLIbsFolder().first); params.setMainClass(MAIN_CLASS); // todo pass sensible parameters, MAVEN_OPTS? @@ -176,14 +178,15 @@ public class MavenFacadeManager { }; } - private void addPluginLibraries(PathsList classPath) { - File pluginFileOrDir = new File(PathUtil.getJarPathForClass(this.getClass())); + public static Pair, File> collectClassPathAndLIbsFolder() { + File pluginFileOrDir = new File(PathUtil.getJarPathForClass(MavenFacadeManager.class)); File libDir; + List classpath = new SmartList(); if (pluginFileOrDir.isDirectory()) { - classPath.add(new File(pluginFileOrDir.getParent(), "maven-facade-api")); - classPath.add(new File(pluginFileOrDir.getParent(), "maven-facade-impl")); + classpath.add(new File(pluginFileOrDir.getParent(), "maven-facade-api")); + classpath.add(new File(pluginFileOrDir.getParent(), "maven-facade-impl")); File luceneLib = new File(PathUtil.getJarPathForClass(Query.class)); libDir = new File(luceneLib.getParentFile().getParentFile().getParentFile(), "facade-impl/lib"); } @@ -195,9 +198,10 @@ public class MavenFacadeManager { File[] files = libDir.listFiles(); for (File jar : files) { if (jar.isFile() && jar.getName().endsWith(".jar") && !jar.equals(pluginFileOrDir)) { - classPath.add(jar.getPath()); + classpath.add(jar); } } + return Pair.create(classpath, libDir); } public MavenEmbedderWrapper createEmbedder(Project project) { diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenEnvironmentForm.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenEnvironmentForm.java index 7faa4c0da883..187501715362 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenEnvironmentForm.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenEnvironmentForm.java @@ -32,7 +32,6 @@ import java.io.File; public class MavenEnvironmentForm { private JPanel panel; private LabeledComponent mavenHomeComponent; - private LabeledComponent localRepositoryComponent; private LabeledComponent mavenSettingsFileComponent; private JCheckBox mavenHomeOverrideCheckBox; private JCheckBox mavenSettingsFileOverrideCheckBox; @@ -79,9 +78,6 @@ public class MavenEnvironmentForm { new FileChooserDescriptor(false, true, false, false, false, false)); mavenSettingsFileComponent.getComponent().addBrowseFolderListener(ProjectBundle.message("maven.select.maven.settings.file"), "", null, new FileChooserDescriptor(true, false, false, false, false, false)); - localRepositoryComponent.getComponent().addBrowseFolderListener(ProjectBundle.message("maven.select.local.repository"), "", null, - new FileChooserDescriptor(false, true, false, false, false, false)); - return panel; } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenUtil.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenUtil.java index 4a09a8aaa039..3884988fa2e1 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenUtil.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenUtil.java @@ -49,6 +49,7 @@ import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.maven.facade.MavenFacadeManager; import org.jetbrains.idea.maven.facade.MavenFacadeUtil; import org.jetbrains.idea.maven.model.MavenConstants; import org.jetbrains.idea.maven.model.MavenId; @@ -546,8 +547,7 @@ public class MavenUtil { public static VirtualFile resolveSuperPomFile(@Nullable File mavenHome) { VirtualFile result = doResolveSuperPomFile(mavenHome); if (result == null) { - URL resource = MavenFacadeUtil.class.getResource("/" + SUPER_POM_PATH); - return VfsUtil.findFileByURL(resource); + doResolveSuperPomFile(MavenFacadeManager.collectClassPathAndLIbsFolder().second); } return result; } From 7c7a65897fa806b7938f7e4bdb66589146486133 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Tue, 1 Jun 2010 16:29:29 +0400 Subject: [PATCH 080/212] Maven: deadlock fix --- .../intellij/execution/rmi/RemoteProcessSupport.java | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/rmi/RemoteProcessSupport.java b/platform/lang-impl/src/com/intellij/execution/rmi/RemoteProcessSupport.java index 3583d5e1a7c5..bd514d0da822 100644 --- a/platform/lang-impl/src/com/intellij/execution/rmi/RemoteProcessSupport.java +++ b/platform/lang-impl/src/com/intellij/execution/rmi/RemoteProcessSupport.java @@ -81,17 +81,7 @@ public abstract class RemoteProcessSupport { final Ref ref = Ref.create(null); final Pair key = Pair.create(target, configuration); if (!getExistingInfo(ref, key)) { - final Runnable runnable = new Runnable() { - public void run() { - startProcess(target, configuration, key); - } - }; - if (ApplicationManager.getApplication().isWriteAccessAllowed()) { - runnable.run(); - } - else { - ApplicationManager.getApplication().executeOnPooledThread(runnable); - } + startProcess(target, configuration, key); if (ref.isNull()) { try { synchronized (ref) { From d8fe1ee442a30aa056abf91a0ae8bb667a5e4fbe Mon Sep 17 00:00:00 2001 From: Gregory Shrago Date: Tue, 1 Jun 2010 17:31:29 +0400 Subject: [PATCH 081/212] better declaration processing --- .../PatternEditorContextMembersProvider.java | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/plugins/groovy/src/org/intellij/plugins/intelliLang/inject/groovy/PatternEditorContextMembersProvider.java b/plugins/groovy/src/org/intellij/plugins/intelliLang/inject/groovy/PatternEditorContextMembersProvider.java index b78c9061bd0e..02faaed56cb8 100644 --- a/plugins/groovy/src/org/intellij/plugins/intelliLang/inject/groovy/PatternEditorContextMembersProvider.java +++ b/plugins/groovy/src/org/intellij/plugins/intelliLang/inject/groovy/PatternEditorContextMembersProvider.java @@ -26,6 +26,8 @@ import org.intellij.plugins.intelliLang.inject.config.BaseInjection; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.GroovyFileType; import org.jetbrains.plugins.groovy.lang.resolve.NonCodeMembersProcessor; +import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil; +import org.jetbrains.plugins.groovy.lang.resolve.processors.ClassHint; /** * @author Gregory.Shrago @@ -38,13 +40,18 @@ public class PatternEditorContextMembersProvider implements NonCodeMembersProces final PsiFile file = place.getContainingFile().getOriginalFile(); final BaseInjection injection = file.getUserData(BaseInjection.INJECTION_KEY); if (injection == null) return true; - return ((UserDataHolderEx)file).putUserDataIfAbsent(INJECTION_PARSED_CONTEXT, new AtomicNotNullLazyValue() { - @NotNull - @Override - protected PsiFile compute() { - return parseInjectionContext(injection, file.getProject()); - } - }).getValue().processDeclarations(processor, ResolveState.initial(), null, place); + final PsiFile contextFile = + ((UserDataHolderEx)file).putUserDataIfAbsent(INJECTION_PARSED_CONTEXT, new AtomicNotNullLazyValue() { + @NotNull + @Override + protected PsiFile compute() { + return parseInjectionContext(injection, file.getProject()); + } + }).getValue(); + for (PsiElement cur = contextFile.getFirstChild(); cur != null; cur = cur.getNextSibling()) { + if (cur instanceof PsiNamedElement && !ResolveUtil.processElement(processor, (PsiNamedElement)cur)) return false; + } + return true; } private static PsiFile parseInjectionContext(@NotNull BaseInjection injection, Project project) { From 16b3cc93bc93b112b09b7b552141e814ab3195d2 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Tue, 1 Jun 2010 18:04:01 +0400 Subject: [PATCH 082/212] Maven: npe fix --- .../src/main/java/org/jetbrains/idea/maven/utils/MavenUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenUtil.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenUtil.java index 3884988fa2e1..72e899b77e9a 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenUtil.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenUtil.java @@ -547,7 +547,7 @@ public class MavenUtil { public static VirtualFile resolveSuperPomFile(@Nullable File mavenHome) { VirtualFile result = doResolveSuperPomFile(mavenHome); if (result == null) { - doResolveSuperPomFile(MavenFacadeManager.collectClassPathAndLIbsFolder().second); + result = doResolveSuperPomFile(MavenFacadeManager.collectClassPathAndLIbsFolder().second); } return result; } From 7fcd710b850d0773b3eb595250a2cefc942d2998 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Tue, 1 Jun 2010 18:07:41 +0400 Subject: [PATCH 083/212] [Mercurial] lazy initialization of the PROMPT_HOOKS_PLUGIN constant. --- plugins/hg4idea/src/org/zmlx/hg4idea/HgUtil.java | 2 ++ .../src/org/zmlx/hg4idea/command/HgCommandService.java | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgUtil.java index 994c8b2c9e1a..97f4a89627e8 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgUtil.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgUtil.java @@ -18,6 +18,7 @@ import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.changes.*; import com.intellij.openapi.vfs.*; import com.intellij.vcsUtil.*; +import org.jetbrains.annotations.Nullable; import java.io.*; @@ -127,6 +128,7 @@ public abstract class HgUtil { * @return The temporary copy the specified python file, with all the necessary hooks installed * to make sure it is completely removed at shutdown */ + @Nullable public static File getTemporaryPythonFile(String base) { try { final File file = copyResourceToTempFile(base, ".py"); diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCommandService.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCommandService.java index e4531f67fda7..f12e83b55470 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCommandService.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCommandService.java @@ -29,7 +29,7 @@ import java.util.List; public final class HgCommandService { - private static final File PROMPT_HOOKS_PLUGIN = HgUtil.getTemporaryPythonFile("prompthooks"); + private static File PROMPT_HOOKS_PLUGIN; static final Logger LOG = Logger.getInstance(HgCommandService.class.getName()); @@ -43,6 +43,9 @@ public final class HgCommandService { public HgCommandService(Project project, HgGlobalSettings settings) { this.project = project; this.settings = settings; + if (PROMPT_HOOKS_PLUGIN == null) { + PROMPT_HOOKS_PLUGIN = HgUtil.getTemporaryPythonFile("prompthooks"); + } } public static HgCommandService getInstance(Project project) { From 3119aa8cdab1a3f780a63c02e0a66a2e56e4fc5a Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Tue, 1 Jun 2010 18:50:34 +0400 Subject: [PATCH 084/212] fix assertion (EA-20597) --- .../zencoding/XmlZenCodingInterpreter.java | 27 ++++++++++++------- .../zencoding/XmlZenCodingTemplate.java | 11 +++++--- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/xml/impl/src/com/intellij/codeInsight/template/zencoding/XmlZenCodingInterpreter.java b/xml/impl/src/com/intellij/codeInsight/template/zencoding/XmlZenCodingInterpreter.java index 21274dd639f9..5ad53eec3a94 100644 --- a/xml/impl/src/com/intellij/codeInsight/template/zencoding/XmlZenCodingInterpreter.java +++ b/xml/impl/src/com/intellij/codeInsight/template/zencoding/XmlZenCodingInterpreter.java @@ -17,6 +17,7 @@ package com.intellij.codeInsight.template.zencoding; import com.intellij.codeInsight.template.CustomTemplateCallback; import com.intellij.codeInsight.template.impl.TemplateImpl; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.util.Pair; @@ -306,21 +307,19 @@ class XmlZenCodingInterpreter { private static void invokeTemplate(TemplateToken token, final CustomTemplateCallback callback, - int numberInIteration, + final int numberInIteration, String filter) { if (token instanceof XmlTemplateToken && token.getTemplate() != null) { XmlTemplateToken xmlTemplateToken = (XmlTemplateToken)token; - List> attr2value = new ArrayList>(xmlTemplateToken.getAttribute2Value()); + final List> attr2value = new ArrayList>(xmlTemplateToken.getAttribute2Value()); TemplateImpl modifiedTemplate = token.getTemplate().copy(); - XmlTag tag = xmlTemplateToken.getTag(); + final XmlTag tag = xmlTemplateToken.getTag(); if (tag != null) { - for (Iterator> iterator = attr2value.iterator(); iterator.hasNext();) { - Pair pair = iterator.next(); - if (tag.getAttribute(pair.first) != null) { - tag.setAttribute(pair.first, ZenCodingUtil.getValue(pair, numberInIteration)); - iterator.remove(); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + setAttributeValues(tag, attr2value, numberInIteration); } - } + }); String s = filterXml(tag, callback, filter); assert s != null; if (HtmlUtil.isHtmlBlockTagL(tag.getName())) { @@ -350,6 +349,16 @@ class XmlZenCodingInterpreter { } } + private static void setAttributeValues(XmlTag tag, List> attr2value, int numberInIteration) { + for (Iterator> iterator = attr2value.iterator(); iterator.hasNext();) { + Pair pair = iterator.next(); + if (tag.getAttribute(pair.first) != null) { + tag.setAttribute(pair.first, ZenCodingUtil.getValue(pair, numberInIteration)); + iterator.remove(); + } + } + } + @Nullable private static String filterXml(XmlTag tag, CustomTemplateCallback callback, String filterSuffix) { PsiElement context = callback.getContext(); diff --git a/xml/impl/src/com/intellij/codeInsight/template/zencoding/XmlZenCodingTemplate.java b/xml/impl/src/com/intellij/codeInsight/template/zencoding/XmlZenCodingTemplate.java index 080397ba94f5..27bff77fc33b 100644 --- a/xml/impl/src/com/intellij/codeInsight/template/zencoding/XmlZenCodingTemplate.java +++ b/xml/impl/src/com/intellij/codeInsight/template/zencoding/XmlZenCodingTemplate.java @@ -20,6 +20,7 @@ import com.intellij.codeInsight.template.CustomTemplateCallback; import com.intellij.codeInsight.template.TemplateInvokationListener; import com.intellij.codeInsight.template.impl.TemplateImpl; import com.intellij.lang.xml.XMLLanguage; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.StdFileTypes; @@ -191,7 +192,7 @@ public class XmlZenCodingTemplate extends ZenCodingTemplate { if (template == null && !isXML11ValidQName(prefix)) { return null; } - XmlTemplateToken token = parseSelectors(key); + final XmlTemplateToken token = parseSelectors(key); if (token == null) { return null; } @@ -203,13 +204,17 @@ public class XmlZenCodingTemplate extends ZenCodingTemplate { } assert prefix.equals(token.getKey()); token.setTemplate(template); - XmlTag tag = parseXmlTagInTemplate(template.getString(), callback, true); + final XmlTag tag = parseXmlTagInTemplate(template.getString(), callback, true); if (token.getAttribute2Value().size() > 0 && tag == null) { return null; } if (tag != null) { if (!XmlZenCodingInterpreter.containsAttrsVar(template) && token.getAttribute2Value().size() > 0) { - addMissingAttributes(tag, token.getAttribute2Value()); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + addMissingAttributes(tag, token.getAttribute2Value()); + } + }); } token.setTag(tag); } From 72522ed6cd3ee90e601e2913fadcfd91333ebadb Mon Sep 17 00:00:00 2001 From: Alexey Pegov Date: Tue, 1 Jun 2010 19:12:32 +0400 Subject: [PATCH 085/212] WI-1470 autocomplete error in css --- .../psi/filters/FilterPositionUtil.java | 11 ++++- .../psi/filters/position/AfterElement.java | 44 +++++++++++++++++++ 2 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/psi/filters/position/AfterElement.java diff --git a/platform/lang-impl/src/com/intellij/psi/filters/FilterPositionUtil.java b/platform/lang-impl/src/com/intellij/psi/filters/FilterPositionUtil.java index 5799c9f946b5..459ec283eb59 100644 --- a/platform/lang-impl/src/com/intellij/psi/filters/FilterPositionUtil.java +++ b/platform/lang-impl/src/com/intellij/psi/filters/FilterPositionUtil.java @@ -30,10 +30,17 @@ public class FilterPositionUtil { @Nullable public static PsiElement searchNonSpaceNonCommentBack(PsiElement element) { + return searchNonSpaceNonCommentBack(element, false); + } + + @Nullable + public static PsiElement searchNonSpaceNonCommentBack(PsiElement element, final boolean strict) { if(element == null || element.getNode() == null) return null; ASTNode leftNeibour = TreeUtil.prevLeaf(element.getNode()); - while (leftNeibour != null && (leftNeibour.getElementType() == TokenType.WHITE_SPACE || leftNeibour.getPsi() instanceof PsiComment)){ - leftNeibour = TreeUtil.prevLeaf(leftNeibour); + if (!strict) { + while (leftNeibour != null && (leftNeibour.getElementType() == TokenType.WHITE_SPACE || leftNeibour.getPsi() instanceof PsiComment)){ + leftNeibour = TreeUtil.prevLeaf(leftNeibour); + } } return leftNeibour != null ? leftNeibour.getPsi() : null; diff --git a/platform/lang-impl/src/com/intellij/psi/filters/position/AfterElement.java b/platform/lang-impl/src/com/intellij/psi/filters/position/AfterElement.java new file mode 100644 index 000000000000..233bb683fb79 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/psi/filters/position/AfterElement.java @@ -0,0 +1,44 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.psi.filters.position; + +import com.intellij.psi.PsiElement; +import com.intellij.psi.filters.ElementFilter; +import com.intellij.psi.filters.FilterPositionUtil; + +/** + * User: spLeaner + */ +public class AfterElement extends PositionElementFilter { + public AfterElement(){} + + public AfterElement(ElementFilter filter){ + setFilter(filter); + } + + public boolean isAcceptable(Object element, PsiElement context){ + if (!(element instanceof PsiElement)) return false; + final PsiElement previous = FilterPositionUtil.searchNonSpaceNonCommentBack((PsiElement) element, true); + if(previous != null){ + return getFilter().isAcceptable(previous, context); + } + return false; + } + + public String toString(){ + return "after(" +getFilter()+")"; + } +} From da8c752870483a6a3f5cfd62a290659602e44d0a Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 1 Jun 2010 19:39:13 +0400 Subject: [PATCH 086/212] Normalize symlinks in fsnotifier --- native/fsNotifier/linux/fsnotifier | Bin 23638 -> 22529 bytes native/fsNotifier/linux/fsnotifier64 | Bin 26146 -> 28917 bytes native/fsNotifier/linux/inotify.c | 4 +++- native/fsNotifier/linux/make.sh | 3 +++ 4 files changed, 6 insertions(+), 1 deletion(-) diff --git a/native/fsNotifier/linux/fsnotifier b/native/fsNotifier/linux/fsnotifier index 3d84ba68c1c23eb8f61adcb4d846f1f2d9f1d699..9290ab239af577c4d72f723b0bf171205b55ecf0 100755 GIT binary patch delta 7822 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 o+!}24|7TjcXvrgmh0{v!Dw?EnA( delta 8737 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 diff --git a/native/fsNotifier/linux/fsnotifier64 b/native/fsNotifier/linux/fsnotifier64 index 1c959e2ddfb8b2fa26bc195709dfd10f947b0216..3a573dd7a1830018ce482924f11e4d681962e654 100755 GIT binary patch literal 28917 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 literal 26146 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 diff --git a/native/fsNotifier/linux/inotify.c b/native/fsNotifier/linux/inotify.c index b3306e5c64ed..411a6def1733 100644 --- a/native/fsNotifier/linux/inotify.c +++ b/native/fsNotifier/linux/inotify.c @@ -284,7 +284,9 @@ static int walk_tree(const char* path, watch_node* parent, array* ignores) { int watch(const char* root, array* ignores) { - return walk_tree(root, NULL, ignores); + char buf[PATH_MAX]; + const char* normalized = realpath(root, buf); + return walk_tree((normalized != NULL ? normalized : root), NULL, ignores); } diff --git a/native/fsNotifier/linux/make.sh b/native/fsNotifier/linux/make.sh index e2741da2778d..f2ec112fc406 100755 --- a/native/fsNotifier/linux/make.sh +++ b/native/fsNotifier/linux/make.sh @@ -1,2 +1,5 @@ +#!/bin/sh +echo "compiling 32-bit version" gcc -O2 -m32 -Wall -std=c99 -D_BSD_SOURCE -D_XOPEN_SOURCE=500 -o fsnotifier main.c inotify.c util.c +echo "compiling 64-bit version" gcc -O2 -m64 -Wall -std=c99 -D_BSD_SOURCE -D_XOPEN_SOURCE=500 -o fsnotifier64 main.c inotify.c util.c From c12cbe3f5438dd623ddf0e41a753292323d0d694 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 1 Jun 2010 19:40:50 +0400 Subject: [PATCH 087/212] C/C++ syntax highlighting: true and false in same group --- platform/platform-resources/src/FileTypeManager.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-resources/src/FileTypeManager.xml b/platform/platform-resources/src/FileTypeManager.xml index 5911348c1044..007518cdb91f 100644 --- a/platform/platform-resources/src/FileTypeManager.xml +++ b/platform/platform-resources/src/FileTypeManager.xml @@ -231,6 +231,7 @@ + @@ -258,7 +259,6 @@ - From 0ee831bb631c17d99a645b66b37c1d4507a2a049 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 1 Jun 2010 23:03:07 +0400 Subject: [PATCH 088/212] Test SVN binary updated --- plugins/svn4idea/testData/svn/bin/svn | Bin 3931756 -> 5589665 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/plugins/svn4idea/testData/svn/bin/svn b/plugins/svn4idea/testData/svn/bin/svn index cb405a4a7326ff080170eeb5c46b63dbad67f829..1c3cce2d7080a456fb035aa60bb56f08b0c27247 100755 GIT binary patch literal 5589665 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 z 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