From 36011336ef4de26fc65668918b153321d7b385f4 Mon Sep 17 00:00:00 2001 From: irengrig Date: Wed, 16 May 2012 15:04:25 +0400 Subject: [PATCH 01/11] svn tree conflict + merge: exclude from patch files that are not under conflict directory --- .../TreeConflictRefreshablePanel.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/TreeConflictRefreshablePanel.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/TreeConflictRefreshablePanel.java index 96fb7257e0e4..9b2db88feadc 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/TreeConflictRefreshablePanel.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/TreeConflictRefreshablePanel.java @@ -443,6 +443,7 @@ public class TreeConflictRefreshablePanel extends AbstractRefreshablePanel { } final List changesForPatch = CommittedChangesTreeBrowser.collectChanges(lst, true); for (Change change : changesForPatch) { + if (! isUnderOldDir(change, oldFilePath)) continue; ContentRevision before = null; ContentRevision after = null; if (change.getBeforeRevision() != null) { @@ -480,6 +481,22 @@ public class TreeConflictRefreshablePanel extends AbstractRefreshablePanel { }; } + private boolean isUnderOldDir(Change change, FilePath path) { + if (change.getBeforeRevision() != null) { + final boolean isUnder = FileUtil.isAncestor(path.getIOFile(), change.getBeforeRevision().getFile().getIOFile(), true); + if (isUnder) { + return true; + } + } + if (change.getAfterRevision() != null) { + final boolean isUnder = FileUtil.isAncestor(path.getIOFile(), change.getAfterRevision().getFile().getIOFile(), true); + if (isUnder) { + return isUnder; + } + } + return false; + } + private FilePath rebasePath(final FilePath oldBase, final FilePath newBase, final FilePath path) { final String relativePath = FileUtil.getRelativePath(oldBase.getPath(), path.getPath(), File.separatorChar); //if (StringUtil.isEmptyOrSpaces(relativePath)) return path; From c464c17d683fc10fcc5921694de9423e99dc9545 Mon Sep 17 00:00:00 2001 From: irengrig Date: Wed, 16 May 2012 16:02:13 +0400 Subject: [PATCH 02/11] apply patch as system operation: no user confirmation should be asked --- .../openapi/vcs/ProjectLevelVcsManager.java | 2 +- .../diff/impl/patch/formove/PatchApplier.java | 50 +++++++++++++++---- .../vcs/impl/ProjectLevelVcsManagerImpl.java | 2 +- 3 files changed, 42 insertions(+), 12 deletions(-) diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/ProjectLevelVcsManager.java b/platform/vcs-api/src/com/intellij/openapi/vcs/ProjectLevelVcsManager.java index 0803d1f0db21..97dd4a636cef 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/ProjectLevelVcsManager.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/ProjectLevelVcsManager.java @@ -177,7 +177,7 @@ public abstract class ProjectLevelVcsManager { @NotNull public abstract VcsShowConfirmationOption getStandardConfirmation(@NotNull VcsConfiguration.StandardConfirmation option, - @NotNull AbstractVcs vcs); + AbstractVcs vcs); @NotNull public abstract VcsShowSettingOption getOrCreateCustomOption(@NotNull String vcsActionName, diff --git a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/formove/PatchApplier.java b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/formove/PatchApplier.java index 5bd033318867..83de5231313b 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/formove/PatchApplier.java +++ b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/formove/PatchApplier.java @@ -132,6 +132,8 @@ public class PatchApplier { private ApplyPatchStatus myStatus; private final boolean myShowNotification; private final boolean mySystemOperation; + private VcsShowConfirmationOption.Value myAddconfirmationvalue; + private VcsShowConfirmationOption.Value myDeleteconfirmationvalue; public ApplyPatchTask(final boolean showNotification, boolean systemOperation) { super("", Where.AWT); @@ -158,17 +160,22 @@ public class PatchApplier { applyStatus = ApplicationManager.getApplication().runReadAction(new Computable() { public ApplyPatchStatus compute() { final Ref refStatus = new Ref(ApplyPatchStatus.FAILURE); - CommandProcessor.getInstance().executeCommand(myProject, new Runnable() { - public void run() { - if (! createFiles()) { - refStatus.set(ApplyPatchStatus.FAILURE); - return; + try { + setConfirmationToDefault(); + CommandProcessor.getInstance().executeCommand(myProject, new Runnable() { + public void run() { + if (! createFiles()) { + refStatus.set(ApplyPatchStatus.FAILURE); + return; + } + addSkippedItems(trigger); + trigger.prepare(); + refStatus.set(executeWritable()); } - addSkippedItems(trigger); - trigger.prepare(); - refStatus.set(executeWritable()); - } - }, VcsBundle.message("patch.apply.command"), null); + }, VcsBundle.message("patch.apply.command"), null); + } finally { + returnConfirmationBack(); + } return refStatus.get(); } }); @@ -185,6 +192,29 @@ public class PatchApplier { refreshFiles(trigger.getAffected(), context); } + private void returnConfirmationBack() { + if (mySystemOperation) { + final ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(myProject); + final VcsShowConfirmationOption addConfirmation = vcsManager.getStandardConfirmation(VcsConfiguration.StandardConfirmation.ADD, null); + addConfirmation.setValue(myAddconfirmationvalue); + final VcsShowConfirmationOption deleteConfirmation = vcsManager.getStandardConfirmation(VcsConfiguration.StandardConfirmation.REMOVE, null); + deleteConfirmation.setValue(myDeleteconfirmationvalue); + } + } + + private void setConfirmationToDefault() { + if (mySystemOperation) { + final ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(myProject); + final VcsShowConfirmationOption addConfirmation = vcsManager.getStandardConfirmation(VcsConfiguration.StandardConfirmation.ADD, null); + myAddconfirmationvalue = addConfirmation.getValue(); + addConfirmation.setValue(VcsShowConfirmationOption.Value.DO_ACTION_SILENTLY); + + final VcsShowConfirmationOption deleteConfirmation = vcsManager.getStandardConfirmation(VcsConfiguration.StandardConfirmation.REMOVE, null); + myDeleteconfirmationvalue = deleteConfirmation.getValue(); + deleteConfirmation.setValue(VcsShowConfirmationOption.Value.DO_ACTION_SILENTLY); + } + } + public ApplyPatchStatus getStatus() { return myStatus; } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ProjectLevelVcsManagerImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ProjectLevelVcsManagerImpl.java index ccfee33b4a11..1e0b36dfadcf 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ProjectLevelVcsManagerImpl.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ProjectLevelVcsManagerImpl.java @@ -546,7 +546,7 @@ public void addMessageToConsoleWindow(final String message, final TextAttributes @NotNull public VcsShowConfirmationOption getStandardConfirmation(@NotNull VcsConfiguration.StandardConfirmation option, - @NotNull AbstractVcs vcs) { + AbstractVcs vcs) { final VcsShowConfirmationOptionImpl result = getConfirmation(option); result.addApplicableVcs(vcs); return result; From 1711b6570e61543df87594ed5ca651dd0fc87d17 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 16 May 2012 16:07:45 +0400 Subject: [PATCH 03/11] Drop PsiElementArrayConstructor in a favor of ArrayFactory --- .../psi/PsiAnnotationMemberValue.java | 14 ++- .../src/com/intellij/psi/PsiCatchSection.java | 10 +- .../src/com/intellij/psi/PsiExpression.java | 10 +- .../com/intellij/psi/PsiNameValuePair.java | 10 +- .../src/com/intellij/psi/PsiStatement.java | 11 +- .../src/com/intellij/psi/PsiTypeElement.java | 10 +- .../com/intellij/psi/impl/PsiImplUtil.java | 13 +-- .../intellij/psi/impl/source/Constants.java | 110 +----------------- .../psi/impl/source/PsiJavaFileBaseImpl.java | 2 +- .../impl/source/PsiMethodReceiverImpl.java | 4 +- .../psi/impl/source/PsiReferenceListImpl.java | 4 +- .../source/javadoc/PsiDocCommentImpl.java | 12 +- .../impl/source/javadoc/PsiDocTagImpl.java | 22 ++-- .../psi/impl/source/tree/ElementType.java | 8 -- .../java/PsiAnnotationParameterListImpl.java | 4 +- .../PsiArrayInitializerExpressionImpl.java | 11 +- .../PsiArrayInitializerMemberValueImpl.java | 4 +- .../java/PsiDeclarationStatementImpl.java | 5 +- .../tree/java/PsiExpressionListImpl.java | 5 +- .../source/tree/java/PsiInlineDocTagImpl.java | 14 +-- .../tree/java/PsiNewExpressionImpl.java | 9 +- .../tree/java/PsiPolyadicExpressionImpl.java | 13 ++- .../java/PsiReferenceParameterListImpl.java | 11 +- .../source/tree/java/PsiTryStatementImpl.java | 4 +- ...PsiTypeParameterExtendsBoundsListImpl.java | 5 +- .../src/com/intellij/psi/PsiElement.java | 8 ++ .../source/PsiElementArrayConstructor.java | 30 ----- .../intellij/psi/impl/source/PsiFileImpl.java | 3 +- .../impl/source/tree/CompositeElement.java | 33 ++---- .../impl/source/tree/CompositePsiElement.java | 8 +- .../source/tree/LazyParseablePsiElement.java | 6 +- .../source/xml/XmlElementContentSpecImpl.java | 15 +-- 32 files changed, 147 insertions(+), 281 deletions(-) delete mode 100644 platform/core-impl/src/com/intellij/psi/impl/source/PsiElementArrayConstructor.java diff --git a/java/java-psi-api/src/com/intellij/psi/PsiAnnotationMemberValue.java b/java/java-psi-api/src/com/intellij/psi/PsiAnnotationMemberValue.java index 17caaf359852..3ca4506e3105 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiAnnotationMemberValue.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiAnnotationMemberValue.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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,9 +15,10 @@ */ package com.intellij.psi; +import com.intellij.util.ArrayFactory; + /** - * Represents a PSI element which can be used as the value of an annotation - * element. + * Represents a PSI element which can be used as the value of an annotation element. * * @author ven */ @@ -26,4 +27,11 @@ public interface PsiAnnotationMemberValue extends PsiElement { * The empty array of PSI annotation member values which can be reused to avoid unnecessary allocations. */ PsiAnnotationMemberValue[] EMPTY_ARRAY = new PsiAnnotationMemberValue[0]; + + ArrayFactory ARRAY_FACTORY = new ArrayFactory() { + @Override + public PsiAnnotationMemberValue[] create(final int count) { + return count == 0 ? PsiAnnotationMemberValue.EMPTY_ARRAY : new PsiAnnotationMemberValue[count]; + } + }; } diff --git a/java/java-psi-api/src/com/intellij/psi/PsiCatchSection.java b/java/java-psi-api/src/com/intellij/psi/PsiCatchSection.java index 18e882353c91..2bcf3c155def 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiCatchSection.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiCatchSection.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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,6 +15,7 @@ */ package com.intellij.psi; +import com.intellij.util.ArrayFactory; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -31,6 +32,13 @@ public interface PsiCatchSection extends PsiElement { */ PsiCatchSection[] EMPTY_ARRAY = new PsiCatchSection[0]; + ArrayFactory ARRAY_FACTORY = new ArrayFactory() { + @Override + public PsiCatchSection[] create(final int count) { + return count == 0 ? PsiCatchSection.EMPTY_ARRAY : new PsiCatchSection[count]; + } + }; + /** * Returns the variable in which the caught exception is captured. * diff --git a/java/java-psi-api/src/com/intellij/psi/PsiExpression.java b/java/java-psi-api/src/com/intellij/psi/PsiExpression.java index 41b4928f0e09..54233636f654 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiExpression.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiExpression.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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,6 +15,7 @@ */ package com.intellij.psi; +import com.intellij.util.ArrayFactory; import com.intellij.util.Function; import com.intellij.util.NullableFunction; import org.jetbrains.annotations.Nullable; @@ -28,6 +29,13 @@ public interface PsiExpression extends PsiAnnotationMemberValue { */ PsiExpression[] EMPTY_ARRAY = new PsiExpression[0]; + ArrayFactory ARRAY_FACTORY = new ArrayFactory() { + @Override + public PsiExpression[] create(final int count) { + return count == 0 ? PsiExpression.EMPTY_ARRAY : new PsiExpression[count]; + } + }; + Function EXPRESSION_TO_TYPE = new NullableFunction() { @Override public PsiType fun(final PsiExpression expression) { diff --git a/java/java-psi-api/src/com/intellij/psi/PsiNameValuePair.java b/java/java-psi-api/src/com/intellij/psi/PsiNameValuePair.java index e7198c61ac72..b694a8639065 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiNameValuePair.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiNameValuePair.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. @@ -15,6 +15,7 @@ */ package com.intellij.psi; +import com.intellij.util.ArrayFactory; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -32,6 +33,13 @@ public interface PsiNameValuePair extends PsiElement { */ PsiNameValuePair[] EMPTY_ARRAY = new PsiNameValuePair[0]; + ArrayFactory ARRAY_FACTORY = new ArrayFactory() { + @Override + public PsiNameValuePair[] create(final int count) { + return count == 0 ? PsiNameValuePair.EMPTY_ARRAY : new PsiNameValuePair[count]; + } + }; + /** * Returns the identifier specifying the name of the element. * diff --git a/java/java-psi-api/src/com/intellij/psi/PsiStatement.java b/java/java-psi-api/src/com/intellij/psi/PsiStatement.java index 4488cbb67174..fcd2ea2c5aa2 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiStatement.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiStatement.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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,6 +15,8 @@ */ package com.intellij.psi; +import com.intellij.util.ArrayFactory; + /** * Represents a Java statement. */ @@ -23,4 +25,11 @@ public interface PsiStatement extends PsiElement { * The empty array of PSI statements which can be reused to avoid unnecessary allocations. */ PsiStatement[] EMPTY_ARRAY = new PsiStatement[0]; + + ArrayFactory ARRAY_FACTORY = new ArrayFactory() { + @Override + public PsiStatement[] create(final int count) { + return count == 0 ? PsiStatement.EMPTY_ARRAY : new PsiStatement[count]; + } + }; } diff --git a/java/java-psi-api/src/com/intellij/psi/PsiTypeElement.java b/java/java-psi-api/src/com/intellij/psi/PsiTypeElement.java index ff0f7fecbbcd..57e5381f6550 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiTypeElement.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiTypeElement.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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,6 +15,7 @@ */ package com.intellij.psi; +import com.intellij.util.ArrayFactory; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -28,6 +29,13 @@ public interface PsiTypeElement extends PsiElement,PsiAnnotationOwner { */ PsiTypeElement[] EMPTY_ARRAY = new PsiTypeElement[0]; + ArrayFactory ARRAY_FACTORY = new ArrayFactory() { + @Override + public PsiTypeElement[] create(final int count) { + return count == 0 ? EMPTY_ARRAY : new PsiTypeElement[count]; + } + }; + /** * Returns the type referenced by the type element. * 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 4849ba75312c..221db4d7c18b 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 @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -24,7 +24,6 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.filters.ElementFilter; import com.intellij.psi.impl.light.LightClassReference; -import com.intellij.psi.impl.source.Constants; import com.intellij.psi.impl.source.PsiClassReferenceType; import com.intellij.psi.impl.source.PsiImmediateClassType; import com.intellij.psi.impl.source.tree.CompositeElement; @@ -493,10 +492,10 @@ public class PsiImplUtil { @Nullable public static ASTNode findStatementChild(CompositePsiElement statement) { - if (DebugUtil.CHECK_INSIDE_ATOMIC_ACTION_ENABLED){ + if (DebugUtil.CHECK_INSIDE_ATOMIC_ACTION_ENABLED) { ApplicationManager.getApplication().assertReadAccessAllowed(); } - for(ASTNode element = statement.getFirstChildNode(); element != null; element = element.getTreeNext()){ + for (ASTNode element = statement.getFirstChildNode(); element != null; element = element.getTreeNext()) { if (element.getPsi() instanceof PsiStatement) return element; } return null; @@ -512,10 +511,8 @@ public class PsiImplUtil { } } - PsiStatement[] result = Constants.PSI_STATEMENT_ARRAY_CONSTRUCTOR.newPsiElementArray(count); - if (count == 0) { - return result; - } + PsiStatement[] result = PsiStatement.ARRAY_FACTORY.create(count); + if (count == 0) return result; int idx = 0; for (ASTNode child = psiCodeBlock.getFirstChildNode(); child != null && idx < count; child = child.getTreeNext()) { if (child.getPsi() instanceof PsiStatement) { diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/Constants.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/Constants.java index fc2a1c2a6282..573da87cf8e4 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/Constants.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/Constants.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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,119 +15,11 @@ */ package com.intellij.psi.impl.source; -import com.intellij.psi.*; import com.intellij.psi.impl.source.tree.ElementType; import com.intellij.psi.impl.source.tree.JavaElementType; import com.intellij.psi.tree.TokenSet; public interface Constants extends ElementType { - - PsiElementArrayConstructor PSI_CLASS_ARRAY_CONSTRUCTOR = new PsiElementArrayConstructor() { - @Override - public PsiClass[] newPsiElementArray(int length) { - return length == 0 ? PsiClass.EMPTY_ARRAY : new PsiClass[length]; - } - }; - - PsiElementArrayConstructor PSI_FIELD_ARRAY_CONSTRUCTOR = new PsiElementArrayConstructor() { - @Override - public PsiField[] newPsiElementArray(int length) { - return length == 0 ? PsiField.EMPTY_ARRAY : new PsiField[length]; - } - }; - - PsiElementArrayConstructor PSI_METHOD_ARRAY_CONSTRUCTOR = new PsiElementArrayConstructor() { - @Override - public PsiMethod[] newPsiElementArray(int length) { - return length == 0 ? PsiMethod.EMPTY_ARRAY : new PsiMethod[length]; - } - }; - - PsiElementArrayConstructor PSI_CLASS_INITIALIZER_ARRAY_CONSTRUCTOR = new PsiElementArrayConstructor() { - @Override - public PsiClassInitializer[] newPsiElementArray(int length) { - return length == 0 ? PsiClassInitializer.EMPTY_ARRAY : new PsiClassInitializer[length]; - } - }; - - PsiElementArrayConstructor PSI_PARAMETER_ARRAY_CONSTRUCTOR = new PsiElementArrayConstructor() { - @Override - public PsiParameter[] newPsiElementArray(int length) { - return length == 0 ? PsiParameter.EMPTY_ARRAY : new PsiParameter[length]; - } - }; - - PsiElementArrayConstructor PSI_CATCH_SECTION_ARRAYS_CONSTRUCTOR = new PsiElementArrayConstructor() { - @Override - public PsiCatchSection[] newPsiElementArray(int length) { - return length == 0 ? PsiCatchSection.EMPTY_ARRAY : new PsiCatchSection[length]; - } - }; - - PsiElementArrayConstructor PSI_REFERENCE_ELEMENT_ARRAY_CONSTRUCTOR = new PsiElementArrayConstructor() { - @Override - public PsiJavaCodeReferenceElement[] newPsiElementArray(int length) { - return length == 0 ? PsiJavaCodeReferenceElement.EMPTY_ARRAY : new PsiJavaCodeReferenceElement[length]; - } - }; - - PsiElementArrayConstructor PSI_STATEMENT_ARRAY_CONSTRUCTOR = new PsiElementArrayConstructor() { - @Override - public PsiStatement[] newPsiElementArray(int length) { - return length == 0 ? PsiStatement.EMPTY_ARRAY : new PsiStatement[length]; - } - }; - - PsiElementArrayConstructor PSI_EXPRESSION_ARRAY_CONSTRUCTOR = new PsiElementArrayConstructor() { - @Override - public PsiExpression[] newPsiElementArray(int length) { - return length == 0 ? PsiExpression.EMPTY_ARRAY : new PsiExpression[length]; - } - }; - - PsiElementArrayConstructor PSI_IMPORT_STATEMENT_ARRAY_CONSTRUCTOR = new PsiElementArrayConstructor() { - @Override - public PsiImportStatement[] newPsiElementArray(int length) { - return length == 0 ? PsiImportStatement.EMPTY_ARRAY : new PsiImportStatement[length]; - } - }; - - PsiElementArrayConstructor PSI_IMPORT_STATIC_STATEMENT_ARRAY_CONSTRUCTOR = new PsiElementArrayConstructor() { - @Override - public PsiImportStaticStatement[] newPsiElementArray(int length) { - return length == 0 ? PsiImportStaticStatement.EMPTY_ARRAY : new PsiImportStaticStatement[length]; - } - }; - - - PsiElementArrayConstructor PSI_IMPORT_STATEMENT_BASE_ARRAY_CONSTRUCTOR = new PsiElementArrayConstructor() { - @Override - public PsiImportStatementBase[] newPsiElementArray(int length) { - return length == 0 ? PsiImportStatementBase.EMPTY_ARRAY : new PsiImportStatementBase[length]; - } - }; - - PsiElementArrayConstructor PSI_ANNOTATION_MEMBER_VALUE_ARRAY_CONSTRUCTOR = new PsiElementArrayConstructor() { - @Override - public PsiAnnotationMemberValue[] newPsiElementArray(int length) { - return length == 0 ? PsiAnnotationMemberValue.EMPTY_ARRAY : new PsiAnnotationMemberValue[length]; - } - }; - - PsiElementArrayConstructor PSI_NAME_VALUE_PAIR_ARRAY_CONSTRUCTOR = new PsiElementArrayConstructor() { - @Override - public PsiNameValuePair[] newPsiElementArray(int length) { - return length == 0 ? PsiNameValuePair.EMPTY_ARRAY : new PsiNameValuePair[length]; - } - }; - - PsiElementArrayConstructor PSI_ANNOTATION_ARRAY_CONSTRUCTOR = new PsiElementArrayConstructor() { - @Override - public PsiAnnotation[] newPsiElementArray(int length) { - return length == 0 ? PsiAnnotation.EMPTY_ARRAY : new PsiAnnotation[length]; - } - }; - TokenSet CLASS_BIT_SET = TokenSet.create(JavaElementType.CLASS, JavaElementType.ANONYMOUS_CLASS, JavaElementType.ENUM_CONSTANT_INITIALIZER); TokenSet FIELD_BIT_SET = TokenSet.create(JavaElementType.FIELD, JavaElementType.ENUM_CONSTANT); TokenSet METHOD_BIT_SET = TokenSet.create(JavaElementType.METHOD, JavaElementType.ANNOTATION_METHOD); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaFileBaseImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaFileBaseImpl.java index 337f9e6a9a46..9ea434fa27f4 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaFileBaseImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaFileBaseImpl.java @@ -89,7 +89,7 @@ public abstract class PsiJavaFileBaseImpl extends PsiFileImpl implements PsiJava return stub.getChildrenByType(JavaStubElementTypes.CLASS, PsiClass.ARRAY_FACTORY); } - return calcTreeElement().getChildrenAsPsiElements(Constants.CLASS_BIT_SET, Constants.PSI_CLASS_ARRAY_CONSTRUCTOR); + return calcTreeElement().getChildrenAsPsiElements(Constants.CLASS_BIT_SET, PsiClass.ARRAY_FACTORY); } @Override diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiMethodReceiverImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiMethodReceiverImpl.java index 166e157a4fb6..af79860a43a7 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiMethodReceiverImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiMethodReceiverImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -46,7 +46,7 @@ public class PsiMethodReceiverImpl extends CompositePsiElement implements PsiMet @Override @NotNull public PsiAnnotation[] getAnnotations() { - return getChildrenAsPsiElements(ElementType.ANNOTATIONS, Constants.PSI_ANNOTATION_ARRAY_CONSTRUCTOR); + return getChildrenAsPsiElements(ElementType.ANNOTATIONS, PsiAnnotation.ARRAY_FACTORY); } @Override diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiReferenceListImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiReferenceListImpl.java index d4fa48c809fc..2eff5acd41ed 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiReferenceListImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiReferenceListImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -40,7 +40,7 @@ public final class PsiReferenceListImpl extends JavaStubPsiElement PSI_TAG_ARRAY_CONSTRUCTOR = new PsiElementArrayConstructor() { + private static final ArrayFactory ARRAY_FACTORY = new ArrayFactory() { @Override - public PsiDocTag[] newPsiElementArray(int length) { - return length == 0 ? PsiDocTag.EMPTY_ARRAY : new PsiDocTag[length]; + public PsiDocTag[] create(final int count) { + return count == 0 ? PsiDocTag.EMPTY_ARRAY : new PsiDocTag[count]; } }; @@ -86,7 +86,7 @@ public class PsiDocCommentImpl extends LazyParseablePsiElement implements PsiDoc @Override @NotNull public PsiDocTag[] getTags() { - return getChildrenAsPsiElements(TAG_BIT_SET, PSI_TAG_ARRAY_CONSTRUCTOR); + return getChildrenAsPsiElements(TAG_BIT_SET, ARRAY_FACTORY); } @Override diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocTagImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocTagImpl.java index d6bc8d3774a3..ae89a54207ee 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocTagImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocTagImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -21,9 +21,8 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.PsiReference; import com.intellij.psi.impl.PsiImplUtil; -import com.intellij.psi.impl.source.SourceTreeToPsiMap; import com.intellij.psi.impl.source.Constants; -import com.intellij.psi.impl.source.PsiElementArrayConstructor; +import com.intellij.psi.impl.source.SourceTreeToPsiMap; import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry; import com.intellij.psi.impl.source.tree.ChildRole; import com.intellij.psi.impl.source.tree.CompositePsiElement; @@ -31,23 +30,16 @@ import com.intellij.psi.impl.source.tree.JavaDocElementType; import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.psi.javadoc.PsiDocTag; import com.intellij.psi.javadoc.PsiDocTagValue; +import com.intellij.psi.tree.ChildRoleBase; import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; -import com.intellij.psi.tree.ChildRoleBase; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; public class PsiDocTagImpl extends CompositePsiElement implements PsiDocTag, Constants { - - private static final TokenSet VALUE_BIT_SET = TokenSet.create(new IElementType[]{ - JAVA_CODE_REFERENCE, - DOC_TAG_VALUE_TOKEN, - DOC_METHOD_OR_FIELD_REF, - DOC_PARAMETER_REF, - DOC_COMMENT_DATA, - DOC_INLINE_TAG, - DOC_REFERENCE_HOLDER - }); + private static final TokenSet VALUE_BIT_SET = TokenSet.create( + JAVA_CODE_REFERENCE, DOC_TAG_VALUE_TOKEN, DOC_METHOD_OR_FIELD_REF, DOC_PARAMETER_REF, + DOC_COMMENT_DATA, DOC_INLINE_TAG, DOC_REFERENCE_HOLDER); public PsiDocTagImpl() { super(DOC_TAG); @@ -70,7 +62,7 @@ public class PsiDocTagImpl extends CompositePsiElement implements PsiDocTag, Con @Override public PsiElement[] getDataElements() { - return getChildrenAsPsiElements(VALUE_BIT_SET, PsiElementArrayConstructor.PSI_ELEMENT_ARRAY_CONSTRUCTOR); + return getChildrenAsPsiElements(VALUE_BIT_SET, PsiElement.ARRAY_FACTORY); } @Override diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/ElementType.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/ElementType.java index 50646ca8f3ca..48b07d17942c 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/ElementType.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/ElementType.java @@ -17,8 +17,6 @@ package com.intellij.psi.impl.source.tree; import com.intellij.psi.JavaDocTokenType; import com.intellij.psi.JavaTokenType; -import com.intellij.psi.PsiTypeElement; -import com.intellij.psi.impl.source.PsiElementArrayConstructor; import com.intellij.psi.tree.TokenSet; public interface ElementType extends JavaTokenType, JavaDocTokenType, JavaElementType, JavaDocElementType { @@ -76,12 +74,6 @@ public interface ElementType extends JavaTokenType, JavaDocTokenType, JavaElemen ); TokenSet TYPES_BIT_SET = TokenSet.create(TYPE); - PsiElementArrayConstructor PSI_TYPE_ELEMENT_ARRAY_CONSTRUCTOR = new PsiElementArrayConstructor() { - @Override - public PsiTypeElement[] newPsiElementArray(int length) { - return length > 0 ? new PsiTypeElement[length] : PsiTypeElement.EMPTY_ARRAY; - } - }; TokenSet IMPORT_STATEMENT_BIT_SET = TokenSet.create(IMPORT_STATEMENT); TokenSet IMPORT_STATIC_STATEMENT_BIT_SET = TokenSet.create(IMPORT_STATIC_STATEMENT); TokenSet IMPORT_STATEMENT_BASE_BIT_SET = TokenSet.create(IMPORT_STATEMENT, IMPORT_STATIC_STATEMENT); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiAnnotationParameterListImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiAnnotationParameterListImpl.java index 1a46f91eb025..7d8225059711 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiAnnotationParameterListImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiAnnotationParameterListImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -47,7 +47,7 @@ public class PsiAnnotationParameterListImpl extends PsiCommaSeparatedListImpl im public PsiNameValuePair[] getAttributes() { PsiNameValuePair[] cachedMembers = myCachedMembers; if (cachedMembers == null) { - myCachedMembers = cachedMembers = getChildrenAsPsiElements(NAME_VALUE_PAIR_BIT_SET, PSI_NAME_VALUE_PAIR_ARRAY_CONSTRUCTOR); + myCachedMembers = cachedMembers = getChildrenAsPsiElements(NAME_VALUE_PAIR_BIT_SET, PsiNameValuePair.ARRAY_FACTORY); } return cachedMembers; diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiArrayInitializerExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiArrayInitializerExpressionImpl.java index 7fb4f275a316..4e2300fcf687 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiArrayInitializerExpressionImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiArrayInitializerExpressionImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -35,7 +35,7 @@ public class PsiArrayInitializerExpressionImpl extends ExpressionPsiElement impl @Override @NotNull public PsiExpression[] getInitializers(){ - return getChildrenAsPsiElements(EXPRESSION_BIT_SET, PSI_EXPRESSION_ARRAY_CONSTRUCTOR); + return getChildrenAsPsiElements(EXPRESSION_BIT_SET, PsiExpression.ARRAY_FACTORY); } @Override @@ -128,16 +128,15 @@ public class PsiArrayInitializerExpressionImpl extends ExpressionPsiElement impl if (ElementType.EXPRESSION_BIT_SET.contains(first.getElementType())) { final CharTable charTab = SharedImplUtil.findCharTableByTree(this); - ASTNode element = first; - for (ASTNode child = element.getTreeNext(); child != null; child = child.getTreeNext()) { + for (ASTNode child = first.getTreeNext(); child != null; child = child.getTreeNext()) { if (child.getElementType() == COMMA) break; if (ElementType.EXPRESSION_BIT_SET.contains(child.getElementType())) { TreeElement comma = Factory.createSingleLeafElement(COMMA, ",", 0, 1, charTab, getManager()); - super.addInternal(comma, comma, element, Boolean.FALSE); + super.addInternal(comma, comma, first, Boolean.FALSE); break; } } - for (ASTNode child = element.getTreePrev(); child != null; child = child.getTreePrev()) { + for (ASTNode child = first.getTreePrev(); child != null; child = child.getTreePrev()) { if (child.getElementType() == COMMA) break; if (ElementType.EXPRESSION_BIT_SET.contains(child.getElementType())) { TreeElement comma = Factory.createSingleLeafElement(COMMA, ",", 0, 1, charTab, getManager()); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiArrayInitializerMemberValueImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiArrayInitializerMemberValueImpl.java index 2d36cac53b22..dd64ed7e41fb 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiArrayInitializerMemberValueImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiArrayInitializerMemberValueImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -38,7 +38,7 @@ public class PsiArrayInitializerMemberValueImpl extends PsiCommaSeparatedListImp @Override @NotNull public PsiAnnotationMemberValue[] getInitializers() { - return getChildrenAsPsiElements(ANNOTATION_MEMBER_VALUE_BIT_SET, PSI_ANNOTATION_MEMBER_VALUE_ARRAY_CONSTRUCTOR); + return getChildrenAsPsiElements(ANNOTATION_MEMBER_VALUE_BIT_SET, PsiAnnotationMemberValue.ARRAY_FACTORY); } @Override diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiDeclarationStatementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiDeclarationStatementImpl.java index 8bacb1a19e3c..9186dd042753 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiDeclarationStatementImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiDeclarationStatementImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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,7 +17,6 @@ package com.intellij.psi.impl.source.tree.java; import com.intellij.lang.ASTNode; import com.intellij.psi.*; -import com.intellij.psi.impl.source.PsiElementArrayConstructor; import com.intellij.psi.impl.source.SourceTreeToPsiMap; import com.intellij.psi.impl.source.tree.*; import com.intellij.psi.scope.ElementClassHint; @@ -33,7 +32,7 @@ public class PsiDeclarationStatementImpl extends CompositePsiElement implements @Override @NotNull public PsiElement[] getDeclaredElements() { - return getChildrenAsPsiElements(DECLARED_ELEMENT_BIT_SET, PsiElementArrayConstructor.PSI_ELEMENT_ARRAY_CONSTRUCTOR); + return getChildrenAsPsiElements(DECLARED_ELEMENT_BIT_SET, PsiElement.ARRAY_FACTORY); } private static final TokenSet DECLARED_ELEMENT_BIT_SET = TokenSet.create(JavaElementType.LOCAL_VARIABLE, JavaElementType.CLASS); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiExpressionListImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiExpressionListImpl.java index 0d29bb84d92f..9f0f4a597aab 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiExpressionListImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiExpressionListImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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,7 +19,6 @@ import com.intellij.lang.ASTNode; import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.*; import com.intellij.psi.impl.PsiImplUtil; -import com.intellij.psi.impl.source.Constants; import com.intellij.psi.impl.source.tree.*; import com.intellij.psi.tree.ChildRoleBase; import com.intellij.psi.tree.IElementType; @@ -36,7 +35,7 @@ public class PsiExpressionListImpl extends CompositePsiElement implements PsiExp @Override @NotNull public PsiExpression[] getExpressions() { - return getChildrenAsPsiElements(ElementType.EXPRESSION_BIT_SET, Constants.PSI_EXPRESSION_ARRAY_CONSTRUCTOR); + return getChildrenAsPsiElements(ElementType.EXPRESSION_BIT_SET, PsiExpression.ARRAY_FACTORY); } @Override diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiInlineDocTagImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiInlineDocTagImpl.java index fe3a08ac5e0d..5e6e534a1f78 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiInlineDocTagImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiInlineDocTagImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -21,26 +21,26 @@ import com.intellij.psi.JavaElementVisitor; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.impl.PsiImplUtil; -import com.intellij.psi.impl.source.SourceTreeToPsiMap; import com.intellij.psi.impl.source.Constants; -import com.intellij.psi.impl.source.PsiElementArrayConstructor; +import com.intellij.psi.impl.source.SourceTreeToPsiMap; import com.intellij.psi.impl.source.tree.ChildRole; import com.intellij.psi.impl.source.tree.CompositePsiElement; import com.intellij.psi.impl.source.tree.JavaDocElementType; import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.psi.javadoc.PsiDocTagValue; import com.intellij.psi.javadoc.PsiInlineDocTag; +import com.intellij.psi.tree.ChildRoleBase; import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; -import com.intellij.psi.tree.ChildRoleBase; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; public class PsiInlineDocTagImpl extends CompositePsiElement implements PsiInlineDocTag, Constants { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.PsiInlineDocTagImpl"); - private static final TokenSet VALUE_BIT_SET = TokenSet.create(JAVA_CODE_REFERENCE, DOC_TAG_VALUE_TOKEN, DOC_METHOD_OR_FIELD_REF, - DOC_COMMENT_DATA, DOC_INLINE_TAG, DOC_REFERENCE_HOLDER, WHITE_SPACE, DOC_COMMENT_BAD_CHARACTER); + private static final TokenSet VALUE_BIT_SET = TokenSet.create( + JAVA_CODE_REFERENCE, DOC_TAG_VALUE_TOKEN, DOC_METHOD_OR_FIELD_REF, DOC_COMMENT_DATA, DOC_INLINE_TAG, + DOC_REFERENCE_HOLDER, WHITE_SPACE, DOC_COMMENT_BAD_CHARACTER); public PsiInlineDocTagImpl() { super(DOC_INLINE_TAG); @@ -62,7 +62,7 @@ public class PsiInlineDocTagImpl extends CompositePsiElement implements PsiInlin @Override public PsiElement[] getDataElements() { - return getChildrenAsPsiElements(VALUE_BIT_SET, PsiElementArrayConstructor.PSI_ELEMENT_ARRAY_CONSTRUCTOR); + return getChildrenAsPsiElements(VALUE_BIT_SET, PsiElement.ARRAY_FACTORY); } @Override diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiNewExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiNewExpressionImpl.java index 26e571a01554..33d55ed03d56 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiNewExpressionImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiNewExpressionImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -20,7 +20,6 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; import com.intellij.psi.impl.PsiImplUtil; -import com.intellij.psi.impl.source.Constants; import com.intellij.psi.impl.source.PsiClassReferenceType; import com.intellij.psi.impl.source.SourceTreeToPsiMap; import com.intellij.psi.impl.source.resolve.reference.impl.PsiPolyVariantCachingReference; @@ -93,12 +92,12 @@ public class PsiNewExpressionImpl extends ExpressionPsiElement implements PsiNew @Override @NotNull public PsiExpression[] getArrayDimensions() { - PsiExpression[] expressions = getChildrenAsPsiElements(ElementType.ARRAY_DIMENSION_BIT_SET, Constants.PSI_EXPRESSION_ARRAY_CONSTRUCTOR); + PsiExpression[] expressions = getChildrenAsPsiElements(ElementType.ARRAY_DIMENSION_BIT_SET, PsiExpression.ARRAY_FACTORY); PsiExpression qualifier = getQualifier(); - if (qualifier == null){ + if (qualifier == null) { return expressions; } - else{ + else { LOG.assertTrue(expressions[0] == qualifier); PsiExpression[] expressions1 = new PsiExpression[expressions.length - 1]; System.arraycopy(expressions, 1, expressions1, 0, expressions1.length); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiPolyadicExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiPolyadicExpressionImpl.java index 94a4f2a36863..d5a22919b586 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiPolyadicExpressionImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiPolyadicExpressionImpl.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. @@ -18,7 +18,6 @@ package com.intellij.psi.impl.source.tree.java; import com.intellij.lang.ASTNode; import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.*; -import com.intellij.psi.impl.source.Constants; import com.intellij.psi.impl.source.resolve.JavaResolveCache; import com.intellij.psi.impl.source.tree.ChildRole; import com.intellij.psi.impl.source.tree.ElementType; @@ -28,7 +27,9 @@ import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; import com.intellij.psi.util.TypeConversionUtil; import com.intellij.util.Function; +import com.intellij.util.NullableFunction; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public class PsiPolyadicExpressionImpl extends ExpressionPsiElement implements PsiPolyadicExpression { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.PsiPolyadicExpressionImpl"); @@ -57,13 +58,15 @@ public class PsiPolyadicExpressionImpl extends ExpressionPsiElement implements P public PsiType getType() { return JavaResolveCache.getInstance(getProject()).getType(this, MY_TYPE_EVALUATOR); } - private static final Function MY_TYPE_EVALUATOR = new Function() { + + private static final Function MY_TYPE_EVALUATOR = new NullableFunction() { @Override public PsiType fun(PsiPolyadicExpressionImpl expression) { return doGetType(expression); } }; + @Nullable private static PsiType doGetType(PsiPolyadicExpressionImpl param) { PsiExpression[] operands = param.getOperands(); PsiType lType = null; @@ -80,7 +83,6 @@ public class PsiPolyadicExpressionImpl extends ExpressionPsiElement implements P return lType; } - @Override public ASTNode findChildByRole(int role) { LOG.assertTrue(ChildRole.isUnique(role)); @@ -124,7 +126,7 @@ public class PsiPolyadicExpressionImpl extends ExpressionPsiElement implements P public PsiExpression[] getOperands() { PsiExpression[] operands = cachedOperands; if (operands == null) { - cachedOperands = operands = getChildrenAsPsiElements(ElementType.EXPRESSION_BIT_SET, Constants.PSI_EXPRESSION_ARRAY_CONSTRUCTOR); + cachedOperands = operands = getChildrenAsPsiElements(ElementType.EXPRESSION_BIT_SET, PsiExpression.ARRAY_FACTORY); } return operands; } @@ -140,4 +142,3 @@ public class PsiPolyadicExpressionImpl extends ExpressionPsiElement implements P return "PsiPolyadicExpression: " + getText(); } } - diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceParameterListImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceParameterListImpl.java index 73d23b7faf06..0cdbf5c21e5a 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceParameterListImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceParameterListImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -38,7 +38,7 @@ public class PsiReferenceParameterListImpl extends CompositePsiElement implement @Override @NotNull public PsiTypeElement[] getTypeParameterElements() { - return getChildrenAsPsiElements(ElementType.TYPES_BIT_SET, ElementType.PSI_TYPE_ELEMENT_ARRAY_CONSTRUCTOR); + return getChildrenAsPsiElements(ElementType.TYPES_BIT_SET, PsiTypeElement.ARRAY_FACTORY); } @Override @@ -125,16 +125,15 @@ public class PsiReferenceParameterListImpl extends CompositePsiElement implement final TreeElement firstAdded = super.addInternal(first, last, anchor, before); if (first == last && first.getElementType() == JavaElementType.TYPE){ - ASTNode element = first; - for(ASTNode child = element.getTreeNext(); child != null; child = child.getTreeNext()){ + for(ASTNode child = first.getTreeNext(); child != null; child = child.getTreeNext()){ if (child.getElementType() == JavaTokenType.COMMA) break; if (child.getElementType() == JavaElementType.TYPE){ TreeElement comma = Factory.createSingleLeafElement(JavaTokenType.COMMA, ",", 0, 1, treeCharTab, getManager()); - super.addInternal(comma, comma, element, Boolean.FALSE); + super.addInternal(comma, comma, first, Boolean.FALSE); break; } } - for(ASTNode child = element.getTreePrev(); child != null; child = child.getTreePrev()){ + for(ASTNode child = first.getTreePrev(); child != null; child = child.getTreePrev()){ if (child.getElementType() == JavaTokenType.COMMA) break; if (child.getElementType() == JavaElementType.TYPE){ TreeElement comma = Factory.createSingleLeafElement(JavaTokenType.COMMA, ",", 0, 1, treeCharTab, getManager()); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiTryStatementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiTryStatementImpl.java index aee7dc12a9e8..3eefe9108c91 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiTryStatementImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiTryStatementImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -90,7 +90,7 @@ public class PsiTryStatementImpl extends CompositePsiElement implements PsiTrySt @Override @NotNull public PsiCatchSection[] getCatchSections() { - return getChildrenAsPsiElements(CATCH_SECTION_BIT_SET, PSI_CATCH_SECTION_ARRAYS_CONSTRUCTOR); + return getChildrenAsPsiElements(CATCH_SECTION_BIT_SET, PsiCatchSection.ARRAY_FACTORY); } @Override diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiTypeParameterExtendsBoundsListImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiTypeParameterExtendsBoundsListImpl.java index b913706545f3..8d03254b1cf2 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiTypeParameterExtendsBoundsListImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiTypeParameterExtendsBoundsListImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -38,8 +38,7 @@ public class PsiTypeParameterExtendsBoundsListImpl extends JavaStubPsiElement ARRAY_FACTORY = new ArrayFactory() { + @Override + public PsiElement[] create(final int count) { + return count == 0 ? EMPTY_ARRAY : new PsiElement[count]; + } + }; + /** * Returns the project to which the PSI element belongs. * diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/PsiElementArrayConstructor.java b/platform/core-impl/src/com/intellij/psi/impl/source/PsiElementArrayConstructor.java deleted file mode 100644 index c145880d6b5b..000000000000 --- a/platform/core-impl/src/com/intellij/psi/impl/source/PsiElementArrayConstructor.java +++ /dev/null @@ -1,30 +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 com.intellij.psi.impl.source; - -import com.intellij.psi.PsiElement; - -public interface PsiElementArrayConstructor { - PsiElementArrayConstructor PSI_ELEMENT_ARRAY_CONSTRUCTOR = new PsiElementArrayConstructor() { - @Override - public PsiElement[] newPsiElementArray(int length) { - return length == 0 ? PsiElement.EMPTY_ARRAY : new PsiElement[length]; - } - }; - - T[] newPsiElementArray(int length); -} diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java b/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java index 40269892c466..2c05de57807b 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java +++ b/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java @@ -52,6 +52,7 @@ import com.intellij.psi.stubs.*; import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.ILazyParseableElementType; import com.intellij.psi.tree.IStubFileElementType; +import com.intellij.psi.tree.TokenSet; import com.intellij.reference.SoftReference; import com.intellij.testFramework.LightVirtualFile; import com.intellij.util.IncorrectOperationException; @@ -755,7 +756,7 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF @Override @NotNull public PsiElement[] getChildren() { - return calcTreeElement().getChildrenAsPsiElements(null, PsiElementArrayConstructor.PSI_ELEMENT_ARRAY_CONSTRUCTOR); + return calcTreeElement().getChildrenAsPsiElements((TokenSet)null, PsiElement.ARRAY_FACTORY); } @Override diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/tree/CompositeElement.java b/platform/core-impl/src/com/intellij/psi/impl/source/tree/CompositeElement.java index 3f85c9c67ce7..0871c7c67705 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/source/tree/CompositeElement.java +++ b/platform/core-impl/src/com/intellij/psi/impl/source/tree/CompositeElement.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. @@ -420,7 +420,7 @@ public class CompositeElement extends TreeElement { } @Override - public ASTNode[] getChildren(TokenSet filter) { + public ASTNode[] getChildren(@Nullable TokenSet filter) { int count = countChildren(filter); if (count == 0) { return EMPTY_ARRAY; @@ -435,28 +435,8 @@ public class CompositeElement extends TreeElement { return result; } - @NotNull - public T[] getChildrenAsPsiElements(TokenSet filter, PsiElementArrayConstructor constructor) { - ApplicationManager.getApplication().assertReadAccessAllowed(); - int count = countChildren(filter); - T[] result = constructor.newPsiElementArray(count); - if (count == 0) { - return result; - } - int idx = 0; - for (ASTNode child = getFirstChildNode(); child != null && idx < count; child = child.getTreeNext()) { - if (filter == null || filter.contains(child.getElementType())) { - T element = (T)child.getPsi(); - LOG.assertTrue(element != null, child); - result[idx++] = element; - } - } - return result; - } - - @NotNull - public T[] getChildrenAsPsiElements(TokenSet filter, ArrayFactory constructor) { + public T[] getChildrenAsPsiElements(@Nullable TokenSet filter, ArrayFactory constructor) { ApplicationManager.getApplication().assertReadAccessAllowed(); int count = countChildren(filter); T[] result = constructor.create(count); @@ -466,13 +446,14 @@ public class CompositeElement extends TreeElement { int idx = 0; for (ASTNode child = getFirstChildNode(); child != null && idx < count; child = child.getTreeNext()) { if (filter == null || filter.contains(child.getElementType())) { - T element = (T)child.getPsi(); + @SuppressWarnings("unchecked") T element = (T)child.getPsi(); LOG.assertTrue(element != null, child); result[idx++] = element; } } return result; } + @NotNull public T[] getChildrenAsPsiElements(@NotNull IElementType type, ArrayFactory constructor) { ApplicationManager.getApplication().assertReadAccessAllowed(); @@ -484,7 +465,7 @@ public class CompositeElement extends TreeElement { int idx = 0; for (ASTNode child = getFirstChildNode(); child != null && idx < count; child = child.getTreeNext()) { if (type == child.getElementType()) { - T element = (T)child.getPsi(); + @SuppressWarnings("unchecked") T element = (T)child.getPsi(); LOG.assertTrue(element != null, child); result[idx++] = element; } @@ -492,7 +473,7 @@ public class CompositeElement extends TreeElement { return result; } - public int countChildren(TokenSet filter) { + public int countChildren(@Nullable TokenSet filter) { // no lock is needed because all chameleons are expanded already int count = 0; for (ASTNode child = getFirstChildNode(); child != null; child = child.getTreeNext()) { diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/tree/CompositePsiElement.java b/platform/core-impl/src/com/intellij/psi/impl/source/tree/CompositePsiElement.java index cf1132ab2ec5..547ff3614b0c 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/source/tree/CompositePsiElement.java +++ b/platform/core-impl/src/com/intellij/psi/impl/source/tree/CompositePsiElement.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -25,15 +25,15 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.psi.impl.CheckUtil; -import com.intellij.psi.impl.SharedPsiElementImplUtil; import com.intellij.psi.impl.ResolveScopeManager; -import com.intellij.psi.impl.source.PsiElementArrayConstructor; +import com.intellij.psi.impl.SharedPsiElementImplUtil; import com.intellij.psi.impl.source.SourceTreeToPsiMap; import com.intellij.psi.impl.source.codeStyle.CodeEditUtil; import com.intellij.psi.scope.PsiScopeProcessor; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.SearchScope; import com.intellij.psi.tree.IElementType; +import com.intellij.psi.tree.TokenSet; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; @@ -56,7 +56,7 @@ public abstract class CompositePsiElement extends CompositeElement implements Ps @Override @NotNull public PsiElement[] getChildren() { - return getChildrenAsPsiElements(null, PsiElementArrayConstructor.PSI_ELEMENT_ARRAY_CONSTRUCTOR); + return getChildrenAsPsiElements((TokenSet)null, PsiElement.ARRAY_FACTORY); } @Override diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/tree/LazyParseablePsiElement.java b/platform/core-impl/src/com/intellij/psi/impl/source/tree/LazyParseablePsiElement.java index 03744cbb2a4c..3678d8a835ec 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/source/tree/LazyParseablePsiElement.java +++ b/platform/core-impl/src/com/intellij/psi/impl/source/tree/LazyParseablePsiElement.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -30,13 +30,13 @@ import com.intellij.psi.*; import com.intellij.psi.impl.CheckUtil; import com.intellij.psi.impl.ResolveScopeManager; import com.intellij.psi.impl.SharedPsiElementImplUtil; -import com.intellij.psi.impl.source.PsiElementArrayConstructor; import com.intellij.psi.impl.source.SourceTreeToPsiMap; import com.intellij.psi.impl.source.codeStyle.CodeEditUtil; import com.intellij.psi.scope.PsiScopeProcessor; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.SearchScope; import com.intellij.psi.tree.IElementType; +import com.intellij.psi.tree.TokenSet; import com.intellij.util.IncorrectOperationException; import com.intellij.util.ReflectionCache; import org.jetbrains.annotations.NotNull; @@ -64,7 +64,7 @@ public class LazyParseablePsiElement extends LazyParseableElement implements Psi @Override @NotNull public PsiElement[] getChildren() { - return getChildrenAsPsiElements(null, PsiElementArrayConstructor.PSI_ELEMENT_ARRAY_CONSTRUCTOR); + return getChildrenAsPsiElements((TokenSet)null, PsiElement.ARRAY_FACTORY); } @Nullable diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlElementContentSpecImpl.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlElementContentSpecImpl.java index a4c6c7765bb2..c060c4327df7 100644 --- a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlElementContentSpecImpl.java +++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlElementContentSpecImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -20,11 +20,9 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.PsiReference; import com.intellij.psi.XmlElementVisitor; -import com.intellij.psi.impl.source.PsiElementArrayConstructor; import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry; -import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.ChildRoleBase; -import com.intellij.psi.tree.TokenSet; +import com.intellij.psi.tree.IElementType; import com.intellij.psi.xml.XmlChildRole; import com.intellij.psi.xml.XmlElementContentGroup; import com.intellij.psi.xml.XmlElementContentSpec; @@ -35,17 +33,8 @@ import org.jetbrains.annotations.NotNull; * @author Mike */ public class XmlElementContentSpecImpl extends XmlElementImpl implements XmlElementContentSpec, XmlElementType { - private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.xml.XmlElementContentSpecImpl"); - private static final TokenSet GROUPS_FILTER = TokenSet.create(XML_ELEMENT_CONTENT_GROUP); - private static final PsiElementArrayConstructor GROUPS_CONSTRUCTOR = new PsiElementArrayConstructor() { - @Override - public XmlElementContentGroup[] newPsiElementArray(int length) { - return new XmlElementContentGroup[length]; - } - }; - public XmlElementContentSpecImpl() { super(XML_ELEMENT_CONTENT_SPEC); } From 0c55db64e35bd57dde3862d7c6b378fada0f5bbf Mon Sep 17 00:00:00 2001 From: Vassiliy Kudryashov Date: Wed, 16 May 2012 16:09:26 +0400 Subject: [PATCH 04/11] IDEA-86093 The big empty space for "Before launch" should not be visible if nothing can be added with "+" --- .../execution/impl/BeforeRunStepsPanel.java | 72 ++++++++++++++++--- .../ConfigurationSettingsEditorWrapper.form | 9 ++- 2 files changed, 69 insertions(+), 12 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/impl/BeforeRunStepsPanel.java b/platform/lang-impl/src/com/intellij/execution/impl/BeforeRunStepsPanel.java index 29e34c124e0a..0d1e0a76b703 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/BeforeRunStepsPanel.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/BeforeRunStepsPanel.java @@ -39,6 +39,8 @@ import net.miginfocom.swing.MigLayout; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import javax.swing.event.ListDataEvent; +import javax.swing.event.ListDataListener; import java.awt.*; import java.util.ArrayList; import java.util.Collections; @@ -56,6 +58,7 @@ class BeforeRunStepsPanel extends JPanel { private final List originalTasks = new ArrayList(); private StepsBeforeRunListener myListener; + private final JPanel myPanel; BeforeRunStepsPanel(StepsBeforeRunListener listener) { myListener = listener; @@ -64,7 +67,28 @@ class BeforeRunStepsPanel extends JPanel { myList.getEmptyText().setText(ExecutionBundle.message("before.launch.panel.empty")); myList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); myList.setCellRenderer(new MyListCellRenderer()); - ToolbarDecorator myDecorator = ToolbarDecorator.createDecorator(myList).setVisibleRowCount(4); + + myModel.addListDataListener(new ListDataListener() { + @Override + public void intervalAdded(ListDataEvent e) { + adjustVisibleRowCount(); + } + + @Override + public void intervalRemoved(ListDataEvent e) { + adjustVisibleRowCount(); + } + + @Override + public void contentsChanged(ListDataEvent e) { + } + + private void adjustVisibleRowCount() { + myList.setVisibleRowCount(Math.max(4, Math.min(8, myModel.getSize()))); + } + }); + + ToolbarDecorator myDecorator = ToolbarDecorator.createDecorator(myList); if (!SystemInfo.isMac) { myDecorator.setAsTopToolbar(); } @@ -72,7 +96,7 @@ class BeforeRunStepsPanel extends JPanel { @Override public void run(AnActionButton button) { int index = myList.getSelectedIndex(); - if (index ==-1) + if (index == -1) return; Pair> selection = getSelection(); if (selection == null) @@ -97,12 +121,19 @@ class BeforeRunStepsPanel extends JPanel { doAddAction(button); } }); + myDecorator.setAddActionUpdater(new AnActionButtonUpdater() { + @Override + public boolean isEnabled(AnActionEvent e) { + return checkBeforeRunTasksAbility(true); + } + }); myShowSettingsBeforeRunCheckBox = new JCheckBox(ExecutionBundle.message("configuration.edit.before.run")); - setLayout(new MigLayout("fill, ins 0, gap 10")); - add(myShowSettingsBeforeRunCheckBox, "shrinky, wrap"); - add(myDecorator.createPanel(), "grow, push"); + setLayout(new MigLayout("fill, ins 0, gap 10, hidemode 3")); + add(myShowSettingsBeforeRunCheckBox, "shrinky, ay bottom, wrap"); + myPanel = myDecorator.createPanel(); + add(myPanel, "grow, push"); } @Nullable @@ -124,6 +155,8 @@ class BeforeRunStepsPanel extends JPanel { myModel.replaceAll(originalTasks); myShowSettingsBeforeRunCheckBox.setSelected(settings.isEditBeforeRun()); myShowSettingsBeforeRunCheckBox.setEnabled(!(myRunConfiguration instanceof UnknownRunConfiguration)); + + myPanel.setVisible(checkBeforeRunTasksAbility(false)); } public List getTasks(boolean applyCurrentState) { @@ -138,6 +171,26 @@ class BeforeRunStepsPanel extends JPanel { return myShowSettingsBeforeRunCheckBox.isSelected(); } + private boolean checkBeforeRunTasksAbility(boolean checkOnlyAddAction) { + if (myRunConfiguration instanceof UnknownRunConfiguration) { + return false; + } + Set activeProviderKeys = getActiveProviderKeys(); + final BeforeRunTaskProvider[] providers = Extensions.getExtensions(BeforeRunTaskProvider.EXTENSION_POINT_NAME, + myRunConfiguration.getProject()); + for (final BeforeRunTaskProvider provider : providers) { + if (provider.createTask(myRunConfiguration) != null) { + if (!checkOnlyAddAction) { + return true; + } + else if (!provider.isSingleton() || !activeProviderKeys.contains(provider.getId())) { + return true; + } + } + } + return false; + } + void doAddAction(AnActionButton button) { if (myRunConfiguration instanceof UnknownRunConfiguration) { return; @@ -146,16 +199,15 @@ class BeforeRunStepsPanel extends JPanel { final JBPopupFactory popupFactory = JBPopupFactory.getInstance(); final BeforeRunTaskProvider[] providers = Extensions.getExtensions(BeforeRunTaskProvider.EXTENSION_POINT_NAME, myRunConfiguration.getProject()); - final List activeProviderKeys = getActiveProviderKeys(); + Set activeProviderKeys = getActiveProviderKeys(); DefaultActionGroup actionGroup = new DefaultActionGroup(null, false); for (final BeforeRunTaskProvider provider : providers) { - String providerName = provider.getName(); if (provider.createTask(myRunConfiguration) == null) continue; if (activeProviderKeys.contains(provider.getId()) && provider.isSingleton()) continue; - AnAction providerAction = new AnAction(providerName, null, provider.getIcon()) { + AnAction providerAction = new AnAction(provider.getName(), null, provider.getIcon()) { @Override public void actionPerformed(AnActionEvent e) { BeforeRunTask task = provider.createTask(myRunConfiguration); @@ -191,8 +243,8 @@ class BeforeRunStepsPanel extends JPanel { popup.show(button.getPreferredPopupPoint()); } - private List getActiveProviderKeys() { - List result = new ArrayList(); + private Set getActiveProviderKeys() { + Set result = new HashSet(); for (BeforeRunTask task : myModel.getItems()) { result.add(task.getProviderId()); } diff --git a/platform/lang-impl/src/com/intellij/execution/impl/ConfigurationSettingsEditorWrapper.form b/platform/lang-impl/src/com/intellij/execution/impl/ConfigurationSettingsEditorWrapper.form index 0a6fff678be3..cdd4f53b2fd4 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/ConfigurationSettingsEditorWrapper.form +++ b/platform/lang-impl/src/com/intellij/execution/impl/ConfigurationSettingsEditorWrapper.form @@ -1,6 +1,6 @@
- + @@ -30,7 +30,7 @@ - + @@ -45,6 +45,11 @@ + + + + +
From 7671fcbd98e38aaeaae09714498d6ad9e69a5693 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Wed, 16 May 2012 16:08:48 +0400 Subject: [PATCH 05/11] IDEA-84399 Android+Maven: support including native libraries through pom.xml --- .../compiler/tools/AndroidApkBuilder.java | 80 +++++++++++++++---- .../android/util/AndroidCommonUtils.java | 6 ++ .../android/util/AndroidNativeLibData.java | 55 +++++++++++++ .../compiler/AndroidPackagingCompiler.java | 52 ++++++++++-- .../facet/AndroidFacetConfiguration.java | 41 ++++++++++ .../maven/AndroidFacetImporterBase.java | 39 +++++++++ .../android/maven/AndroidMavenUtil.java | 1 + 7 files changed, 250 insertions(+), 24 deletions(-) create mode 100644 plugins/android/common/src/org/jetbrains/android/util/AndroidNativeLibData.java diff --git a/plugins/android/common/src/org/jetbrains/android/compiler/tools/AndroidApkBuilder.java b/plugins/android/common/src/org/jetbrains/android/compiler/tools/AndroidApkBuilder.java index f4ac855c0e3d..5cf3bca40dc2 100644 --- a/plugins/android/common/src/org/jetbrains/android/compiler/tools/AndroidApkBuilder.java +++ b/plugins/android/common/src/org/jetbrains/android/compiler/tools/AndroidApkBuilder.java @@ -23,12 +23,14 @@ import com.android.sdklib.SdkConstants; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.util.ArrayUtil; import com.intellij.util.containers.HashMap; import com.intellij.util.containers.HashSet; import com.intellij.util.text.DateFormatUtil; import org.jetbrains.android.util.AndroidCommonUtils; import org.jetbrains.android.util.AndroidCompilerMessageKind; import org.jetbrains.android.util.AndroidExecutionUtil; +import org.jetbrains.android.util.AndroidNativeLibData; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -113,32 +115,78 @@ public class AndroidApkBuilder { @NotNull String[] sourceRoots, @NotNull String[] externalJars, @NotNull String[] nativeLibsFolders, + @NotNull Collection additionalNativeLibs, @NotNull String finalApk, boolean unsigned, @NotNull String sdkPath, @Nullable String customKeystorePath, @NotNull Condition resourceFilter) throws IOException { - if (unsigned) { - return filterUsingKeystoreMessages( - finalPackage(dexPath, sourceRoots, externalJars, nativeLibsFolders, finalApk, resPackagePath, customKeystorePath, false, - resourceFilter)); - } - final Map> map = new HashMap>(); - final String zipAlignPath = sdkPath + File.separator + AndroidCommonUtils.toolPath(SdkConstants.FN_ZIPALIGN); - boolean withAlignment = new File(zipAlignPath).exists(); - String unalignedApk = finalApk + UNALIGNED_SUFFIX; + map.put(ERROR, new ArrayList()); + map.put(WARNING, new ArrayList()); + File additionalLibsDir = null; + try { + if (additionalNativeLibs.size() > 0) { + additionalLibsDir = FileUtil.createTempDirectory("android_additional_libs", "tmp"); - Map> map2 = filterUsingKeystoreMessages( - finalPackage(dexPath, sourceRoots, externalJars, nativeLibsFolders, withAlignment ? unalignedApk : finalApk, resPackagePath, - customKeystorePath, true, resourceFilter)); - map.putAll(map2); + if (!copyNativeLibs(additionalNativeLibs, additionalLibsDir, map)) { + return map; + } + nativeLibsFolders = ArrayUtil.append(nativeLibsFolders, additionalLibsDir.getPath()); + } - if (withAlignment && map.get(ERROR).size() == 0) { - map2 = AndroidExecutionUtil.doExecute(zipAlignPath, "-f", "4", unalignedApk, finalApk); + if (unsigned) { + return filterUsingKeystoreMessages( + finalPackage(dexPath, sourceRoots, externalJars, nativeLibsFolders, finalApk, resPackagePath, customKeystorePath, false, + resourceFilter)); + } + final String zipAlignPath = sdkPath + File.separator + AndroidCommonUtils.toolPath(SdkConstants.FN_ZIPALIGN); + boolean withAlignment = new File(zipAlignPath).exists(); + String unalignedApk = finalApk + UNALIGNED_SUFFIX; + + Map> map2 = filterUsingKeystoreMessages( + finalPackage(dexPath, sourceRoots, externalJars, nativeLibsFolders, withAlignment ? unalignedApk : finalApk, resPackagePath, + customKeystorePath, true, resourceFilter)); map.putAll(map2); + + if (withAlignment && map.get(ERROR).size() == 0) { + map2 = AndroidExecutionUtil.doExecute(zipAlignPath, "-f", "4", unalignedApk, finalApk); + map.putAll(map2); + } + return map; } - return map; + finally { + if (additionalLibsDir != null) { + FileUtil.delete(additionalLibsDir); + } + } + } + + private static boolean copyNativeLibs(@NotNull Collection libs, + @NotNull File targetDir, + @NotNull Map> map) throws IOException { + for (AndroidNativeLibData lib : libs) { + final String path = lib.getPath(); + final File srcFile = new File(path); + if (!srcFile.exists()) { + map.get(WARNING).add("File not found: " + FileUtil.toSystemDependentName(path) + ". The native library won't be placed into APK"); + continue; + } + final File dstDir = new File(targetDir, lib.getArchitecture()); + + final File dstFile = new File(dstDir, lib.getTargetFileName()); + if (dstFile.exists()) { + map.get(WARNING).add("Duplicate native library " + dstFile.getName() + "; " + dstFile.getPath() + " already exists"); + continue; + } + + if (!dstDir.mkdirs()) { + map.get(ERROR).add("Cannot create directory: " + FileUtil.toSystemDependentName(dstDir.getPath())); + continue; + } + FileUtil.copy(srcFile, dstFile); + } + return map.get(ERROR).size() == 0; } private static Map> finalPackage(@NotNull String dexPath, 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 47fb7b9d689e..2dab42af9725 100644 --- a/plugins/android/common/src/org/jetbrains/android/util/AndroidCommonUtils.java +++ b/plugins/android/common/src/org/jetbrains/android/util/AndroidCommonUtils.java @@ -75,7 +75,13 @@ public class AndroidCommonUtils { public static final ResourceType[] ID_PROVIDING_RESOURCE_TYPES = new ResourceType[] { ResourceType.LAYOUT, ResourceType.MENU }; + @NonNls public static final String INCLUDE_SYSTEM_PROGUARD_FILE_ELEMENT_NAME = "includeSystemProguardFile"; + @NonNls public static final String ADDITIONAL_NATIVE_LIBS_ELEMENT = "additionalNativeLibs"; + @NonNls public static final String ITEM_ELEMENT = "item"; + @NonNls public static final String ARCHITECTURE_ATTRIBUTE = "architecture"; + @NonNls public static final String URL_ATTRIBUTE = "url"; + @NonNls public static final String TARGET_FILE_NAME_ATTRIBUTE = "targetFileName"; private static final String[] TEST_CONFIGURATION_TYPE_IDS = {"JUnit", "TestNG", "ScalaTestRunConfiguration", "SpecsRunConfiguration", "Specs2RunConfiguration"}; diff --git a/plugins/android/common/src/org/jetbrains/android/util/AndroidNativeLibData.java b/plugins/android/common/src/org/jetbrains/android/util/AndroidNativeLibData.java new file mode 100644 index 000000000000..ca60aeaa14f2 --- /dev/null +++ b/plugins/android/common/src/org/jetbrains/android/util/AndroidNativeLibData.java @@ -0,0 +1,55 @@ +package org.jetbrains.android.util; + +import org.jetbrains.annotations.NotNull; + +/** + * @author Eugene.Kudelevsky + */ +public class AndroidNativeLibData { + private final String myPath; + private final String myArchitecture; + private final String myTargetFileName; + + public AndroidNativeLibData(@NotNull String architecture, @NotNull String path, @NotNull String targetFileName) { + myPath = path; + myArchitecture = architecture; + myTargetFileName = targetFileName; + } + + @NotNull + public String getPath() { + return myPath; + } + + @NotNull + public String getArchitecture() { + return myArchitecture; + } + + @NotNull + public String getTargetFileName() { + return myTargetFileName; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + AndroidNativeLibData lib = (AndroidNativeLibData)o; + + if (!myArchitecture.equals(lib.myArchitecture)) return false; + if (!myTargetFileName.equals(lib.myTargetFileName)) return false; + if (!myPath.equals(lib.myPath)) return false; + + return true; + } + + @Override + public int hashCode() { + int result = myPath.hashCode(); + result = 31 * result + myArchitecture.hashCode(); + result = 31 * result + myTargetFileName.hashCode(); + return result; + } +} diff --git a/plugins/android/src/org/jetbrains/android/compiler/AndroidPackagingCompiler.java b/plugins/android/src/org/jetbrains/android/compiler/AndroidPackagingCompiler.java index d4210883e469..4d4dd37aa8e7 100644 --- a/plugins/android/src/org/jetbrains/android/compiler/AndroidPackagingCompiler.java +++ b/plugins/android/src/org/jetbrains/android/compiler/AndroidPackagingCompiler.java @@ -36,6 +36,7 @@ import org.jetbrains.android.facet.AndroidRootUtil; import org.jetbrains.android.sdk.AndroidPlatform; import org.jetbrains.android.util.AndroidBundle; import org.jetbrains.android.util.AndroidCommonUtils; +import org.jetbrains.android.util.AndroidNativeLibData; import org.jetbrains.android.util.AndroidUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -157,8 +158,9 @@ public class AndroidPackagingCompiler implements PackagingCompiler { boolean generateSignedApk, boolean releaseBuild, String customKeystorePath) { - AptPackagingItem item = - new AptPackagingItem(sdkPath, manifestFile, resPackagePath, outputPath, generateSignedApk, releaseBuild, module, customKeystorePath); + final AptPackagingItem item = + new AptPackagingItem(sdkPath, manifestFile, resPackagePath, outputPath, generateSignedApk, releaseBuild, module, customKeystorePath, + facet.getConfiguration().getAdditionalNativeLibraries()); item.setNativeLibsFolders(collectNativeLibsFolders(facet)); item.setClassesDexPath(classesDexPath); item.setSourceRoots(sourceRoots); @@ -239,8 +241,8 @@ public class AndroidPackagingCompiler implements PackagingCompiler { final Project project = context.getProject(); final Map> messages = AndroidCompileUtil.toCompilerMessageCategoryKeys( - AndroidApkBuilder.execute(resPackagePath, item.getClassesDexPath(), sourceRoots, externalLibPaths, - nativeLibsFolders, finalPath, unsigned, item.mySdkPath, item.getCustomKeystorePath(), + AndroidApkBuilder.execute(resPackagePath, item.getClassesDexPath(), sourceRoots, externalLibPaths, nativeLibsFolders, + item.getAdditionalNativeLibs(), finalPath, unsigned, item.mySdkPath, item.getCustomKeystorePath(), new ExcludedSourcesFilter(project))); AndroidCompileUtil.addMessages(context, messages); @@ -298,6 +300,7 @@ public class AndroidPackagingCompiler implements PackagingCompiler { private final String myFinalPath; private String myClassesDexPath; private VirtualFile[] myNativeLibsFolders; + private final List myAdditionalNativeLibs; private VirtualFile[] mySourceRoots; private VirtualFile[] myExternalLibraries; private final boolean myGenerateUnsigendApk; @@ -313,7 +316,8 @@ public class AndroidPackagingCompiler implements PackagingCompiler { boolean generateUnsigendApk, boolean releaseBuild, @NotNull Module module, - @Nullable String customKeystorePath) { + @Nullable String customKeystorePath, + @NotNull List additionalNativeLibs) { mySdkPath = sdkPath; myManifestFile = manifestFile; myResPackagePath = resPackagePath; @@ -322,6 +326,7 @@ public class AndroidPackagingCompiler implements PackagingCompiler { myReleaseBuild = releaseBuild; myModule = module; myCustomKeystorePath = customKeystorePath; + myAdditionalNativeLibs = additionalNativeLibs; } @NotNull @@ -349,6 +354,11 @@ public class AndroidPackagingCompiler implements PackagingCompiler { return myNativeLibsFolders; } + @NotNull + public List getAdditionalNativeLibs() { + return myAdditionalNativeLibs; + } + @NotNull public VirtualFile[] getSourceRoots() { return mySourceRoots; @@ -383,12 +393,14 @@ public class AndroidPackagingCompiler implements PackagingCompiler { @Nullable public ValidityState getValidityState() { return new MyValidityState(myModule.getProject(), myResPackagePath, myClassesDexPath, myFinalPath, myGenerateUnsigendApk, - myReleaseBuild, mySourceRoots, myExternalLibraries, myNativeLibsFolders, myCustomKeystorePath); + myReleaseBuild, mySourceRoots, myExternalLibraries, myNativeLibsFolders, myCustomKeystorePath, + myAdditionalNativeLibs); } } private static class MyValidityState implements ValidityState { private final Map myResourceTimestamps = new HashMap(); + private final Map myAdditionalNativeLibs = new HashMap(); private final String myApkPath; private final boolean myGenerateUnsignedApk; private final boolean myReleaseBuild; @@ -405,6 +417,15 @@ public class AndroidPackagingCompiler implements PackagingCompiler { myReleaseBuild = is.readBoolean(); myApkPath = is.readUTF(); myCustomKeystorePath = CompilerIOUtil.readString(is); + + size = is.readInt(); + for (int i = 0; i < size; i++) { + final String architecture = is.readUTF(); + final String path = is.readUTF(); + final String targetFileName = is.readUTF(); + final long timestamp = is.readLong(); + myAdditionalNativeLibs.put(new AndroidNativeLibData(architecture, path, targetFileName), timestamp); + } } MyValidityState(Project project, @@ -416,7 +437,8 @@ public class AndroidPackagingCompiler implements PackagingCompiler { VirtualFile[] sourceRoots, VirtualFile[] externalLibs, VirtualFile[] nativeLibFolders, - String customKeystorePath) { + String customKeystorePath, + List additionalNativeLibs) { myResourceTimestamps.put(FileUtil.toSystemIndependentName(resPackagePath), new File(resPackagePath).lastModified()); myResourceTimestamps.put(FileUtil.toSystemIndependentName(classesDexPath), new File(classesDexPath).lastModified()); myApkPath = apkPath; @@ -445,6 +467,10 @@ public class AndroidPackagingCompiler implements PackagingCompiler { for (File nativeLib : nativeLibs) { myResourceTimestamps.put(FileUtil.toSystemIndependentName(nativeLib.getPath()), nativeLib.lastModified()); } + for (AndroidNativeLibData lib : additionalNativeLibs) { + final String path = lib.getPath(); + myAdditionalNativeLibs.put(lib, new File(path).lastModified()); + } } @Override @@ -457,7 +483,8 @@ public class AndroidPackagingCompiler implements PackagingCompiler { mvs.myReleaseBuild == myReleaseBuild && mvs.myResourceTimestamps.equals(myResourceTimestamps) && mvs.myApkPath.equals(myApkPath) && - mvs.myCustomKeystorePath.equals(myCustomKeystorePath); + mvs.myCustomKeystorePath.equals(myCustomKeystorePath) && + mvs.myAdditionalNativeLibs.equals(myAdditionalNativeLibs); } @Override @@ -471,6 +498,15 @@ public class AndroidPackagingCompiler implements PackagingCompiler { out.writeBoolean(myReleaseBuild); out.writeUTF(myApkPath); CompilerIOUtil.writeString(myCustomKeystorePath, out); + + out.writeInt(myAdditionalNativeLibs.size()); + for (Map.Entry entry : myAdditionalNativeLibs.entrySet()) { + final AndroidNativeLibData lib = entry.getKey(); + out.writeUTF(lib.getArchitecture()); + out.writeUTF(lib.getPath()); + out.writeUTF(lib.getTargetFileName()); + out.writeLong(entry.getValue()); + } } } } diff --git a/plugins/android/src/org/jetbrains/android/facet/AndroidFacetConfiguration.java b/plugins/android/src/org/jetbrains/android/facet/AndroidFacetConfiguration.java index db8be815d555..5bffd531bfed 100644 --- a/plugins/android/src/org/jetbrains/android/facet/AndroidFacetConfiguration.java +++ b/plugins/android/src/org/jetbrains/android/facet/AndroidFacetConfiguration.java @@ -28,6 +28,7 @@ import com.intellij.openapi.util.DefaultJDOMExternalizer; import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.WriteExternalException; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import org.jdom.Element; import org.jetbrains.android.compiler.AndroidCompileUtil; @@ -36,12 +37,14 @@ import org.jetbrains.android.sdk.AndroidSdkAdditionalData; import org.jetbrains.android.sdk.AndroidSdkData; import org.jetbrains.android.sdk.AndroidSdkType; import org.jetbrains.android.util.AndroidCommonUtils; +import org.jetbrains.android.util.AndroidNativeLibData; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; /** @@ -89,6 +92,8 @@ public class AndroidFacetConfiguration implements FacetConfiguration { private boolean myIncludeSystemProguardCfgPath = true; + private List myAdditionalNativeLibraries = Collections.emptyList(); + private AndroidFacet myFacet = null; public void init(@NotNull Module module, @NotNull VirtualFile contentRoot) { @@ -153,6 +158,22 @@ public class AndroidFacetConfiguration implements FacetConfiguration { DefaultJDOMExternalizer.readExternal(this, element); readResOverlayFolders(element); + final Element additionalNativeLibsElement = element.getChild(AndroidCommonUtils.ADDITIONAL_NATIVE_LIBS_ELEMENT); + myAdditionalNativeLibraries = new ArrayList(); + + if (additionalNativeLibsElement != null) { + for (Object child : additionalNativeLibsElement.getChildren()) { + final Element childElement = (Element)child; + final String architecture = childElement.getAttributeValue(AndroidCommonUtils.ARCHITECTURE_ATTRIBUTE); + final String url = childElement.getAttributeValue(AndroidCommonUtils.URL_ATTRIBUTE); + final String targetFileName = childElement.getAttributeValue(AndroidCommonUtils.TARGET_FILE_NAME_ATTRIBUTE); + + if (url != null && architecture != null && targetFileName != null) { + myAdditionalNativeLibraries.add(new AndroidNativeLibData(architecture, VfsUtil.urlToPath(url), targetFileName)); + } + } + } + final Element includeSystemProguardFile = element.getChild(AndroidCommonUtils.INCLUDE_SYSTEM_PROGUARD_FILE_ELEMENT_NAME); if (includeSystemProguardFile != null) { final String includeSystemProguardFileValue = includeSystemProguardFile.getValue(); @@ -172,6 +193,17 @@ public class AndroidFacetConfiguration implements FacetConfiguration { final Element includeSystemProguerdFile = new Element(AndroidCommonUtils.INCLUDE_SYSTEM_PROGUARD_FILE_ELEMENT_NAME); includeSystemProguerdFile.setText(Boolean.toString(myIncludeSystemProguardCfgPath)); element.addContent(includeSystemProguerdFile); + + final Element additionalNativeLibs = new Element(AndroidCommonUtils.ADDITIONAL_NATIVE_LIBS_ELEMENT); + + for (AndroidNativeLibData lib : myAdditionalNativeLibraries) { + final Element item = new Element(AndroidCommonUtils.ITEM_ELEMENT); + item.setAttribute(AndroidCommonUtils.ARCHITECTURE_ATTRIBUTE, lib.getArchitecture()); + item.setAttribute(AndroidCommonUtils.URL_ATTRIBUTE, VfsUtil.pathToUrl(lib.getPath())); + item.setAttribute(AndroidCommonUtils.TARGET_FILE_NAME_ATTRIBUTE, lib.getTargetFileName()); + additionalNativeLibs.addContent(item); + } + element.addContent(additionalNativeLibs); } private void readResOverlayFolders(final Element element) throws InvalidDataException { @@ -205,4 +237,13 @@ public class AndroidFacetConfiguration implements FacetConfiguration { public void setIncludeSystemProguardCfgPath(boolean includeSystemProguardCfgPath) { myIncludeSystemProguardCfgPath = includeSystemProguardCfgPath; } + + @NotNull + public List getAdditionalNativeLibraries() { + return myAdditionalNativeLibraries; + } + + public void setAdditionalNativeLibraries(@NotNull List additionalNativeLibraries) { + myAdditionalNativeLibraries = additionalNativeLibraries; + } } diff --git a/plugins/android/src/org/jetbrains/android/maven/AndroidFacetImporterBase.java b/plugins/android/src/org/jetbrains/android/maven/AndroidFacetImporterBase.java index e4dd5f37e23f..7f565fa7993e 100644 --- a/plugins/android/src/org/jetbrains/android/maven/AndroidFacetImporterBase.java +++ b/plugins/android/src/org/jetbrains/android/maven/AndroidFacetImporterBase.java @@ -45,7 +45,9 @@ import org.jetbrains.android.facet.AndroidFacetConfiguration; import org.jetbrains.android.facet.AndroidFacetType; import org.jetbrains.android.facet.AndroidRootUtil; import org.jetbrains.android.sdk.*; +import org.jetbrains.android.util.AndroidNativeLibData; import org.jetbrains.android.util.AndroidUtils; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.maven.importing.FacetImporter; @@ -71,6 +73,7 @@ public abstract class AndroidFacetImporterBase extends FacetImporter MODULE_IMPORTED = Key.create("ANDROID_NEWLY_CREATED_KEY"); + @NonNls private static final String DEFAULT_NATIVE_ARCHITECTURE = "armeabi"; public AndroidFacetImporterBase(@NotNull String pluginId) { super("com.jayway.maven.plugins.android.generation2", pluginId, FacetType.findInstance(AndroidFacetType.class), "Android"); @@ -137,6 +140,37 @@ public abstract class AndroidFacetImporterBase extends FacetImporter additionalNativeLibs = new ArrayList(); + final String localRepository = MavenProjectsManager.getInstance(facet.getModule().getProject()).getLocalRepository().getPath(); + + String defaultArchitecture = getPathFromConfig(facet.getModule(), mavenProject, moduleDirPath, + "nativeLibrariesDependenciesHardwareArchitectureDefault", false, true); + if (defaultArchitecture == null) { + defaultArchitecture = DEFAULT_NATIVE_ARCHITECTURE; + } + final String forcedArchitecture = getPathFromConfig(facet.getModule(), mavenProject, moduleDirPath, + "nativeLibrariesDependenciesHardwareArchitectureOverride", false, true); + + for (MavenArtifact depArtifact : mavenProject.getDependencies()) { + if (AndroidMavenUtil.SO_PACKAGING_AND_DEPENDENCY_TYPE.equals(depArtifact.getType())) { + final String architecture; + if (forcedArchitecture != null) { + architecture = forcedArchitecture; + } + else { + final String classifier = depArtifact.getClassifier(); + architecture = classifier != null ? classifier : defaultArchitecture; + } + final String path = FileUtil.toSystemIndependentName(localRepository + '/' + depArtifact.getRelativePath()); + final String artifactId = depArtifact.getArtifactId(); + final String targetFileName = artifactId.startsWith("lib") ? artifactId + ".so" : "lib" + artifactId + ".so"; + additionalNativeLibs.add(new AndroidNativeLibData(architecture, path, targetFileName)); + } + } + facet.getConfiguration().setAdditionalNativeLibraries(additionalNativeLibs); + } + private static boolean hasApklibDependencies(@NotNull MavenProject mavenProject) { for (MavenArtifact depArtifact : mavenProject.getDependencies()) { if (AndroidMavenUtil.APKLIB_DEPENDENCY_AND_PACKAGING_TYPE.equals(depArtifact.getType())) { @@ -676,6 +710,9 @@ public abstract class AndroidFacetImporterBase extends FacetImporter Date: Wed, 16 May 2012 16:11:23 +0400 Subject: [PATCH 06/11] IDEA-84399 support including native libs though pom.xml (JPS support) --- .../android/AndroidApkBuilderConfigState.java | 28 +++++++++++++-- .../jetbrains/jps/android/AndroidFacet.groovy | 3 ++ .../jps/android/AndroidFacetType.groovy | 16 +++++++++ .../jps/android/AndroidPackagingBuilder.java | 35 +++++++++++-------- .../jetbrains/jps/android/AndroidSdk.groovy | 12 +++++++ 5 files changed, 78 insertions(+), 16 deletions(-) diff --git a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidApkBuilderConfigState.java b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidApkBuilderConfigState.java index 0bc4758d373a..d546b4fb620a 100644 --- a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidApkBuilderConfigState.java +++ b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidApkBuilderConfigState.java @@ -1,11 +1,14 @@ package org.jetbrains.jps.android; +import org.jetbrains.android.util.AndroidNativeLibData; import org.jetbrains.annotations.NotNull; import org.jetbrains.jps.incremental.storage.ValidityState; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; /** * @author Eugene.Kudelevsky @@ -13,15 +16,28 @@ import java.io.IOException; public class AndroidApkBuilderConfigState implements ValidityState { private final String myOutputApkPath; private final String myCustomKeystorePath; + private final List myAdditionalNativeLibs; - public AndroidApkBuilderConfigState(@NotNull String outputApkPath, @NotNull String customKeystorePath) { + public AndroidApkBuilderConfigState(@NotNull String outputApkPath, + @NotNull String customKeystorePath, + @NotNull List additionalNativeLibs) { myOutputApkPath = outputApkPath; myCustomKeystorePath = customKeystorePath; + myAdditionalNativeLibs = additionalNativeLibs; } public AndroidApkBuilderConfigState(DataInput in) throws IOException { myOutputApkPath = in.readUTF(); myCustomKeystorePath = in.readUTF(); + + final int additionalNativeLibsCount = in.readInt(); + myAdditionalNativeLibs = new ArrayList(additionalNativeLibsCount); + for (int i = 0; i < additionalNativeLibsCount; i++) { + final String architecture = in.readUTF(); + final String path = in.readUTF(); + final String targetFileName = in.readUTF(); + myAdditionalNativeLibs.add(new AndroidNativeLibData(architecture, path, targetFileName)); + } } @Override @@ -31,12 +47,20 @@ public class AndroidApkBuilderConfigState implements ValidityState { } final AndroidApkBuilderConfigState apkBuilderConfigState = (AndroidApkBuilderConfigState)otherState; return apkBuilderConfigState.myOutputApkPath.equals(myOutputApkPath) && - apkBuilderConfigState.myCustomKeystorePath.equals(myCustomKeystorePath); + apkBuilderConfigState.myCustomKeystorePath.equals(myCustomKeystorePath) && + apkBuilderConfigState.myAdditionalNativeLibs.equals(myAdditionalNativeLibs); } @Override public void save(DataOutput out) throws IOException { out.writeUTF(myOutputApkPath); out.writeUTF(myCustomKeystorePath); + + out.writeInt(myAdditionalNativeLibs.size()); + for (AndroidNativeLibData lib : myAdditionalNativeLibs) { + out.writeUTF(lib.getArchitecture()); + out.writeUTF(lib.getPath()); + out.writeUTF(lib.getTargetFileName()); + } } } diff --git a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidFacet.groovy b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidFacet.groovy index 3438a95df1d5..ba64de3f7dc4 100644 --- a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidFacet.groovy +++ b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidFacet.groovy @@ -1,6 +1,7 @@ package org.jetbrains.jps.android import com.intellij.openapi.util.io.FileUtil +import org.jetbrains.android.util.AndroidNativeLibData import org.jetbrains.jps.Module import org.jetbrains.jps.idea.Facet @@ -33,6 +34,8 @@ class AndroidFacet extends Facet { boolean runProguard boolean includeSystemProguardCfgFile + List additionalNativeLibs + AndroidFacet(Module module, String name) { this.module = module this.name = name; diff --git a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidFacetType.groovy b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidFacetType.groovy index f22096aec1a7..a7e5bf8634e0 100644 --- a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidFacetType.groovy +++ b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidFacetType.groovy @@ -1,6 +1,7 @@ package org.jetbrains.jps.android import org.jetbrains.android.util.AndroidCommonUtils +import org.jetbrains.android.util.AndroidNativeLibData import org.jetbrains.jps.MacroExpander import org.jetbrains.jps.Module import org.jetbrains.jps.idea.Facet @@ -20,12 +21,27 @@ class AndroidFacetType extends FacetTypeService { @Override Facet createFacet(Module module, String name, Node facetConfiguration, MacroExpander macroExpander) { def facet = new AndroidFacet(module, name); + facet.additionalNativeLibs = new ArrayList() facetConfiguration.each {Node child -> if (AndroidCommonUtils.INCLUDE_SYSTEM_PROGUARD_FILE_ELEMENT_NAME.equals(child.name())) { facet.includeSystemProguardCfgFile = Boolean.parseBoolean((String)child.text()) } + if (AndroidCommonUtils.ADDITIONAL_NATIVE_LIBS_ELEMENT.equals(child.name())) { + child.each {Node nativeLibItem -> + final architecture = nativeLibItem.get("@" + AndroidCommonUtils.ARCHITECTURE_ATTRIBUTE) + final url = nativeLibItem.get("@" + AndroidCommonUtils.URL_ATTRIBUTE) + final targetFileName = nativeLibItem.get("@" + AndroidCommonUtils.TARGET_FILE_NAME_ATTRIBUTE) + + if (architecture != null && url != null && targetFileName != null) { + facet.additionalNativeLibs.add(new AndroidNativeLibData((String)architecture, + IdeaProjectLoadingUtil.pathFromUrl((String)url), + (String)targetFileName)) + } + } + } + String value = child."@value" switch (child."@name") { 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 a689ef7b755d..a2af3d4916c2 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 @@ -10,6 +10,7 @@ import org.jetbrains.android.compiler.tools.AndroidApkBuilder; import org.jetbrains.android.compiler.tools.AndroidApt; import org.jetbrains.android.util.AndroidCommonUtils; import org.jetbrains.android.util.AndroidCompilerMessageKind; +import org.jetbrains.android.util.AndroidNativeLibData; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -139,9 +140,11 @@ public class AndroidPackagingBuilder extends ProjectLevelBuilder { @NotNull Module module, @NotNull AndroidFileSetStorage storage, @Nullable AndroidFileSetState state) throws IOException { - final AndroidFileSetState savedState = storage.getState(module.getName()); - if (context.isMake() && savedState != null && savedState.equalsTo(state)) { - return true; + if (context.isMake()) { + final AndroidFileSetState savedState = storage.getState(module.getName()); + if (savedState != null && savedState.equalsTo(state)) { + return true; + } } final AndroidFacet facet = AndroidJpsUtil.getFacet(module); @@ -362,27 +365,31 @@ public class AndroidPackagingBuilder extends ProjectLevelBuilder { final String classesDexFilePath = classesDexFile.getPath(); final String[] externalJars = ArrayUtil.toStringArray(externalJarsSet); + // currently including native libraries through pom.xml doesn't work when jps compilation is used, MAVEN_REPOSITORY url macros needed + final List additionalNativeLibs = facet.getAdditionalNativeLibs(); + final AndroidFileSetState currentFileSetState = - buildCurrentApkBuilderState(context.getProject(), resPackagePath, classesDexFilePath, nativeLibDirs, - sourceRoots, externalJars, release); + buildCurrentApkBuilderState(context.getProject(), resPackagePath, classesDexFilePath, nativeLibDirs, sourceRoots, + externalJars, release); final AndroidApkBuilderConfigState currentApkBuilderConfigState = - new AndroidApkBuilderConfigState(outputApkPath, customKeyStorePath); + new AndroidApkBuilderConfigState(outputApkPath, customKeyStorePath, additionalNativeLibs); - final AndroidFileSetState savedApkFileSetState = apkFileSetStorage.getState(module.getName()); - final AndroidApkBuilderConfigState savedApkBuilderConfigState = apkBuilderConfigStateStorage.getState(module.getName()); + if (context.isMake()) { + final AndroidFileSetState savedApkFileSetState = apkFileSetStorage.getState(module.getName()); + final AndroidApkBuilderConfigState savedApkBuilderConfigState = apkBuilderConfigStateStorage.getState(module.getName()); - if (context.isMake() && - currentFileSetState.equalsTo(savedApkFileSetState) && - currentApkBuilderConfigState.equalsTo(savedApkBuilderConfigState)) { - return true; + if (currentFileSetState.equalsTo(savedApkFileSetState) && + currentApkBuilderConfigState.equalsTo(savedApkBuilderConfigState)) { + return true; + } } context .processMessage(new ProgressMessage(AndroidJpsBundle.message("android.jps.progress.packaging", AndroidJpsUtil.getApkName(module)))); final Map> messages = AndroidApkBuilder - .execute(resPackagePath, classesDexFilePath, sourceRoots, externalJars, nativeLibDirs, outputApkPath, - release, sdkPath, customKeyStorePath, new MyExcludedSourcesFilter(context.getProject())); + .execute(resPackagePath, classesDexFilePath, sourceRoots, externalJars, nativeLibDirs, additionalNativeLibs, + outputApkPath, release, sdkPath, customKeyStorePath, new MyExcludedSourcesFilter(context.getProject())); AndroidJpsUtil.addMessages(context, messages, BUILDER_NAME); final boolean success = messages.get(AndroidCompilerMessageKind.ERROR).isEmpty(); diff --git a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidSdk.groovy b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidSdk.groovy index e105eb6b275e..6e805e0e06bc 100644 --- a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidSdk.groovy +++ b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidSdk.groovy @@ -30,4 +30,16 @@ class AndroidSdk extends JavaSdk { def javaSdk = project.sdks[javaSdkName] return javaSdk instanceof JavaSdkImpl ? javaSdk.getJavaExecutable() : null } + + @Override + String getHomePath() { + def javaSdk = project.sdks[javaSdkName] + return javaSdk instanceof JavaSdkImpl ? javaSdk.getHomePath() : null + } + + @Override + String getVersion() { + def javaSdk = project.sdks[javaSdkName] + return javaSdk instanceof JavaSdkImpl ? javaSdk.getVersion() : null + } } From bd75e04b7fb51517f449360481d7e72a153d702f Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Wed, 16 May 2012 15:21:02 +0400 Subject: [PATCH 07/11] resolver of property accessor should sort category results to choose the best one --- .../GrReferenceExpressionImpl.java | 29 +++--------- .../lang/psi/util/GroovyPropertyUtils.java | 14 ++++-- .../groovy/lang/resolve/ResolveUtil.java | 2 +- .../processors/AccessorResolverProcessor.java | 46 +++++++++++++++---- .../processors/MethodResolverProcessor.java | 2 +- .../lang/resolve/ResolvePropertyTest.groovy | 14 +++++- 6 files changed, 70 insertions(+), 37 deletions(-) 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 10833924d997..8cdc0970c303 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 @@ -47,7 +47,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; 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.expressions.path.GrMethodCallExpression; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod; 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.impl.*; @@ -171,21 +170,17 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl accessorResults = new ArrayList(); for (String accessorName : accessorNames) { - AccessorResolverProcessor accessorResolver = - new AccessorResolverProcessor(accessorName, this, !isLValue, false, getThisType(), getTypeArguments()); + AccessorResolverProcessor accessorResolver = new AccessorResolverProcessor(accessorName, name, this, !isLValue, false, getThisType(), getTypeArguments()); GrReferenceResolveUtil.resolveImpl(accessorResolver, this); - final GroovyResolveResult[] candidates = accessorResolver.getCandidates(); //can be only one correct candidate - if (candidates.length > 0 && candidates[candidates.length - 1].isStaticsOK()) { - if (isPropertyName || isCorrectRefNameForResolved(candidates, name)) { - if (candidates.length == 1) return candidates; - return new GroovyResolveResult[]{candidates[candidates.length - 1]}; - } + final GroovyResolveResult[] candidates = accessorResolver.getCandidates(); + + //can be only one correct candidate or some incorrect + if (candidates.length == 1 && candidates[0].isStaticsOK() && candidates[0].isAccessible()) { + return candidates; } else { ContainerUtil.addAll(accessorResults, candidates); @@ -202,17 +197,7 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl applicable = new ArrayList(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/AccessorResolverProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/AccessorResolverProcessor.java index 713ee4bff9dd..4d6cc10e9c4c 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/AccessorResolverProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/AccessorResolverProcessor.java @@ -19,27 +19,33 @@ import com.intellij.psi.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; +import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod; import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyResolveResultImpl; import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils; /** * @author Maxim.Medvedev */ -public class AccessorResolverProcessor extends ResolverProcessor { +public class AccessorResolverProcessor extends MethodResolverProcessor { + private final String myPropertyName; private final boolean mySearchForGetter; private final SubstitutorComputer mySubstitutorComputer; - public AccessorResolverProcessor(String name, GroovyPsiElement place, boolean searchForGetter) { - this(name, place, searchForGetter, false, null, PsiType.EMPTY_ARRAY); + public AccessorResolverProcessor(String accessorName, String propertyName, GroovyPsiElement place, boolean searchForGetter) { + this(accessorName, propertyName, place, searchForGetter, false, null, PsiType.EMPTY_ARRAY); } - public AccessorResolverProcessor(String name, + public AccessorResolverProcessor(String accessorName, + String propertyName, GroovyPsiElement place, boolean searchForGetter, boolean byShape, @Nullable PsiType thisType, @NotNull PsiType[] typeArguments) { - super(name, RESOLVE_KINDS_METHOD, place, PsiType.EMPTY_ARRAY); + super(accessorName, place, false, thisType, null, typeArguments, false, byShape); + myPropertyName = propertyName; + mySearchForGetter = searchForGetter; mySubstitutorComputer = byShape ? null : new SubstitutorComputer(thisType, PsiType.EMPTY_ARRAY, typeArguments, false, place) { @Override @@ -51,12 +57,12 @@ public class AccessorResolverProcessor extends ResolverProcessor { public boolean execute(PsiElement element, ResolveState state) { if (mySearchForGetter) { - if (element instanceof PsiMethod && GroovyPropertyUtils.isSimplePropertyGetter((PsiMethod)element, null)) { + if (element instanceof PsiMethod && GroovyPropertyUtils.isSimplePropertyGetter((PsiMethod)element, myPropertyName)) { return addAccessor((PsiMethod)element, state); } } else { - if (element instanceof PsiMethod && GroovyPropertyUtils.isSimplePropertySetter((PsiMethod)element, null)) { + if (element instanceof PsiMethod && GroovyPropertyUtils.isSimplePropertySetter((PsiMethod)element, myPropertyName)) { return addAccessor((PsiMethod)element, state); } } @@ -73,7 +79,29 @@ public class AccessorResolverProcessor extends ResolverProcessor { boolean isAccessible = isAccessible(method); final GroovyPsiElement resolveContext = state.get(RESOLVE_CONTEXT); boolean isStaticsOK = isStaticsOK(method, resolveContext, true); - addCandidate(new GroovyResolveResultImpl(method, resolveContext, substitutor, isAccessible, isStaticsOK, true)); - return !isAccessible || !isStaticsOK; + final GroovyResolveResultImpl candidate = + new GroovyResolveResultImpl(method, resolveContext, substitutor, isAccessible, isStaticsOK, true); + if (isAccessible && isStaticsOK) { + addCandidate(candidate); + return method instanceof GrGdkMethod; //don't stop searching if we found only gdk method + } + else { + myInapplicableCandidates.add(candidate); + return true; + } + } + + @NotNull + @Override + public GroovyResolveResult[] getCandidates() { + final boolean hasApplicableCandidates = hasApplicableCandidates(); + final GroovyResolveResult[] candidates = super.getCandidates(); + if (hasApplicableCandidates) { + if (candidates.length <= 1) return candidates; + return new GroovyResolveResult[]{candidates[0]}; + } + else { + return candidates; + } } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/MethodResolverProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/MethodResolverProcessor.java index 9231fea405f6..27f5859ec0db 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/MethodResolverProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/MethodResolverProcessor.java @@ -48,7 +48,7 @@ public class MethodResolverProcessor extends ResolverProcessor { private final PsiType[] myArgumentTypes; private final boolean myAllVariants; - private final Set myInapplicableCandidates = new LinkedHashSet(); + protected final Set myInapplicableCandidates = new LinkedHashSet(); private final boolean myIsConstructor; private boolean myStopExecuting = false; 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 069cc059b04b..24be0c7871be 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 @@ -28,6 +28,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrRefere 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.refactoring.GroovyRefactoringUtil @@ -593,7 +594,7 @@ setFoo(2) } public void testUpperCaseFieldWithoutGetter() { - assertTrue resolve("A.groovy") instanceof GrAccessorMethod + assertInstanceOf(resolve("A.groovy"), GrAccessorMethod) } public void testGetterWithUpperCaseFieldReference() { @@ -788,4 +789,15 @@ class A { new A().prop''') assertNotNull ref.resolve() } + + void testGetChars() { + def ref = configureByText('''\ +'abc'.chars +''') + def resolved = ref.resolve() + assertInstanceOf(resolved, GrGdkMethod) + def method = resolved.staticMethod as PsiMethod + + assertEquals(method.parameterList.parameters[0].type.canonicalText, CommonClassNames.JAVA_LANG_STRING) + } } From 01b36b46dc440d0ffe9a1ece83c433068f2c38ef Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Wed, 16 May 2012 16:07:20 +0400 Subject: [PATCH 08/11] find usage of category accessor --- .../AccessorMethodReferencesSearcher.java | 21 ++++++++++++-- .../lang/resolve/MixinMemberContributor.java | 13 +++++---- .../lang/findUsages/FindUsagesTest.groovy | 29 ++++++++++++++----- 3 files changed, 46 insertions(+), 17 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/AccessorMethodReferencesSearcher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/AccessorMethodReferencesSearcher.java index 1e648bb67fa0..ceb9e4fe04b5 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/AccessorMethodReferencesSearcher.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/AccessorMethodReferencesSearcher.java @@ -20,12 +20,16 @@ import com.intellij.openapi.application.QueryExecutorBase; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiReference; +import com.intellij.psi.search.SearchScope; import com.intellij.psi.search.UsageSearchContext; import com.intellij.psi.search.searches.MethodReferencesSearch; import com.intellij.util.Processor; import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod; +import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrGdkMethodImpl; import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; +import org.jetbrains.plugins.groovy.lang.resolve.MixinMemberContributor; /** * author ven @@ -39,13 +43,24 @@ public class AccessorMethodReferencesSearcher extends QueryExecutorBase consumer) { final PsiMethod method = queryParameters.getMethod(); - final String propertyName = GroovyPropertyUtils.getPropertyName(method); + + final String propertyName; + if (MixinMemberContributor.isCategoryMethod(method, null)) { + final GrGdkMethod cat = GrGdkMethodImpl.createGdkMethod(method, false); + propertyName = GroovyPropertyUtils.getPropertyName((PsiMethod)cat); + } + else { + propertyName = GroovyPropertyUtils.getPropertyName(method); + } + if (propertyName == null) return; - queryParameters.getOptimizer().searchWord(propertyName, PsiUtil.restrictScopeToGroovyFiles(queryParameters.getScope()), UsageSearchContext.IN_CODE, true, method); + final SearchScope onlyGroovyFiles = PsiUtil.restrictScopeToGroovyFiles(queryParameters.getScope()); + + queryParameters.getOptimizer().searchWord(propertyName, onlyGroovyFiles, UsageSearchContext.IN_CODE, true, method); if (!GroovyPropertyUtils.isPropertyName(propertyName)) { - queryParameters.getOptimizer().searchWord(StringUtil.decapitalize(propertyName), PsiUtil.restrictScopeToGroovyFiles(queryParameters.getScope()), UsageSearchContext.IN_CODE, true, method); + queryParameters.getOptimizer().searchWord(StringUtil.decapitalize(propertyName), onlyGroovyFiles, UsageSearchContext.IN_CODE, true, method); } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/MixinMemberContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/MixinMemberContributor.java index 45c436b49308..60e8e2133474 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/MixinMemberContributor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/MixinMemberContributor.java @@ -19,6 +19,7 @@ import com.intellij.psi.*; import com.intellij.psi.scope.DelegatingScopeProcessor; import com.intellij.psi.scope.PsiScopeProcessor; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotationArrayInitializer; @@ -38,9 +39,9 @@ import java.util.List; public class MixinMemberContributor extends NonCodeMembersContributor { @Override public void processDynamicElements(@NotNull final PsiType qualifierType, - PsiScopeProcessor processor, - GroovyPsiElement place, - ResolveState state) { + @NotNull PsiScopeProcessor processor, + @NotNull GroovyPsiElement place, + @NotNull ResolveState state) { if (!(qualifierType instanceof PsiClassType)) return; if (isInAnnotation(place)) return; final PsiClassType.ClassResolveResult resolveResult = ((PsiClassType)qualifierType).resolveGenerics(); @@ -92,16 +93,16 @@ public class MixinMemberContributor extends NonCodeMembersContributor { return result; } - private static boolean isCategoryMethod(PsiElement element, PsiType qualifierType) { + public static boolean isCategoryMethod(@Nullable PsiElement element, @Nullable PsiType qualifierType) { if (!(element instanceof PsiMethod)) return false; if (!((PsiMethod)element).hasModifierProperty(PsiModifier.STATIC)) return false; final PsiParameter[] parameters = ((PsiMethod)element).getParameterList().getParameters(); if (parameters.length == 0) return false; - final PsiParameter selfParam = parameters[0]; - final PsiType selfType = selfParam.getType(); + if (qualifierType == null) return true; + final PsiType selfType = parameters[0].getType(); return TypesUtil.isAssignable(selfType, qualifierType, element.getManager(), element.getResolveScope()); } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/findUsages/FindUsagesTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/findUsages/FindUsagesTest.groovy index ed5e8a4daa62..db6fd3e4d287 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/findUsages/FindUsagesTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/findUsages/FindUsagesTest.groovy @@ -221,43 +221,51 @@ public class FindUsagesTest extends LightGroovyTestCase { } void testCapitalizedProperty1() { - myFixture.configureByText('_.groovy', '''\ + doTest(1, '''\ class A { def Prop } new A().Prop''') - assertUsageCount(1); } void testCapitalizedProperty2() { - myFixture.configureByText('_.groovy', '''\ + doTest(1, '''\ class A { def Prop } new A().prop''') - assertUsageCount(1) } void testCapitalizedProperty3() { - myFixture.configureByText('_.groovy', '''\ + doTest(0, '''\ class A { def prop } new A().Prop''') - assertUsageCount(0) } void testCapitalizedProperty4() { - myFixture.configureByText('_.groovy', '''\ + doTest(1, '''\ class A { def prop } new A().prop''') - assertUsageCount(1) + } + + void testCategoryProperty() { + doTest(1, '''\ +class Cat { + static def getFoo(Number s) {'num'} +} + +use(Cat) { + 2.foo +} +''') } private void doSuperMethodTest(String... firstParameterTypes) { @@ -279,4 +287,9 @@ new A().prop''') } } + private void doTest(int usageCount, String text) { + myFixture.configureByText('_.groovy', text) + assertUsageCount(usageCount); + } + } From 12bae2d705aacafdcf5efa6c9203be2b1346a289 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 16 May 2012 16:28:20 +0400 Subject: [PATCH 09/11] Fix compilation --- .../src/com/intellij/psi/impl/compiled/ClsClassImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsClassImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsClassImpl.java index 68ea27d5a7b0..0daf21a0417d 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsClassImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsClassImpl.java @@ -257,7 +257,7 @@ public class ClsClassImpl extends ClsRepositoryPsiElement> imple @NotNull @Override public List getOwnInnerClasses() { - return Arrays.asList(getStub().getChildrenByType(JavaStubElementTypes.CLASS, ARRAY_FACTORY)); + return Arrays.asList(getStub().getChildrenByType(JavaStubElementTypes.CLASS, PsiClass.ARRAY_FACTORY)); } @Override From acf43dc96725c2da58586f2eaf81601c3d3b1cdf Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Wed, 16 May 2012 14:49:38 +0200 Subject: [PATCH 10/11] IDEA-86056 (Unnecessary 'null' check before 'equals()' call quick fix changes the logic) --- ...implifiableEqualsExpressionInspection.java | 31 ++++++++++++++++--- .../SimplifiableEqualsExpression.java | 28 +++++++++++++++++ .../expected.xml | 26 ++++++++++++++++ ...ifiableEqualsExpressionInspectionTest.java | 11 +++++++ 4 files changed, 91 insertions(+), 5 deletions(-) rename plugins/InspectionGadgets/src/com/siyeh/ig/{style => controlflow}/SimplifiableEqualsExpressionInspection.java (89%) create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/simplifiable_equals_expression/SimplifiableEqualsExpression.java create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/simplifiable_equals_expression/expected.xml create mode 100644 plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/SimplifiableEqualsExpressionInspectionTest.java diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/style/SimplifiableEqualsExpressionInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/SimplifiableEqualsExpressionInspection.java similarity index 89% rename from plugins/InspectionGadgets/src/com/siyeh/ig/style/SimplifiableEqualsExpressionInspection.java rename to plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/SimplifiableEqualsExpressionInspection.java index 76ef652140bf..d53b7ab0572a 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/style/SimplifiableEqualsExpressionInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/SimplifiableEqualsExpressionInspection.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.siyeh.ig.style; +package com.siyeh.ig.controlflow; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.openapi.project.Project; @@ -71,7 +71,14 @@ public class SimplifiableEqualsExpressionInspection extends BaseInspection { if (operands.length != 2) { return; } - final PsiExpression operand = ParenthesesUtils.stripParentheses(operands[1]); + PsiExpression operand = ParenthesesUtils.stripParentheses(operands[1]); + if (operand instanceof PsiPrefixExpression) { + final PsiPrefixExpression prefixExpression = (PsiPrefixExpression)operand; + if (!JavaTokenType.EXCL.equals(prefixExpression.getOperationTokenType())) { + return; + } + operand = ParenthesesUtils.stripParentheses(prefixExpression.getOperand()); + } if (!(operand instanceof PsiMethodCallExpression)) { return; } @@ -170,7 +177,15 @@ public class SimplifiableEqualsExpressionInspection extends BaseInspection { return; } final PsiExpression rhs = ParenthesesUtils.stripParentheses(operands[1]); - if (!isEqualsConstant(rhs, variable)) { + if (!(rhs instanceof PsiPrefixExpression)) { + return; + } + final PsiPrefixExpression prefixExpression = (PsiPrefixExpression)rhs; + if (!JavaTokenType.EXCL.equals(prefixExpression.getOperationTokenType())) { + return; + } + final PsiExpression operand = ParenthesesUtils.stripParentheses(prefixExpression.getOperand()); + if (!isEqualsConstant(operand, variable)) { return; } registerError(lhs); @@ -226,8 +241,14 @@ public class SimplifiableEqualsExpressionInspection extends BaseInspection { if (operands.length != 2) { return null; } - final PsiExpression lhs = operands[0]; - final PsiExpression rhs = operands[1]; + final PsiExpression lhs = ParenthesesUtils.stripParentheses(operands[0]); + if (lhs == null) { + return null; + } + final PsiExpression rhs = ParenthesesUtils.stripParentheses(operands[1]); + if (rhs == null) { + return null; + } if (PsiType.NULL.equals(lhs.getType())) { if (!(rhs instanceof PsiReferenceExpression)) { return null; diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/simplifiable_equals_expression/SimplifiableEqualsExpression.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/simplifiable_equals_expression/SimplifiableEqualsExpression.java new file mode 100644 index 000000000000..5c0f5a121691 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/simplifiable_equals_expression/SimplifiableEqualsExpression.java @@ -0,0 +1,28 @@ +package com.siyeh.igtest.controlflow.simplifiable_equals_expression; + +public class SimplifiableEqualsExpression { + + void foo(String namespace) { + if (namespace != null && namespace.equals("")) { + return; + } + } + + void bar(String namespace) { + if (namespace == null || !namespace.equals("")) { + return; + } + } + + void baz(Integer i) { + if (i != null && i.equals(1)) { + return; + } + } + + void boz(String namespace) { + if (namespace == null || namespace.equals("")) { // don't warn here + return; + } + } +} diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/simplifiable_equals_expression/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/simplifiable_equals_expression/expected.xml new file mode 100644 index 000000000000..bf2d793746ba --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/simplifiable_equals_expression/expected.xml @@ -0,0 +1,26 @@ + + + + SimplifiableEqualsExpression.java + 12 + + Unnecessary 'null' check before 'equals()' call + Unnecessary 'null' check #loc + + + + SimplifiableEqualsExpression.java + 18 + + Unnecessary 'null' check before 'equals()' call + Unnecessary 'null' check #loc + + + + SimplifiableEqualsExpression.java + 6 + + Unnecessary 'null' check before 'equals()' call + Unnecessary 'null' check #loc + + \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/SimplifiableEqualsExpressionInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/SimplifiableEqualsExpressionInspectionTest.java new file mode 100644 index 000000000000..867d44e82f68 --- /dev/null +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/SimplifiableEqualsExpressionInspectionTest.java @@ -0,0 +1,11 @@ +package com.siyeh.ig.controlflow; + +import com.siyeh.ig.IGInspectionTestCase; + +public class SimplifiableEqualsExpressionInspectionTest extends IGInspectionTestCase { + + public void test() throws Exception { + doTest("com/siyeh/igtest/controlflow/simplifiable_equals_expression", + new SimplifiableEqualsExpressionInspection()); + } +} From 81be9fcfd2301aa90fd8d9d7b9f9830bae2fddf1 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 16 May 2012 16:53:58 +0400 Subject: [PATCH 11/11] Fix compilation --- .../src/com/intellij/psi/impl/source/PsiClassImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassImpl.java index eee618e80bff..6835a032c9e7 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassImpl.java @@ -311,7 +311,7 @@ public class PsiClassImpl extends JavaStubPsiElement> implements @NotNull @Override public List getOwnInnerClasses() { - return Arrays.asList(getStubOrPsiChildren(JavaStubElementTypes.CLASS, ARRAY_FACTORY)); + return Arrays.asList(getStubOrPsiChildren(JavaStubElementTypes.CLASS, PsiClass.ARRAY_FACTORY)); } @Override @@ -589,7 +589,7 @@ public class PsiClassImpl extends JavaStubPsiElement> implements final StubBasedPsiElementBase context = (StubBasedPsiElementBase)parentStub.getPsi(); @SuppressWarnings("unchecked") - PsiClass[] classesInScope = (PsiClass[])parentStub.getChildrenByType(Constants.CLASS_BIT_SET, ARRAY_FACTORY); + PsiClass[] classesInScope = (PsiClass[])parentStub.getChildrenByType(Constants.CLASS_BIT_SET, PsiClass.ARRAY_FACTORY); boolean needPreciseContext = false; if (classesInScope.length > 1) {