diff --git a/.idea/libraries/Netty.xml b/.idea/libraries/Netty.xml index 7fd31a45d2a5..5233598e8385 100644 --- a/.idea/libraries/Netty.xml +++ b/.idea/libraries/Netty.xml @@ -1,11 +1,11 @@ - + - + \ No newline at end of file diff --git a/build/scripts/libLicenses.gant b/build/scripts/libLicenses.gant index fe9441b2d4ee..ff02012c094d 100644 --- a/build/scripts/libLicenses.gant +++ b/build/scripts/libLicenses.gant @@ -233,7 +233,7 @@ libraryLicense(name: "XML-RPC", libraryName: "XmlRPC", version: "2.0", license: libraryLicense(name: "XStream", version: "1.2.1", license: "BSD", url: "http://xstream.codehaus.org/", licenseUrl: "http://xstream.codehaus.org/license.html") libraryLicense(name: "YourKit Java Profiler", libraryName: "yjp-controller-api-redist.jar", version: "8.0.x", license: "link (commercial license)", url: "http://yourkit.com/", licenseUrl: "http://www.yourkit.com/purchase/license.html") libraryLicense(name: "protobuf", version: "2.3.0", license: "New BSD", url: "http://code.google.com/p/protobuf/", licenseUrl: "http://code.google.com/p/protobuf/source/browse/trunk/COPYING.txt?r=367") -libraryLicense(name: "Netty", libraryName: "Netty", version: "3.5.7", license: "Apache 2.0", url: "http://netty.io", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0") +libraryLicense(name: "Netty", libraryName: "Netty", version: "3.5.8", license: "Apache 2.0", url: "http://netty.io", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0") libraryLicense(name: "Kryo", libraryName: "Kryo", version: "1.04", license: "New BSD License", url: "http://code.google.com/p/kryo/", licenseUrl: "http://www.opensource.org/licenses/bsd-license.php") libraryLicense(name: "Snappy-Java", libraryName: "Snappy-Java", version: "1.0.4.1", license: "Apache 2.0", url: "http://code.google.com/p/snappy-java/", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0") libraryLicense(name: "Cucumber-JVM", libraryName: "cucumber-jvm", version: "1.0.11", license: "MIT License", url: "https://github.com/cucumber/cucumber-jvm/", licenseUrl: "http://www.opensource.org/licenses/mit-license.html") diff --git a/java/idea-ui/src/com/intellij/ide/impl/NewProjectUtil.java b/java/idea-ui/src/com/intellij/ide/impl/NewProjectUtil.java index d4f8324e454b..f2e2ba5be0a0 100644 --- a/java/idea-ui/src/com/intellij/ide/impl/NewProjectUtil.java +++ b/java/idea-ui/src/com/intellij/ide/impl/NewProjectUtil.java @@ -42,6 +42,7 @@ import com.intellij.openapi.roots.ui.configuration.ModulesProvider; import com.intellij.openapi.startup.StartupManager; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.ThrowableComputable; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.wm.*; @@ -67,7 +68,7 @@ public class NewProjectUtil { } }, ProjectBundle.message("project.new.wizard.progress.title"), true, null); if (!proceed) return; - AddModuleWizard dialog = new AddModuleWizard(null, ModulesProvider.EMPTY_MODULES_PROVIDER, defaultPath); + final AddModuleWizard dialog = new AddModuleWizard(null, ModulesProvider.EMPTY_MODULES_PROVIDER, defaultPath); dialog.show(); if (!dialog.isOK()) { return; @@ -92,8 +93,18 @@ public class NewProjectUtil { } } - final Project newProject = - projectBuilder == null || !projectBuilder.isUpdate() ? projectManager.newProject(dialog.getProjectName(), projectFilePath, true, false) : projectToClose; + final Project newProject; + if (projectBuilder == null || !projectBuilder.isUpdate()) { + newProject = ProgressManager.getInstance().runProcessWithProgressSynchronously(new ThrowableComputable() { + @Override + public Project compute() throws RuntimeException { + return projectManager.newProject(dialog.getProjectName(), projectFilePath, true, false); + } + }, "Creating Project", true, null); + } + else { + newProject = projectToClose; + } if (newProject == null) return; diff --git a/java/idea-ui/src/com/intellij/platform/templates/ArchivedProjectTemplate.java b/java/idea-ui/src/com/intellij/platform/templates/ArchivedProjectTemplate.java index 2fa05510dcf4..e3916a29e894 100644 --- a/java/idea-ui/src/com/intellij/platform/templates/ArchivedProjectTemplate.java +++ b/java/idea-ui/src/com/intellij/platform/templates/ArchivedProjectTemplate.java @@ -20,6 +20,7 @@ import com.intellij.ide.util.projectWizard.ProjectBuilder; import com.intellij.ide.util.projectWizard.WizardContext; import com.intellij.openapi.module.ModifiableModuleModel; import com.intellij.openapi.module.Module; +import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ui.configuration.ModulesProvider; import com.intellij.openapi.util.Condition; @@ -95,7 +96,7 @@ public class ArchivedProjectTemplate implements ProjectTemplate { try { File dir = new File(path); ZipInputStream zipInputStream = getStream(); - ZipUtil.unzip(null, dir, zipInputStream); + ZipUtil.unzip(ProgressManager.getInstance().getProgressIndicator(), dir, zipInputStream); VirtualFile virtualFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(dir); RefreshQueue.getInstance().refresh(false, true, null, virtualFile); iml = ContainerUtil.find(dir.list(), new Condition() { diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/CreateClassDialog.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/CreateClassDialog.java index 5cb86ad43c17..2aa865d316c6 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/CreateClassDialog.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/CreateClassDialog.java @@ -86,18 +86,17 @@ public class CreateClassDialog extends DialogWrapper { public CreateClassDialog(@NotNull Project project, @NotNull String title, - String targetClassName, - String targetPackageName, + @NotNull String targetClassName, + @NotNull String targetPackageName, @NotNull CreateClassKind kind, boolean classNameEditable, - Module defaultModule) { + @Nullable Module defaultModule) { super(project, true); myClassNameEditable = classNameEditable; myModule = defaultModule; myClassName = targetClassName; myProject = project; - final String normalizedPackageName = targetPackageName != null ? targetPackageName : ""; - myPackageComponent = new PackageNameReferenceEditorCombo(normalizedPackageName, myProject, RECENTS_KEY, CodeInsightBundle.message("dialog.create.class.package.chooser.title")); + myPackageComponent = new PackageNameReferenceEditorCombo(targetPackageName, myProject, RECENTS_KEY, CodeInsightBundle.message("dialog.create.class.package.chooser.title")); myPackageComponent.setTextFieldPreferredWidth(40); init(); @@ -111,7 +110,7 @@ public class CreateClassDialog extends DialogWrapper { } myTfClassName.setText(myClassName); - myDestinationCB.setData(myProject, getBaseDir(normalizedPackageName), new Pass() { + myDestinationCB.setData(myProject, getBaseDir(targetPackageName), new Pass() { @Override public void pass(String s) { setErrorText(s); @@ -278,6 +277,7 @@ public class CreateClassDialog extends DialogWrapper { return myModule == null? null : PackageUtil.findPossiblePackageDirectoryInModule(myModule, packageName); } + @NotNull public String getClassName() { if (myClassNameEditable) { return myTfClassName.getText(); diff --git a/java/java-impl/src/com/intellij/ide/structureView/impl/java/PsiMethodTreeElement.java b/java/java-impl/src/com/intellij/ide/structureView/impl/java/PsiMethodTreeElement.java index 0896cadf4bef..f290c69f48f2 100644 --- a/java/java-impl/src/com/intellij/ide/structureView/impl/java/PsiMethodTreeElement.java +++ b/java/java-impl/src/com/intellij/ide/structureView/impl/java/PsiMethodTreeElement.java @@ -31,6 +31,7 @@ import com.intellij.psi.util.MethodSignatureBackedByPsiMethod; import com.intellij.psi.util.PsiFormatUtil; import com.intellij.psi.util.PsiFormatUtilBase; import com.intellij.util.Function; +import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; @@ -38,6 +39,8 @@ import java.util.Arrays; import java.util.Collection; import java.util.HashSet; +import static com.intellij.psi.util.PsiFormatUtilBase.*; + public class PsiMethodTreeElement extends JavaClassTreeElementBase implements SortableTreeElement, LocationPresentation { private String myLocation; @@ -67,19 +70,17 @@ public class PsiMethodTreeElement extends JavaClassTreeElementBase im if (!(aClass instanceof PsiAnonymousClass) && !(aClass instanceof PsiTypeParameter)) { result.add(new JavaClassTreeElement(aClass, isInherited(), new HashSet(Arrays.asList(aClass.getSupers())))); } - } }); return result; } public String getPresentableText() { - return StringUtil.replace(PsiFormatUtil.formatMethod( - getElement(), - PsiSubstitutor.EMPTY, PsiFormatUtilBase.SHOW_NAME | - PsiFormatUtilBase.SHOW_TYPE | PsiFormatUtilBase.TYPE_AFTER | PsiFormatUtilBase.SHOW_PARAMETERS, - PsiFormatUtilBase.SHOW_TYPE - ), ":", ": "); + String method = PsiFormatUtil.formatMethod(getElement(), + PsiSubstitutor.EMPTY, + SHOW_NAME | SHOW_TYPE | TYPE_AFTER | SHOW_PARAMETERS, + SHOW_TYPE); + return StringUtil.replace(method, ":", ": "); } @@ -104,15 +105,16 @@ public class PsiMethodTreeElement extends JavaClassTreeElementBase im //some searchers (EJB) require indices. What shall we do? } - if (myLocation == null) { + if (StringUtil.isEmpty(myLocation)) { myLocation = ""; + } else { + char upArrow = '\u2191'; + myLocation = UIUtil.getLabelFont().canDisplay(upArrow) ? upArrow + myLocation : myLocation; } } return StringUtil.isEmpty(myLocation) ? null : myLocation; } - - @Override public TextAttributesKey getTextAttributesKey() { if (isInherited()) return CodeInsightColors.NOT_USED_ELEMENT_ATTRIBUTES; @@ -139,7 +141,7 @@ public class PsiMethodTreeElement extends JavaClassTreeElementBase im @Override public String getLocationPrefix() { - return " \u2191"; + return " "; } @Override diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java b/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java index 5871b73aeb8e..868b98106996 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java @@ -1186,7 +1186,7 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor { @Override public void visitMethodReferenceExpression(PsiMethodReferenceExpression expression) { - if ((myRole1 == ChildRole.DOUBLE_COLON && myRole2 == ChildRole.EXPRESSION) || + if ((myRole1 == ChildRole.DOUBLE_COLON && myRole2 == ChildRole.REFERENCE_NAME) || (myRole1 == ChildRole.EXPRESSION && myRole2 == ChildRole.DOUBLE_COLON)) { createSpaceInCode(mySettings.SPACE_AROUND_METHOD_REF_DBL_COLON); } diff --git a/java/java-impl/src/com/intellij/psi/impl/JavaCodeFragmentFactoryImpl.java b/java/java-impl/src/com/intellij/psi/impl/JavaCodeFragmentFactoryImpl.java index 315dc3133db1..f0623c07049f 100644 --- a/java/java-impl/src/com/intellij/psi/impl/JavaCodeFragmentFactoryImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/JavaCodeFragmentFactoryImpl.java @@ -35,8 +35,8 @@ public class JavaCodeFragmentFactoryImpl extends JavaCodeFragmentFactory { @NotNull @Override public PsiExpressionCodeFragment createExpressionCodeFragment(@NotNull final String text, - final PsiElement context, - final PsiType expectedType, + @Nullable final PsiElement context, + @Nullable final PsiType expectedType, final boolean isPhysical) { return new PsiExpressionCodeFragmentImpl(myProject, isPhysical, "fragment.java", text, expectedType, context); } @@ -62,7 +62,7 @@ public class JavaCodeFragmentFactoryImpl extends JavaCodeFragmentFactory { @NotNull @Override public PsiJavaCodeReferenceCodeFragment createReferenceCodeFragment(@NotNull final String text, - final PsiElement context, + @Nullable final PsiElement context, final boolean isPhysical, final boolean isClassesAccepted) { return new PsiJavaCodeReferenceCodeFragmentImpl(myProject, isPhysical, "fragment.java", text, isClassesAccepted, context); diff --git a/java/java-impl/src/com/intellij/psi/impl/source/PsiCodeFragmentImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/PsiCodeFragmentImpl.java index 62cac663ef17..a281f2725bab 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/PsiCodeFragmentImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/PsiCodeFragmentImpl.java @@ -39,6 +39,7 @@ import com.intellij.psi.tree.IElementType; import com.intellij.testFramework.LightVirtualFile; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.LinkedHashMap; import java.util.StringTokenizer; @@ -59,7 +60,7 @@ public class PsiCodeFragmentImpl extends PsiFileImpl implements JavaCodeFragment boolean isPhysical, @NonNls String name, CharSequence text, - PsiElement context) { + @Nullable PsiElement context) { super(TokenType.CODE_FRAGMENT, contentElementType, ((PsiManagerEx)PsiManager.getInstance(project)).getFileManager().createFileViewProvider( diff --git a/java/java-impl/src/com/intellij/psi/impl/source/PsiExpressionCodeFragmentImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/PsiExpressionCodeFragmentImpl.java index c314f49efe55..299abf842186 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/PsiExpressionCodeFragmentImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/PsiExpressionCodeFragmentImpl.java @@ -25,6 +25,7 @@ import com.intellij.psi.PsiType; import com.intellij.psi.impl.source.tree.ElementType; import com.intellij.psi.impl.source.tree.JavaElementType; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.Nullable; public class PsiExpressionCodeFragmentImpl extends PsiCodeFragmentImpl implements PsiExpressionCodeFragment { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.PsiExpressionCodeFragmentImpl"); @@ -34,12 +35,13 @@ public class PsiExpressionCodeFragmentImpl extends PsiCodeFragmentImpl implement boolean isPhysical, @NonNls String name, CharSequence text, - final PsiType expectedType, - PsiElement context) { + @Nullable final PsiType expectedType, + @Nullable PsiElement context) { super(project, JavaElementType.EXPRESSION_TEXT, isPhysical, name, text, context); setExpectedType(expectedType); } + @Nullable @Override public PsiExpression getExpression() { ASTNode exprChild = calcTreeElement().findChildByType(ElementType.EXPRESSION_BIT_SET); @@ -57,7 +59,7 @@ public class PsiExpressionCodeFragmentImpl extends PsiCodeFragmentImpl implement } @Override - public void setExpectedType(PsiType type) { + public void setExpectedType(@Nullable PsiType type) { myExpectedType = type; if (type != null) { LOG.assertTrue(type.isValid()); diff --git a/java/java-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceCodeFragmentImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceCodeFragmentImpl.java index 5d604ad067c0..333894257d04 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceCodeFragmentImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceCodeFragmentImpl.java @@ -23,6 +23,7 @@ import com.intellij.psi.PsiJavaCodeReferenceElement; import com.intellij.psi.impl.source.tree.CompositeElement; import com.intellij.psi.impl.source.tree.JavaElementType; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.Nullable; /** * @author ven @@ -36,7 +37,7 @@ public class PsiJavaCodeReferenceCodeFragmentImpl extends PsiCodeFragmentImpl im @NonNls final String name, final CharSequence text, boolean isClassesAccepted, - PsiElement context) { + @Nullable PsiElement context) { super(project, JavaElementType.REFERENCE_TEXT, isPhysical, name, text, context); myIsClassesAccepted = isClassesAccepted; } diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDialog.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDialog.java index 187887259826..ec6b50cb5665 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDialog.java @@ -80,7 +80,7 @@ import static com.intellij.refactoring.changeSignature.ChangeSignatureHandler.RE /** * @author Konstantin Bulenkov */ -public class JavaChangeSignatureDialog extends ChangeSignatureDialogBase { +public class JavaChangeSignatureDialog extends ChangeSignatureDialogBase, JavaParameterTableModel> { private ExceptionsTableModel myExceptionsModel; protected Set myMethodsToPropagateExceptions; private AnActionButton myPropExceptionsButton; @@ -192,8 +192,8 @@ public class JavaChangeSignatureDialog extends ChangeSignatureDialogBase createParametersInfoModel(MethodDescriptor descriptor) { - final PsiParameterList parameterList = ((JavaMethodDescriptor)descriptor).getMethod().getParameterList(); + protected JavaParameterTableModel createParametersInfoModel(JavaMethodDescriptor descriptor) { + final PsiParameterList parameterList = descriptor.getMethod().getParameterList(); return new JavaParameterTableModel(parameterList, myDefaultValueContext, this); } diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaParameterTableModel.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaParameterTableModel.java index 30c96ca5d0e2..6d075daac616 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaParameterTableModel.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaParameterTableModel.java @@ -45,7 +45,7 @@ import java.awt.event.KeyEvent; import java.util.LinkedHashSet; import java.util.Set; -public class JavaParameterTableModel extends ParameterTableModelBase { +public class JavaParameterTableModel extends ParameterTableModelBase> { private final Project myProject; public JavaParameterTableModel(final PsiElement typeContext, @@ -54,12 +54,13 @@ public class JavaParameterTableModel extends ParameterTableModelBase(typeContext.getProject(), StdFileTypes.JAVA) { + new DefaultValueColumn>(typeContext.getProject(), StdFileTypes.JAVA) { @Override public TableCellEditor doCreateEditor(ParameterTableModelItemBase item) { return new EditorWithExpectedType(typeContext); } - }, new AnyVarColumn() { + }, + new AnyVarColumn>() { @Override public boolean isCellEditable(ParameterTableModelItemBase item) { boolean isGenerateDelegate = ((ChangeSignatureDialogBase)dialog).isGenerateDelegate(); @@ -128,8 +129,7 @@ public class JavaParameterTableModel extends ParameterTableModelBase { - private final Project myProject; - + public static class JavaTypeColumn extends TypeColumn> { public JavaTypeColumn(Project project) { super(project, StdFileTypes.JAVA); - myProject = project; } @Override @@ -185,7 +182,7 @@ public class JavaParameterTableModel extends ParameterTableModelBase { + public static class JavaNameColumn extends NameColumn> { private final Project myProject; public JavaNameColumn(Project project) { diff --git a/java/java-impl/src/com/intellij/refactoring/util/CanonicalTypes.java b/java/java-impl/src/com/intellij/refactoring/util/CanonicalTypes.java index cef76e7779bb..f7fac6349135 100644 --- a/java/java-impl/src/com/intellij/refactoring/util/CanonicalTypes.java +++ b/java/java-impl/src/com/intellij/refactoring/util/CanonicalTypes.java @@ -323,7 +323,7 @@ public class CanonicalTypes { } } - public static Type createTypeWrapper(final PsiType type) { + public static Type createTypeWrapper(@NotNull final PsiType type) { return type.accept(Creator.INSTANCE); } } diff --git a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java index b88206e5a780..9c6e3bbaccec 100644 --- a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java @@ -59,7 +59,7 @@ public class LambdaUtil { } @Nullable - public static PsiMethod getFunctionalInterfaceMethod(PsiType functionalInterfaceType) { + public static PsiMethod getFunctionalInterfaceMethod(@Nullable PsiType functionalInterfaceType) { return getFunctionalInterfaceMethod(PsiUtil.resolveGenericsClassInType(functionalInterfaceType)); } @@ -224,8 +224,12 @@ public class LambdaUtil { if (checkReturnType) { final String uniqueVarName = JavaCodeStyleManager.getInstance(lambdaExpression.getProject()).suggestUniqueVariableName("l", lambdaExpression, true); + String canonicalText = leftType.getCanonicalText(); + if (leftType instanceof PsiEllipsisType) { + canonicalText = ((PsiEllipsisType)leftType).toArrayType().getCanonicalText(); + } final PsiStatement assignmentFromText = JavaPsiFacade.getElementFactory(lambdaExpression.getProject()) - .createStatementFromText(leftType.getCanonicalText() + " " + uniqueVarName + " = " + lambdaExpression.getText(), lambdaExpression); + .createStatementFromText(canonicalText + " " + uniqueVarName + " = " + lambdaExpression.getText(), lambdaExpression); final PsiLocalVariable localVariable = (PsiLocalVariable)((PsiDeclarationStatement)assignmentFromText).getDeclaredElements()[0]; LOG.assertTrue(psiClass != null); PsiType methodReturnType = getReturnType(psiClass, methodSignature); diff --git a/java/java-psi-api/src/com/intellij/psi/PsiAnnotation.java b/java/java-psi-api/src/com/intellij/psi/PsiAnnotation.java index f6ea47bb4878..367efb2a7043 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiAnnotation.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiAnnotation.java @@ -75,7 +75,7 @@ public interface PsiAnnotation extends PsiAnnotationMemberValue, PsiMetaOwner { * the element and the element has no default value. */ @Nullable - PsiAnnotationMemberValue findAttributeValue(@NonNls String attributeName); + PsiAnnotationMemberValue findAttributeValue(@Nullable @NonNls String attributeName); /** * Returns the value of the annotation element with the specified name. diff --git a/java/java-psi-api/src/com/intellij/psi/PsiExpressionCodeFragment.java b/java/java-psi-api/src/com/intellij/psi/PsiExpressionCodeFragment.java index a0a4e1d79d34..b385031dc866 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiExpressionCodeFragment.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiExpressionCodeFragment.java @@ -28,6 +28,7 @@ public interface PsiExpressionCodeFragment extends JavaCodeFragment { * * @return the expression contained in the fragment. */ + @Nullable PsiExpression getExpression(); /** diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java index 7fb45493a58f..07233da1f0fe 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java @@ -85,7 +85,7 @@ public class PsiImplUtil { } @Nullable - public static PsiAnnotationMemberValue findAttributeValue(@NotNull PsiAnnotation annotation, @NonNls String attributeName) { + public static PsiAnnotationMemberValue findAttributeValue(@NotNull PsiAnnotation annotation, @Nullable @NonNls String attributeName) { final PsiAnnotationMemberValue value = findDeclaredAttributeValue(annotation, attributeName); if (value != null) return value; diff --git a/java/openapi/src/com/intellij/psi/JavaCodeFragmentFactory.java b/java/openapi/src/com/intellij/psi/JavaCodeFragmentFactory.java index fc91555bb674..eefda4003d47 100644 --- a/java/openapi/src/com/intellij/psi/JavaCodeFragmentFactory.java +++ b/java/openapi/src/com/intellij/psi/JavaCodeFragmentFactory.java @@ -38,7 +38,10 @@ public abstract class JavaCodeFragmentFactory { * @return the created code fragment. */ @NotNull - public abstract PsiExpressionCodeFragment createExpressionCodeFragment(@NotNull String text, PsiElement context, final PsiType expectedType, boolean isPhysical); + public abstract PsiExpressionCodeFragment createExpressionCodeFragment(@NotNull String text, + @Nullable PsiElement context, + @Nullable final PsiType expectedType, + boolean isPhysical); /** * Creates a Java code fragment from the text of a Java code block. @@ -77,7 +80,7 @@ public abstract class JavaCodeFragmentFactory { * @return the created code fragment. */ @NotNull - public abstract PsiTypeCodeFragment createTypeCodeFragment(@NotNull String text, PsiElement context, boolean isPhysical); + public abstract PsiTypeCodeFragment createTypeCodeFragment(@NotNull String text, @Nullable PsiElement context, boolean isPhysical); /** * Creates a Java type code fragment from the text of the name of a Java type (the name @@ -91,11 +94,12 @@ public abstract class JavaCodeFragmentFactory { * @param flags types allowed to present in text. * @return the created code fragment. */ - @NotNull - public abstract PsiTypeCodeFragment createTypeCodeFragment(@NotNull String text, PsiElement context, boolean isPhysical, - @MagicConstant(flags = {ALLOW_VOID, ALLOW_ELLIPSIS, ALLOW_DISJUNCTION}) - int flags); - + @NotNull + public abstract PsiTypeCodeFragment createTypeCodeFragment(@NotNull String text, + @Nullable PsiElement context, + boolean isPhysical, + @MagicConstant(flags = {ALLOW_VOID, ALLOW_ELLIPSIS, ALLOW_DISJUNCTION}) int flags); + /** * Creates a Java reference code fragment from the text of a Java reference to a * package or class. @@ -110,7 +114,7 @@ public abstract class JavaCodeFragmentFactory { */ @NotNull public abstract PsiJavaCodeReferenceCodeFragment createReferenceCodeFragment(@NotNull String text, - PsiElement context, + @Nullable PsiElement context, boolean isPhysical, boolean isClassesAccepted); diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/AdditionalRootsProviderService.java b/jps/jps-builders/src/org/jetbrains/jps/builders/AdditionalRootsProviderService.java index 04f060466409..cfc2d984f399 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/builders/AdditionalRootsProviderService.java +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/AdditionalRootsProviderService.java @@ -1,6 +1,7 @@ package org.jetbrains.jps.builders; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.builders.storage.BuildDataPaths; import java.io.File; import java.util.Collection; @@ -22,7 +23,7 @@ public abstract class AdditionalRootsProviderService getAdditionalRoots(@NotNull BuildTarget target, File dataStorageRoot) { + public List getAdditionalRoots(@NotNull BuildTarget target, BuildDataPaths dataPaths) { return Collections.emptyList(); } } diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/BuildTarget.java b/jps/jps-builders/src/org/jetbrains/jps/builders/BuildTarget.java index dc21636f6a92..2750aefcfdf5 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/builders/BuildTarget.java +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/BuildTarget.java @@ -2,6 +2,7 @@ package org.jetbrains.jps.builders; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jps.builders.storage.BuildDataPaths; import org.jetbrains.jps.indices.IgnoredFileIndex; import org.jetbrains.jps.indices.ModuleExcludeIndex; import org.jetbrains.jps.model.JpsModel; @@ -32,7 +33,10 @@ public abstract class BuildTarget { } @NotNull - public abstract List computeRootDescriptors(JpsModel model, ModuleExcludeIndex index, IgnoredFileIndex ignoredFileIndex); + public abstract List computeRootDescriptors(JpsModel model, + ModuleExcludeIndex index, + IgnoredFileIndex ignoredFileIndex, + BuildDataPaths dataPaths); @Nullable public abstract BuildRootDescriptor findRootDescriptor(String rootId, BuildRootIndex rootIndex); diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/BuildTargetType.java b/jps/jps-builders/src/org/jetbrains/jps/builders/BuildTargetType.java index 2b606f055037..797640408a09 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/builders/BuildTargetType.java +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/BuildTargetType.java @@ -15,7 +15,7 @@ public abstract class BuildTargetType> { myTypeId = typeId; } - public String getTypeId() { + public final String getTypeId() { return myTypeId; } diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildDataPathsImpl.java b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildDataPathsImpl.java new file mode 100644 index 000000000000..caa7c26f3076 --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildDataPathsImpl.java @@ -0,0 +1,39 @@ +package org.jetbrains.jps.builders.impl; + +import com.intellij.util.PathUtilRt; +import org.jetbrains.jps.builders.BuildTarget; +import org.jetbrains.jps.builders.BuildTargetType; +import org.jetbrains.jps.builders.storage.BuildDataPaths; + +import java.io.File; + +/** + * @author nik + */ +public class BuildDataPathsImpl implements BuildDataPaths { + private final File myDataStorageRoot; + + public BuildDataPathsImpl(File dataStorageRoot) { + myDataStorageRoot = dataStorageRoot; + } + + @Override + public File getDataStorageRoot() { + return myDataStorageRoot; + } + + @Override + public File getTargetsDataRoot() { + return new File(myDataStorageRoot, "targets"); + } + + @Override + public File getTargetTypeDataRoot(BuildTargetType targetType) { + return new File(getTargetsDataRoot(), targetType.getTypeId()); + } + + @Override + public File getTargetDataRoot(BuildTarget target) { + return new File(getTargetTypeDataRoot(target.getTargetType()), PathUtilRt.suggestFileName(target.getId(), true, true)); + } +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildRootIndexImpl.java b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildRootIndexImpl.java index 3178be5f18f1..9ceaf2fd307e 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildRootIndexImpl.java +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildRootIndexImpl.java @@ -11,6 +11,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.builders.*; import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType; import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor; +import org.jetbrains.jps.builders.storage.BuildDataPaths; import org.jetbrains.jps.incremental.BuilderRegistry; import org.jetbrains.jps.incremental.CompileContext; import org.jetbrains.jps.indices.IgnoredFileIndex; @@ -33,32 +34,30 @@ public class BuildRootIndexImpl implements BuildRootIndex { private THashMap> myRootToDescriptor; private ConcurrentMap myFileFilters; - public BuildRootIndexImpl(BuildTargetIndex targetIndex, - JpsModel model, - ModuleExcludeIndex index, - File dataStorageRoot, final IgnoredFileIndex ignoredFileIndex) { + public BuildRootIndexImpl(BuildTargetIndex targetIndex, JpsModel model, ModuleExcludeIndex index, + BuildDataPaths dataPaths, final IgnoredFileIndex ignoredFileIndex) { myRootsByTarget = new HashMap, List>(); myRootToDescriptor = new THashMap>(FileUtil.FILE_HASHING_STRATEGY); myFileFilters = new ConcurrentHashMap(); final Iterable rootsProviders = JpsServiceManager.getInstance().getExtensions(AdditionalRootsProviderService.class); for (BuildTargetType targetType : BuilderRegistry.getInstance().getTargetTypes()) { for (BuildTarget target : targetIndex.getAllTargets(targetType)) { - addRoots(dataStorageRoot, rootsProviders, targetType, target, model, index, ignoredFileIndex); + addRoots(dataPaths, rootsProviders, targetType, target, model, index, ignoredFileIndex); } } } - private void addRoots(File dataStorageRoot, Iterable rootsProviders, + private void addRoots(BuildDataPaths dataPaths, Iterable rootsProviders, BuildTargetType targetType, BuildTarget target, JpsModel model, ModuleExcludeIndex index, IgnoredFileIndex ignoredFileIndex) { - List descriptors = target.computeRootDescriptors(model, index, ignoredFileIndex); + List descriptors = target.computeRootDescriptors(model, index, ignoredFileIndex, dataPaths); for (AdditionalRootsProviderService provider : rootsProviders) { if (provider.getTargetTypes().contains(targetType)) { //noinspection unchecked AdditionalRootsProviderService providerService = (AdditionalRootsProviderService)provider; - final List additionalRoots = providerService.getAdditionalRoots(target, dataStorageRoot); + final List additionalRoots = providerService.getAdditionalRoots(target, dataPaths); if (!additionalRoots.isEmpty()) { descriptors = new ArrayList(descriptors); descriptors.addAll(additionalRoots); diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/storage/BuildDataPaths.java b/jps/jps-builders/src/org/jetbrains/jps/builders/storage/BuildDataPaths.java new file mode 100644 index 000000000000..8925d0d25c81 --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/storage/BuildDataPaths.java @@ -0,0 +1,19 @@ +package org.jetbrains.jps.builders.storage; + +import org.jetbrains.jps.builders.BuildTarget; +import org.jetbrains.jps.builders.BuildTargetType; + +import java.io.File; + +/** + * @author nik + */ +public interface BuildDataPaths { + File getDataStorageRoot(); + + File getTargetsDataRoot(); + + File getTargetTypeDataRoot(BuildTargetType targetType); + + File getTargetDataRoot(BuildTarget target); +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildRunner.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildRunner.java index a3bade8b0d37..28d397acd634 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildRunner.java +++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildRunner.java @@ -11,9 +11,11 @@ import org.jetbrains.jps.builders.BuildRootDescriptor; import org.jetbrains.jps.builders.BuildTarget; import org.jetbrains.jps.builders.BuildTargetLoader; import org.jetbrains.jps.builders.BuildTargetType; +import org.jetbrains.jps.builders.impl.BuildDataPathsImpl; import org.jetbrains.jps.builders.impl.BuildRootIndexImpl; import org.jetbrains.jps.builders.impl.BuildTargetIndexImpl; import org.jetbrains.jps.builders.java.dependencyView.Callbacks; +import org.jetbrains.jps.builders.storage.BuildDataPaths; import org.jetbrains.jps.incremental.*; import org.jetbrains.jps.incremental.fs.BuildFSState; import org.jetbrains.jps.incremental.messages.BuildMessage; @@ -55,17 +57,18 @@ public class BuildRunner { public ProjectDescriptor load(MessageHandler msgHandler, File dataStorageRoot, BuildFSState fsState) throws IOException { final JpsModel jpsModel = myModelLoader.loadModel(); + BuildDataPaths dataPaths = new BuildDataPathsImpl(dataStorageRoot); BuildTargetIndexImpl targetIndex = new BuildTargetIndexImpl(jpsModel); ModuleExcludeIndex index = new ModuleExcludeIndexImpl(jpsModel); IgnoredFileIndexImpl ignoredFileIndex = new IgnoredFileIndexImpl(jpsModel); - BuildRootIndexImpl buildRootIndex = new BuildRootIndexImpl(targetIndex, jpsModel, index, dataStorageRoot, ignoredFileIndex); - BuildTargetsState targetsState = new BuildTargetsState(dataStorageRoot, jpsModel, buildRootIndex); + BuildRootIndexImpl buildRootIndex = new BuildRootIndexImpl(targetIndex, jpsModel, index, dataPaths, ignoredFileIndex); + BuildTargetsState targetsState = new BuildTargetsState(dataPaths, jpsModel, buildRootIndex); ProjectTimestamps projectTimestamps = null; BuildDataManager dataManager = null; try { projectTimestamps = new ProjectTimestamps(dataStorageRoot, targetsState); - dataManager = new BuildDataManager(dataStorageRoot, targetsState, STORE_TEMP_CACHES_IN_MEMORY); + dataManager = new BuildDataManager(dataPaths, targetsState, STORE_TEMP_CACHES_IN_MEMORY); if (dataManager.versionDiffers()) { myForceCleanCaches = true; msgHandler.processMessage(new CompilerMessage("build", BuildMessage.Kind.INFO, "Dependency data format has changed, project rebuild required")); @@ -82,9 +85,9 @@ public class BuildRunner { } myForceCleanCaches = true; FileUtil.delete(dataStorageRoot); - targetsState = new BuildTargetsState(dataStorageRoot, jpsModel, buildRootIndex); + targetsState = new BuildTargetsState(dataPaths, jpsModel, buildRootIndex); projectTimestamps = new ProjectTimestamps(dataStorageRoot, targetsState); - dataManager = new BuildDataManager(dataStorageRoot, targetsState, STORE_TEMP_CACHES_IN_MEMORY); + dataManager = new BuildDataManager(dataPaths, targetsState, STORE_TEMP_CACHES_IN_MEMORY); // second attempt succeded msgHandler.processMessage(new CompilerMessage("build", BuildMessage.Kind.INFO, "Project rebuild forced: " + e.getMessage())); } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java index 28407dfeef68..b7c0e74a189b 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java @@ -18,7 +18,7 @@ public class BuilderRegistry { static final BuilderRegistry ourInstance = new BuilderRegistry(); } private final Map> myModuleLevelBuilders = new HashMap>(); - private final List> myTargetBuilders = new ArrayList>(); + private final List> myTargetBuilders = new ArrayList>(); private final Map> myTargetTypes = new LinkedHashMap>(); public static BuilderRegistry getInstance() { @@ -79,7 +79,7 @@ public class BuilderRegistry { return ContainerUtil.concat(myModuleLevelBuilders.values()); } - public List> getTargetBuilders() { + public List> getTargetBuilders() { return myTargetBuilders; } } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderService.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderService.java index d2d9455104bc..ce3102a4436b 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderService.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderService.java @@ -20,7 +20,7 @@ public abstract class BuilderService { } @NotNull - public List> createBuilders() { + public List> createBuilders() { return Collections.emptyList(); } } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/FSOperations.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/FSOperations.java index 3e9803ea97b3..05b519556582 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/FSOperations.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/FSOperations.java @@ -5,6 +5,7 @@ import com.intellij.openapi.util.io.FileSystemUtil; import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jps.builders.BuildRootDescriptor; import org.jetbrains.jps.util.JpsPathUtil; import org.jetbrains.jps.ModuleChunk; import org.jetbrains.jps.builders.BuildTarget; @@ -131,17 +132,21 @@ public class FSOperations { Timestamps timestamps, boolean forceMarkDirty, @Nullable THashSet currentFiles) throws IOException { final ModuleExcludeIndex rootsIndex = context.getProjectDescriptor().getModuleExcludeIndex(); - final Set excludes = new HashSet(rootsIndex.getModuleExcludes(target.getModule())); - for (JavaSourceRootDescriptor rd : context.getProjectDescriptor().getBuildRootIndex().getTargetRoots(target, context)) { - if (!rd.root.exists()) { + markDirtyFiles(context, target, timestamps, forceMarkDirty, currentFiles, + new HashSet(rootsIndex.getModuleExcludes(target.getModule()))); + } + + static void markDirtyFiles(CompileContext context, BuildTarget target, Timestamps timestamps, boolean forceMarkDirty, @Nullable THashSet currentFiles, final Set excludes) throws IOException { + for (BuildRootDescriptor rd : context.getProjectDescriptor().getBuildRootIndex().getTargetRoots(target, context)) { + if (!rd.getRootFile().exists()) { continue; } context.getProjectDescriptor().fsState.clearRecompile(rd); - traverseRecursively(context, rd, rd.root, excludes, timestamps, forceMarkDirty, currentFiles); + traverseRecursively(context, rd, rd.getRootFile(), excludes, timestamps, forceMarkDirty, currentFiles); } } - private static void traverseRecursively(CompileContext context, final JavaSourceRootDescriptor rd, final File file, Set excludes, @NotNull final Timestamps tsStorage, final boolean forceDirty, @Nullable Set currentFiles) throws IOException { + private static void traverseRecursively(CompileContext context, final BuildRootDescriptor rd, final File file, Set excludes, @NotNull final Timestamps tsStorage, final boolean forceDirty, @Nullable Set currentFiles) throws IOException { final File[] children = file.listFiles(); if (children != null) { // is directory if (children.length > 0 && !JpsPathUtil.isUnder(excludes, file)) { @@ -153,7 +158,7 @@ public class FSOperations { else { // is file boolean markDirty = forceDirty; if (!markDirty) { - markDirty = tsStorage.getStamp(file, rd.target) != FileSystemUtil.lastModified(file); + markDirty = tsStorage.getStamp(file, rd.getTarget()) != FileSystemUtil.lastModified(file); } if (markDirty) { // if it is full project rebuild, all storages are already completely cleared; diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java index 641e1fc95d9f..28d0881a3dbd 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java @@ -528,13 +528,19 @@ public class IncProjectBuilder { buildModuleChunk(context, new ModuleChunk(Collections.singleton(moduleBuildTarget))); } else { - buildTarget(target, context); + try { + buildTarget(target, context); + } + catch (IOException e) { + throw new ProjectBuildException(e); + } } } - private void buildTarget(BuildTarget target, CompileContext context) throws ProjectBuildException { - List> builders = BuilderRegistry.getInstance().getTargetBuilders(); - for (TargetBuilder builder : builders) { + private void buildTarget(BuildTarget target, CompileContext context) throws ProjectBuildException, IOException { + ensureFSStateInitialized(context, target); + List> builders = BuilderRegistry.getInstance().getTargetBuilders(); + for (TargetBuilder builder : builders) { buildTarget(target, context, builder); updateDoneFraction(context, 1.0f / builders.size()); } @@ -546,10 +552,17 @@ public class IncProjectBuilder { context.setDone(processed / myTotalTargetsWork); } - private static > void buildTarget(B target, CompileContext context, TargetBuilder builder) throws ProjectBuildException { + private static > void buildTarget(final T target, final CompileContext context, TargetBuilder builder) + throws ProjectBuildException, IOException { if (builder.getTargetTypes().contains(target.getTargetType())) { + DirtyFilesHolder holder = new DirtyFilesHolder() { + @Override + public void processDirtyFiles(@NotNull FileProcessor processor) throws IOException { + context.getProjectDescriptor().fsState.processFilesToRecompile(context, target, processor); + } + }; //noinspection unchecked - ((TargetBuilder)builder).build(target, context); + ((TargetBuilder)builder).build(target, context, holder); context.checkCanceled(); } } @@ -952,6 +965,16 @@ public class IncProjectBuilder { } } + private static void ensureFSStateInitialized(CompileContext context, BuildTarget target) throws IOException { + final ProjectDescriptor pd = context.getProjectDescriptor(); + final Timestamps timestamps = pd.timestamps.getStorage(); + final BuildTargetConfiguration configuration = pd.getTargetsState().getTargetConfiguration(target); + if (context.isProjectRebuild() || configuration.isTargetDirty() || context.getScope().isRecompilationForced(target)) { + FSOperations.markDirtyFiles(context, target, timestamps, true, null, Collections.emptySet()); + configuration.save(); + } + } + private static void ensureFSStateInitialized(CompileContext context, ModuleChunk chunk) throws IOException { final ProjectDescriptor pd = context.getProjectDescriptor(); final Timestamps timestamps = pd.timestamps.getStorage(); diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleBuildTarget.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleBuildTarget.java index 62fba04a2a3c..99f5a4bc23a9 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleBuildTarget.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleBuildTarget.java @@ -3,6 +3,7 @@ package org.jetbrains.jps.incremental; import com.intellij.util.Consumer; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.builders.storage.BuildDataPaths; import org.jetbrains.jps.util.JpsPathUtil; import org.jetbrains.jps.builders.BuildRootIndex; import org.jetbrains.jps.builders.BuildTarget; @@ -79,7 +80,10 @@ public class ModuleBuildTarget extends BuildTarget { @NotNull @Override - public List computeRootDescriptors(JpsModel model, ModuleExcludeIndex index, IgnoredFileIndex ignoredFileIndex) { + public List computeRootDescriptors(JpsModel model, + ModuleExcludeIndex index, + IgnoredFileIndex ignoredFileIndex, + BuildDataPaths dataPaths) { List roots = new ArrayList(); JavaSourceRootType type = isTests() ? JavaSourceRootType.TEST_SOURCE : JavaSourceRootType.SOURCE; for (JpsTypedModuleSourceRoot> sourceRoot : myModule.getSourceRoots(type)) { diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/TargetBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/TargetBuilder.java index 6a4d7474a1d7..7fea04440365 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/TargetBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/TargetBuilder.java @@ -1,26 +1,30 @@ package org.jetbrains.jps.incremental; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.builders.BuildRootDescriptor; import org.jetbrains.jps.builders.BuildTarget; import org.jetbrains.jps.builders.BuildTargetType; +import org.jetbrains.jps.builders.DirtyFilesHolder; +import java.io.IOException; import java.util.Collection; /** * Use {@link BuilderService} to register implementations of this class * @author nik */ -public abstract class TargetBuilder> extends Builder { - private final Collection> myTargetTypes; +public abstract class TargetBuilder> extends Builder { + private final Collection> myTargetTypes; - protected TargetBuilder(Collection> targetTypes) { + protected TargetBuilder(Collection> targetTypes) { myTargetTypes = targetTypes; } - public Collection> getTargetTypes() { + public Collection> getTargetTypes() { return myTargetTypes; } - public abstract void build(@NotNull B target, @NotNull CompileContext context) throws ProjectBuildException; + public abstract void build(@NotNull T target, @NotNull CompileContext context, DirtyFilesHolder holder) + throws ProjectBuildException, IOException; } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactBuildTarget.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactBuildTarget.java index 0e39ecbb829f..5cbffd1bc4f3 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactBuildTarget.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactBuildTarget.java @@ -6,20 +6,16 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.jps.builders.BuildRootDescriptor; import org.jetbrains.jps.builders.BuildRootIndex; import org.jetbrains.jps.builders.BuildTarget; -import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType; -import org.jetbrains.jps.incremental.ModuleBuildTarget; -import org.jetbrains.jps.indices.IgnoredFileIndex; -import org.jetbrains.jps.indices.ModuleExcludeIndex; +import org.jetbrains.jps.builders.storage.BuildDataPaths; import org.jetbrains.jps.incremental.artifacts.builders.LayoutElementBuildersRegistry; import org.jetbrains.jps.incremental.artifacts.impl.JpsArtifactUtil; import org.jetbrains.jps.incremental.artifacts.instructions.*; +import org.jetbrains.jps.indices.IgnoredFileIndex; +import org.jetbrains.jps.indices.ModuleExcludeIndex; import org.jetbrains.jps.model.JpsModel; import org.jetbrains.jps.model.artifact.JpsArtifact; import org.jetbrains.jps.model.artifact.elements.JpsArtifactOutputPackagingElement; import org.jetbrains.jps.model.artifact.elements.JpsPackagingElement; -import org.jetbrains.jps.model.java.JpsProductionModuleOutputPackagingElement; -import org.jetbrains.jps.model.java.JpsTestModuleOutputPackagingElement; -import org.jetbrains.jps.model.module.JpsModule; import java.io.PrintWriter; import java.util.Collection; @@ -61,18 +57,7 @@ public class ArtifactBuildTarget extends BuildTarget { } } } - else if (element instanceof JpsProductionModuleOutputPackagingElement) { - JpsModule module = ((JpsProductionModuleOutputPackagingElement)element).getModuleReference().resolve(); - if (module != null) { - dependencies.add(new ModuleBuildTarget(module, JavaModuleBuildTargetType.PRODUCTION)); - } - } - else if (element instanceof JpsTestModuleOutputPackagingElement) { - JpsModule module = ((JpsTestModuleOutputPackagingElement)element).getModuleReference().resolve(); - if (module != null) { - dependencies.add(new ModuleBuildTarget(module, JavaModuleBuildTargetType.TEST)); - } - } + dependencies.addAll(LayoutElementBuildersRegistry.getInstance().getDependencies(element)); return true; } }); @@ -102,9 +87,12 @@ public class ArtifactBuildTarget extends BuildTarget { @NotNull @Override - public List computeRootDescriptors(JpsModel model, ModuleExcludeIndex index, IgnoredFileIndex ignoredFileIndex) { + public List computeRootDescriptors(JpsModel model, + ModuleExcludeIndex index, + IgnoredFileIndex ignoredFileIndex, + BuildDataPaths dataPaths) { ArtifactInstructionsBuilderImpl builder = new ArtifactInstructionsBuilderImpl(index, ignoredFileIndex, this); - ArtifactInstructionsBuilderContext context = new ArtifactInstructionsBuilderContextImpl(); + ArtifactInstructionsBuilderContext context = new ArtifactInstructionsBuilderContextImpl(model, dataPaths); String outputPath = StringUtil.notNullize(myArtifact.getOutputPath()); final CopyToDirectoryInstructionCreator instructionCreator = new CopyToDirectoryInstructionCreator(builder, outputPath); LayoutElementBuildersRegistry.getInstance().generateInstructions(myArtifact, instructionCreator, context); diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderService.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderService.java index c609cb7e67db..df816e768ed6 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderService.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderService.java @@ -19,7 +19,7 @@ public class ArtifactBuilderService extends BuilderService { @NotNull @Override - public List> createBuilders() { + public List> createBuilders() { return Collections.singletonList(new IncArtifactBuilder()); } } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/IncArtifactBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/IncArtifactBuilder.java index ad50f36d7384..898ae711d18d 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/IncArtifactBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/IncArtifactBuilder.java @@ -9,6 +9,7 @@ import gnu.trove.TIntObjectHashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.jps.builders.BuildRootDescriptor; import org.jetbrains.jps.builders.BuildRootIndex; +import org.jetbrains.jps.builders.DirtyFilesHolder; import org.jetbrains.jps.builders.storage.SourceToOutputMapping; import org.jetbrains.jps.cmdline.ProjectDescriptor; import org.jetbrains.jps.incremental.*; @@ -28,7 +29,7 @@ import java.util.*; /** * @author nik */ -public class IncArtifactBuilder extends TargetBuilder { +public class IncArtifactBuilder extends TargetBuilder { public static final String BUILDER_NAME = "artifacts"; public IncArtifactBuilder() { @@ -36,7 +37,9 @@ public class IncArtifactBuilder extends TargetBuilder { } @Override - public void build(@NotNull ArtifactBuildTarget target, @NotNull CompileContext context) throws ProjectBuildException { + public void build(@NotNull ArtifactBuildTarget target, + @NotNull CompileContext context, + DirtyFilesHolder holder) throws ProjectBuildException { JpsArtifact artifact = target.getArtifact(); if (StringUtil.isEmpty(artifact.getOutputPath())) { context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, "Cannot build '" + artifact.getName() + "' artifact: output path is not specified")); diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/builders/LayoutElementBuilderService.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/builders/LayoutElementBuilderService.java index df1322c2b2ad..261670a00b04 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/builders/LayoutElementBuilderService.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/builders/LayoutElementBuilderService.java @@ -1,9 +1,14 @@ package org.jetbrains.jps.incremental.artifacts.builders; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.builders.BuildTarget; import org.jetbrains.jps.incremental.artifacts.instructions.ArtifactCompilerInstructionCreator; import org.jetbrains.jps.incremental.artifacts.instructions.ArtifactInstructionsBuilderContext; import org.jetbrains.jps.model.artifact.elements.JpsPackagingElement; +import java.util.Collection; +import java.util.Collections; + /** * @author nik */ @@ -16,6 +21,10 @@ public abstract class LayoutElementBuilderService public abstract void generateInstructions(E element, ArtifactCompilerInstructionCreator instructionCreator, ArtifactInstructionsBuilderContext builderContext); + public Collection> getDependencies(@NotNull E element) { + return Collections.emptyList(); + } + public final Class getElementClass() { return myElementClass; } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/builders/LayoutElementBuildersRegistry.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/builders/LayoutElementBuildersRegistry.java index 82e3c0143ba5..f594bab2aafe 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/builders/LayoutElementBuildersRegistry.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/builders/LayoutElementBuildersRegistry.java @@ -4,6 +4,12 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.containers.ClassMap; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jps.builders.BuildTarget; +import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType; +import org.jetbrains.jps.incremental.ModuleBuildTarget; +import org.jetbrains.jps.model.module.JpsModule; import org.jetbrains.jps.util.JpsPathUtil; import org.jetbrains.jps.incremental.artifacts.instructions.ArtifactCompilerInstructionCreator; import org.jetbrains.jps.incremental.artifacts.instructions.ArtifactInstructionsBuilderContext; @@ -15,6 +21,8 @@ import org.jetbrains.jps.model.java.JpsTestModuleOutputPackagingElement; import org.jetbrains.jps.service.JpsServiceManager; import java.io.File; +import java.util.Collection; +import java.util.Collections; import java.util.List; /** @@ -24,9 +32,9 @@ public class LayoutElementBuildersRegistry { private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.artifacts.builders.LayoutElementBuildersRegistry"); private static class InstanceHolder { + static final LayoutElementBuildersRegistry ourInstance = new LayoutElementBuildersRegistry(); } - public static LayoutElementBuildersRegistry getInstance() { return InstanceHolder.ourInstance; } @@ -53,16 +61,30 @@ public class LayoutElementBuildersRegistry { generateInstructions(artifact.getRootElement(), creator, context); } + public Collection> getDependencies(JpsPackagingElement element) { + LayoutElementBuilderService builder = getElementBuilder(element); + if (builder != null) { + //noinspection unchecked + return builder.getDependencies(element); + } + return Collections.emptyList(); + } + private void generateInstructions(JpsPackagingElement layoutElement, ArtifactCompilerInstructionCreator instructionCreator, ArtifactInstructionsBuilderContext builderContext) { - final LayoutElementBuilderService builder = myBuilders.get(layoutElement.getClass()); + final LayoutElementBuilderService builder = getElementBuilder(layoutElement); if (builder != null) { //noinspection unchecked builder.generateInstructions(layoutElement, instructionCreator, builderContext); } - else { + } + + private LayoutElementBuilderService getElementBuilder(JpsPackagingElement layoutElement) { + final LayoutElementBuilderService builder = myBuilders.get(layoutElement.getClass()); + if (builder == null) { LOG.error("Builder not found for artifact output layout element of class " + layoutElement.getClass()); } + return builder; } private void generateChildrenInstructions(JpsCompositePackagingElement element, ArtifactCompilerInstructionCreator instructionCreator, @@ -86,7 +108,7 @@ public class LayoutElementBuildersRegistry { } } - private static void generateModuleOutputInstructions(String outputUrl, ArtifactCompilerInstructionCreator creator) { + private static void generateModuleOutputInstructions(@Nullable String outputUrl, ArtifactCompilerInstructionCreator creator) { if (outputUrl != null) { creator.addDirectoryCopyInstructions(JpsPathUtil.urlToFile(outputUrl)); } @@ -194,6 +216,15 @@ public class LayoutElementBuildersRegistry { ArtifactInstructionsBuilderContext builderContext) { generateModuleOutputInstructions(element.getOutputUrl(), instructionCreator); } + + @Override + public Collection> getDependencies(@NotNull JpsProductionModuleOutputPackagingElement element) { + JpsModule module = element.getModuleReference().resolve(); + if (module != null) { + return Collections.singletonList(new ModuleBuildTarget(module, JavaModuleBuildTargetType.PRODUCTION)); + } + return Collections.emptyList(); + } } private static class ModuleTestOutputElementBuilder extends LayoutElementBuilderService { @@ -207,6 +238,15 @@ public class LayoutElementBuildersRegistry { ArtifactInstructionsBuilderContext builderContext) { generateModuleOutputInstructions(element.getOutputUrl(), instructionCreator); } + + @Override + public Collection> getDependencies(@NotNull JpsTestModuleOutputPackagingElement element) { + JpsModule module = element.getModuleReference().resolve(); + if (module != null) { + return Collections.singletonList(new ModuleBuildTarget(module, JavaModuleBuildTargetType.TEST)); + } + return Collections.emptyList(); + } } private class ComplexElementBuilder extends LayoutElementBuilderService { diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderContext.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderContext.java index b6f7899f9407..892ff84de519 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderContext.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderContext.java @@ -1,5 +1,7 @@ package org.jetbrains.jps.incremental.artifacts.instructions; +import org.jetbrains.jps.builders.storage.BuildDataPaths; +import org.jetbrains.jps.model.JpsModel; import org.jetbrains.jps.model.artifact.JpsArtifact; /** @@ -10,4 +12,8 @@ public interface ArtifactInstructionsBuilderContext { boolean enterArtifact(JpsArtifact artifact); void leaveArtifact(JpsArtifact artifact); + + BuildDataPaths getDataPaths(); + + JpsModel getModel(); } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderContextImpl.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderContextImpl.java index cf24cf98c650..8fc91355a537 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderContextImpl.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderContextImpl.java @@ -1,5 +1,7 @@ package org.jetbrains.jps.incremental.artifacts.instructions; +import org.jetbrains.jps.builders.storage.BuildDataPaths; +import org.jetbrains.jps.model.JpsModel; import org.jetbrains.jps.model.artifact.JpsArtifact; import java.util.HashSet; @@ -10,11 +12,25 @@ import java.util.Set; */ public class ArtifactInstructionsBuilderContextImpl implements ArtifactInstructionsBuilderContext { private final Set myParentArtifacts; + private final JpsModel myModel; + private final BuildDataPaths myDataPaths; - public ArtifactInstructionsBuilderContextImpl() { + public ArtifactInstructionsBuilderContextImpl(JpsModel model, BuildDataPaths dataPaths) { + myModel = model; + myDataPaths = dataPaths; myParentArtifacts = new HashSet(); } + @Override + public JpsModel getModel() { + return myModel; + } + + @Override + public BuildDataPaths getDataPaths() { + return myDataPaths; + } + @Override public boolean enterArtifact(JpsArtifact artifact) { return myParentArtifacts.add(artifact); diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java index 88727c9752de..4b5cd74d2732 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java @@ -6,6 +6,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.builders.BuildTarget; import org.jetbrains.jps.builders.impl.BuildTargetChunk; import org.jetbrains.jps.builders.java.dependencyView.Mappings; +import org.jetbrains.jps.builders.storage.BuildDataPaths; import org.jetbrains.jps.incremental.artifacts.ArtifactsBuildData; import java.io.*; @@ -20,7 +21,6 @@ import java.util.Map; public class BuildDataManager implements StorageOwner { private static final int VERSION = 12; private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.storage.BuildDataManager"); - private static final String SRC_TO_OUTPUTS_STORAGE = "src-out"; private static final String SRC_TO_FORM_STORAGE = "src-form"; private static final String MAPPINGS_STORAGE = "mappings"; @@ -31,22 +31,22 @@ public class BuildDataManager implements StorageOwner { private final ArtifactsBuildData myArtifactsBuildData; private final ModuleOutputRootsLayout myOutputRootsLayout; private final Mappings myMappings; - private final File myDataStorageRoot; + private final BuildDataPaths myDataPaths; private final BuildTargetsState myTargetsState; private final File myVersionFile; - public BuildDataManager(final File dataStorageRoot, BuildTargetsState targetsState, final boolean useMemoryTempCaches) throws IOException { - myDataStorageRoot = dataStorageRoot; + public BuildDataManager(final BuildDataPaths dataPaths, BuildTargetsState targetsState, final boolean useMemoryTempCaches) throws IOException { + myDataPaths = dataPaths; myTargetsState = targetsState; mySrcToFormMap = new SourceToFormMapping(new File(getSourceToFormsRoot(), "data")); myOutputRootsLayout = new ModuleOutputRootsLayout(new File(getOutputsLayoutRoot(), "data")); myMappings = new Mappings(getMappingsRoot(), useMemoryTempCaches); - myArtifactsBuildData = new ArtifactsBuildData(new File(dataStorageRoot, "artifacts")); - myVersionFile = new File(myDataStorageRoot, "version.dat"); + myArtifactsBuildData = new ArtifactsBuildData(new File(dataPaths.getDataStorageRoot(), "artifacts")); + myVersionFile = new File(myDataPaths.getDataStorageRoot(), "version.dat"); } private File getOutputsLayoutRoot() { - return new File(myDataStorageRoot, "output-roots"); + return new File(myDataPaths.getDataStorageRoot(), "output-roots"); } public SourceToOutputMappingImpl getSourceToOutputMap(final BuildTarget target) throws IOException { @@ -54,7 +54,7 @@ public class BuildDataManager implements StorageOwner { synchronized (mySourceToOutputLock) { mapping = mySourceToOutputs.get(target); if (mapping == null) { - mapping = new SourceToOutputMappingImpl(new File(myTargetsState.getTargetDataRoot(target), "src-out" + File.separator + "data")); + mapping = new SourceToOutputMappingImpl(new File(myDataPaths.getTargetDataRoot(target), "src-out" + File.separator + "data")); mySourceToOutputs.put(target, mapping); } } @@ -204,16 +204,16 @@ public class BuildDataManager implements StorageOwner { } } - public File getSourceToFormsRoot() { - return new File(myDataStorageRoot, SRC_TO_FORM_STORAGE); + private File getSourceToFormsRoot() { + return new File(myDataPaths.getDataStorageRoot(), SRC_TO_FORM_STORAGE); } - public File getMappingsRoot() { - return new File(myDataStorageRoot, MAPPINGS_STORAGE); + private File getMappingsRoot() { + return new File(myDataPaths.getDataStorageRoot(), MAPPINGS_STORAGE); } - public File getDataStorageRoot() { - return myDataStorageRoot; + public BuildDataPaths getDataPaths() { + return myDataPaths; } private static void wipeStorage(File root, @Nullable AbstractStateStorage storage) { diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildTargetConfiguration.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildTargetConfiguration.java index 4c177a40d28c..f87b475a846a 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildTargetConfiguration.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildTargetConfiguration.java @@ -75,6 +75,6 @@ public class BuildTargetConfiguration { } private File getConfigFile() { - return new File(myTargetsState.getTargetDataRoot(myTarget), "config.dat"); + return new File(myTargetsState.getDataPaths().getTargetDataRoot(myTarget), "config.dat"); } } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildTargetTypeState.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildTargetTypeState.java index 5657be9c0a91..477843622e5a 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildTargetTypeState.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildTargetTypeState.java @@ -27,7 +27,7 @@ public class BuildTargetTypeState { public BuildTargetTypeState(BuildTargetType targetType, BuildTargetsState state) { myTargetType = targetType; myTargetsState = state; - myTargetsFile = new File(state.getTargetTypeDataRoot(targetType), "targets.dat"); + myTargetsFile = new File(state.getDataPaths().getTargetTypeDataRoot(targetType), "targets.dat"); myConfigurations = new ConcurrentHashMap, BuildTargetConfiguration>(); myTargetIds = new HashMap, Integer>(); load(); diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildTargetsState.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildTargetsState.java index 22a950c81908..8260bb784a86 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildTargetsState.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildTargetsState.java @@ -2,12 +2,12 @@ package org.jetbrains.jps.incremental.storage; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.io.FileUtil; -import com.intellij.util.PathUtilRt; import com.intellij.util.containers.ConcurrentHashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.jps.builders.BuildTarget; import org.jetbrains.jps.builders.BuildTargetType; import org.jetbrains.jps.builders.impl.BuildRootIndexImpl; +import org.jetbrains.jps.builders.storage.BuildDataPaths; import org.jetbrains.jps.incremental.BuilderRegistry; import org.jetbrains.jps.model.JpsModel; @@ -20,14 +20,14 @@ import java.util.concurrent.atomic.AtomicInteger; */ public class BuildTargetsState { private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.storage.BuildTargetsState"); - private final File myDataStorageRoot; + private final BuildDataPaths myDataPaths; private AtomicInteger myMaxTargetId = new AtomicInteger(0); private ConcurrentMap, BuildTargetTypeState> myTypeStates = new ConcurrentHashMap, BuildTargetTypeState>(); private JpsModel myModel; private final BuildRootIndexImpl myBuildRootIndex; - public BuildTargetsState(File dataStorageRoot, JpsModel model, BuildRootIndexImpl buildRootIndex) { - myDataStorageRoot = dataStorageRoot; + public BuildTargetsState(BuildDataPaths dataPaths, JpsModel model, BuildRootIndexImpl buildRootIndex) { + myDataPaths = dataPaths; myModel = model; myBuildRootIndex = buildRootIndex; File targetTypesFile = getTargetTypesFile(); @@ -49,16 +49,8 @@ public class BuildTargetsState { } } - public File getTargetTypeDataRoot(BuildTargetType targetType) { - return new File(getTargetsDataRoot(), targetType.getTypeId()); - } - - public File getTargetsDataRoot() { - return new File(myDataStorageRoot, "targets"); - } - private File getTargetTypesFile() { - return new File(getTargetsDataRoot(), "targetTypes.dat"); + return new File(myDataPaths.getTargetsDataRoot(), "targetTypes.dat"); } public void save() { @@ -113,12 +105,8 @@ public class BuildTargetsState { return myMaxTargetId.incrementAndGet(); } - public File getTargetDataRoot(BuildTarget target) { - return new File(getTargetTypeDataRoot(target.getTargetType()), PathUtilRt.suggestFileName(target.getId(), true, true)); - } - public void clean() { - FileUtil.delete(getTargetsDataRoot()); + FileUtil.delete(myDataPaths.getTargetsDataRoot()); } public JpsModel getModel() { @@ -128,4 +116,8 @@ public class BuildTargetsState { public BuildRootIndexImpl getBuildRootIndex() { return myBuildRootIndex; } + + public BuildDataPaths getDataPaths() { + return myDataPaths; + } } diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/JpsBuildTestCase.java b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/JpsBuildTestCase.java index 67fc6a462b96..cdb04c9cd468 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/JpsBuildTestCase.java +++ b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/JpsBuildTestCase.java @@ -6,6 +6,8 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.testFramework.UsefulTestCase; import com.intellij.util.io.TestFileSystemBuilder; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jps.builders.impl.BuildDataPathsImpl; +import org.jetbrains.jps.builders.storage.BuildDataPaths; import org.jetbrains.jps.util.JpsPathUtil; import org.jetbrains.jps.api.CanceledStatus; import org.jetbrains.jps.builders.impl.BuildRootIndexImpl; @@ -125,10 +127,11 @@ public abstract class JpsBuildTestCase extends UsefulTestCase { BuildTargetIndexImpl targetIndex = new BuildTargetIndexImpl(myModel); ModuleExcludeIndex index = new ModuleExcludeIndexImpl(myModel); IgnoredFileIndexImpl ignoredFileIndex = new IgnoredFileIndexImpl(myModel); - BuildRootIndexImpl buildRootIndex = new BuildRootIndexImpl(targetIndex, myModel, index, myDataStorageRoot, ignoredFileIndex); - BuildTargetsState targetsState = new BuildTargetsState(myDataStorageRoot, myModel, buildRootIndex); + BuildDataPaths dataPaths = new BuildDataPathsImpl(myDataStorageRoot); + BuildRootIndexImpl buildRootIndex = new BuildRootIndexImpl(targetIndex, myModel, index, dataPaths, ignoredFileIndex); + BuildTargetsState targetsState = new BuildTargetsState(dataPaths, myModel, buildRootIndex); ProjectTimestamps timestamps = new ProjectTimestamps(myDataStorageRoot, targetsState); - BuildDataManager dataManager = new BuildDataManager(myDataStorageRoot, targetsState, true); + BuildDataManager dataManager = new BuildDataManager(dataPaths, targetsState, true); return new ProjectDescriptor(myModel, new BuildFSState(true), timestamps, dataManager, buildLoggingManager, index, targetsState, targetIndex, buildRootIndex, ignoredFileIndex); } @@ -186,7 +189,7 @@ public abstract class JpsBuildTestCase extends UsefulTestCase { return module; } - protected void doRebuild() { + protected void rebuildAll() { ProjectDescriptor descriptor = createProjectDescriptor(new BuildLoggingManager(new ArtifactBuilderLoggerImpl(), new JavaBuilderLoggerImpl())); try { CompileScope scope = new CompileScopeImpl(true, BuilderRegistry.getInstance().getTargetTypes(), Collections.>emptySet(), Collections.,Set>emptyMap()); diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/JpsRebuildTestCase.groovy b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/JpsRebuildTestCase.groovy index 76d6d892ee9c..c0d6192d2626 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/JpsRebuildTestCase.groovy +++ b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/JpsRebuildTestCase.groovy @@ -39,7 +39,7 @@ abstract class JpsRebuildTestCase extends JpsBuildTestCase { protected void rebuild() { JpsJavaExtensionService.getInstance().getOrCreateProjectExtension(myProject).outputUrl = JpsPathUtil.pathToUrl(FileUtil.toSystemIndependentName(getOrCreateOutputDirectory().getAbsolutePath())) - doRebuild() + rebuildAll() } private File getOrCreateOutputDirectory() { diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/resources/ResourceCopyingTest.java b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/resources/ResourceCopyingTest.java index a4eca58617fe..bc9dcfa02c41 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/resources/ResourceCopyingTest.java +++ b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/resources/ResourceCopyingTest.java @@ -25,7 +25,7 @@ public class ResourceCopyingTest extends JpsBuildTestCase { public void testSimple() { String file = createFile("src/a.xml"); JpsModule m = addModule("m", PathUtil.getParentPath(file)); - doRebuild(); + rebuildAll(); assertOutput(m, fs().file("a.xml")); } public void testPackagePrefix() { @@ -35,7 +35,7 @@ public class ResourceCopyingTest extends JpsBuildTestCase { JpsTypedModuleSourceRoot> typed = sourceRoot.asTyped(JavaSourceRootType.SOURCE); assertNotNull(typed); typed.getProperties().setData(new JavaSourceRootProperties("xxx")); - doRebuild(); + rebuildAll(); assertOutput(m, fs().dir("xxx").file("a.xml")); } } diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/RebuildArtifactOnConfigurationChangeTest.java b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/RebuildArtifactOnConfigurationChangeTest.java index b8f51999f000..a181fd4a81e3 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/RebuildArtifactOnConfigurationChangeTest.java +++ b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/RebuildArtifactOnConfigurationChangeTest.java @@ -21,7 +21,7 @@ public class RebuildArtifactOnConfigurationChangeTest extends ArtifactBuilderTes a.getRootElement().addChild(JpsPackagingElementFactory.getInstance().createDirectoryCopy(dir2)); buildAll(); assertOutput(a, fs().file("a.txt", "a").file("b.txt", "b")); - assertCopied("dir1/a.txt", "dir2/b.txt"); + assertDeletedAndCopied("out/artifacts/a/a.txt", "dir1/a.txt", "dir2/b.txt"); buildAllAndAssertUpToDate(); } diff --git a/jps/model-api/src/org/jetbrains/jps/util/JpsPathUtil.java b/jps/model-api/src/org/jetbrains/jps/util/JpsPathUtil.java index 02bf56a777b8..4fe47bf9892e 100644 --- a/jps/model-api/src/org/jetbrains/jps/util/JpsPathUtil.java +++ b/jps/model-api/src/org/jetbrains/jps/util/JpsPathUtil.java @@ -1,6 +1,8 @@ package org.jetbrains.jps.util; +import com.intellij.openapi.util.SystemInfoRt; import com.intellij.openapi.util.io.FileUtilRt; +import org.jetbrains.annotations.NotNull; import java.io.File; import java.util.Set; @@ -39,6 +41,23 @@ public class JpsPathUtil { return url; } + //todo[nik] copied from VfsUtil + @NotNull + public static String fixURLforIDEA(@NotNull String url ) { + int idx = url.indexOf(":/"); + if( idx >= 0 && idx+2 < url.length() && url.charAt(idx+2) != '/' ) { + String prefix = url.substring(0, idx); + String suffix = url.substring(idx+2); + + if (SystemInfoRt.isWindows) { + url = prefix+"://"+suffix; + } else { + url = prefix+":///"+suffix; + } + } + return url; + } + public static String pathToUrl(String path) { return "file://" + path; } diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/facet/JpsFacetSerializer.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/facet/JpsFacetSerializer.java index 4e75ee9d5a81..10e0640db0d0 100644 --- a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/facet/JpsFacetSerializer.java +++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/facet/JpsFacetSerializer.java @@ -7,7 +7,9 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.model.JpsElement; +import org.jetbrains.jps.model.JpsElementFactory; import org.jetbrains.jps.model.module.JpsModule; +import org.jetbrains.jps.model.module.JpsModuleReference; import org.jetbrains.jps.model.serialization.JpsModelSerializerExtension; import java.util.List; @@ -68,4 +70,13 @@ public class JpsFacetSerializer { } return null; } + + public static JpsModuleReference createModuleReference(String facetId) { + String moduleName = facetId.substring(0, facetId.indexOf('/')); + return JpsElementFactory.getInstance().createModuleReference(moduleName); + } + + public static String getFacetId(final JpsModuleReference moduleReference, final String facetTypeId, final String facetName) { + return moduleReference.getModuleName() + "/" + facetTypeId + "/" + facetName; + } } diff --git a/lib/netty-3.5.7.Final.jar b/lib/netty-3.5.8.Final.jar similarity index 77% rename from lib/netty-3.5.7.Final.jar rename to lib/netty-3.5.8.Final.jar index fb05e766d5e0..e2e42a528e00 100644 Binary files a/lib/netty-3.5.7.Final.jar and b/lib/netty-3.5.8.Final.jar differ diff --git a/lib/required_for_dist.txt b/lib/required_for_dist.txt index 7e1ac032c8a0..d254215c9399 100644 --- a/lib/required_for_dist.txt +++ b/lib/required_for_dist.txt @@ -45,5 +45,5 @@ xmlrpc-2.0.jar xpp3-1.1.4-min.jar xstream.jar swingx-core-1.6.2.jar -netty-3.5.7.Final.jar +netty-3.5.8.Final.jar protobuf-2.4.1.jar diff --git a/lib/src/netty-3.5.7.Final-sources.jar b/lib/src/netty-3.5.8.Final-sources.jar similarity index 86% rename from lib/src/netty-3.5.7.Final-sources.jar rename to lib/src/netty-3.5.8.Final-sources.jar index 88a573e2b6cd..76f306756017 100644 Binary files a/lib/src/netty-3.5.7.Final-sources.jar and b/lib/src/netty-3.5.8.Final-sources.jar differ diff --git a/platform/lang-api/src/com/intellij/execution/ui/RunContentDescriptor.java b/platform/lang-api/src/com/intellij/execution/ui/RunContentDescriptor.java index 500616f5265f..295da9011365 100644 --- a/platform/lang-api/src/com/intellij/execution/ui/RunContentDescriptor.java +++ b/platform/lang-api/src/com/intellij/execution/ui/RunContentDescriptor.java @@ -30,9 +30,9 @@ import javax.swing.*; public class RunContentDescriptor implements Disposable { private static final Logger LOG = Logger.getInstance("#com.intellij.execution.ui.RunContentDescriptor"); - private final ExecutionConsole myExecutionConsole; + private ExecutionConsole myExecutionConsole; private ProcessHandler myProcessHandler; - private final JComponent myComponent; + private JComponent myComponent; private final String myDisplayName; private final Icon myIcon; @@ -74,6 +74,11 @@ public class RunContentDescriptor implements Disposable { public void dispose() { if (myExecutionConsole != null) { Disposer.dispose(myExecutionConsole); + myExecutionConsole = null; + } + if (myComponent != null) { + DataManager.removeDataProvider(myComponent); + myComponent = null; } } diff --git a/platform/lang-impl/src/com/intellij/application/options/TabbedLanguageCodeStylePanel.java b/platform/lang-impl/src/com/intellij/application/options/TabbedLanguageCodeStylePanel.java index 90504d9a2b5e..cdf701dec2f7 100644 --- a/platform/lang-impl/src/com/intellij/application/options/TabbedLanguageCodeStylePanel.java +++ b/platform/lang-impl/src/com/intellij/application/options/TabbedLanguageCodeStylePanel.java @@ -278,10 +278,22 @@ public abstract class TabbedLanguageCodeStylePanel extends CodeStyleAbstractPane public void setupCopyFromMenu(JPopupMenu copyMenu) { super.setupCopyFromMenu(copyMenu); if (myPredefinedCodeStyles.length > 0) { - JMenu langs = new JMenu("Language"); //TODO: Move to resource bundle + JMenu langs = new JMenu("Language") { + @Override + public void paint(Graphics g) { + GraphicsUtil.setupAntialiasing(g); + super.paint(g); + } + }; //TODO: Move to resource bundle copyMenu.add(langs); fillLanguages(langs); - JMenu predefined = new JMenu("Predefined Style"); //TODO: Move to resource bundle + JMenu predefined = new JMenu("Predefined Style") { + @Override + public void paint(Graphics g) { + GraphicsUtil.setupAntialiasing(g); + super.paint(g); + } + }; //TODO: Move to resource bundle copyMenu.add(predefined); fillPredefined(predefined); } @@ -298,7 +310,13 @@ public abstract class TabbedLanguageCodeStylePanel extends CodeStyleAbstractPane for (final Language lang : languages) { if (!lang.equals(getDefaultLanguage())) { final String langName = LanguageCodeStyleSettingsProvider.getLanguageName(lang); - JMenuItem langItem = new JMenuItem(langName); + JMenuItem langItem = new JMenuItem(langName) { + @Override + public void paint(Graphics g) { + GraphicsUtil.setupAntialiasing(g); + super.paint(g); + } + }; langItem.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent e) { @@ -321,7 +339,13 @@ public abstract class TabbedLanguageCodeStylePanel extends CodeStyleAbstractPane private void fillPredefined(JMenuItem parentMenu) { for (final PredefinedCodeStyle predefinedCodeStyle : myPredefinedCodeStyles) { - JMenuItem predefinedItem = new JMenuItem(predefinedCodeStyle.getName()); + JMenuItem predefinedItem = new JMenuItem(predefinedCodeStyle.getName()) { + @Override + public void paint(Graphics g) { + GraphicsUtil.setupAntialiasing(g); + super.paint(g); + } + }; parentMenu.add(predefinedItem); predefinedItem.addActionListener(new ActionListener() { @Override diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java index c7e26b2201bb..64d77f6b4462 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java @@ -179,7 +179,7 @@ public class ReformatCodeAction extends AnAction implements DumbAware { final TextRange range; if (!processWholeFile && editor != null && editor.getSelectionModel().hasSelection()){ - range = new TextRange(editor.getSelectionModel().getSelectionStart(), editor.getSelectionModel().getSelectionEnd()); + range = TextRange.create(editor.getSelectionModel().getSelectionStart(), editor.getSelectionModel().getSelectionEnd()); } else{ range = null; @@ -203,8 +203,8 @@ public class ReformatCodeAction extends AnAction implements DumbAware { final PsiFile finalFile = file; SelectionModel selectionModel = editor.getSelectionModel(); final TextRange rangeToUse = selectionModel.hasSelection() - ? TextRange.from(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd()) - : TextRange.from(0, editor.getDocument().getTextLength()); + ? TextRange.create(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd()) + : TextRange.create(0, editor.getDocument().getTextLength()); CommandProcessor.getInstance().executeCommand(project, new Runnable() { @Override public void run() { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionFeatures.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionFeatures.java index 31e511143da3..5c8398f08b28 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionFeatures.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionFeatures.java @@ -20,7 +20,8 @@ import org.jetbrains.annotations.NonNls; /** * @author peter */ -public interface CodeCompletionFeatures { +public interface + CodeCompletionFeatures { @NonNls String EXCLAMATION_FINISH = "editing.completion.finishByExclamation"; @NonNls String SECOND_BASIC_COMPLETION = "editing.completion.second.basic"; @NonNls String EDITING_COMPLETION_SMARTTYPE_GENERAL = "editing.completion.smarttype.general"; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonEditorPopup.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonEditorPopup.java index 59fac9a484d7..4a7f7874a498 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonEditorPopup.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonEditorPopup.java @@ -26,6 +26,7 @@ import com.intellij.openapi.editor.EditorBundle; import com.intellij.psi.PsiFile; import com.intellij.ui.PopupHandler; import com.intellij.ui.awt.RelativePoint; +import com.intellij.util.ui.GraphicsUtil; import javax.swing.*; import java.awt.*; @@ -49,7 +50,13 @@ public class DaemonEditorPopup extends PopupHandler { DaemonCodeAnalyzerSettings.getInstance().NEXT_ERROR_ACTION_GOES_TO_ERRORS_FIRST = errorsFirst.isSelected(); } }); - final JPopupMenu popupMenu = new JPopupMenu(); + final JPopupMenu popupMenu = new JPopupMenu() { + @Override + public void paint(Graphics g) { + GraphicsUtil.setupAntialiasing(g); + super.paint(g); + } + }; popupMenu.add(errorsFirst); final JRadioButtonMenuItem next = new JRadioButtonMenuItem(EditorBundle.message("errors.panel.go.to.next.error.warning.radio")); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfo.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfo.java index 63b33b02f2be..04b794608721 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfo.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfo.java @@ -191,7 +191,7 @@ public class HighlightInfo implements Segment { } @Nullable - public static HighlightInfo createHighlightInfo(@NotNull HighlightInfoType type, @NotNull PsiElement element, String description, String toolTip) { + public static HighlightInfo createHighlightInfo(@NotNull HighlightInfoType type, @NotNull PsiElement element, @Nullable String description, @Nullable String toolTip) { TextRange range = element.getTextRange(); int start = range.getStartOffset(); int end = range.getEndOffset(); @@ -199,8 +199,8 @@ public class HighlightInfo implements Segment { } @Nullable - public static HighlightInfo createHighlightInfo(@NotNull HighlightInfoType type, @Nullable PsiElement element, int start, int end, String description, - String toolTip, + public static HighlightInfo createHighlightInfo(@NotNull HighlightInfoType type, @Nullable PsiElement element, int start, int end, @Nullable String description, + @Nullable String toolTip, boolean isEndOfLine, @Nullable TextAttributes forcedAttributes) { LOG.assertTrue(element != null || ArrayUtil.find(HighlightSeverity.DEFAULT_SEVERITIES, type.getSeverity(element)) != -1, "Custom type demands element to detect its text attributes"); @@ -215,7 +215,7 @@ public class HighlightInfo implements Segment { return highlightInfo; } @Nullable - public static HighlightInfo createHighlightInfo(@NotNull HighlightInfoType type, @Nullable PsiElement element, int start, int end, String description, String toolTip) { + public static HighlightInfo createHighlightInfo(@NotNull HighlightInfoType type, @Nullable PsiElement element, int start, int end, @Nullable String description, @Nullable String toolTip) { return createHighlightInfo(type, element, start, end, description, toolTip, false, null); } @@ -279,7 +279,7 @@ public class HighlightInfo implements Segment { this.isFileLevelAnnotation = isFileLevelAnnotation; } - private static boolean calcNeedUpdateOnTyping(Boolean needsUpdateOnTyping, HighlightInfoType type) { + private static boolean calcNeedUpdateOnTyping(@Nullable Boolean needsUpdateOnTyping, HighlightInfoType type) { if (needsUpdateOnTyping != null) return needsUpdateOnTyping.booleanValue(); if (type == HighlightInfoType.TODO) return false; @@ -417,7 +417,7 @@ public class HighlightInfo implements Segment { return info; } - private static void appendFixes(TextRange fixedRange, HighlightInfo info, List fixes) { + private static void appendFixes(@Nullable TextRange fixedRange, HighlightInfo info, List fixes) { if (fixes != null) { for (final Annotation.QuickFixInfo quickFixInfo : fixes) { QuickFixAction.registerQuickFixAction(info, fixedRange != null ? fixedRange : quickFixInfo.textRange, quickFixInfo.quickFix, @@ -435,11 +435,12 @@ public class HighlightInfo implements Segment { } public static HighlightInfoType convertSeverity(final HighlightSeverity severity) { - return severity == HighlightSeverity.ERROR - ? HighlightInfoType.ERROR - : severity == HighlightSeverity.WARNING ? HighlightInfoType.WARNING - : severity == HighlightSeverity.INFO ? HighlightInfoType.INFO - : severity == HighlightSeverity.WEAK_WARNING ? HighlightInfoType.WEAK_WARNING : HighlightInfoType.INFORMATION; + return severity == HighlightSeverity.ERROR? HighlightInfoType.ERROR : + severity == HighlightSeverity.WARNING ? HighlightInfoType.WARNING : + severity == HighlightSeverity.INFO ? HighlightInfoType.INFO : + severity == HighlightSeverity.WEAK_WARNING ? HighlightInfoType.WEAK_WARNING : + severity ==HighlightSeverity.GENERIC_SERVER_ERROR_OR_WARNING ? HighlightInfoType.GENERIC_WARNINGS_OR_ERRORS_FROM_SERVER : + HighlightInfoType.INFORMATION; } public static ProblemHighlightType convertType(HighlightInfoType infoType) { @@ -450,10 +451,10 @@ public class HighlightInfo implements Segment { } public static ProblemHighlightType convertSeverityToProblemHighlight(HighlightSeverity severity) { - return severity == HighlightSeverity.ERROR? ProblemHighlightType.ERROR : + return severity == HighlightSeverity.ERROR ? ProblemHighlightType.ERROR : severity == HighlightSeverity.WARNING ? ProblemHighlightType.GENERIC_ERROR_OR_WARNING : - severity == HighlightSeverity.INFO ? ProblemHighlightType.INFO : - severity == HighlightSeverity.WEAK_WARNING? ProblemHighlightType.WEAK_WARNING : ProblemHighlightType.INFORMATION; + severity == HighlightSeverity.INFO ? ProblemHighlightType.INFO : + severity == HighlightSeverity.WEAK_WARNING ? ProblemHighlightType.WEAK_WARNING : ProblemHighlightType.INFORMATION; } @@ -497,7 +498,7 @@ public class HighlightInfo implements Segment { this(action, options, displayName, icon, null); } - public IntentionActionDescriptor(@NotNull IntentionAction action, final List options, final String displayName, Icon icon, @Nullable HighlightDisplayKey key) { + public IntentionActionDescriptor(@NotNull IntentionAction action, @Nullable final List options, @Nullable final String displayName, @Nullable Icon icon, @Nullable HighlightDisplayKey key) { myAction = action; myOptions = options; myDisplayName = displayName; @@ -565,6 +566,7 @@ public class HighlightInfo implements Segment { return options; } + @Nullable public String getDisplayName() { return myDisplayName; } @@ -575,6 +577,7 @@ public class HighlightInfo implements Segment { return "descriptor: " + (text.isEmpty() ? getAction().getClass() : text); } + @Nullable public Icon getIcon() { return myIcon; } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfoType.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfoType.java index 336eb99cc344..48b65e3391e5 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfoType.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfoType.java @@ -116,7 +116,7 @@ public interface HighlightInfoType { @Override @NotNull - public HighlightSeverity getSeverity(PsiElement psiElement) { + public HighlightSeverity getSeverity(@Nullable PsiElement psiElement) { return mySeverity; } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java index c9051170c817..b9a75f43d403 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java @@ -133,7 +133,7 @@ public class SeverityRegistrar implements JDOMExternalizable, Comparator actions) { + public static void registerQuickFixActions(@Nullable final HighlightInfo info, @NotNull final Collection actions) { for (IntentionAction action : actions) { registerQuickFixAction(info, action); } @@ -61,16 +62,16 @@ public final class QuickFixAction { /** This is used by TeamCity plugin */ @Deprecated - public static void registerQuickFixAction(HighlightInfo info, IntentionAction action, List options, String displayName) { + public static void registerQuickFixAction(@Nullable HighlightInfo info, @Nullable IntentionAction action, @Nullable List options, @Nullable String displayName) { doRegister(info, action, options, displayName, null, null); } - private static void doRegister(HighlightInfo info, - IntentionAction action, - List options, - String displayName, - TextRange fixRange, - HighlightDisplayKey key) { + private static void doRegister(@Nullable HighlightInfo info, + @Nullable IntentionAction action, + @Nullable List options, + @Nullable String displayName, + @Nullable TextRange fixRange, + @Nullable HighlightDisplayKey key) { if (info == null || action == null) return; if (fixRange == null) fixRange = new TextRange(info.startOffset, info.endOffset); if (info.quickFixActionRanges == null) { @@ -85,11 +86,11 @@ public final class QuickFixAction { } } - public static void registerQuickFixAction(HighlightInfo info, TextRange fixRange, IntentionAction action, final HighlightDisplayKey key) { + public static void registerQuickFixAction(@Nullable HighlightInfo info, @Nullable TextRange fixRange, @Nullable IntentionAction action, @Nullable final HighlightDisplayKey key) { doRegister(info, action, null, HighlightDisplayKey.getDisplayNameByKey(key), fixRange, key); } - public static void registerQuickFixAction(HighlightInfo info, TextRange fixRange, IntentionAction action) { + public static void registerQuickFixAction(@Nullable HighlightInfo info, @Nullable TextRange fixRange, @Nullable IntentionAction action) { doRegister(info, action, null, null, fixRange, null); } 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 594088b83af1..6740f388b45c 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java @@ -55,6 +55,7 @@ import com.intellij.util.SmartList; import com.intellij.util.concurrency.Semaphore; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.messages.MessageBus; +import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -795,7 +796,11 @@ public class PsiDocumentManagerImpl extends PsiDocumentManager implements Projec @Override public void save() { // Ensure all documents are committed on save so file content dependent indices, that use PSI to build have consistent content. - commitAllDocuments(); + UIUtil.invokeLaterIfNeeded(new Runnable() { + public void run() { + commitAllDocuments(); + } + }); } @NonNls diff --git a/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureDialogBase.java b/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureDialogBase.java index a2f5b4e4cc17..b57406143617 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureDialogBase.java +++ b/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureDialogBase.java @@ -18,6 +18,7 @@ package com.intellij.refactoring.changeSignature; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CustomShortcutSet; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.event.DocumentAdapter; import com.intellij.openapi.editor.event.DocumentEvent; @@ -53,6 +54,7 @@ import com.intellij.util.ui.table.JBListTable; import com.intellij.util.ui.table.JBTableRow; import com.intellij.util.ui.table.JBTableRowEditor; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.border.EmptyBorder; @@ -72,28 +74,36 @@ import java.util.Set; /** * @author Konstantin Bulenkov */ -public abstract class ChangeSignatureDialogBase

> - extends RefactoringDialog { +public abstract class ChangeSignatureDialogBase< + ParamInfo extends ParameterInfo, + Method extends PsiElement, + Visibility, + Descriptor extends MethodDescriptor, + ParameterTableModelItem extends ParameterTableModelItemBase, + ParameterTableModel extends ParameterTableModelBase + > extends RefactoringDialog { + + private static final Logger LOG = Logger.getInstance(ChangeSignatureDialogBase.class); protected static final String EXIT_SILENTLY = ""; - protected final D myMethod; + protected final Descriptor myMethod; private final boolean myAllowDelegation; protected JPanel myNamePanel; protected EditorTextField myNameField; protected EditorTextField myReturnTypeField; protected JBListTable myParametersList; - protected TableView> myParametersTable; - protected final ParameterTableModelBase

myParametersTableModel; + protected TableView myParametersTable; + protected final ParameterTableModel myParametersTableModel; protected final UpdateSignatureListener mySignatureUpdater = new UpdateSignatureListener(); private MethodSignatureComponent mySignatureArea; private final Alarm myUpdateSignatureAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD); - protected VisibilityPanelBase myVisibilityPanel; + protected VisibilityPanelBase myVisibilityPanel; protected PsiCodeFragment myReturnTypeCodeFragment; private DelegationPanel myDelegationPanel; protected AnActionButton myPropagateParamChangesButton; - protected Set myMethodsToPropagateParameters = null; + protected Set myMethodsToPropagateParameters = null; private Tree myParameterPropagationTreeToReuse; @@ -101,21 +111,23 @@ public abstract class ChangeSignatureDialogBase

createParametersInfoModel(MethodDescriptor method); + protected abstract ParameterTableModel createParametersInfoModel(Descriptor method); protected abstract BaseRefactoringProcessor createRefactoringProcessor(); protected abstract PsiCodeFragment createReturnTypeCodeFragment(); - protected abstract CallerChooserBase createCallerChooser(String title, Tree treeToReuse, Consumer> callback); + @Nullable + protected abstract CallerChooserBase createCallerChooser(String title, Tree treeToReuse, Consumer> callback); + @Nullable protected abstract String validateAndCommitData(); protected abstract String calculateSignature(); - protected abstract VisibilityPanelBase createVisibilityControl(); + protected abstract VisibilityPanelBase createVisibilityControl(); - public ChangeSignatureDialogBase(Project project, final D method, boolean allowDelegation, PsiElement defaultValueContext) { + public ChangeSignatureDialogBase(Project project, final Descriptor method, boolean allowDelegation, PsiElement defaultValueContext) { super(project, true); myMethod = method; myDefaultValueContext = defaultValueContext; @@ -134,7 +146,7 @@ public abstract class ChangeSignatureDialogBase

parameterInfos) { + public void setParameterInfos(List parameterInfos) { myParametersTableModel.setParameterInfos(parameterInfos); updateSignature(); } @@ -148,7 +160,8 @@ public abstract class ChangeSignatureDialogBase

getParameters() { - List

result = new ArrayList

(myParametersTableModel.getRowCount()); - for (ParameterTableModelItemBase

item : myParametersTableModel.getItems()) { + public List getParameters() { + List result = new ArrayList(myParametersTableModel.getRowCount()); + for (ParameterTableModelItemBase item : myParametersTableModel.getItems()) { result.add(item.parameter); } return result; @@ -319,18 +332,17 @@ public abstract class ChangeSignatureDialogBase

> chooser = new Ref>(); - Consumer> callback = new Consumer>() { + final Ref> chooser = new Ref>(); + Consumer> callback = new Consumer>() { @Override - public void consume(Set callers) { + public void consume(Set callers) { myMethodsToPropagateParameters = callers; myParameterPropagationTreeToReuse = chooser.get().getTree(); } }; try { - chooser.set( - createCallerChooser(RefactoringBundle.message("changeSignature.parameter.caller.chooser"), myParameterPropagationTreeToReuse, - callback)); + String message = RefactoringBundle.message("changeSignature.parameter.caller.chooser"); + chooser.set(createCallerChooser(message, myParameterPropagationTreeToReuse, callback)); } catch (ProcessCanceledException ex) { // user cancelled initial callers search, don't show dialog @@ -368,7 +380,7 @@ public abstract class ChangeSignatureDialogBase

>(myParametersTableModel) { + myParametersTable = new TableView(myParametersTableModel) { public void removeEditor() { clearEditorListeners(); @@ -427,7 +439,7 @@ public abstract class ChangeSignatureDialogBase

> items = myParametersTable.getItems(); + final List items = myParametersTable.getItems(); final JComponent component = getRowPresentation(items.get(row), selected, focused); for (EditorTextField editorTextField : UIUtil.findComponentsOfType(component, EditorTextField.class)) { editorTextField.addSettingsProvider(new EditorSettingsProvider() { @@ -442,14 +454,15 @@ public abstract class ChangeSignatureDialogBase

> items = myParametersTable.getItems(); + final List items = myParametersTable.getItems(); return isEmptyRow(items.get(row)); } @Override protected JBTableRowEditor getRowEditor(final int row) { - final List> items = myParametersTable.getItems(); + final List items = myParametersTable.getItems(); JBTableRowEditor editor = getTableEditor(myParametersList.getTable(), items.get(row)); + LOG.assertTrue(editor != null); editor.addDocumentListener(new JBTableRowEditor.RowDocumentListener() { @Override public void documentChanged(DocumentEvent e, int column) { @@ -496,19 +509,21 @@ public abstract class ChangeSignatureDialogBase

item) { + @Nullable + protected JBTableRowEditor getTableEditor(JTable table, ParameterTableModelItemBase item) { return null; } - protected boolean isEmptyRow(ParameterTableModelItemBase

row) { + protected boolean isEmptyRow(ParameterTableModelItemBase row) { return false; } - protected JComponent getRowPresentation(ParameterTableModelItemBase

item, boolean selected, boolean focused) { + @Nullable + protected JComponent getRowPresentation(ParameterTableModelItemBase item, boolean selected, boolean focused) { return null; } - protected void customizeParametersTable(TableView> table) { + protected void customizeParametersTable(TableView table) { } private JComponent createSignaturePanel() { @@ -592,7 +607,7 @@ public abstract class ChangeSignatureDialogBase

infos = getParameters(); + final List infos = getParameters(); if (infos.size() <= myMethod.getParametersCount()) return false; for (int i = 0; i < myMethod.getParametersCount(); i++) { if (infos.get(i).getOldIndex() != i) return false; diff --git a/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ParameterTableModelBase.java b/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ParameterTableModelBase.java index 976933fb98b3..67c1a7e5b301 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ParameterTableModelBase.java +++ b/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ParameterTableModelBase.java @@ -35,8 +35,7 @@ import java.awt.*; import java.util.ArrayList; import java.util.List; -public abstract class ParameterTableModelBase

extends ListTableModel> - implements RowEditableTableModel { +public abstract class ParameterTableModelBase

> extends ListTableModel implements RowEditableTableModel { protected final PsiElement myTypeContext; protected final PsiElement myDefaultValueContext; @@ -49,14 +48,14 @@ public abstract class ParameterTableModelBase

extends L myDefaultValueContext = defaultValueContext; } - protected abstract ParameterTableModelItemBase

createRowItem(@Nullable P parameterInfo); + protected abstract TableItem createRowItem(@Nullable P parameterInfo); public void addRow() { addRow(createRowItem(null)); } public void setParameterInfos(List

parameterInfos) { - List> items = new ArrayList>(parameterInfos.size()); + List items = new ArrayList(parameterInfos.size()); for (P parameterInfo : parameterInfos) { items.add(createRowItem(parameterInfo)); } @@ -73,8 +72,8 @@ public abstract class ParameterTableModelBase

extends L fireTableCellUpdated(rowIndex, columnIndex); // to update signature } - protected static abstract class ColumnInfoBase

- extends ColumnInfo, Aspect> { + protected static abstract class ColumnInfoBase

, Aspect> + extends ColumnInfo { private TableCellRenderer myRenderer; private TableCellEditor myEditor; @@ -83,7 +82,7 @@ public abstract class ParameterTableModelBase

extends L } @Override - public final TableCellEditor getEditor(ParameterTableModelItemBase

o) { + public final TableCellEditor getEditor(TableItem o) { if (myEditor == null) { myEditor = doCreateEditor(o); } @@ -91,7 +90,7 @@ public abstract class ParameterTableModelBase

extends L } @Override - public final TableCellRenderer getRenderer(ParameterTableModelItemBase

item) { + public final TableCellRenderer getRenderer(TableItem item) { if (myRenderer == null) { final TableCellRenderer original = doCreateRenderer(item); myRenderer = new TableCellRenderer() { @@ -119,12 +118,12 @@ public abstract class ParameterTableModelBase

extends L return myRenderer; } - protected abstract TableCellRenderer doCreateRenderer(ParameterTableModelItemBase

item); + protected abstract TableCellRenderer doCreateRenderer(TableItem item); - protected abstract TableCellEditor doCreateEditor(ParameterTableModelItemBase

item); + protected abstract TableCellEditor doCreateEditor(TableItem item); } - protected static class TypeColumn

extends ColumnInfoBase { + protected static class TypeColumn

> extends ColumnInfoBase { protected final Project myProject; private final FileType myFileType; @@ -139,25 +138,25 @@ public abstract class ParameterTableModelBase

extends L } @Override - public PsiCodeFragment valueOf(ParameterTableModelItemBase

item) { + public PsiCodeFragment valueOf(TableItem item) { return item.typeCodeFragment; } @Override - public boolean isCellEditable(ParameterTableModelItemBase

pParameterTableModelItemBase) { + public boolean isCellEditable(TableItem pParameterTableModelItemBase) { return true; } - public TableCellRenderer doCreateRenderer(ParameterTableModelItemBase

pParameterTableModelItemBase) { + public TableCellRenderer doCreateRenderer(TableItem pParameterTableModelItemBase) { return new CodeFragmentTableCellRenderer(myProject, myFileType); } - public TableCellEditor doCreateEditor(ParameterTableModelItemBase

o) { + public TableCellEditor doCreateEditor(TableItem o) { return new CodeFragmentTableCellEditorBase(myProject, myFileType); } } - protected static class NameColumn

extends ColumnInfoBase { + protected static class NameColumn

> extends ColumnInfoBase { private final Project myProject; public NameColumn(Project project) { @@ -170,21 +169,21 @@ public abstract class ParameterTableModelBase

extends L } @Override - public String valueOf(ParameterTableModelItemBase

item) { + public String valueOf(TableItem item) { return item.parameter.getName(); } @Override - public void setValue(ParameterTableModelItemBase

item, String value) { + public void setValue(TableItem item, String value) { item.parameter.setName(value); } @Override - public boolean isCellEditable(ParameterTableModelItemBase

pParameterTableModelItemBase) { + public boolean isCellEditable(TableItem pParameterTableModelItemBase) { return true; } - public TableCellRenderer doCreateRenderer(ParameterTableModelItemBase

item) { + public TableCellRenderer doCreateRenderer(TableItem item) { return new ColoredTableCellRenderer() { public void customizeCellRenderer(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { @@ -194,12 +193,12 @@ public abstract class ParameterTableModelBase

extends L }; } - public TableCellEditor doCreateEditor(ParameterTableModelItemBase

o) { + public TableCellEditor doCreateEditor(TableItem o) { return new StringTableCellEditor(myProject); } } - protected static class DefaultValueColumn

extends ColumnInfoBase { + protected static class DefaultValueColumn

> extends ColumnInfoBase { private final Project myProject; private final FileType myFileType; @@ -214,50 +213,50 @@ public abstract class ParameterTableModelBase

extends L } @Override - public boolean isCellEditable(ParameterTableModelItemBase

item) { + public boolean isCellEditable(TableItem item) { return !item.isEllipsisType() && item.parameter.getOldIndex() == -1; } @Override - public PsiCodeFragment valueOf(ParameterTableModelItemBase

item) { + public PsiCodeFragment valueOf(TableItem item) { return item.defaultValueCodeFragment; } - public TableCellRenderer doCreateRenderer(ParameterTableModelItemBase

item) { + public TableCellRenderer doCreateRenderer(TableItem item) { return new CodeFragmentTableCellRenderer(myProject, myFileType); } - public TableCellEditor doCreateEditor(ParameterTableModelItemBase

item) { + public TableCellEditor doCreateEditor(TableItem item) { return new CodeFragmentTableCellEditorBase(myProject, myFileType); } } - protected static class AnyVarColumn

extends ColumnInfoBase { + protected static class AnyVarColumn

> extends ColumnInfoBase { public AnyVarColumn() { super(RefactoringBundle.message("column.name.any.var")); } @Override - public boolean isCellEditable(ParameterTableModelItemBase

item) { + public boolean isCellEditable(TableItem item) { return !item.isEllipsisType() && item.parameter.getOldIndex() == -1; } @Override - public Boolean valueOf(ParameterTableModelItemBase

item) { + public Boolean valueOf(TableItem item) { return item.parameter.isUseAnySingleVariable(); } @Override - public void setValue(ParameterTableModelItemBase

item, Boolean value) { + public void setValue(TableItem item, Boolean value) { item.parameter.setUseAnySingleVariable(value); } - public TableCellRenderer doCreateRenderer(ParameterTableModelItemBase

item) { + public TableCellRenderer doCreateRenderer(TableItem item) { return new BooleanTableCellRenderer(); } - public TableCellEditor doCreateEditor(ParameterTableModelItemBase

item) { + public TableCellEditor doCreateEditor(TableItem item) { return new BooleanTableCellEditor(false); } diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/AutomaticRenamingDialog.java b/platform/lang-impl/src/com/intellij/refactoring/rename/AutomaticRenamingDialog.java index e22dcc4d8923..9e6dfc0a4d16 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/AutomaticRenamingDialog.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/AutomaticRenamingDialog.java @@ -36,7 +36,6 @@ import com.intellij.ui.TableUtil; import com.intellij.ui.table.JBTable; import com.intellij.usageView.UsageInfo; import com.intellij.usages.impl.UsagePreviewPanel; -import com.intellij.util.ui.Table; import javax.swing.*; import javax.swing.event.ListSelectionEvent; @@ -134,9 +133,11 @@ public class AutomaticRenamingDialog extends DialogWrapper { protected void handleChanges() { final int selectedRow = myTable.getSelectedRow(); - final boolean validName = RenameUtil.isValidName(myProject, myRenames[selectedRow], myNewNames[selectedRow]); - getOKAction().setEnabled(validName); - setErrorText(validName ? null : "Identifier \'" + myNewNames[selectedRow] + "\' is invalid"); + if (selectedRow > -1) { + final boolean validName = RenameUtil.isValidName(myProject, myRenames[selectedRow], myNewNames[selectedRow]); + getOKAction().setEnabled(validName); + setErrorText(validName ? null : "Identifier \'" + myNewNames[selectedRow] + "\' is invalid"); + } } protected JComponent createCenterPanel() { diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java index 7f743742985f..ad16b2b986fe 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java @@ -696,20 +696,21 @@ public abstract class InplaceRefactoring { releaseIfNotRestart(); } }); - myEditor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE); + final Editor topLevelEditor = InjectedLanguageUtil.getTopLevelEditor(myEditor); + topLevelEditor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE); final JBPopupFactory popupFactory = JBPopupFactory.getInstance(); - myBalloon.show(new PositionTracker(myEditor.getContentComponent()) { + myBalloon.show(new PositionTracker(topLevelEditor.getContentComponent()) { @Override public RelativePoint recalculateLocation(Balloon object) { - if (myTarget != null && !popupFactory.isBestPopupLocationVisible(myEditor)) { + if (myTarget != null && !popupFactory.isBestPopupLocationVisible(topLevelEditor)) { return myTarget; } - final RelativePoint target = popupFactory.guessBestPopupLocation(myEditor); + final RelativePoint target = popupFactory.guessBestPopupLocation(topLevelEditor); if (target == null) return myTarget; final Point screenPoint = target.getScreenPoint(); int y = screenPoint.y; - if (target.getPoint().getY() > myEditor.getLineHeight() + myBalloon.getPreferredSize().getHeight()) { - y -= myEditor.getLineHeight(); + if (target.getPoint().getY() > topLevelEditor.getLineHeight() + myBalloon.getPreferredSize().getHeight()) { + y -= topLevelEditor.getLineHeight(); } myTarget = new RelativePoint(new Point(screenPoint.x, y)); return myTarget; diff --git a/platform/lang-impl/src/com/intellij/ui/debugger/ShowUIDefaultsAction.java b/platform/lang-impl/src/com/intellij/ui/debugger/ShowUIDefaultsAction.java index 737f4f6da3fa..f1b11c6d469a 100644 --- a/platform/lang-impl/src/com/intellij/ui/debugger/ShowUIDefaultsAction.java +++ b/platform/lang-impl/src/com/intellij/ui/debugger/ShowUIDefaultsAction.java @@ -19,11 +19,14 @@ import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.ui.Cell; import com.intellij.ui.ColorPicker; import com.intellij.ui.ColorUtil; import com.intellij.ui.TableSpeedSearch; import com.intellij.ui.components.JBScrollPane; import com.intellij.ui.table.JBTable; +import com.intellij.util.PairFunction; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.border.Border; @@ -31,6 +34,7 @@ import javax.swing.plaf.ColorUIResource; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.DefaultTableModel; import java.awt.*; +import java.awt.event.MouseEvent; import java.util.Arrays; import java.util.Comparator; import java.util.Enumeration; @@ -76,7 +80,7 @@ public class ShowUIDefaultsAction extends AnAction { }) { @Override public boolean editCellAt(int row, int column, EventObject e) { - if (isCellEditable(row, column)) { + if (isCellEditable(row, column) && e instanceof MouseEvent) { final Object color = getValueAt(row, column); final Color newColor = ColorPicker.showDialog(this, "Choose Color", (Color)color, true, null); if (newColor != null) { @@ -107,16 +111,20 @@ public class ShowUIDefaultsAction extends AnAction { panel.setBackground(c); return panel; } else if (value instanceof Icon) { - //final Icon icon = (Icon)value; - //if (icon.getIconHeight() <= 20) { - // //label.setIcon(icon); - //} - //label.setText(String.format("(%dx%d) %s)",icon.getIconWidth(), icon.getIconHeight(), label.getText())); + try { + final Icon icon = (Icon)value; + if (icon.getIconHeight() <= 20) { + label.setIcon(icon); + } + label.setText(String.format("(%dx%d) %s)",icon.getIconWidth(), icon.getIconHeight(), label.getText())); + } + catch (Throwable e1) {// + } return panel; } else if (value instanceof Border) { try { final Insets i = ((Border)value).getBorderInsets(null); - label.setText(String.format("border[%d, %d, %d, %d] %s", i.top, i.left, i.bottom, i.right, label.getText())); + label.setText(String.format("[%d, %d, %d, %d] %s", i.top, i.left, i.bottom, i.right, label.getText())); return panel; } catch (Exception ignore) {} } @@ -124,7 +132,13 @@ public class ShowUIDefaultsAction extends AnAction { } }); final JBScrollPane pane = new JBScrollPane(table); - new TableSpeedSearch(table); + new TableSpeedSearch(table, new PairFunction() { + @Nullable + @Override + public String fun(Object o, Cell cell) { + return cell.column == 1 ? null : String.valueOf(o); + } + }); table.setShowGrid(false); final JPanel panel = new JPanel(new BorderLayout()); panel.add(pane, BorderLayout.CENTER); diff --git a/platform/platform-api/src/com/intellij/execution/configurations/ParametersList.java b/platform/platform-api/src/com/intellij/execution/configurations/ParametersList.java index ea58d2795e91..c7a03937eef3 100644 --- a/platform/platform-api/src/com/intellij/execution/configurations/ParametersList.java +++ b/platform/platform-api/src/com/intellij/execution/configurations/ParametersList.java @@ -22,8 +22,8 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.ArrayUtil; import com.intellij.util.EnvironmentUtil; -import com.intellij.util.StringBuilderSpinAllocator; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.execution.ParametersListUtil; import gnu.trove.THashMap; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -254,64 +254,27 @@ public class ParametersList implements Cloneable { } /** - *

Joins list of parameters into single string, which may be then parsed back into list by {@link #parse(String)}.

- *

- *

- * Conversion rules: - *

    - *
  • double quotes are escaped by backslash (\);
  • - *
  • empty parameters parameters and parameters with spaces inside are surrounded with double quotes (");
  • - *
  • parameters are separated by single whitespace.
  • - *
- *

- *

- *

Examples:

- *

- * ['a', 'b'] => 'a b'
- * ['a="1 2"', 'b'] => '"a \"1 2\"" b' - *

- * - * @param parameters a list of parameters to join. - * @return a string with parameters. + * @see ParametersListUtil#join(java.util.List) */ @NotNull public static String join(@NotNull final List parameters) { - return ParametersTokenizer.encode(parameters); - } - - @NotNull - public static String join(final String... parameters) { - return ParametersTokenizer.encode(Arrays.asList(parameters)); + return ParametersListUtil.join(parameters); } /** - *

Converts single parameter string (as created by {@link #join(java.util.List)}) into list of parameters.

- *

- *

- * Conversion rules: - *

    - *
  • starting/whitespaces are trimmed;
  • - *
  • parameters are split by whitespaces, whitespaces itself are dropped
  • - *
  • parameters inside double quotes ("a b") are kept as single one;
  • - *
  • double quotes are dropped, escaped double quotes (\") are un-escaped.
  • - *
- *

- *

- *

Examples:

- *

- * ' a b ' => ['a', 'b']
- * 'a="1 2" b' => ['a=1 2', 'b']
- * 'a " " b' => ['a', ' ', 'b']
- * '"a \"1 2\"" b' => ['a="1 2"', 'b'] - *

- * - * @param string parameter string to split. - * @return array of parameters. + * @see ParametersListUtil#join(java.util.List) + */ + @NotNull + public static String join(final String... parameters) { + return ParametersListUtil.join(parameters); + } + + /** + * @see ParametersListUtil#parseToArray(String) */ @NotNull public static String[] parse(@NotNull final String string) { - final List params = ParametersTokenizer.decode(string); - return ArrayUtil.toStringArray(params); + return ParametersListUtil.parseToArray(string); } public String expandMacros(String text) { @@ -356,84 +319,4 @@ public class ParametersList implements Cloneable { return myParameters.toString(); } - private static class ParametersTokenizer { - private ParametersTokenizer() { - } - - @NotNull - public static String encode(@NotNull final List parameters) { - final StringBuilder buffer = new StringBuilder(); - for (final String parameter : parameters) { - if (buffer.length() > 0) { - buffer.append(' '); - } - buffer.append(encode(parameter)); - } - return buffer.toString(); - } - - @NotNull - public static String encode(@NotNull String parameter) { - final StringBuilder builder = StringBuilderSpinAllocator.alloc(); - try { - builder.append(parameter); - StringUtil.escapeQuotes(builder); - if (builder.length() == 0 || StringUtil.indexOf(builder, ' ') >= 0 || StringUtil.indexOf(builder, '|') >= 0) { - StringUtil.quote(builder); - } - return builder.toString(); - } - finally { - StringBuilderSpinAllocator.dispose(builder); - } - } - - @NotNull - public static List decode(@NotNull String parameterString) { - parameterString = parameterString.trim(); - - final ArrayList params = ContainerUtil.newArrayList(); - final StringBuilder token = new StringBuilder(128); - boolean inQuotes = false; - boolean escapedQuote = false; - boolean nonEmpty = false; - - for (int i = 0; i < parameterString.length(); i++) { - final char ch = parameterString.charAt(i); - - if (ch == '\"') { - if (!escapedQuote) { - inQuotes = !inQuotes; - nonEmpty = true; - continue; - } - escapedQuote = false; - } - else if (Character.isWhitespace(ch)) { - if (!inQuotes) { - if (token.length() > 0 || nonEmpty) { - params.add(token.toString()); - token.setLength(0); - nonEmpty = false; - } - continue; - } - } - else if (ch == '\\') { - if (i < parameterString.length() - 1 && parameterString.charAt(i + 1) == '"') { - escapedQuote = true; - continue; - } - } - - token.append(ch); - } - - if (token.length() > 0 || nonEmpty) { - params.add(token.toString()); - } - - return params; - } - } } diff --git a/platform/platform-api/src/com/intellij/ide/util/treeView/PresentableNodeDescriptor.java b/platform/platform-api/src/com/intellij/ide/util/treeView/PresentableNodeDescriptor.java index c4add9f856f1..6816f1442adc 100644 --- a/platform/platform-api/src/com/intellij/ide/util/treeView/PresentableNodeDescriptor.java +++ b/platform/platform-api/src/com/intellij/ide/util/treeView/PresentableNodeDescriptor.java @@ -17,6 +17,7 @@ package com.intellij.ide.util.treeView; import com.intellij.ide.projectView.PresentationData; import com.intellij.openapi.project.Project; +import com.intellij.ui.Gray; import com.intellij.ui.SimpleTextAttributes; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; @@ -167,7 +168,7 @@ public abstract class PresentableNodeDescriptor extends NodeDescriptor { } public Color getHighlightColor() { - return UIUtil.isUnderDarcula() ? UIUtil.getPanelBackground().brighter() : UIUtil.getTreeBackground().brighter(); + return UIUtil.isUnderDarcula() ? Gray._100 : UIUtil.getTreeBackground().brighter(); } public static class ColoredFragment { diff --git a/platform/platform-api/src/com/intellij/xml/util/XmlStringUtil.java b/platform/platform-api/src/com/intellij/xml/util/XmlStringUtil.java index b211e11310a4..844be9811c0a 100644 --- a/platform/platform-api/src/com/intellij/xml/util/XmlStringUtil.java +++ b/platform/platform-api/src/com/intellij/xml/util/XmlStringUtil.java @@ -16,6 +16,8 @@ package com.intellij.xml.util; +import org.jetbrains.annotations.Nullable; + /** * @author yole */ @@ -23,11 +25,11 @@ public class XmlStringUtil { private XmlStringUtil() { } - public static String escapeString(String str) { + public static String escapeString(@Nullable String str) { return escapeString(str, false); } - public static String escapeString(String str, final boolean escapeWhiteSpace) { + public static String escapeString(@Nullable String str, final boolean escapeWhiteSpace) { return XmlTagUtilBase.escapeString(str, escapeWhiteSpace); } } \ No newline at end of file diff --git a/platform/platform-api/src/com/intellij/xml/util/XmlTagUtilBase.java b/platform/platform-api/src/com/intellij/xml/util/XmlTagUtilBase.java index b93a7b722e88..f3d9c9a86ae1 100644 --- a/platform/platform-api/src/com/intellij/xml/util/XmlTagUtilBase.java +++ b/platform/platform-api/src/com/intellij/xml/util/XmlTagUtilBase.java @@ -16,9 +16,10 @@ package com.intellij.xml.util; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.Nullable; public class XmlTagUtilBase { - public static String escapeString(final String str, final boolean escapeWhiteSpace) { + public static String escapeString(@Nullable final String str, final boolean escapeWhiteSpace) { if (str == null) return null; StringBuffer buffer = null; for (int i = 0; i < str.length(); i++) { diff --git a/platform/platform-impl/src/com/intellij/ide/dnd/FileCopyPasteUtil.java b/platform/platform-impl/src/com/intellij/ide/dnd/FileCopyPasteUtil.java index 215a90fd41c5..382c9736322e 100644 --- a/platform/platform-impl/src/com/intellij/ide/dnd/FileCopyPasteUtil.java +++ b/platform/platform-impl/src/com/intellij/ide/dnd/FileCopyPasteUtil.java @@ -16,6 +16,9 @@ package com.intellij.ide.dnd; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -94,8 +97,14 @@ public class FileCopyPasteUtil { public static List getFileList(@NotNull final Transferable transferable) { try { if (transferable.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) { - @SuppressWarnings({"unchecked"}) final List fileList = (List)transferable.getTransferData(DataFlavor.javaFileListFlavor); - return fileList; + @SuppressWarnings({"unchecked"}) + final List fileList = (List)transferable.getTransferData(DataFlavor.javaFileListFlavor); + return ContainerUtil.filter(fileList, new Condition() { + @Override + public boolean value(File file) { + return !StringUtil.isEmptyOrSpaces(file.getPath()); + } + }); } else { return LinuxDragAndDropSupport.getFiles(transferable); @@ -105,4 +114,5 @@ public class FileCopyPasteUtil { return null; } + } diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java index 449e2dc54eab..721770359a4e 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java @@ -21,7 +21,8 @@ import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.ColorUtil; -import org.jetbrains.annotations.Nullable; +import com.intellij.util.containers.hash.HashMap; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import javax.swing.plaf.ColorUIResource; @@ -104,8 +105,7 @@ public final class DarculaLaf extends BasicLookAndFeel { @SuppressWarnings({"HardCodedStringLiteral"}) static void initIdeaDefaults(UIDefaults defaults) { - loadDefaults(defaults, null); //load defaults - loadDefaults(defaults, SystemInfo.isMac ? "mac" : SystemInfo.isWindows ? "windows" : "linux"); // load OS customization + loadDefaults(defaults); defaults.put("Table.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] { "ctrl C", "copy", "ctrl V", "paste", @@ -158,44 +158,70 @@ public final class DarculaLaf extends BasicLookAndFeel { })); } - private static void loadDefaults(UIDefaults defaults, @Nullable String postfix) { + private static void loadDefaults(UIDefaults defaults) { + final Properties properties = new Properties(); + final String osSuffix = SystemInfo.isMac ? "mac" : SystemInfo.isWindows ? "windows" : "linux"; try { - final Properties properties = new Properties(); - final String secondPart = postfix == null ? "" : "_" + postfix; - final String name = "darcula" + secondPart + ".properties"; - final InputStream stream = DarculaLaf.class.getResourceAsStream(name); + InputStream stream = DarculaLaf.class.getResourceAsStream("darcula.properties"); properties.load(stream); + stream.close(); + + stream = DarculaLaf.class.getResourceAsStream("darcula_" + osSuffix + ".properties"); + properties.load(stream); + stream.close(); + + HashMap darculaGlobalSettings = new HashMap(); + final String prefix = "darcula."; for (String key : properties.stringPropertyNames()) { - final String value = properties.getProperty(key); - if (key.endsWith("Insets")) { - final List numbers = StringUtil.split(value, ","); - defaults.put(key, new InsetsUIResource(Integer.parseInt(numbers.get(0)), - Integer.parseInt(numbers.get(1)), - Integer.parseInt(numbers.get(2)), - Integer.parseInt(numbers.get(3)))); - } else if (key.endsWith(".border")) { - try { - defaults.put(key, Class.forName(value).newInstance()); - } catch (Exception e) {log(e);} - } else { - final Color color = ColorUtil.fromHex(value, null); - final Integer invVal = getInteger(value); - Icon icon = value != null && value.startsWith("AllIcons.") ? IconLoader.getIcon(value) : null; - if (color != null) { - defaults.put(key, new ColorUIResource(color)); - } else if (invVal != null) { - defaults.put(key, invVal); - } else if (icon != null) { - defaults.put(key, new IconUIResource(icon)); - } else { - defaults.put(key, value); + if (key.startsWith(prefix)) { + darculaGlobalSettings.put(key.substring(prefix.length()), parseValue(key, properties.getProperty(key))); + } + } + + for (Object key : defaults.keySet()) { + if (key instanceof String && ((String)key).contains(".")) { + final String s = (String)key; + final String darculaKey = s.substring(s.lastIndexOf('.') + 1); + if (darculaGlobalSettings.containsKey(darculaKey)) { + defaults.put(key, darculaGlobalSettings.get(darculaKey)); } } } + + for (String key : properties.stringPropertyNames()) { + final String value = properties.getProperty(key); + defaults.put(key, parseValue(key, value)); + } } catch (IOException e) {log(e);} } + private static Object parseValue(String key, @NotNull String value) { + if (key.endsWith("Insets")) { + final List numbers = StringUtil.split(value, ","); + return new InsetsUIResource(Integer.parseInt(numbers.get(0)), + Integer.parseInt(numbers.get(1)), + Integer.parseInt(numbers.get(2)), + Integer.parseInt(numbers.get(3))); + } else if (key.endsWith(".border")) { + try { + return Class.forName(value).newInstance(); + } catch (Exception e) {log(e);} + } else { + final Color color = ColorUtil.fromHex(value, null); + final Integer invVal = getInteger(value); + Icon icon = value.startsWith("AllIcons.") ? IconLoader.getIcon(value) : null; + if (color != null) { + return new ColorUIResource(color); + } else if (invVal != null) { + return invVal; + } else if (icon != null) { + return new IconUIResource(icon); + } + } + return value; + } + private static Integer getInteger(String value) { try { return Integer.parseInt(value); diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties index a767d6aef668..9a1a2bee2097 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties @@ -1,84 +1,50 @@ +darcula.background=535353 +darcula.textBackground=535353 +darcula.foreground=eeeeee +darcula.textForeground=eeeeee +darcula.caretForeground=eeeeee + text=eeeeee Menu.maxGutterIconWidth=18 MenuItem.maxGutterIconWidth=18 MenuItem.acceleratorDelimiter=- -#Trees -Tree.background=535353 -Tree.foreground=eeeeee -Tree.textForeground=eeeeee -Tree.textBackground=535353 -#Tree.selectionBackground=BEBEBE -#Tree.selectionForeground=535353 - -EditorPane.background=535353 EditorPane.inactiveBackground=535353 -EditorPane.foreground=eeeeee EditorPane.inactiveForeground=eeeeee EditorPaneUI=com.intellij.ide.ui.laf.darcula.ui.DarculaEditorPaneUI -#Lists -List.background=535353 -List.foreground=eeeeee -#Tables -Table.background=535353 -Table.foreground=eeeeee control=535353 -Panel.background=535353 -Panel.foreground=eeeeee + +ScrollBarUI=com.intellij.ide.ui.laf.darcula.ui.DarculaScrollBarUI + Menu.selectionBackground=bebebe -MenuBar.background=535353 MenuBar.disabledBackground=535353 MenuBar.shadow=535353 -Menu.background=535353 -MenuItem.background=535353 -Menu.foreground=eeeeee -MenuItem.foreground=eeeeee TabbedPane.tabInsets=0,4,0,4 -ToggleButton.foreground=eeeeee -Separator.background=535353 Separator.foreground=888888 -Label.background=535353 -Label.foreground=eeeeee Focus.color=ff0000 -TextField.background=535353 -TextField.foreground=eeeeee -TextField.caretForeground=eeeeee -#TextFieldUI=com.intellij.ide.ui.laf.darcula.ui.DarculaTextFieldUI +TextField.background=737373 +TextFieldUI=com.intellij.ide.ui.laf.darcula.ui.DarculaTextFieldUI +TextField.border=com.intellij.ide.ui.laf.darcula.ui.DarculaTextBorder -PasswordField.background=535353 -PasswordField.foreground=eeeeee -PasswordField.caretForeground=eeeeee +PasswordField.background=aaaaaa -TextArea.background=535353 -TextArea.foreground=eeeeee -TextArea.caretForeground=eeeeee - -TextPane.background=535353 -TextPane.foreground=eeeeee -TextPane.caretForeground=eeeeee - -CheckBox.background=535353 -CheckBox.foreground=eeeeee CheckBoxUI=com.intellij.ide.ui.laf.darcula.ui.DarculaCheckBoxUI - -RadioButton.foreground=eeeeee -RadioButton.background=535353 +#ComboBoxUI=com.intellij.ide.ui.laf.darcula.ui.DarculaComboBoxUI +ComboBox.background=eeeeee +ComboBox.foreground=000000 RadioButtonUI=com.intellij.ide.ui.laf.darcula.ui.DarculaRadioButtonUI StatusBar.topColor=2c2c2c StatusBar.top2Color=2c2c2c StatusBar.bottomColor=2c2c2c -Button.foreground=eeeeee -Button.background=535353 Button.border=com.intellij.ide.ui.laf.darcula.ui.DarculaButtonPainter #ButtonUI=com.intellij.ide.ui.laf.borders.DarculaButtonUI MenuItem.acceleratorForeground=eeeeee -PopupMenu.background=535353 PopupMenu.translucentBackground=535353 diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaButtonPainter.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaButtonPainter.java index 6c4e03292e74..b571c8e5a78c 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaButtonPainter.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaButtonPainter.java @@ -63,6 +63,6 @@ public class DarculaButtonPainter implements Border, UIResource { @Override public boolean isBorderOpaque() { - return false; + return true; } } diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaComboBoxButton.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaComboBoxButton.java new file mode 100644 index 000000000000..3669d47c86aa --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaComboBoxButton.java @@ -0,0 +1,56 @@ +/* + * Copyright 2000-2012 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.ide.ui.laf.darcula.ui; + +import com.intellij.icons.AllIcons; + +import javax.swing.*; +import javax.swing.plaf.basic.BasicButtonUI; +import java.awt.*; + +/** + * @author Konstantin Bulenkov + */ +public class DarculaComboBoxButton extends JButton { + private final JComboBox myComboBox; + + public DarculaComboBoxButton(JComboBox comboBox) { + myComboBox = comboBox; + setUI(new BasicButtonUI() { + @Override + public void paint(Graphics g, JComponent c) { + final Icon i; + if (myComboBox.isEditable()) { + g.drawLine(0,0,0,c.getHeight()); + i = AllIcons.Mac.Tree_white_down_arrow; + } else { + i = AllIcons.Ide.Statusbar_arrows; + } + i.paintIcon(c, g, (c.getWidth() - i.getIconWidth()) / 2, (c.getHeight() - i.getIconHeight()) / 2); + } + + @Override + public Dimension getPreferredSize(JComponent c) { + return super.getPreferredSize(c); + } + }); + } + + @Override + protected void paintComponent(Graphics g) { + super.paintComponent(g); + } +} diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaComboBoxUI.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaComboBoxUI.java new file mode 100644 index 000000000000..f9a5b2b6144c --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaComboBoxUI.java @@ -0,0 +1,88 @@ +/* + * Copyright 2000-2012 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.ide.ui.laf.darcula.ui; + +import javax.swing.*; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicComboBoxUI; +import java.awt.*; + +/** + * @author Konstantin Bulenkov + */ +public class DarculaComboBoxUI extends BasicComboBoxUI { + private final JComboBox myComboBox; + + public DarculaComboBoxUI(JComboBox c) { + myComboBox = c; + c.setBorder(null); + } + + @SuppressWarnings({"MethodOverridesStaticMethodOfSuperclass", "UnusedDeclaration"}) + public static ComponentUI createUI(JComponent c) { + return new DarculaComboBoxUI(((JComboBox)c)); + } + + @Override + protected LayoutManager createLayoutManager() { + return new DarculaComboBoxLayoutManager(); + } + + @Override + public void paintCurrentValueBackground(Graphics g, Rectangle bounds, boolean hasFocus) { + super.paintCurrentValueBackground(g, bounds, false); + } + + @Override + public void paint(Graphics g, JComponent c) { + super.paint(g, c); + } + + @Override + protected JButton createArrowButton() { + return new DarculaComboBoxButton(myComboBox); + } + + class DarculaComboBoxLayoutManager extends BasicComboBoxUI.ComboBoxLayoutManager { + public void layoutContainer(final Container parent) { + if (arrowButton != null && !comboBox.isEditable()) { + final Insets insets = comboBox.getInsets(); + final int width = comboBox.getWidth(); + final int height = comboBox.getHeight(); + arrowButton.setBounds(insets.left, insets.top, width - (insets.left + insets.right), height - (insets.top + insets.bottom)); + return; + } + + final JComboBox cb = (JComboBox)parent; + final int width = cb.getWidth(); + final int height = cb.getHeight(); + + final Insets insets = getInsets(); + final int buttonHeight = height - (insets.top + insets.bottom); + final int buttonWidth = 20; + + if (arrowButton != null) { + arrowButton.setBounds(width - (insets.right + buttonWidth), insets.top, buttonWidth, buttonHeight); + } + + if (editor != null) { + final Rectangle editorRect = rectangleForCurrentValue(); + editorRect.width += 4; + editor.setBounds(editorRect); + } + } + } +} diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaScrollBarUI.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaScrollBarUI.java new file mode 100644 index 000000000000..39704f20de1d --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaScrollBarUI.java @@ -0,0 +1,32 @@ +/* + * Copyright 2000-2012 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.ide.ui.laf.darcula.ui; + +import com.intellij.util.ui.ButtonlessScrollBarUI; + +import javax.swing.*; +import javax.swing.plaf.ComponentUI; + +/** + * @author Konstantin Bulenkov + */ +public class DarculaScrollBarUI extends ButtonlessScrollBarUI { + + @SuppressWarnings({"MethodOverridesStaticMethodOfSuperclass", "UnusedDeclaration"}) + public static ComponentUI createUI(JComponent c) { + return new DarculaScrollBarUI(); + } +} diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTest.form b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTest.form new file mode 100644 index 000000000000..f79276e2ca53 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTest.form @@ -0,0 +1,417 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTest.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTest.java new file mode 100644 index 000000000000..75fb440d792a --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTest.java @@ -0,0 +1,58 @@ +/* + * Copyright 2000-2012 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.ide.ui.laf.darcula.ui; + +import com.intellij.ide.ui.laf.darcula.DarculaLaf; +import com.intellij.ui.components.JBCheckBox; + +import javax.swing.*; + +/** + * @author Konstantin Bulenkov + */ +public class DarculaTest { + private JBCheckBox myJBCheckBox1; + private JBCheckBox myJBCheckBox2; + private JBCheckBox myJBCheckBox3; + private JBCheckBox myJBCheckBox4; + private JBCheckBox myJBCheckBox5; + private JComboBox myComboBox1; + private JComboBox myComboBox2; + private JComboBox myComboBox3; + private JComboBox myComboBox4; + private JComboBox myComboBox5; + private JTextField myTextField1; + private JTextField myThisTextIsDisabledTextField; + private JPasswordField myPasswordField1; + private JPanel myRoot; + + public static void main(String[] args) { + try { + UIManager.setLookAndFeel(new DarculaLaf()); + } + catch (UnsupportedLookAndFeelException ignored) {} + final JFrame frame = new JFrame("Darcula Demo"); + frame.setSize(600, 500); + frame.setContentPane(new DarculaTest().myRoot); + frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + frame.setVisible(true); + } + }); + } +} diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTextBorder.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTextBorder.java new file mode 100644 index 000000000000..65f1993bcc8c --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTextBorder.java @@ -0,0 +1,82 @@ +/* + * Copyright 2000-2012 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.ide.ui.laf.darcula.ui; + +import com.intellij.ide.ui.laf.darcula.DarculaUIUtil; +import com.intellij.openapi.ui.GraphicsConfig; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.ui.ColorUtil; +import com.intellij.util.ui.JBInsets; + +import javax.swing.border.Border; +import javax.swing.plaf.UIResource; +import java.awt.*; + +/** + * @author Konstantin Bulenkov + */ +public class DarculaTextBorder implements Border, UIResource { + private JBInsets myInsets = new JBInsets(4, 7, 4, 7); + + @Override + public JBInsets getBorderInsets(Component c) { + return myInsets; + } + + @Override + public boolean isBorderOpaque() { + return false; + } + + @Override + public void paintBorder(Component c, Graphics g2, int x, int y, int width, int height) { + Graphics2D g = ((Graphics2D)g2); + g.setColor(ColorUtil.fromHex("737373")); + int cX = myInsets.right; + int cY = myInsets.top; + int cW = width - myInsets.width(); + int cH = height - myInsets.height(); + final GraphicsConfig config = new GraphicsConfig(g); + g.translate(x, y); + + if (c.hasFocus()) { + int sysOffX = SystemInfo.isMac ? 0 : 1; + int sysOffY = SystemInfo.isMac ? 0 : -1; + DarculaUIUtil.paintFocusRing(g, 2, 2, width-4, height-4); + + //g.setColor(DarculaUIUtil.GLOW_COLOR.darker().darker()); + //g.drawRect(1, 1, width - 2, height - 2); + //g.drawRect(2, 2, width-4, height-4); + //g.setColor(ColorUtil.toAlpha(DarculaUIUtil.GLOW_COLOR, 70)); + //g.drawRoundRect(0, 0, width, height, 5, 5); + //g.setColor(ColorUtil.toAlpha(DarculaUIUtil.GLOW_COLOR, 80)); + //g.drawRoundRect(1, 1, width - 2, height-2, 5, 5); + //g.setColor(ColorUtil.toAlpha(DarculaUIUtil.GLOW_COLOR, 120)); + //g.drawRoundRect(2, 2, width - 4, height - 4, 5, 5); + //g.setColor(ColorUtil.toAlpha(DarculaUIUtil.GLOW_COLOR, 140)); + //g.drawRoundRect(3, 2, width - 6, height - 4, 5, 5); + } else { + //g.fillRect(2, 1, cX-2, height - 2); //left + //g.fillRect(cX + cW , 1, width-cW - cX, height - 2); //right + //g.fillRect(1, 1, width - 2, cY); //top + //g.fillRect(1, cY + cH, width - 2, height - 2); //bottom + g.setColor(ColorUtil.fromHex("939393")); + g.drawRect(1, 1, width - 2, height - 2); + } + g.translate(-x, -y); + config.restore(); + } +} diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTextFieldUI.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTextFieldUI.java index 6ce1da2d01d3..04cbd44f9107 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTextFieldUI.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTextFieldUI.java @@ -15,9 +15,17 @@ */ package com.intellij.ide.ui.laf.darcula.ui; +import com.intellij.openapi.ui.GraphicsConfig; +import com.intellij.util.ui.JBInsets; + import javax.swing.*; +import javax.swing.border.Border; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicTextFieldUI; +import javax.swing.text.JTextComponent; +import java.awt.*; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; /** * @author Konstantin Bulenkov @@ -25,7 +33,57 @@ import javax.swing.plaf.basic.BasicTextFieldUI; public class DarculaTextFieldUI extends BasicTextFieldUI { @SuppressWarnings("MethodOverridesStaticMethodOfSuperclass") - public static ComponentUI createUI(JComponent c) { + public static ComponentUI createUI(final JComponent c) { + c.addFocusListener(new FocusAdapter() { + @Override + public void focusGained(FocusEvent e) { + c.repaint(); + } + + @Override + public void focusLost(FocusEvent e) { + c.repaint(); + } + }); return new DarculaTextFieldUI(); } + + @Override + protected void installDefaults() { + super.installDefaults(); + } + + @Override + protected void paintSafely(Graphics g) { + super.paintSafely(g); + } + + @Override + protected void paintBackground(Graphics g) { + final JTextComponent c = getComponent(); + final Container parent = c.getParent(); + if (parent != null) { + g.setColor(parent.getBackground()); + g.fillRect(0,0,c.getWidth(), c.getHeight()); + } + final Border border = c.getBorder(); + if (border instanceof DarculaTextBorder) { + g.setColor(c.getBackground()); + final int width = c.getWidth(); + final int height = c.getHeight(); + final JBInsets insets = ((DarculaTextBorder)border).getBorderInsets(c); + if (c.hasFocus()) { + final GraphicsConfig config = new GraphicsConfig(g); + ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE); + + g.fillRoundRect(insets.left-5, insets.top-2, width - insets.width() + 10, height - insets.height() + 6, 5, 5); + config.restore(); + } else { + g.fillRect(insets.left-5, insets.top-2, width - insets.width() + 12, height - insets.height() + 6); + } + } else { + super.paintBackground(g); + } + } } diff --git a/platform/platform-impl/src/com/intellij/internal/anomalies/TopAnomaliesAction.java b/platform/platform-impl/src/com/intellij/internal/anomalies/TopAnomaliesAction.java new file mode 100644 index 000000000000..e6e892dad43f --- /dev/null +++ b/platform/platform-impl/src/com/intellij/internal/anomalies/TopAnomaliesAction.java @@ -0,0 +1,273 @@ +/* + * Copyright 2000-2012 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.internal.anomalies; + +import com.intellij.openapi.Disposable; +import com.intellij.openapi.actionSystem.ActionGroup; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.objectTree.ObjectNode; +import com.intellij.openapi.util.objectTree.ObjectTree; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.awt.*; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.*; + +/** + * User: Vassiliy.Kudryashov + */ +public class TopAnomaliesAction extends ActionGroup { + private static final Comparator> COMPARATOR = new Comparator>() { + @Override + public int compare(Pair o1, Pair o2) { + int i = o2.getSecond() - o1.getSecond(); + if (i != 0) { + return i; + } + int h1 = o1.hashCode(); + int h2 = o2.hashCode(); + if (h1 > h2) { + return 1; + } + if (h1 < h2) { + return -1; + } + return 0; + } + }; + private static final int LIMIT = 10; + + private static final ResettableAction TOP_PARENTS = new ResettableAction("Parents") { + TreeSet> top = new TreeSet>(COMPARATOR); + TreeSet> old = new TreeSet>(COMPARATOR); + + @Override + public void update(AnActionEvent e) { + e.getPresentation().setText("Top " + LIMIT + " component parents"); + } + + @Override + void reset() { + top.clear(); + old.clear(); + } + + @Override + public void actionPerformed(AnActionEvent e) { + old = new TreeSet>(top); + top.clear(); + Window[] windows = Window.getWindows(); + for (Window window : windows) { + if (window.isVisible() && (window instanceof JFrame)) { + JFrame f = (JFrame)window; + checkParents((JComponent)f.getContentPane(), top, LIMIT); + } + } + + System.out.println("Top " + LIMIT + " component parents"); + for (Pair pair : top) { + System.out.println( + pair.first.getClass().getName() + " (" + pair.second + " children)" + getChange(old, pair.first, pair.second)); + } + } + + private void checkParents(JComponent component, Set> top, int limit) { + top.add(Pair.create(component, component.getComponentCount())); + + trimToLimit(top, limit); + + for (int i = 0; i < component.getComponentCount(); i++) { + Component child = component.getComponent(i); + if (child instanceof JComponent) { + checkParents((JComponent)child, top, limit); + } + } + } + }; + + private static final ResettableAction TOP_UI_PROPERTIES = new ResettableAction("ClientProperties") { + TreeSet> top = new TreeSet>(COMPARATOR); + TreeSet> old = new TreeSet>(COMPARATOR); + + @Override + public void update(AnActionEvent e) { + e.getPresentation().setText("Top " + LIMIT + " ClientProperties"); + } + + @Override + void reset() { + top.clear(); + old.clear(); + } + + @Override + public void actionPerformed(AnActionEvent e) { + old = new TreeSet>(top); + top.clear(); + Window[] windows = Window.getWindows(); + for (Window window : windows) { + if (window.isVisible() && (window instanceof JFrame)) { + JFrame f = (JFrame)window; + checkClientProperties((JComponent)f.getContentPane(), top, LIMIT); + } + } + System.out.println("Top " + LIMIT + " ClientProperties"); + for (Pair pair : top) { + System.out.println(pair.first.getClass().getName() + " (" + pair.second + " properties)" + getChange(old, pair.first, pair.second)); + } + } + + private void checkClientProperties(JComponent component, Set> top, int limit) { + try { + Field clientProperties = JComponent.class.getDeclaredField("clientProperties"); + clientProperties.setAccessible(true); + Object o = clientProperties.get(component); + if (o != null) { + Method size = o.getClass().getMethod("size"); + size.setAccessible(true); + Object sizeResult = size.invoke(o); + if (sizeResult instanceof Integer) { + top.add(Pair.create(component, (Integer)sizeResult)); + trimToLimit(top, limit); + } + } + } + catch (NoSuchMethodException e) { + } + catch (InvocationTargetException e) { + } + catch (IllegalAccessException e) { + } + catch (NoSuchFieldException e) { + } + for (int i = 0; i < component.getComponentCount(); i++) { + Component child = component.getComponent(i); + if (child instanceof JComponent) { + checkClientProperties((JComponent)child, top, limit); + } + } + } + }; + + private static final ResettableAction TOP_DISPOSABLE = new ResettableAction("Disposable") { + TreeSet> top = new TreeSet>(COMPARATOR); + TreeSet> old = new TreeSet>(COMPARATOR); + + @Override + public void update(AnActionEvent e) { + e.getPresentation().setText("Top " + LIMIT + " disposables"); + } + + @Override + void reset() { + top.clear(); + old.clear(); + } + + @Override + public void actionPerformed(AnActionEvent e) { + old = new TreeSet>(top); + top.clear(); + ObjectTree tree = Disposer.getTree(); + Set roots = tree.getRootObjects(); + for (Disposable root : roots) { + checkDisposables(tree, root, top, LIMIT); + } + System.out.println("Top " + LIMIT + " disposables"); + for (Pair pair : top) { + System.out.println(pair.first.getClass().getName() + " (" + pair.second + " related)" + getChange(old, pair.first, pair.second)); + } + } + + private void checkDisposables(ObjectTree tree, Object key, Set> top, int limit) { + ObjectNode node = tree.getNode(key); + if (node == null) { + return; + } + Collection children = node.getChildren(); + top.add(Pair.create(key, children.size())); + trimToLimit(top, limit); + for (Object child : children) { + checkDisposables(tree, child, top, limit); + } + } + }; + + private static final ResettableAction RESET_THEM_ALL = new ResettableAction("Reset statistics") { + @Override + void reset() { + } + + @Override + public void actionPerformed(AnActionEvent e) { + for (ResettableAction action : CHILDREN) { + action.reset(); + } + } + }; + + private static ResettableAction[] CHILDREN = {TOP_PARENTS, TOP_UI_PROPERTIES, TOP_DISPOSABLE, RESET_THEM_ALL}; + + @Override + public void update(AnActionEvent e) { + e.getPresentation().setText("Top " + LIMIT); + } + + @NotNull + @Override + public AnAction[] getChildren(@Nullable AnActionEvent e) { + return CHILDREN; + } + + private static void trimToLimit(Set> top, int limit) { + int k = 0; + for (Iterator> iterator = top.iterator(); iterator.hasNext(); ) { + k++; + iterator.next(); + if (k >= limit) { + iterator.remove(); + } + } + } + + private static String getChange(Set> old, K key, int newResult) { + for (Pair oldPair : old) { + if (oldPair.first == key) { + int oldResult = oldPair.second.intValue(); + if (oldResult != newResult) { + return (oldResult > newResult ? " -" : " +") + Math.abs(newResult - oldResult); + } + break; + } + } + return ""; + } + + private static abstract class ResettableAction extends AnAction { + protected ResettableAction(@Nullable String text) { + super(text); + } + + abstract void reset(); + } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java index 7366a191e09e..e8d710a22114 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java @@ -179,14 +179,30 @@ public class DumbServiceImpl extends DumbService { if (!wasDumb) { // always change dumb status inside write action. // This will ensure all active read actions are completed before the app goes dumb + final Ref startFailure = new Ref(Boolean.FALSE); application.runWriteAction(new Runnable() { public void run() { myDumb = true; - myPublisher.enteredDumbMode(); - - updateRunnable.run(); + try { + myPublisher.enteredDumbMode(); + } + catch (Throwable e) { + LOG.error(e); + } + finally { + try { + updateRunnable.run(); + } + catch (Throwable e) { + startFailure.set(Boolean.TRUE); + LOG.error("Failed to start background index update task", e); + } + } } }); + if (startFailure.get()) { + updateFinished(); + } } else { myUpdatesQueue.addLast(updateRunnable); @@ -197,23 +213,27 @@ public class DumbServiceImpl extends DumbService { private void updateFinished() { myDumb = false; - if (!myProject.isDisposed()) { - myPublisher.exitDumbMode(); - FileEditorManagerEx.getInstanceEx(myProject).refreshIcons(); + try { + if (!myProject.isDisposed()) { + myPublisher.exitDumbMode(); + FileEditorManagerEx.getInstanceEx(myProject).refreshIcons(); + } } - while (true) { - final Runnable runnable; - synchronized (myRunWhenSmartQueue) { - if (myRunWhenSmartQueue.isEmpty()) { - break; + finally { + while (true) { + final Runnable runnable; + synchronized (myRunWhenSmartQueue) { + if (myRunWhenSmartQueue.isEmpty()) { + break; + } + runnable = myRunWhenSmartQueue.pullFirst(); + } + try { + runnable.run(); + } + catch (Throwable e) { + LOG.error(e); } - runnable = myRunWhenSmartQueue.pullFirst(); - } - try { - runnable.run(); - } - catch (Throwable e) { - LOG.error(e); } } } @@ -278,10 +298,6 @@ public class DumbServiceImpl extends DumbService { } public void run() { - if (myProject.isDisposed()) { - return; - } - ProgressManager.getInstance().run(new Task.Backgroundable(myProject, IdeBundle.message("progress.indexing"), false) { private final BlockingQueue> myActionQueue = new LinkedBlockingQueue>(); @@ -358,7 +374,7 @@ public class DumbServiceImpl extends DumbService { finally { myProcessedItems += count; if (LOG.isDebugEnabled()) { - LOG.debug("Scheduling checkNextUpdateFromQueue"); + LOG.debug("Scheduling checkNextUpdateFromQueue; Thread: " + Thread.currentThread().getName()); } UIUtil.invokeLaterIfNeeded(new DumbAwareRunnable() { public void run() { @@ -389,7 +405,7 @@ public class DumbServiceImpl extends DumbService { private void checkNextUpdateFromQueue() { if (LOG.isDebugEnabled()) { - LOG.debug("Inside checkNextUpdateFromQueue"); + LOG.debug("Inside checkNextUpdateFromQueue, Thread: " + Thread.currentThread().getName()); } IndexUpdateRunnable nextUpdateRunnable = null; try { diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java index fe04d1b429bb..ab31cbcd2f9f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java @@ -261,7 +261,13 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt return message; } - private static void initProject(ProjectImpl project, @Nullable ProjectImpl template) throws IOException { + private void initProject(@NotNull ProjectImpl project, @Nullable ProjectImpl template) throws IOException { + + final ProgressIndicator indicator = myProgressManager.getProgressIndicator(); + if (indicator != null) { + indicator.setText(ProjectBundle.message("loading.components.for", project.isDefault() ? "Default" : project.getName())); + indicator.setIndeterminate(true); + } ApplicationManager.getApplication().getMessageBus().syncPublisher(ProjectLifecycleListener.TOPIC).beforeProjectLoaded(project); @@ -311,7 +317,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt public Project loadProject(String filePath) throws IOException, JDOMException, InvalidDataException { try { ProjectImpl project = createProject(null, filePath, false, false); - doLoadProject(filePath, project); + initProject(project, null); return project; } catch (StateStorageException e) { @@ -319,16 +325,6 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt } } - private void doLoadProject(String filePath, ProjectImpl project) throws IOException, StateStorageException { - filePath = toCanonicalName(filePath); - final ProgressIndicator indicator = myProgressManager.getProgressIndicator(); - if (indicator != null) { - indicator.setText(ProjectBundle.message("loading.components.for", FileUtil.toSystemDependentName(filePath))); - indicator.setIndeterminate(true); - } - initProject(project, null); - } - @NotNull private static String toCanonicalName(@NotNull final String filePath) { try { @@ -540,7 +536,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt @Override @Nullable public Project compute() throws IOException { - doLoadProject(filePath, project); + initProject(project, null); return project; } }, ProjectBundle.message("project.load.progress"), true, project); diff --git a/platform/platform-resources/src/idea/PlatformActions.xml b/platform/platform-resources/src/idea/PlatformActions.xml index 76548ac14f6a..43099147515f 100644 --- a/platform/platform-resources/src/idea/PlatformActions.xml +++ b/platform/platform-resources/src/idea/PlatformActions.xml @@ -547,6 +547,7 @@ + diff --git a/platform/testRunner/src/com/intellij/execution/testframework/CompositePrintable.java b/platform/testRunner/src/com/intellij/execution/testframework/CompositePrintable.java index 8385499e86df..220bfd917393 100644 --- a/platform/testRunner/src/com/intellij/execution/testframework/CompositePrintable.java +++ b/platform/testRunner/src/com/intellij/execution/testframework/CompositePrintable.java @@ -261,7 +261,10 @@ public class CompositePrintable implements Printable, Disposable { @Override public void print(String text, ConsoleViewContentType contentType) { try { - IOUtil.writeString(contentType.toString() + text, getFileWriter()); + final DataOutputStream writer = getFileWriter(); + if (writer != null) { + IOUtil.writeString(contentType.toString() + text, writer); + } } catch (FileNotFoundException e) { LOG.info(e); @@ -276,11 +279,13 @@ public class CompositePrintable implements Printable, Disposable { if (info instanceof DiffHyperlink.DiffHyperlinkInfo) { final DiffHyperlink diffHyperlink = ((DiffHyperlink.DiffHyperlinkInfo)info).getPrintable(); try { - DataOutputStream fileWriter = getFileWriter(); - IOUtil.writeString(HYPERLINK, fileWriter); - IOUtil.writeString(diffHyperlink.getLeft(), fileWriter); - IOUtil.writeString(diffHyperlink.getRight(), fileWriter); - IOUtil.writeString(diffHyperlink.getFilePath(), fileWriter); + final DataOutputStream fileWriter = getFileWriter(); + if (fileWriter != null) { + IOUtil.writeString(HYPERLINK, fileWriter); + IOUtil.writeString(diffHyperlink.getLeft(), fileWriter); + IOUtil.writeString(diffHyperlink.getRight(), fileWriter); + IOUtil.writeString(diffHyperlink.getFilePath(), fileWriter); + } } catch (FileNotFoundException e) { LOG.info(e); diff --git a/platform/util/src/com/intellij/util/execution/ParametersListUtil.java b/platform/util/src/com/intellij/util/execution/ParametersListUtil.java new file mode 100644 index 000000000000..9d8ac99297c1 --- /dev/null +++ b/platform/util/src/com/intellij/util/execution/ParametersListUtil.java @@ -0,0 +1,171 @@ +/* + * Copyright 2000-2012 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.util.execution; + +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.ArrayUtil; +import com.intellij.util.StringBuilderSpinAllocator; +import com.intellij.util.containers.ContainerUtilRt; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * @author nik + */ +public class ParametersListUtil { + /** + *

Joins list of parameters into single string, which may be then parsed back into list by {@link #parseToArray(String)}.

+ *

+ *

+ * Conversion rules: + *

    + *
  • double quotes are escaped by backslash (\);
  • + *
  • empty parameters parameters and parameters with spaces inside are surrounded with double quotes (");
  • + *
  • parameters are separated by single whitespace.
  • + *
+ *

+ *

+ *

Examples:

+ *

+ * ['a', 'b'] => 'a b'
+ * ['a="1 2"', 'b'] => '"a \"1 2\"" b' + *

+ * + * @param parameters a list of parameters to join. + * @return a string with parameters. + */ + @NotNull + public static String join(@NotNull final List parameters) { + return encode(parameters); + } + + @NotNull + public static String join(final String... parameters) { + return encode(Arrays.asList(parameters)); + } + + /** + * @see #parse(String) + */ + @NotNull + public static String[] parseToArray(@NotNull final String string) { + final List params = parse(string); + return ArrayUtil.toStringArray(params); + } + + /** + *

Converts single parameter string (as created by {@link #join(java.util.List)}) into list of parameters.

+ *

+ *

+ * Conversion rules: + *

    + *
  • starting/whitespaces are trimmed;
  • + *
  • parameters are split by whitespaces, whitespaces itself are dropped
  • + *
  • parameters inside double quotes ("a b") are kept as single one;
  • + *
  • double quotes are dropped, escaped double quotes (\") are un-escaped.
  • + *
+ *

+ *

+ *

Examples:

+ *

+ * ' a b ' => ['a', 'b']
+ * 'a="1 2" b' => ['a=1 2', 'b']
+ * 'a " " b' => ['a', ' ', 'b']
+ * '"a \"1 2\"" b' => ['a="1 2"', 'b'] + *

+ * + * @param string parameter string to split. + * @return array of parameters. + */ + @NotNull + public static List parse(@NotNull String parameterString) { + parameterString = parameterString.trim(); + + final ArrayList params = ContainerUtilRt.newArrayList(); + final StringBuilder token = new StringBuilder(128); + boolean inQuotes = false; + boolean escapedQuote = false; + boolean nonEmpty = false; + + for (int i = 0; i < parameterString.length(); i++) { + final char ch = parameterString.charAt(i); + + if (ch == '\"') { + if (!escapedQuote) { + inQuotes = !inQuotes; + nonEmpty = true; + continue; + } + escapedQuote = false; + } + else if (Character.isWhitespace(ch)) { + if (!inQuotes) { + if (token.length() > 0 || nonEmpty) { + params.add(token.toString()); + token.setLength(0); + nonEmpty = false; + } + continue; + } + } + else if (ch == '\\') { + if (i < parameterString.length() - 1 && parameterString.charAt(i + 1) == '"') { + escapedQuote = true; + continue; + } + } + + token.append(ch); + } + + if (token.length() > 0 || nonEmpty) { + params.add(token.toString()); + } + + return params; + } + + @NotNull + private static String encode(@NotNull final List parameters) { + final StringBuilder buffer = new StringBuilder(); + for (final String parameter : parameters) { + if (buffer.length() > 0) { + buffer.append(' '); + } + buffer.append(encode(parameter)); + } + return buffer.toString(); + } + + @NotNull + private static String encode(@NotNull String parameter) { + final StringBuilder builder = StringBuilderSpinAllocator.alloc(); + try { + builder.append(parameter); + StringUtil.escapeQuotes(builder); + if (builder.length() == 0 || StringUtil.indexOf(builder, ' ') >= 0 || StringUtil.indexOf(builder, '|') >= 0) { + StringUtil.quote(builder); + } + return builder.toString(); + } + finally { + StringBuilderSpinAllocator.dispose(builder); + } + } +} diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/ObjectsConvertor.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/ObjectsConvertor.java index 282a4900a12a..0f5645adf4fb 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/ObjectsConvertor.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/ObjectsConvertor.java @@ -74,24 +74,24 @@ public class ObjectsConvertor { private ObjectsConvertor() { } - public static List fp2vf(final Collection in) { + public static List fp2vf(@NotNull final Collection in) { return convert(in, FILEPATH_TO_VIRTUAL); } - public static List vf2fp(final List in) { + public static List vf2fp(@NotNull final List in) { return convert(in, VIRTUAL_FILEPATH); } - public static List fp2jiof(final Collection in) { + public static List fp2jiof(@NotNull final Collection in) { return convert(in, FILEPATH_FILE); } - public static List convert(final Collection in, final Convertor convertor) { + public static List convert(@NotNull final Collection in, final Convertor convertor) { return convert(in, convertor, null); } - public static List convert(final Collection in, final Convertor convertor, - @Nullable final NotNullFunction outFilter) { + public static List convert(@NotNull final Collection in, final Convertor convertor, + @Nullable final NotNullFunction outFilter) { final List out = new ArrayList(); for (T t : in) { final S converted = convertor.convert(t); diff --git a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties index d621336c5735..7509709015be 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties +++ b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties @@ -1337,6 +1337,7 @@ switch.statement.with.too.few.branches.problem.descriptor='#ref' ha switch.statement.without.default.ignore.option=Ignore if all cases of an enumerated type are covered unnecessary.label.remove.quickfix=Remove label unnecessary.return.problem.descriptor=#ref is unnecessary as the last statement in a 'void' method #loc +unnecessary.return.constructor.problem.descriptor=#ref is unnecessary as the last statement in a constructor #loc unused.label.remove.quickfix=Remove unused label unnecessarily.qualified.static.usage.problem.descriptor=Unnecessarily qualified static method call #ref() #loc unnecessarily.qualified.static.usage.problem.descriptor1=Unnecessarily qualified static access #ref #loc @@ -1945,7 +1946,7 @@ parameter.of.concrete.class.option=Ignore parameters whose type is abstract clas static.variable.of.concrete.class.option=Ignore static fields whose type is an abstract class class.only.used.in.one.package.display.name=Class only used from one other package class.only.used.in.one.package.problem.descriptor=Class #ref has only dependencies on and/or dependents in package ''{0}'' #loc -unnecessary.return.option=Ignore in then branch branch of 'if' statement with 'else' branch +unnecessary.return.option=Ignore in then branch of 'if' statement with 'else' branch usage.of.obsolete.assert.display.name=Usage of obsolete 'junit.framework.Assert' use.of.obsolete.assert.problem.descriptor=Call to #ref() from 'org.junit.framework.Assert' should be replaced with call to method from 'org.junit.Assert' #loc use.of.obsolete.assert.quickfix=Replace with 'org.junit.Assert' method call diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/UnnecessaryReturnInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/UnnecessaryReturnInspection.java index c0e1f312a90d..2ba67d48bf3c 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/UnnecessaryReturnInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/UnnecessaryReturnInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2011 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -41,8 +41,18 @@ public class UnnecessaryReturnInspection extends BaseInspection { @Override @NotNull public String getDisplayName() { - return InspectionGadgetsBundle.message( - "unnecessary.return.display.name"); + return InspectionGadgetsBundle.message("unnecessary.return.display.name"); + } + + @Override + @NotNull + public String buildErrorString(Object... infos) { + if (((Boolean)infos[0]).booleanValue()) { + return InspectionGadgetsBundle.message("unnecessary.return.constructor.problem.descriptor"); + } + else { + return InspectionGadgetsBundle.message("unnecessary.return.problem.descriptor"); + } } @Override @@ -52,15 +62,7 @@ public class UnnecessaryReturnInspection extends BaseInspection { @Override public JComponent createOptionsPanel() { - return new SingleCheckboxOptionsPanel( - InspectionGadgetsBundle.message("unnecessary.return.option"), - this, "ignoreInThenBranch"); - } - - @Override - @NotNull - public String buildErrorString(Object... infos) { - return InspectionGadgetsBundle.message("unnecessary.return.problem.descriptor"); + return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message("unnecessary.return.option"), this, "ignoreInThenBranch"); } @Override @@ -85,41 +87,43 @@ public class UnnecessaryReturnInspection extends BaseInspection { } final PsiElement methodParent = PsiTreeUtil.getParentOfType(statement, PsiMethod.class, PsiLambdaExpression.class); PsiCodeBlock codeBlock = null; + final boolean constructor; if (methodParent instanceof PsiMethod) { - codeBlock = ((PsiMethod)methodParent).getBody(); + final PsiMethod method = (PsiMethod)methodParent; + codeBlock = method.getBody(); + constructor = method.isConstructor(); } else if (methodParent instanceof PsiLambdaExpression) { - final PsiElement lambdaBody = ((PsiLambdaExpression)methodParent).getBody(); + constructor = false; + final PsiLambdaExpression lambdaExpression = (PsiLambdaExpression)methodParent; + final PsiElement lambdaBody = lambdaExpression.getBody(); if (lambdaBody instanceof PsiCodeBlock) { codeBlock = (PsiCodeBlock)lambdaBody; } } + else { + return; + } if (codeBlock == null) { return; } if (!ControlFlowUtils.blockCompletesWithStatement(codeBlock, statement)) { return; } - if (ignoreInThenBranch && isInThenBranch(statement, statement.getParent())) { + if (ignoreInThenBranch && isInThenBranch(statement)) { return; } - registerStatementError(statement); + registerStatementError(statement, Boolean.valueOf(constructor)); } - private boolean isInThenBranch(PsiReturnStatement statement, PsiElement parent) { - if (!(parent instanceof PsiCodeBlock)) { + private boolean isInThenBranch(PsiStatement statement) { + final PsiIfStatement ifStatement = + PsiTreeUtil.getParentOfType(statement, PsiIfStatement.class, true, PsiMethod.class, PsiLambdaExpression.class); + if (ifStatement == null) { return false; } - final PsiElement grandParent = parent.getParent(); - if (grandParent == null) { - return false; - } - final PsiElement greatGrandParent = grandParent.getParent(); - if (!(greatGrandParent instanceof PsiIfStatement)) { - return false; - } - final PsiStatement elseBranch = ((PsiIfStatement)greatGrandParent).getElseBranch(); - return elseBranch == null || !PsiTreeUtil.isAncestor(elseBranch, statement, true); + final PsiStatement elseBranch = ifStatement.getElseBranch(); + return elseBranch != null && !PsiTreeUtil.isAncestor(elseBranch, statement, true); } } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/imports/StaticImportInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/imports/StaticImportInspection.java index 6d2fe1ba3c48..f2809b40c0f4 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/imports/StaticImportInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/imports/StaticImportInspection.java @@ -18,6 +18,7 @@ package com.siyeh.ig.imports; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.openapi.project.Project; import com.intellij.psi.*; +import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; @@ -34,8 +35,10 @@ import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; public class StaticImportInspection extends BaseInspection { @@ -139,27 +142,22 @@ public class StaticImportInspection extends BaseInspection { final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project); final PsiElementFactory factory = psiFacade.getElementFactory(); final PsiClass aClass = target.getContainingClass(); + if (aClass == null) { + return; + } final String qualifiedName = aClass.getQualifiedName(); final String text = reference.getText(); final String referenceText = qualifiedName + '.' + text; if (reference instanceof PsiReferenceExpression) { - try { - final PsiExpression newReference = factory.createExpressionFromText(referenceText, reference); - reference.replace(newReference); - } - catch (IncorrectOperationException e) { - throw new RuntimeException(e); - } + final PsiExpression newReference = factory.createExpressionFromText(referenceText, reference); + final PsiElement insertedElement = reference.replace(newReference); + JavaCodeStyleManager.getInstance(project).shortenClassReferences(insertedElement); } else { final PsiJavaCodeReferenceElement referenceElement = factory.createReferenceElementByFQClassName(referenceText, reference.getResolveScope()); - try { - reference.replace(referenceElement); - } - catch (IncorrectOperationException e) { - throw new RuntimeException(e); - } + final PsiElement insertedElement = reference.replace(referenceElement); + JavaCodeStyleManager.getInstance(project).shortenClassReferences(insertedElement); } } @@ -204,7 +202,7 @@ public class StaticImportInspection extends BaseInspection { final PsiMember member = (PsiMember)target; for (JavaResolveResult importTarget : importTargets) { final PsiElement targetElement = importTarget.getElement(); - if (targetElement instanceof PsiMethod) { + if (targetElement instanceof PsiMethod || targetElement instanceof PsiField) { if (member.equals(targetElement)) { addReference(reference); } diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/junit/AssertEqualsCalledOnArrayInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/AssertEqualsCalledOnArrayInspection.java index 8c05fc9b086b..30608ed8588b 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/junit/AssertEqualsCalledOnArrayInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/AssertEqualsCalledOnArrayInspection.java @@ -24,6 +24,7 @@ import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; import com.siyeh.ig.InspectionGadgetsFix; +import com.siyeh.ig.psiutils.ImportUtils; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -47,8 +48,7 @@ public class AssertEqualsCalledOnArrayInspection extends BaseInspection { return new AssertEqualsCalledOnArrayFix(); } - private static class AssertEqualsCalledOnArrayFix - extends InspectionGadgetsFix { + private static class AssertEqualsCalledOnArrayFix extends InspectionGadgetsFix { @Override @NotNull @@ -59,17 +59,17 @@ public class AssertEqualsCalledOnArrayInspection extends BaseInspection { @Override protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException { final PsiElement methodNameIdentifier = descriptor.getPsiElement(); - final PsiReferenceExpression methodExpression = (PsiReferenceExpression)methodNameIdentifier.getParent(); - if (methodExpression == null) { + final PsiElement parent = methodNameIdentifier.getParent(); + if (!(parent instanceof PsiReferenceExpression)) { return; } + final PsiReferenceExpression methodExpression = (PsiReferenceExpression)parent; final PsiExpression qualifier = methodExpression.getQualifierExpression(); - if (qualifier == null) { + if (qualifier == null && ImportUtils.addStaticImport("org.junit.Assert", "assertArrayEquals", methodExpression)) { replaceExpression(methodExpression, "assertArrayEquals"); } else { - final String qualifierText = qualifier.getText(); - replaceExpression(methodExpression, qualifierText + ".assertArrayEquals"); + replaceExpression(methodExpression, "org.junit.Assert.assertArrayEquals"); } } } diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/junit/AssertEqualsMayBeAssertSameInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/AssertEqualsMayBeAssertSameInspection.java index cea04d38dc84..362c5a17c41f 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/junit/AssertEqualsMayBeAssertSameInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/AssertEqualsMayBeAssertSameInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2010 Bas Leijdekkers + * Copyright 2008-2012 Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,7 @@ import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; import com.siyeh.ig.InspectionGadgetsFix; +import com.siyeh.ig.psiutils.ImportUtils; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -31,15 +32,13 @@ public class AssertEqualsMayBeAssertSameInspection extends BaseInspection { @Override @NotNull public String getDisplayName() { - return InspectionGadgetsBundle.message( - "assertequals.may.be.assertsame.display.name"); + return InspectionGadgetsBundle.message("assertequals.may.be.assertsame.display.name"); } @Override @NotNull protected String buildErrorString(Object... infos) { - return InspectionGadgetsBundle.message( - "assertequals.may.be.assertsame.problem.descriptor"); + return InspectionGadgetsBundle.message("assertequals.may.be.assertsame.problem.descriptor"); } @Override @@ -47,29 +46,45 @@ public class AssertEqualsMayBeAssertSameInspection extends BaseInspection { return new AssertEqualsMayBeAssertSameFix(); } - private static class AssertEqualsMayBeAssertSameFix - extends InspectionGadgetsFix { + private static class AssertEqualsMayBeAssertSameFix extends InspectionGadgetsFix { @NotNull public String getName() { - return InspectionGadgetsBundle.message( - "assertequals.may.be.assertsame.quickfix"); + return InspectionGadgetsBundle.message("assertequals.may.be.assertsame.quickfix"); } @Override - protected void doFix(Project project, ProblemDescriptor descriptor) - throws IncorrectOperationException { + protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException { final PsiElement element = descriptor.getPsiElement(); - final PsiElement grandParent = element.getParent().getParent(); + final PsiElement parent = element.getParent(); + if (!(parent instanceof PsiReferenceExpression)) { + return; + } + final PsiReferenceExpression methodExpression = (PsiReferenceExpression)parent; + final PsiElement grandParent = methodExpression.getParent(); if (!(grandParent instanceof PsiMethodCallExpression)) { return; } - final PsiMethodCallExpression methodCallExpression = - (PsiMethodCallExpression)grandParent; - @NonNls final String text = methodCallExpression.getText(); - final String newExpressionText = - text.replace("assertEquals", "assertSame"); - replaceExpression(methodCallExpression, newExpressionText); + final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)grandParent; + final PsiMethod method = methodCallExpression.resolveMethod(); + if (method == null) { + return; + } + final PsiClass containingClass = method.getContainingClass(); + if (containingClass == null) { + return; + } + final String className = containingClass.getQualifiedName(); + if (className == null) { + return; + } + final PsiExpression qualifier = methodExpression.getQualifierExpression(); + if (qualifier == null && ImportUtils.addStaticImport(className, "assertSame", methodExpression)) { + replaceExpression(methodExpression, "assertSame"); + } + else { + replaceExpression(methodExpression, className + ".assertSame"); + } } } @@ -78,22 +93,19 @@ public class AssertEqualsMayBeAssertSameInspection extends BaseInspection { return new AssertEqualsMayBeAssertSameVisitor(); } - private static class AssertEqualsMayBeAssertSameVisitor - extends BaseInspectionVisitor { + private static class AssertEqualsMayBeAssertSameVisitor extends BaseInspectionVisitor { @Override - public void visitMethodCallExpression( - PsiMethodCallExpression expression) { + public void visitMethodCallExpression(PsiMethodCallExpression expression) { super.visitMethodCallExpression(expression); - final PsiReferenceExpression methodExpression = - expression.getMethodExpression(); + final PsiReferenceExpression methodExpression = expression.getMethodExpression(); @NonNls final String name = methodExpression.getReferenceName(); if (!"assertEquals".equals(name)) { return; } final PsiExpressionList argumentList = expression.getArgumentList(); final PsiExpression[] arguments = argumentList.getExpressions(); - if (arguments.length == 3 && arguments.length == 2) { + if (arguments.length != 3 && arguments.length != 2) { return; } final PsiMethod method = expression.resolveMethod(); @@ -105,8 +117,7 @@ public class AssertEqualsMayBeAssertSameInspection extends BaseInspection { return; } final String qualifiedName = aClass.getQualifiedName(); - if (!"org.junit.Assert".equals(qualifiedName) && - !"junit.framework.Assert".equals(qualifiedName)) { + if (!"org.junit.Assert".equals(qualifiedName) && !"junit.framework.Assert".equals(qualifiedName)) { return; } final PsiExpression argument1 = arguments[arguments.length - 2]; @@ -120,9 +131,8 @@ public class AssertEqualsMayBeAssertSameInspection extends BaseInspection { registerMethodCallError(expression); } - private static boolean couldBeAssertSameArgument( - PsiExpression argument1) { - final PsiType type = argument1.getType(); + private static boolean couldBeAssertSameArgument(PsiExpression expression) { + final PsiType type = expression.getType(); if (!(type instanceof PsiClassType)) { return false; } @@ -134,19 +144,15 @@ public class AssertEqualsMayBeAssertSameInspection extends BaseInspection { if (!argumentClass.hasModifierProperty(PsiModifier.FINAL)) { return false; } - final PsiMethod[] methods = - argumentClass.findMethodsByName("equals", true); - final PsiManager manager = argument1.getManager(); - final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance( - manager.getProject()); - final PsiClass objectClass = psiFacade.findClass( - CommonClassNames.JAVA_LANG_OBJECT, - argumentClass.getResolveScope()); + final PsiMethod[] methods = argumentClass.findMethodsByName("equals", true); + final PsiManager manager = expression.getManager(); + final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(manager.getProject()); + final PsiClass objectClass = psiFacade.findClass(CommonClassNames.JAVA_LANG_OBJECT, argumentClass.getResolveScope()); if (objectClass == null) { return false; } - for (PsiMethod psiMethod : methods) { - final PsiClass containingClass = psiMethod.getContainingClass(); + for (PsiMethod method : methods) { + final PsiClass containingClass = method.getContainingClass(); if (!objectClass.equals(containingClass)) { return false; } diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/junit/SimplifiableJUnitAssertionInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/SimplifiableJUnitAssertionInspection.java index 2b5f8c0b74ab..72080f759e70 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/junit/SimplifiableJUnitAssertionInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/SimplifiableJUnitAssertionInspection.java @@ -19,7 +19,6 @@ import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.psi.tree.IElementType; -import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; @@ -34,15 +33,13 @@ public class SimplifiableJUnitAssertionInspection extends BaseInspection { @Override @NotNull public String getDisplayName() { - return InspectionGadgetsBundle.message( - "simplifiable.junit.assertion.display.name"); + return InspectionGadgetsBundle.message("simplifiable.junit.assertion.display.name"); } @Override @NotNull protected String buildErrorString(Object... infos) { - return InspectionGadgetsBundle.message( - "simplifiable.junit.assertion.problem.descriptor", infos[0]); + return InspectionGadgetsBundle.message("simplifiable.junit.assertion.problem.descriptor", infos[0]); } @Override @@ -55,20 +52,17 @@ public class SimplifiableJUnitAssertionInspection extends BaseInspection { @Override @NotNull public String getName() { - return InspectionGadgetsBundle.message( - "simplify.junit.assertion.simplify.quickfix"); + return InspectionGadgetsBundle.message("simplify.junit.assertion.simplify.quickfix"); } @Override - public void doFix(Project project, ProblemDescriptor descriptor) - throws IncorrectOperationException { + public void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException { final PsiElement methodNameIdentifier = descriptor.getPsiElement(); final PsiElement parent = methodNameIdentifier.getParent(); if (parent == null) { return; } - final PsiMethodCallExpression callExpression = - (PsiMethodCallExpression)parent.getParent(); + final PsiMethodCallExpression callExpression = (PsiMethodCallExpression)parent.getParent(); if (isAssertThatCouldBeAssertNull(callExpression)) { replaceAssertWithAssertNull(callExpression); } @@ -86,15 +80,12 @@ public class SimplifiableJUnitAssertionInspection extends BaseInspection { } } - private static void replaceAssertWithFail( - PsiMethodCallExpression callExpression) - throws IncorrectOperationException { + private static void replaceAssertWithFail(PsiMethodCallExpression callExpression) throws IncorrectOperationException { final PsiMethod method = callExpression.resolveMethod(); if (method == null) { return; } - final PsiExpressionList argumentList = - callExpression.getArgumentList(); + final PsiExpressionList argumentList = callExpression.getArgumentList(); final PsiExpression[] arguments = argumentList.getExpressions(); final PsiExpression message; if (arguments.length == 2) { @@ -104,19 +95,18 @@ public class SimplifiableJUnitAssertionInspection extends BaseInspection { message = null; } @NonNls final StringBuilder newExpression = new StringBuilder(); - addStaticImportIfPossible(callExpression, "fail", newExpression); + if (!ImportUtils.addStaticImport("org.junit.Assert", "fail", callExpression)) { + newExpression.append("org.junit.Assert."); + } newExpression.append("fail("); if (message != null) { newExpression.append(message.getText()); } newExpression.append(')'); - replaceExpressionAndShorten(callExpression, - newExpression.toString()); + replaceExpressionAndShorten(callExpression, newExpression.toString()); } - private static void replaceAssertTrueWithAssertEquals( - PsiMethodCallExpression callExpression) - throws IncorrectOperationException { + private static void replaceAssertTrueWithAssertEquals(PsiMethodCallExpression callExpression) throws IncorrectOperationException { final PsiMethod method = callExpression.resolveMethod(); if (method == null) { return; @@ -125,8 +115,7 @@ public class SimplifiableJUnitAssertionInspection extends BaseInspection { final PsiParameter[] parameters = parameterList.getParameters(); final PsiType stringType = TypeUtils.getStringType(callExpression); final PsiType paramType1 = parameters[0].getType(); - final PsiExpressionList argumentList = - callExpression.getArgumentList(); + final PsiExpressionList argumentList = callExpression.getArgumentList(); final PsiExpression[] arguments = argumentList.getExpressions(); final int testPosition; final PsiExpression message; @@ -142,25 +131,19 @@ public class SimplifiableJUnitAssertionInspection extends BaseInspection { PsiExpression lhs = null; PsiExpression rhs = null; if (testArgument instanceof PsiBinaryExpression) { - final PsiBinaryExpression binaryExpression = - (PsiBinaryExpression)testArgument; + final PsiBinaryExpression binaryExpression = (PsiBinaryExpression)testArgument; lhs = binaryExpression.getLOperand(); rhs = binaryExpression.getROperand(); } else if (testArgument instanceof PsiMethodCallExpression) { - final PsiMethodCallExpression call = - (PsiMethodCallExpression)testArgument; - final PsiReferenceExpression equalityMethodExpression = - call.getMethodExpression(); - final PsiExpressionList equalityArgumentList = - call.getArgumentList(); - final PsiExpression[] equalityArgs = - equalityArgumentList.getExpressions(); + final PsiMethodCallExpression call = (PsiMethodCallExpression)testArgument; + final PsiReferenceExpression equalityMethodExpression = call.getMethodExpression(); + final PsiExpressionList equalityArgumentList = call.getArgumentList(); + final PsiExpression[] equalityArgs = equalityArgumentList.getExpressions(); rhs = equalityArgs[0]; lhs = equalityMethodExpression.getQualifierExpression(); } - if (!(lhs instanceof PsiLiteralExpression) && - rhs instanceof PsiLiteralExpression) { + if (!(lhs instanceof PsiLiteralExpression) && rhs instanceof PsiLiteralExpression) { final PsiExpression temp = lhs; lhs = rhs; rhs = temp; @@ -169,27 +152,22 @@ public class SimplifiableJUnitAssertionInspection extends BaseInspection { return; } @NonNls final StringBuilder newExpression = new StringBuilder(); - addStaticImportIfPossible(callExpression, "assertEquals", - newExpression); + if (!ImportUtils.addStaticImport("org.junit.Assert", "assertEquals", callExpression)) { + newExpression.append("org.junit.Assert."); + } newExpression.append("assertEquals("); if (message != null) { - newExpression.append(message.getText()); - newExpression.append(','); + newExpression.append(message.getText()).append(','); } - newExpression.append(lhs.getText()); - newExpression.append(','); - newExpression.append(rhs.getText()); - if (isFloatingPoint(lhs) || isFloatingPoint(rhs)) { + newExpression.append(lhs.getText()).append(',').append(rhs.getText()); + if (TypeUtils.hasFloatingPointType(lhs) || TypeUtils.hasFloatingPointType(rhs)) { newExpression.append(",0.0"); } newExpression.append(')'); - replaceExpressionAndShorten(callExpression, - newExpression.toString()); + replaceExpressionAndShorten(callExpression, newExpression.toString()); } - private static void replaceAssertWithAssertNull( - PsiMethodCallExpression callExpression) - throws IncorrectOperationException { + private static void replaceAssertWithAssertNull(PsiMethodCallExpression callExpression) throws IncorrectOperationException { final PsiMethod method = callExpression.resolveMethod(); if (method == null) { return; @@ -198,8 +176,7 @@ public class SimplifiableJUnitAssertionInspection extends BaseInspection { final PsiParameter[] parameters = parameterList.getParameters(); final PsiType stringType = TypeUtils.getStringType(callExpression); final PsiType paramType1 = parameters[0].getType(); - final PsiExpressionList argumentList = - callExpression.getArgumentList(); + final PsiExpressionList argumentList = callExpression.getArgumentList(); final PsiExpression[] arguments = argumentList.getExpressions(); final int testPosition; final PsiExpression message; @@ -211,48 +188,38 @@ public class SimplifiableJUnitAssertionInspection extends BaseInspection { testPosition = 0; message = null; } - final PsiBinaryExpression binaryExpression = - (PsiBinaryExpression)arguments[testPosition]; + final PsiBinaryExpression binaryExpression = (PsiBinaryExpression)arguments[testPosition]; final PsiExpression lhs = binaryExpression.getLOperand(); PsiExpression rhs = binaryExpression.getROperand(); if (rhs == null) { return; } - final IElementType tokenType = - binaryExpression.getOperationTokenType(); - if (!(lhs instanceof PsiLiteralExpression) && - rhs instanceof PsiLiteralExpression) { + final IElementType tokenType = binaryExpression.getOperationTokenType(); + if (!(lhs instanceof PsiLiteralExpression) && rhs instanceof PsiLiteralExpression) { rhs = lhs; } @NonNls final StringBuilder newExpression = new StringBuilder(); - final PsiReferenceExpression methodExpression = - callExpression.getMethodExpression(); - @NonNls final String methodName = - methodExpression.getReferenceName(); + final PsiReferenceExpression methodExpression = callExpression.getMethodExpression(); + @NonNls final String methodName = methodExpression.getReferenceName(); @NonNls final String memberName; - if ("assertFalse".equals(methodName) ^ - tokenType.equals(JavaTokenType.NE)) { + if ("assertFalse".equals(methodName) ^ tokenType.equals(JavaTokenType.NE)) { memberName = "assertNotNull"; } else { memberName = "assertNull"; } - addStaticImportIfPossible(callExpression, memberName, newExpression); - newExpression.append(memberName); - newExpression.append('('); - if (message != null) { - newExpression.append(message.getText()); - newExpression.append(','); + if (!ImportUtils.addStaticImport("org.junit.Assert", memberName, callExpression)) { + newExpression.append("org.junit.Assert."); } - newExpression.append(rhs.getText()); - newExpression.append(')'); - replaceExpressionAndShorten(callExpression, - newExpression.toString()); + newExpression.append(memberName).append('('); + if (message != null) { + newExpression.append(message.getText()).append(','); + } + newExpression.append(rhs.getText()).append(')'); + replaceExpressionAndShorten(callExpression, newExpression.toString()); } - private static void replaceAssertWithAssertSame( - PsiMethodCallExpression callExpression) - throws IncorrectOperationException { + private static void replaceAssertWithAssertSame(PsiMethodCallExpression callExpression) throws IncorrectOperationException { final PsiMethod method = callExpression.resolveMethod(); if (method == null) { return; @@ -261,8 +228,7 @@ public class SimplifiableJUnitAssertionInspection extends BaseInspection { final PsiParameter[] parameters = parameterList.getParameters(); final PsiType stringType = TypeUtils.getStringType(callExpression); final PsiType paramType1 = parameters[0].getType(); - final PsiExpressionList argumentList = - callExpression.getArgumentList(); + final PsiExpressionList argumentList = callExpression.getArgumentList(); final PsiExpression[] arguments = argumentList.getExpressions(); final int testPosition; final PsiExpression message; @@ -274,14 +240,11 @@ public class SimplifiableJUnitAssertionInspection extends BaseInspection { testPosition = 0; message = null; } - final PsiBinaryExpression binaryExpression = - (PsiBinaryExpression)arguments[testPosition]; + final PsiBinaryExpression binaryExpression = (PsiBinaryExpression)arguments[testPosition]; PsiExpression lhs = binaryExpression.getLOperand(); PsiExpression rhs = binaryExpression.getROperand(); - final IElementType tokenType = - binaryExpression.getOperationTokenType(); - if (!(lhs instanceof PsiLiteralExpression) && - rhs instanceof PsiLiteralExpression) { + final IElementType tokenType = binaryExpression.getOperationTokenType(); + if (!(lhs instanceof PsiLiteralExpression) && rhs instanceof PsiLiteralExpression) { final PsiExpression temp = lhs; lhs = rhs; rhs = temp; @@ -290,31 +253,24 @@ public class SimplifiableJUnitAssertionInspection extends BaseInspection { return; } @NonNls final StringBuilder newExpression = new StringBuilder(); - final PsiReferenceExpression methodExpression = - callExpression.getMethodExpression(); - @NonNls final String methodName = - methodExpression.getReferenceName(); + final PsiReferenceExpression methodExpression = callExpression.getMethodExpression(); + @NonNls final String methodName = methodExpression.getReferenceName(); @NonNls final String memberName; - if ("assertFalse".equals(methodName) ^ - tokenType.equals(JavaTokenType.NE)) { + if ("assertFalse".equals(methodName) ^ tokenType.equals(JavaTokenType.NE)) { memberName = "assertNotSame"; } else { memberName = "assertSame"; } - addStaticImportIfPossible(callExpression, memberName, newExpression); - newExpression.append(memberName); - newExpression.append('('); - if (message != null) { - newExpression.append(message.getText()); - newExpression.append(','); + if (!ImportUtils.addStaticImport("org.junit.Assert", memberName, callExpression)) { + newExpression.append("org.junit.Assert."); } - newExpression.append(lhs.getText()); - newExpression.append(','); - newExpression.append(rhs.getText()); - newExpression.append(')'); - replaceExpressionAndShorten(callExpression, - newExpression.toString()); + newExpression.append(memberName).append('('); + if (message != null) { + newExpression.append(message.getText()).append(','); + } + newExpression.append(lhs.getText()).append(',').append(rhs.getText()).append(')'); + replaceExpressionAndShorten(callExpression, newExpression.toString()); } private static void replaceAssertEqualsWithAssertLiteral( @@ -328,8 +284,7 @@ public class SimplifiableJUnitAssertionInspection extends BaseInspection { final PsiParameter[] parameters = parameterList.getParameters(); final PsiType stringType = TypeUtils.getStringType(callExpression); final PsiType paramType1 = parameters[0].getType(); - final PsiExpressionList argumentList = - callExpression.getArgumentList(); + final PsiExpressionList argumentList = callExpression.getArgumentList(); final PsiExpression[] arguments = argumentList.getExpressions(); final int firstTestPosition; final int secondTestPosition; @@ -344,10 +299,8 @@ public class SimplifiableJUnitAssertionInspection extends BaseInspection { secondTestPosition = 1; message = null; } - final PsiExpression firstTestArgument = - arguments[firstTestPosition]; - final PsiExpression secondTestArgument = - arguments[secondTestPosition]; + final PsiExpression firstTestArgument = arguments[firstTestPosition]; + final PsiExpression secondTestArgument = arguments[secondTestPosition]; final String literalValue; final String compareValue; if (isSimpleLiteral(firstTestArgument, secondTestArgument)) { @@ -358,47 +311,18 @@ public class SimplifiableJUnitAssertionInspection extends BaseInspection { literalValue = secondTestArgument.getText(); compareValue = firstTestArgument.getText(); } - final String uppercaseLiteralValue = - Character.toUpperCase(literalValue.charAt(0)) + - literalValue.substring(1); + final String uppercaseLiteralValue = Character.toUpperCase(literalValue.charAt(0)) + literalValue.substring(1); @NonNls final StringBuilder newExpression = new StringBuilder(); @NonNls final String methodName = "assert" + uppercaseLiteralValue; - addStaticImportIfPossible(callExpression, methodName, newExpression); - newExpression.append(methodName); - newExpression.append('('); + if (!ImportUtils.addStaticImport("org.junit.Assert", methodName, callExpression)) { + newExpression.append("org.junit.Assert."); + } + newExpression.append(methodName).append('('); if (message != null) { - newExpression.append(message.getText()); - newExpression.append(','); + newExpression.append(message.getText()).append(','); } - newExpression.append(compareValue); - newExpression.append(')'); - replaceExpressionAndShorten(callExpression, - newExpression.toString()); - } - - private static void addStaticImportIfPossible( - PsiMethodCallExpression context, @NonNls String memberName, - @NonNls StringBuilder out) { - final PsiMethod containingMethod = PsiTreeUtil.getParentOfType( - context, PsiMethod.class); - if (TestUtils.isJUnit4TestMethod(containingMethod)) { - final PsiReferenceExpression methodExpression = - context.getMethodExpression(); - if (methodExpression.isQualified() || - !ImportUtils.nameCanBeStaticallyImported( - "org.junit.Assert", memberName, context)) { - out.append("org.junit.Assert."); - } - else { - ImportUtils.addStaticImport( - "org.junit.Assert", memberName, context); - } - } - } - - private static boolean isFloatingPoint(PsiExpression expression) { - final PsiType type = expression.getType(); - return PsiType.FLOAT.equals(type) || PsiType.DOUBLE.equals(type); + newExpression.append(compareValue).append(')'); + replaceExpressionAndShorten(callExpression, newExpression.toString()); } } @@ -407,12 +331,10 @@ public class SimplifiableJUnitAssertionInspection extends BaseInspection { return new SimplifiableJUnitAssertionVisitor(); } - private static class SimplifiableJUnitAssertionVisitor - extends BaseInspectionVisitor { + private static class SimplifiableJUnitAssertionVisitor extends BaseInspectionVisitor { @Override - public void visitMethodCallExpression( - @NotNull PsiMethodCallExpression expression) { + public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) { super.visitMethodCallExpression(expression); if (isAssertThatCouldBeAssertNull(expression)) { if (hasEqEqExpressionArgument(expression)) { @@ -434,8 +356,7 @@ public class SimplifiableJUnitAssertionInspection extends BaseInspection { registerMethodCallError(expression, "assertEquals()"); } else if (isAssertEqualsThatCouldBeAssertLiteral(expression)) { - registerMethodCallError(expression, - getReplacementMethodName(expression)); + registerMethodCallError(expression, getReplacementMethodName(expression)); } else if (isAssertThatCouldBeFail(expression)) { registerMethodCallError(expression, "fail()"); @@ -443,14 +364,12 @@ public class SimplifiableJUnitAssertionInspection extends BaseInspection { } @NonNls - private static String getReplacementMethodName( - PsiMethodCallExpression expression) { + private static String getReplacementMethodName(PsiMethodCallExpression expression) { final PsiExpressionList argumentList = expression.getArgumentList(); final PsiExpression[] arguments = argumentList.getExpressions(); final PsiExpression firstArgument = arguments[0]; if (firstArgument instanceof PsiLiteralExpression) { - final PsiLiteralExpression literalExpression = - (PsiLiteralExpression)firstArgument; + final PsiLiteralExpression literalExpression = (PsiLiteralExpression)firstArgument; final Object value = literalExpression.getValue(); if (value == Boolean.TRUE) { return "assertTrue()"; @@ -464,8 +383,7 @@ public class SimplifiableJUnitAssertionInspection extends BaseInspection { } final PsiExpression secondArgument = arguments[1]; if (secondArgument instanceof PsiLiteralExpression) { - final PsiLiteralExpression literalExpression = - (PsiLiteralExpression)secondArgument; + final PsiLiteralExpression literalExpression = (PsiLiteralExpression)secondArgument; final Object value = literalExpression.getValue(); if (value == Boolean.TRUE) { return "assertTrue()"; @@ -480,18 +398,15 @@ public class SimplifiableJUnitAssertionInspection extends BaseInspection { return ""; } - private static boolean hasEqEqExpressionArgument( - PsiMethodCallExpression expression) { + private static boolean hasEqEqExpressionArgument(PsiMethodCallExpression expression) { final PsiExpressionList list = expression.getArgumentList(); final PsiExpression[] arguments = list.getExpressions(); final PsiExpression argument = arguments[0]; if (!(argument instanceof PsiBinaryExpression)) { return false; } - final PsiBinaryExpression binaryExpression = - (PsiBinaryExpression)argument; - final IElementType tokenType = - binaryExpression.getOperationTokenType(); + final PsiBinaryExpression binaryExpression = (PsiBinaryExpression)argument; + final IElementType tokenType = binaryExpression.getOperationTokenType(); return JavaTokenType.EQEQ.equals(tokenType); } } @@ -501,8 +416,7 @@ public class SimplifiableJUnitAssertionInspection extends BaseInspection { if (!isAssertTrue(expression)) { return false; } - final PsiReferenceExpression methodExpression = - expression.getMethodExpression(); + final PsiReferenceExpression methodExpression = expression.getMethodExpression(); final PsiMethod method = (PsiMethod)methodExpression.resolve(); if (method == null) { return false; @@ -527,13 +441,11 @@ public class SimplifiableJUnitAssertionInspection extends BaseInspection { return testArgument != null && isEqualityComparison(testArgument); } - static boolean isAssertThatCouldBeAssertSame( - PsiMethodCallExpression expression) { + static boolean isAssertThatCouldBeAssertSame(PsiMethodCallExpression expression) { if (!isAssertTrue(expression) && !isAssertFalse(expression)) { return false; } - final PsiReferenceExpression methodExpression = - expression.getMethodExpression(); + final PsiReferenceExpression methodExpression = expression.getMethodExpression(); final PsiMethod method = (PsiMethod)methodExpression.resolve(); if (method == null) { return false; @@ -558,13 +470,11 @@ public class SimplifiableJUnitAssertionInspection extends BaseInspection { return testArgument != null && isIdentityComparison(testArgument); } - static boolean isAssertThatCouldBeAssertNull( - PsiMethodCallExpression expression) { + static boolean isAssertThatCouldBeAssertNull(PsiMethodCallExpression expression) { if (!isAssertTrue(expression) && !isAssertFalse(expression)) { return false; } - final PsiReferenceExpression methodExpression = - expression.getMethodExpression(); + final PsiReferenceExpression methodExpression = expression.getMethodExpression(); final PsiMethod method = (PsiMethod)methodExpression.resolve(); if (method == null) { return false; @@ -601,8 +511,7 @@ public class SimplifiableJUnitAssertionInspection extends BaseInspection { else { return false; } - final PsiReferenceExpression methodExpression = - expression.getMethodExpression(); + final PsiReferenceExpression methodExpression = expression.getMethodExpression(); final PsiMethod method = (PsiMethod)methodExpression.resolve(); if (method == null) { return false; @@ -636,13 +545,11 @@ public class SimplifiableJUnitAssertionInspection extends BaseInspection { } } - static boolean isAssertEqualsThatCouldBeAssertLiteral( - PsiMethodCallExpression expression) { + static boolean isAssertEqualsThatCouldBeAssertLiteral(PsiMethodCallExpression expression) { if (!isAssertEquals(expression)) { return false; } - final PsiReferenceExpression methodExpression = - expression.getMethodExpression(); + final PsiReferenceExpression methodExpression = expression.getMethodExpression(); final PsiMethod method = (PsiMethod)methodExpression.resolve(); if (method == null) { return false; @@ -675,8 +582,7 @@ public class SimplifiableJUnitAssertionInspection extends BaseInspection { isSimpleLiteral(secondTestArgument, firstTestArgument); } - static boolean isSimpleLiteral(PsiExpression expression1, - PsiExpression expression2) { + static boolean isSimpleLiteral(PsiExpression expression1, PsiExpression expression2) { if (!(expression1 instanceof PsiLiteralExpression)) { return false; } @@ -684,8 +590,7 @@ public class SimplifiableJUnitAssertionInspection extends BaseInspection { if (PsiKeyword.NULL.equals(text)) { return true; } - if (!PsiKeyword.TRUE.equals(text) && - !PsiKeyword.FALSE.equals(text)) { + if (!PsiKeyword.TRUE.equals(text) && !PsiKeyword.FALSE.equals(text)) { return false; } final PsiType type = expression2.getType(); @@ -694,8 +599,7 @@ public class SimplifiableJUnitAssertionInspection extends BaseInspection { private static boolean isEqualityComparison(PsiExpression expression) { if (expression instanceof PsiBinaryExpression) { - final PsiBinaryExpression binaryExpression = - (PsiBinaryExpression)expression; + final PsiBinaryExpression binaryExpression = (PsiBinaryExpression)expression; final IElementType tokenType = binaryExpression.getOperationTokenType(); if (!tokenType.equals(JavaTokenType.EQEQ)) { return false; @@ -709,13 +613,11 @@ public class SimplifiableJUnitAssertionInspection extends BaseInspection { return type != null && ClassUtils.isPrimitive(type); } else if (expression instanceof PsiMethodCallExpression) { - final PsiMethodCallExpression call = - (PsiMethodCallExpression)expression; + final PsiMethodCallExpression call = (PsiMethodCallExpression)expression; if (!MethodCallUtils.isEqualsCall(call)) { return false; } - final PsiReferenceExpression methodExpression = - call.getMethodExpression(); + final PsiReferenceExpression methodExpression = call.getMethodExpression(); return methodExpression.getQualifierExpression() != null; } return false; @@ -725,8 +627,7 @@ public class SimplifiableJUnitAssertionInspection extends BaseInspection { if (!(expression instanceof PsiBinaryExpression)) { return false; } - final PsiBinaryExpression binaryExpression = - (PsiBinaryExpression)expression; + final PsiBinaryExpression binaryExpression = (PsiBinaryExpression)expression; if (!ComparisonUtils.isEqualityComparison(binaryExpression)) { return false; } @@ -747,8 +648,7 @@ public class SimplifiableJUnitAssertionInspection extends BaseInspection { if (!(expression instanceof PsiBinaryExpression)) { return false; } - final PsiBinaryExpression binaryExpression = - (PsiBinaryExpression)expression; + final PsiBinaryExpression binaryExpression = (PsiBinaryExpression)expression; if (!ComparisonUtils.isEqualityComparison(binaryExpression)) { return false; } @@ -757,30 +657,24 @@ public class SimplifiableJUnitAssertionInspection extends BaseInspection { return false; } final PsiExpression lhs = binaryExpression.getLOperand(); - return PsiKeyword.NULL.equals(lhs.getText()) || - PsiKeyword.NULL.equals(rhs.getText()); + return PsiKeyword.NULL.equals(lhs.getText()) || PsiKeyword.NULL.equals(rhs.getText()); } - private static boolean isAssertTrue( - @NotNull PsiMethodCallExpression expression) { + private static boolean isAssertTrue(@NotNull PsiMethodCallExpression expression) { return isAssertMethodCall(expression, "assertTrue"); } - private static boolean isAssertFalse( - @NotNull PsiMethodCallExpression expression) { + private static boolean isAssertFalse(@NotNull PsiMethodCallExpression expression) { return isAssertMethodCall(expression, "assertFalse"); } - private static boolean isAssertEquals( - @NotNull PsiMethodCallExpression expression) { + private static boolean isAssertEquals(@NotNull PsiMethodCallExpression expression) { return isAssertMethodCall(expression, "assertEquals"); } - private static boolean isAssertMethodCall( - @NotNull PsiMethodCallExpression expression, + private static boolean isAssertMethodCall(@NotNull PsiMethodCallExpression expression, @NonNls @NotNull String assertMethodName) { - final PsiReferenceExpression methodExpression = - expression.getMethodExpression(); + final PsiReferenceExpression methodExpression = expression.getMethodExpression(); @NonNls final String methodName = methodExpression.getReferenceName(); if (!assertMethodName.equals(methodName)) { return false; @@ -794,7 +688,6 @@ public class SimplifiableJUnitAssertionInspection extends BaseInspection { return false; } final String qualifiedName = targetClass.getQualifiedName(); - return "junit.framework.Assert".equals(qualifiedName) || - "org.junit.Assert".equals(qualifiedName); + return "junit.framework.Assert".equals(qualifiedName) || "org.junit.Assert".equals(qualifiedName); } } diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/numeric/ComparisonToNaNInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/numeric/ComparisonToNaNInspection.java index 8cd48af13333..b8ab455042d3 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/numeric/ComparisonToNaNInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/numeric/ComparisonToNaNInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2011 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; import com.siyeh.ig.InspectionGadgetsFix; import com.siyeh.ig.psiutils.ComparisonUtils; +import com.siyeh.ig.psiutils.TypeUtils; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -109,7 +110,7 @@ public class ComparisonToNaNInspection extends BaseInspection { } final PsiExpression lhs = expression.getLOperand(); final PsiExpression rhs = expression.getROperand(); - if (rhs == null || !isFloatingPointType(lhs) && !isFloatingPointType(rhs)) { + if (rhs == null || !TypeUtils.hasFloatingPointType(lhs) && !TypeUtils.hasFloatingPointType(rhs)) { return; } if (isNaN(lhs)) { @@ -120,17 +121,6 @@ public class ComparisonToNaNInspection extends BaseInspection { } } - private static boolean isFloatingPointType(PsiExpression expression) { - if (expression == null) { - return false; - } - final PsiType type = expression.getType(); - if (type == null) { - return false; - } - return PsiType.DOUBLE.equals(type) || PsiType.FLOAT.equals(type); - } - private static boolean isNaN(PsiExpression expression) { if (!(expression instanceof PsiReferenceExpression)) { return false; diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/numeric/FloatingPointEqualityInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/numeric/FloatingPointEqualityInspection.java index bc9ac42ae111..3b0a32d94094 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/numeric/FloatingPointEqualityInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/numeric/FloatingPointEqualityInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2007 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,38 +17,34 @@ package com.siyeh.ig.numeric; import com.intellij.psi.PsiBinaryExpression; import com.intellij.psi.PsiExpression; -import com.intellij.psi.PsiType; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; import com.siyeh.ig.psiutils.ComparisonUtils; import com.siyeh.ig.psiutils.ExpressionUtils; +import com.siyeh.ig.psiutils.TypeUtils; import org.jetbrains.annotations.NotNull; public class FloatingPointEqualityInspection extends BaseInspection { @NotNull public String getDisplayName() { - return InspectionGadgetsBundle.message( - "floating.point.equality.display.name"); + return InspectionGadgetsBundle.message("floating.point.equality.display.name"); } @NotNull protected String buildErrorString(Object... infos) { - return InspectionGadgetsBundle.message( - "floating.point.equality.problem.descriptor"); + return InspectionGadgetsBundle.message("floating.point.equality.problem.descriptor"); } public BaseInspectionVisitor buildVisitor() { return new FloatingPointEqualityComparisonVisitor(); } - private static class FloatingPointEqualityComparisonVisitor - extends BaseInspectionVisitor { + private static class FloatingPointEqualityComparisonVisitor extends BaseInspectionVisitor { @Override - public void visitBinaryExpression( - @NotNull PsiBinaryExpression expression) { + public void visitBinaryExpression(@NotNull PsiBinaryExpression expression) { super.visitBinaryExpression(expression); final PsiExpression rhs = expression.getROperand(); if (rhs == null) { @@ -58,8 +54,7 @@ public class FloatingPointEqualityInspection extends BaseInspection { return; } final PsiExpression lhs = expression.getLOperand(); - - if (!isFloatingPointType(lhs) && !isFloatingPointType(rhs)) { + if (!TypeUtils.hasFloatingPointType(lhs) && !TypeUtils.hasFloatingPointType(rhs)) { return; } if (ExpressionUtils.isZero(lhs) || ExpressionUtils.isZero(rhs)) { @@ -67,16 +62,5 @@ public class FloatingPointEqualityInspection extends BaseInspection { } registerError(expression); } - - private static boolean isFloatingPointType(PsiExpression expression) { - if (expression == null) { - return false; - } - final PsiType type = expression.getType(); - if (type == null) { - return false; - } - return PsiType.DOUBLE.equals(type) || PsiType.FLOAT.equals(type); - } } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/ImportUtils.java b/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/ImportUtils.java index fc3d59e8bebe..caf1b66c010c 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/ImportUtils.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/ImportUtils.java @@ -445,64 +445,56 @@ public class ImportUtils { return false; } - public static void addStaticImport( - @NotNull String qualifierClass, @NotNull String memberName, - @NotNull PsiElement context) + public static boolean addStaticImport(@NotNull String qualifierClass, @NotNull String memberName, @NotNull PsiElement context) throws IncorrectOperationException { - final PsiClass containingClass = - PsiTreeUtil.getParentOfType(context, PsiClass.class); + if (!nameCanBeStaticallyImported(qualifierClass, memberName, context)) { + return false; + } + final PsiClass containingClass = PsiTreeUtil.getParentOfType(context, PsiClass.class); if (InheritanceUtil.isInheritor(containingClass, qualifierClass)) { - return; + return true; } final PsiFile psiFile = context.getContainingFile(); if (!(psiFile instanceof PsiJavaFile)) { - return; + return false; } final PsiJavaFile javaFile = (PsiJavaFile)psiFile; final PsiImportList importList = javaFile.getImportList(); if (importList == null) { - return; + return false; } - final PsiImportStatementBase existingImportStatement = - importList.findSingleImportStatement(memberName); + final PsiImportStatementBase existingImportStatement = importList.findSingleImportStatement(memberName); if (existingImportStatement != null) { - return; + return false; } - final PsiImportStaticStatement onDemandImportStatement = - findOnDemandImportStaticStatement(importList, qualifierClass); - if (onDemandImportStatement != null && - !hasOnDemandImportStaticConflict(qualifierClass, memberName, - context)) { - return; + final PsiImportStaticStatement onDemandImportStatement = findOnDemandImportStaticStatement(importList, qualifierClass); + if (onDemandImportStatement != null && !hasOnDemandImportStaticConflict(qualifierClass, memberName, context)) { + return true; } final Project project = context.getProject(); final GlobalSearchScope scope = context.getResolveScope(); final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project); final PsiClass aClass = psiFacade.findClass(qualifierClass, scope); if (aClass == null) { - return; + return false; } final String qualifiedName = aClass.getQualifiedName(); if (qualifiedName == null) { - return; + return false; } - final List imports = - getMatchingImports(importList, qualifiedName); - final CodeStyleSettings codeStyleSettings = - CodeStyleSettingsManager.getSettings(project); + final List imports = getMatchingImports(importList, qualifiedName); + final CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(project); final PsiElementFactory elementFactory = psiFacade.getElementFactory(); - if (imports.size() < - codeStyleSettings.NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND) { - importList.add(elementFactory.createImportStaticStatement(aClass, - memberName)); + if (imports.size() < codeStyleSettings.NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND) { + importList.add(elementFactory.createImportStaticStatement(aClass, memberName)); } else { for (PsiImportStaticStatement importStatement : imports) { importStatement.delete(); } - importList.add( - elementFactory.createImportStaticStatement(aClass, "*")); + importList.add(elementFactory.createImportStaticStatement(aClass, "*")); } + return true; } private static PsiImportStaticStatement findOnDemandImportStaticStatement( diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/TypeUtils.java b/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/TypeUtils.java index 2648bf91df13..093bd308b5b8 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/TypeUtils.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/TypeUtils.java @@ -65,9 +65,7 @@ public class TypeUtils { return typeEquals(CommonClassNames.JAVA_LANG_STRING, targetType); } - public static boolean expressionHasTypeOrSubtype( - @Nullable PsiExpression expression, - @NonNls @NotNull String typeName) { + public static boolean expressionHasTypeOrSubtype(@Nullable PsiExpression expression, @NonNls @NotNull String typeName) { if (expression == null) { return false; } @@ -84,8 +82,7 @@ public class TypeUtils { } //getTypeIfOneOfOrSubtype - public static String expressionHasTypeOrSubtype( - @Nullable PsiExpression expression, + public static String expressionHasTypeOrSubtype(@Nullable PsiExpression expression, @NonNls @NotNull String... typeNames) { if (expression == null) { return null; @@ -110,9 +107,7 @@ public class TypeUtils { return null; } - public static boolean expressionHasTypeOrSubtype( - @Nullable PsiExpression expression, - @NonNls @NotNull Collection typeNames) { + public static boolean expressionHasTypeOrSubtype(@Nullable PsiExpression expression, @NonNls @NotNull Collection typeNames) { if (expression == null) { return false; } @@ -136,9 +131,7 @@ public class TypeUtils { return false; } - public static boolean variableHasTypeOrSubtype( - @Nullable PsiVariable variable, - @NonNls @NotNull String... typeNames) { + public static boolean variableHasTypeOrSubtype(@Nullable PsiVariable variable, @NonNls @NotNull String... typeNames) { if (variable == null) { return false; } @@ -158,4 +151,15 @@ public class TypeUtils { } return false; } + + public static boolean hasFloatingPointType(@Nullable PsiExpression expression) { + if (expression == null) { + return false; + } + final PsiType type = expression.getType(); + if (type == null) { + return false; + } + return PsiType.FLOAT.equals(type) || PsiType.DOUBLE.equals(type); + } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/unnecessary_return/UnnecessaryReturn.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/unnecessary_return/UnnecessaryReturn.java new file mode 100644 index 000000000000..b8c679dd5f54 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/unnecessary_return/UnnecessaryReturn.java @@ -0,0 +1,97 @@ +package com.siyeh.igtest.controlflow.unnecessary_return; + +import java.util.concurrent.Callable; + +public class UnnecessaryReturn +{ + + public UnnecessaryReturn() + { + return; + } + + public void foo() + { + return; + } + public void foo2() + { + { + { + return; + } + } + } + + public void bar() + { + if(true) + { + return; + } + } + + public void barzoom() + { + while(true) + { + return; + } + } + +} +class C { + public C() { + return; + } + + public void m1() { + return; + } + + public boolean m2() { + return true; + } + + public void m3(boolean f) { + if (!f) { + return; + } + System.out.println("m3()"); + if (f) { + return; + } + } + + public void m4(boolean f) { + if (f) { + System.out.println("m4()"); + return; + } + else { + return; + } + } + + public void m5() { + while (true) { + System.out.println("m5()"); + return; + } + } + + public void lambda() { + Runnable r = () -> { return; }; + System.out.println(r); + + Callable c = () -> { return 42; }; + System.out.println(c); + } + + void m5(boolean a) { + if (a) return; + else { + System.out.println(); + } + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/unnecessary_return/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/unnecessary_return/expected.xml new file mode 100644 index 000000000000..036f82831456 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/unnecessary_return/expected.xml @@ -0,0 +1,67 @@ + + + + + UnnecessaryReturn.java + 10 + Unnecessary 'return' statement + <code>return</code> is unnecessary as the last statement in a constructor #loc + + + + UnnecessaryReturn.java + 15 + Unnecessary 'return' statement + <code>return</code> is unnecessary as the last statement in a 'void' method #loc + + + + UnnecessaryReturn.java + 21 + Unnecessary 'return' statement + <code>return</code> is unnecessary as the last statement in a 'void' method #loc + + + + UnnecessaryReturn.java + 30 + Unnecessary 'return' statement + <code>return</code> is unnecessary as the last statement in a 'void' method #loc + + + + UnnecessaryReturn.java + 45 + Unnecessary 'return' statement + <code>return</code> is unnecessary as the last statement in a constructor #loc + + + + UnnecessaryReturn.java + 49 + Unnecessary 'return' statement + <code>return</code> is unnecessary as the last statement in a 'void' method #loc + + + + UnnecessaryReturn.java + 62 + Unnecessary 'return' statement + <code>return</code> is unnecessary as the last statement in a 'void' method #loc + + + + UnnecessaryReturn.java + 72 + Unnecessary 'return' statement + <code>return</code> is unnecessary as the last statement in a 'void' method #loc + + + + UnnecessaryReturn.java + 84 + Unnecessary 'return' statement + <code>return</code> is unnecessary as the last statement in a 'void' method #loc + + + \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/verbose/UnnecessaryReturnInspection.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/verbose/UnnecessaryReturnInspection.java deleted file mode 100644 index 08e4fbae335d..000000000000 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/verbose/UnnecessaryReturnInspection.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.siyeh.igtest.verbose; - -public class UnnecessaryReturnInspection -{ - - public UnnecessaryReturnInspection() - { - return; - } - - public void foo() - { - return; - } - public void foo2() - { - { - { - return; - } - } - } - - public void bar() - { - if(true) - { - return; - } - } - - public void barzoom() - { - while(true) - { - return; - } - } - -} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/common/UnnecessaryReturns.java b/plugins/InspectionGadgets/test/common/UnnecessaryReturns.java deleted file mode 100644 index a681eb3fd156..000000000000 --- a/plugins/InspectionGadgets/test/common/UnnecessaryReturns.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2000-2012 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. - */ -import java.util.concurrent.Callable; - -class C { - public C() { - return; - } - - public void m1() { - return; - } - - public boolean m2() { - return true; - } - - public void m3(boolean f) { - if (!f) { - return; - } - System.out.println("m3()"); - if (f) { - return; - } - } - - public void m4(boolean f) { - if (f) { - System.out.println("m4()"); - return; - } - else { - return; - } - } - - public void m5() { - while (true) { - System.out.println("m5()"); - return; - } - } - - public void lambda() { - Runnable r = () -> { return; }; - System.out.println(r); - - Callable c = () -> { return 42; }; - System.out.println(c); - } -} \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/CommonIGInspectionsTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/CommonIGInspectionsTest.java deleted file mode 100644 index 15463ce3ae18..000000000000 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/CommonIGInspectionsTest.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2000-2012 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.siyeh.ig; - -import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase; -import com.intellij.codeInspection.InspectionProfileEntry; -import com.intellij.openapi.application.PluginPathManager; -import com.siyeh.ig.controlflow.UnnecessaryReturnInspection; -import org.jetbrains.annotations.NotNull; - -public class CommonIGInspectionsTest extends LightDaemonAnalyzerTestCase { - @NotNull - @Override - protected String getTestDataPath() { - return PluginPathManager.getPluginHomePath("InspectionGadgets") + "/test"; - } - - private void doTest(boolean checkWarnings, boolean checkInfos, InspectionProfileEntry... tools) throws Exception { - for (InspectionProfileEntry tool : tools) { enableInspectionTool(tool); } - doTest("/common/" + getTestName(false) + ".java", checkWarnings, checkInfos); - } - - public void testUnnecessaryReturns() throws Exception { - final UnnecessaryReturnInspection inspection = new UnnecessaryReturnInspection(); - inspection.ignoreInThenBranch = true; - doTest(true, false, inspection); - } -} diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/UnnecessaryReturnInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/UnnecessaryReturnInspectionTest.java new file mode 100644 index 000000000000..75bbc7d78a66 --- /dev/null +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/UnnecessaryReturnInspectionTest.java @@ -0,0 +1,23 @@ +package com.siyeh.ig.controlflow; + +import com.intellij.codeInspection.ex.LocalInspectionToolWrapper; +import com.intellij.openapi.roots.LanguageLevelProjectExtension; +import com.intellij.pom.java.LanguageLevel; +import com.siyeh.ig.IGInspectionTestCase; + +public class UnnecessaryReturnInspectionTest extends IGInspectionTestCase { + + public void test() throws Exception { + final UnnecessaryReturnInspection inspection = new UnnecessaryReturnInspection(); + inspection.ignoreInThenBranch = true; + final LanguageLevelProjectExtension levelProjectExtension = LanguageLevelProjectExtension.getInstance(getProject()); + final LanguageLevel level = levelProjectExtension.getLanguageLevel(); + try { + levelProjectExtension.setLanguageLevel(LanguageLevel.JDK_1_8); + doTest("com/siyeh/igtest/controlflow/unnecessary_return", new LocalInspectionToolWrapper(inspection), "java 1.8"); + } + finally { + levelProjectExtension.setLanguageLevel(level); + } + } +} diff --git a/plugins/android/common/src/org/jetbrains/android/util/AndroidCommonUtils.java b/plugins/android/common/src/org/jetbrains/android/util/AndroidCommonUtils.java index 0353bfa77f2d..dacb858218b8 100644 --- a/plugins/android/common/src/org/jetbrains/android/util/AndroidCommonUtils.java +++ b/plugins/android/common/src/org/jetbrains/android/util/AndroidCommonUtils.java @@ -135,7 +135,14 @@ public class AndroidCommonUtils { return null; } - return SdkManager.createManager(path + File.separatorChar, log); + // safety from errors inside sdklib + try { + return SdkManager.createManager(path + File.separatorChar, log); + } + catch (Exception e) { + LOG.error(e); + return null; + } } public static void moveAllFiles(@NotNull File from, @NotNull File to, @NotNull Collection newFiles) throws IOException { diff --git a/plugins/android/common/src/org/jetbrains/android/util/AndroidExecutionUtil.java b/plugins/android/common/src/org/jetbrains/android/util/AndroidExecutionUtil.java index 4f709a40268a..228bf274c7fd 100644 --- a/plugins/android/common/src/org/jetbrains/android/util/AndroidExecutionUtil.java +++ b/plugins/android/common/src/org/jetbrains/android/util/AndroidExecutionUtil.java @@ -50,7 +50,7 @@ public final class AndroidExecutionUtil { } else { if (code == 0) { - messages.get(AndroidCompilerMessageKind.INFORMATION).addAll(errMessages); + messages.get(AndroidCompilerMessageKind.WARNING).addAll(errMessages); errMessages.clear(); } return messages; @@ -86,6 +86,7 @@ public final class AndroidExecutionUtil { myMessages = new HashMap>(2); myMessages.put(AndroidCompilerMessageKind.INFORMATION, information); myMessages.put(AndroidCompilerMessageKind.ERROR, error); + myMessages.put(AndroidCompilerMessageKind.WARNING, new ArrayList()); } public Map> getMessages() { diff --git a/plugins/android/common/src/org/jetbrains/android/util/AndroidOSProcessHandler.java b/plugins/android/common/src/org/jetbrains/android/util/AndroidOSProcessHandler.java index 4a48d0687d9a..2c6b9d36064a 100644 --- a/plugins/android/common/src/org/jetbrains/android/util/AndroidOSProcessHandler.java +++ b/plugins/android/common/src/org/jetbrains/android/util/AndroidOSProcessHandler.java @@ -32,6 +32,7 @@ import java.util.List; public class AndroidOSProcessHandler extends BaseOSProcessHandler { @NonNls private static final String IGNORING = "ignoring"; @NonNls private static final String SKIPPING = "skipping"; + @NonNls private static final String DEBUGGABLE_ERROR = "androidmanifest.xml already defines debuggable"; private final List myInfoMessages = new ArrayList(); private final List myErrorMessages = new ArrayList(); @@ -54,7 +55,7 @@ public class AndroidOSProcessHandler extends BaseOSProcessHandler { myInfoMessages.add(line); } else if (outputType == ProcessOutputTypes.STDERR) { - if (l.contains(IGNORING) || l.contains(SKIPPING)) { + if (l.contains(IGNORING) || l.contains(SKIPPING) || l.contains(DEBUGGABLE_ERROR)) { myInfoMessages.add(line); } else { diff --git a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidAdditionalRootProviderService.java b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidAdditionalRootProviderService.java index e23a7d31cf50..5a2872e57753 100644 --- a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidAdditionalRootProviderService.java +++ b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidAdditionalRootProviderService.java @@ -5,6 +5,7 @@ import org.jetbrains.jps.builders.AdditionalRootsProviderService; import org.jetbrains.jps.builders.BuildTarget; import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType; import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor; +import org.jetbrains.jps.builders.storage.BuildDataPaths; import org.jetbrains.jps.incremental.ModuleBuildTarget; import java.io.File; @@ -22,9 +23,9 @@ public class AndroidAdditionalRootProviderService extends AdditionalRootsProvide @NotNull @Override - public List getAdditionalRoots(@NotNull BuildTarget target, File dataStorageRoot) { + public List getAdditionalRoots(@NotNull BuildTarget target, BuildDataPaths dataPaths) { ModuleBuildTarget buildTarget = (ModuleBuildTarget)target; - final File generatedSourcesRoot = AndroidJpsUtil.getGeneratedSourcesStorage(buildTarget.getModule(), dataStorageRoot); + final File generatedSourcesRoot = AndroidJpsUtil.getGeneratedSourcesStorage(buildTarget.getModule(), dataPaths); final List result = new ArrayList(); addRoot(result, buildTarget, new File(generatedSourcesRoot, AndroidJpsUtil.AAPT_GENERATED_SOURCE_ROOT_NAME)); diff --git a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidBuilderService.java b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidBuilderService.java index 85d1f0f5e35e..d6863127ca92 100644 --- a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidBuilderService.java +++ b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidBuilderService.java @@ -28,7 +28,7 @@ public class AndroidBuilderService extends BuilderService { @NotNull @Override - public List> createBuilders() { + public List> createBuilders() { return Arrays.asList(new AndroidDexBuilder(), new AndroidPackagingBuilder()); } diff --git a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidDexBuilder.java b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidDexBuilder.java index 7684f661b890..7354f9e55e80 100644 --- a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidDexBuilder.java +++ b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidDexBuilder.java @@ -33,6 +33,8 @@ import org.jetbrains.jps.ProjectPaths; import org.jetbrains.jps.android.builder.AndroidProjectBuildTarget; import org.jetbrains.jps.android.model.JpsAndroidModuleExtension; import org.jetbrains.jps.android.model.JpsAndroidSdkProperties; +import org.jetbrains.jps.builders.BuildRootDescriptor; +import org.jetbrains.jps.builders.DirtyFilesHolder; import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType; import org.jetbrains.jps.cmdline.ClasspathBootstrap; import org.jetbrains.jps.incremental.*; @@ -53,7 +55,7 @@ import java.util.*; /** * @author Eugene.Kudelevsky */ -public class AndroidDexBuilder extends TargetBuilder { +public class AndroidDexBuilder extends TargetBuilder { private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.android.AndroidDexBuilder"); @NonNls private static final String BUILDER_NAME = "android-dex"; @@ -66,7 +68,8 @@ public class AndroidDexBuilder extends TargetBuilder } @Override - public void build(@NotNull AndroidProjectBuildTarget target, @NotNull CompileContext context) throws ProjectBuildException { + public void build(@NotNull AndroidProjectBuildTarget target, @NotNull CompileContext context, + DirtyFilesHolder holder) throws ProjectBuildException { if (target.getKind() != AndroidProjectBuildTarget.AndroidBuilderKind.DEX && AndroidJpsUtil.isLightBuild(context)) { return; } @@ -83,7 +86,7 @@ public class AndroidDexBuilder extends TargetBuilder } private static void doBuild(CompileContext context) throws IOException, ProjectBuildException { - final File root = context.getProjectDescriptor().dataManager.getDataStorageRoot(); + final File root = context.getProjectDescriptor().dataManager.getDataPaths().getDataStorageRoot(); AndroidFileSetStorage dexStateStorage = null; AndroidFileSetStorage proguardStateStorage = null; diff --git a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidJpsUtil.java b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidJpsUtil.java index a58439655916..79d8c1e7a22f 100644 --- a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidJpsUtil.java +++ b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidJpsUtil.java @@ -16,6 +16,7 @@ import org.jetbrains.android.util.AndroidCompilerMessageKind; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jps.builders.storage.BuildDataPaths; import org.jetbrains.jps.util.JpsPathUtil; import org.jetbrains.jps.ModuleChunk; import org.jetbrains.jps.ProjectPaths; @@ -153,7 +154,7 @@ public class AndroidJpsUtil { @NotNull public static File getDirectoryForIntermediateArtifacts(@NotNull CompileContext context, @NotNull JpsModule module) { - final File androidStorage = new File(context.getProjectDescriptor().dataManager.getDataStorageRoot(), ANDROID_STORAGE_DIR); + final File androidStorage = new File(context.getProjectDescriptor().dataManager.getDataPaths().getDataStorageRoot(), ANDROID_STORAGE_DIR); return new File(new File(androidStorage, INTERMEDIATE_ARTIFACTS_STORAGE), module.getName()); } @@ -520,7 +521,7 @@ public class AndroidJpsUtil { @NotNull public static File getResourcesCacheDir(@NotNull CompileContext context, @NotNull JpsModule module) { - final File androidStorage = new File(context.getProjectDescriptor().dataManager.getDataStorageRoot(), ANDROID_STORAGE_DIR); + final File androidStorage = new File(context.getProjectDescriptor().dataManager.getDataPaths().getDataStorageRoot(), ANDROID_STORAGE_DIR); return new File(new File(androidStorage, RESOURCE_CACHE_STORAGE), module.getName()); } @@ -585,19 +586,19 @@ public class AndroidJpsUtil { @NotNull public static File getGeneratedSourcesStorage(@NotNull JpsModule module, BuildDataManager dataManager) { - return getGeneratedSourcesStorage(module, dataManager.getDataStorageRoot()); + return getGeneratedSourcesStorage(module, dataManager.getDataPaths()); } @NotNull - public static File getGeneratedSourcesStorage(@NotNull JpsModule module, final File dataStorageRoot) { - final File androidStorageRoot = new File(dataStorageRoot, ANDROID_STORAGE_DIR); + public static File getGeneratedSourcesStorage(@NotNull JpsModule module, final BuildDataPaths dataPaths) { + final File androidStorageRoot = new File(dataPaths.getDataStorageRoot(), ANDROID_STORAGE_DIR); final File generatedSourcesRoot = new File(androidStorageRoot, GENERATED_SOURCES_FOLDER_NAME); return new File(generatedSourcesRoot, module.getName()); } @NotNull public static File getGeneratedResourcesStorage(@NotNull JpsModule module, BuildDataManager dataManager) { - final File dataStorageRoot = dataManager.getDataStorageRoot(); + final File dataStorageRoot = dataManager.getDataPaths().getDataStorageRoot(); final File androidStorageRoot = new File(dataStorageRoot, ANDROID_STORAGE_DIR); final File generatedSourcesRoot = new File(androidStorageRoot, GENERATED_RESOURCES_DIR_NAME); return new File(generatedSourcesRoot, module.getName()); diff --git a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidPackagingBuilder.java b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidPackagingBuilder.java index 2421a9fca633..fca96bda9677 100644 --- a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidPackagingBuilder.java +++ b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidPackagingBuilder.java @@ -18,6 +18,8 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.ProjectPaths; import org.jetbrains.jps.android.builder.AndroidProjectBuildTarget; import org.jetbrains.jps.android.model.JpsAndroidModuleExtension; +import org.jetbrains.jps.builders.BuildRootDescriptor; +import org.jetbrains.jps.builders.DirtyFilesHolder; import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType; import org.jetbrains.jps.incremental.*; import org.jetbrains.jps.incremental.messages.BuildMessage; @@ -38,7 +40,7 @@ import java.util.*; /** * @author Eugene.Kudelevsky */ -public class AndroidPackagingBuilder extends TargetBuilder { +public class AndroidPackagingBuilder extends TargetBuilder { @NonNls private static final String BUILDER_NAME = "android-packager"; @NonNls private static final String RELEASE_SUFFIX = ".release"; @NonNls private static final String UNSIGNED_SUFFIX = ".unsigned"; @@ -58,7 +60,8 @@ public class AndroidPackagingBuilder extends TargetBuilder holder) throws ProjectBuildException { if (target.getKind() != AndroidProjectBuildTarget.AndroidBuilderKind.PACKAGING || AndroidJpsUtil.isLightBuild(context)) { return; } @@ -123,7 +126,7 @@ public class AndroidPackagingBuilder extends TargetBuilder modules, @NotNull Map module2state) throws IOException { boolean success = true; - final File dataStorageRoot = context.getProjectDescriptor().dataManager.getDataStorageRoot(); + final File dataStorageRoot = context.getProjectDescriptor().dataManager.getDataPaths().getDataStorageRoot(); final AndroidFileSetStorage storage = new AndroidFileSetStorage(dataStorageRoot, "resource_caching"); try { @@ -212,7 +215,7 @@ public class AndroidPackagingBuilder extends TargetBuilder manifestFiles) throws IOException { boolean success = true; - final File dataStorageRoot = context.getProjectDescriptor().dataManager.getDataStorageRoot(); + final File dataStorageRoot = context.getProjectDescriptor().dataManager.getDataPaths().getDataStorageRoot(); final boolean releaseBuild = AndroidJpsUtil.isReleaseBuild(context); AndroidFileSetStorage resourcesStorage = null; AndroidFileSetStorage assetsStorage = null; @@ -292,7 +295,7 @@ public class AndroidPackagingBuilder extends TargetBuilder modules) throws IOException { final boolean release = AndroidJpsUtil.isReleaseBuild(context); - final File dataStorageRoot = context.getProjectDescriptor().dataManager.getDataStorageRoot(); + final File dataStorageRoot = context.getProjectDescriptor().dataManager.getDataPaths().getDataStorageRoot(); boolean success = true; diff --git a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidSourceGeneratingBuilder.java b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidSourceGeneratingBuilder.java index ab3aef84ee90..ee604d2c8b52 100644 --- a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidSourceGeneratingBuilder.java +++ b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidSourceGeneratingBuilder.java @@ -162,7 +162,7 @@ public class AndroidSourceGeneratingBuilder extends ModuleLevelBuilder { success = false; } - final File dataStorageRoot = dataManager.getDataStorageRoot(); + final File dataStorageRoot = dataManager.getDataPaths().getDataStorageRoot(); final AndroidAptStateStorage aptStorage = new AndroidAptStateStorage(dataStorageRoot); try { diff --git a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/builder/AndroidProjectBuildTarget.java b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/builder/AndroidProjectBuildTarget.java index 89b7525ed1d4..244355050dbc 100644 --- a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/builder/AndroidProjectBuildTarget.java +++ b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/builder/AndroidProjectBuildTarget.java @@ -21,6 +21,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.android.AndroidJpsUtil; import org.jetbrains.jps.builders.*; import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType; +import org.jetbrains.jps.builders.storage.BuildDataPaths; import org.jetbrains.jps.incremental.ModuleBuildTarget; import org.jetbrains.jps.indices.IgnoredFileIndex; import org.jetbrains.jps.indices.ModuleExcludeIndex; @@ -81,7 +82,10 @@ public class AndroidProjectBuildTarget extends BuildTarget @NotNull @Override - public List computeRootDescriptors(JpsModel model, ModuleExcludeIndex index, IgnoredFileIndex ignoredFileIndex) { + public List computeRootDescriptors(JpsModel model, + ModuleExcludeIndex index, + IgnoredFileIndex ignoredFileIndex, + BuildDataPaths dataPaths) { return Collections.emptyList(); } diff --git a/plugins/android/src/META-INF/plugin.xml b/plugins/android/src/META-INF/plugin.xml index 9536901bc038..dcb74c102da0 100644 --- a/plugins/android/src/META-INF/plugin.xml +++ b/plugins/android/src/META-INF/plugin.xml @@ -318,6 +318,7 @@ + diff --git a/plugins/android/src/org/jetbrains/android/AndroidIdIndex.java b/plugins/android/src/org/jetbrains/android/AndroidIdIndex.java index e68a3ec9ea4b..792157300eb5 100644 --- a/plugins/android/src/org/jetbrains/android/AndroidIdIndex.java +++ b/plugins/android/src/org/jetbrains/android/AndroidIdIndex.java @@ -22,7 +22,9 @@ import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.ex.temp.TempFileSystem; import com.intellij.util.containers.HashMap; +import com.intellij.util.containers.HashSet; import com.intellij.util.indexing.*; +import com.intellij.util.io.DataExternalizer; import com.intellij.util.io.EnumeratorStringDescriptor; import com.intellij.util.io.KeyDescriptor; import com.intellij.util.text.CharArrayUtil; @@ -30,15 +32,18 @@ import com.intellij.util.xml.NanoXmlUtil; import org.jetbrains.android.util.AndroidResourceUtil; import org.jetbrains.annotations.NotNull; +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; import java.util.Collections; import java.util.Map; +import java.util.Set; /** * @author Eugene.Kudelevsky */ -public class AndroidIdIndex extends ScalarIndexExtension { - public static final String[] RES_TYPES_CONTAINING_ID_DECLARATIONS = {AndroidConstants.FD_RES_LAYOUT, AndroidConstants.FD_RES_MENU}; - public static final ID INDEX_ID = ID.create("android.id.index"); +public class AndroidIdIndex extends FileBasedIndexExtension> { + public static final ID> INDEX_ID = ID.create("android.id.index"); public static final String MARKER = "$"; private static final FileBasedIndex.InputFilter INPUT_FILTER = new FileBasedIndex.InputFilter() { @@ -49,16 +54,16 @@ public class AndroidIdIndex extends ScalarIndexExtension { } }; - private static final DataIndexer INDEXER = new DataIndexer() { + private static final DataIndexer, FileContent> INDEXER = new DataIndexer, FileContent>() { @Override @NotNull - public Map map(FileContent inputData) { + public Map> map(FileContent inputData) { final CharSequence content = inputData.getContentAsText(); if (content == null || CharArrayUtil.indexOf(content, SdkConstants.NS_RESOURCES, 0) == -1) { return Collections.emptyMap(); } - final HashMap ids = new HashMap(); + final HashMap> map = new HashMap>(); NanoXmlUtil.parse(CharArrayUtil.readerFromCharSequence(inputData.getContentAsText()), new NanoXmlUtil.IXMLBuilderAdapter() { @Override @@ -66,29 +71,52 @@ public class AndroidIdIndex extends ScalarIndexExtension { super.addAttribute(key, nsPrefix, nsURI, value, type); if (AndroidResourceUtil.isIdDeclaration(value)) { - String id = AndroidResourceUtil.getResourceNameByReferenceText(value); + final String id = AndroidResourceUtil.getResourceNameByReferenceText(value); + if (id != null) { - if (ids.isEmpty()) { - ids.put(MARKER, null); - } - ids.put(id, null); + map.put(id, Collections.emptySet()); } } } }); - return ids; + if (map.size() > 0) { + map.put(MARKER, new HashSet(map.keySet())); + } + return map; + } + }; + + private static final DataExternalizer> DATA_EXTERNALIZER = new DataExternalizer>() { + @Override + public void save(DataOutput out, Set value) throws IOException { + out.writeInt(value.size()); + for (String s : value) { + out.writeUTF(s); + } + } + + @Override + public Set read(DataInput in) throws IOException { + final int size = in.readInt(); + final Set result = new HashSet(size); + + for (int i = 0; i < size; i++) { + final String s = in.readUTF(); + result.add(s); + } + return result; } }; @NotNull @Override - public ID getName() { + public ID> getName() { return INDEX_ID; } @NotNull @Override - public DataIndexer getIndexer() { + public DataIndexer, FileContent> getIndexer() { return INDEXER; } @@ -97,6 +125,11 @@ public class AndroidIdIndex extends ScalarIndexExtension { return new EnumeratorStringDescriptor(); } + @Override + public DataExternalizer> getValueExternalizer() { + return DATA_EXTERNALIZER; + } + @Override public FileBasedIndex.InputFilter getInputFilter() { return INPUT_FILTER; @@ -109,6 +142,6 @@ public class AndroidIdIndex extends ScalarIndexExtension { @Override public int getVersion() { - return 2; + return 3; } } diff --git a/plugins/android/src/org/jetbrains/android/augment/AndroidPsiElementFinder.java b/plugins/android/src/org/jetbrains/android/augment/AndroidPsiElementFinder.java new file mode 100644 index 000000000000..03722456bb48 --- /dev/null +++ b/plugins/android/src/org/jetbrains/android/augment/AndroidPsiElementFinder.java @@ -0,0 +1,51 @@ +package org.jetbrains.android.augment; + +import com.intellij.facet.ProjectFacetManager; +import com.intellij.openapi.project.Project; +import com.intellij.psi.JavaPsiFacade; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiElementFinder; +import com.intellij.psi.search.GlobalSearchScope; +import org.jetbrains.android.facet.AndroidFacet; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Eugene.Kudelevsky + */ +public class AndroidPsiElementFinder extends PsiElementFinder { + @Nullable + @Override + public PsiClass findClass(@NotNull String qualifiedName, @NotNull GlobalSearchScope scope) { + final Project project = scope.getProject(); + + if (project == null || + !ProjectFacetManager.getInstance(project).hasFacets(AndroidFacet.ID)) { + return null; + } + + final int lastDot = qualifiedName.lastIndexOf('.'); + if (lastDot < 0) { + return null; + } + final String shortName = qualifiedName.substring(lastDot + 1); + final String parentName = qualifiedName.substring(0, lastDot); + + if (shortName.length() == 0 || !parentName.endsWith(".R")) { + return null; + } + final PsiClass rClass = JavaPsiFacade.getInstance(project).findClass(parentName, scope); + + if (rClass == null) { + return null; + } + return rClass.findInnerClassByName(shortName, false); + } + + @NotNull + @Override + public PsiClass[] findClasses(@NotNull String qualifiedName, @NotNull GlobalSearchScope scope) { + final PsiClass aClass = findClass(qualifiedName, scope); + return aClass != null ? new PsiClass[] {aClass} : PsiClass.EMPTY_ARRAY; + } +} diff --git a/plugins/android/src/org/jetbrains/android/dom/layout/Include.java b/plugins/android/src/org/jetbrains/android/dom/layout/Include.java index fec96eaadcbd..88a4c21efa04 100644 --- a/plugins/android/src/org/jetbrains/android/dom/layout/Include.java +++ b/plugins/android/src/org/jetbrains/android/dom/layout/Include.java @@ -39,4 +39,8 @@ public interface Include extends LayoutElement { @AndroidResourceType("layout") @Convert(ResourceReferenceConverter.class) GenericAttributeValue getLayout(); + + @Convert(ResourceReferenceConverter.class) + @AndroidResourceType("style") + GenericAttributeValue getStyle(); } diff --git a/plugins/android/src/org/jetbrains/android/logcat/AndroidLogcatReceiver.java b/plugins/android/src/org/jetbrains/android/logcat/AndroidLogcatReceiver.java index 5abf7afef561..f55e48de6c09 100644 --- a/plugins/android/src/org/jetbrains/android/logcat/AndroidLogcatReceiver.java +++ b/plugins/android/src/org/jetbrains/android/logcat/AndroidLogcatReceiver.java @@ -19,6 +19,7 @@ package org.jetbrains.android.logcat; import com.android.ddmlib.Log; import com.intellij.openapi.diagnostic.Logger; import org.jetbrains.android.util.AndroidOutputReceiver; +import org.jetbrains.annotations.Nullable; import java.io.IOException; import java.io.PrintWriter; @@ -56,7 +57,7 @@ public class AndroidLogcatReceiver extends AndroidOutputReceiver { myLastMessageHeader = new LogMessageHeader(); myLastMessageHeader.myTime = matcher.group(1); myLastMessageHeader.myPid = Integer.valueOf(matcher.group(2)); - myLastMessageHeader.myLogLevel = Log.LogLevel.getByLetterString(matcher.group(4)); + myLastMessageHeader.myLogLevel = getByLetterString(matcher.group(4)); myLastMessageHeader.myTag = matcher.group(5).trim(); } else { @@ -77,6 +78,21 @@ public class AndroidLogcatReceiver extends AndroidOutputReceiver { } } + @Nullable + private static Log.LogLevel getByLetterString(@Nullable String s) { + if (s == null) { + return null; + } + final Log.LogLevel logLevel = Log.LogLevel.getByLetterString(s); + + /* LogLevel doesn't support messages with severity "F". Log.wtf() is supposed + * to generate "A", but generates "F" */ + if (logLevel == null && s.equals("F")) { + return Log.LogLevel.ASSERT; + } + return logLevel; + } + public boolean isCancelled() { return myCanceled; } diff --git a/plugins/android/src/org/jetbrains/android/maven/AndroidFacetImporterBase.java b/plugins/android/src/org/jetbrains/android/maven/AndroidFacetImporterBase.java index 84873f133a27..5e4340a2847f 100644 --- a/plugins/android/src/org/jetbrains/android/maven/AndroidFacetImporterBase.java +++ b/plugins/android/src/org/jetbrains/android/maven/AndroidFacetImporterBase.java @@ -920,10 +920,7 @@ public abstract class AndroidFacetImporterBase extends FacetImporter> file2ids = new HashMap>(); - for (String key : index.getAllKeys(AndroidIdIndex.INDEX_ID, project)) { - if (!AndroidIdIndex.MARKER.equals(key)) { - if (index.getValues(AndroidIdIndex.INDEX_ID, key, scope).size() > 0) { - - for (VirtualFile file : index.getContainingFiles(AndroidIdIndex.INDEX_ID, key, scope)) { - Set ids = file2ids.get(file); - - if (ids == null) { - ids = new HashSet(); - file2ids.put(file, ids); - } - ids.add(key); - } - } + index.processValues(AndroidIdIndex.INDEX_ID, AndroidIdIndex.MARKER, null, new FileBasedIndex.ValueProcessor>() { + @Override + public boolean process(VirtualFile file, Set value) { + file2ids.put(file, value); + return true; } - } + }, scope); + final Set result = new HashSet(); for (VirtualFile resSubdir : getResourceSubdirsToSearchIds()) { diff --git a/plugins/android/src/org/jetbrains/android/resourceManagers/SystemResourceManager.java b/plugins/android/src/org/jetbrains/android/resourceManagers/SystemResourceManager.java index 6fb06630121f..779c75148b94 100644 --- a/plugins/android/src/org/jetbrains/android/resourceManagers/SystemResourceManager.java +++ b/plugins/android/src/org/jetbrains/android/resourceManagers/SystemResourceManager.java @@ -15,86 +15,30 @@ */ package org.jetbrains.android.resourceManagers; -import com.android.resources.ResourceType; import com.android.sdklib.IAndroidTarget; -import com.android.sdklib.SdkConstants; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.module.Module; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.JavaPsiFacade; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiField; -import com.intellij.util.containers.HashMap; -import com.intellij.util.containers.HashSet; import com.intellij.util.xml.ConvertContext; import org.jetbrains.android.dom.attrs.AttributeDefinitions; import org.jetbrains.android.facet.AndroidFacet; import org.jetbrains.android.sdk.AndroidPlatform; -import org.jetbrains.android.sdk.AndroidTargetData; -import org.jetbrains.android.util.AndroidResourceUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Map; -import java.util.Set; - /** * @author coyote */ public class SystemResourceManager extends ResourceManager { private final AndroidPlatform myPlatform; - private final Map> myPublicResourcesCache = new HashMap>(); public SystemResourceManager(@NotNull AndroidFacet facet, @NotNull AndroidPlatform androidPlatform) { super(facet); myPlatform = androidPlatform; - final Module module = facet.getModule(); - - ApplicationManager.getApplication().runReadAction(new Runnable() { - @Override - public void run() { - buildPublicResourceCache(module); - } - }); - } - - private void buildPublicResourceCache(@NotNull Module module) { - final PsiClass rClass = JavaPsiFacade.getInstance(module.getProject()) - .findClass(SdkConstants.CLASS_R, module.getModuleWithDependenciesAndLibrariesScope(false)); - if (rClass == null) { - return; - } - - for (PsiClass resourceClass : rClass.getInnerClasses()) { - final String resType = resourceClass.getName(); - - if (resType != null) { - Set resNameSet = myPublicResourcesCache.get(resType); - - if (resNameSet == null) { - resNameSet = new HashSet(); - myPublicResourcesCache.put(resType, resNameSet); - } - - for (PsiField resField : resourceClass.getFields()) { - final String resName = resField.getName(); - - if (resName != null) { - resNameSet.add(resName); - } - } - } - } } protected boolean isResourcePublic(@NotNull String type, @NotNull String name) { - final Set fieldNames = myPublicResourcesCache.get(type); - if (fieldNames == null || fieldNames.isEmpty()) { - return false; - } - final String fieldName = AndroidResourceUtil.getFieldNameByResourceName(name); - return fieldNames.contains(fieldName); + return myPlatform.getSdkData().getTargetData(myPlatform.getTarget()). + isResourcePublic(type, name); } @NotNull @@ -117,22 +61,7 @@ public class SystemResourceManager extends ResourceManager { @Nullable public synchronized AttributeDefinitions getAttributeDefinitions() { - final AndroidTargetData targetData = myPlatform.getSdkData().getTargetData(myPlatform.getTarget()); - if (targetData == null) { - return null; - } - final AttributeDefinitions attrDefs = targetData.getAttrDefs(myModule.getProject()); - return attrDefs != null ? new MyAttributeDefinitions(attrDefs) : null; - } - - private class MyAttributeDefinitions extends FilteredAttributeDefinitions { - protected MyAttributeDefinitions(@NotNull AttributeDefinitions wrappee) { - super(wrappee); - } - - @Override - protected boolean isAttributeAcceptable(@NotNull String name) { - return isResourcePublic(ResourceType.ATTR.getName(), name); - } + return myPlatform.getSdkData().getTargetData(myPlatform.getTarget()). + getAttrDefs(myModule.getProject()); } } diff --git a/plugins/android/src/org/jetbrains/android/sdk/AndroidSdkData.java b/plugins/android/src/org/jetbrains/android/sdk/AndroidSdkData.java index 91b53de228de..491f06a4c553 100644 --- a/plugins/android/src/org/jetbrains/android/sdk/AndroidSdkData.java +++ b/plugins/android/src/org/jetbrains/android/sdk/AndroidSdkData.java @@ -350,7 +350,7 @@ public class AndroidSdkData { return mySdkManager; } - @Nullable + @NotNull public AndroidTargetData getTargetData(@NotNull IAndroidTarget target) { final SoftReference targetDataRef = myTargetDatas.get(target); AndroidTargetData targetData = targetDataRef != null ? targetDataRef.get() : null; diff --git a/plugins/android/src/org/jetbrains/android/sdk/AndroidTargetData.java b/plugins/android/src/org/jetbrains/android/sdk/AndroidTargetData.java index 2c110d6c12d4..5ae25345cba0 100644 --- a/plugins/android/src/org/jetbrains/android/sdk/AndroidTargetData.java +++ b/plugins/android/src/org/jetbrains/android/sdk/AndroidTargetData.java @@ -1,5 +1,6 @@ package org.jetbrains.android.sdk; +import com.android.AndroidConstants; import com.android.resources.ResourceType; import com.android.sdklib.IAndroidTarget; import com.intellij.lang.injection.InjectedLanguageManager; @@ -9,6 +10,7 @@ import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; @@ -16,9 +18,13 @@ import com.intellij.psi.PsiManager; import com.intellij.psi.XmlRecursiveElementVisitor; import com.intellij.psi.xml.XmlFile; import com.intellij.psi.xml.XmlTag; +import com.intellij.util.containers.HashMap; import com.intellij.util.containers.HashSet; +import com.intellij.util.xml.NanoXmlUtil; +import org.jetbrains.android.dom.attrs.AttributeDefinitions; import org.jetbrains.android.dom.attrs.AttributeDefinitionsImpl; import org.jetbrains.android.facet.AndroidFacet; +import org.jetbrains.android.resourceManagers.FilteredAttributeDefinitions; import org.jetbrains.android.resourceManagers.SystemResourceManager; import org.jetbrains.android.uipreview.RenderServiceFactory; import org.jetbrains.android.uipreview.RenderingException; @@ -26,6 +32,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.IOException; +import java.util.Map; import java.util.Set; /** @@ -42,13 +49,22 @@ public class AndroidTargetData { private volatile Set myThemes; private volatile boolean myThemesLoaded; + private final Object myPublicResourceCacheLock = new Object(); + private volatile Map> myPublicResourceCache; + public AndroidTargetData(@NotNull AndroidSdkData sdkData, @NotNull IAndroidTarget target) { mySdkData = sdkData; myTarget = target; } @Nullable - public AttributeDefinitionsImpl getAttrDefs(@NotNull final Project project) { + public AttributeDefinitions getAttrDefs(@NotNull Project project) { + final AttributeDefinitionsImpl attrDefs = getAttrDefsImpl(project); + return attrDefs != null ? new PublicAttributeDefinitions(attrDefs) : null; + } + + @Nullable + private AttributeDefinitionsImpl getAttrDefsImpl(@NotNull final Project project) { if (myAttrDefs == null) { ApplicationManager.getApplication().runReadAction(new Runnable() { @Override @@ -65,10 +81,51 @@ public class AndroidTargetData { return myAttrDefs; } + @Nullable + private Map> getPublicResourceCache() { + synchronized (myPublicResourceCacheLock) { + if (myPublicResourceCache == null) { + myPublicResourceCache = parsePublicResCache(); + } + return myPublicResourceCache; + } + } + + public boolean isResourcePublic(@NotNull String type, @NotNull String name) { + final Map> publicResourceCache = getPublicResourceCache(); + + if (publicResourceCache == null) { + return false; + } + final Set set = publicResourceCache.get(type); + return set != null && set.contains(name); + } + + @Nullable + private Map> parsePublicResCache() { + final String resDirPath = myTarget.getPath(IAndroidTarget.RESOURCES); + final String publicXmlPath = resDirPath + '/' + AndroidConstants.FD_RES_VALUES + "/public.xml"; + final VirtualFile publicXml = LocalFileSystem.getInstance().findFileByPath( + FileUtil.toSystemIndependentName(publicXmlPath)); + + if (publicXml != null) { + try { + final MyPublicResourceCacheBuilder builder = new MyPublicResourceCacheBuilder(); + NanoXmlUtil.parse(publicXml.getInputStream(), builder); + myPublicResourceCache = builder.getPublicResourceCache(); + return myPublicResourceCache; + } + catch (IOException e) { + LOG.error(e); + } + } + return null; + } + @Nullable public RenderServiceFactory getRenderServiceFactory(@NotNull Project project) throws RenderingException, IOException { if (myRenderServiceFactory == null) { - final AttributeDefinitionsImpl attrDefs = getAttrDefs(project); + final AttributeDefinitionsImpl attrDefs = getAttrDefsImpl(project); if (attrDefs == null) { return null; } @@ -162,4 +219,57 @@ public class AndroidTargetData { } return xmlFiles; } + + private class PublicAttributeDefinitions extends FilteredAttributeDefinitions { + protected PublicAttributeDefinitions(@NotNull AttributeDefinitions wrappee) { + super(wrappee); + } + + @Override + protected boolean isAttributeAcceptable(@NotNull String name) { + return isResourcePublic(ResourceType.ATTR.getName(), name); + } + } + + private static class MyPublicResourceCacheBuilder extends NanoXmlUtil.IXMLBuilderAdapter { + private final Map> myResult = new HashMap>(); + + private String myName; + private String myType; + + @Override + public void elementAttributesProcessed(String name, String nsPrefix, String nsURI) throws Exception { + if ("public".equals(name) && myName != null && myType != null) { + Set set = myResult.get(myType); + + if (set == null) { + set = new HashSet(); + myResult.put(myType, set); + } + set.add(myName); + } + } + + @Override + public void addAttribute(String key, String nsPrefix, String nsURI, String value, String type) + throws Exception { + if ("name".equals(key)) { + myName = value; + } + else if ("type".endsWith(key)) { + myType = value; + } + } + + @Override + public void startElement(String name, String nsPrefix, String nsURI, String systemID, int lineNr) + throws Exception { + myName = null; + myType = null; + } + + public Map> getPublicResourceCache() { + return myResult; + } + } } diff --git a/plugins/android/src/org/jetbrains/android/uipreview/ProjectCallback.java b/plugins/android/src/org/jetbrains/android/uipreview/ProjectCallback.java index c6bc9a0a8e8a..1883bd9c8c40 100644 --- a/plugins/android/src/org/jetbrains/android/uipreview/ProjectCallback.java +++ b/plugins/android/src/org/jetbrains/android/uipreview/ProjectCallback.java @@ -224,7 +224,9 @@ class ProjectCallback extends LegacyCallback implements IProjectCallback { while (psiClass != null) { final String qName = psiClass.getQualifiedName(); - if (qName == null || !visited.add(qName)) { + if (qName == null || + !visited.add(qName) || + AndroidUtils.VIEW_CLASS_NAME.equals(psiClass.getQualifiedName())) { break; } diff --git a/plugins/android/src/org/jetbrains/android/uipreview/RenderUtil.java b/plugins/android/src/org/jetbrains/android/uipreview/RenderUtil.java index 63bc3aea8345..68118496f5fc 100644 --- a/plugins/android/src/org/jetbrains/android/uipreview/RenderUtil.java +++ b/plugins/android/src/org/jetbrains/android/uipreview/RenderUtil.java @@ -239,7 +239,7 @@ public class RenderUtil { if (brokenClasses.size() > 1) { builder.append("Unable to initialize:\n"); for (String brokenClass : brokenClasses.keySet()) { - builder.append(" ").append(brokenClass).append('\n'); + builder.append("       ").append(brokenClass).append('\n'); } } else { diff --git a/plugins/android/testData/dom/layout/layoutAttrs.xml b/plugins/android/testData/dom/layout/layoutAttrs.xml index 58a9e115e7f8..5bdd5ad4a6f3 100644 --- a/plugins/android/testData/dom/layout/layoutAttrs.xml +++ b/plugins/android/testData/dom/layout/layoutAttrs.xml @@ -6,6 +6,6 @@ /> - + \ No newline at end of file diff --git a/plugins/android/testData/sdk1.5/platforms/android-1.5/data/res/values/public.xml b/plugins/android/testData/sdk1.5/platforms/android-1.5/data/res/values/public.xml index a7af68b584cb..1c17b6ccc05d 100644 --- a/plugins/android/testData/sdk1.5/platforms/android-1.5/data/res/values/public.xml +++ b/plugins/android/testData/sdk1.5/platforms/android-1.5/data/res/values/public.xml @@ -5,16 +5,16 @@ *************************************************************** IMPORTANT NOTE FOR ANYONE MODIFYING THIS FILE READ THIS BEFORE YOU MAKE ANY CHANGES - + This file defines the binary compatibility for resources. As such, you must be very careful when making changes here, or you will completely break backwards compatibility with old applications. - + To avoid breaking compatibility, all new resources must be placed at the end of the list of resources of the same type. Placing a resource in the middle of type will cause all following resources to be assigned new resource numbers, breaking compatibility. - + *************************************************************** *************************************************************** --> @@ -22,13 +22,1669 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -411,7 +2067,9 @@ + + @@ -569,10 +2227,10 @@ - + - + @@ -601,7 +2259,7 @@ - + @@ -748,7 +2406,7 @@ - + @@ -869,8 +2527,11 @@ + + + @@ -916,25 +2577,27 @@ - + + + - + - + - - + + @@ -1062,7 +2725,7 @@ - + @@ -1070,7 +2733,7 @@ - + @@ -1081,8 +2744,912 @@ - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/CvsCheckinHandlerFactory.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/CvsCheckinHandlerFactory.java index 2f0fa0a6c757..eba8130b1a94 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/CvsCheckinHandlerFactory.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/CvsCheckinHandlerFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -19,13 +19,22 @@ package com.intellij.cvsSupport2; import com.intellij.cvsSupport2.checkinProject.AdditionalOptionsPanel; import com.intellij.cvsSupport2.config.CvsConfiguration; import com.intellij.openapi.Disposable; +import com.intellij.openapi.project.Project; import com.intellij.openapi.vcs.CheckinProjectPanel; +import com.intellij.openapi.vcs.FilePath; +import com.intellij.openapi.vcs.ProjectLevelVcsManager; +import com.intellij.openapi.vcs.VcsRoot; +import com.intellij.openapi.vcs.actions.VcsContextFactory; import com.intellij.openapi.vcs.checkin.CheckinHandler; import com.intellij.openapi.vcs.checkin.VcsCheckinHandlerFactory; import com.intellij.openapi.vcs.ui.RefreshableOnComponent; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.containers.HashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Collection; + /** * @author yole */ @@ -41,7 +50,19 @@ class CvsCheckinHandlerFactory extends VcsCheckinHandlerFactory { return new CheckinHandler() { @Nullable public RefreshableOnComponent getAfterCheckinConfigurationPanel(Disposable parentDisposable) { - return new AdditionalOptionsPanel(CvsConfiguration.getInstance(panel.getProject())); + final Project project = panel.getProject(); + final CvsVcs2 cvs = CvsVcs2.getInstance(project); + final ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(project); + final Collection roots = panel.getRoots(); + final Collection files = new HashSet(); + for (VirtualFile root : roots) { + final VcsRoot vcsRoot = vcsManager.getVcsRootObjectFor(root); + if (vcsRoot == null || vcsRoot.getVcs() != cvs) { + continue; + } + files.add(VcsContextFactory.SERVICE.getInstance().createFilePathOn(root)); + } + return new AdditionalOptionsPanel(CvsConfiguration.getInstance(project), files, project); } }; } diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/checkinProject/AdditionalOptionsPanel.form b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/checkinProject/AdditionalOptionsPanel.form index 14b6d418f6ee..fa7033f1e51b 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/checkinProject/AdditionalOptionsPanel.form +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/checkinProject/AdditionalOptionsPanel.form @@ -3,7 +3,7 @@ - + @@ -31,7 +31,7 @@ - + @@ -41,14 +41,6 @@ - - - - - - - - @@ -57,6 +49,12 @@ + + + + + + diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/checkinProject/AdditionalOptionsPanel.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/checkinProject/AdditionalOptionsPanel.java index 99b6083df016..c74d98db23da 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/checkinProject/AdditionalOptionsPanel.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/checkinProject/AdditionalOptionsPanel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -17,40 +17,46 @@ package com.intellij.cvsSupport2.checkinProject; import com.intellij.CvsBundle; import com.intellij.cvsSupport2.config.CvsConfiguration; +import com.intellij.cvsSupport2.cvsoperations.cvsTagOrBranch.TagsHelper; import com.intellij.cvsSupport2.cvsoperations.cvsTagOrBranch.ui.TagNameFieldOwner; import com.intellij.cvsSupport2.ui.experts.importToCvs.CvsFieldValidator; +import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.InputException; +import com.intellij.openapi.ui.TextFieldWithBrowseButton; +import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.ui.RefreshableOnComponent; import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.util.Collection; public class AdditionalOptionsPanel implements RefreshableOnComponent, TagNameFieldOwner { private JPanel myPanel; - private JTextField myTagName; + private TextFieldWithBrowseButton myTagName; private JCheckBox myTag; private JLabel myErrorLabel; + private JCheckBox myOverrideExisting; private final CvsConfiguration myConfiguration; private boolean myIsCorrect = true; private String myErrorMessage; - private JCheckBox myOverrideExisting; - public AdditionalOptionsPanel(CvsConfiguration configuration) { + public AdditionalOptionsPanel(CvsConfiguration configuration, Collection files, Project project) { myConfiguration = configuration; + TagsHelper.addChooseBranchAction(myTagName, files, project); myTag.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { updateEnable(); } }); - CvsFieldValidator.installOn(this, myTagName, myErrorLabel, new AbstractButton[]{myTag}); + CvsFieldValidator.installOn(this, myTagName.getTextField(), myErrorLabel, new AbstractButton[]{myTag}); } private void updateEnable() { - boolean tag = myTag.isSelected(); - myTagName.setEditable(tag); + final boolean tag = myTag.isSelected(); + myTagName.setEnabled(tag); myOverrideExisting.setEnabled(tag); } diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/cvsTagOrBranch/TagsHelper.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/cvsTagOrBranch/TagsHelper.java index 064a526c0534..441e3b795e59 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/cvsTagOrBranch/TagsHelper.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/cvsTagOrBranch/TagsHelper.java @@ -122,8 +122,8 @@ public class TagsHelper { return (BranchesProvider)operation; } - private static Collection collectAllBranches(Collection files, Project project) throws VcsException { - if (files.isEmpty()) { + public static Collection findVcsRoots(FilePath[] files, Project project) { + if (files.length == 0) { return Collections.emptyList(); } final Collection roots = new HashSet(); @@ -135,10 +135,14 @@ public class TagsHelper { } roots.add(VcsContextFactory.SERVICE.getInstance().createFilePathOn(root)); } - if (roots.isEmpty()) { + return roots; + } + + private static Collection collectAllBranches(Collection files, Project project) throws VcsException { + if (files.isEmpty()) { return Collections.emptyList(); } - return getBranchesProvider(new LogOperation(roots), project).getAllBranches(); + return getBranchesProvider(new LogOperation(files), project).getAllBranches(); } private static void showErrorMessage(VcsException e1) { diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/cvsTagOrBranch/ui/CreateTagDialog.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/cvsTagOrBranch/ui/CreateTagDialog.java index 46ad32b8b6b0..a7fe33cebb7b 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/cvsTagOrBranch/ui/CreateTagDialog.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/cvsTagOrBranch/ui/CreateTagDialog.java @@ -23,7 +23,6 @@ import com.intellij.openapi.ui.TextFieldWithBrowseButton; import com.intellij.openapi.vcs.FilePath; import javax.swing.*; -import java.util.Arrays; /** * author: lesya @@ -37,7 +36,7 @@ public class CreateTagDialog extends CvsTagDialog { private JLabel myTagOrBranchLabel; private JLabel myErrorLabel; - public CreateTagDialog(final FilePath[] files, final Project project, boolean isTag) { + public CreateTagDialog(FilePath[] files, Project project, boolean isTag) { if (isTag) { myTagOrBranchLabel.setText(CvsBundle.message("label.tag.name")); mySwitchToThisTag.setText(CvsBundle.message("checkbox.switch.to.this.tag")); @@ -48,7 +47,7 @@ public class CreateTagDialog extends CvsTagDialog { mySwitchToThisTag.setText(CvsBundle.message("checkbox.switch.to.this.branch")); myOverrideExisting.setText(CvsBundle.message("checkbox.create.tag.override.existing.branch")); } - TagsHelper.addChooseBranchAction(myTagName, Arrays.asList(files), project); + TagsHelper.addChooseBranchAction(myTagName, TagsHelper.findVcsRoots(files, project), project); setTitle(isTag ? CvsBundle.message("operation.name.create.tag") : CvsBundle.message("operation.name.create.branch")); CvsFieldValidator.installOn(this, myTagName.getTextField(), myErrorLabel); init(); diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/cvsTagOrBranch/ui/DeleteTagDialog.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/cvsTagOrBranch/ui/DeleteTagDialog.java index ef928a174915..11b628943d07 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/cvsTagOrBranch/ui/DeleteTagDialog.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/cvsTagOrBranch/ui/DeleteTagDialog.java @@ -23,7 +23,6 @@ import com.intellij.openapi.ui.TextFieldWithBrowseButton; import com.intellij.openapi.vcs.FilePath; import javax.swing.*; -import java.util.Arrays; /** * author: lesya @@ -34,8 +33,8 @@ public class DeleteTagDialog extends CvsTagDialog { private JPanel myPanel; private JLabel myErrorLabel; - public DeleteTagDialog(final FilePath[] files, final Project project) { - TagsHelper.addChooseBranchAction(myTagName, Arrays.asList(files), project); + public DeleteTagDialog(FilePath[] files, Project project) { + TagsHelper.addChooseBranchAction(myTagName, TagsHelper.findVcsRoots(files, project), project); CvsFieldValidator.installOn(this, myTagName.getTextField(), myErrorLabel); setTitle(CvsBundle.message("action.name.delete.tag")); init(); diff --git a/plugins/git4idea/src/git4idea/history/browser/LowLevelAccessImpl.java b/plugins/git4idea/src/git4idea/history/browser/LowLevelAccessImpl.java index f774ff6a8bd0..10e4616e253f 100644 --- a/plugins/git4idea/src/git4idea/history/browser/LowLevelAccessImpl.java +++ b/plugins/git4idea/src/git4idea/history/browser/LowLevelAccessImpl.java @@ -15,6 +15,7 @@ */ package git4idea.history.browser; +import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Getter; @@ -27,6 +28,7 @@ import com.intellij.util.AsynchConsumer; import git4idea.GitBranch; import git4idea.GitTag; import git4idea.GitUtil; +import git4idea.PlatformFacade; import git4idea.branch.GitBranchesCollection; import git4idea.config.GitConfigUtil; import git4idea.history.GitHistoryUtils; @@ -110,7 +112,7 @@ public class LowLevelAccessImpl implements LowLevelAccess { if (! child.exists()) { throw new VcsException("No git repository in " + myRoot.getPath()); } - repository = GitRepositoryImpl.getLightInstance(myRoot, myProject, myProject); + repository = GitRepositoryImpl.getLightInstance(myRoot, myProject, ServiceManager.getService(myProject, PlatformFacade.class), myProject); repository.update(GitRepository.TrackedTopic.BRANCHES); repository.getBranches(); } diff --git a/plugins/git4idea/src/git4idea/repo/GitRepositoryImpl.java b/plugins/git4idea/src/git4idea/repo/GitRepositoryImpl.java index 80e5e7979eec..0e95f68a22da 100644 --- a/plugins/git4idea/src/git4idea/repo/GitRepositoryImpl.java +++ b/plugins/git4idea/src/git4idea/repo/GitRepositoryImpl.java @@ -16,10 +16,9 @@ package git4idea.repo; 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.vfs.VfsUtil; +import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Consumer; import com.intellij.util.concurrency.QueueProcessor; @@ -43,6 +42,7 @@ public class GitRepositoryImpl implements GitRepository, Disposable { private static final Object STUB_OBJECT = new Object(); private final Project myProject; + @NotNull private final PlatformFacade myPlatformFacade; private final VirtualFile myRootDir; private final GitRepositoryReader myReader; private final VirtualFile myGitDir; @@ -59,29 +59,29 @@ public class GitRepositoryImpl implements GitRepository, Disposable { /** * Get the GitRepository instance from the {@link GitRepositoryManager}. * If you need to have an instance of GitRepository for a repository outside the project, use - * {@link #getLightInstance(com.intellij.openapi.vfs.VirtualFile, com.intellij.openapi.project.Project, com.intellij.openapi.Disposable)}. + * {@link #getLightInstance(VirtualFile, Project, PlatformFacade, Disposable)}. */ - private GitRepositoryImpl(@NotNull VirtualFile rootDir, @NotNull Project project, @NotNull Disposable parentDisposable, - final boolean light) { + private GitRepositoryImpl(@NotNull VirtualFile rootDir, @NotNull PlatformFacade facade, @NotNull Project project, + @NotNull Disposable parentDisposable, final boolean light) { myRootDir = rootDir; + myPlatformFacade = facade; myProject = project; Disposer.register(parentDisposable, this); myGitDir = GitUtil.findGitDir(myRootDir); assert myGitDir != null : ".git directory wasn't found under " + rootDir.getPresentableUrl(); - myReader = new GitRepositoryReader(VfsUtil.virtualToIoFile(myGitDir)); + myReader = new GitRepositoryReader(VfsUtilCore.virtualToIoFile(myGitDir)); myMessageBus = project.getMessageBus(); myNotifier = new QueueProcessor(new NotificationConsumer(myProject, myMessageBus), myProject.getDisposed()); - if (! light) { + if (!light) { myUntrackedFilesHolder = new GitUntrackedFilesHolder(this); Disposer.register(this, myUntrackedFilesHolder); - - update(TrackedTopic.ALL); } else { myUntrackedFilesHolder = null; } + update(TrackedTopic.ALL); } /** @@ -90,16 +90,18 @@ public class GitRepositoryImpl implements GitRepository, Disposable { * {@link GitUntrackedFilesHolder}. */ @NotNull - public static GitRepository getLightInstance(@NotNull VirtualFile root, @NotNull Project project, @NotNull Disposable parentDisposable) { - return new GitRepositoryImpl(root, project, parentDisposable, true); + public static GitRepository getLightInstance(@NotNull VirtualFile root, @NotNull Project project, @NotNull PlatformFacade facade, + @NotNull Disposable parentDisposable) { + return new GitRepositoryImpl(root, facade, project, parentDisposable, true); } /** * Returns the full-functional instance of GitRepository - with UntrackedFilesHolder and GitRepositoryUpdater. * This is used for repositories registered in project, and should be optained via {@link GitRepositoryManager}. */ - public static GitRepository getFullInstance(@NotNull VirtualFile root, @NotNull Project project, @NotNull Disposable parentDisposable) { - GitRepositoryImpl repository = new GitRepositoryImpl(root, project, parentDisposable, false); + public static GitRepository getFullInstance(@NotNull VirtualFile root, @NotNull Project project, @NotNull PlatformFacade facade, + @NotNull Disposable parentDisposable) { + GitRepositoryImpl repository = new GitRepositoryImpl(root, facade, project, parentDisposable, false); repository.myUntrackedFilesHolder.setupVfsListener(project); repository.setupUpdater(); return repository; @@ -240,8 +242,8 @@ public class GitRepositoryImpl implements GitRepository, Disposable { } private void updateConfig() { - File configFile = new File(VfsUtil.virtualToIoFile(myGitDir), "config"); - myConfig = GitConfig.read(ServiceManager.getService(PlatformFacade.class), configFile); + File configFile = new File(VfsUtilCore.virtualToIoFile(myGitDir), "config"); + myConfig = GitConfig.read(myPlatformFacade, configFile); } /** diff --git a/plugins/git4idea/src/git4idea/repo/GitRepositoryManagerImpl.java b/plugins/git4idea/src/git4idea/repo/GitRepositoryManagerImpl.java index 11462582d4c4..c46d49ef4bc6 100644 --- a/plugins/git4idea/src/git4idea/repo/GitRepositoryManagerImpl.java +++ b/plugins/git4idea/src/git4idea/repo/GitRepositoryManagerImpl.java @@ -50,9 +50,11 @@ public class GitRepositoryManagerImpl extends AbstractProjectComponent implement @NotNull private final Set myListeners = new HashSet(); @NotNull private final ReentrantReadWriteLock REPO_LOCK = new ReentrantReadWriteLock(); + @NotNull private final PlatformFacade myPlatformFacade; public GitRepositoryManagerImpl(@NotNull Project project, @NotNull PlatformFacade platformFacade) { super(project); + myPlatformFacade = platformFacade; myVcsManager = ProjectLevelVcsManager.getInstance(myProject); myVcs = platformFacade.getVcs(myProject); } @@ -227,7 +229,7 @@ public class GitRepositoryManagerImpl extends AbstractProjectComponent implement } private GitRepository createGitRepository(VirtualFile root) { - GitRepository repository = GitRepositoryImpl.getFullInstance(root, myProject, this); + GitRepository repository = GitRepositoryImpl.getFullInstance(root, myProject, myPlatformFacade, this); for (GitRepositoryChangeListener listener : myListeners) { repository.addListener(listener); } diff --git a/plugins/git4idea/src/git4idea/repo/GitRepositoryReader.java b/plugins/git4idea/src/git4idea/repo/GitRepositoryReader.java index 0b7a08ae321b..0432f040b8de 100644 --- a/plugins/git4idea/src/git4idea/repo/GitRepositoryReader.java +++ b/plugins/git4idea/src/git4idea/repo/GitRepositoryReader.java @@ -15,13 +15,9 @@ */ package git4idea.repo; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.vfs.encoding.EncodingManager; import com.intellij.util.Processor; -import com.intellij.vcsUtil.VcsUtil; import git4idea.GitBranch; import git4idea.branch.GitBranchesCollection; import org.jetbrains.annotations.NonNls; @@ -32,7 +28,6 @@ import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; -import java.nio.charset.Charset; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -155,13 +150,13 @@ class GitRepositoryReader { if (!headName.exists()) { return null; } - String branchName = tryLoadFile(headName, calcEncoding(headName)).trim(); + String branchName = tryLoadFile(headName).trim(); if (branchName.startsWith(REFS_HEADS_PREFIX)) { branchName = branchName.substring(REFS_HEADS_PREFIX.length()); } return new GitBranch(branchName, true, false); } - + private boolean isMergeInProgress() { File mergeHead = new File(myGitDir, "MERGE_HEAD"); return mergeHead.exists(); @@ -298,7 +293,7 @@ class GitRepositoryReader { @Nullable private static String loadHashFromBranchFile(@NotNull File branchFile) { try { - return tryLoadFile(branchFile, null); + return tryLoadFile(branchFile); } catch (GitRepoStateException e) { // notify about error but don't break the process LOG.error("Couldn't read " + branchFile, e); @@ -341,7 +336,7 @@ class GitRepositoryReader { if (!myPackedRefsFile.exists()) { return GitBranchesCollection.EMPTY; } - final String content = tryLoadFile(myPackedRefsFile, calcEncoding(myPackedRefsFile)); + final String content = tryLoadFile(myPackedRefsFile); for (String line : content.split("\n")) { parsePackedRefsLine(line, new PackedRefsLineResultHandler() { @@ -362,7 +357,7 @@ class GitRepositoryReader { private static String readBranchFile(File branchFile) { - String rev = tryLoadFile(branchFile, null); // we expect just hash in branch file, no need to check encoding + String rev = tryLoadFile(branchFile); return rev.trim(); } @@ -373,7 +368,7 @@ class GitRepositoryReader { } private Head readHead() { - String headContent = tryLoadFile(myHeadFile, calcEncoding(myHeadFile)); + String headContent = tryLoadFile(myHeadFile); headContent = headContent.trim(); // remove possible leading and trailing spaces to clearly match regexps Matcher matcher = BRANCH_PATTERN.matcher(headContent); @@ -396,15 +391,14 @@ class GitRepositoryReader { * Loads the file content. * Tries 3 times, then a {@link GitRepoStateException} is thrown. * @param file File to read. - * @param encoding Encoding of the file, or null for using "UTF-8". Encoding is important for non-latin branch names. * @return file content. */ @NotNull - private static String tryLoadFile(@NotNull final File file, @Nullable final Charset encoding) { + private static String tryLoadFile(final File file) { return tryOrThrow(new Callable() { @Override public String call() throws Exception { - return FileUtil.loadFile(file, encoding == null ? "UTF-8" : encoding.name()); + return FileUtil.loadFile(file); } }, file); } @@ -484,15 +478,6 @@ class GitRepositoryReader { void handleResult(@Nullable String hash, @Nullable String branchName); } - /** - * @return File encoding or null if the encoding is unknown. - */ - @Nullable - private static Charset calcEncoding(File file) { - VirtualFile vf = VcsUtil.getVirtualFile(file); - return ApplicationManager.getApplication().isDisposed() ? null : EncodingManager.getInstance().getEncoding(vf, false); - } - /** * Container to hold two information items: current .git/HEAD value and is Git on branch. */ diff --git a/plugins/git4idea/tests/git4idea/crlf/GitCrlfProblemsDetectorTest.groovy b/plugins/git4idea/tests/git4idea/crlf/GitCrlfProblemsDetectorTest.groovy index 90073d9771ea..f09aef3ad343 100644 --- a/plugins/git4idea/tests/git4idea/crlf/GitCrlfProblemsDetectorTest.groovy +++ b/plugins/git4idea/tests/git4idea/crlf/GitCrlfProblemsDetectorTest.groovy @@ -60,7 +60,7 @@ class GitCrlfProblemsDetectorTest { git ("init") - GitRepository repository = GitRepositoryImpl.getLightInstance(new GitMockVirtualFile(myRootDir), myProject, myProject) + GitRepository repository = GitRepositoryImpl.getLightInstance(new GitMockVirtualFile(myRootDir), myProject, myPlatformFacade, myProject) ((GitTestRepositoryManager)myPlatformFacade.getRepositoryManager(myProject)).add(repository) } diff --git a/plugins/git4idea/tests/git4idea/repo/GitRepositoryTest.java b/plugins/git4idea/tests/git4idea/repo/GitRepositoryTest.java index 0f308f8e7e66..83b74a198cd5 100644 --- a/plugins/git4idea/tests/git4idea/repo/GitRepositoryTest.java +++ b/plugins/git4idea/tests/git4idea/repo/GitRepositoryTest.java @@ -15,8 +15,10 @@ */ package git4idea.repo; +import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.vfs.VfsUtil; import git4idea.GitBranch; +import git4idea.PlatformFacade; import git4idea.tests.GitTest; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -48,7 +50,8 @@ public class GitRepositoryTest extends GitTest { @BeforeMethod public void setUp(Method testMethod) throws Exception { super.setUp(testMethod); - myRepository = GitRepositoryImpl.getFullInstance(myRepo.getVFRootDir(), myProject, myProject); + PlatformFacade facade = ServiceManager.getService(myProject, PlatformFacade.class); + myRepository = GitRepositoryImpl.getFullInstance(myRepo.getVFRootDir(), myProject, facade, myProject); myReader = new GitRepositoryReader(new File(VfsUtil.virtualToIoFile(myRepository.getRoot()), ".git")); } diff --git a/plugins/git4idea/tests/git4idea/test/GitExec.java b/plugins/git4idea/tests/git4idea/test/GitExec.java index faaa945d817a..a0e6cb98e590 100644 --- a/plugins/git4idea/tests/git4idea/test/GitExec.java +++ b/plugins/git4idea/tests/git4idea/test/GitExec.java @@ -15,6 +15,7 @@ */ package git4idea.test; +import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; @@ -22,6 +23,7 @@ import com.intellij.testFramework.vcs.AbstractVcsTestCase; import com.intellij.testFramework.VfsTestUtil; import com.intellij.util.ArrayUtil; import com.intellij.util.ui.UIUtil; +import git4idea.PlatformFacade; import git4idea.repo.GitRepository; import git4idea.repo.GitRepositoryImpl; import org.jetbrains.annotations.NotNull; @@ -42,7 +44,7 @@ public class GitExec { public static GitRepository init(@NotNull Project project, @NotNull VirtualFile root) throws IOException { new GitTestRunEnv(new File(root.getPath())).run("init"); root.refresh(false, true); - return GitRepositoryImpl.getLightInstance(root, project, project); + return GitRepositoryImpl.getLightInstance(root, project, ServiceManager.getService(project, PlatformFacade.class), project); } /** @@ -58,7 +60,8 @@ public class GitExec { VirtualFile root = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(destinationPath)); assert root != null; root.refresh(false, true); - return bare ? null : GitRepositoryImpl.getLightInstance(root, project, project); + return bare ? null : GitRepositoryImpl.getLightInstance(root, project, + ServiceManager.getService(project, PlatformFacade.class), project); } public static String push(@NotNull GitRepository repository, String... args) throws IOException { diff --git a/plugins/git4idea/tests/git4idea/test/GitLightRepository.java b/plugins/git4idea/tests/git4idea/test/GitLightRepository.java index cd7013becb59..7bdf48abd357 100644 --- a/plugins/git4idea/tests/git4idea/test/GitLightRepository.java +++ b/plugins/git4idea/tests/git4idea/test/GitLightRepository.java @@ -33,7 +33,10 @@ import java.util.Collection; * Stores information about commits and branches in memory. * * @author Kirill Likhodedov + * + * @deprecated Use the standard GitRepository instance returned from {@link GitRepositoryImpl.getLightInstance()} */ +@Deprecated public class GitLightRepository implements GitRepository { public static class Commit { diff --git a/plugins/git4idea/tests/git4idea/test/MockGit.groovy b/plugins/git4idea/tests/git4idea/test/MockGit.groovy index c396f244806c..d41e6cf77e09 100644 --- a/plugins/git4idea/tests/git4idea/test/MockGit.groovy +++ b/plugins/git4idea/tests/git4idea/test/MockGit.groovy @@ -34,7 +34,10 @@ import static git4idea.test.MockGit.OperationName.GET_UNMERGED_FILES /** * * @author Kirill Likhodedov + * + * @deprecated Use {@link GitTestImpl} - prefer fair Git to the simulation. */ +@Deprecated class MockGit implements Git { public static final GitCommandResult FAKE_SUCCESS_RESULT = new GitCommandResult(true, 0, Collections.emptyList(), Collections.emptyList()) diff --git a/plugins/groovy/resources/inspectionDescriptions/GrPackage.html b/plugins/groovy/resources/inspectionDescriptions/GrPackage.html new file mode 100644 index 000000000000..265089823c8a --- /dev/null +++ b/plugins/groovy/resources/inspectionDescriptions/GrPackage.html @@ -0,0 +1,7 @@ + + + + This inspection reports files which declared package mismatches with an expected one. + + + diff --git a/plugins/groovy/src/META-INF/plugin.xml b/plugins/groovy/src/META-INF/plugin.xml index a4b2104dd0dd..260e29c46a8d 100644 --- a/plugins/groovy/src/META-INF/plugin.xml +++ b/plugins/groovy/src/META-INF/plugin.xml @@ -478,7 +478,7 @@ - @@ -747,6 +747,10 @@ bundle="org.jetbrains.plugins.groovy.codeInspection.GroovyInspectionBundle" key="clashing.getters" groupName="Potentially confusing code constructs" enabledByDefault="false" level="WARNING" implementationClass="org.jetbrains.plugins.groovy.codeInspection.confusing.ClashingGettersInspection"/> + collectControlFlowOwners(final PsiFile file, final Editor editor, final int offset) { - final PsiElement elementAtCaret = file.findElementAt(GrIntroduceHandlerBase.correctOffset(editor, offset)); + final PsiElement elementAtCaret = file.findElementAt(offset); final List result = new ArrayList(); for (GrControlFlowOwner owner = ControlFlowUtils.findControlFlowOwner(elementAtCaret); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/GrGetPsiTypeAction.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/GrGetPsiTypeAction.java index 099f43c85f40..bcc284c5d90b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/GrGetPsiTypeAction.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/GrGetPsiTypeAction.java @@ -55,7 +55,7 @@ public class GrGetPsiTypeAction extends AnAction implements DumbAware { int offset = editor.getCaretModel().getOffset(); - List expressions = GrIntroduceHandlerBase.collectExpressions(psiFile, editor, offset); + List expressions = GrIntroduceHandlerBase.collectExpressions(psiFile, editor, offset, true); if (expressions.size() == 0) return; if (expressions.size() == 1) { passInner(expressions.get(0)); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GrHighlightUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GrHighlightUtil.java index f59869f4abf7..fd36a30c3642 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GrHighlightUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GrHighlightUtil.java @@ -35,12 +35,16 @@ import org.jetbrains.plugins.groovy.highlighter.DefaultHighlighter; import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; import org.jetbrains.plugins.groovy.lang.lexer.TokenSets; import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement; +import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrAssignmentExpression; 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.GrUnaryExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrExtendsClause; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrImplementsClause; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod; import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass; import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils; @@ -185,7 +189,7 @@ public class GrHighlightUtil { if (isDeclarationAssignment(referenceExpression)) return false; GrExpression qualifier = referenceExpression.getQualifier(); - if (qualifier != null && qualifier.getType() == null) return false; + if (qualifier != null && qualifier.getType() == null && !isRefToPackage(qualifier)) return false; if (qualifier != null && referenceExpression.getDotTokenType() == GroovyTokenTypes.mMEMBER_POINTER && @@ -204,6 +208,10 @@ public class GrHighlightUtil { return true; } + private static boolean isRefToPackage(GrExpression expr) { + return expr instanceof GrReferenceExpression && ((GrReferenceExpression)expr).resolve() instanceof PsiPackage; + } + public static TextRange getMethodHeaderTextRange(PsiMethod method) { final PsiModifierList modifierList = method.getModifierList(); final PsiParameterList parameterList = method.getParameterList(); @@ -221,4 +229,25 @@ public class GrHighlightUtil { final PsiElement refNameElement = refElement.getReferenceNameElement(); return refNameElement != null ? refNameElement : refElement; } + + public static TextRange getClassHeaderTextRange(GrTypeDefinition clazz) { + final GrModifierList modifierList = clazz.getModifierList(); + final int startOffset = modifierList != null ? modifierList.getTextOffset() : clazz.getTextOffset(); + final GrImplementsClause implementsClause = clazz.getImplementsClause(); + + final int endOffset; + if (implementsClause != null) { + endOffset = implementsClause.getTextRange().getEndOffset(); + } + else { + final GrExtendsClause extendsClause = clazz.getExtendsClause(); + if (extendsClause != null) { + endOffset = extendsClause.getTextRange().getEndOffset(); + } + else { + endOffset = clazz.getNameIdentifierGroovy().getTextRange().getEndOffset(); + } + } + return new TextRange(startOffset, endOffset); + } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GrKeywordAndDeclarationHighlighter.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GrKeywordAndDeclarationHighlighter.java index 85927b279fdf..4f4c37bbd315 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GrKeywordAndDeclarationHighlighter.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GrKeywordAndDeclarationHighlighter.java @@ -21,6 +21,7 @@ import com.intellij.codeInsight.daemon.impl.UpdateHighlightersUtil; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.colors.TextAttributesKey; import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiErrorElement; import com.intellij.psi.PsiRecursiveElementVisitor; @@ -80,6 +81,12 @@ public class GrKeywordAndDeclarationHighlighter extends TextEditorHighlightingPa if (element instanceof GrLabel) { addInfo(element, LABEL); } + else if (element instanceof GrCodeReferenceElement) { + PsiElement resolved = ((GrCodeReferenceElement)element).resolve(); + if (resolved instanceof PsiClass && ((PsiClass)resolved).isAnnotationType()) { + addInfo(element, ANNOTATION); + } + } super.visitElement(element); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GrReferenceHighlighter.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GrReferenceHighlighter.java index 59ddb6cbdee4..99f693988e1c 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GrReferenceHighlighter.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GrReferenceHighlighter.java @@ -23,11 +23,14 @@ import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.colors.TextAttributesKey; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiRecursiveElementWalkingVisitor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GroovyUnresolvedAccessInspection; import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement; -import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; +import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; +import org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement; import java.util.ArrayList; import java.util.List; @@ -36,10 +39,10 @@ import java.util.List; * @author Max Medvedev */ public class GrReferenceHighlighter extends TextEditorHighlightingPass { - @NotNull private final GroovyFile myFile; + @NotNull private final GroovyFileBase myFile; @Nullable private List myInfos = null; - protected GrReferenceHighlighter(@Nullable Document document, @NotNull GroovyFile file) { + public GrReferenceHighlighter(@Nullable Document document, @NotNull GroovyFileBase file) { super(file.getProject(), document); myFile = file; } @@ -47,14 +50,30 @@ public class GrReferenceHighlighter extends TextEditorHighlightingPass { @Override public void doCollectInformation(@NotNull ProgressIndicator progress) { myInfos = new ArrayList(); - myFile.accept(new PsiRecursiveElementWalkingVisitor() { + myFile.accept(new GroovyRecursiveElementVisitor() { @Override - public void visitElement(PsiElement element) { - super.visitElement(element); - if (element instanceof GrReferenceElement) { - visit((GrReferenceElement)element); + public void visitReferenceExpression(GrReferenceExpression referenceExpression) { + super.visitReferenceExpression(referenceExpression); + + visit(referenceExpression); + HighlightInfo info = GroovyUnresolvedAccessInspection.checkReferenceExpression(referenceExpression); + if (info != null) { + myInfos.add(info); } } + + @Override + public void visitCodeReferenceElement(GrCodeReferenceElement refElement) { + super.visitCodeReferenceElement(refElement); + + visit(refElement); + + HighlightInfo info = GroovyUnresolvedAccessInspection.checkCodeReferenceElement(refElement); + if (info != null) { + myInfos.add(info); + } + } + private void visit(GrReferenceElement element) { final PsiElement resolved = element.resolve(); final TextAttributesKey attribute = GrHighlightUtil.getDeclarationHighlightingAttribute(resolved); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GrReferenceHighlighterFactory.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GrReferenceHighlighterFactory.java index 33d55a3f1950..c0a8e9635d82 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GrReferenceHighlighterFactory.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GrReferenceHighlighterFactory.java @@ -23,7 +23,7 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; +import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; /** * @author Max Medvedev @@ -36,7 +36,7 @@ public class GrReferenceHighlighterFactory extends AbstractProjectComponent impl @Override public TextEditorHighlightingPass createHighlightingPass(@NotNull PsiFile file, @NotNull Editor editor) { - if (!(file instanceof GroovyFile)) return null; - return new GrReferenceHighlighter(editor.getDocument(), (GroovyFile)file); + if (!(file instanceof GroovyFileBase)) return null; + return new GrReferenceHighlighter(editor.getDocument(), (GroovyFileBase)file); } } 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 36d9fbf9a9d0..1ab2daa88197 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java @@ -16,15 +16,13 @@ package org.jetbrains.plugins.groovy.annotator; -import com.intellij.codeInsight.daemon.HighlightDisplayKey; import com.intellij.codeInsight.daemon.JavaErrorMessages; -import com.intellij.codeInsight.daemon.QuickFixActionRegistrar; -import com.intellij.codeInsight.daemon.impl.quickfix.*; +import com.intellij.codeInsight.daemon.impl.quickfix.AddMethodBodyFix; +import com.intellij.codeInsight.daemon.impl.quickfix.CreateConstructorMatchingSuperFix; +import com.intellij.codeInsight.daemon.impl.quickfix.DeleteMethodBodyFix; import com.intellij.codeInsight.generation.OverrideImplementUtil; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInsight.intention.QuickFixFactory; -import com.intellij.codeInsight.quickfix.UnresolvedReferenceQuickFixProvider; -import com.intellij.codeInspection.ProblemHighlightType; import com.intellij.lang.ASTNode; import com.intellij.lang.annotation.Annotation; import com.intellij.lang.annotation.AnnotationHolder; @@ -32,10 +30,8 @@ import com.intellij.lang.annotation.Annotator; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.project.IndexNotReadyException; -import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.psi.impl.light.LightElement; import com.intellij.psi.infos.CandidateInfo; @@ -52,18 +48,12 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.GroovyBundle; import org.jetbrains.plugins.groovy.annotator.intentions.*; -import org.jetbrains.plugins.groovy.annotator.intentions.CreateFieldFromUsageFix; -import org.jetbrains.plugins.groovy.annotator.intentions.CreateMethodFromUsageFix; -import org.jetbrains.plugins.groovy.annotator.intentions.CreateParameterFromUsageFix; -import org.jetbrains.plugins.groovy.annotator.intentions.dynamic.DynamicMethodFix; -import org.jetbrains.plugins.groovy.annotator.intentions.dynamic.DynamicPropertyFix; import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyAssignabilityCheckInspection; import org.jetbrains.plugins.groovy.config.GroovyConfigUtils; import org.jetbrains.plugins.groovy.debugger.fragments.GroovyCodeFragment; import org.jetbrains.plugins.groovy.highlighter.DefaultHighlighter; import org.jetbrains.plugins.groovy.lang.documentation.GroovyPresentationUtil; import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocReferenceElement; -import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GroovyDocPsiElement; import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; import org.jetbrains.plugins.groovy.lang.lexer.TokenSets; import org.jetbrains.plugins.groovy.lang.psi.*; @@ -94,7 +84,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.*; import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement; import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.packaging.GrPackageDefinition; import org.jetbrains.plugins.groovy.lang.psi.api.types.*; -import org.jetbrains.plugins.groovy.lang.psi.api.util.GrVariableDeclarationOwner; import org.jetbrains.plugins.groovy.lang.psi.dataFlow.types.TypeInferenceHelper; import org.jetbrains.plugins.groovy.lang.psi.impl.auxiliary.annotation.GrAnnotationImpl; import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil; @@ -113,7 +102,6 @@ import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil; import java.util.*; import static com.intellij.psi.PsiModifier.*; -import static org.jetbrains.plugins.groovy.annotator.intentions.QuickfixUtil.isCall; /** * @author ven @@ -230,42 +218,6 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator { } } - @Override - public void visitCodeReferenceElement(GrCodeReferenceElement refElement) { - if (PsiTreeUtil.getParentOfType(refElement, GroovyDocPsiElement.class) != null) return; - - PsiElement nameElement = refElement.getReferenceNameElement(); - if (nameElement == null) return; - - if (isResolvedStaticImport(refElement)) return; - - GroovyResolveResult resolveResult = refElement.advancedResolve(); - final PsiElement resolved = resolveResult.getElement(); - - if (refElement.getParent() instanceof GrPackageDefinition) { - checkPackage((GrPackageDefinition)refElement.getParent()); - } - else if (resolved == null) { - final Annotation annotation = myHolder.createErrorAnnotation(nameElement, GroovyBundle.message("cannot.resolve", refElement.getReferenceName())); - annotation.setHighlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL); - - // todo implement for nested classes - if (refElement.getQualifier() == null || PsiTreeUtil.getParentOfType(refElement, GrImportStatement.class) != null) { - registerCreateClassByTypeFix(refElement, annotation); - registerAddImportFixes(refElement, annotation); - UnresolvedReferenceQuickFixProvider.registerReferenceFixes(refElement, new QuickFixActionRegistrarAdapter(annotation)); - OrderEntryFix.registerFixes(new QuickFixActionRegistrarAdapter(annotation), refElement); - } - } - } - - private static boolean isResolvedStaticImport(GrCodeReferenceElement refElement) { - final PsiElement parent = refElement.getParent(); - return parent instanceof GrImportStatement && - ((GrImportStatement)parent).isStatic() && - refElement.multiResolve(false).length > 0; - } - @Override public void visitTryStatement(GrTryCatchStatement statement) { final GrCatchClause[] clauses = statement.getCatchClauses(); @@ -334,92 +286,7 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator { @Override public void visitReferenceExpression(final GrReferenceExpression referenceExpression) { - PsiElement refNameElement = referenceExpression.getReferenceNameElement(); - if (refNameElement == null) return; - checkStringNameIdentifier(referenceExpression); - - boolean cannotBeDynamic = PsiUtil.isCompileStatic(referenceExpression) || isPropertyAccessInStaticMethod(referenceExpression); - GroovyResolveResult resolveResult = getBestResolveResult(referenceExpression); - - if (resolveResult.getElement() != null) { - if (!isStaticOk(resolveResult)) { - createAnnotationForRef(referenceExpression, cannotBeDynamic, - GroovyBundle.message("cannot.reference.nonstatic", referenceExpression.getReferenceName())); - } - return; - } - - if (ResolveUtil.isKeyOfMap(referenceExpression)) { - Annotation annotation = myHolder.createInfoAnnotation(refNameElement, null); - annotation.setTextAttributes(DefaultHighlighter.MAP_KEY); - return; - } - - if (GrHighlightUtil.shouldHighlightAsUnresolved(referenceExpression)) { - Annotation annotation = createAnnotationForRef(referenceExpression, cannotBeDynamic, GroovyBundle.message("cannot.resolve", referenceExpression.getReferenceName())); - if (referenceExpression.getQualifier() == null) { - if (isCall(referenceExpression)) { - registerStaticImportFix(referenceExpression, annotation); - } - else { - registerCreateClassByTypeFix(referenceExpression, annotation); - registerAddImportFixes(referenceExpression, annotation); - } - } - - registerReferenceFixes(referenceExpression, annotation, cannotBeDynamic); - UnresolvedReferenceQuickFixProvider.registerReferenceFixes(referenceExpression, new QuickFixActionRegistrarAdapter(annotation)); - OrderEntryFix.registerFixes(new QuickFixActionRegistrarAdapter(annotation), referenceExpression); - } - } - - private static boolean isStaticOk(GroovyResolveResult resolveResult) { - if (resolveResult.isStaticsOK()) return true; - - PsiElement resolved = resolveResult.getElement(); - LOG.assertTrue(resolved != null); - LOG.assertTrue(resolved instanceof PsiModifierListOwner, resolved + " : " + resolved.getText()); - - return (((PsiModifierListOwner)resolved).hasModifierProperty(STATIC)); - } - - private static GroovyResolveResult getBestResolveResult(GrReferenceExpression ref) { - GroovyResolveResult[] results = ref.multiResolve(false); - if (results.length == 0) return GroovyResolveResult.EMPTY_RESULT; - if (results.length == 1) return results[0]; - - for (GroovyResolveResult result : results) { - if (result.isAccessible() && result.isStaticsOK()) return result; - } - - for (GroovyResolveResult result : results) { - if (result.isStaticsOK()) return result; - } - - return results[0]; - } - - private static boolean isPropertyAccessInStaticMethod(GrReferenceExpression referenceExpression) { - if (referenceExpression.getParent() instanceof GrMethodCall) return false; - GrMember context = PsiTreeUtil.getParentOfType(referenceExpression, GrMember.class, true, GrClosableBlock.class); - return (context instanceof GrMethod || context instanceof GrClassInitializer) && context.hasModifierProperty(STATIC); - } - - private Annotation createAnnotationForRef(GrReferenceExpression referenceExpression, boolean compileStatic, final String message) { - PsiElement refNameElement = referenceExpression.getReferenceNameElement(); - assert refNameElement != null; - - Annotation annotation; - if (compileStatic) { - annotation = myHolder.createErrorAnnotation(refNameElement, message); - annotation.setHighlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL); - } - else { - annotation = myHolder.createInfoAnnotation(refNameElement, message); - annotation.setTextAttributes(DefaultHighlighter.UNRESOLVED_ACCESS); - } - return annotation; } private void checkStringNameIdentifier(GrReferenceExpression ref) { @@ -435,18 +302,11 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator { } } - private static void registerStaticImportFix(GrReferenceExpression referenceExpression, Annotation annotation) { - final String referenceName = referenceExpression.getReferenceName(); - if (StringUtil.isEmpty(referenceName)) return; - - annotation.registerFix(new GroovyStaticImportMethodFix((GrMethodCall)referenceExpression.getParent())); - } - @Override public void visitTypeDefinition(GrTypeDefinition typeDefinition) { final PsiElement parent = typeDefinition.getParent(); if (!(typeDefinition.isAnonymous() || parent instanceof GrTypeDefinitionBody || parent instanceof GroovyFile || typeDefinition instanceof GrTypeParameter)) { - final TextRange range = getClassHeaderTextRange(typeDefinition); + final TextRange range = GrHighlightUtil.getClassHeaderTextRange(typeDefinition); final Annotation errorAnnotation = myHolder.createErrorAnnotation(range, GroovyBundle.message("class.definition.is.not.expected.here")); errorAnnotation.registerFix(new GrMoveClassToCorrectPlaceFix(typeDefinition)); @@ -488,7 +348,7 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator { final String qName = superClass.getQualifiedName(); if (constructors.length == 0) { if (!hasImplicitDefConstructor && (defConstructor == null || !PsiUtil.isAccessible(typeDefinition, defConstructor))) { - final TextRange range = getClassHeaderTextRange(typeDefinition); + final TextRange range = GrHighlightUtil.getClassHeaderTextRange(typeDefinition); holder.createErrorAnnotation(range, GroovyBundle.message("there.is.no.default.constructor.available.in.class.0", qName)).registerFix(new CreateConstructorMatchingSuperFix(typeDefinition)); } return; @@ -1106,25 +966,6 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator { checkAnnotationList(myHolder, modifierList, GroovyBundle.message("package.definition.cannot.have.modifiers")); } - private void checkPackage(GrPackageDefinition packageDefinition) { - final PsiFile file = packageDefinition.getContainingFile(); - assert file != null; - - PsiDirectory psiDirectory = file.getContainingDirectory(); - if (psiDirectory != null && file instanceof GroovyFile) { - PsiPackage aPackage = JavaDirectoryService.getInstance().getPackage(psiDirectory); - if (aPackage != null) { - String expectedPackage = aPackage.getQualifiedName(); - String actualPackage = packageDefinition.getPackageName(); - if (!expectedPackage.equals(actualPackage)) { - final Annotation annotation = myHolder.createWarningAnnotation(packageDefinition, GroovyBundle.message("wrong.package.name", actualPackage, aPackage.getQualifiedName())); - annotation.registerFix(new ChangePackageQuickFix((GroovyFile)packageDefinition.getContainingFile(), expectedPackage)); - annotation.registerFix(new GrMoveToDirFix(actualPackage)); - } - } - } - } - @Override public void visitClosure(GrClosableBlock closure) { super.visitClosure(closure); @@ -1563,33 +1404,12 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator { assert element instanceof PsiNamedElement; String notImplementedMethodName = ((PsiNamedElement)element).getName(); - final TextRange range = getClassHeaderTextRange(typeDefinition); + final TextRange range = GrHighlightUtil.getClassHeaderTextRange(typeDefinition); final Annotation annotation = holder.createErrorAnnotation(range, GroovyBundle.message("method.is.not.implemented", notImplementedMethodName)); registerImplementsMethodsFix(typeDefinition, annotation); } - private static TextRange getClassHeaderTextRange(GrTypeDefinition clazz) { - final GrModifierList modifierList = clazz.getModifierList(); - final int startOffset = modifierList != null ? modifierList.getTextOffset() : clazz.getTextOffset(); - final GrImplementsClause implementsClause = clazz.getImplementsClause(); - - final int endOffset; - if (implementsClause != null) { - endOffset = implementsClause.getTextRange().getEndOffset(); - } - else { - final GrExtendsClause extendsClause = clazz.getExtendsClause(); - if (extendsClause != null) { - endOffset = extendsClause.getTextRange().getEndOffset(); - } - else { - endOffset = clazz.getNameIdentifierGroovy().getTextRange().getEndOffset(); - } - } - return new TextRange(startOffset, endOffset); - } - private static void registerImplementsMethodsFix(GrTypeDefinition typeDefinition, Annotation annotation) { annotation.registerFix(QuickFixFactory.getInstance().createImplementMethodsFix(typeDefinition)); } @@ -1860,7 +1680,7 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator { GrTypeDefinition typeDefinition) { final PsiClass psiClass = getCircularClass(typeDefinition, new HashSet()); if (psiClass != null) { - holder.createErrorAnnotation(getClassHeaderTextRange(typeDefinition), + holder.createErrorAnnotation(GrHighlightUtil.getClassHeaderTextRange(typeDefinition), GroovyBundle.message("cyclic.inheritance.involving.0", psiClass.getQualifiedName())); } } @@ -1963,110 +1783,6 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator { } - private static void registerReferenceFixes(GrReferenceExpression refExpr, Annotation annotation, boolean compileStatic) { - PsiClass targetClass = QuickfixUtil.findTargetClass(refExpr, compileStatic); - if (targetClass == null) return; - - if (!compileStatic) { - addDynamicAnnotation(annotation, refExpr); - } - if (targetClass.isWritable()) { - if (!(targetClass instanceof GroovyScriptClass)) { - annotation.registerFix(new CreateFieldFromUsageFix(refExpr, targetClass)); - } - - if (refExpr.getParent() instanceof GrCall && refExpr.getParent() instanceof GrExpression) { - annotation.registerFix(new CreateMethodFromUsageFix(refExpr, targetClass)); - } - } - - if (!refExpr.isQualified()) { - GrVariableDeclarationOwner owner = PsiTreeUtil.getParentOfType(refExpr, GrVariableDeclarationOwner.class); - if (!(owner instanceof GroovyFileBase) || ((GroovyFileBase)owner).isScript()) { - annotation.registerFix(new CreateLocalVariableFromUsageFix(refExpr, owner)); - } - if (PsiTreeUtil.getParentOfType(refExpr, GrMethod.class)!=null) { - annotation.registerFix(new CreateParameterFromUsageFix(refExpr)); - } - } - } - - private static void addDynamicAnnotation(Annotation annotation, GrReferenceExpression referenceExpression) { - final PsiFile containingFile = referenceExpression.getContainingFile(); - VirtualFile file; - if (containingFile != null) { - file = containingFile.getVirtualFile(); - if (file == null) return; - } - else { - return; - } - - if (isCall(referenceExpression)) { - PsiType[] argumentTypes = PsiUtil.getArgumentTypes(referenceExpression, false); - if (argumentTypes != null) { - annotation.registerFix(new DynamicMethodFix(referenceExpression, argumentTypes), referenceExpression.getTextRange()); - } - } - else { - annotation.registerFix(new DynamicPropertyFix(referenceExpression), referenceExpression.getTextRange()); - } - } - - private static void registerAddImportFixes(GrReferenceElement refElement, Annotation annotation) { - final String referenceName = refElement.getReferenceName(); - //noinspection ConstantConditions - if (StringUtil.isEmpty(referenceName) || - (!(refElement instanceof GrCodeReferenceElement) && Character.isLowerCase(referenceName.charAt(0)))) { - return; - } - - annotation.registerFix(new GroovyAddImportAction(refElement)); - } - - private static void registerCreateClassByTypeFix(GrReferenceElement refElement, Annotation annotation) { - GrPackageDefinition packageDefinition = PsiTreeUtil.getParentOfType(refElement, GrPackageDefinition.class); - if (packageDefinition == null && refElement.getQualifier() == null) { - PsiElement parent = refElement.getParent(); - if (parent instanceof GrNewExpression && - refElement.getManager().areElementsEquivalent(((GrNewExpression)parent).getReferenceElement(), refElement)) { - annotation.registerFix(CreateClassFix.createClassFromNewAction((GrNewExpression)parent)); - } - else { - if (shouldBeInterface(refElement)) { - annotation.registerFix(CreateClassFix.createClassFixAction(refElement, CreateClassKind.INTERFACE)); - } - else if (shouldBeClass(refElement)) { - annotation.registerFix(CreateClassFix.createClassFixAction(refElement, CreateClassKind.CLASS)); - annotation.registerFix(CreateClassFix.createClassFixAction(refElement, CreateClassKind.ENUM)); - } - else if (shouldBeAnnotation(refElement)) { - annotation.registerFix(CreateClassFix.createClassFixAction(refElement, CreateClassKind.ANNOTATION)); - } - else { - annotation.registerFix(CreateClassFix.createClassFixAction(refElement, CreateClassKind.CLASS)); - annotation.registerFix(CreateClassFix.createClassFixAction(refElement, CreateClassKind.INTERFACE)); - annotation.registerFix(CreateClassFix.createClassFixAction(refElement, CreateClassKind.ENUM)); - annotation.registerFix(CreateClassFix.createClassFixAction(refElement, CreateClassKind.ANNOTATION)); - } - } - } - } - - private static boolean shouldBeAnnotation(GrReferenceElement element) { - return element.getParent() instanceof GrAnnotation; - } - - private static boolean shouldBeInterface(GrReferenceElement myRefElement) { - PsiElement parent = myRefElement.getParent(); - return parent instanceof GrImplementsClause || parent instanceof GrExtendsClause && parent.getParent() instanceof GrInterfaceDefinition; - } - - private static boolean shouldBeClass(GrReferenceElement myRefElement) { - PsiElement parent = myRefElement.getParent(); - return parent instanceof GrExtendsClause && !(parent.getParent() instanceof GrInterfaceDefinition); - } - public static class DuplicateVariablesProcessor extends PropertyResolverProcessor { private boolean myBorderPassed; private final boolean myHasVisibilityModifier; @@ -2105,28 +1821,5 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator { super.handleEvent(event, associated); } } - - private static class QuickFixActionRegistrarAdapter implements QuickFixActionRegistrar { - private final Annotation myAnnotation; - - public QuickFixActionRegistrarAdapter(Annotation annotation) { - myAnnotation = annotation; - } - - @Override - public void register(IntentionAction action) { - myAnnotation.registerFix(action); - } - - @Override - public void register(TextRange fixRange, IntentionAction action, HighlightDisplayKey key) { - myAnnotation.registerFix(action, fixRange, key); - } - - @Override - public void unregister(Condition condition) { - throw new UnsupportedOperationException(); - } - } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/ChangePackageQuickFix.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/ChangePackageQuickFix.java deleted file mode 100644 index b15449ee0a2a..000000000000 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/ChangePackageQuickFix.java +++ /dev/null @@ -1,64 +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.plugins.groovy.annotator.intentions; - -import com.intellij.codeInsight.intention.IntentionAction; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiFile; -import com.intellij.util.IncorrectOperationException; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.groovy.GroovyBundle; -import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; - -/** - * User: Dmitry.Krasilschikov - * Date: 01.11.2007 - */ -public class ChangePackageQuickFix implements IntentionAction { - private static final Logger LOG = Logger.getInstance("org.jetbrains.plugins.groovy.annotator.intentions.ChangePackageQuickFix"); - - private final GroovyFile myFile; - private final String myNewPackageName; - - public ChangePackageQuickFix(GroovyFile file, String newPackageName) { - myFile = file; - myNewPackageName = newPackageName; - } - - @NotNull - public String getText() { - return GroovyBundle.message("fix.package.name"); - } - - @NotNull - public String getFamilyName() { - return GroovyBundle.message("fix.package.name"); - } - - public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - return myFile.isValid() && myFile.getManager().isInProject(file); - } - - public void invoke(@NotNull Project project, Editor editor, PsiFile psiFile) throws IncorrectOperationException { - myFile.setPackageName(myNewPackageName); - } - - public boolean startInWriteAction() { - return true; - } -} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateClassActionBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateClassActionBase.java index 0c341df41ece..bb23f9fe44e6 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateClassActionBase.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateClassActionBase.java @@ -152,7 +152,11 @@ public abstract class CreateClassActionBase implements IntentionAction { } @Nullable - protected PsiDirectory getTargetDirectory(Project project, String qualifier, String name, Module module, String title) { + protected PsiDirectory getTargetDirectory(@NotNull Project project, + @NotNull String qualifier, + @NotNull String name, + @Nullable Module module, + @NotNull String title) { CreateClassDialog dialog = new CreateClassDialog(project, title, name, qualifier, getType(), false, module) { @Override protected boolean reportBaseInSourceSelectionInTest() { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateClassFix.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateClassFix.java index 9fd4752e824d..bf8fde3b3b33 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateClassFix.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateClassFix.java @@ -16,9 +16,12 @@ package org.jetbrains.plugins.groovy.annotator.intentions; +import com.intellij.codeInsight.CodeInsightUtilBase; import com.intellij.codeInsight.daemon.impl.quickfix.CreateClassKind; +import com.intellij.codeInsight.hint.HintManager; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.openapi.application.AccessToken; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ReadAction; import com.intellij.openapi.application.WriteAction; import com.intellij.openapi.editor.Editor; @@ -30,19 +33,22 @@ import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.actions.NewGroovyClassAction; -import org.jetbrains.plugins.groovy.template.expressions.ChooseTypeExpression; +import org.jetbrains.plugins.groovy.intentions.GroovyIntentionsBundle; import org.jetbrains.plugins.groovy.intentions.base.IntentionUtils; import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement; import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrNewExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; 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.expectedTypes.SupertypeConstraint; import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.TypeConstraint; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; +import org.jetbrains.plugins.groovy.template.expressions.ChooseTypeExpression; import static com.intellij.openapi.module.ModuleUtilCore.findModuleForPsiElement; @@ -124,8 +130,8 @@ public abstract class CreateClassFix { GrMethod method = GroovyPsiElementFactory.getInstance(project).createConstructorFromText(name, paramTypes, paramNames, "{\n}"); - method = targetClass.addMemberDeclaration(method, null); - final PsiNameIdentifierOwner context = PsiTreeUtil.getParentOfType(refElement, PsiMethod.class, PsiClass.class); + method = (GrMethod)targetClass.addBefore(method, null); + final PsiElement context = PsiTreeUtil.getParentOfType(refElement, PsiMethod.class, PsiClass.class, PsiFile.class); IntentionUtils.createTemplateForMethod(argTypes, paramTypesExpressions, method, targetClass, new TypeConstraint[0], true, context); } finally { @@ -135,22 +141,98 @@ public abstract class CreateClassFix { public static IntentionAction createClassFixAction(final GrReferenceElement refElement, CreateClassKind type) { return new CreateClassActionBase(type, refElement) { - public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + public void invoke(@NotNull Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException { if (!(file instanceof GroovyFileBase)) return; GroovyFileBase groovyFile = (GroovyFileBase)file; - final String qualifier = groovyFile instanceof GroovyFile ? groovyFile.getPackageName() : ""; + + PsiElement qualifier = myRefElement.getQualifier(); + + if (qualifier == null) { + createTopLevelClass(project, file, groovyFile); + } + else { + createInnerClass(project, editor, qualifier); + } + } + + private void createInnerClass(Project project, final Editor editor, PsiElement qualifier) { + PsiElement resolved = null; + if (qualifier instanceof GrCodeReferenceElement) { + resolved = ((GrCodeReferenceElement)qualifier).resolve(); + } + else if (qualifier instanceof GrExpression) { + PsiType type = ((GrExpression)qualifier).getType(); + if (type instanceof PsiClassType) { + resolved = ((PsiClassType)type).resolve(); + } + } + + + JVMElementFactory factory = JVMElementFactories.getFactory(resolved.getLanguage(), project); + if (factory == null) return; + + String name = myRefElement.getReferenceName(); + PsiClass template = createTemplate(factory, name); + + if (template == null) { + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + if (editor != null && editor.getComponent().isDisplayable()) { + HintManager.getInstance().showErrorHint(editor, GroovyIntentionsBundle.message("cannot.create.class")); + } + } + }); + return; + } + + + AccessToken lock = ApplicationManager.getApplication().acquireWriteActionLock(CreateClassFix.class); + try { + if (!(resolved instanceof PsiClass)) return; + CodeInsightUtilBase.preparePsiElementForWrite(resolved); + + PsiClass added = (PsiClass)resolved.add(template); + PsiModifierList modifierList = added.getModifierList(); + if (modifierList != null) { + modifierList.setModifierProperty(PsiModifier.STATIC, true); + } + putCursor(project, added.getContainingFile(), added); + } + finally { + lock.finish(); + } + } + + @Nullable + private PsiClass createTemplate(JVMElementFactory factory, String name) { + switch (getType()) { + case ENUM: + return factory.createEnum(name); + case CLASS: + return factory.createClass(name); + case INTERFACE: + return factory.createInterface(name); + case ANNOTATION: + return factory.createAnnotationType(name); + default: + return null; + } + } + + private void createTopLevelClass(Project project, PsiFile file, GroovyFileBase groovyFile) { + final String pack = groovyFile instanceof GroovyFile ? groovyFile.getPackageName() : ""; final PsiManager manager = PsiManager.getInstance(project); final String name = myRefElement.getReferenceName(); + assert name != null; final Module module = findModuleForPsiElement(file); - PsiDirectory targetDirectory = getTargetDirectory(project, qualifier, name, module, getText()); + PsiDirectory targetDirectory = getTargetDirectory(project, pack, name, module, getText()); if (targetDirectory == null) return; - String templateName = getTemplateName(getType()); - assert name != null; PsiClass targetClass = createClassByType(targetDirectory, name, manager, myRefElement, templateName); if (targetClass != null) { - addImportForClass(groovyFile, qualifier, targetClass); + addImportForClass(groovyFile, pack, targetClass); putCursor(project, targetClass.getContainingFile(), targetClass); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateFieldFix.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateFieldFix.java index a0c86a6b4503..f7c2af5200fd 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateFieldFix.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateFieldFix.java @@ -23,12 +23,15 @@ import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.psi.util.PsiUtil; import com.intellij.util.IncorrectOperationException; +import org.jetbrains.plugins.groovy.lang.GrReferenceAdjuster; import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.TypeConstraint; +import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass; +import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames; /** * @author Maxim.Medvedev */ -public class CreateFieldFix { +public class CreateFieldFix { private final PsiClass myTargetClass; protected PsiClass getTargetClass() { @@ -44,12 +47,20 @@ public class CreateFieldFix { } protected void doFix(Project project, String[] modifiers, String fieldName, TypeConstraint[] typeConstraints, PsiElement context) throws IncorrectOperationException { - PsiField field = JVMElementFactories.getFactory(myTargetClass.getLanguage(), project).createField(fieldName, PsiType.INT); + JVMElementFactory factory = JVMElementFactories.getFactory(myTargetClass.getLanguage(), project); + if (factory == null) return; + + PsiField field = factory.createField(fieldName, PsiType.INT); + if (myTargetClass instanceof GroovyScriptClass) { + field.getModifierList().addAnnotation(GroovyCommonClassNames.GROOVY_TRANSFORM_FIELD); + } + for (String modifier : modifiers) { PsiUtil.setModifierProperty(field, modifier, true); } field = CreateFieldFromUsageHelper.insertField(myTargetClass, field, context); + GrReferenceAdjuster.shortenReferences(field.getParent()); Editor newEditor = QuickfixUtil.positionCursor(project, myTargetClass.getContainingFile(), field); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateFieldFromConstructorLabelFix.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateFieldFromConstructorLabelFix.java index a750a097c74b..b5b032a23660 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateFieldFromConstructorLabelFix.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateFieldFromConstructorLabelFix.java @@ -27,7 +27,7 @@ import org.jetbrains.plugins.groovy.codeInspection.GroovyFix; import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentLabel; import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrMemberOwner; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.SupertypeConstraint; import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.TypeConstraint; @@ -38,7 +38,7 @@ public class CreateFieldFromConstructorLabelFix extends GroovyFix { private final CreateFieldFix myFix; private final GrNamedArgument myNamedArgument; - public CreateFieldFromConstructorLabelFix(GrMemberOwner targetClass, GrNamedArgument namedArgument) { + public CreateFieldFromConstructorLabelFix(GrTypeDefinition targetClass, GrNamedArgument namedArgument) { myFix = new CreateFieldFix(targetClass); myNamedArgument = namedArgument; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateMethodFromUsageFix.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateMethodFromUsageFix.java index 550217c9aaec..5c37b7fe7b8b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateMethodFromUsageFix.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateMethodFromUsageFix.java @@ -27,7 +27,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.GroovyBundle; import org.jetbrains.plugins.groovy.GroovyFileType; -import org.jetbrains.plugins.groovy.template.expressions.ChooseTypeExpression; import org.jetbrains.plugins.groovy.intentions.base.IntentionUtils; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; @@ -37,6 +36,7 @@ import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.TypeConstraint; 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.util.PsiUtil; +import org.jetbrains.plugins.groovy.template.expressions.ChooseTypeExpression; /** * @author ven @@ -80,7 +80,7 @@ public class CreateMethodFromUsageFix implements IntentionAction { TypeConstraint[] constraints = GroovyExpectedTypesProvider.calculateTypeConstraints((GrExpression)myRefExpression.getParent()); final PsiGenerationInfo info = OverrideImplementUtil.createGenerationInfo(method); - info.insert(myTargetClass, findInsertionAnchor(info), true); + info.insert(myTargetClass, findInsertionAnchor(info), false); method = info.getPsiMember(); final PsiElement context = PsiTreeUtil.getParentOfType(myRefExpression, PsiClass.class, PsiMethod.class); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateParameterFromUsageFix.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateParameterFromUsageFix.java index 33d5876beb45..9669b5a7cd35 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateParameterFromUsageFix.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateParameterFromUsageFix.java @@ -21,7 +21,10 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.JBPopup; -import com.intellij.psi.*; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiMethod; +import com.intellij.psi.PsiType; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiTypesUtil; import com.intellij.refactoring.RefactoringBundle; @@ -39,8 +42,8 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMe import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.GroovyExpectedTypesProvider; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; import org.jetbrains.plugins.groovy.refactoring.changeSignature.GrChangeSignatureDialog; -import org.jetbrains.plugins.groovy.refactoring.changeSignature.GrParameterTableModel; -import org.jetbrains.plugins.groovy.refactoring.changeSignature.GrTableParameterInfo; +import org.jetbrains.plugins.groovy.refactoring.changeSignature.GrMethodDescriptor; +import org.jetbrains.plugins.groovy.refactoring.changeSignature.GrParameterInfo; import org.jetbrains.plugins.groovy.refactoring.convertToJava.GroovyToJavaGenerator; import org.jetbrains.plugins.groovy.refactoring.ui.MethodOrClosureScopeChooser; @@ -138,28 +141,18 @@ public class CreateParameterFromUsageFix implements IntentionAction, MethodOrClo final String name = ref.getName(); final Set types = GroovyExpectedTypesProvider.getDefaultExpectedTypes(ref); - final PsiType type; - if (types.isEmpty()) { - type = PsiType.getJavaLangObject(PsiManager.getInstance(project), ref.getResolveScope()); - } - else { - type = TypesUtil.unboxPrimitiveTypeWrapper(types.iterator().next()); - } + + PsiType unboxed = types.isEmpty() ? null : TypesUtil.unboxPrimitiveTypeWrapper(types.iterator().next()); + @NotNull final PsiType type = unboxed != null ? unboxed : PsiType.getJavaLangObject(ref.getManager(), ref.getResolveScope()); if (method instanceof GrMethod) { - new GrChangeSignatureDialog(project, (GrMethod)method) { - @Override - protected GrParameterTableModel createParameterTableModel() { - GrParameterTableModel model = super.createParameterTableModel(); + GrMethodDescriptor descriptor = new GrMethodDescriptor((GrMethod)method); + GrChangeSignatureDialog dialog = new GrChangeSignatureDialog(project, descriptor, true, ref); - model.addRow(new GrTableParameterInfo(project, ref, name, type.getPresentableText(), - GroovyToJavaGenerator.getDefaultValueText(type.getCanonicalText()), "")); - if (method.isVarArgs()) { - model.exchangeRows(model.getRowCount() - 1, model.getRowCount() - 2); - } - return model; - } - }.show(); + List parameters = dialog.getParameters(); + parameters.add(createParameterInfo(name, type)); + dialog.setParameterInfos(parameters); + dialog.show(); } else if (method != null) { JavaChangeSignatureDialog dialog = new JavaChangeSignatureDialog(project, method, false, ref); @@ -178,6 +171,12 @@ public class CreateParameterFromUsageFix implements IntentionAction, MethodOrClo }); } + private static GrParameterInfo createParameterInfo(String name, PsiType type) { + String notNullName = name != null ? name : ""; + String defaultValueText = GroovyToJavaGenerator.getDefaultValueText(type.getCanonicalText()); + return new GrParameterInfo(notNullName, defaultValueText, "", type, -1, false); + } + @Override public boolean startInWriteAction() { return true; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/GroovyCreateFieldFromUsageHelper.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/GroovyCreateFieldFromUsageHelper.java index 80551faef83b..aac667269c6a 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/GroovyCreateFieldFromUsageHelper.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/GroovyCreateFieldFromUsageHelper.java @@ -26,12 +26,13 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; -import org.jetbrains.plugins.groovy.template.expressions.ChooseTypeExpression; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement; import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.TypeConstraint; +import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass; +import org.jetbrains.plugins.groovy.template.expressions.ChooseTypeExpression; /** * @author Max Medvedev @@ -48,7 +49,6 @@ public class GroovyCreateFieldFromUsageHelper extends CreateFieldFromUsageHelper GrVariableDeclaration fieldDecl = (GrVariableDeclaration)f.getParent(); GrField field = (GrField)fieldDecl.getVariables()[0]; - TemplateBuilderImpl builder = new TemplateBuilderImpl(fieldDecl); Project project = context.getProject(); @@ -84,6 +84,12 @@ public class GroovyCreateFieldFromUsageHelper extends CreateFieldFromUsageHelper @Override public PsiField insertFieldImpl(PsiClass targetClass, PsiField field, PsiElement place) { - return (PsiField)targetClass.add(field); + if (targetClass instanceof GroovyScriptClass) { + PsiElement added = targetClass.getContainingFile().add(field.getParent()); + return (PsiField)((GrVariableDeclaration)added).getVariables()[0]; + } + else { + return (PsiField)targetClass.add(field); + } } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/BaseInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/BaseInspection.java index a7d6f5302f2c..70051c8b2956 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/BaseInspection.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/BaseInspection.java @@ -21,12 +21,10 @@ import com.intellij.codeInspection.ProblemsHolder; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; -import java.lang.reflect.Method; import java.util.List; @@ -34,16 +32,16 @@ public abstract class BaseInspection extends GroovySuppressableInspectionTool { private final String m_shortName = StringUtil.trimEnd(getClass().getSimpleName(), "Inspection"); - protected static final String ASSIGNMENT_ISSUES = "Assignment issues"; - protected static final String CONFUSING_CODE_CONSTRUCTS = "Potentially confusing code constructs"; - protected static final String CONTROL_FLOW = "Control Flow"; - protected static final String PROBABLE_BUGS = "Probable bugs"; - protected static final String ERROR_HANDLING = "Error handling"; - protected static final String GPATH = "GPath inspections"; - protected static final String METHOD_METRICS = "Method Metrics"; - protected static final String THREADING_ISSUES = "Threading issues"; - protected static final String VALIDITY_ISSUES = "Validity issues"; - protected static final String ANNOTATIONS_ISSUES = "Annotations verifying"; + public static final String ASSIGNMENT_ISSUES = "Assignment issues"; + public static final String CONFUSING_CODE_CONSTRUCTS = "Potentially confusing code constructs"; + public static final String CONTROL_FLOW = "Control Flow"; + public static final String PROBABLE_BUGS = "Probable bugs"; + public static final String ERROR_HANDLING = "Error handling"; + public static final String GPATH = "GPath inspections"; + public static final String METHOD_METRICS = "Method Metrics"; + public static final String THREADING_ISSUES = "Threading issues"; + public static final String VALIDITY_ISSUES = "Validity issues"; + public static final String ANNOTATIONS_ISSUES = "Annotations verifying"; @NotNull @Override @@ -99,16 +97,5 @@ public abstract class BaseInspection extends GroovySuppressableInspectionTool { } - public boolean hasQuickFix() { - final Method[] methods = getClass().getDeclaredMethods(); - for (final Method method : methods) { - @NonNls final String methodName = method.getName(); - if ("buildFix".equals(methodName)) { - return true; - } - } - return false; - } - protected abstract BaseInspectionVisitor buildVisitor(); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.properties index ae0be4bc6eb6..b1f8d5a2455b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.properties +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.properties @@ -95,3 +95,7 @@ method.may.be.static.ignore.empty.method.option=Ignore empty methods have.instance.refs.in.closure=(have instance references inside closure) method.may.be.static.ignore.instance.refs.in.closure.option=Ignore instance references inside closures ignore.boolean.expressions=Ignore unassigned variables in boolean checks +highlight.if.groovy.object.methods.overridden=Highlight references from class overriding invokeMethod(), getProperty(), or setProperty() +highlight.if.missing.methods.declared=Highlight references from class declaring missingMethod() or missingProperty() +gr.package.inspection.check.scripts=Check scripts +gr.package=Package mismatch diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovySuppressableInspectionTool.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovySuppressableInspectionTool.java index 1c060d80e94d..3db32d7e7936 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovySuppressableInspectionTool.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovySuppressableInspectionTool.java @@ -61,7 +61,11 @@ public abstract class GroovySuppressableInspectionTool extends LocalInspectionTo } public boolean isSuppressedFor(final PsiElement element) { - return getElementToolSuppressedIn(element, getID()) != null; + return isElementToolSuppressedIn(element, getID()); + } + + public static boolean isElementToolSuppressedIn(final PsiElement place, final String toolId) { + return getElementToolSuppressedIn(place, toolId) != null; } @Nullable diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyUnusedDeclarationInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyUnusedDeclarationInspection.java index 7e9b9549b300..d60aacc647cb 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyUnusedDeclarationInspection.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyUnusedDeclarationInspection.java @@ -15,36 +15,11 @@ */ package org.jetbrains.plugins.groovy.codeInspection; -import com.intellij.analysis.AnalysisScope; -import com.intellij.codeInspection.GlobalInspectionContext; -import com.intellij.codeInspection.InspectionManager; -import com.intellij.codeInspection.ex.DescriptorProviderInspection; -import com.intellij.codeInspection.ex.JobDescriptor; import com.intellij.codeInspection.ex.UnfairLocalInspectionTool; -import org.jetbrains.annotations.Nls; -import org.jetbrains.annotations.NotNull; /** * @author peter */ -public class GroovyUnusedDeclarationInspection extends DescriptorProviderInspection implements UnfairLocalInspectionTool { +public class GroovyUnusedDeclarationInspection extends GroovySuppressableInspectionTool implements UnfairLocalInspectionTool { public static final String SHORT_NAME = "GroovyUnusedDeclaration"; - - @Override - public void runInspection(@NotNull AnalysisScope scope, @NotNull InspectionManager manager) { - } - - @Nls - @NotNull - @Override - public String getDisplayName() { - return "Unused declaration"; - } - - @NotNull - @Override - public JobDescriptor[] getJobDescriptors(GlobalInspectionContext globalInspectionContext) { - return JobDescriptor.EMPTY_ARRAY; - } - } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyConstructorNamedArgumentsInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyConstructorNamedArgumentsInspection.java index 1a826a113638..c25f93222b91 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyConstructorNamedArgumentsInspection.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyConstructorNamedArgumentsInspection.java @@ -32,7 +32,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgument import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrNewExpression; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrMemberOwner; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; @@ -126,7 +126,7 @@ public class GroovyConstructorNamedArgumentsInspection extends BaseInspection { registerError(nameElement, GroovyBundle.message("property.name.expected")); } } - else { + else if (!"*".equals(nameElement.getText())) { registerError(nameElement, GroovyBundle.message("property.name.expected")); } } @@ -139,8 +139,8 @@ public class GroovyConstructorNamedArgumentsInspection extends BaseInspection { } List fixes = new ArrayList(2); - if (element instanceof GrMemberOwner) { - fixes.add(new CreateFieldFromConstructorLabelFix((GrMemberOwner)element, label.getNamedArgument())); + if (element instanceof GrTypeDefinition) { + fixes.add(new CreateFieldFromConstructorLabelFix((GrTypeDefinition)element, label.getNamedArgument())); } if (element instanceof PsiClass) { fixes.add(new DynamicPropertyFix(label, (PsiClass)element)); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrPackageInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrPackageInspection.java new file mode 100644 index 000000000000..fd6c32e1381f --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrPackageInspection.java @@ -0,0 +1,154 @@ +/* + * Copyright 2000-2012 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.codeInspection.confusing; + +import com.intellij.codeInspection.LocalQuickFix; +import com.intellij.codeInspection.MoveToPackageFix; +import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.codeInspection.ProblemHighlightType; +import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.SyntheticElement; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.GroovyBundle; +import org.jetbrains.plugins.groovy.codeInspection.BaseInspection; +import org.jetbrains.plugins.groovy.codeInspection.BaseInspectionVisitor; +import org.jetbrains.plugins.groovy.codeInspection.GroovyInspectionBundle; +import org.jetbrains.plugins.groovy.lang.psi.GrNamedElement; +import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; +import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; +import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.GrTopStatement; +import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.packaging.GrPackageDefinition; +import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil; + +import javax.swing.*; + +/** + * @author Max Medvedev + */ +public class GrPackageInspection extends BaseInspection { + public boolean myCheckScripts = true; + + @Nls + @NotNull + public String getGroupDisplayName() { + return CONFUSING_CODE_CONSTRUCTS; + } + + @Nls + @NotNull + public String getDisplayName() { + return "Package name mismatch"; + } + + + + @Nullable + protected String buildErrorString(Object... args) { + return "Package name mismatch"; + } + + @Nullable + @Override + public JComponent createOptionsPanel() { + final MultipleCheckboxOptionsPanel optionsPanel = new MultipleCheckboxOptionsPanel(this); + optionsPanel.addCheckbox(GroovyInspectionBundle.message("gr.package.inspection.check.scripts"), "myCheckScripts"); + return optionsPanel; + + } + + @Override + protected BaseInspectionVisitor buildVisitor() { + return new BaseInspectionVisitor() { + @Override + public void visitFile(GroovyFileBase file) { + if (!(file instanceof GroovyFile)) return; + + if (!myCheckScripts && file.isScript()) return; + + String expectedPackage = ResolveUtil.inferExpectedPackageName(file); + String actual = file.getPackageName(); + if (!expectedPackage.equals(actual)) { + + PsiElement toHighlight = getElementToHighlight((GroovyFile)file); + if (toHighlight == null) return; + + registerError(toHighlight, "Package name mismatch. Actual: '" + actual + "', expected: '" + expectedPackage+"'", + new LocalQuickFix[]{new ChangePackageQuickFix(expectedPackage), new MoveToPackageFix(actual)}, + ProblemHighlightType.GENERIC_ERROR_OR_WARNING); + } + } + }; + } + + @Nullable + private static PsiElement getElementToHighlight(GroovyFile file) { + GrPackageDefinition packageDefinition = file.getPackageDefinition(); + if (packageDefinition != null) return packageDefinition; + + PsiClass[] classes = file.getClasses(); + for (PsiClass aClass : classes) { + if (!(aClass instanceof SyntheticElement) && aClass instanceof GrTypeDefinition) { + return ((GrTypeDefinition)aClass).getNameIdentifierGroovy(); + } + } + + GrTopStatement[] statements = file.getTopStatements(); + if (statements.length > 0) { + GrTopStatement first = statements[0]; + if (first instanceof GrNamedElement) return ((GrNamedElement)first).getNameIdentifierGroovy(); + + return first; + } + + return null; + } + + /** + * User: Dmitry.Krasilschikov + * Date: 01.11.2007 + */ + public static class ChangePackageQuickFix implements LocalQuickFix { + private final String myNewPackageName; + + public ChangePackageQuickFix(String newPackageName) { + myNewPackageName = newPackageName; + } + + @NotNull + @Override + public String getName() { + return GroovyBundle.message("fix.package.name"); + } + + @NotNull + public String getFamilyName() { + return GroovyBundle.message("fix.package.name"); + } + + @Override + public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { + PsiFile file = descriptor.getPsiElement().getContainingFile(); + ((GroovyFile)file).setPackageName(myNewPackageName); + } + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/declaration/GrMethodMayBeStaticInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/declaration/GrMethodMayBeStaticInspection.java index 3c93580cf4df..d880246e236f 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/declaration/GrMethodMayBeStaticInspection.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/declaration/GrMethodMayBeStaticInspection.java @@ -51,7 +51,7 @@ import javax.swing.*; public class GrMethodMayBeStaticInspection extends BaseInspection { public boolean myOnlyPrivateOrFinal = false; public boolean myIgnoreEmptyMethods = true; - public boolean myIgnoreInstanceRefsInClosure = true; + public boolean myIgnoreInstanceRefsInClosure = false; @Override public JComponent createOptionsPanel() { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/local/GroovyPostHighlightingPass.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/local/GroovyPostHighlightingPass.java index 471224f71585..91b12bf090b4 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/local/GroovyPostHighlightingPass.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/local/GroovyPostHighlightingPass.java @@ -49,6 +49,7 @@ import com.intellij.psi.search.searches.SuperMethodsSearch; import com.intellij.util.Processor; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.codeInspection.GroovyInspectionBundle; +import org.jetbrains.plugins.groovy.codeInspection.GroovySuppressableInspectionTool; import org.jetbrains.plugins.groovy.codeInspection.GroovyUnusedDeclarationInspection; import org.jetbrains.plugins.groovy.editor.GroovyImportOptimizer; import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; @@ -84,13 +85,15 @@ public class GroovyPostHighlightingPass extends TextEditorHighlightingPass { } public void doCollectInformation(@NotNull final ProgressIndicator progress) { - final InspectionProfile profile = InspectionProjectProfileManager.getInstance(myProject).getInspectionProfile(); - final boolean deadCodeEnabled = profile.isToolEnabled(HighlightDisplayKey.find(GroovyUnusedDeclarationInspection.SHORT_NAME), myFile); ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex(); VirtualFile virtualFile = myFile.getViewProvider().getVirtualFile(); if (!fileIndex.isInContent(virtualFile)) { return; } + + final InspectionProfile profile = InspectionProjectProfileManager.getInstance(myProject).getInspectionProfile(); + final HighlightDisplayKey unusedDefKey = HighlightDisplayKey.find(GroovyUnusedDeclarationInspection.SHORT_NAME); + final boolean deadCodeEnabled = profile.isToolEnabled(unusedDefKey, myFile); final UnusedDeclarationInspection deadCodeInspection = (UnusedDeclarationInspection)profile.getUnwrappedTool(UnusedDeclarationInspection.SHORT_NAME, myFile); final GlobalUsageHelper usageHelper = new GlobalUsageHelper() { public boolean isCurrentFileAlreadyChecked() { @@ -122,13 +125,16 @@ public class GroovyPostHighlightingPass extends TextEditorHighlightingPass { } } - if (deadCodeEnabled && element instanceof GrNamedElement && !PostHighlightingPass.isImplicitUsage((GrNamedElement)element, progress)) { + if (deadCodeEnabled && + element instanceof GrNamedElement && + !PostHighlightingPass.isImplicitUsage((GrNamedElement)element, progress) && + !GroovySuppressableInspectionTool.isElementToolSuppressedIn(element, GroovyUnusedDeclarationInspection.SHORT_NAME)) { PsiElement nameId = ((GrNamedElement)element).getNameIdentifierGroovy(); if (nameId.getNode().getElementType() == GroovyTokenTypes.mIDENT) { String name = ((GrNamedElement)element).getName(); if (element instanceof GrTypeDefinition && !PostHighlightingPass.isClassUsed((GrTypeDefinition)element, progress, usageHelper)) { HighlightInfo highlightInfo = PostHighlightingPass.createUnusedSymbolInfo(nameId, "Class " + name + " is unused", HighlightInfoType.UNUSED_SYMBOL); - QuickFixAction.registerQuickFixAction(highlightInfo, new SafeDeleteFix(element)); + QuickFixAction.registerQuickFixAction(highlightInfo, new SafeDeleteFix(element), unusedDefKey); unusedDeclarations.add(highlightInfo); } else if (element instanceof GrMethod) { @@ -136,14 +142,14 @@ public class GroovyPostHighlightingPass extends TextEditorHighlightingPass { if (!PostHighlightingPass.isMethodReferenced(method, progress, usageHelper)) { String message = (method.isConstructor() ? "Constructor" : "Method") + " " + name + " is unused"; HighlightInfo highlightInfo = PostHighlightingPass.createUnusedSymbolInfo(nameId, message, HighlightInfoType.UNUSED_SYMBOL); - QuickFixAction.registerQuickFixAction(highlightInfo, new SafeDeleteFix(method)); + QuickFixAction.registerQuickFixAction(highlightInfo, new SafeDeleteFix(method), unusedDefKey); unusedDeclarations.add(highlightInfo); } } else if (element instanceof GrField && isFieldUnused((GrField)element, progress, usageHelper)) { HighlightInfo highlightInfo = PostHighlightingPass.createUnusedSymbolInfo(nameId, "Property " + name + " is unused", HighlightInfoType.UNUSED_SYMBOL); - QuickFixAction.registerQuickFixAction(highlightInfo, new SafeDeleteFix(element)); + QuickFixAction.registerQuickFixAction(highlightInfo, new SafeDeleteFix(element), unusedDefKey); unusedDeclarations.add(highlightInfo); } else if (element instanceof GrParameter) { @@ -168,18 +174,11 @@ public class GroovyPostHighlightingPass extends TextEditorHighlightingPass { PsiElement scope = parameter.getDeclarationScope(); if (scope instanceof GrMethod) { GrMethod method = (GrMethod)scope; - if ((method.isConstructor() || - method.hasModifierProperty(PsiModifier.PRIVATE) || - method.hasModifierProperty(PsiModifier.STATIC) || - !method.hasModifierProperty(PsiModifier.ABSTRACT) && - !isOverriddenOrOverrides(method)) && - !method.hasModifierProperty(PsiModifier.NATIVE) && - !HighlightMethodUtil.isSerializationRelatedMethod(method, method.getContainingClass()) && - !PsiClassImplUtil.isMainOrPremainMethod(method)) { + if (methodMayHaveUnusedParameters(method)) { + PsiElement identifier = parameter.getNameIdentifierGroovy(); HighlightInfo highlightInfo = PostHighlightingPass - .createUnusedSymbolInfo(parameter.getNameIdentifierGroovy(), "Parameter " + parameter.getName() + " is unused", - HighlightInfoType.UNUSED_SYMBOL); - QuickFixAction.registerQuickFixAction(highlightInfo, new RemoveUnusedGrParameterFix(parameter)); + .createUnusedSymbolInfo(identifier, "Parameter " + parameter.getName() + " is unused", HighlightInfoType.UNUSED_SYMBOL); + QuickFixAction.registerQuickFixAction(highlightInfo, new RemoveUnusedGrParameterFix(parameter), unusedDefKey); unusedDeclarations.add(highlightInfo); } } @@ -206,6 +205,16 @@ public class GroovyPostHighlightingPass extends TextEditorHighlightingPass { } + private static boolean methodMayHaveUnusedParameters(GrMethod method) { + return (method.isConstructor() || + method.hasModifierProperty(PsiModifier.PRIVATE) || + method.hasModifierProperty(PsiModifier.STATIC) || + !method.hasModifierProperty(PsiModifier.ABSTRACT) && !isOverriddenOrOverrides(method)) && + !method.hasModifierProperty(PsiModifier.NATIVE) && + !HighlightMethodUtil.isSerializationRelatedMethod(method, method.getContainingClass()) && + !PsiClassImplUtil.isMainOrPremainMethod(method); + } + private static boolean isFieldUnused(GrField field, ProgressIndicator progress, GlobalUsageHelper usageHelper) { if (!PostHighlightingPass.isFieldUnused(field, progress, usageHelper)) return false; final GrAccessorMethod[] getters = field.getGetters(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/untypedUnresolvedAccess/GroovyUnresolvedAccessInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/untypedUnresolvedAccess/GroovyUnresolvedAccessInspection.java index 45eb0dae6ba3..dc39065933bc 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/untypedUnresolvedAccess/GroovyUnresolvedAccessInspection.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/untypedUnresolvedAccess/GroovyUnresolvedAccessInspection.java @@ -16,38 +16,462 @@ package org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess; +import com.intellij.codeHighlighting.HighlightDisplayLevel; +import com.intellij.codeInsight.daemon.HighlightDisplayKey; +import com.intellij.codeInsight.daemon.QuickFixActionRegistrar; +import com.intellij.codeInsight.daemon.impl.HighlightInfo; +import com.intellij.codeInsight.daemon.impl.HighlightInfoType; +import com.intellij.codeInsight.daemon.impl.quickfix.CreateClassKind; +import com.intellij.codeInsight.daemon.impl.quickfix.OrderEntryFix; +import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction; +import com.intellij.codeInsight.intention.EmptyIntentionAction; +import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.codeInsight.quickfix.UnresolvedReferenceQuickFixProvider; +import com.intellij.codeInspection.InspectionProfile; +import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.profile.codeInspection.InspectionProjectProfileManager; import com.intellij.psi.*; -import com.intellij.util.containers.ContainerUtil; +import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.GroovyBundle; import org.jetbrains.plugins.groovy.annotator.GrHighlightUtil; +import org.jetbrains.plugins.groovy.annotator.intentions.*; +import org.jetbrains.plugins.groovy.annotator.intentions.dynamic.DynamicMethodFix; +import org.jetbrains.plugins.groovy.annotator.intentions.dynamic.DynamicPropertyFix; import org.jetbrains.plugins.groovy.codeInspection.BaseInspection; -import org.jetbrains.plugins.groovy.codeInspection.BaseInspectionVisitor; -import org.jetbrains.plugins.groovy.gpp.GppTypeConverter; -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.GrReferenceExpression; +import org.jetbrains.plugins.groovy.codeInspection.GroovyInspectionBundle; +import org.jetbrains.plugins.groovy.codeInspection.GroovySuppressableInspectionTool; +import org.jetbrains.plugins.groovy.findUsages.MissingMethodAndPropertyUtil; +import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GroovyDocPsiElement; +import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement; +import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; +import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; +import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrClassInitializer; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrExtendsClause; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrImplementsClause; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrInterfaceDefinition; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMember; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; +import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement; +import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.packaging.GrPackageDefinition; +import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement; +import org.jetbrains.plugins.groovy.lang.psi.api.util.GrVariableDeclarationOwner; +import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrReferenceResolveUtil; import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil; -import java.util.Iterator; -import java.util.List; +import javax.swing.*; -import static org.jetbrains.plugins.groovy.annotator.GrHighlightUtil.isDeclarationAssignment; +import static com.intellij.psi.PsiModifier.STATIC; +import static org.jetbrains.plugins.groovy.annotator.intentions.QuickfixUtil.isCall; +import static org.jetbrains.plugins.groovy.highlighter.DefaultHighlighter.MAP_KEY_ATTRIBUTES; +import static org.jetbrains.plugins.groovy.highlighter.DefaultHighlighter.UNRESOLVED_ACCESS_ATTRIBUTES; /** * @author Maxim.Medvedev */ -public class GroovyUnresolvedAccessInspection extends BaseInspection { - protected BaseInspectionVisitor buildVisitor() { - return new Visitor(); +public class GroovyUnresolvedAccessInspection extends GroovySuppressableInspectionTool { + private static final Logger LOG = Logger.getInstance(GroovyUnresolvedAccessInspection.class); + private static final String SHORT_NAME = "GroovyUnresolvedAccess"; + + public boolean myHighlightIfGroovyObjectOverridden = true; + public boolean myHighlightIfMissingMethodsDeclared = true; + + @Nullable + @Override + public JComponent createOptionsPanel() { + final MultipleCheckboxOptionsPanel optionsPanel = new MultipleCheckboxOptionsPanel(this); + optionsPanel.addCheckbox(GroovyInspectionBundle.message("highlight.if.groovy.object.methods.overridden"), "myHighlightIfGroovyObjectOverridden"); + optionsPanel.addCheckbox(GroovyInspectionBundle.message("highlight.if.missing.methods.declared"), "myHighlightIfMissingMethodsDeclared"); + return optionsPanel; + } + + private static boolean isInspectionEnabled(PsiFile file, Project project) { + final InspectionProfile profile = InspectionProjectProfileManager.getInstance(project).getInspectionProfile(); + final HighlightDisplayKey unusedDefKey = HighlightDisplayKey.find(SHORT_NAME); + return profile.isToolEnabled(unusedDefKey, file); + } + + private static GroovyUnresolvedAccessInspection getInstance(PsiFile file, Project project) { + final InspectionProfile profile = InspectionProjectProfileManager.getInstance(project).getInspectionProfile(); + return (GroovyUnresolvedAccessInspection)profile.getUnwrappedTool(SHORT_NAME, file); + } + + private static HighlightDisplayLevel getHighlightDisplayLevel(Project project, GrReferenceElement ref) { + final InspectionProfile profile = InspectionProjectProfileManager.getInstance(project).getInspectionProfile(); + return profile.getErrorLevel(HighlightDisplayKey.find(SHORT_NAME), ref); + } + + @Nullable + public static HighlightInfo checkCodeReferenceElement(GrCodeReferenceElement refElement) { + if (GroovySuppressableInspectionTool.isElementToolSuppressedIn(refElement, SHORT_NAME)) return null; + + HighlightInfo info = checkCodeRefInner(refElement); + addEmptyIntentionIfNeeded(info); + return info; + } + + @Nullable + public static HighlightInfo checkReferenceExpression(GrReferenceExpression ref) { + if (GroovySuppressableInspectionTool.isElementToolSuppressedIn(ref, SHORT_NAME)) return null; + + HighlightInfo info = checkRefInner(ref); + addEmptyIntentionIfNeeded(info); + return info; + } + + @Nullable + private static HighlightInfo checkCodeRefInner(GrCodeReferenceElement refElement) { + if (PsiTreeUtil.getParentOfType(refElement, GroovyDocPsiElement.class) != null) return null; + + PsiElement nameElement = refElement.getReferenceNameElement(); + if (nameElement == null) return null; + + + if (!isInspectionEnabled(refElement.getContainingFile(), refElement.getProject())) return null; + //GroovyUnresolvedAccessInspection inspection = getInstance(refElement.getContainingFile(), refElement.getProject()); + + if (isResolvedStaticImport(refElement)) return null; + + GroovyResolveResult resolveResult = refElement.advancedResolve(); + final PsiElement resolved = resolveResult.getElement(); + + if (!(refElement.getParent() instanceof GrPackageDefinition) && resolved == null) { + String message = GroovyBundle.message("cannot.resolve", refElement.getReferenceName()); + HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.WRONG_REF, nameElement, message); + + // todo implement for nested classes + HighlightDisplayKey displayKey = HighlightDisplayKey.find(SHORT_NAME); + registerCreateClassByTypeFix(refElement, info, displayKey); + registerAddImportFixes(refElement, info, displayKey); + UnresolvedReferenceQuickFixProvider.registerReferenceFixes(refElement, new QuickFixActionRegistrarAdapter(info, displayKey)); + OrderEntryFix.registerFixes(new QuickFixActionRegistrarAdapter(info, displayKey), refElement); + + return info; + } + + return null; + } + + @Nullable + private static HighlightInfo checkRefInner(GrReferenceExpression ref) { + PsiElement refNameElement = ref.getReferenceNameElement(); + if (refNameElement == null) return null; + + if (!isInspectionEnabled(ref.getContainingFile(), ref.getProject())) return null; + GroovyUnresolvedAccessInspection inspection = getInstance(ref.getContainingFile(), ref.getProject()); + + + boolean cannotBeDynamic = PsiUtil.isCompileStatic(ref) || isPropertyAccessInStaticMethod(ref); + GroovyResolveResult resolveResult = getBestResolveResult(ref); + + if (resolveResult.getElement() != null) { + if (isStaticOk(resolveResult)) return null; + String message = GroovyBundle.message("cannot.reference.nonstatic", ref.getReferenceName()); + return createAnnotationForRef(ref, cannotBeDynamic, message); + } + + if (ResolveUtil.isKeyOfMap(ref)) { + return HighlightInfo.createHighlightInfo(HighlightInfoType.INFORMATION, refNameElement, null, MAP_KEY_ATTRIBUTES); + } + + if (!inspection.myHighlightIfGroovyObjectOverridden) { + if (areGroovyObjectMethodsOverridden(ref)) return null; + } + + if (!inspection.myHighlightIfMissingMethodsDeclared) { + if (areMissingMethodsDeclared(ref)) return null; + } + + + if (GrHighlightUtil.shouldHighlightAsUnresolved(ref)) { + HighlightInfo info = createAnnotationForRef(ref, cannotBeDynamic, GroovyBundle.message("cannot.resolve", ref.getReferenceName())); + + HighlightDisplayKey displayKey = HighlightDisplayKey.find(SHORT_NAME); + if (isCall(ref)) { + registerStaticImportFix(ref, info, displayKey); + } + else { + registerCreateClassByTypeFix(ref, info, displayKey); + registerAddImportFixes(ref, info, displayKey); + } + + registerReferenceFixes(ref, info, cannotBeDynamic, displayKey); + UnresolvedReferenceQuickFixProvider.registerReferenceFixes(ref, new QuickFixActionRegistrarAdapter(info, displayKey)); + OrderEntryFix.registerFixes(new QuickFixActionRegistrarAdapter(info, displayKey), ref); + return info; + } + + return null; + } + + private static boolean areMissingMethodsDeclared(GrReferenceExpression ref) { + PsiType qualifierType = GrReferenceResolveUtil.getQualifierType(ref); + if (!(qualifierType instanceof PsiClassType)) return false; + + PsiClass resolved = ((PsiClassType)qualifierType).resolve(); + if (resolved == null) return false; + + if (ref.getParent() instanceof GrCall) { + PsiMethod[] found = resolved.findMethodsByName("methodMissing", true); + for (PsiMethod method : found) { + if (MissingMethodAndPropertyUtil.isMethodMissing(method)) return true; + } + } + else { + PsiMethod[] found = resolved.findMethodsByName("propertyMissing", true); + for (PsiMethod method : found) { + if (MissingMethodAndPropertyUtil.isPropertyMissing(method)) return true; + } + } + + return false; + } + + private static boolean areGroovyObjectMethodsOverridden(GrReferenceExpression ref) { + PsiType qualifierType = GrReferenceResolveUtil.getQualifierType(ref); + if (!(qualifierType instanceof PsiClassType)) return false; + + PsiClass resolved = ((PsiClassType)qualifierType).resolve(); + if (resolved == null) return false; + + PsiClass groovyObject = + JavaPsiFacade.getInstance(ref.getProject()).findClass(GroovyCommonClassNames.GROOVY_OBJECT, ref.getResolveScope()); + if (groovyObject == null) return false; + + + String methodName; + if (ref.getParent() instanceof GrCall) { + methodName = "invokeMethod"; + } + else if (PsiUtil.isLValue(ref)) { + methodName = "setProperty"; + } + else { + methodName = "getProperty"; + } + + PsiMethod[] patternMethods = groovyObject.findMethodsByName(methodName, false); + if (patternMethods.length != 1) return false; + + PsiMethod patternMethod = patternMethods[0]; + PsiMethod found = resolved.findMethodBySignature(patternMethod, true); + if (found == null) return false; + + PsiClass aClass = found.getContainingClass(); + if (aClass == null) return false; + String qname = aClass.getQualifiedName(); + if (GroovyCommonClassNames.GROOVY_OBJECT.equals(qname)) return false; + if (GroovyCommonClassNames.GROOVY_OBJECT_SUPPORT.equals(qname)) return false; + + return true; + } + + private static void addEmptyIntentionIfNeeded(@Nullable HighlightInfo info) { + if (info != null) { + int s1 = info.quickFixActionMarkers != null ? info.quickFixActionMarkers.size() : 0; + int s2 = info.quickFixActionRanges != null ? info.quickFixActionRanges.size() : 0; + + if (s1 + s2 == 0) { + EmptyIntentionAction emptyIntentionAction = new EmptyIntentionAction("Access to unresolved expression"); + QuickFixAction.registerQuickFixAction(info, emptyIntentionAction, HighlightDisplayKey.find(SHORT_NAME)); + } + } + } + + + private static boolean isResolvedStaticImport(GrCodeReferenceElement refElement) { + final PsiElement parent = refElement.getParent(); + return parent instanceof GrImportStatement && + ((GrImportStatement)parent).isStatic() && + refElement.multiResolve(false).length > 0; + } + + private static boolean isStaticOk(GroovyResolveResult resolveResult) { + if (resolveResult.isStaticsOK()) return true; + + PsiElement resolved = resolveResult.getElement(); + LOG.assertTrue(resolved != null); + LOG.assertTrue(resolved instanceof PsiModifierListOwner, resolved + " : " + resolved.getText()); + + return (((PsiModifierListOwner)resolved).hasModifierProperty(STATIC)); + } + + private static GroovyResolveResult getBestResolveResult(GrReferenceExpression ref) { + GroovyResolveResult[] results = ref.multiResolve(false); + if (results.length == 0) return GroovyResolveResult.EMPTY_RESULT; + if (results.length == 1) return results[0]; + + for (GroovyResolveResult result : results) { + if (result.isAccessible() && result.isStaticsOK()) return result; + } + + for (GroovyResolveResult result : results) { + if (result.isStaticsOK()) return result; + } + + return results[0]; + } + + private static boolean isPropertyAccessInStaticMethod(GrReferenceExpression referenceExpression) { + if (referenceExpression.getParent() instanceof GrMethodCall) return false; + GrMember context = PsiTreeUtil.getParentOfType(referenceExpression, GrMember.class, true, GrClosableBlock.class); + return (context instanceof GrMethod || context instanceof GrClassInitializer) && context.hasModifierProperty(STATIC); + } + + @Nullable + private static HighlightInfo createAnnotationForRef(@NotNull GrReferenceExpression ref, + boolean compileStatic, + @Nullable final String message) { + PsiElement refNameElement = ref.getReferenceNameElement(); + assert refNameElement != null; + + HighlightDisplayLevel displayLevel = getHighlightDisplayLevel(ref.getProject(), ref); + + if (compileStatic || displayLevel == HighlightDisplayLevel.ERROR) { + return HighlightInfo.createHighlightInfo(HighlightInfoType.WRONG_REF, refNameElement, message); + } + + if (displayLevel == HighlightDisplayLevel.WARNING) { + boolean isTestMode = ApplicationManager.getApplication().isUnitTestMode(); + HighlightInfoType infotype = isTestMode ? HighlightInfoType.WARNING : HighlightInfoType.INFORMATION; + + return HighlightInfo.createHighlightInfo(infotype, refNameElement, message, UNRESOLVED_ACCESS_ATTRIBUTES); + } + + HighlightInfoType highlightInfoType = HighlightInfo.convertSeverity(displayLevel.getSeverity()); + return HighlightInfo.createHighlightInfo(highlightInfoType, refNameElement, message); + } + + private static void registerStaticImportFix(GrReferenceExpression referenceExpression, HighlightInfo info, final HighlightDisplayKey key) { + final String referenceName = referenceExpression.getReferenceName(); + if (StringUtil.isEmpty(referenceName)) return; + if (referenceExpression.getQualifier() != null) return; + + QuickFixAction.registerQuickFixAction(info, new GroovyStaticImportMethodFix((GrMethodCall)referenceExpression.getParent()), key); + } + + private static void registerReferenceFixes(GrReferenceExpression refExpr, + HighlightInfo info, + boolean compileStatic, final HighlightDisplayKey key) { + PsiClass targetClass = QuickfixUtil.findTargetClass(refExpr, compileStatic); + if (targetClass == null) return; + + if (!compileStatic) { + addDynamicAnnotation(info, refExpr, key); + } + if (targetClass.isWritable()) { + QuickFixAction.registerQuickFixAction(info, new CreateFieldFromUsageFix(refExpr, targetClass), key); + + if (refExpr.getParent() instanceof GrCall && refExpr.getParent() instanceof GrExpression) { + QuickFixAction.registerQuickFixAction(info, new CreateMethodFromUsageFix(refExpr, targetClass), key); + } + } + + if (!refExpr.isQualified()) { + GrVariableDeclarationOwner owner = PsiTreeUtil.getParentOfType(refExpr, GrVariableDeclarationOwner.class); + if (!(owner instanceof GroovyFileBase) || ((GroovyFileBase)owner).isScript()) { + QuickFixAction.registerQuickFixAction(info, new CreateLocalVariableFromUsageFix(refExpr, owner), key); + } + if (PsiTreeUtil.getParentOfType(refExpr, GrMethod.class) != null) { + QuickFixAction.registerQuickFixAction(info, new CreateParameterFromUsageFix(refExpr), key); + } + } + } + + private static void addDynamicAnnotation(HighlightInfo info, GrReferenceExpression referenceExpression, HighlightDisplayKey key) { + final PsiFile containingFile = referenceExpression.getContainingFile(); + VirtualFile file; + if (containingFile != null) { + file = containingFile.getVirtualFile(); + if (file == null) return; + } + else { + return; + } + + if (isCall(referenceExpression)) { + PsiType[] argumentTypes = PsiUtil.getArgumentTypes(referenceExpression, false); + if (argumentTypes != null) { + QuickFixAction.registerQuickFixAction(info, referenceExpression.getTextRange(), + new DynamicMethodFix(referenceExpression, argumentTypes), key); + } + } + else { + QuickFixAction.registerQuickFixAction(info, referenceExpression.getTextRange(), new DynamicPropertyFix(referenceExpression), key); + } + } + + private static void registerAddImportFixes(GrReferenceElement refElement, HighlightInfo info, final HighlightDisplayKey key) { + final String referenceName = refElement.getReferenceName(); + //noinspection ConstantConditions + if (StringUtil.isEmpty(referenceName)) return; + if (!(refElement instanceof GrCodeReferenceElement) && Character.isLowerCase(referenceName.charAt(0))) return; + if (refElement.getQualifier() != null) return; + + QuickFixAction.registerQuickFixAction(info, new GroovyAddImportAction(refElement), key); + } + + private static void registerCreateClassByTypeFix(GrReferenceElement refElement, HighlightInfo info, final HighlightDisplayKey key) { + GrPackageDefinition packageDefinition = PsiTreeUtil.getParentOfType(refElement, GrPackageDefinition.class); + if (packageDefinition != null) return; + + PsiElement parent = refElement.getParent(); + if (parent instanceof GrNewExpression && + refElement.getManager().areElementsEquivalent(((GrNewExpression)parent).getReferenceElement(), refElement)) { + QuickFixAction.registerQuickFixAction(info, CreateClassFix.createClassFromNewAction((GrNewExpression)parent), key); + } + else { + if (shouldBeInterface(refElement)) { + QuickFixAction.registerQuickFixAction(info, CreateClassFix.createClassFixAction(refElement, CreateClassKind.INTERFACE), key); + } + else if (shouldBeClass(refElement)) { + QuickFixAction.registerQuickFixAction(info, CreateClassFix.createClassFixAction(refElement, CreateClassKind.CLASS), key); + QuickFixAction.registerQuickFixAction(info, CreateClassFix.createClassFixAction(refElement, CreateClassKind.ENUM), key); + } + else if (shouldBeAnnotation(refElement)) { + QuickFixAction.registerQuickFixAction(info, CreateClassFix.createClassFixAction(refElement, CreateClassKind.ANNOTATION), key); + } + else { + QuickFixAction.registerQuickFixAction(info, CreateClassFix.createClassFixAction(refElement, CreateClassKind.CLASS), key); + QuickFixAction.registerQuickFixAction(info, CreateClassFix.createClassFixAction(refElement, CreateClassKind.INTERFACE),key); + QuickFixAction.registerQuickFixAction(info, CreateClassFix.createClassFixAction(refElement, CreateClassKind.ENUM), key); + QuickFixAction.registerQuickFixAction(info, CreateClassFix.createClassFixAction(refElement, CreateClassKind.ANNOTATION), key); + } + } + } + + private static boolean shouldBeAnnotation(GrReferenceElement element) { + return element.getParent() instanceof GrAnnotation; + } + + private static boolean shouldBeInterface(GrReferenceElement myRefElement) { + PsiElement parent = myRefElement.getParent(); + return parent instanceof GrImplementsClause || parent instanceof GrExtendsClause && parent.getParent() instanceof GrInterfaceDefinition; + } + + private static boolean shouldBeClass(GrReferenceElement myRefElement) { + PsiElement parent = myRefElement.getParent(); + return parent instanceof GrExtendsClause && !(parent.getParent() instanceof GrInterfaceDefinition); } @Nls @NotNull public String getGroupDisplayName() { - return PROBABLE_BUGS; + return BaseInspection.PROBABLE_BUGS; } @Nls @@ -56,91 +480,29 @@ public class GroovyUnresolvedAccessInspection extends BaseInspection { return "Access to unresolved expression"; } + private static class QuickFixActionRegistrarAdapter implements QuickFixActionRegistrar { + private final HighlightInfo myInfo; + private HighlightDisplayKey myKey; - @Override - protected String buildErrorString(Object... args) { - return "Can not resolve symbol '#ref'"; - } + public QuickFixActionRegistrarAdapter(HighlightInfo info, HighlightDisplayKey displayKey) { + myInfo = info; + myKey = displayKey; + } - private static class Visitor extends BaseInspectionVisitor { @Override - public void visitReferenceExpression(GrReferenceExpression refExpr) { - super.visitReferenceExpression(refExpr); - - PsiElement resolved = refExpr.advancedResolve().getElement(); - if (resolved != null) return; - - GrExpression qualifier = refExpr.getQualifierExpression(); - if (qualifier == null && isDeclarationAssignment(refExpr)) return; - - PsiElement parent = refExpr.getParent(); - if (!(parent instanceof GrCall) && ResolveUtil.isKeyOfMap(refExpr)) return; // It's a key of map. - - if (!GrHighlightUtil.shouldHighlightAsUnresolved(refExpr)) return; - - if (qualifier != null && isBuilderInvocation(refExpr)) return; - - PsiElement refNameElement = refExpr.getReferenceNameElement(); - registerError(refNameElement == null ? refExpr : refNameElement); + public void register(IntentionAction action) { + myKey = HighlightDisplayKey.find(SHORT_NAME); + QuickFixAction.registerQuickFixAction(myInfo, action, myKey); } - } - private static boolean isBuilderInvocation(@NotNull GrReferenceExpression refExpr) { - GrExpression qualifier = refExpr.getQualifier(); - PsiType type = qualifier == null ? null : qualifier.getType(); - if (type instanceof PsiClassType) { - PsiClass target = ((PsiClassType)type).resolve(); - if (target != null) { - for (PsiMethod method : findBuilderMetaMethods(refExpr, target)) { - PsiClass containingClass = method.getContainingClass(); - if (containingClass != null && - method.getParameterList().getParameters()[0].getType().equalsToText(CommonClassNames.JAVA_LANG_STRING)) { - String qname = containingClass.getQualifiedName(); - if (!GroovyCommonClassNames.GROOVY_OBJECT.equals(qname) && !GroovyCommonClassNames.GROOVY_OBJECT_SUPPORT.equals(qname)) { - return true; - } - } - } - } + @Override + public void register(TextRange fixRange, IntentionAction action, HighlightDisplayKey key) { + QuickFixAction.registerQuickFixAction(myInfo, fixRange, action, key); } - return false; - } - - private static List findBuilderMetaMethods(GrReferenceExpression refExpr, PsiClass target) { - boolean gpp = GppTypeConverter.hasTypedContext(target) && GppTypeConverter.hasTypedContext(refExpr); - if (refExpr.getParent() instanceof GrCall) { - List toSearch = - ContainerUtil.newArrayList(target.findMethodsByName(gpp ? "invokeUnresolvedMethod" : "invokeMethod", true)); - for (Iterator iterator = toSearch.iterator(); iterator.hasNext(); ) { - PsiMethod method = iterator.next(); - if (!gpp && - (method.getParameterList().getParametersCount() != 2 || method.getParameterList().getParameters()[1].getType() - .equalsToText(CommonClassNames.JAVA_LANG_OBJECT + "[]"))) { - iterator.remove(); - } - } - return toSearch; + @Override + public void unregister(Condition condition) { + QuickFixAction.unregisterQuickFixAction(myInfo, condition); } - - if (PsiUtil.isLValue(refExpr)) { - List toSearch = ContainerUtil.newArrayList(target.findMethodsByName(gpp ? "setUnresolvedProperty" : "setProperty", true)); - for (Iterator iterator = toSearch.iterator(); iterator.hasNext(); ) { - PsiMethod method = iterator.next(); - if (method.getParameterList().getParametersCount() != 2 || (!gpp && !method.getParameterList().getParameters()[1].getType() - .equalsToText(CommonClassNames.JAVA_LANG_OBJECT))) { - iterator.remove(); - } - } - return toSearch; - } - - List toSearch = ContainerUtil.newArrayList(target.findMethodsByName(gpp ? "getUnresolvedProperty" : "getProperty", true)); - for (Iterator iterator = toSearch.iterator(); iterator.hasNext(); ) { - if (iterator.next().getParameterList().getParametersCount() != 1) { - iterator.remove(); - } - } - return toSearch; } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java index c55fb9338803..8b5774d0195f 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java @@ -56,6 +56,7 @@ import org.jetbrains.plugins.groovy.lang.psi.controlFlow.impl.ThrowingInstructio import org.jetbrains.plugins.groovy.lang.psi.dataFlow.DFAEngine; import org.jetbrains.plugins.groovy.lang.psi.dataFlow.DfaInstance; import org.jetbrains.plugins.groovy.lang.psi.dataFlow.Semilattice; +import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightLocalVariable; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import java.util.*; @@ -822,7 +823,9 @@ public class ControlFlowUtils { if (element instanceof GrVariable && element != var) return; if (element instanceof GrReferenceExpression) { final GrReferenceExpression ref = (GrReferenceExpression)element; - if (ref.isQualified() || ref.resolve() != var) return; + if (ref.isQualified() || !(ref.resolve() == var || var instanceof GrLightLocalVariable && var.getNavigationElement() == ref)) { + return; + } } if (!((ReadWriteVariableInstruction)instruction).getVariableName().equals(var.getName())) { return; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/GrImplicitUsageProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/GrImplicitUsageProvider.java index 928b27d35f2e..ca486c2d972d 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/GrImplicitUsageProvider.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/GrImplicitUsageProvider.java @@ -21,6 +21,9 @@ import org.jetbrains.plugins.groovy.lang.completion.GroovyCompletionUtil; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; +import static org.jetbrains.plugins.groovy.findUsages.MissingMethodAndPropertyUtil.isMethodMissing; +import static org.jetbrains.plugins.groovy.findUsages.MissingMethodAndPropertyUtil.isPropertyMissing; + /** * @author Max Medvedev */ @@ -45,16 +48,6 @@ public class GrImplicitUsageProvider implements ImplicitUsageProvider { return false; } - private static boolean isMethodMissing(GrMethod method) { - GrParameter[] parameters = method.getParameters(); - return method.getName().equals("methodMissing") && (parameters.length == 2 || parameters.length == 1); - } - - private static boolean isPropertyMissing(GrMethod method) { - GrParameter[] parameters = method.getParameters(); - return method.getName().equals("propertyMissing") && (parameters.length == 2 || parameters.length == 1); - } - @Override public boolean isImplicitRead(PsiElement element) { return false; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/MissingMethodAndPropertyUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/MissingMethodAndPropertyUtil.java new file mode 100644 index 000000000000..a0c75e60d99f --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/MissingMethodAndPropertyUtil.java @@ -0,0 +1,35 @@ +/* + * Copyright 2000-2012 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.findUsages; + +import com.intellij.psi.PsiMethod; +import com.intellij.psi.PsiParameter; + +/** + * @author Max Medvedev + */ +public class MissingMethodAndPropertyUtil { + public static boolean isMethodMissing(PsiMethod method) { + PsiParameter[] parameters = method.getParameterList().getParameters(); + return method.getName().equals("methodMissing") && (parameters.length == 2 || parameters.length == 1); + } + + + public static boolean isPropertyMissing(PsiMethod method) { + PsiParameter[] parameters = method.getParameterList().getParameters(); + return method.getName().equals("propertyMissing") && (parameters.length == 2 || parameters.length == 1); + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties index f040996b8e0d..d52cfd6e5bf7 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties @@ -193,4 +193,5 @@ gr.make.member.protected.intention.family.name=Make 'protected' convert.multiline.string.to.single.line.intention.name=Convert to single-line convert.multiline.string.to.single.line.intention.family.name=Convert multiline string to single-line gr.convert.type.cast.to.safe.cast.intention.name=Convert to safe cast -gr.convert.type.cast.to.safe.cast.intention.family.name=Convert cast expression to safe cast expression \ No newline at end of file +gr.convert.type.cast.to.safe.cast.intention.family.name=Convert cast expression to safe cast expression +cannot.create.class=Cannot create class \ No newline at end of file diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/strings/ConvertConcatenationToGstringIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/strings/ConvertConcatenationToGstringIntention.java index 6fd84ee408ff..49043aa22ab3 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/strings/ConvertConcatenationToGstringIntention.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/strings/ConvertConcatenationToGstringIntention.java @@ -55,7 +55,6 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUt import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.literals.GrLiteralImpl; import org.jetbrains.plugins.groovy.lang.psi.util.GrStringUtil; import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames; -import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceHandlerBase; import java.util.ArrayList; import java.util.List; @@ -74,9 +73,8 @@ public class ConvertConcatenationToGstringIntention extends Intention { } - private static List collectExpressions(final PsiFile file, final Editor editor, final int offset) { - int correctedOffset = GrIntroduceHandlerBase.correctOffset(editor, offset); - final PsiElement elementAtCaret = file.findElementAt(correctedOffset); + private static List collectExpressions(final PsiFile file, final int offset) { + final PsiElement elementAtCaret = file.findElementAt(offset); final List expressions = new ArrayList(); for (GrExpression expression = PsiTreeUtil.getParentOfType(elementAtCaret, GrExpression.class); @@ -100,7 +98,7 @@ public class ConvertConcatenationToGstringIntention extends Intention { final AccessToken accessToken = ReadAction.start(); final List expressions; try { - expressions = collectExpressions(file, editor, offset); + expressions = collectExpressions(file, offset); } finally { accessToken.finish(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyMembersGetter.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyMembersGetter.java index 8cc15d43cebb..30a087ca3187 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyMembersGetter.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyMembersGetter.java @@ -23,7 +23,6 @@ import com.intellij.psi.*; import com.intellij.psi.filters.getters.MembersGetter; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.Consumer; -import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; @@ -63,6 +62,6 @@ class GroovyMembersGetter extends MembersGetter { } private boolean isSuitableType(PsiType type) { - return type != null && TypesUtil.isAssignable(myExpectedType, type, (GroovyPsiElement)myPlace.getParent(), false); + return type != null && TypesUtil.isAssignableByMethodCallConversion(myExpectedType, type, myPlace.getManager(), myPlace.getResolveScope()); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovySmartCompletionContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovySmartCompletionContributor.java index 397989a17057..66631baad5df 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovySmartCompletionContributor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovySmartCompletionContributor.java @@ -45,6 +45,8 @@ import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; +import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation; +import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotationNameValuePair; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration; @@ -53,6 +55,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals import org.jetbrains.plugins.groovy.lang.psi.dataFlow.types.TypeInferenceHelper; import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.GroovyExpectedTypesProvider; import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.TypeConstraint; +import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.CompleteReferenceExpression; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil; @@ -73,6 +76,9 @@ public class GroovySmartCompletionContributor extends CompletionContributor { or(psiElement(GrAssignmentExpression.class), psiElement(GrVariable.class)))); static final ElementPattern AFTER_NEW = psiElement().afterLeaf(psiElement().withText(PsiKeyword.NEW)); + + private static final ElementPattern IN_ANNOTATION = psiElement().withParent(psiElement(GrReferenceExpression.class).withParent(GrAnnotationNameValuePair.class)); + private static final TObjectHashingStrategy EXPECTED_TYPE_INFO_STRATEGY = new TObjectHashingStrategy() { public int computeHashCode(final TypeConstraint object) { @@ -93,6 +99,8 @@ public class GroovySmartCompletionContributor extends CompletionContributor { final PsiElement position = params.getPosition(); if (position.getParent() instanceof GrLiteral) return; + if (isInDefaultAnnotationNameValuePair(position)) return; + final Set infos = getExpectedTypeInfos(params); final PsiElement reference = position.getParent(); @@ -195,10 +203,59 @@ public class GroovySmartCompletionContributor extends CompletionContributor { } }); + extend(CompletionType.SMART, IN_ANNOTATION, new CompletionProvider() { + @Override + protected void addCompletions(@NotNull CompletionParameters params, + ProcessingContext context, + @NotNull final CompletionResultSet result) { + final PsiElement position = params.getPosition(); + + if (!isInDefaultAnnotationNameValuePair(position)) return; + + final GrReferenceExpression reference = (GrReferenceExpression)position.getParent(); + if (reference == null) return; + + CompleteReferenceExpression.processRefInAnnotation(reference, result.getPrefixMatcher(), new Consumer() { + @Override + public void consume(@Nullable LookupElement element) { + if (element != null) { + result.addElement(element); + } + } + }); + } + }); + + } + + /** + * we are here: @Abc() + * where Abc does not have 'value' attribute + */ + private static boolean isInDefaultAnnotationNameValuePair(PsiElement position) { + PsiElement parent = position.getParent(); + if (parent instanceof GrReferenceExpression) { + PsiElement pparent = parent.getParent(); + if (pparent instanceof GrAnnotationNameValuePair) { + PsiElement identifier = ((GrAnnotationNameValuePair)pparent).getNameIdentifierGroovy(); + if (identifier == null) { + PsiElement ppparent = pparent.getParent().getParent(); + if (ppparent instanceof GrAnnotation) { + PsiElement resolved = ((GrAnnotation)ppparent).getClassReference().resolve(); + if (resolved instanceof PsiClass && ((PsiClass)resolved).isAnnotationType()) { + PsiMethod[] values = ((PsiClass)resolved).findMethodsByName("value", false); + return values.length == 0; + } + } + } + } + } + + return false; } static void addExpectedClassMembers(CompletionParameters params, final CompletionResultSet result) { - for (TypeConstraint info : getExpectedTypeInfos(params)) { + for (final TypeConstraint info : getExpectedTypeInfos(params)) { Consumer consumer = new Consumer() { @Override public void consume(LookupElement element) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/annotations/AnnotationArguments.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/annotations/AnnotationArguments.java index 720ab13428dd..4bb0a5a55b2f 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/annotations/AnnotationArguments.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/annotations/AnnotationArguments.java @@ -43,24 +43,20 @@ public class AnnotationArguments implements GroovyElementTypes { } if (ParserUtils.lookAhead(builder, mIDENT, mASSIGN)) { - if (!parseAnnotationMemberValuePairs(builder, parser)) { - annArgs.rollbackTo(); - return; - } - } else { + parsePairs(builder, parser); + } + else { PsiBuilder.Marker pairMarker = builder.mark(); - if (!parseAnnotationMemberValueInitializer(builder, parser)) { - pairMarker.drop(); - } else { + if (parseAnnotationMemberValueInitializer(builder, parser)) { pairMarker.done(ANNOTATION_MEMBER_VALUE_PAIR); } + else { + pairMarker.drop(); + } } ParserUtils.getToken(builder, mNLS); - - if (!ParserUtils.getToken(builder, mRPAREN)) { - builder.error(GroovyBundle.message("rparen.expected")); - } + ParserUtils.getToken(builder, mRPAREN, GroovyBundle.message("rparen.expected")); annArgs.done(ANNOTATION_ARGUMENTS); } @@ -71,14 +67,15 @@ public class AnnotationArguments implements GroovyElementTypes { public static boolean parseAnnotationMemberValueInitializer(PsiBuilder builder, GroovyParser parser) { if (builder.getTokenType() == mAT) { return Annotation.parse(builder, parser); - } else if(builder.getTokenType() == mLBRACK) { + } + else if (builder.getTokenType() == mLBRACK) { PsiBuilder.Marker marker = builder.mark(); ParserUtils.getToken(builder, mLBRACK); - while (parseAnnotationMemberValueInitializer(builder, parser)){ + while (parseAnnotationMemberValueInitializer(builder, parser)) { if (builder.eof() || builder.getTokenType() == mRBRACK) break; ParserUtils.getToken(builder, mCOMMA, GroovyBundle.message("comma.expected")); } - + ParserUtils.getToken(builder, mRBRACK, GroovyBundle.message("rbrack.expected")); marker.done(ANNOTATION_ARRAY_INITIALIZER); return true; @@ -92,10 +89,10 @@ public class AnnotationArguments implements GroovyElementTypes { * anntotationMemberValuePairs ::= annotationMemberValuePair ( COMMA nls annotationMemberValuePair )* */ - private static boolean parseAnnotationMemberValuePairs(PsiBuilder builder, GroovyParser parser) { + private static boolean parsePairs(PsiBuilder builder, GroovyParser parser) { PsiBuilder.Marker start = builder.mark(); - if (!parseAnnotationMemberValueSinglePair(builder, parser)) { + if (!parsePair(builder, parser)) { start.rollbackTo(); return false; } @@ -103,10 +100,7 @@ public class AnnotationArguments implements GroovyElementTypes { while (ParserUtils.getToken(builder, mCOMMA)) { ParserUtils.getToken(builder, mNLS); - if (!parseAnnotationMemberValueSinglePair(builder, parser)) { - start.rollbackTo(); - return false; - } + parsePair(builder, parser); } start.drop(); @@ -117,26 +111,23 @@ public class AnnotationArguments implements GroovyElementTypes { * annotationMemberValuePair ::= IDENT ASSIGN nls annotationMemberValueInitializer */ - private static boolean parseAnnotationMemberValueSinglePair(PsiBuilder builder, GroovyParser parser) { - PsiBuilder.Marker annmvp = builder.mark(); + private static boolean parsePair(PsiBuilder builder, GroovyParser parser) { + PsiBuilder.Marker marker = builder.mark(); - if (!ParserUtils.getToken(builder, mIDENT)) { - annmvp.rollbackTo(); - return false; + if (ParserUtils.lookAhead(builder, mIDENT, mASSIGN)) { + ParserUtils.getToken(builder, mIDENT); + ParserUtils.getToken(builder, mASSIGN); + ParserUtils.getToken(builder, mNLS); } - - if (!ParserUtils.getToken(builder, mASSIGN)) { - annmvp.rollbackTo(); - return false; + else { + builder.error(GroovyBundle.message("attribute.name.expected")); } - ParserUtils.getToken(builder, mNLS); - if (!parseAnnotationMemberValueInitializer(builder, parser)) { builder.error(GroovyBundle.message("annotation.member.value.initializer.expected")); } - annmvp.done(ANNOTATION_MEMBER_VALUE_PAIR); + marker.done(ANNOTATION_MEMBER_VALUE_PAIR); return true; } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyElementVisitor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyElementVisitor.java index a8d2cc28afc6..ab15bfcb5bc6 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyElementVisitor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyElementVisitor.java @@ -52,7 +52,6 @@ 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.toplevel.packaging.GrPackageDefinition; import org.jetbrains.plugins.groovy.lang.psi.api.types.*; -import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrDisjunctionTypeElementImpl; /** * @author ven @@ -218,7 +217,7 @@ public abstract class GroovyElementVisitor { } public void visitPropertySelection(GrPropertySelection expression) { - visitReferenceExpression(expression); + visitExpression(expression); } public void visitIndexProperty(GrIndexProperty expression) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyFile.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyFile.java index ee10ed9afb9c..5c3014d7aebc 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyFile.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyFile.java @@ -15,12 +15,9 @@ */ package org.jetbrains.plugins.groovy.lang.psi; -import com.intellij.psi.PsiElement; import com.intellij.psi.PsiType; -import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMembersDeclaration; import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement; import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.packaging.GrPackageDefinition; @@ -40,14 +37,9 @@ public interface GroovyFile extends GroovyFileBase { void setPackageName(String packageName); - T addMemberDeclaration(@NotNull T decl, PsiElement anchorBefore) throws IncorrectOperationException; - - void removeMemberDeclaration (GrMembersDeclaration decl); - @Nullable GrPackageDefinition setPackage(GrPackageDefinition newPackage); @Nullable PsiType getInferredScriptReturnType(); - } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyFileBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyFileBase.java index a03536411b3f..916272361218 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyFileBase.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyFileBase.java @@ -23,7 +23,6 @@ import com.intellij.psi.PsiImportHolder; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrTopLevelDefinition; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.GrTopStatement; @@ -58,8 +57,6 @@ public interface GroovyFileBase extends PsiFile, GrVariableDeclarationOwner, GrS GrMethod[] getMethods(); - GrVariableDeclaration[] getTopLevelVariableDeclarations(); - GrTopStatement[] getTopStatements(); GrImportStatement addImportForClass(PsiClass aClass) throws IncorrectOperationException; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/auxiliary/modifiers/annotation/GrAnnotationNameValuePair.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/auxiliary/modifiers/annotation/GrAnnotationNameValuePair.java index ec19efd8a678..ea78e8b54af9 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/auxiliary/modifiers/annotation/GrAnnotationNameValuePair.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/auxiliary/modifiers/annotation/GrAnnotationNameValuePair.java @@ -31,5 +31,6 @@ public interface GrAnnotationNameValuePair extends GroovyPsiElement, PsiNameValu @Nullable PsiElement getNameIdentifierGroovy(); + @Nullable GrAnnotationMemberValue getValue(); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/expressions/path/GrPropertySelection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/expressions/path/GrPropertySelection.java index aa47134122a3..14aab5ba5f68 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/expressions/path/GrPropertySelection.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/expressions/path/GrPropertySelection.java @@ -18,20 +18,17 @@ package org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path; import com.intellij.psi.PsiElement; 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; /** * @author ilyas */ -public interface GrPropertySelection extends GrReferenceExpression { +public interface GrPropertySelection extends GrExpression { @NotNull GrExpression getQualifier(); @NotNull PsiElement getDotToken(); - @Override PsiElement getReferenceNameElement(); } \ No newline at end of file diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/typedef/GrMemberOwner.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/typedef/GrMemberOwner.java deleted file mode 100644 index dd269d9f46c2..000000000000 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/typedef/GrMemberOwner.java +++ /dev/null @@ -1,31 +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.plugins.groovy.lang.psi.api.statements.typedef; - -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiElement; -import com.intellij.util.IncorrectOperationException; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMembersDeclaration; - -/** - * @author ilyas - */ -public interface GrMemberOwner extends PsiClass { - T addMemberDeclaration(T decl, @Nullable PsiElement anchorBefore) throws IncorrectOperationException ; - -} \ No newline at end of file diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/typedef/GrTypeDefinition.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/typedef/GrTypeDefinition.java index aa8ace28d434..026ecfa4e209 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/typedef/GrTypeDefinition.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/typedef/GrTypeDefinition.java @@ -38,8 +38,8 @@ import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeParameterList; * @autor: Dmitry.Krasilschikov * @date: 18.03.2007 */ -public interface GrTypeDefinition extends GrTopStatement, NavigatablePsiElement, PsiClass, GrTopLevelDefinition, GrMemberOwner, - GrDocCommentOwner, GrMember { +public interface GrTypeDefinition + extends GrTopStatement, NavigatablePsiElement, PsiClass, GrTopLevelDefinition, GrDocCommentOwner, GrMember { GrTypeDefinition[] EMPTY_ARRAY = new GrTypeDefinition[0]; ArrayFactory ARRAY_FACTORY = new ArrayFactory() { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java index 122739f24165..e847b0bc611d 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java @@ -995,6 +995,10 @@ public class ControlFlowBuilder extends GroovyRecursiveElementVisitor { statement.accept(this); if (j == i) handlePossibleReturn(statement); } + + if (myHead != null) { + addPendingEdge(caseSection, myHead); + } } public void visitTryStatement(GrTryCatchStatement tryCatchStatement) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileBaseImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileBaseImpl.java index 78abf78d6221..c5184f32dc4c 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileBaseImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileBaseImpl.java @@ -134,10 +134,6 @@ public abstract class GroovyFileBaseImpl extends PsiFileBase implements GroovyFi return myMethods; } - public GrVariableDeclaration[] getTopLevelVariableDeclarations() { - return findChildrenByClass(GrVariableDeclaration.class); - } - public GrTopStatement[] getTopStatements() { return findChildrenByClass(GrTopStatement.class); } 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 182881295063..cf1f00d3a4f3 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,9 +18,7 @@ package org.jetbrains.plugins.groovy.lang.psi.impl; import com.intellij.lang.ASTNode; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; -import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.codeStyle.PackageEntry; import com.intellij.psi.codeStyle.PackageEntryTable; @@ -47,7 +45,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrTopLevelDefinition 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.GrMember; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMembersDeclaration; import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.GrTopStatement; import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement; import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.packaging.GrPackageDefinition; @@ -402,35 +399,10 @@ public class GroovyFileImpl extends GroovyFileBaseImpl implements GroovyFile { } } - public T addMemberDeclaration(@NotNull T decl, PsiElement anchorBefore) - throws IncorrectOperationException { - T result = (T)addBefore(decl, anchorBefore); - CodeStyleManager styleManager = CodeStyleManager.getInstance(getManager().getProject()); - PsiElement parent = result.getContainingFile(); - TextRange range = result.getTextRange(); - if (checkRange(parent, range.getEndOffset())) { - styleManager.reformatRange(parent, range.getEndOffset() - 1, range.getEndOffset() + 1); - } - if (checkRange(parent, range.getStartOffset())) { - styleManager.reformatRange(parent, range.getStartOffset() - 1, range.getStartOffset() + 1); - } - - return result; - } - private static boolean checkRange(PsiElement parent, int offset) { return parent.getTextRange().contains(offset -1) && parent.getTextRange().contains(offset+1); } - public void removeMemberDeclaration(GrMembersDeclaration decl) { - try { - deleteChildRange(decl, decl); - } - catch (IncorrectOperationException e) { - throw new RuntimeException(e); - } - } - @Nullable @Override public GrPackageDefinition setPackage(@Nullable GrPackageDefinition newPackage) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationImpl.java index ddb032dfb9ef..d2a891b4b3f1 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationImpl.java @@ -95,7 +95,7 @@ public class GrAnnotationImpl extends GrStubElementBase implem return null; } - public PsiAnnotationMemberValue findAttributeValue(String attributeName) { + public PsiAnnotationMemberValue findAttributeValue(@Nullable String attributeName) { return PsiImplUtil.findAttributeValue(this, attributeName); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/CompleteReferenceExpression.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/CompleteReferenceExpression.java index 243dead9969f..124fbd9f9994 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/CompleteReferenceExpression.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/CompleteReferenceExpression.java @@ -72,7 +72,7 @@ public class CompleteReferenceExpression { } public static void processVariants(PrefixMatcher matcher, Consumer consumer, GrReferenceExpressionImpl refExpr, CompletionParameters parameters) { - processRefInAnnotation(consumer, refExpr, matcher); + processRefInAnnotation(refExpr, matcher, consumer); final CompleteReferenceProcessor processor = new CompleteReferenceProcessor(refExpr, consumer, matcher, parameters); getVariantsImpl(refExpr, processor); @@ -82,8 +82,10 @@ public class CompleteReferenceExpression { } } - private static void processRefInAnnotation(Consumer consumer, GrReferenceExpressionImpl refExpr, PrefixMatcher matcher) { - if (refExpr.getParent() instanceof GrAnnotationNameValuePair) { + public static void processRefInAnnotation(GrReferenceExpression refExpr, + PrefixMatcher matcher, Consumer consumer) { + if (refExpr.getParent() instanceof GrAnnotationNameValuePair && + ((GrAnnotationNameValuePair)refExpr.getParent()).getNameIdentifierGroovy() == null) { PsiElement parent = refExpr.getParent().getParent(); if (!(parent instanceof GrAnnotation)) { parent = parent.getParent(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrAssignmentExpressionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrAssignmentExpressionImpl.java index 04bfbddf302f..7503b9891456 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrAssignmentExpressionImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrAssignmentExpressionImpl.java @@ -17,11 +17,16 @@ package org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions; import com.intellij.lang.ASTNode; +import com.intellij.openapi.util.Key; import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; import com.intellij.psi.impl.source.resolve.ResolveCache; import com.intellij.psi.scope.PsiScopeProcessor; import com.intellij.psi.tree.IElementType; +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.ArrayUtil; import com.intellij.util.Function; import com.intellij.util.IncorrectOperationException; @@ -32,13 +37,15 @@ import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; import org.jetbrains.plugins.groovy.lang.lexer.TokenSets; import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor; import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrAssignmentExpression; 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.GrIndexProperty; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod; -import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil; import org.jetbrains.plugins.groovy.lang.psi.dataFlow.types.TypeInferenceHelper; +import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil; +import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightLocalVariable; import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil; import org.jetbrains.plugins.groovy.lang.resolve.processors.ResolverProcessor; @@ -68,6 +75,7 @@ public class GrAssignmentExpressionImpl extends GrExpressionImpl implements GrAs return returnType; } }; + private static final Key> LOCAL_VAR_KEY = Key.create("local var"); public GrAssignmentExpressionImpl(@NotNull ASTNode node) { super(node); @@ -109,20 +117,42 @@ public class GrAssignmentExpressionImpl extends GrExpressionImpl implements GrAs } GrExpression lValue = getLValue(); - if (lValue instanceof GrReferenceExpression) { - String refName = processor instanceof ResolverProcessor ? ((ResolverProcessor) processor).getName() : null; - if (isDeclarationAssignment((GrReferenceExpression) lValue, refName)) { - if (!processor.execute(lValue, ResolveState.initial())) return false; + if (lValue instanceof GrReferenceExpression && ((GrReferenceExpression)lValue).getQualifier() == null) { + String refName = processor instanceof ResolverProcessor ? ((ResolverProcessor)processor).getName() : null; + if (isDeclarationAssignment((GrReferenceExpression)lValue, refName)) { + + GrVariable var = getOrCreateLocalVar(); + if (!processor.execute(var, ResolveState.initial())) { + return false; + } + + //if (!processor.execute(lValue, ResolveState.initial())) return false; } } return true; } + private GrVariable getOrCreateLocalVar() { + GrExpression lValue = getLValue(); + CachedValue local = lValue.getUserData(LOCAL_VAR_KEY); + if (local == null) { + local = CachedValuesManager.getManager(getProject()).createCachedValue(new CachedValueProvider() { + @Nullable + @Override + public Result compute() { + return Result.create(new GrLightLocalVariable(GrAssignmentExpressionImpl.this), PsiModificationTracker.MODIFICATION_COUNT); + } + }); + lValue.putUserData(LOCAL_VAR_KEY, local); + } + return local.getValue(); + } + private static boolean isDeclarationAssignment(@NotNull GrReferenceExpression lRefExpr, @Nullable String nameHint) { if (nameHint == null || nameHint.equals(lRefExpr.getName())) { final PsiElement target = lRefExpr.resolve(); //this is NOT quadratic since the next statement will prevent from further processing declarations upstream - if (!(target instanceof PsiVariable) && !(target instanceof GrAccessorMethod)) { + if (!(target instanceof PsiVariable || target instanceof GrAccessorMethod)) { return true; } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java index aab274df0977..0bde09c323aa 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java @@ -57,10 +57,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrM import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeArgumentList; import org.jetbrains.plugins.groovy.lang.psi.dataFlow.types.TypeInferenceHelper; -import org.jetbrains.plugins.groovy.lang.psi.impl.GrClosureType; -import org.jetbrains.plugins.groovy.lang.psi.impl.GrReferenceElementImpl; -import org.jetbrains.plugins.groovy.lang.psi.impl.InferenceContext; -import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil; +import org.jetbrains.plugins.groovy.lang.psi.impl.*; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.literals.GrLiteralImpl; import org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.GrReferenceTypeEnhancer; import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames; @@ -69,6 +66,7 @@ import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import org.jetbrains.plugins.groovy.lang.resolve.ClosureMissingMethodContributor; import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil; import org.jetbrains.plugins.groovy.lang.resolve.processors.*; +import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil; import java.util.ArrayList; import java.util.Arrays; @@ -157,13 +155,6 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl 0) return classCandidates; - } - ResolverProcessor processor = new PropertyResolverProcessor(name, this); GrReferenceResolveUtil.resolveImpl(processor, this); final GroovyResolveResult[] fieldCandidates = processor.getCandidates(); @@ -172,6 +163,16 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl 0) return classCandidates; + } + } + //if reference expression is in class we need to return field instead of accessor method for (GroovyResolveResult candidate : fieldCandidates) { final PsiElement element = candidate.getElement(); @@ -212,6 +213,20 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl 0) { + for (GroovyResolveResult candidate : fieldCandidates) { + PsiElement element = candidate.getElement(); + if (GroovyRefactoringUtil.isLocalVariable(element)) { + preferVar = true; + break; + } + } + } + return preferVar; + } + public GroovyResolveResult[] getCallVariants(GrExpression upToArgument) { return resolveMethodOrProperty(true, upToArgument, true); @@ -632,7 +647,7 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl T addMemberDeclaration(T decl, PsiElement anchorBefore) throws IncorrectOperationException { - return myFile.addMemberDeclaration(decl, anchorBefore); - } } 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 fffe0454ddb5..722c36d2c691 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 @@ -69,7 +69,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrI import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousClassDefinition; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrMemberOwner; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.*; import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement; @@ -1319,17 +1318,6 @@ public class PsiUtil { return getArgumentsList(context) != null; } - @Nullable - public static GrMemberOwner getMemberOwner(GrStatement statement) { - PsiElement parent = statement.getParent(); - while (!(parent instanceof GrMemberOwner)) { - if (parent == null) return null; - if (parent instanceof GroovyFileBase) return (GrMemberOwner) ((GroovyFileBase) parent).getScriptClass(); - parent = parent.getParent(); - } - return ((GrMemberOwner) parent); - } - @NotNull public static List getValidImportStatements(final GroovyFile file) { final List oldImports = new ArrayList(); 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 62867dbd5aa1..7293bfb8cb35 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 @@ -761,4 +761,17 @@ public class ResolveUtil { if (element instanceof PsiClass && ((PsiClass)element).isAnnotationType()) return (PsiClass)element; return null; } + + @NotNull + public static String inferExpectedPackageName(PsiElement place) { + PsiFile file = place.getContainingFile(); + PsiDirectory psiDirectory = file.getContainingDirectory(); + if (psiDirectory != null && file instanceof GroovyFile) { + PsiPackage aPackage = JavaDirectoryService.getInstance().getPackage(psiDirectory); + if (aPackage != null) { + return aPackage.getQualifiedName(); + } + } + return ""; + } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/PropertyResolverProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/PropertyResolverProcessor.java index 8fc7d4b9c805..93571229a258 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/PropertyResolverProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/PropertyResolverProcessor.java @@ -22,7 +22,6 @@ import com.intellij.psi.PsiType; import com.intellij.psi.ResolveState; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; import java.util.List; @@ -37,9 +36,6 @@ public class PropertyResolverProcessor extends ResolverProcessor { @Override public boolean execute(@NotNull PsiElement element, ResolveState state) { - if (element instanceof GrReferenceExpression && ((GrReferenceExpression)element).getQualifier() != null) { - return true; - } return super.execute(element, state) || state.get(RESOLVE_CONTEXT) != null; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcModuleStructureUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcModuleStructureUtil.java index 452e974f69b8..b7851b9307a7 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcModuleStructureUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcModuleStructureUtil.java @@ -411,7 +411,13 @@ public class MvcModuleStructureUtil { } public static boolean hasModulesWithSupport(Project project, final MvcFramework framework) { - return !getAllModulesWithSupport(project, framework).isEmpty(); + for (Module module : ModuleManager.getInstance(project).getModules()) { + if (framework.hasSupport(module)) { + return true; + } + } + + return false; } public static List getAllModulesWithSupport(Project project, MvcFramework framework) { 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 d7c0bb1000e7..d57431951943 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 @@ -99,8 +99,8 @@ public class GrChangeInfoImpl implements JavaChangeInfo { GrParameter[] params = method.getParameters(); final int oldParameterCount = this.method.getParameters().length; - myOldParameterNames=new String[oldParameterCount]; - myOldParameterTypes=new String[oldParameterCount]; + myOldParameterNames = new String[oldParameterCount]; + myOldParameterTypes = new String[oldParameterCount]; for (int i = 0; i < oldParameterCount; i++) { GrParameter param = params[i]; @@ -156,7 +156,8 @@ public class GrChangeInfoImpl implements JavaChangeInfo { if (myIsNameChanged) { if (StringUtil.isJavaIdentifier(newName)) { myNewNameIdentifier = JavaPsiFacade.getElementFactory(getMethod().getProject()).createIdentifier(newName); - } else { + } + else { myNewNameIdentifier = getMethod().getNameIdentifier(); } } 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 deleted file mode 100644 index f97eb7d54a7d..000000000000 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureDialog.form +++ /dev/null @@ -1,153 +0,0 @@ - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 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 80bfeeca7d46..afcade4a57ed 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 @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 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,333 +15,170 @@ */ package org.jetbrains.plugins.groovy.refactoring.changeSignature; -import com.intellij.openapi.editor.Document; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.event.DocumentAdapter; import com.intellij.openapi.editor.event.DocumentEvent; -import com.intellij.openapi.editor.event.DocumentListener; +import com.intellij.openapi.fileTypes.LanguageFileType; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; -import com.intellij.refactoring.HelpID; -import com.intellij.refactoring.changeSignature.ChangeSignatureHandler; +import com.intellij.refactoring.BaseRefactoringProcessor; +import com.intellij.refactoring.RefactoringBundle; +import com.intellij.refactoring.changeSignature.CallerChooserBase; +import com.intellij.refactoring.changeSignature.ChangeSignatureDialogBase; import com.intellij.refactoring.changeSignature.ExceptionsTableModel; import com.intellij.refactoring.changeSignature.ThrownExceptionInfo; import com.intellij.refactoring.ui.CodeFragmentTableCellRenderer; import com.intellij.refactoring.ui.JavaCodeFragmentTableCellEditor; -import com.intellij.refactoring.ui.MethodSignatureComponent; -import com.intellij.refactoring.ui.RefactoringDialog; +import com.intellij.refactoring.ui.VisibilityPanelBase; import com.intellij.refactoring.util.CanonicalTypes; -import com.intellij.refactoring.util.CommonRefactoringUtil; -import com.intellij.ui.*; +import com.intellij.ui.IdeBorderFactory; +import com.intellij.ui.ToolbarDecorator; import com.intellij.ui.table.JBTable; +import com.intellij.ui.treeStructure.Tree; +import com.intellij.util.Consumer; import com.intellij.util.Function; -import com.intellij.util.VisibilityUtil; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; 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; -import org.jetbrains.plugins.groovy.refactoring.ui.GrCodeFragmentTableCellEditor; -import org.jetbrains.plugins.groovy.refactoring.ui.GrMethodSignatureComponent; import org.jetbrains.plugins.groovy.refactoring.ui.GroovyComboboxVisibilityPanel; import javax.swing.*; -import javax.swing.border.EmptyBorder; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import javax.swing.event.TableModelEvent; -import javax.swing.event.TableModelListener; -import javax.swing.table.TableColumnModel; -import java.awt.*; +import java.util.ArrayList; import java.util.List; +import java.util.Set; import static org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle.message; /** - * @author Maxim.Medvedev + * @author Max Medvedev */ -public class GrChangeSignatureDialog extends RefactoringDialog { - private EditorTextField myNameField; - private EditorTextField myReturnTypeField; - private JBTable myParameterTable; - private JPanel contentPane; - private JLabel myNameLabel; - private JLabel myReturnTypeLabel; - private JRadioButton myDelegateRadioButton; - private JPanel myDelegatePanel; - private GroovyComboboxVisibilityPanel myVisibilityPanel; - private MethodSignatureComponent mySignaturePreview; - private JComponent myTabPanel; - private GrParameterTableModel myParameterModel; - private GrMethod myMethod; - private PsiTypeCodeFragment myReturnTypeCodeFragment; - private ExceptionsTableModel myExceptionTableModel; +public class GrChangeSignatureDialog extends ChangeSignatureDialogBase { + private static final Logger LOG = Logger.getInstance(GrChangeSignatureDialog.class); + private static final String INDENT = " "; - public GrChangeSignatureDialog(@NotNull Project project, GrMethod method) { - super(project, true); - myMethod = method; + private ExceptionsTableModel myExceptionsModel; - init(); - updateSignature(); - } - - protected void init() { - super.init(); - - setTitle(ChangeSignatureHandler.REFACTORING_NAME); - - final PsiClass psiClass = myMethod.getContainingClass(); - if (psiClass == null) return; - if (psiClass.isInterface()) { - myDelegatePanel.setVisible(false); - } - - myVisibilityPanel.setVisibility(VisibilityUtil.getVisibilityModifier(myMethod.getModifierList())); - - myVisibilityPanel.addListener(new ChangeListener() { - @Override - public void stateChanged(ChangeEvent e) { - updateSignature(); - } - }); + public GrChangeSignatureDialog(Project project, + GrMethodDescriptor method, + boolean allowDelegation, + PsiElement defaultValueContext) { + super(project, method, allowDelegation, defaultValueContext); } @Override - protected JComponent createCenterPanel() { - return contentPane; + protected LanguageFileType getFileType() { + return GroovyFileType.GROOVY_FILE_TYPE; } - - private void createUIComponents() { - createNameAndReturnTypeEditors(); - createSignaturePreview(); - - JPanel paramPanel = createParametersPanel(); - paramPanel.setBorder(new EmptyBorder(0, 0, 0, 0)); - JPanel exceptionPanel = createExceptionsPanel(); - exceptionPanel.setBorder(new EmptyBorder(0, 0, 0, 0)); - - final TabbedPaneWrapper tabbedPane = new TabbedPaneWrapper(getDisposable()); - tabbedPane.addTab("Parameters", paramPanel); - tabbedPane.addTab("Exceptions", exceptionPanel); - - myTabPanel = tabbedPane.getComponent(); - - for (JComponent c : UIUtil.findComponentsOfType(myTabPanel, JComponent.class)) { - c.setFocusCycleRoot(false); - c.setFocusTraversalPolicy(null); - } + @Override + protected GrParameterTableModel createParametersInfoModel(GrMethodDescriptor method) { + final PsiParameterList parameterList = method.getMethod().getParameterList(); + return new GrParameterTableModel(parameterList, myDefaultValueContext, this); } - private void createSignaturePreview() { - mySignaturePreview = new GrMethodSignatureComponent("", myProject); + @Override + protected BaseRefactoringProcessor createRefactoringProcessor() { + final CanonicalTypes.Type type = getReturnType(); + final ThrownExceptionInfo[] exceptionInfos = myExceptionsModel.getThrownExceptions(); + final GrChangeInfoImpl info = new GrChangeInfoImpl(myMethod.getMethod(), getVisibility(), type, getMethodName(), getParameters(), exceptionInfos, isGenerateDelegate()); + return new GrChangeSignatureProcessor(myProject, info); } - private void createNameAndReturnTypeEditors() { - myNameField = new EditorTextField("", myProject,GroovyFileType.GROOVY_FILE_TYPE); + @NotNull + @Override + protected List> createAdditionalPanels() { + // this method is invoked before constructor body + myExceptionsModel = new ExceptionsTableModel(myMethod.getMethod().getThrowsList()); + myExceptionsModel.setTypeInfos(myMethod.getMethod()); - final JavaCodeFragmentFactory factory = JavaCodeFragmentFactory.getInstance(myProject); - myReturnTypeCodeFragment = factory.createTypeCodeFragment("", myMethod, true, JavaCodeFragmentFactory.ALLOW_VOID); - 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()); - } - - myReturnTypeLabel = new JLabel(); - myReturnTypeLabel.setLabelFor(myReturnTypeField); - - myNameLabel = new JLabel(); - myNameLabel.setLabelFor(myNameField); - - final DocumentListener listener = new DocumentListener() { + final JBTable table = new JBTable(myExceptionsModel); + table.setStriped(true); + table.setRowHeight(20); + table.getColumnModel().getColumn(0).setCellRenderer(new CodeFragmentTableCellRenderer(myProject)); + final JavaCodeFragmentTableCellEditor cellEditor = new JavaCodeFragmentTableCellEditor(myProject); + cellEditor.addDocumentListener(new DocumentAdapter() { @Override - public void beforeDocumentChange(DocumentEvent event) { - } - - @Override - public void documentChanged(DocumentEvent event) { + public void documentChanged(DocumentEvent e) { + final int row = table.getSelectedRow(); + final int col = table.getSelectedColumn(); + myExceptionsModel.setValueAt(cellEditor.getCellEditorValue(), row, col); updateSignature(); } + }); + table.getColumnModel().getColumn(0).setCellEditor(cellEditor); + table.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + table.getSelectionModel().setSelectionInterval(0, 0); + table.setSurrendersFocusOnKeystroke(true); + + /* myPropExceptionsButton = new AnActionButton( //todo propagate parameters + RefactoringBundle.message("changeSignature.propagate.exceptions.title"), null, PlatformIcons.NEW_EXCEPTION) { + @Override + public void actionPerformed(AnActionEvent e) { + final Ref chooser = new Ref(); + Consumer> callback = new Consumer>() { + @Override + public void consume(Set psiMethods) { + myMethodsToPropagateExceptions = psiMethods; + myExceptionPropagationTree = chooser.get().getTree(); + } + }; + chooser.set(new JavaCallerChooser(myMethod.getMethod(), + myProject, + RefactoringBundle.message("changeSignature.exception.caller.chooser"), + myExceptionPropagationTree, + callback)); + chooser.get().show(); + } }; - myReturnTypeField.addDocumentListener(listener); - myNameField.addDocumentListener(listener); + myPropExceptionsButton.setShortcut(CustomShortcutSet.fromString("alt X"));*/ + + final JPanel panel = ToolbarDecorator.createDecorator(table).createPanel(); + //.addExtraAction(myPropExceptionsButton).createPanel(); + panel.setBorder(IdeBorderFactory.createEmptyBorder(0)); + + myExceptionsModel.addTableModelListener(mySignatureUpdater); + + final ArrayList> result = new ArrayList>(); + final String message = RefactoringBundle.message("changeSignature.exceptions.panel.border.title"); + result.add(Pair.create(message, panel)); + return result; + } - private JPanel createParametersPanel() { - myParameterModel = createParameterTableModel(); - myParameterModel.addTableModelListener(new TableModelListener() { - public void tableChanged(TableModelEvent e) { - updateSignature(); - } - }); - myParameterTable = new JBTable(myParameterModel); - myParameterTable.setPreferredScrollableViewportSize(new Dimension(550, myParameterTable.getRowHeight() * 8)); - - myParameterTable.setCellSelectionEnabled(true); - final TableColumnModel columnModel = myParameterTable.getColumnModel(); - - columnModel.getColumn(0).setCellRenderer(new CodeFragmentTableCellRenderer(myProject)); - columnModel.getColumn(1).setCellRenderer(new CodeFragmentTableCellRenderer(myProject, GroovyFileType.GROOVY_FILE_TYPE)); - columnModel.getColumn(2).setCellRenderer(new CodeFragmentTableCellRenderer(myProject, GroovyFileType.GROOVY_FILE_TYPE)); - columnModel.getColumn(3).setCellRenderer(new CodeFragmentTableCellRenderer(myProject, GroovyFileType.GROOVY_FILE_TYPE)); - columnModel.getColumn(4).setCellRenderer(new BooleanTableCellRenderer()); - - columnModel.getColumn(0).setCellEditor(new JavaCodeFragmentTableCellEditor(myProject)); - columnModel.getColumn(1).setCellEditor(new GrCodeFragmentTableCellEditor(myProject)); - columnModel.getColumn(2).setCellEditor(new GrCodeFragmentTableCellEditor(myProject)); - columnModel.getColumn(3).setCellEditor(new GrCodeFragmentTableCellEditor(myProject)); - columnModel.getColumn(4).setCellEditor(new BooleanTableCellEditor(false)); - - if (myParameterModel.getRowCount() > 0) { - myParameterTable.setRowSelectionInterval(0, 0); - myParameterTable.setColumnSelectionInterval(0, 0); - } - - return ToolbarDecorator.createDecorator(myParameterTable).createPanel(); - } - - protected GrParameterTableModel createParameterTableModel() { - return new GrParameterTableModel(myMethod, myProject); - } - - private JPanel createExceptionsPanel() { - myExceptionTableModel = new ExceptionsTableModel(myMethod); - myExceptionTableModel.setTypeInfos(myMethod); - myExceptionTableModel.addTableModelListener(new TableModelListener() { - public void tableChanged(TableModelEvent e) { - updateSignature(); - } - }); - JBTable exceptionTable = new JBTable(myExceptionTableModel); - exceptionTable.setPreferredScrollableViewportSize(new Dimension(200, exceptionTable.getRowHeight() * 8)); - - exceptionTable.getColumnModel().getColumn(0).setCellRenderer(new CodeFragmentTableCellRenderer(myProject)); - exceptionTable.getColumnModel().getColumn(0).setCellEditor(new JavaCodeFragmentTableCellEditor(myProject)); - - if (myExceptionTableModel.getRowCount() > 0) { - exceptionTable.setRowSelectionInterval(0, 0); - exceptionTable.setColumnSelectionInterval(0, 0); - } - - myExceptionTableModel.addTableModelListener(new TableModelListener() { - @Override - public void tableChanged(TableModelEvent e) { - updateSignature(); - } - }); - - return ToolbarDecorator.createDecorator(exceptionTable).createPanel(); - } - - - private void updateSignature() { - mySignaturePreview.setSignature(generateSignatureText()); - } - - private String generateSignatureText() { - String name = getNewName(); - String type = myReturnTypeField.getText().trim(); - - StringBuilder builder = new StringBuilder(); - builder.append(myVisibilityPanel.getVisibility()).append(' '); - if (!type.isEmpty()) { - builder.append(type).append(' '); - } - builder.append(name).append('('); - - final List infos = myParameterModel.getParameterInfos(); - if (infos.size() > 0) { - final List paramsText = ContainerUtil.map(infos, new Function() { - public String fun(GrTableParameterInfo 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 String generateParameterText(GrTableParameterInfo 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; - builder.append(typeText).append(' '); - final GroovyCodeFragment nameFragment = info.getNameFragment(); - builder.append(nameFragment != null ? nameFragment.getText().trim() : ""); - final GroovyCodeFragment defaultInitializer = info.getDefaultInitializerFragment(); - - final String defaultInitializerText = defaultInitializer != null ? defaultInitializer.getText().trim() : ""; - if (defaultInitializerText.length() > 0) { - builder.append(" = ").append(defaultInitializerText); - } - return builder.toString(); - } - - @Override - protected void doAction() { - if (!validateInputData()) { - return; - } - - TableUtil.stopEditing(myParameterTable); - String modifier = myVisibilityPanel.getVisibility(); - + @Nullable + private CanonicalTypes.Type getReturnType() { PsiType returnType = null; try { - returnType = myReturnTypeCodeFragment.getType(); + returnType = ((PsiTypeCodeFragment)myReturnTypeCodeFragment).getType(); } catch (PsiTypeCodeFragment.TypeSyntaxException ignored) { } catch (PsiTypeCodeFragment.NoTypeException ignored) { } - String newName = getNewName(); - 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(); - final CanonicalTypes.Type type = returnType == null ? null : CanonicalTypes.createTypeWrapper(returnType); - final GrChangeInfoImpl info = - new GrChangeInfoImpl(myMethod, modifier, type, newName, parameterInfos, exceptionInfos, myDelegateRadioButton.isSelected()); - invokeRefactoring(new GrChangeSignatureProcessor(myProject, info)); + return returnType == null ? null : CanonicalTypes.createTypeWrapper(returnType); } - private String getNewName() { - return myNameField.getText().trim(); + @Override + protected PsiCodeFragment createReturnTypeCodeFragment() { + final JavaCodeFragmentFactory factory = JavaCodeFragmentFactory.getInstance(myProject); + return factory.createTypeCodeFragment(myMethod.getReturnTypeText(), myMethod.getMethod(), true, JavaCodeFragmentFactory.ALLOW_VOID); } - private void showErrorHint(String hint) { - CommonRefactoringUtil.showErrorHint(myProject, null, hint, message("incorrect.data"), HelpID.CHANGE_SIGNATURE); + @Nullable + @Override + protected CallerChooserBase createCallerChooser(String title, Tree treeToReuse, Consumer> callback) { + return null; //todo next iteration } + private boolean isGroovyMethodName(String name) { String methodText = "def " + name + "(){}"; try { @@ -353,69 +190,6 @@ public class GrChangeSignatureDialog extends RefactoringDialog { } } - private boolean validateInputData() { - if (!isGroovyMethodName(getNewName())) { - showErrorHint(message("name.is.wrong", getNewName())); - return false; - } - - if (!checkType(myReturnTypeCodeFragment, true)) { - showErrorHint(message("return.type.is.wrong")); - return false; - } - - List parameterInfos = myParameterModel.getParameterInfos(); - for (int i = 0; i < parameterInfos.size(); i++) { - GrTableParameterInfo info = parameterInfos.get(i); - if (!StringUtil.isJavaIdentifier(info.getName())) { - showErrorHint(message("name.is.wrong", info.getName())); - return false; - } - if (!checkType(info.getTypeFragment(), i == parameterInfos.size() - 1)) { - showErrorHint(message("type.for.parameter.is.incorrect", info.getName())); - return false; - } - String defaultValue = info.getDefaultValue(); - final String initializer = info.getDefaultInitializerFragment().getText(); - if (info.getOldIndex() < 0 && defaultValue.trim().length() == 0 && initializer.trim().length() == 0) { - 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(message("changeSignature.wrong.type.for.exception", typeCodeFragment.getText())); - return false; - } - - PsiClassType throwable = JavaPsiFacade.getInstance(myMethod.getProject()).getElementFactory() - .createTypeByFQClassName("java.lang.Throwable", myMethod.getResolveScope()); - if (!throwable.isAssignableFrom(type)) { - showErrorHint(message("changeSignature.not.throwable.type", typeCodeFragment.getText())); - return false; - } - exceptionInfo.setType((PsiClassType)type); - } - catch (PsiTypeCodeFragment.TypeSyntaxException e) { - showErrorHint(message("changeSignature.wrong.type.for.exception", typeCodeFragment.getText())); - return false; - } - catch (PsiTypeCodeFragment.NoTypeException e) { - showErrorHint(message("changeSignature.no.type.for.exception")); - return false; - } - } - - return true; - } - private static boolean checkType(PsiTypeCodeFragment typeCodeFragment, boolean allowEllipsis) { try { final PsiType type = typeCodeFragment.getType(); @@ -428,4 +202,137 @@ public class GrChangeSignatureDialog extends RefactoringDialog { return true; //Groovy accepts methods and parameters without explicit type } } + + + @Nullable + @Override + protected String validateAndCommitData() { + if (!isGroovyMethodName(getMethodName())) { + return message("name.is.wrong", getMethodName()); + } + + if (!checkType((PsiTypeCodeFragment)myReturnTypeCodeFragment, true)) { + return message("return.type.is.wrong"); + } + + List parameterInfos = myParametersTableModel.getItems(); + int newParameterCount = parameterInfos.size(); + for (int i = 0; i < newParameterCount; i++) { + GrParameterTableModelItem item = parameterInfos.get(i); + + String name = item.parameter.getName(); + if (!StringUtil.isJavaIdentifier(name)) { + return message("name.is.wrong", name); + } + + if (!checkType((PsiTypeCodeFragment)item.typeCodeFragment, i == newParameterCount - 1)) { + return message("type.for.parameter.is.incorrect", name); + } + try { + item.parameter.setType(((PsiTypeCodeFragment)item.typeCodeFragment).getType()); + } + catch (PsiTypeCodeFragment.TypeSyntaxException e) { + LOG.error(e); + } + catch (PsiTypeCodeFragment.NoTypeException e) { + item.parameter.setType(null); + } + + String defaultValue = item.defaultValueCodeFragment.getText(); + final String initializer = item.initializerCodeFragment.getText(); + if (item.parameter.getOldIndex() < 0 && defaultValue.trim().length() == 0 && initializer.trim().length() == 0) { + return message("specify.default.value", name); + } + + item.parameter.setInitializer(initializer); + } + + ThrownExceptionInfo[] exceptionInfos = myExceptionsModel.getThrownExceptions(); + PsiTypeCodeFragment[] typeCodeFragments = myExceptionsModel.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)) { + return message("changeSignature.wrong.type.for.exception", typeCodeFragment.getText()); + } + + PsiElementFactory factory = JavaPsiFacade.getInstance(getProject()).getElementFactory(); + PsiClassType throwable = factory.createTypeByFQClassName("java.lang.Throwable", myMethod.getMethod().getResolveScope()); + if (!throwable.isAssignableFrom(type)) { + return message("changeSignature.not.throwable.type", typeCodeFragment.getText()); + } + exceptionInfo.setType((PsiClassType)type); + } + catch (PsiTypeCodeFragment.TypeSyntaxException e) { + return message("changeSignature.wrong.type.for.exception", typeCodeFragment.getText()); + } + catch (PsiTypeCodeFragment.NoTypeException e) { + return message("changeSignature.no.type.for.exception"); + } + } + + return null; + } + + + private static String generateParameterText(GrParameterInfo info) { + StringBuilder builder = new StringBuilder(); + String typeText = info.getTypeText(); + if (typeText.length() == 0) typeText = GrModifier.DEF; + builder.append(typeText).append(' '); + builder.append(info.getName()); + + String initializer = info.getDefaultInitializer(); + if (!StringUtil.isEmpty(initializer)) { + builder.append(" = ").append(initializer); + } + return builder.toString(); + } + + + @Override + protected String calculateSignature() { + String name = getMethodName(); + String type = myReturnTypeCodeFragment.getText().trim(); + + StringBuilder builder = new StringBuilder(); + builder.append(myVisibilityPanel.getVisibility()).append(' '); + if (!type.isEmpty()) { + builder.append(type).append(' '); + } + builder.append(name).append('('); + + final List infos = getParameters(); + if (infos.size() > 0) { + final List paramsText = ContainerUtil.map(infos, new Function() { + public String fun(GrParameterInfo info) { + return generateParameterText(info); + } + }); + builder.append("\n").append(INDENT); + builder.append(StringUtil.join(paramsText, ",\n" + INDENT)); + builder.append('\n'); + } + builder.append(')'); + + final PsiTypeCodeFragment[] exceptions = myExceptionsModel.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(); + } + + @Override + protected VisibilityPanelBase createVisibilityControl() { + return new GroovyComboboxVisibilityPanel(); + } } 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 56ce5cf264cd..2353e68ebba3 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 @@ -86,7 +86,7 @@ public class GrChangeSignatureHandler implements ChangeSignatureHandler { if (!CommonRefactoringUtil.checkReadOnlyStatus(project, method)) return; if (!(method instanceof GrMethod)) return; //todo - final GrChangeSignatureDialog dialog = new GrChangeSignatureDialog(project, (GrMethod)method); + final GrChangeSignatureDialog dialog = new GrChangeSignatureDialog(project, new GrMethodDescriptor((GrMethod)method), true, null); dialog.show(); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodDescriptor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodDescriptor.java new file mode 100644 index 000000000000..74ece699810c --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodDescriptor.java @@ -0,0 +1,98 @@ +/* + * Copyright 2000-2012 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.refactoring.changeSignature.MethodDescriptor; +import com.intellij.util.VisibilityUtil; +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; +import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Max Medvedev + */ +public class GrMethodDescriptor implements MethodDescriptor { + private final GrMethod myMethod; + + public GrMethodDescriptor(GrMethod method) { + myMethod = method; + } + + @Override + public String getName() { + return myMethod.getName(); + } + + @Override + public List getParameters() { + final ArrayList result = new ArrayList(); + final GrParameter[] parameters = myMethod.getParameters(); + for (int i = 0; i < parameters.length; i++) { + GrParameter parameter = parameters[i]; + GrExpression initializer = parameter.getDefaultInitializer(); + String initializerText = initializer != null ? initializer.getText() : null; + GrParameterInfo info = new GrParameterInfo(parameter.getName(), "", initializerText, parameter.getType(), i, false); + result.add(info); + } + return result; + } + + @Override + public int getParametersCount() { + return myMethod.getParameterList().getParametersCount(); + } + + @Override + public String getVisibility() { + return VisibilityUtil.getVisibilityModifier(myMethod.getModifierList()); + } + + @Override + public GrMethod getMethod() { + return myMethod; + } + + @Override + public boolean canChangeVisibility() { + PsiClass containingClass = myMethod.getContainingClass(); + return containingClass != null && !containingClass.isInterface(); + } + + @Override + public boolean canChangeParameters() { + return true; + } + + @Override + public boolean canChangeName() { + return !myMethod.isConstructor(); + } + + @Override + public ReadWriteOption canChangeReturnType() { + return myMethod.isConstructor() ? ReadWriteOption.None : ReadWriteOption.ReadWrite; + } + + public String getReturnTypeText() { + GrTypeElement returnTypeElement = myMethod.getReturnTypeElementGroovy(); + return returnTypeElement != null ? returnTypeElement.getText() : ""; + } +} 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 f7e2026cee6f..efcfc9852f05 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 @@ -30,10 +30,10 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; public class GrParameterInfo implements JavaParameterInfo { private String myName; private final String myDefaultValue; - private final String myDefaultInitializer; + private String myDefaultInitializer; private final int myPosition; private CanonicalTypes.Type myTypeWrapper; - private final boolean myUseAnySingleVariable; + private boolean myUseAnySingleVariable; public GrParameterInfo(GrParameter parameter, int position) { myPosition = position; @@ -67,12 +67,7 @@ public class GrParameterInfo implements JavaParameterInfo { myDefaultInitializer = defaultInitializer; myPosition = position; myUseAnySingleVariable = useAnySingleVariable; - if (type != null) { - myTypeWrapper = CanonicalTypes.createTypeWrapper(type); - } - else { - myTypeWrapper = null; - } + setType(type); } public String getName() { @@ -94,6 +89,7 @@ public class GrParameterInfo implements JavaParameterInfo { return myTypeWrapper.getType(context, manager); } + @NotNull public String getTypeText() { if (myTypeWrapper != null) { return myTypeWrapper.getTypeText(); @@ -119,8 +115,8 @@ public class GrParameterInfo implements JavaParameterInfo { } @Override - public void setUseAnySingleVariable(boolean b) { - throw new UnsupportedOperationException(); + public void setUseAnySingleVariable(boolean useAnyVar) { + myUseAnySingleVariable = useAnyVar; } public boolean isOptional() { @@ -145,4 +141,12 @@ public class GrParameterInfo implements JavaParameterInfo { public void setName(String newName) { myName = newName; } + + public void setType(@Nullable PsiType type) { + myTypeWrapper = type == null ? null : CanonicalTypes.createTypeWrapper(type); + } + + public void setInitializer(String initializer) { + myDefaultInitializer = initializer; + } } 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 ffbba118b5a6..61d6c99f5ec5 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 @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -17,144 +17,91 @@ package org.jetbrains.plugins.groovy.refactoring.changeSignature; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiCodeFragment; -import com.intellij.util.ui.EditableModel; +import com.intellij.psi.PsiElement; +import com.intellij.refactoring.changeSignature.ParameterTableModelBase; +import com.intellij.refactoring.ui.JavaCodeFragmentTableCellEditor; +import com.intellij.util.ui.ColumnInfo; 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; +import org.jetbrains.plugins.groovy.GroovyFileType; +import org.jetbrains.plugins.groovy.refactoring.ui.GrCodeFragmentTableCellEditor; -import javax.swing.table.AbstractTableModel; -import java.util.ArrayList; -import java.util.List; +import javax.swing.table.TableCellEditor; /** - * @author Maxim.Medvedev + * @author Max Medvedev */ -public class GrParameterTableModel extends AbstractTableModel implements EditableModel { - private static final int COLUMN_COUNT = 5; - - private final List infos; - private final GrMethod myMethod; - private final Project myProject; - - public GrParameterTableModel(GrMethod method, Project project) { - myMethod = method; - 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 GrTableParameterInfo(parameter, i)); - } - myProject = project; +public class GrParameterTableModel extends ParameterTableModelBase{ + public GrParameterTableModel(final PsiElement typeContext, PsiElement defaultValueContext, final GrChangeSignatureDialog dialog) { + this(typeContext, defaultValueContext, + new GrTypeColumn(typeContext.getProject()), + new NameColumn(typeContext.getProject(), "Name"), + new GrInitializerColumn(typeContext.getProject()), + new GrDefaultValueColumn(typeContext.getProject()), + new AnyVarColumn() { + @Override + public boolean isCellEditable(GrParameterTableModelItem item) { + boolean isGenerateDelegate = dialog.isGenerateDelegate(); + return !isGenerateDelegate && super.isCellEditable(item); + } + }); } - public void addRow() { - addRow(new GrTableParameterInfo(myProject, myMethod)); + private GrParameterTableModel(PsiElement typeContext, PsiElement defaultValueContext, ColumnInfo... columnInfos) { + super(typeContext, defaultValueContext, columnInfos); } - public void addRow(GrTableParameterInfo info) { - final int row = infos.size(); - infos.add(info); - fireTableRowsInserted(row, row); - } - - public void removeRow(int index) { - infos.remove(index); - fireTableRowsDeleted(index, index); - } - - public void exchangeRows(int index1, int index2) { - 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)); - } @Override - public boolean canExchangeRows(int oldIndex, int newIndex) { - return true; + protected GrParameterTableModelItem createRowItem(@Nullable GrParameterInfo parameterInfo) { + return GrParameterTableModelItem.create(parameterInfo, myTypeContext.getProject(), myDefaultValueContext); } - public int getRowCount() { - return infos.size(); - } + private static class GrTypeColumn extends TypeColumn { - public int getColumnCount() { - return COLUMN_COUNT; - } + public GrTypeColumn(Project project) { + super(project, GroovyFileType.GROOVY_FILE_TYPE, "Type"); + } - @Nullable - public Object getValueAt(int rowIndex, int columnIndex) { - if (rowIndex < 0 || rowIndex >= infos.size()) return null; - final GrTableParameterInfo info = infos.get(rowIndex); - switch (columnIndex) { - case 0: - return info.getTypeFragment(); - case 1: - return info.getNameFragment(); - case 2: - return info.getDefaultInitializerFragment(); - case 3: - return info.getDefaultValueFragment(); - case 4: - return info.isUseAnyVar(); - default: - throw new IllegalArgumentException(); + @Override + public TableCellEditor doCreateEditor(GrParameterTableModelItem o) { + return new JavaCodeFragmentTableCellEditor(myProject); } } - @Override - public void setValueAt(Object value, int rowIndex, int columnIndex) { - if (rowIndex < 0 || rowIndex >= infos.size()) return; - if (columnIndex < 0 || columnIndex >= COLUMN_COUNT) return; - if (columnIndex==4) infos.get(rowIndex).setUseAnyVar(((Boolean)value).booleanValue()); - fireTableCellUpdated(rowIndex, columnIndex); - } + private static class GrDefaultValueColumn extends DefaultValueColumn { + private final Project myProject; + public GrDefaultValueColumn(Project project) { + super(project, GroovyFileType.GROOVY_FILE_TYPE); + myProject = project; + } - @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"); - case 4: - return GroovyRefactoringBundle.message("column.name.use.any.var"); - default: - throw new IllegalArgumentException(); + @Override + public TableCellEditor doCreateEditor(GrParameterTableModelItem item) { + return new GrCodeFragmentTableCellEditor(myProject); } } - @Override - public Class getColumnClass(int columnIndex) { - switch (columnIndex) { - case 0: - return PsiCodeFragment.class; - case 1: - case 2: - case 3: - return GroovyCodeFragment.class; - case 4: - return Boolean.class; - default: - throw new IllegalArgumentException(); + private static class GrInitializerColumn extends GrDefaultValueColumn { + public GrInitializerColumn(Project project) { + super(project); + } + + @Override + public String getName() { + return "Default initializer"; + } + + @Override + public boolean isCellEditable(GrParameterTableModelItem item) { + return true; + } + + @Override + public PsiCodeFragment valueOf(GrParameterTableModelItem item) { + return item.initializerCodeFragment; } - } - @Override - public boolean isCellEditable(int rowIndex, int columnIndex) { - if (columnIndex < 3) return true; - GrTableParameterInfo info = infos.get(rowIndex); - return info.getOldIndex() < 0; - } - public List getParameterInfos() { - return infos; } -} \ No newline at end of file +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterTableModelItem.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterTableModelItem.java new file mode 100644 index 000000000000..acc785c9ee85 --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrParameterTableModelItem.java @@ -0,0 +1,67 @@ +/* + * Copyright 2000-2012 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.*; +import com.intellij.refactoring.changeSignature.ParameterTableModelItemBase; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.debugger.fragments.GroovyCodeFragment; + +/** +* @author Max Medvedev +*/ +public class GrParameterTableModelItem extends ParameterTableModelItemBase { + public PsiCodeFragment initializerCodeFragment; + + public GrParameterTableModelItem(GrParameterInfo parameter, + PsiCodeFragment typeCodeFragment, + PsiCodeFragment initializerCodeFragment, + PsiCodeFragment defaultValueCodeFragment) { + super(parameter, typeCodeFragment, defaultValueCodeFragment); + this.initializerCodeFragment = initializerCodeFragment; + } + + public static GrParameterTableModelItem create(@Nullable GrParameterInfo parameterInfo, + @NotNull final Project project, + @Nullable final PsiElement context) { + if (parameterInfo == null) { + parameterInfo = new GrParameterInfo("", "", "", null, -1, false); + } + + PsiTypeCodeFragment typeCodeFragment = + JavaCodeFragmentFactory.getInstance(project).createTypeCodeFragment(parameterInfo.getTypeText(), context, true, JavaCodeFragmentFactory.ALLOW_ELLIPSIS); + String initializer = parameterInfo.getDefaultInitializer(); + GroovyCodeFragment initializerCodeFragment = new GroovyCodeFragment(project, initializer != null ? initializer : ""); + GroovyCodeFragment defaultValueCodeFragment = new GroovyCodeFragment(project, parameterInfo.getDefaultValue()); + return new GrParameterTableModelItem(parameterInfo, typeCodeFragment, initializerCodeFragment, defaultValueCodeFragment); + } + + @Override + public boolean isEllipsisType() { + try { + PsiType type = ((PsiTypeCodeFragment)typeCodeFragment).getType(); + return type instanceof PsiArrayType; + } + catch (PsiTypeCodeFragment.TypeSyntaxException e) { + return false; + } + catch (PsiTypeCodeFragment.NoTypeException e) { + return false; + } + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionGenerator.java index bf202bdfd560..133792caada4 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionGenerator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionGenerator.java @@ -61,6 +61,7 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil; import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.ClosureSyntheticParameter; +import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightLocalVariable; import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass; import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames; import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils; @@ -432,7 +433,7 @@ public class ExpressionGenerator extends Generator { writeAssignmentWithSetter(((GrReferenceExpression)realLValue).getQualifier(), (PsiMethod)resolved, expression); return; } - else if (resolved == null || resolved instanceof GrReferenceExpression) { + else if (resolved == null || resolved instanceof GrLightLocalVariable) { //write unresolved reference assignment via setter GroovyObject.setProperty(String name, Object value) final GrExpression qualifier = ((GrReferenceExpression)realLValue).getQualifier(); final PsiType type = qualifier != null ? qualifier.getType() : factory.createExpressionFromText("this", expression).getType(); @@ -889,7 +890,7 @@ public class ExpressionGenerator extends Generator { //all refs in script that are not resolved are saved in 'binding' of the script if (qualifier == null && (resolved == null || - resolved instanceof GrReferenceExpression || + resolved instanceof GrLightLocalVariable || resolved instanceof LightElement && !(resolved instanceof ClosureSyntheticParameter)) && (referenceExpression.getParent() instanceof GrIndexProperty || !(referenceExpression.getParent() instanceof GrCall)) && PsiUtil.getContextClass(referenceExpression) instanceof GroovyScriptClass) { @@ -941,7 +942,7 @@ public class ExpressionGenerator extends Generator { builder.append('.'); } - if (resolved instanceof PsiNamedElement && !(resolved instanceof GrReferenceExpression)) { + if (resolved instanceof PsiNamedElement && !(resolved instanceof GrLightLocalVariable)) { final String refName = ((PsiNamedElement)resolved).getName(); if (resolved instanceof GrVariable && context.analyzedVars.toWrap((GrVariable)resolved)) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/StubGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/StubGenerator.java index 22eb159a0c53..767f9b3c731b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/StubGenerator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/StubGenerator.java @@ -394,7 +394,8 @@ public class StubGenerator implements ClassItemGenerator { private static String getVariableInitializer(GrVariable variable, PsiType declaredType) { if (declaredType instanceof PsiPrimitiveType) { Object eval = GroovyConstantExpressionEvaluator.evaluate(variable.getInitializerGroovy()); - if (eval instanceof Float) { + if (eval instanceof Float || + PsiType.FLOAT.equals(TypesUtil.unboxPrimitiveTypeWrapper(variable.getType())) && eval instanceof Number) { return eval.toString() + "f"; } else if (eval instanceof Character) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/GroovyExtractChooser.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/GroovyExtractChooser.java index 2bb9c84f9012..d23bfe922779 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/GroovyExtractChooser.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/GroovyExtractChooser.java @@ -19,10 +19,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.SelectionModel; import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiDocumentManager; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiType; +import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.RefactoringBundle; import com.intellij.refactoring.util.CommonRefactoringUtil; @@ -39,7 +36,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrReturnState import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrAssignmentExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrMemberOwner; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner; import org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.FragmentVariableInfos; @@ -96,7 +92,7 @@ public class GroovyExtractChooser { } GrStatement statement0 = statements[0]; - GrMemberOwner owner = PsiUtil.getMemberOwner(statement0); + PsiClass owner = PsiUtil.getContextClass(statement0); GrStatementOwner declarationOwner = getDeclarationOwner(statement0); if (owner == null || declarationOwner == null && !ExtractUtil.isSingleExpression(statements)) { throw new GrRefactoringError(GroovyRefactoringBundle.message("refactoring.is.not.supported.in.the.current.context")); @@ -108,7 +104,7 @@ public class GroovyExtractChooser { throw new GrRefactoringError(GroovyRefactoringBundle.message("selected.expression.has.void.type")); } - if (ExtractUtil.isSingleExpression(statements) && GrIntroduceHandlerBase.expressionIsIncorrect((GrExpression)statement0)) { + if (ExtractUtil.isSingleExpression(statements) && GrIntroduceHandlerBase.expressionIsIncorrect((GrExpression)statement0, true)) { throw new GrRefactoringError(GroovyRefactoringBundle.message("selected.block.should.represent.an.expression")); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodInfoHelper.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodInfoHelper.java index 82deb83b4982..89f231ebad57 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodInfoHelper.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodInfoHelper.java @@ -16,12 +16,12 @@ package org.jetbrains.plugins.groovy.refactoring.extract.method; +import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiModifier; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrMemberOwner; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.refactoring.extract.ExtractInfoHelperBase; import org.jetbrains.plugins.groovy.refactoring.extract.InitialInfo; @@ -35,10 +35,10 @@ public class ExtractMethodInfoHelper extends ExtractInfoHelperBase { private boolean mySpecifyType = true; private String myVisibility; private String myName; - private final GrMemberOwner myOwner; + private final PsiClass myOwner; private boolean myForceReturn; - public ExtractMethodInfoHelper(InitialInfo initialInfo, String name, GrMemberOwner owner, boolean forceReturn) { + public ExtractMethodInfoHelper(InitialInfo initialInfo, String name, PsiClass owner, boolean forceReturn) { super(initialInfo); myOwner = owner; myForceReturn = forceReturn; @@ -78,7 +78,7 @@ public class ExtractMethodInfoHelper extends ExtractInfoHelperBase { } @NotNull - public GrMemberOwner getOwner() { + public PsiClass getOwner() { return myOwner; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodDialog.java index 589bf918a178..6e2487bb9cc2 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodDialog.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodDialog.java @@ -38,7 +38,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.GroovyFileType; import org.jetbrains.plugins.groovy.intentions.utils.DuplicatesUtil; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrMemberOwner; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass; import org.jetbrains.plugins.groovy.refactoring.GroovyNamesUtil; @@ -81,7 +80,7 @@ public class GroovyExtractMethodDialog extends DialogWrapper { private ParameterTablePanel myParameterTablePanel; private final Project myProject; - public GroovyExtractMethodDialog(InitialInfo info, GrMemberOwner owner) { + public GroovyExtractMethodDialog(InitialInfo info, PsiClass owner) { super(info.getProject(), true); myProject = info.getProject(); myHelper = new ExtractMethodInfoHelper(info, "", owner, false); @@ -260,7 +259,7 @@ public class GroovyExtractMethodDialog extends DialogWrapper { private static boolean validateMethod(GrMethod method, ExtractMethodInfoHelper helper) { ArrayList conflicts = new ArrayList(); - GrMemberOwner owner = helper.getOwner(); + PsiClass owner = helper.getOwner(); PsiMethod[] methods = ArrayUtil.mergeArrays(owner.getAllMethods(), new PsiMethod[]{method}, PsiMethod.ARRAY_FACTORY); final Map> map = DuplicatesUtil.factorDuplicates(methods, new TObjectHashingStrategy() { public int computeHashCode(PsiMethod method) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodHandler.java index e3978ac5b5fc..cbce4d32bb92 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodHandler.java @@ -49,7 +49,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock; 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.GrMemberOwner; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; @@ -152,7 +151,7 @@ public class GroovyExtractMethodHandler implements RefactoringActionHandler { } private static void performRefactoring(@NotNull final InitialInfo initialInfo, final Editor editor) { - final GrMemberOwner owner = PsiUtil.getMemberOwner(initialInfo.getStatements()[0]); + final PsiClass owner = PsiUtil.getContextClass(initialInfo.getStatements()[0]); LOG.assertTrue(owner!=null); final ExtractMethodInfoHelper helper = getSettings(initialInfo, owner); @@ -180,10 +179,10 @@ public class GroovyExtractMethodHandler implements RefactoringActionHandler { }, REFACTORING_NAME, null); } - private static void createMethod(ExtractMethodInfoHelper helper, GrMemberOwner owner) { + private static void createMethod(ExtractMethodInfoHelper helper, PsiClass owner) { final GrMethod method = ExtractUtil.createMethod(helper); PsiElement anchor = calculateAnchorToInsertBefore(owner, helper.getStatements()[0]); - GrMethod newMethod = owner.addMemberDeclaration(method, anchor); + GrMethod newMethod = (GrMethod)owner.addBefore(method, anchor); renameParameterOccurrences(newMethod, helper); GrReferenceAdjuster.shortenReferences(newMethod); PsiElement prev = newMethod.getPrevSibling(); @@ -194,7 +193,7 @@ public class GroovyExtractMethodHandler implements RefactoringActionHandler { } @Nullable - private static ExtractMethodInfoHelper getSettings(@NotNull InitialInfo initialInfo, GrMemberOwner owner) { + private static ExtractMethodInfoHelper getSettings(@NotNull InitialInfo initialInfo, PsiClass owner) { if (ApplicationManager.getApplication().isUnitTestMode()) { final ExtractMethodInfoHelper helper = new ExtractMethodInfoHelper(initialInfo, "testMethod", owner, true); final PsiType type = helper.getOutputType(); @@ -217,7 +216,7 @@ public class GroovyExtractMethodHandler implements RefactoringActionHandler { } @Nullable - private static PsiElement calculateAnchorToInsertBefore(GrMemberOwner owner, PsiElement startElement) { + private static PsiElement calculateAnchorToInsertBefore(PsiClass owner, PsiElement startElement) { while (startElement != null && !isEnclosingDefinition(owner, startElement)) { if (startElement.getParent() instanceof GroovyFile) { return startElement.getNextSibling(); @@ -231,7 +230,7 @@ public class GroovyExtractMethodHandler implements RefactoringActionHandler { return startElement == null ? null : startElement.getNextSibling(); } - private static boolean isEnclosingDefinition(GrMemberOwner owner, PsiElement startElement) { + private static boolean isEnclosingDefinition(PsiClass owner, PsiElement startElement) { if (owner instanceof GrTypeDefinition) { GrTypeDefinition definition = (GrTypeDefinition) owner; return startElement.getParent() == definition.getBody(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/inline/GroovyInlineLocalHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/inline/GroovyInlineLocalHandler.java index b22229313e47..2f0c6ce47f0b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/inline/GroovyInlineLocalHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/inline/GroovyInlineLocalHandler.java @@ -133,6 +133,7 @@ public class GroovyInlineLocalHandler extends InlineActionHandler { } } + PsiElement old_cur = cur; if (controlFlowOwner instanceof GrClosableBlock) { cur = controlFlowOwner; } @@ -140,6 +141,7 @@ public class GroovyInlineLocalHandler extends InlineActionHandler { PsiElement parent = controlFlowOwner.getParent(); if (parent instanceof GrMember) cur = ((GrMember)parent).getContainingClass(); } + if (cur == old_cur) break; } while (initializer == null); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java index b7f4cc4c1053..4e3dc84f7ba1 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java @@ -83,7 +83,7 @@ public abstract class GrIntroduceHandlerBase collectExpressions(final PsiFile file, final Editor editor, final int offset) { + public static List collectExpressions(final PsiFile file, final Editor editor, final int offset, boolean acceptVoidCalls) { int correctedOffset = correctOffset(editor, offset); final PsiElement elementAtCaret = file.findElementAt(correctedOffset); final List expressions = new ArrayList(); @@ -92,14 +92,17 @@ public abstract class GrIntroduceHandlerBase expressions = collectExpressions(file, editor, offset); + final List expressions = collectExpressions(file, editor, offset, false); if (expressions.isEmpty()) { final GrVariable variable = findVariableAtCaret(file, editor, offset); if (variable == null || variable instanceof GrField || variable instanceof GrParameter) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantDialog.java index ac6dc350b332..de5d45a4591b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantDialog.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantDialog.java @@ -22,7 +22,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.event.DocumentAdapter; import com.intellij.openapi.editor.event.DocumentEvent; import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleUtil; +import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; @@ -36,8 +36,6 @@ import com.intellij.refactoring.RefactoringBundle; import com.intellij.refactoring.introduceField.IntroduceConstantHandler; import com.intellij.refactoring.ui.JavaVisibilityPanel; import com.intellij.refactoring.ui.NameSuggestionsField; -import com.intellij.refactoring.util.CommonRefactoringUtil; -import com.intellij.refactoring.util.RefactoringMessageUtil; import com.intellij.ui.RecentsManager; import com.intellij.ui.ReferenceEditorComboWithBrowseButton; import com.intellij.util.ArrayUtil; @@ -53,7 +51,6 @@ import org.jetbrains.plugins.groovy.actions.GroovyTemplatesFactory; import org.jetbrains.plugins.groovy.actions.NewGroovyActionBase; import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; -import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass; import org.jetbrains.plugins.groovy.refactoring.GroovyNameSuggestionUtil; import org.jetbrains.plugins.groovy.refactoring.GroovyNamesUtil; import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle; @@ -92,6 +89,8 @@ public class GrIntroduceConstantDialog extends DialogWrapper @Nullable private PsiClass myTargetClass; @Nullable private PsiClass myDefaultTargetClass; + private TargetClassInfo myTargetClassInfo; + public GrIntroduceConstantDialog(GrIntroduceContext context, @Nullable PsiClass defaultTargetClass) { super(context.getProject()); myContext = context; @@ -209,7 +208,7 @@ public class GrIntroduceConstantDialog extends DialogWrapper @Nullable @Override public PsiClass getTargetClass() { - return myTargetClass; + return myTargetClassInfo.getTargetClass(); } @NotNull @@ -336,48 +335,18 @@ public class GrIntroduceConstantDialog extends DialogWrapper final String targetClassName = getTargetClassName(); PsiClass newClass = myDefaultTargetClass; - if (myDefaultTargetClass == null || - !targetClassName.isEmpty() && !Comparing.strEqual(targetClassName, myDefaultTargetClass.getQualifiedName())) { - final Module module = ModuleUtil.findModuleForPsiElement(myContext.getPlace()); - newClass = JavaPsiFacade.getInstance(myContext.getProject()).findClass(targetClassName, GlobalSearchScope.projectScope( - myContext.getProject())); - if (newClass == null) { - if (Messages.showOkCancelDialog(myContext.getProject(), GroovyRefactoringBundle.message("class.does.not.exist.in.the.module"), - IntroduceConstantHandler.REFACTORING_NAME, Messages.getErrorIcon()) != OK_EXIT_CODE) { - return; - } - myTargetClass = - getTargetClass(targetClassName, myContext.getPlace().getContainingFile().getContainingDirectory(), myContext.getProject(), module); - if (myTargetClass == null) return; - } - else { - myTargetClass = - getTargetClass(targetClassName, myContext.getPlace().getContainingFile().getContainingDirectory(), myContext.getProject(), module); + if (myDefaultTargetClass == null || !targetClassName.isEmpty() && !Comparing.strEqual(targetClassName, myDefaultTargetClass.getQualifiedName())) { + final Module module = ModuleUtilCore.findModuleForPsiElement(myContext.getPlace()); + newClass = JavaPsiFacade.getInstance(myContext.getProject()).findClass(targetClassName, GlobalSearchScope.projectScope(myContext.getProject())); + + if (newClass == null && + Messages.showOkCancelDialog(myContext.getProject(), GroovyRefactoringBundle.message("class.does.not.exist.in.the.module"), + IntroduceConstantHandler.REFACTORING_NAME, Messages.getErrorIcon()) != OK_EXIT_CODE) { + return; } + myTargetClassInfo = new TargetClassInfo(targetClassName, myContext.getPlace().getContainingFile().getContainingDirectory(), module, myContext.getProject()); } - final GrIntroduceConstantHandler introduceConstantHandler = new GrIntroduceConstantHandler(); - String errorString = check(); - if (errorString != null) { - CommonRefactoringUtil.showErrorMessage(introduceConstantHandler.getRefactoringName(), - RefactoringBundle.getCannotRefactorMessage(errorString), introduceConstantHandler.getHelpID(), - myContext.getProject()); - return; - } - - String fieldName = getName(); - if (newClass != null) { - PsiField oldField = newClass.findFieldByName(fieldName, true); - - if (oldField != null) { - int answer = Messages.showYesNoDialog(myContext.getProject(), RefactoringBundle - .message("field.exists", fieldName, oldField.getContainingClass().getQualifiedName()), - introduceConstantHandler.getRefactoringName(), Messages.getWarningIcon()); - if (answer != 0) { - return; - } - } - } JavaRefactoringSettings.getInstance().INTRODUCE_CONSTANT_VISIBILITY = getVisibilityModifier(); @@ -386,64 +355,63 @@ public class GrIntroduceConstantDialog extends DialogWrapper super.doOKAction(); } - @Nullable - private String check() { - if (myTargetClass != null && !GroovyFileType.GROOVY_LANGUAGE.equals(myTargetClass.getLanguage())) { - return GroovyRefactoringBundle.message("class.language.is.not.groovy"); + private static class TargetClassInfo { + private PsiClass myTargetClass; + + String myQualifiedName; + PsiDirectory myBaseDirectory; + Module myModule; + Project myProject; + + private TargetClassInfo(PsiClass targetClass) { + myTargetClass = targetClass; } - String fieldName = getName(); - final JavaPsiFacade facade = JavaPsiFacade.getInstance(myContext.getProject()); - - if (fieldName == null || fieldName.isEmpty()) { - return RefactoringBundle.message("no.field.name.specified"); + private TargetClassInfo(String qualifiedName, PsiDirectory baseDirectory, Module module, Project project) { + myQualifiedName = qualifiedName; + myBaseDirectory = baseDirectory; + myModule = module; + myProject = project; } - else if (!facade.getNameHelper().isIdentifier(fieldName)) { - return RefactoringMessageUtil.getIncorrectIdentifierMessage(fieldName); + @Nullable + public PsiClass getTargetClass() { + if (myTargetClass == null) { + myTargetClass = getTargetClass(myQualifiedName, myBaseDirectory, myProject, myModule); + } + return myTargetClass; } - final String targetClassName = getTargetClassName(); - if (myDefaultTargetClass == null && targetClassName.isEmpty()) { - return GroovyRefactoringBundle.message("target.class.is.not.specified"); - } + @Nullable + private static PsiClass getTargetClass(String qualifiedName, PsiDirectory baseDirectory, Project project, Module module) { + GlobalSearchScope scope = GlobalSearchScope.projectScope(project); - if (myTargetClass instanceof GroovyScriptClass) { - return GroovyRefactoringBundle.message("target.class.must.not.be.script"); - } + PsiClass targetClass = JavaPsiFacade.getInstance(project).findClass(qualifiedName, scope); + if (targetClass != null) return targetClass; - return null; - } - - @Nullable - private static PsiClass getTargetClass(String qualifiedName, PsiDirectory baseDirectory, Project project, Module module) { - GlobalSearchScope scope = GlobalSearchScope.projectScope(project); - - PsiClass targetClass = JavaPsiFacade.getInstance(project).findClass(qualifiedName, scope); - if (targetClass != null) return targetClass; - - final String packageName = StringUtil.getPackageName(qualifiedName); - PsiPackage psiPackage = JavaPsiFacade.getInstance(project).findPackage(packageName); - final PsiDirectory psiDirectory; - if (psiPackage != null) { - final PsiDirectory[] directories = psiPackage.getDirectories(GlobalSearchScope.allScope(project)); - psiDirectory = directories.length > 1 ? DirectoryChooserUtil - .chooseDirectory(directories, null, project, new HashMap()) : directories[0]; - } - else { - psiDirectory = PackageUtil.findOrCreateDirectoryForPackage(module, packageName, baseDirectory, false); - } - if (psiDirectory == null) return null; - final String shortName = StringUtil.getShortName(qualifiedName); - final String fileName = shortName + NewGroovyActionBase.GROOVY_EXTENSION; - final AccessToken lock = ApplicationManager.getApplication().acquireWriteActionLock(GrIntroduceConstantDialog.class); - try { - final GroovyFile file = (GroovyFile)GroovyTemplatesFactory.createFromTemplate(psiDirectory, shortName, fileName, "GroovyClass.groovy"); - return file.getTypeDefinitions()[0]; - } - finally { - lock.finish(); + final String packageName = StringUtil.getPackageName(qualifiedName); + PsiPackage psiPackage = JavaPsiFacade.getInstance(project).findPackage(packageName); + final PsiDirectory psiDirectory; + if (psiPackage != null) { + final PsiDirectory[] directories = psiPackage.getDirectories(GlobalSearchScope.allScope(project)); + psiDirectory = directories.length > 1 ? DirectoryChooserUtil + .chooseDirectory(directories, null, project, new HashMap()) : directories[0]; + } + else { + psiDirectory = PackageUtil.findOrCreateDirectoryForPackage(module, packageName, baseDirectory, false); + } + if (psiDirectory == null) return null; + final String shortName = StringUtil.getShortName(qualifiedName); + final String fileName = shortName + NewGroovyActionBase.GROOVY_EXTENSION; + final AccessToken lock = ApplicationManager.getApplication().acquireWriteActionLock(GrIntroduceConstantDialog.class); + try { + final GroovyFile file = + (GroovyFile)GroovyTemplatesFactory.createFromTemplate(psiDirectory, shortName, fileName, "GroovyClass.groovy"); + return file.getTypeDefinitions()[0]; + } + finally { + lock.finish(); + } } } - } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantHandler.java index 307b16663143..a974fcf91d67 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantHandler.java @@ -12,13 +12,17 @@ */ package org.jetbrains.plugins.groovy.refactoring.introduce.constant; +import com.intellij.openapi.ui.Messages; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.HelpID; import com.intellij.refactoring.RefactoringBundle; +import com.intellij.refactoring.util.CommonRefactoringUtil; +import com.intellij.refactoring.util.RefactoringMessageUtil; import com.intellij.util.VisibilityUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.GroovyFileType; import org.jetbrains.plugins.groovy.lang.GrReferenceAdjuster; import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; @@ -32,6 +36,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrRefere 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.members.GrEnumConstantList; +import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import org.jetbrains.plugins.groovy.refactoring.GrRefactoringError; import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle; @@ -107,6 +112,23 @@ public class GrIntroduceConstantHandler extends GrIntroduceHandlerBase expressions = GrIntroduceHandlerBase.collectExpressions(file, editor, offset); + final List expressions = GrIntroduceHandlerBase.collectExpressions(file, editor, offset, false); if (expressions.isEmpty()) { final GrVariable variable = GrIntroduceHandlerBase.findVariableAtCaret(file, editor, offset); if (variable == null || variable instanceof GrField || variable instanceof GrParameter) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/ui/GrTypeComboBox.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/ui/GrTypeComboBox.java index ef85dc4943c2..bb92a8358451 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/ui/GrTypeComboBox.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/ui/GrTypeComboBox.java @@ -28,6 +28,7 @@ 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.GrNewExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames; @@ -50,13 +51,18 @@ public class GrTypeComboBox extends ComboBox { return new GrTypeComboBox(type, null, true, null, null, false); } - public static GrTypeComboBox createTypeComboBoxFromExpression(GrExpression expression) { + public static GrTypeComboBox createTypeComboBoxFromExpression(@NotNull GrExpression expression) { return createTypeComboBoxFromExpression(expression, false); } - public static GrTypeComboBox createTypeComboBoxFromExpression(GrExpression expression, boolean selectDef) { + public static GrTypeComboBox createTypeComboBoxFromExpression(@NotNull GrExpression expression, boolean selectDef) { PsiType type = expression.getType(); - + if (expression instanceof GrReferenceExpression) { + PsiElement resolved = ((GrReferenceExpression)expression).resolve(); + if (resolved instanceof PsiClass) { + type = TypesUtil.createJavaLangClassType(type, expression.getProject(), expression.getResolveScope()); + } + } if (GroovyRefactoringUtil.isDiamondNewOperator(expression)) { LOG.assertTrue(expression instanceof GrNewExpression); PsiType expected = PsiImplUtil.inferExpectedTypeForDiamond(expression); diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/FileScanner.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/FileScanner.java deleted file mode 100644 index 37900a1d92d0..000000000000 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/FileScanner.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2000-2007 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; - -import java.io.File; -import java.io.FileNotFoundException; -import java.util.ArrayList; -import java.util.List; - -/** - * Scans for needed files in path - * - * @author Ilya.Sergey - */ -public class FileScanner { - - /** - * @param path Path to base file (often it`s a directory to scan) - * @param pattern Pattern to match files - * @param dirAllowed true if directory is allowed. - * @return List of files - * @throws java.io.FileNotFoundException if file not found - */ - public static List scan(final String path, final String pattern, final boolean dirAllowed) throws FileNotFoundException { - List myFiles = new ArrayList(); - File baseFile = new File(path); - if (!baseFile.exists()) { - throw new FileNotFoundException("File " + path + " doesn`t exist!"); - } - scanForFiles(myFiles, baseFile, pattern, dirAllowed); - return myFiles; - } - - @SuppressWarnings({"HardCodedStringLiteral"}) - private static void scanForFiles(final List files, final File f, final String pattern, final boolean dirAllowed) { - // recursively scan for all subdirectories - if (f.isDirectory()) { - for (File file : f.listFiles()) { - if (!file.isDirectory()) { - String path = file.getAbsolutePath(); - if (!path.contains(".svn") && - !path.contains(".cvs") && - path.matches(pattern)) { - files.add(file); - } - } else { - if (dirAllowed) { - files.add(file); - } - scanForFiles(files, file, pattern, dirAllowed); - } - } - } - } - -} diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy index 9777551bddf9..3273a445b671 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy @@ -1566,4 +1566,8 @@ import static Foo.foo as barrr setBarrr() ''') } + + void testParenthesesAfterDot() { + myFixture.testCompletionTyping(getTestName(false) + '.groovy', '\t', getTestName(false) + '_after.groovy') + } } \ No newline at end of file diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovySmartCompletionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovySmartCompletionTest.groovy index 6fe0e9b6be07..a21e3cb1a0db 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovySmartCompletionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovySmartCompletionTest.groovy @@ -93,6 +93,37 @@ public class GroovySmartCompletionTest extends GroovyCompletionTestBase { assertOrderedEquals(myFixture.lookupElementStrings, 'SUBSTRING', 'createExpected', 'createSubGeneric', 'SUB_RAW') } + public void testGlobalStaticMembersForString() { + myFixture.configureByText('a.groovy', ''''\ +class Foo { + public static String string(){} + public static Comparator comparator(){} + public static String foo(){} +} + +String s = +''') + + myFixture.complete(CompletionType.SMART, 2) + assertOrderedEquals(myFixture.lookupElementStrings, + 'copyValueOf', + 'copyValueOf', + 'format', + 'format', + 'valueOf', + 'valueOf', + 'valueOf', + 'valueOf', + 'valueOf', + 'valueOf', + 'valueOf', + 'valueOf', + 'valueOf', + 'foo', + 'string', + 'toString') + } + public void testGlobalListCreators() { myFixture.configureByFile(getTestName(false) + ".groovy"); myFixture.complete(CompletionType.SMART, 2); diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/inspections/GrMethodMayBeStaticTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/inspections/GrMethodMayBeStaticTest.groovy index 4c72ede2ba1b..9ab179004fe4 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/inspections/GrMethodMayBeStaticTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/inspections/GrMethodMayBeStaticTest.groovy @@ -15,6 +15,8 @@ */ package org.jetbrains.plugins.groovy.inspections +import com.intellij.codeInspection.InspectionProfile +import com.intellij.profile.codeInspection.InspectionProjectProfileManager import org.jetbrains.plugins.groovy.LightGroovyTestCase import org.jetbrains.plugins.groovy.codeInspection.declaration.GrMethodMayBeStaticInspection /** @@ -130,7 +132,7 @@ class Bar extends Base { } void testInstanceRefInsideClosure() { - doTest('''\ + myFixture.configureByText('_.groovy', '''\ class Base { void var() {} @@ -145,5 +147,10 @@ class Bar extends Base { } } ''') + myFixture.enableInspections(GrMethodMayBeStaticInspection) + final InspectionProfile profile = InspectionProjectProfileManager.getInstance(project).inspectionProfile; + def inspection = (GrMethodMayBeStaticInspection)profile.getUnwrappedTool('GrMethodMayBeStatic', myFixture.file); + inspection.myIgnoreInstanceRefsInClosure = true + myFixture.checkHighlighting(true, false, false) } } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyFixesTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyFixesTest.groovy index 59d118097bc0..66c405619bff 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyFixesTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyFixesTest.groovy @@ -43,8 +43,9 @@ if (true) { } public void testSecondAnnotationSuppression() { - myFixture.enableInspections new GroovyUnresolvedAccessInspection() - myFixture.configureByText "a.groovy", """class FooBarGoo { + myFixture.enableInspections(new GroovyUnresolvedAccessInspection()) + myFixture.configureByText "a.groovy", """\ +class FooBarGoo { @SuppressWarnings(["GroovyParameterNamingConvention"]) def test(Object abc) { abc.def() @@ -52,7 +53,8 @@ if (true) { } """ myFixture.launchAction(myFixture.findSingleIntention("Suppress for method")) - myFixture.checkResult """class FooBarGoo { + myFixture.checkResult """\ +class FooBarGoo { @SuppressWarnings(["GroovyParameterNamingConvention", "GroovyUnresolvedAccess"]) def test(Object abc) { abc.def() diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.groovy index 74b6b96638d7..991e3d9e30f6 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyHighlightingTest.groovy @@ -58,6 +58,11 @@ public class GroovyHighlightingTest extends LightGroovyTestCase { myFixture.testHighlighting(true, false, true, getTestName(false) + ".groovy"); } + private void doRefTest(InspectionProfileEntry... tools) { + myFixture.enableInspections(*tools, new GroovyUnresolvedAccessInspection()) + myFixture.testHighlighting(true, true, true, getTestName(false) + '.groovy') + } + public void testCircularInheritance() { doTest(); } @@ -96,7 +101,7 @@ public class GroovyHighlightingTest extends LightGroovyTestCase { } public void testSuperClassNotExists() { - doTest(); + doTest(new GroovyUnresolvedAccessInspection()); } public void testDontSimplifyString() { doTest(new GroovyTrivialIfInspection(), new GroovyTrivialConditionalInspection()); } @@ -151,7 +156,7 @@ public class GroovyHighlightingTest extends LightGroovyTestCase { public void testDefinitionUsedInClosure() { doTest(new UnusedDefInspection(), new GrUnusedIncDecInspection()); } public void testDefinitionUsedInClosure2() { doTest(new UnusedDefInspection(), new GrUnusedIncDecInspection()); } public void testDefinitionUsedInSwitchCase() { doTest(new UnusedDefInspection(), new GrUnusedIncDecInspection()); } - public void testUnusedDefinitionForMethodMissing() {doTest(new GroovyUnusedDeclarationInspection())} + public void testUnusedDefinitionForMethodMissing() {doTest(new GroovyUnusedDeclarationInspection(), new UnusedDeclarationInspection())} public void testDuplicateInnerClass() {doTest();} public void testThisInStaticContext() {doTest();} @@ -352,8 +357,8 @@ print foo+barbar list2 doTest(new GroovyUnusedDeclarationInspection(), new UnusedDeclarationInspection()) } + public void testSuppressUnusedMethod() { + myFixture.configureByText('_.groovy', '''\ +class Foo { + @SuppressWarnings("GroovyUnusedDeclaration") + static def foo(int x) { + print 2 + } + + static def bar() {} +} +''') + myFixture.enableInspections(new UnusedDeclarationInspection(), new GroovyUnusedDeclarationInspection()) + myFixture.testHighlighting(true, false, true) + } + public void testAliasInParameterType() { myFixture.configureByText('a_.groovy', '''\ import java.awt.event.ActionListener @@ -950,20 +970,21 @@ public @interface CompileStatic { }''') myFixture.configureByText('_.groovy', '''\ -import groovy.transform.CompileStatic +import groovy.transform.CompileStatic -class A { +class A { -def foo() { -print abc +def foo() { +print abc } -@CompileStatic -def bar() { -print abc +@CompileStatic +def bar() { +print abc } } ''') + myFixture.enableInspections(new GroovyUnresolvedAccessInspection()) myFixture.testHighlighting(true, false, false) } @@ -1029,10 +1050,10 @@ static def foo() { print abc def cl = { - print cde + print cde } } -''') +''', GroovyUnresolvedAccessInspection) } void testMissingReturnInBinaryOr() { @@ -1130,7 +1151,7 @@ test() { cl() var.toUpperCase() } -""") +""", GroovyUnresolvedAccessInspection) } void testReassignedVarInClosureInspection() { @@ -1488,22 +1509,22 @@ private int getObjects() { void testPackageDefinition() { myFixture.addFileToProject('abc/foo.groovy', '''\ -package cde +package cde print 2 ''') myFixture.addFileToProject('cde/bar.groovy', '//empty file') - + myFixture.enableInspections(new GrPackageInspection()) myFixture.testHighlighting(true, false, false, 'abc/foo.groovy') } void testPackageDefinition2() { myFixture.addFileToProject('abc/foo.groovy', '''\ -package cde +package cde print 2 ''') - + myFixture.enableInspections(new GrPackageInspection()) myFixture.testHighlighting(true, false, false, 'abc/foo.groovy') } @@ -1516,4 +1537,22 @@ class A { A.B foo = new A.B() ''') } + + void testFallthroughInSwitch() { + testHighlighting('''\ +def f(String foo, int mode) { + switch (mode) { + case 0: foo = foo.reverse() + case 1: return foo + } +} + +def f2(String foo, int mode) { + switch (mode) { + case 0: foo = foo.reverse() + case 1: return 2 + } +} +''', UnusedDefInspection) + } } \ No newline at end of file diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/dynamic/DynamicTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/dynamic/DynamicTest.java index 1169f935d44e..ff7a4a359353 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/dynamic/DynamicTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/dynamic/DynamicTest.java @@ -12,6 +12,7 @@ import org.jetbrains.plugins.groovy.annotator.intentions.dynamic.DynamicProperty import org.jetbrains.plugins.groovy.annotator.intentions.dynamic.ParamInfo; import org.jetbrains.plugins.groovy.annotator.intentions.dynamic.elements.DClassElement; import org.jetbrains.plugins.groovy.annotator.intentions.dynamic.elements.DRootElement; +import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GroovyUnresolvedAccessInspection; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import org.jetbrains.plugins.groovy.util.TestUtils; @@ -53,6 +54,8 @@ public class DynamicTest extends JavaCodeInsightFixtureTestCase { } private GrReferenceExpression doDynamicFix() throws Throwable { + myFixture.enableInspections(new GroovyUnresolvedAccessInspection()); + final List actions = myFixture.getAvailableIntentions(getTestName(false) + ".groovy"); DynamicPropertyFix dynamicFix = ContainerUtil.findInstance(actions, DynamicPropertyFix.class); @@ -62,6 +65,7 @@ public class DynamicTest extends JavaCodeInsightFixtureTestCase { } else { final DynamicMethodFix fix = ContainerUtil.findInstance(actions, DynamicMethodFix.class); + assertNotNull(fix); fix.invoke(getProject()); return fix.getReferenceExpression(); } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolvePropertyTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolvePropertyTest.groovy index 004c02162912..6b2ed66ace68 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolvePropertyTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolvePropertyTest.groovy @@ -14,33 +14,26 @@ * limitations under the License. */ package org.jetbrains.plugins.groovy.lang.resolve - import com.intellij.psi.* import com.intellij.psi.util.PropertyUtil import org.jetbrains.plugins.groovy.GroovyFileType import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement -import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase 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.expressions.GrAssignmentExpression -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.members.GrAccessorMethod import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod -import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.GrTopStatement +import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightLocalVariable import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil import org.jetbrains.plugins.groovy.util.TestUtils /** * @author ven */ public class ResolvePropertyTest extends GroovyResolveTestCase { - @Override - protected String getBasePath() { - return TestUtils.getTestDataPath() + "resolve/property/"; - } + final String basePath = TestUtils.testDataPath + "resolve/property/" public void testParameter1() throws Exception { doTest("parameter1/A.groovy"); @@ -147,9 +140,7 @@ public class ResolvePropertyTest extends GroovyResolveTestCase { public void testUndefinedVar1() throws Exception { PsiReference ref = configureByFile("undefinedVar1/A.groovy"); PsiElement resolved = ref.resolve(); - assertInstanceOf(resolved, GrReferenceExpression); - GrTopStatement statement = ((GroovyFileBase) resolved.getContainingFile()).getTopStatements()[2]; - assertTrue(resolved.equals(((GrAssignmentExpression) statement).getLValue())); + assertInstanceOf(resolved, GrLightLocalVariable); } public void testRecursive1() throws Exception { @@ -319,7 +310,7 @@ print bar private void doUndefinedVarTest(String fileName) throws Exception { PsiReference ref = configureByFile(fileName); PsiElement resolved = ref.resolve(); - assertTrue(resolved instanceof GrReferenceExpression); + assertInstanceOf(resolved, GrLightLocalVariable); } public void testBooleanProperty() throws Exception { @@ -878,4 +869,30 @@ print other assertInstanceOf(ref.resolve(), GrAccessorMethod) } + + void testPrefLocalVarToScriptName() { + myFixture.addFileToProject('foo.groovy', 'print 2') + + def ref = configureByText('''\ +class Bar { + public float FOO = 1.23f + public float ZZZ = 5.78f + public float pi = 3.14f + public float xxx = 6f + + void doSmth() {} +} + +class User { + public static void main(String[] args) { + Bar foo = new Bar() + foo.bar() + println foo.FOO * foo.ZZZ * foo.pi * foo.xxx + foo.doSmth() + } +} +''') + + assertInstanceOf(ref.resolve(), GrField) + } } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/inline/InlineVariableTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/inline/InlineVariableTest.groovy similarity index 58% rename from plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/inline/InlineVariableTest.java rename to plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/inline/InlineVariableTest.groovy index e22910d5d64d..789ef538619d 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/inline/InlineVariableTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/inline/InlineVariableTest.groovy @@ -13,49 +13,43 @@ * limitations under the License. */ -package org.jetbrains.plugins.groovy.refactoring.inline; - -import com.intellij.codeInsight.TargetElementUtilBase; -import com.intellij.lang.ASTNode; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; -import com.intellij.psi.*; -import com.intellij.psi.impl.source.codeStyle.CodeEditUtil; -import com.intellij.psi.impl.source.tree.TreeElement; -import com.intellij.refactoring.util.CommonRefactoringUtil; -import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; -import junit.framework.Assert; -import org.jetbrains.plugins.groovy.GroovyFileType; -import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; -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.refactoring.GroovyRefactoringUtil; -import org.jetbrains.plugins.groovy.util.TestUtils; - -import java.util.List; +package org.jetbrains.plugins.groovy.refactoring.inline +import com.intellij.codeInsight.TargetElementUtilBase +import com.intellij.lang.ASTNode +import com.intellij.openapi.editor.Editor +import com.intellij.openapi.project.Project +import com.intellij.psi.* +import com.intellij.psi.impl.source.codeStyle.CodeEditUtil +import com.intellij.psi.impl.source.tree.TreeElement +import com.intellij.refactoring.util.CommonRefactoringUtil +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase +import junit.framework.Assert +import org.jetbrains.plugins.groovy.GroovyFileType +import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable +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.refactoring.GroovyRefactoringUtil +import org.jetbrains.plugins.groovy.util.TestUtils /** * @author ilyas */ public class InlineVariableTest extends LightCodeInsightFixtureTestCase { - @Override - protected String getBasePath() { - return TestUtils.getTestDataPath() + "groovy/refactoring/inlineLocal/"; - } + final String basePath = TestUtils.testDataPath + "groovy/refactoring/inlineLocal/" - public void testGRVY_1232() throws Throwable { doTest(); } - public void testGRVY_1248() throws Throwable { doTest(); } - public void testVar1() throws Throwable { doTest(); } - public void testVar2() throws Throwable { doTest(); } - public void testVar3() throws Throwable { doTest(); } - public void testVar4() throws Throwable { doTest(); } - public void testVar5() throws Throwable { doTest(); } - public void testVar6() throws Throwable { doTest(); } - public void testVarInGString() throws Throwable { doTest(); } - public void testVarInGString2() throws Throwable { doTest(); } - public void testVarInGString3() throws Throwable { doTest(); } - public void testVarInGString4() throws Throwable { doTest(); } + public void testGRVY_1232() { doTest(); } + public void testGRVY_1248() { doTest(); } + public void testVar1() { doTest(); } + public void testVar2() { doTest(); } + public void testVar3() { doTest(); } + public void testVar4() { doTest(); } + public void testVar5() { doTest(); } + public void testVar6() { doTest(); } + public void testVarInGString() { doTest(); } + public void testVarInGString2() { doTest(); } + public void testVarInGString3() { doTest(); } + public void testVarInGString4() { doTest(); } public void testField() {doFieldTest();} @@ -75,8 +69,10 @@ public class InlineVariableTest extends LightCodeInsightFixtureTestCase { public void testRegexInCommandArg4() {doTest();} public void testRegexInCommandArg5() {doTest();} + public void testUndefinedVarInline() {doTest()} + protected void doFieldTest() { - InlineMethodTest.doInlineTest(myFixture, getTestDataPath() + getTestName(true) + ".test", new GroovyInlineHandler()); + InlineMethodTest.doInlineTest(myFixture, testDataPath + getTestName(true) + ".test", new GroovyInlineHandler()); } private void doTest() { @@ -84,53 +80,53 @@ public class InlineVariableTest extends LightCodeInsightFixtureTestCase { } private void doTest(final boolean inlineDef) { - final List data = TestUtils.readInput(getTestDataPath() + getTestName(true) + ".test"); + final List data = TestUtils.readInput(testDataPath + getTestName(true) + ".test"); String fileText = data.get(0); myFixture.configureByText(GroovyFileType.GROOVY_FILE_TYPE, fileText); - final Editor editor = myFixture.getEditor(); - final PsiFile file = myFixture.getFile(); - setIndentationToNode(file.getNode()); + final Editor editor = myFixture.editor; + final PsiFile file = myFixture.file; + setIndentationToNode(file.node); - int startOffset = editor.getSelectionModel().getSelectionStart(); - int endOffset = editor.getSelectionModel().getSelectionEnd(); - editor.getCaretModel().moveToOffset(endOffset); + int startOffset = editor.selectionModel.selectionStart; + int endOffset = editor.selectionModel.selectionEnd; + editor.caretModel.moveToOffset(endOffset); GroovyPsiElement selectedArea = GroovyRefactoringUtil.findElementInRange(file, startOffset, endOffset, GrReferenceExpression.class); if (selectedArea == null) { PsiElement identifier = GroovyRefactoringUtil.findElementInRange(file, startOffset, endOffset, PsiElement.class); if (identifier != null) { - Assert.assertTrue("Selected area doesn't point to var", identifier.getParent() instanceof GrVariable); - selectedArea = (GroovyPsiElement)identifier.getParent(); + Assert.assertTrue("Selected area doesn't point to var", identifier.parent instanceof GrVariable); + selectedArea = (GroovyPsiElement)identifier.parent; } } Assert.assertNotNull("Selected area reference points to nothing", selectedArea); - PsiElement element = selectedArea instanceof GrExpression ? selectedArea.getReference().resolve() : selectedArea; + PsiElement element = selectedArea instanceof GrExpression ? selectedArea.reference.resolve() : selectedArea; Assert.assertNotNull("Cannot resolve selected reference expression", element); try { if (!inlineDef) { - performInline(getProject(), editor); + performInline(project, editor); } else { - performDefInline(getProject(), editor); + performDefInline(project, editor); } - editor.getSelectionModel().removeSelection(); + editor.selectionModel.removeSelection(); myFixture.checkResult(data.get(1), true); } catch (CommonRefactoringUtil.RefactoringErrorHintException e) { - assertEquals(data.get(1), "FAIL: " + e.getMessage()); + assertEquals(data.get(1), "FAIL: " + e.message); } } public static void performInline(Project project, Editor editor) { PsiElement element = TargetElementUtilBase.findTargetElement(editor, TargetElementUtilBase.ELEMENT_NAME_ACCEPTED | TargetElementUtilBase.REFERENCED_ELEMENT_ACCEPTED); - assertTrue(element instanceof GrVariable); + assertInstanceOf(element, GrVariable); - GroovyInlineLocalHandler.invoke(project, editor, (GrVariable)element); + GroovyInlineLocalHandler.invoke(project, editor, element as GrVariable); } public static void performDefInline(Project project, Editor editor) { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/optimizeImports/GroovyAddImportActionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/optimizeImports/GroovyAddImportActionTest.groovy index 1024ce2d1728..7c888b0d9693 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/optimizeImports/GroovyAddImportActionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/optimizeImports/GroovyAddImportActionTest.groovy @@ -17,6 +17,7 @@ package org.jetbrains.plugins.groovy.refactoring.optimizeImports import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase +import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GroovyUnresolvedAccessInspection /** * @author peter */ @@ -31,6 +32,8 @@ public class Foo { Log l = bar.LogFactory.log(); } ''' + myFixture.enableInspections(new GroovyUnresolvedAccessInspection()) + importClass() myFixture.checkResult '''import bar.Log diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/spock/SpockTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/spock/SpockTest.groovy index 3299df42ec84..e222c242ca72 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/spock/SpockTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/spock/SpockTest.groovy @@ -220,9 +220,9 @@ class FooSpec extends spock.lang.Specification { myFixture.configureByText("FooSpec.groovy", """\ class FooSpec extends spock.lang.Specification { def "foo test"() { - String subscriber = Mock() + String subscriber = Mock() then: (0.._) * subscriber.concat(_) - subscriber.concat(asdasdasd) + subscriber.concat(asdasdasd) subscriber.concat(23) } } diff --git a/plugins/groovy/testdata/groovy/completion/ParenthesesAfterDot.groovy b/plugins/groovy/testdata/groovy/completion/ParenthesesAfterDot.groovy new file mode 100644 index 000000000000..1d22333fbe30 --- /dev/null +++ b/plugins/groovy/testdata/groovy/completion/ParenthesesAfterDot.groovy @@ -0,0 +1,4 @@ +class Abc { +} + +Abc.(1/2) \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/completion/ParenthesesAfterDot_after.groovy b/plugins/groovy/testdata/groovy/completion/ParenthesesAfterDot_after.groovy new file mode 100644 index 000000000000..7385cd77a8b2 --- /dev/null +++ b/plugins/groovy/testdata/groovy/completion/ParenthesesAfterDot_after.groovy @@ -0,0 +1,4 @@ +class Abc { +} + +Abc.annotation(1/2) \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/reachingDefs/em2.test b/plugins/groovy/testdata/groovy/reachingDefs/em2.test index b3dcad80e08a..f98ddfcf2ca4 100644 --- a/plugins/groovy/testdata/groovy/reachingDefs/em2.test +++ b/plugins/groovy/testdata/groovy/reachingDefs/em2.test @@ -14,6 +14,8 @@ int yyy = xxx + p System.out.println(yyy); ----- input: +xxx +jjj p output: yyy \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/refactoring/extractMethod/em1.test b/plugins/groovy/testdata/groovy/refactoring/extractMethod/em1.test index c2e307e2123e..1bb7d60994a6 100644 --- a/plugins/groovy/testdata/groovy/refactoring/extractMethod/em1.test +++ b/plugins/groovy/testdata/groovy/refactoring/extractMethod/em1.test @@ -18,15 +18,14 @@ def vv = 6 def gg = 7 -int yyy = testMethod(kkk, vv, gg) +int yyy = testMethod(kkk, iii, vv, gg) -private int testMethod(int kkk, int vv, int gg) { +private int testMethod(int kkk, int iii, int vv, int gg) { println(kkk + iii + (vv + gg)) yyy = kkk + 2 return yyy } - www = kkk + 3 println(yyy) diff --git a/plugins/groovy/testdata/groovy/refactoring/extractMethod/err1.test b/plugins/groovy/testdata/groovy/refactoring/extractMethod/err1.test index c814d80dea75..26ae9dc8e120 100644 --- a/plugins/groovy/testdata/groovy/refactoring/extractMethod/err1.test +++ b/plugins/groovy/testdata/groovy/refactoring/extractMethod/err1.test @@ -19,16 +19,14 @@ def gg = 7 int www, yyy -(yyy, www) = testMethod(kkk, vv, gg) +(yyy, www) = testMethod(kkk, iii, vv, gg) -private List testMethod(int kkk, int vv, int gg) { +private List testMethod(int kkk, int iii, int vv, int gg) { println(kkk + iii + (vv + gg)) yyy = kkk + 2 www = kkk + 3 return [yyy, www] } - - println(yyy) println(www) \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/refactoring/extractMethod/expr3.test b/plugins/groovy/testdata/groovy/refactoring/extractMethod/expr3.test index b070a0802028..fa7a15a8b26f 100644 --- a/plugins/groovy/testdata/groovy/refactoring/extractMethod/expr3.test +++ b/plugins/groovy/testdata/groovy/refactoring/extractMethod/expr3.test @@ -4,8 +4,8 @@ jjj = iii + 1 ----- iii = null -jjj = testMethod() +jjj = testMethod(iii) -private testMethod() { +private testMethod(iii) { iii + 1 } \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/refactoring/extractMethod/multiOutput1.test b/plugins/groovy/testdata/groovy/refactoring/extractMethod/multiOutput1.test index e3cf98ac8cad..d055619b1a17 100644 --- a/plugins/groovy/testdata/groovy/refactoring/extractMethod/multiOutput1.test +++ b/plugins/groovy/testdata/groovy/refactoring/extractMethod/multiOutput1.test @@ -20,5 +20,4 @@ private List testMethod(int a) { return [a, b] } - print a+b \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/refactoring/extractMethod/multiOutput2.test b/plugins/groovy/testdata/groovy/refactoring/extractMethod/multiOutput2.test index fcab0f67eaca..f5213ee7b72d 100644 --- a/plugins/groovy/testdata/groovy/refactoring/extractMethod/multiOutput2.test +++ b/plugins/groovy/testdata/groovy/refactoring/extractMethod/multiOutput2.test @@ -20,5 +20,4 @@ private List testMethod(int a) { return [b, c] } - print a+b+c \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/refactoring/extractMethod/multiOutput3.test b/plugins/groovy/testdata/groovy/refactoring/extractMethod/multiOutput3.test index f02466b484fe..ca3e08f92ae9 100644 --- a/plugins/groovy/testdata/groovy/refactoring/extractMethod/multiOutput3.test +++ b/plugins/groovy/testdata/groovy/refactoring/extractMethod/multiOutput3.test @@ -20,5 +20,4 @@ private List testMethod(int a) { return [b, c] } - print a+b+c \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/refactoring/extractMethod/multiOutput4.test b/plugins/groovy/testdata/groovy/refactoring/extractMethod/multiOutput4.test index 4806033aaf8a..871ca50dc8c6 100644 --- a/plugins/groovy/testdata/groovy/refactoring/extractMethod/multiOutput4.test +++ b/plugins/groovy/testdata/groovy/refactoring/extractMethod/multiOutput4.test @@ -15,5 +15,4 @@ private int testMethod(int a) { return b } - print a+b \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/refactoring/extractMethod/resul1.test b/plugins/groovy/testdata/groovy/refactoring/extractMethod/resul1.test index fa214bee04a5..55080158fa16 100644 --- a/plugins/groovy/testdata/groovy/refactoring/extractMethod/resul1.test +++ b/plugins/groovy/testdata/groovy/refactoring/extractMethod/resul1.test @@ -17,5 +17,4 @@ private boolean testMethod(boolean cond) { return result } - println result \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/refactoring/inlineLocal/undefinedVarInline.test b/plugins/groovy/testdata/groovy/refactoring/inlineLocal/undefinedVarInline.test new file mode 100644 index 000000000000..bc03b22572d4 --- /dev/null +++ b/plugins/groovy/testdata/groovy/refactoring/inlineLocal/undefinedVarInline.test @@ -0,0 +1,8 @@ +x = 5 +print x +x = 7 +print x +----- +x = 5 +print x +print 7 \ No newline at end of file diff --git a/plugins/groovy/testdata/highlighting/BooleanProperties.groovy b/plugins/groovy/testdata/highlighting/BooleanProperties.groovy index ec2c8e74aa98..aa00591ee02f 100644 --- a/plugins/groovy/testdata/highlighting/BooleanProperties.groovy +++ b/plugins/groovy/testdata/highlighting/BooleanProperties.groovy @@ -6,5 +6,5 @@ class Foo { } } def x = new Foo().small -def y = new Foo().big -def z = new Foo().inferred \ No newline at end of file +def y = new Foo().big +def z = new Foo().inferred \ No newline at end of file diff --git a/plugins/groovy/testdata/highlighting/PassingCollectionSubtractionIntoGenericMethod.groovy b/plugins/groovy/testdata/highlighting/PassingCollectionSubtractionIntoGenericMethod.groovy index d13089d52775..3eb09b2d240b 100644 --- a/plugins/groovy/testdata/highlighting/PassingCollectionSubtractionIntoGenericMethod.groovy +++ b/plugins/groovy/testdata/highlighting/PassingCollectionSubtractionIntoGenericMethod.groovy @@ -3,7 +3,7 @@ def foo(Set zzz) { while (xxx) { def sub = xxx - xxx.iterator().next() xxx = bar(sub, zzz) - doo() + doo() } } diff --git a/plugins/groovy/testdata/highlighting/SuperClassNotExists.groovy b/plugins/groovy/testdata/highlighting/SuperClassNotExists.groovy index 96400e0172a9..e668ee296b05 100644 --- a/plugins/groovy/testdata/highlighting/SuperClassNotExists.groovy +++ b/plugins/groovy/testdata/highlighting/SuperClassNotExists.groovy @@ -1,5 +1,5 @@ public class PhpTypeTest extends String1 { def foo() { - print abc.class - } + print abc.class +} } diff --git a/plugins/groovy/testdata/highlighting/UnresolvedAccess.groovy b/plugins/groovy/testdata/highlighting/UnresolvedAccess.groovy index aea042d47dad..47484d840a36 100644 --- a/plugins/groovy/testdata/highlighting/UnresolvedAccess.groovy +++ b/plugins/groovy/testdata/highlighting/UnresolvedAccess.groovy @@ -1 +1 @@ -def x = abc + 2 \ No newline at end of file +def x = abc + 2 \ No newline at end of file diff --git a/plugins/groovy/testdata/highlighting/UnresolvedLhsAssignment.groovy b/plugins/groovy/testdata/highlighting/UnresolvedLhsAssignment.groovy index 8f9dd1693933..3cc5d0af95f0 100644 --- a/plugins/groovy/testdata/highlighting/UnresolvedLhsAssignment.groovy +++ b/plugins/groovy/testdata/highlighting/UnresolvedLhsAssignment.groovy @@ -1,6 +1,6 @@ class Zoo { def foo() { - xxxx = 2 + xxxx = 2 } } diff --git a/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties b/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties index 815d26857998..1a696ce18dd1 100644 --- a/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties +++ b/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties @@ -106,6 +106,7 @@ hg4idea.progress.pull.with.update=Updating repository hg4idea.error.invalidTarget=Invalid integration target hg4idea.status.currentSituationtext={0}({1}) hg4idea.status.currentSituation.description=Current mercurial branch and parents of the working directory +hg4idea.progress.checking.ignored=Checking for ignoring files 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 diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgFile.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgFile.java index 924822f5ecb3..6787f19c11e3 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgFile.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgFile.java @@ -13,9 +13,7 @@ package org.zmlx.hg4idea; import com.google.common.base.Objects; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vfs.VfsUtil; @@ -64,12 +62,7 @@ public class HgFile { @NotNull public FilePath toFilePath() { - return ApplicationManager.getApplication().runReadAction( - new Computable() { - public FilePath compute() { - return VcsUtil.getFilePath(file); - } - }); + return VcsUtil.getFilePath(file); } private static String buildRelativePath(File anchestor, File descendant) { diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgVFSListener.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgVFSListener.java index a9f743e7c44c..edb45b31163f 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgVFSListener.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgVFSListener.java @@ -15,14 +15,18 @@ */ package org.zmlx.hg4idea; +import com.intellij.execution.ui.ConsoleViewContentType; import com.intellij.openapi.application.ApplicationManager; 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.*; import com.intellij.openapi.vcs.changes.ChangeListManagerImpl; import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.ui.AppUIUtil; +import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.VcsBackgroundTask; import com.intellij.vcsUtil.VcsUtil; import org.jetbrains.annotations.NotNull; @@ -61,7 +65,7 @@ public class HgVFSListener extends VcsVFSListener { } @Override - protected void executeAdd(List addedFiles, Map copyFromMap) { + protected void executeAdd(final List addedFiles, final Map copyFromMap) { // if a file is copied from another repository, then 'hg add' should be used instead of 'hg copy'. // Thus here we remove such files from the copyFromMap. for (Iterator> it = copyFromMap.entrySet().iterator(); it.hasNext(); ) { @@ -80,11 +84,50 @@ public class HgVFSListener extends VcsVFSListener { it.remove(); } } + // exclude files which are ignored in .hgignore in background and execute adding after that + final Map> sortedFiles = HgUtil.sortByHgRoots(myProject, addedFiles); + final HashSet untrackedFiles = new HashSet(); + new Task.Backgroundable(myProject, HgVcsMessages.message("hg4idea.progress.checking.ignored"), false) { + @Override + public void run(@NotNull ProgressIndicator pi) { + for (Map.Entry> e : sortedFiles.entrySet()) { + VirtualFile repo = e.getKey(); + final Collection files = e.getValue(); + pi.setText(repo.getPresentableUrl()); + try { + untrackedFiles.addAll(new HgStatusCommand(myProject).getHgUntrackedFiles(repo, new ArrayList(files))); + } + catch (final VcsException ex) { + UIUtil.invokeLaterIfNeeded(new Runnable() { + public void run() { + ((HgVcs)myVcs).showMessageInConsole(ex.getMessage(), ConsoleViewContentType.ERROR_OUTPUT.getAttributes()); + } + }); + } + } + addedFiles.retainAll(untrackedFiles); + // select files to add if there is something to select + if (!addedFiles.isEmpty() || !copyFromMap.isEmpty()) { - // select files to add if there is something to select - if (!addedFiles.isEmpty() || !copyFromMap.isEmpty()) { - super.executeAdd(addedFiles, copyFromMap); - } + AppUIUtil.invokeLaterIfProjectAlive(myProject, new Runnable() { + @Override + public void run() { + originalExecuteAdd(addedFiles, copyFromMap); + } + }); + } + } + }.queue(); + } + + /** + * The version of execute add before overriding + * + * @param addedFiles the added files + * @param copiedFiles the copied files + */ + private void originalExecuteAdd(List addedFiles, final Map copiedFiles) { + super.executeAdd(addedFiles, copiedFiles); } @Override diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgStatusCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgStatusCommand.java index 41f935837215..dc9fcf611ed7 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgStatusCommand.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgStatusCommand.java @@ -16,8 +16,11 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.FilePath; +import com.intellij.openapi.vcs.ObjectsConvertor; +import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.vcsUtil.VcsFileUtil; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.zmlx.hg4idea.HgChange; import org.zmlx.hg4idea.HgFile; @@ -179,4 +182,26 @@ public class HgStatusCommand { } return changes; } + + private void setOnlyUntrackedTrue() { + includeAdded = false; + includeModified = false; + includeRemoved = false; + includeDeleted = false; + includeCopySource = false; + includeIgnored = false; + includeUnknown = true; + } + + @NotNull + public Collection getHgUntrackedFiles(@NotNull VirtualFile repo, @NotNull List files) throws VcsException { + Collection untrackedFiles = new HashSet(); + setOnlyUntrackedTrue(); + List filePaths = ObjectsConvertor.vf2fp(files); + Set change = execute(repo, filePaths); + for (HgChange hgChange : change) { + untrackedFiles.add(hgChange.afterFile().toFilePath().getVirtualFile()); + } + return untrackedFiles; + } } diff --git a/plugins/maven/jps-plugin/testSrc/org/jetbrains/jps/maven/model/JpsMavenJavaBuildingTest.java b/plugins/maven/jps-plugin/testSrc/org/jetbrains/jps/maven/model/JpsMavenJavaBuildingTest.java index 56363ee875ad..003b88ff60f4 100644 --- a/plugins/maven/jps-plugin/testSrc/org/jetbrains/jps/maven/model/JpsMavenJavaBuildingTest.java +++ b/plugins/maven/jps-plugin/testSrc/org/jetbrains/jps/maven/model/JpsMavenJavaBuildingTest.java @@ -32,6 +32,6 @@ public class JpsMavenJavaBuildingTest extends JpsBuildTestCase { FileUtil.copyDir(srcDir, workDir); addJdk("1.6"); loadProject(workDir.getAbsolutePath()); - doRebuild(); + rebuildAll(); } } diff --git a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerEmbedderImpl.java b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerEmbedderImpl.java index d576f6f5bebf..ed60dab83d83 100644 --- a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerEmbedderImpl.java +++ b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerEmbedderImpl.java @@ -17,26 +17,42 @@ package org.jetbrains.idea.maven.server; import com.intellij.util.SystemProperties; import gnu.trove.THashSet; +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.repository.ArtifactRepositoryPolicy; +import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout; +import org.apache.maven.artifact.resolver.ArtifactResolutionRequest; +import org.apache.maven.artifact.resolver.ArtifactResolutionResult; +import org.apache.maven.artifact.resolver.ArtifactResolver; +import org.apache.maven.artifact.resolver.ResolutionListener; import org.apache.maven.cli.MavenCli; +import org.apache.maven.execution.DefaultMavenExecutionRequest; +import org.apache.maven.execution.MavenExecutionRequest; import org.apache.maven.model.Activation; import org.apache.maven.model.Model; import org.apache.maven.model.Profile; import org.apache.maven.model.profile.DefaultProfileInjector; import org.apache.maven.profiles.activation.*; -import org.apache.maven.project.DefaultProjectBuilderConfiguration; -import org.apache.maven.project.ProjectBuilderConfiguration; +import org.apache.maven.project.*; import org.apache.maven.project.interpolation.AbstractStringBasedModelInterpolator; import org.apache.maven.project.interpolation.ModelInterpolationException; 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.settings.Settings; +import org.apache.maven.settings.SettingsUtils; import org.apache.maven.settings.building.DefaultSettingsBuildingRequest; import org.apache.maven.settings.building.SettingsBuilder; import org.apache.maven.settings.building.SettingsBuildingException; import org.apache.maven.settings.building.SettingsBuildingRequest; +import org.apache.maven.shared.dependency.tree.DependencyNode; +import org.apache.maven.shared.dependency.tree.DependencyTreeResolutionListener; import org.codehaus.plexus.DefaultPlexusContainer; import org.codehaus.plexus.PlexusContainer; import org.codehaus.plexus.classworlds.ClassWorld; +import org.codehaus.plexus.component.repository.exception.ComponentLookupException; import org.codehaus.plexus.context.ContextException; import org.codehaus.plexus.context.DefaultContext; import org.codehaus.plexus.logging.BaseLoggerManager; @@ -45,28 +61,33 @@ import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationExce import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.maven.model.*; -import org.jetbrains.idea.maven.server.embedder.CustomMaven3ModelInterpolator; -import org.jetbrains.idea.maven.server.embedder.FieldAccessor; +import org.jetbrains.idea.maven.server.embedder.*; import java.io.File; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.rmi.RemoteException; +import java.rmi.server.UnicastRemoteObject; import java.util.*; public class Maven3ServerEmbedderImpl extends MavenRemoteObject implements MavenServerEmbedder { @NotNull private final DefaultPlexusContainer myContainer; @NotNull private final Settings myMavenSettings; + private final ArtifactRepository myLocalRepository; + private final Maven3ServerConsoleLogger myConsoleWrapper; + + private volatile MavenServerProgressIndicator myCurrentIndicator; + public Maven3ServerEmbedderImpl(MavenServerSettings settings) throws RemoteException { File mavenHome = settings.getMavenHome(); if (mavenHome != null) { System.setProperty("maven.home", mavenHome.getPath()); } - final Maven3ServerConsoleLogger logger = new Maven3ServerConsoleLogger(); - logger.setThreshold(settings.getLoggingLevel()); + myConsoleWrapper = new Maven3ServerConsoleLogger(); + myConsoleWrapper.setThreshold(settings.getLoggingLevel()); ClassWorld classWorld = new ClassWorld("plexus.core", Thread.currentThread().getContextClassLoader()); MavenCli cli = new MavenCli(classWorld) { @@ -75,13 +96,13 @@ public class Maven3ServerEmbedderImpl extends MavenRemoteObject implements Maven ((DefaultPlexusContainer)container).setLoggerManager(new BaseLoggerManager() { @Override protected Logger createLogger(String s) { - return logger; + return myConsoleWrapper; } }); } }; - Class cliRequestClass = null; + Class cliRequestClass; try { cliRequestClass = MavenCli.class.getClassLoader().loadClass("org.apache.maven.cli.MavenCli$CliRequest"); } @@ -128,12 +149,14 @@ public class Maven3ServerEmbedderImpl extends MavenRemoteObject implements Maven settings, FieldAccessor.get(cliRequestClass, cliRequest, "systemProperties"), FieldAccessor.get(cliRequestClass, cliRequest, "userProperties")); + + myLocalRepository = createLocalRepository(settings.getSnapshotUpdatePolicy()); } - private Settings buildSettings(SettingsBuilder builder, - MavenServerSettings settings, - Properties systemProperties, - Properties userProperties) + private static Settings buildSettings(SettingsBuilder builder, + MavenServerSettings settings, + Properties systemProperties, + Properties userProperties) throws RemoteException { SettingsBuildingRequest settingsRequest = new DefaultSettingsBuildingRequest(); settingsRequest.setGlobalSettingsFile(settings.getGlobalSettingsFile()); @@ -160,18 +183,258 @@ public class Maven3ServerEmbedderImpl extends MavenRemoteObject implements Maven return result; } + @SuppressWarnings({"unchecked"}) + public T getComponent(Class clazz, String roleHint) { + try { + return (T) myContainer.lookup(clazz.getName(), roleHint); + } catch (ComponentLookupException e) { + throw new RuntimeException(e); + } + } + + @SuppressWarnings({"unchecked"}) + public T getComponent(Class clazz) { + try { + return (T) myContainer.lookup(clazz.getName()); + } catch (ComponentLookupException e) { + throw new RuntimeException(e); + } + } + + private ArtifactRepository createLocalRepository(MavenServerSettings.UpdatePolicy snapshotUpdatePolicy) { + ArtifactRepositoryLayout layout = getComponent(ArtifactRepositoryLayout.class, "default"); + ArtifactRepositoryFactory factory = getComponent(ArtifactRepositoryFactory.class); + + String url = myMavenSettings.getLocalRepository(); + if (!url.startsWith("file:")) url = "file://" + url; + + ArtifactRepository localRepository = factory.createArtifactRepository("local", url, layout, null, null); + + boolean snapshotPolicySet = myMavenSettings.isOffline(); + if (!snapshotPolicySet && snapshotUpdatePolicy == MavenServerSettings.UpdatePolicy.ALWAYS_UPDATE) { + factory.setGlobalUpdatePolicy(ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS); + } + factory.setGlobalChecksumPolicy(ArtifactRepositoryPolicy.CHECKSUM_POLICY_WARN); + + return localRepository; + } + @Override public void customize(@Nullable MavenWorkspaceMap workspaceMap, boolean failOnUnresolvedDependency, @NotNull MavenServerConsole console, @NotNull MavenServerProgressIndicator indicator) throws RemoteException { + + try { + //((CustomArtifactFactory)getComponent(ArtifactFactory.class)).customize(); + //((CustomArtifactFactory)getComponent(ProjectArtifactFactory.class)).customize(); + //((CustomArtifactResolver)getComponent(ArtifactResolver.class)).customize(workspaceMap, failOnUnresolvedDependency); + //((CustomRepositoryMetadataManager)getComponent(RepositoryMetadataManager.class)).customize(workspaceMap); + //((CustomMaven3WagonManager)getComponent(WagonManager.class)).customize(failOnUnresolvedDependency); + + setConsoleAndIndicator(console, indicator); + } + catch (Exception e) { + throw rethrowException(e); + } + } + + private void setConsoleAndIndicator(MavenServerConsole console, MavenServerProgressIndicator indicator) { + myConsoleWrapper.setWrappee(console); + myCurrentIndicator = indicator; } @NotNull @Override public MavenServerExecutionResult resolveProject(@NotNull File file, @NotNull Collection activeProfiles) throws RemoteException, MavenServerProcessCanceledException { - throw new UnsupportedOperationException(); + DependencyTreeResolutionListener listener = new DependencyTreeResolutionListener(myConsoleWrapper); + + MavenExecutionResult result = doResolveProject(file, + new ArrayList(activeProfiles), + Arrays.asList(listener)); + return createExecutionResult(file, result, listener.getRootNode()); + } + + private static void setProfilesFromSettings(MavenExecutionRequest request, Settings settings) { + List settingsProfiles = settings.getProfiles(); + + request.setActiveProfiles(settings.getActiveProfiles()); + + if (settingsProfiles != null) { + for (org.apache.maven.settings.Profile rawProfile : settingsProfiles) { + Profile profile = SettingsUtils.convertFromSettingsProfile(rawProfile); + request.addProfile(profile); + } + } + } + + @NotNull + public MavenExecutionResult doResolveProject(@NotNull final File file, + @NotNull final List activeProfiles, + List listeners) { + MavenExecutionRequest request = createRequest(file, activeProfiles, Collections.emptyList(), Collections.emptyList()); + + setProfilesFromSettings(request, myMavenSettings); + + ProjectBuildingRequest config = request.getProjectBuildingRequest(); + + List exceptions = new ArrayList(); + + try { + // copied from DefaultMavenProjectBuilder.buildWithDependencies + ProjectBuilder builder = getComponent(ProjectBuilder.class); + ProjectBuildingResult buildingResult = builder.build(new File(file.getPath()), config); + //builder.calculateConcreteState(project, config, false); + + MavenProject project = buildingResult.getProject(); + + // copied from DefaultLifecycleExecutor.execute + //findExtensions(project); + // end copied from DefaultLifecycleExecutor.execute + + //Artifact projectArtifact = project.getArtifact(); + //Map managedVersions = project.getManagedVersionMap(); + //ArtifactMetadataSource metadataSource = getComponent(ArtifactMetadataSource.class); + project.setDependencyArtifacts(project.createArtifacts(getComponent(ArtifactFactory.class), null, null)); + // + ArtifactResolver resolver = getComponent(ArtifactResolver.class); + + ArtifactResolutionRequest resolutionRequest = new ArtifactResolutionRequest(); + resolutionRequest.setArtifactDependencies(project.getDependencyArtifacts()); + resolutionRequest.setArtifact(project.getArtifact()); + resolutionRequest.setManagedVersionMap(project.getManagedVersionMap()); + resolutionRequest.setLocalRepository(myLocalRepository); + resolutionRequest.setRemoteRepositories(project.getRemoteArtifactRepositories()); + resolutionRequest.setListeners(listeners); + + resolutionRequest.setResolveRoot(false); + resolutionRequest.setResolveTransitively(true); + + ArtifactResolutionResult result = resolver.resolve(resolutionRequest); + + project.setArtifacts(result.getArtifacts()); + // end copied from DefaultMavenProjectBuilder.buildWithDependencies + + return new MavenExecutionResult(project, exceptions); + } + catch (Exception e) { + return handleException(e); + } + + + } + + private MavenExecutionRequest createRequest(File file, List activeProfiles, List inactiveProfiles, List goals) { + //Properties executionProperties = myMavenSettings.getProperties(); + //if (executionProperties == null) { + // executionProperties = new Properties(); + //} + + MavenExecutionRequest result = new DefaultMavenExecutionRequest(); + result.setLocalRepository(myLocalRepository); + result.setGoals(goals); + result.setBaseDirectory(file.getParentFile()); + + + result.setPom(file); + + return result; + } + + private static MavenExecutionResult handleException(Throwable e) { + if (e instanceof RuntimeException) throw (RuntimeException) e; + if (e instanceof Error) throw (Error) e; + + return new MavenExecutionResult(null, Collections.singletonList((Exception) e)); + } + + @NotNull + public File getLocalRepositoryFile() { + return new File(myLocalRepository.getBasedir()); + } + + @NotNull + private MavenServerExecutionResult createExecutionResult(File file, MavenExecutionResult result, DependencyNode rootNode) + throws RemoteException { + Collection problems = MavenProjectProblem.createProblemsList(); + THashSet unresolvedArtifacts = new THashSet(); + + validate(file, result.getExceptions(), problems, unresolvedArtifacts); + + MavenProject mavenProject = result.getMavenProject(); + if (mavenProject == null) return new MavenServerExecutionResult(null, problems, unresolvedArtifacts); + + MavenModel model = MavenModelConverter.convertModel(mavenProject.getModel(), + mavenProject.getCompileSourceRoots(), + mavenProject.getTestCompileSourceRoots(), + mavenProject.getArtifacts(), + (rootNode == null ? Collections.emptyList() : rootNode.getChildren()), + mavenProject.getExtensionArtifacts(), + getLocalRepositoryFile()); + + RemoteNativeMavenProjectHolder holder = new RemoteNativeMavenProjectHolder(mavenProject); + try { + UnicastRemoteObject.exportObject(holder, 0); + } + catch (RemoteException e) { + throw new RuntimeException(e); + } + + Collection activatedProfiles = collectActivatedProfiles(mavenProject); + + MavenServerExecutionResult.ProjectData data = new MavenServerExecutionResult.ProjectData( + model, MavenModelConverter.convertToMap(mavenProject.getModel()), holder, activatedProfiles); + return new MavenServerExecutionResult(data, problems, unresolvedArtifacts); + } + + private static Collection collectActivatedProfiles(MavenProject mavenProject) { + // for some reason project's active profiles do not contain parent's profiles - only local and settings'. + // parent's profiles do not contain settings' profiles. + + List profiles = new ArrayList(); + while (mavenProject != null) { + profiles.addAll(mavenProject.getActiveProfiles()); + mavenProject = mavenProject.getParent(); + } + return collectProfilesIds(profiles); + } + + + private void validate(File file, + Collection exceptions, + Collection problems, + Collection unresolvedArtifacts) throws RemoteException { + for (Exception each : exceptions) { + Maven3ServerGlobals.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(); + ((CustomMaven3WagonManager)getComponent(WagonManager.class)).getUnresolvedCollector().retrieveUnresolvedIds(result); + ((CustomMaven3ArtifactResolver)getComponent(ArtifactResolver.class)).getUnresolvedCollector().retrieveUnresolvedIds(result); + return result; } @NotNull diff --git a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/embedder/MavenExecutionResult.java b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/embedder/MavenExecutionResult.java new file mode 100644 index 000000000000..4908debadea3 --- /dev/null +++ b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/embedder/MavenExecutionResult.java @@ -0,0 +1,44 @@ +/* + * Copyright 2000-2012 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.server.embedder; + +import org.apache.maven.project.MavenProject; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public class MavenExecutionResult { + private final MavenProject myMavenProject; + private final List myExceptions; + + public MavenExecutionResult(@Nullable MavenProject mavenProject, List exceptions) { + myMavenProject = mavenProject; + myExceptions = exceptions; + } + + @Nullable + public MavenProject getMavenProject() { + return myMavenProject; + } + + public List getExceptions() { + return myExceptions; + } + + public boolean hasExceptions() { + return !myExceptions.isEmpty(); + } +} 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 bb46e9d7ab1c..bc3f699db42d 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 @@ -50,6 +50,9 @@ public class MavenIndices { File[] indices = myIndicesDir.listFiles(); if (indices == null) return; Arrays.sort(indices); + + if (Boolean.getBoolean("idea.use.maven3")) return; + for (File each : indices) { if (!each.isDirectory()) continue; 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 ce2793d3d28b..bba769cf3a71 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 @@ -171,6 +171,8 @@ public class MavenIndicesManager { MavenIndices indicesObjectCache = getIndicesObject(); + if (Boolean.getBoolean("idea.use.maven3")) return new ArrayList(result); + try { MavenIndex localIndex = indicesObjectCache.add(LOCAL_REPOSITORY_ID, localRepository.getPath(), MavenIndex.Kind.LOCAL); result.add(localIndex); diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java index 230133baac11..520b68302c0d 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java @@ -222,7 +222,10 @@ public class MavenServerManager extends RemoteObjectWrapper { } } - //params.getVMParametersList().addParametersString("-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5009"); + String mavenEmbedderDebugPort = System.getProperty("idea.maven.embedder.debug.port"); + if (mavenEmbedderDebugPort != null) { + params.getVMParametersList().addParametersString("-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=" + mavenEmbedderDebugPort); + } return params; } @@ -264,15 +267,15 @@ public class MavenServerManager extends RemoteObjectWrapper { classpath.add(new File(pluginFileOrDir.getParent(), "maven3-server-impl")); File luceneLib = new File(PathUtil.getJarPathForClass(Query.class)); - File maven3Lib = new File(luceneLib.getParentFile().getParentFile().getParentFile(), "maven3-server-impl/lib/maven3"); + File maven3Module_Lib = new File(luceneLib.getParentFile().getParentFile().getParentFile(), "maven3-server-impl/lib"); - File maven3Home = new File(maven3Lib, "maven3"); + File maven3Home = new File(maven3Module_Lib, "maven3"); libDir = new File(maven3Home, "lib"); classpath.add(new File(maven3Home, "boot/plexus-classworlds-2.4.jar")); - for (File jar : maven3Lib.listFiles()) { + for (File jar : maven3Module_Lib.listFiles()) { if (jar.isFile() && jar.getName().endsWith(".jar")) { classpath.add(jar); } diff --git a/plugins/ui-designer/jps-plugin/src/org/jetbrains/jps/uiDesigner/model/JpsUiDesignerExtensionService.java b/plugins/ui-designer/jps-plugin/src/org/jetbrains/jps/uiDesigner/model/JpsUiDesignerExtensionService.java index df5f0ac82bc4..1ec6aee21b86 100644 --- a/plugins/ui-designer/jps-plugin/src/org/jetbrains/jps/uiDesigner/model/JpsUiDesignerExtensionService.java +++ b/plugins/ui-designer/jps-plugin/src/org/jetbrains/jps/uiDesigner/model/JpsUiDesignerExtensionService.java @@ -16,5 +16,5 @@ public abstract class JpsUiDesignerExtensionService { @Nullable public abstract JpsUiDesignerConfiguration getUiDesignerConfiguration(@NotNull JpsProject project); - public abstract void setUiDesignerConfiguration(@NotNull JpsProject project, @Nullable JpsUiDesignerConfiguration configuration); + public abstract void setUiDesignerConfiguration(@NotNull JpsProject project, @NotNull JpsUiDesignerConfiguration configuration); } diff --git a/plugins/ui-designer/jps-plugin/src/org/jetbrains/jps/uiDesigner/model/impl/JpsUiDesignerConfigurationSerializer.java b/plugins/ui-designer/jps-plugin/src/org/jetbrains/jps/uiDesigner/model/impl/JpsUiDesignerConfigurationSerializer.java index dcf8f9fbc7f1..cba28c775213 100644 --- a/plugins/ui-designer/jps-plugin/src/org/jetbrains/jps/uiDesigner/model/impl/JpsUiDesignerConfigurationSerializer.java +++ b/plugins/ui-designer/jps-plugin/src/org/jetbrains/jps/uiDesigner/model/impl/JpsUiDesignerConfigurationSerializer.java @@ -22,6 +22,9 @@ public class JpsUiDesignerConfigurationSerializer extends JpsProjectExtensionSer @Override public void loadExtension(@NotNull JpsProject element, @NotNull Element componentTag) { JpsUiDesignerConfigurationImpl.UiDesignerConfigurationState state = XmlSerializer.deserialize(componentTag, JpsUiDesignerConfigurationImpl.UiDesignerConfigurationState.class); + if (state == null) { + state = new JpsUiDesignerConfigurationImpl.UiDesignerConfigurationState(); + } JpsUiDesignerExtensionService.getInstance().setUiDesignerConfiguration(element, new JpsUiDesignerConfigurationImpl(state)); } diff --git a/plugins/ui-designer/jps-plugin/src/org/jetbrains/jps/uiDesigner/model/impl/JpsUiDesignerExtensionServiceImpl.java b/plugins/ui-designer/jps-plugin/src/org/jetbrains/jps/uiDesigner/model/impl/JpsUiDesignerExtensionServiceImpl.java index c39dc9044fdb..9f5a04ad81f8 100644 --- a/plugins/ui-designer/jps-plugin/src/org/jetbrains/jps/uiDesigner/model/impl/JpsUiDesignerExtensionServiceImpl.java +++ b/plugins/ui-designer/jps-plugin/src/org/jetbrains/jps/uiDesigner/model/impl/JpsUiDesignerExtensionServiceImpl.java @@ -17,7 +17,7 @@ public class JpsUiDesignerExtensionServiceImpl extends JpsUiDesignerExtensionSer } @Override - public void setUiDesignerConfiguration(@NotNull JpsProject project, @Nullable JpsUiDesignerConfiguration configuration) { + public void setUiDesignerConfiguration(@NotNull JpsProject project, @NotNull JpsUiDesignerConfiguration configuration) { project.getContainer().setChild(JpsUiDesignerConfigurationImpl.ROLE, configuration); } } diff --git a/xml/dom-impl/src/com/intellij/util/xml/structure/DomStructureViewBuilderProvider.java b/xml/dom-impl/src/com/intellij/util/xml/structure/DomStructureViewBuilderProvider.java index be6d36c02907..88007741d179 100644 --- a/xml/dom-impl/src/com/intellij/util/xml/structure/DomStructureViewBuilderProvider.java +++ b/xml/dom-impl/src/com/intellij/util/xml/structure/DomStructureViewBuilderProvider.java @@ -25,10 +25,12 @@ import com.intellij.util.xml.DomService; import org.jetbrains.annotations.NotNull; /** + * This SHOULD NOT be subclassed! + * * @author Dmitry Avdeev * Date: 6/7/12 */ -public class DomStructureViewBuilderProvider implements XmlStructureViewBuilderProvider { +public final class DomStructureViewBuilderProvider implements XmlStructureViewBuilderProvider { @Override public StructureViewBuilder createStructureViewBuilder(@NotNull XmlFile file) { @@ -38,7 +40,7 @@ public class DomStructureViewBuilderProvider implements XmlStructureViewBuilderP return null; } - protected static final Function DESCRIPTOR = + public static final Function DESCRIPTOR = new Function() { @Override public DomService.StructureViewMode fun(DomElement element) {