From ca2ca74aeb8e3accd89d93176985d1245a5ce550 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Fri, 10 Feb 2012 15:52:37 +0400 Subject: [PATCH 01/15] IDEA-80996 Groovy: a newly created dynamic method stays unresolved until some changes are made in editor --- .../annotator/intentions/dynamic/DynamicManagerImpl.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/dynamic/DynamicManagerImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/dynamic/DynamicManagerImpl.java index 6117e7c5d6ba..129680841b74 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/dynamic/DynamicManagerImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/dynamic/DynamicManagerImpl.java @@ -25,6 +25,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.startup.StartupManager; import com.intellij.openapi.wm.ToolWindow; import com.intellij.psi.*; +import com.intellij.psi.impl.PsiModificationTrackerImpl; import com.intellij.ui.treeStructure.treetable.ListTreeTableModelOnColumns; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; @@ -34,7 +35,6 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.annotator.intentions.QuickfixUtil; import org.jetbrains.plugins.groovy.annotator.intentions.dynamic.elements.*; import org.jetbrains.plugins.groovy.annotator.intentions.dynamic.ui.DynamicElementSettings; -import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager; import javax.swing.tree.DefaultMutableTreeNode; import java.util.ArrayList; @@ -384,8 +384,7 @@ public class DynamicManagerImpl extends DynamicManager { final PsiFile file = PsiDocumentManager.getInstance(myProject).getPsiFile(textEditor.getDocument()); if (file == null) return; - GroovyPsiManager.getInstance(myProject).dropTypesCache(); - PsiManager.getInstance(myProject).dropResolveCaches(); + ((PsiModificationTrackerImpl)PsiManager.getInstance(myProject).getModificationTracker()).incCounter(); DaemonCodeAnalyzer.getInstance(myProject).restart(); } From 106739bed1e052cef946ac1801eff308d28d13d6 Mon Sep 17 00:00:00 2001 From: Serge Baranov Date: Fri, 10 Feb 2012 23:57:11 +0400 Subject: [PATCH 02/15] Proper fix for IDEA-78076 --- .../platform-resources-en/src/messages/IdeBundle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-resources-en/src/messages/IdeBundle.properties b/platform/platform-resources-en/src/messages/IdeBundle.properties index f985fba72fd6..77fc75407f13 100644 --- a/platform/platform-resources-en/src/messages/IdeBundle.properties +++ b/platform/platform-resources-en/src/messages/IdeBundle.properties @@ -246,7 +246,7 @@ message.nothing.to.show.in.structure.view=Nothing to show in the Structure View error.license.collision=This license is being used elsewhere on the network by {0}.\nOnly one active computer at a time can use the license.\nWould you like to re-activate this computer?\nClick Yes to re-activate, or No to shutdown {1}. title.license.collision.detected=License Collision Detected message.licensed.to=Licensed to {0} -title.enter.license.data=Enter License Data +title.enter.license.data=Enter {0} License message.purchase.or.upgrade=For information on how to upgrade your evaluation software please go to {0} message.expiration.date=Expiration date: {0} message.educational.license=1-Year Educational License. {0} From 80ca8dc18c40ab90cacdc6392e01fbe7d4b92626 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 10 Feb 2012 19:26:53 +0100 Subject: [PATCH 03/15] some logging --- .../vcs/changes/VcsDirtyScopeManagerImpl.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeManagerImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeManagerImpl.java index 3fa1acb67898..decb13a4393a 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeManagerImpl.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeManagerImpl.java @@ -17,6 +17,7 @@ package com.intellij.openapi.vcs.changes; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ProjectComponent; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.project.DumbAwareRunnable; import com.intellij.openapi.project.Project; @@ -32,6 +33,7 @@ import com.intellij.util.Consumer; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import sun.reflect.Reflection; import java.util.ArrayList; import java.util.Collection; @@ -40,6 +42,8 @@ import java.util.Collection; * @author max */ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements ProjectComponent { + private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.changes.VcsDirtyScopeManagerImpl"); + private final Project myProject; private final ChangeListManager myChangeListManager; private final ProjectLevelVcsManager myVcsManager; @@ -100,6 +104,10 @@ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements Pr public void markEverythingDirty() { if ((! myProject.isOpen()) || myProject.isDisposed() || myVcsManager.getAllActiveVcss().length == 0) return; + if (LOG.isDebugEnabled()) { + LOG.debug("everything dirty: " + Reflection.getCallerClass(1)); + } + final LifeDrop lifeDrop = myLife.doIfAlive(new Runnable() { public void run() { myDirtBuilder.everythingDirty(); @@ -160,6 +168,10 @@ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements Pr || dirsConverted != null && ! dirsConverted.isEmpty(); if (! haveStuff) return; + if (LOG.isDebugEnabled()) { + LOG.debug("paths dirty: " + filesConverted + "; " + dirsConverted + "; " + Reflection.getCallerClass(2)); + } + takeDirt(new Consumer() { public void consume(final DirtBuilder dirt) { if (filesConverted != null) { @@ -218,6 +230,10 @@ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements Pr final boolean haveStuff = filesConverted != null && ! filesConverted.isEmpty() || dirsConverted != null && ! dirsConverted.isEmpty(); if (! haveStuff) return; + if (LOG.isDebugEnabled()) { + LOG.debug("files dirty: " + filesConverted + "; " + dirsConverted + "; " + Reflection.getCallerClass(2)); + } + takeDirt(new Consumer() { public void consume(final DirtBuilder dirt) { if (filesConverted != null) { @@ -240,6 +256,9 @@ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements Pr try { final AbstractVcs vcs = myGuess.getVcsForDirty(file); if (vcs == null) return; + if (LOG.isDebugEnabled()) { + LOG.debug("file dirty: " + file + "; " + Reflection.getCallerClass(2)); + } final VcsRoot root = new VcsRoot(vcs, file); takeDirt(new Consumer() { public void consume(DirtBuilder dirtBuilder) { @@ -254,6 +273,9 @@ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements Pr try { final AbstractVcs vcs = myGuess.getVcsForDirty(file); if (vcs == null) return; + if (LOG.isDebugEnabled()) { + LOG.debug("file dirty: " + file + "; " + Reflection.getCallerClass(1)); + } final FilePathUnderVcs root = new FilePathUnderVcs(file, vcs); takeDirt(new Consumer() { public void consume(DirtBuilder dirtBuilder) { @@ -272,6 +294,9 @@ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements Pr try { final AbstractVcs vcs = myGuess.getVcsForDirty(dir); if (vcs == null) return; + if (LOG.isDebugEnabled()) { + LOG.debug("dir dirty recursively: " + dir + "; " + Reflection.getCallerClass(2)); + } final VcsRoot root = new VcsRoot(vcs, dir); takeDirt(new Consumer() { public void consume(DirtBuilder dirtBuilder) { @@ -286,6 +311,9 @@ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements Pr try { final AbstractVcs vcs = myGuess.getVcsForDirty(path); if (vcs == null) return; + if (LOG.isDebugEnabled()) { + LOG.debug("dir dirty recursively: " + path + "; " + Reflection.getCallerClass(2)); + } final FilePathUnderVcs root = new FilePathUnderVcs(path, vcs); takeDirt(new Consumer() { public void consume(DirtBuilder dirtBuilder) { From a434a2807e48c551afd64ab887988de46a6355f9 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Fri, 10 Feb 2012 21:08:25 +0100 Subject: [PATCH 04/15] quick fix toolwindow activation --- .../src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java index c5f32e12a57f..3cba80b1fe26 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java @@ -719,7 +719,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements final ArrayList commandList, boolean forced, boolean autoFocusContents) { - if (/*!getFocusManagerImpl(myProject).isUnforcedRequestAllowed() && */!forced) return; + if (!FocusManagerImpl.getInstance().isUnforcedRequestAllowed() && !forced) return; if (LOG.isDebugEnabled()) { LOG.debug("enter: activateToolWindowImpl(" + id + ")"); From e7285155992f64f524937691d08f83f14801bff4 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 10 Feb 2012 21:09:08 +0100 Subject: [PATCH 05/15] expire sticky balloons when hidden --- .../intellij/notification/impl/NotificationsManagerImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/notification/impl/NotificationsManagerImpl.java b/platform/platform-impl/src/com/intellij/notification/impl/NotificationsManagerImpl.java index f4475fd7937d..7af1d81950b4 100644 --- a/platform/platform-impl/src/com/intellij/notification/impl/NotificationsManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/notification/impl/NotificationsManagerImpl.java @@ -154,7 +154,7 @@ public class NotificationsManagerImpl extends NotificationsManager implements No case BALLOON: default: Balloon balloon = notifyByBalloon(notification, type, project); - if (!settings.isShouldLog()) { + if (!settings.isShouldLog() || type == NotificationDisplayType.STICKY_BALLOON) { if (balloon == null) { notification.expire(); } else { From e90b093156199a9ee7fb44e668cc63777a347520 Mon Sep 17 00:00:00 2001 From: Dmitry Boulytchev Date: Sat, 11 Feb 2012 01:00:41 +0400 Subject: [PATCH 06/15] Overriden methods supported in a conservative manner (compile server). --- .../deleteMethodImplementation4.log | 2 + .../deleteMethodImplementation5.log | 6 ++ .../deleteMethodImplementation6.log | 6 ++ .../org/jetbrains/ether/GenericTest.java | 6 +- .../jetbrains/ether/IncrementalTestCase.java | 2 +- .../org/jetbrains/ether/MemberChangeTest.java | 2 - .../ether/dependencyView/Mappings.java | 78 ++++++++++--------- 7 files changed, 60 insertions(+), 42 deletions(-) diff --git a/java/java-tests/testData/compileServer/incremental/membersChange/deleteMethodImplementation4.log b/java/java-tests/testData/compileServer/incremental/membersChange/deleteMethodImplementation4.log index 30038ec68e16..db72b0f2704d 100644 --- a/java/java-tests/testData/compileServer/incremental/membersChange/deleteMethodImplementation4.log +++ b/java/java-tests/testData/compileServer/incremental/membersChange/deleteMethodImplementation4.log @@ -5,8 +5,10 @@ Compiling files: src/Base.java End of files Cleaning output files: +out/production/DeleteMethodImplementation4/BaseImpl.class out/production/DeleteMethodImplementation4/BaseImplImpl.class End of files Compiling files: +src/BaseImpl.java src/BaseImplImpl.java End of files diff --git a/java/java-tests/testData/compileServer/incremental/membersChange/deleteMethodImplementation5.log b/java/java-tests/testData/compileServer/incremental/membersChange/deleteMethodImplementation5.log index c8a95e08349b..a36940f74f64 100644 --- a/java/java-tests/testData/compileServer/incremental/membersChange/deleteMethodImplementation5.log +++ b/java/java-tests/testData/compileServer/incremental/membersChange/deleteMethodImplementation5.log @@ -4,3 +4,9 @@ End of files Compiling files: src/Base.java End of files +Cleaning output files: +out/production/DeleteMethodImplementation5/BaseImpl.class +End of files +Compiling files: +src/BaseImpl.java +End of files diff --git a/java/java-tests/testData/compileServer/incremental/membersChange/deleteMethodImplementation6.log b/java/java-tests/testData/compileServer/incremental/membersChange/deleteMethodImplementation6.log index 0548319f9020..e4bd38375b69 100644 --- a/java/java-tests/testData/compileServer/incremental/membersChange/deleteMethodImplementation6.log +++ b/java/java-tests/testData/compileServer/incremental/membersChange/deleteMethodImplementation6.log @@ -4,3 +4,9 @@ End of files Compiling files: src/BaseImpl.java End of files +Cleaning output files: +out/production/DeleteMethodImplementation6/BaseImplImpl.class +End of files +Compiling files: +src/BaseImplImpl.java +End of files diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/GenericTest.java b/jps/jps-builders/testSrc/org/jetbrains/ether/GenericTest.java index facc69d594e6..5fded763c906 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/ether/GenericTest.java +++ b/jps/jps-builders/testSrc/org/jetbrains/ether/GenericTest.java @@ -72,7 +72,7 @@ public class GenericTest extends IncrementalTestCase { public void testChangeToCovariantMethodInBase3() throws Exception { doTest(); } - + */ public void testChangeVarargSignature() throws Exception { doTest(); } @@ -80,7 +80,6 @@ public class GenericTest extends IncrementalTestCase { public void testChangeVarargSignature1() throws Exception { doTest(); } - */ public void testCovariance() throws Exception { doTest(); @@ -114,7 +113,7 @@ public class GenericTest extends IncrementalTestCase { doTest(); } - /* Not working yet + /* Not working yet */ public void testOverrideAnnotatedAnonymousNotRecompile() throws Exception { doTest(); } @@ -122,7 +121,6 @@ public class GenericTest extends IncrementalTestCase { public void testOverrideAnnotatedInner() throws Exception { doTest(); } - */ public void testParamTypes() throws Exception { doTest(); diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java b/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java index 48ed13b9920e..6160a0126ced 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java +++ b/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java @@ -177,7 +177,7 @@ public abstract class IncrementalTestCase extends TestCase { finally { try { closeAppender(); - delete(new File(workDir)); + //delete(new File(workDir)); } finally { Logger.setFactory(oldFactory); diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/MemberChangeTest.java b/jps/jps-builders/testSrc/org/jetbrains/ether/MemberChangeTest.java index 7fbcc9becf45..cfe091f05825 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/ether/MemberChangeTest.java +++ b/jps/jps-builders/testSrc/org/jetbrains/ether/MemberChangeTest.java @@ -116,11 +116,9 @@ public class MemberChangeTest extends IncrementalTestCase { doTest(); } - /* Not working yet public void testDeleteMethodImplementation4() throws Exception { doTest(); } - */ public void testDeleteMethodImplementation5() throws Exception { doTest(); diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java b/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java index d5d3bd1957c0..cc586037d2b9 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java @@ -1103,47 +1103,55 @@ public class Mappings { } if ((m.access & Opcodes.ACC_ABSTRACT) == 0) { + final Collection> overriding = u.findOverridingMethods(m, it, false); + + for (final Pair p : overriding) { + final DependencyContext.S fName = myClassToSourceFile.get(p.second.name); + affectedFiles.add(new File(myContext.getValue(fName))); + } + for (DependencyContext.S p : propagated) { - final ClassRepr s = u.reprByName(p); + if (!p.equals(it.name)) { + final ClassRepr s = u.reprByName(p); - if (s != null) { - final Collection> overridenInS = u.findOverridenMethods(m, s); + if (s != null) { + final Collection> overridenInS = u.findOverridenMethods(m, s); - overridenInS.addAll(overridenMethods); + overridenInS.addAll(overridenMethods); - boolean allAbstract = true; - boolean visited = false; + boolean allAbstract = true; + boolean visited = false; - for (Pair pp : overridenInS) { - final ClassRepr cc = pp.second; + for (Pair pp : overridenInS) { + final ClassRepr cc = pp.second; + + if (cc == myMockClass) { + visited = true; + continue; + } + + if (cc.name.equals(it.name)) { + continue; + } - if (cc == myMockClass) { visited = true; - continue; + allAbstract = ((pp.first.access & Opcodes.ACC_ABSTRACT) > 0) || ((cc.access & Opcodes.ACC_INTERFACE) > 0); + + if (!allAbstract) { + break; + } } - if (cc.name.equals(it.name)) { - continue; - } + if (allAbstract && visited) { + final DependencyContext.S source = myClassToSourceFile.get(p); - visited = true; - allAbstract = ((pp.first.access & Opcodes.ACC_ABSTRACT) > 0) || ((cc.access & Opcodes.ACC_INTERFACE) > 0); - - if (!allAbstract) { - break; - } - } - - if (allAbstract && visited) { - final DependencyContext.S source = myClassToSourceFile.get(p); - - if (source != null) { - final String f = myContext.getValue(source); - debug( - "Removed method is not abstract & is overrides some abstract method which is not then over-overriden in subclass ", - p); - debug("Affecting subclass source file ", f); - affectedFiles.add(new File(f)); + if (source != null) { + final String f = myContext.getValue(source); + debug("Removed method is not abstract & overrides some abstract method which is not then over-overriden in subclass ", + p); + debug("Affecting subclass source file ", f); + affectedFiles.add(new File(f)); + } } } } @@ -1597,19 +1605,19 @@ public class Mappings { for (DependencyContext.S f : delta.getChangedFiles()) { mySourceFileToClasses.remove(f); final Collection classes = delta.mySourceFileToClasses.get(f); - if (classes != null){ + if (classes != null) { mySourceFileToClasses.put(f, classes); } mySourceFileToUsages.remove(f); final Collection clusters = delta.mySourceFileToUsages.get(f); - if (clusters != null){ + if (clusters != null) { mySourceFileToUsages.put(f, clusters); } mySourceFileToAnnotationUsages.remove(f); final Collection usages = delta.mySourceFileToAnnotationUsages.get(f); - if (usages != null){ + if (usages != null) { mySourceFileToAnnotationUsages.put(f, usages); } } @@ -1637,7 +1645,7 @@ public class Mappings { depClasses.retainAll(changedClasses); - if (! classChanged && depClasses.isEmpty()) { + if (!classChanged && depClasses.isEmpty()) { continue; } } From 95bc62e2358d84198befec020b50684f9b8f02c4 Mon Sep 17 00:00:00 2001 From: Dmitry Boulytchev Date: Sat, 11 Feb 2012 01:01:57 +0400 Subject: [PATCH 07/15] Overriden methods supported in a conservative manner (compile server). --- .../generics/overrideAnnotatedAnonymousNotRecompile.log | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/java/java-tests/testData/compileServer/incremental/generics/overrideAnnotatedAnonymousNotRecompile.log b/java/java-tests/testData/compileServer/incremental/generics/overrideAnnotatedAnonymousNotRecompile.log index 4be3d1f3669d..33badcc6d70d 100644 --- a/java/java-tests/testData/compileServer/incremental/generics/overrideAnnotatedAnonymousNotRecompile.log +++ b/java/java-tests/testData/compileServer/incremental/generics/overrideAnnotatedAnonymousNotRecompile.log @@ -4,3 +4,10 @@ End of files Compiling files: src/packageA/Base.java End of files +Cleaning output files: +out/production/OverrideAnnotatedAnonymousNotRecompile/packageA/Derived$1.class +out/production/OverrideAnnotatedAnonymousNotRecompile/packageA/Derived.class +End of files +Compiling files: +src/packageA/Derived.java +End of files From 622232247f2a96864c29651e9769b0d99f56aa59 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Sat, 11 Feb 2012 11:08:25 +0400 Subject: [PATCH 08/15] IDEA-80689 Groovy: Extract Closure Parameter applied to a command expression results with invalid code --- .../psi/impl/ApplicationStatementUtil.java | 104 ++++++++++++++++++ .../groovy/lang/psi/impl/PsiImplUtil.java | 7 +- .../refactoring/extract/ExtractUtil.java | 22 +--- .../extract/GroovyExtractChooser.java | 4 +- .../introduce/GrIntroduceHandlerBase.java | 4 +- .../parameter/GrIntroduceParameterDialog.java | 15 ++- ...troduceParameterMethodUsagesProcessor.java | 6 +- .../extract/closure/ExtractClosureTest.groovy | 14 +++ ...thodTest.java => ExtractMethodTest.groovy} | 30 ++--- .../GrIntroduceParameterTest.java | 1 + .../extractMethod/terribleAppStatement.test | 11 ++ .../appStatement/AppStatementAfter.groovy | 1 + .../appStatement/AppStatementBefore.groovy | 1 + .../appStatement/AppStatementMyClass.groovy | 5 + .../IncorrectArgumentListAfter.groovy | 2 +- 15 files changed, 180 insertions(+), 47 deletions(-) create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/ApplicationStatementUtil.java rename plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/extract/method/{ExtractMethodTest.java => ExtractMethodTest.groovy} (81%) create mode 100644 plugins/groovy/testdata/groovy/refactoring/extractMethod/terribleAppStatement.test create mode 100644 plugins/groovy/testdata/refactoring/introduceParameterGroovy/appStatement/AppStatementAfter.groovy create mode 100644 plugins/groovy/testdata/refactoring/introduceParameterGroovy/appStatement/AppStatementBefore.groovy create mode 100644 plugins/groovy/testdata/refactoring/introduceParameterGroovy/appStatement/AppStatementMyClass.groovy diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/ApplicationStatementUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/ApplicationStatementUtil.java new file mode 100644 index 000000000000..e6873b1a0882 --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/ApplicationStatementUtil.java @@ -0,0 +1,104 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.groovy.lang.psi.impl; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiElement; +import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrApplicationStatement; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCommandArgumentList; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression; + +/** + * @author Max Medvedev + */ +public class ApplicationStatementUtil { + private static final Logger LOG = Logger.getInstance(ApplicationStatementUtil.class); + + public static GrExpression convertToMethodCallExpression(GrExpression expr) { + final Project project = expr.getProject(); + final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(project); + + boolean copied = false; + if (expr instanceof GrApplicationStatement) { + expr = convertAppInternal(factory, (GrApplicationStatement)expr); + copied = true; + } + + if (expr instanceof GrReferenceExpression && + ((GrReferenceExpression)expr).getDotToken() == null && + ((GrReferenceExpression)expr).getQualifier() != null) { + expr = convertRefInternal(factory, ((GrReferenceExpression)expr)); + copied = true; + } + + + if (!shouldManage(expr)) return expr; + if (!copied) expr = (GrExpression)expr.copy(); + + for (PsiElement child = expr.getFirstChild(); child != null; child = child.getFirstChild()) { + if (child instanceof GrApplicationStatement) { + child = child.replace(convertAppInternal(factory, (GrApplicationStatement)child)); + } + else if (child instanceof GrReferenceExpression && + ((GrReferenceExpression)child).getDotToken() == null && + ((GrReferenceExpression)child).getQualifier() != null) { + child = child.replace(convertRefInternal(factory, ((GrReferenceExpression)child))); + } + } + + return expr; + } + + private static boolean shouldManage(GrExpression expr) { + for (PsiElement child = expr.getFirstChild(); child != null; child = child.getFirstChild()) { + if (child instanceof GrApplicationStatement) { + return true; + } + else if (child instanceof GrReferenceExpression && + ((GrReferenceExpression)child).getDotToken() == null && + ((GrReferenceExpression)child).getQualifier() != null) { + return true; + } + } + return false; + } + + private static GrReferenceExpression convertRefInternal(GroovyPsiElementFactory factory, GrReferenceExpression ref) { + ref.addAfter(factory.createDotToken("."), ref.getQualifier()); + return ref; + } + + private static GrMethodCallExpression convertAppInternal(GroovyPsiElementFactory factory, GrApplicationStatement app) { + final GrCommandArgumentList list = app.getArgumentList(); + + final GrMethodCallExpression prototype = (GrMethodCallExpression)factory.createExpressionFromText("foo()"); + prototype.getInvokedExpression().replace(app.getInvokedExpression()); + final GrArgumentList pList = prototype.getArgumentList(); + LOG.assertTrue(pList != null); + + final PsiElement anchor = pList.getRightParen(); + for (PsiElement ch = list.getFirstChild(); ch != null; ch = ch.getNextSibling()) { + pList.addBefore(ch, anchor); + } + + return prototype; + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/PsiImplUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/PsiImplUtil.java index fd65881d29d5..f837f3687ec3 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/PsiImplUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/PsiImplUtil.java @@ -110,16 +110,15 @@ public class PsiImplUtil { private static boolean isAfterIdentifier(PsiElement el) { final PsiElement prev = GeeseUtil.getPreviousNonWhitespaceToken(el); - return prev != null && prev.getNode().getElementType() == GroovyTokenTypes.mIDENT; + return prev != null && prev.getNode().getElementType() == mIDENT; } public static GrExpression replaceExpression(GrExpression oldExpr, GrExpression newExpr, boolean removeUnnecessaryParentheses) { PsiElement oldParent = oldExpr.getParent(); if (oldParent == null) throw new PsiInvalidElementAccessException(oldExpr); - if (newExpr instanceof GrApplicationStatement && !(oldExpr instanceof GrApplicationStatement)) { - GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(oldExpr.getProject()); - newExpr = factory.createMethodCallByAppCall(((GrApplicationStatement)newExpr)); + if (!(oldExpr instanceof GrApplicationStatement)) { + newExpr = ApplicationStatementUtil.convertToMethodCallExpression(newExpr); } // Remove unnecessary parentheses diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractUtil.java index 309578d656a4..e6d501651b6a 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractUtil.java @@ -30,13 +30,16 @@ import org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrAssignmentExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner; import org.jetbrains.plugins.groovy.lang.psi.api.util.GrVariableDeclarationOwner; import org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.VariableInfo; +import org.jetbrains.plugins.groovy.lang.psi.impl.ApplicationStatementUtil; import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; @@ -311,21 +314,8 @@ public class ExtractUtil { boolean addReturn = !isVoid && expr != null && expr.getType() != null && expr.getType() != PsiType.VOID; if (addReturn) { buffer.append("return "); - if (expr instanceof GrApplicationStatement) { - final GrApplicationStatement appStatement = (GrApplicationStatement)expr; - - buffer.append(appStatement.getInvokedExpression().getText()); - buffer.append('('); - - final GrCommandArgumentList argList = appStatement.getArgumentList(); - if (argList != null) { - buffer.append(argList.getText()); - } - buffer.append(')'); - } - else { - buffer.append(expr.getText()); - } + expr = ApplicationStatementUtil.convertToMethodCallExpression(expr); + buffer.append(expr.getText()); } else { buffer.append(expr != null ? expr.getText() : ""); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/GroovyExtractChooser.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/GroovyExtractChooser.java index f32ed727f3b3..4c8ee6d821bc 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/GroovyExtractChooser.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/GroovyExtractChooser.java @@ -113,7 +113,9 @@ public class GroovyExtractChooser { throw new GrRefactoringError(GroovyRefactoringBundle.message("selected.block.should.represent.an.expression")); } - if (ExtractUtil.isSingleExpression(statements) && statement0.getParent() instanceof GrAssignmentExpression && ((GrAssignmentExpression)statement0.getParent()).getLValue()==statement0) { + if (ExtractUtil.isSingleExpression(statements) && + statement0.getParent() instanceof GrAssignmentExpression && + ((GrAssignmentExpression)statement0.getParent()).getLValue() == statement0) { throw new GrRefactoringError(GroovyRefactoringBundle.message("selected.expression.should.not.be.lvalue")); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java index 85c2530e7aee..61cd64f3e1c8 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java @@ -107,9 +107,7 @@ public abstract class GrIntroduceHandlerBase"zxcvbn".substring 2 charAt(1) +} +foo() +''', ''' +void foo(Closure closure) { + def s = closure() +} +foo {return "zxcvbn".substring(2).charAt(1)} ''') } } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodTest.groovy similarity index 81% rename from plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodTest.java rename to plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodTest.groovy index 522cb0214bf0..04fee16b1f12 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodTest.groovy @@ -16,14 +16,13 @@ package org.jetbrains.plugins.groovy.refactoring.extract.method; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.psi.impl.source.PostprocessReformattingAspect; -import com.intellij.refactoring.util.CommonRefactoringUtil; -import org.jetbrains.plugins.groovy.GroovyFileType; -import org.jetbrains.plugins.groovy.LightGroovyTestCase; -import org.jetbrains.plugins.groovy.util.TestUtils; -import java.util.List; +import com.intellij.openapi.util.text.StringUtil +import com.intellij.psi.impl.source.PostprocessReformattingAspect +import com.intellij.refactoring.util.CommonRefactoringUtil +import org.jetbrains.plugins.groovy.GroovyFileType +import org.jetbrains.plugins.groovy.LightGroovyTestCase +import org.jetbrains.plugins.groovy.util.TestUtils /** * @author ilyas @@ -31,29 +30,29 @@ import java.util.List; public class ExtractMethodTest extends LightGroovyTestCase { @Override protected String getBasePath() { - return TestUtils.getTestDataPath() + "groovy/refactoring/extractMethod/"; + return TestUtils.testDataPath + "groovy/refactoring/extractMethod/"; } - private void doAntiTest(String errorMessage) throws Exception { + private void doAntiTest(String errorMessage) { GroovyExtractMethodHandler handler = configureFromText(readInput().get(0)); try { - handler.invoke(getProject(), myFixture.getEditor(), myFixture.getFile(), null); + handler.invoke(project, myFixture.editor, myFixture.file, null); assertTrue(false); } catch (CommonRefactoringUtil.RefactoringErrorHintException e) { - assertEquals(errorMessage, e.getLocalizedMessage()); + assertEquals(errorMessage, e.localizedMessage); } } private List readInput() { - return TestUtils.readInput(getTestDataPath() + getTestName(true) + ".test"); + return TestUtils.readInput(testDataPath + getTestName(true) + ".test"); } private void doTest() { final List data = readInput(); GroovyExtractMethodHandler handler = configureFromText(data.get(0)); - handler.invoke(getProject(), myFixture.getEditor(), myFixture.getFile(), null); - PostprocessReformattingAspect.getInstance(getProject()).doPostponedFormatting(); + handler.invoke(project, myFixture.editor, myFixture.file, null); + PostprocessReformattingAspect.getInstance(project).doPostponedFormatting(); myFixture.checkResult(StringUtil.trimEnd(data.get(1), "\n")); } @@ -64,7 +63,7 @@ public class ExtractMethodTest extends LightGroovyTestCase { fileText = TestUtils.removeEndMarker(fileText); myFixture.configureByText(GroovyFileType.GROOVY_FILE_TYPE, fileText); - myFixture.getEditor().getSelectionModel().setSelection(startOffset, endOffset); + myFixture.editor.selectionModel.setSelection(startOffset, endOffset); return new GroovyExtractMethodHandler(); } @@ -114,4 +113,5 @@ public class ExtractMethodTest extends LightGroovyTestCase { public void testWildCardReturnType() {doTest();} public void testParamChangedInsideExtractedMethod() {doTest();} + public void testTerribleAppStatement() {doTest()} } \ No newline at end of file diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceParameter/GrIntroduceParameterTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceParameter/GrIntroduceParameterTest.java index 5de6df11474f..cf4e7c8249a5 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceParameter/GrIntroduceParameterTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceParameter/GrIntroduceParameterTest.java @@ -295,4 +295,5 @@ public class GrIntroduceParameterTest extends LightCodeInsightFixtureTestCase { public void testClosureArgWithEmptyArgList() {doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, true, false);} public void testScriptMethod() {doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, true, false);} + public void testAppStatement() {doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false);} } diff --git a/plugins/groovy/testdata/groovy/refactoring/extractMethod/terribleAppStatement.test b/plugins/groovy/testdata/groovy/refactoring/extractMethod/terribleAppStatement.test new file mode 100644 index 000000000000..870a4066921a --- /dev/null +++ b/plugins/groovy/testdata/groovy/refactoring/extractMethod/terribleAppStatement.test @@ -0,0 +1,11 @@ +def foo() { + def s = "zxcvbn".substring 2 charAt(1) +} +----- +def foo() { + def s = testMethod() +} + +private char testMethod() { + return "zxcvbn".substring(2).charAt(1) +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/introduceParameterGroovy/appStatement/AppStatementAfter.groovy b/plugins/groovy/testdata/refactoring/introduceParameterGroovy/appStatement/AppStatementAfter.groovy new file mode 100644 index 000000000000..5ed212b144fc --- /dev/null +++ b/plugins/groovy/testdata/refactoring/introduceParameterGroovy/appStatement/AppStatementAfter.groovy @@ -0,0 +1 @@ +new A().foo("zxcvbn".substring(2).charAt(1)) \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/introduceParameterGroovy/appStatement/AppStatementBefore.groovy b/plugins/groovy/testdata/refactoring/introduceParameterGroovy/appStatement/AppStatementBefore.groovy new file mode 100644 index 000000000000..56e2e38b9a3d --- /dev/null +++ b/plugins/groovy/testdata/refactoring/introduceParameterGroovy/appStatement/AppStatementBefore.groovy @@ -0,0 +1 @@ +new A().foo() \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/introduceParameterGroovy/appStatement/AppStatementMyClass.groovy b/plugins/groovy/testdata/refactoring/introduceParameterGroovy/appStatement/AppStatementMyClass.groovy new file mode 100644 index 000000000000..e4828d69722f --- /dev/null +++ b/plugins/groovy/testdata/refactoring/introduceParameterGroovy/appStatement/AppStatementMyClass.groovy @@ -0,0 +1,5 @@ +class A { + void foo() { + def s = "zxcvbn".substring(2).charAt(1) + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/introduceParameterGroovy/incorrectArgumentList/IncorrectArgumentListAfter.groovy b/plugins/groovy/testdata/refactoring/introduceParameterGroovy/incorrectArgumentList/IncorrectArgumentListAfter.groovy index 853f4929faec..52ba1446be3e 100644 --- a/plugins/groovy/testdata/refactoring/introduceParameterGroovy/incorrectArgumentList/IncorrectArgumentListAfter.groovy +++ b/plugins/groovy/testdata/refactoring/introduceParameterGroovy/incorrectArgumentList/IncorrectArgumentListAfter.groovy @@ -1 +1 @@ -new A().foo(27 + 4.5) \ No newline at end of file +new A().foo(27+ 4.5) \ No newline at end of file From 035c4cd67f72976f4c1bb95c59925a29d46c016b Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Sat, 11 Feb 2012 15:14:45 +0100 Subject: [PATCH 09/15] dir diff context menu --- .../src/idea/PlatformActions.xml | 6 ++ .../openapi/diff/impl/dir/DirDiffElement.java | 4 ++ .../openapi/diff/impl/dir/DirDiffPanel.java | 33 +++++++++- .../impl/dir/actions/popup/SetCopyToLeft.java | 30 +++++++++ .../dir/actions/popup/SetCopyToRight.java | 30 +++++++++ .../impl/dir/actions/popup/SetDelete.java | 30 +++++++++ .../dir/actions/popup/SetOperationToBase.java | 66 +++++++++++++++++++ 7 files changed, 197 insertions(+), 2 deletions(-) create mode 100644 platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/popup/SetCopyToLeft.java create mode 100644 platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/popup/SetCopyToRight.java create mode 100644 platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/popup/SetDelete.java create mode 100644 platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/popup/SetOperationToBase.java diff --git a/platform/platform-resources/src/idea/PlatformActions.xml b/platform/platform-resources/src/idea/PlatformActions.xml index dd30603f1365..7e170bca3e77 100644 --- a/platform/platform-resources/src/idea/PlatformActions.xml +++ b/platform/platform-resources/src/idea/PlatformActions.xml @@ -533,6 +533,12 @@ + + + + + + diff --git a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffElement.java b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffElement.java index 08f327c3ab49..beb08b6a427b 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffElement.java +++ b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffElement.java @@ -192,6 +192,10 @@ public class DirDiffElement { } } + public void setOperation(@NotNull DirDiffOperation operation) { + myOperation = operation; + } + public Icon getIcon() { return mySource != null ? mySource.getIcon() : myTarget.getIcon(); } diff --git a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffPanel.java b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffPanel.java index ec9c59ce7633..5ea1bf1a22ae 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffPanel.java +++ b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffPanel.java @@ -29,6 +29,7 @@ import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.ui.FilterComponent; +import com.intellij.ui.PopupHandler; import com.intellij.ui.TableSpeedSearch; import com.intellij.ui.awt.RelativePoint; import com.intellij.ui.components.JBLabel; @@ -37,6 +38,7 @@ import com.intellij.ui.components.JBLoadingPanelListener; import com.intellij.ui.table.JBTable; import com.intellij.util.diff.FilesTooBigForDiffException; import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.NonNls; import javax.swing.*; import javax.swing.border.EmptyBorder; @@ -54,7 +56,7 @@ import java.util.concurrent.atomic.AtomicBoolean; * @author Konstantin Bulenkov */ @SuppressWarnings({"unchecked"}) -public class DirDiffPanel implements Disposable { +public class DirDiffPanel implements Disposable, DataProvider { public static final String DIVIDER_PROPERTY = "dir.diff.panel.divider.location"; private JPanel myDiffPanel; private JBTable myTable; @@ -77,6 +79,8 @@ public class DirDiffPanel implements Disposable { private JComponent myViewComponent; private DiffElement myCurrentElement; private String oldFilter; + public static final DataKey DIR_DIFF_MODEL = DataKey.create("DIR_DIFF_MODEL"); + public static final DataKey DIR_DIFF_TABLE = DataKey.create("DIR_DIFF_TABLE"); public DirDiffPanel(DirDiffTableModel model, DirDiffWindow wnd) { myModel = model; @@ -130,6 +134,7 @@ public class DirDiffPanel implements Disposable { myTable.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { + if (e.getButton() == MouseEvent.BUTTON3) return; if (myTable.getRowCount() > 0) { final int row = myTable.rowAtPoint(e.getPoint()); final int col = myTable.columnAtPoint(e.getPoint()); @@ -192,12 +197,22 @@ public class DirDiffPanel implements Disposable { } } final DirDiffToolbarActions actions = new DirDiffToolbarActions(myModel, myDiffPanel); - final ActionToolbar toolbar = ActionManager.getInstance().createActionToolbar("DirDiff", actions, true); + final ActionManager actionManager = ActionManager.getInstance(); + final ActionToolbar toolbar = actionManager.createActionToolbar("DirDiff", actions, true); registerCustomShortcuts(actions, myTable); myToolBarPanel.add(toolbar.getComponent(), BorderLayout.CENTER); final JBLabel label = new JBLabel("Use Space button or mouse click to change operation for the selected elements. Enter to perform.", SwingConstants.CENTER); label.setForeground(UIUtil.getInactiveTextColor()); UIUtil.applyStyle(UIUtil.ComponentStyle.MINI, label); + DataManager.registerDataProvider(myFilesPanel, this); + myTable.addMouseListener(new PopupHandler() { + @Override + public void invokePopup(Component comp, int x, int y) { + final JPopupMenu popupMenu = + actionManager.createActionPopupMenu("DirDiffPanel", (ActionGroup)actionManager.getAction("DirDiffMenu")).getComponent(); + popupMenu.show(comp, x, y); + } + }); myFilesPanel.add(label, BorderLayout.SOUTH); final JBLoadingPanel loadingPanel = new JBLoadingPanel(new BorderLayout(), wnd.getDisposable()); loadingPanel.addListener(new JBLoadingPanelListener.Adapter() { @@ -472,4 +487,18 @@ public class DirDiffPanel implements Disposable { public void setupSplitter() { mySplitPanel.setDividerLocation(Integer.valueOf(PropertiesComponent.getInstance().getValue(DIVIDER_PROPERTY, "200"))); } + + @Override + public Object getData(@NonNls String dataId) { + if (PlatformDataKeys.PROJECT.is(dataId)) { + return myModel.getProject(); + } + if (DIR_DIFF_MODEL.is(dataId)) { + return myModel; + } + if (DIR_DIFF_TABLE.is(dataId)) { + return myTable; + } + return null; + } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/popup/SetCopyToLeft.java b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/popup/SetCopyToLeft.java new file mode 100644 index 000000000000..92839c69c867 --- /dev/null +++ b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/popup/SetCopyToLeft.java @@ -0,0 +1,30 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.diff.impl.dir.actions.popup; + +import com.intellij.openapi.diff.impl.dir.DirDiffOperation; +import org.jetbrains.annotations.NotNull; + +/** + * @author Konstantin Bulenkov + */ +public class SetCopyToLeft extends SetOperationToBase { + @NotNull + @Override + protected DirDiffOperation getOperation() { + return DirDiffOperation.COPY_FROM; + } +} diff --git a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/popup/SetCopyToRight.java b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/popup/SetCopyToRight.java new file mode 100644 index 000000000000..80d982d8ec28 --- /dev/null +++ b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/popup/SetCopyToRight.java @@ -0,0 +1,30 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.diff.impl.dir.actions.popup; + +import com.intellij.openapi.diff.impl.dir.DirDiffOperation; +import org.jetbrains.annotations.NotNull; + +/** + * @author Konstantin Bulenkov + */ +public class SetCopyToRight extends SetOperationToBase { + @NotNull + @Override + protected DirDiffOperation getOperation() { + return DirDiffOperation.COPY_TO; + } +} diff --git a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/popup/SetDelete.java b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/popup/SetDelete.java new file mode 100644 index 000000000000..3a8038108a61 --- /dev/null +++ b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/popup/SetDelete.java @@ -0,0 +1,30 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.diff.impl.dir.actions.popup; + +import com.intellij.openapi.diff.impl.dir.DirDiffOperation; +import org.jetbrains.annotations.NotNull; + +/** + * @author Konstantin Bulenkov + */ +public class SetDelete extends SetOperationToBase { + @NotNull + @Override + protected DirDiffOperation getOperation() { + return DirDiffOperation.DELETE; + } +} diff --git a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/popup/SetOperationToBase.java b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/popup/SetOperationToBase.java new file mode 100644 index 000000000000..264757c85ea2 --- /dev/null +++ b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/popup/SetOperationToBase.java @@ -0,0 +1,66 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.diff.impl.dir.actions.popup; + +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.diff.impl.dir.DirDiffElement; +import com.intellij.openapi.diff.impl.dir.DirDiffOperation; +import com.intellij.openapi.diff.impl.dir.DirDiffPanel; +import com.intellij.openapi.diff.impl.dir.DirDiffTableModel; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; + +/** + * @author Konstantin Bulenkov + */ +public abstract class SetOperationToBase extends AnAction { + @Override + public void actionPerformed(AnActionEvent e) { + DirDiffOperation operation = getOperation(); + final DirDiffTableModel model = getModel(e); + final JTable table = getTable(e); + assert model != null && table != null; + for (DirDiffElement element : model.getSelectedElements()) { + element.setOperation(operation); + } + table.repaint(); + } + + @NotNull + protected abstract DirDiffOperation getOperation(); + + @Override + public void update(AnActionEvent e) { + final DirDiffTableModel model = getModel(e); + final JTable table = getTable(e); + e.getPresentation().setEnabled(table != null + && model != null + && !model.getSelectedElements().isEmpty()); + } + + @Nullable + private static JTable getTable(AnActionEvent e) { + return e.getData(DirDiffPanel.DIR_DIFF_TABLE); + } + + @Nullable + public static DirDiffTableModel getModel(AnActionEvent e) { + return e.getData(DirDiffPanel.DIR_DIFF_MODEL); + } +} From d585fdd30f35a06a3b7a0c15b0694754d138dd02 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Sat, 11 Feb 2012 15:21:45 +0100 Subject: [PATCH 10/15] additional checks --- .../com/intellij/openapi/diff/impl/dir/DirDiffElement.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffElement.java b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffElement.java index beb08b6a427b..c46fc1dd7ae6 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffElement.java +++ b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffElement.java @@ -193,6 +193,11 @@ public class DirDiffElement { } public void setOperation(@NotNull DirDiffOperation operation) { + if (myType == DType.EQUAL || myType == DType.SEPARATOR) return; + if (myType == DType.TARGET && operation == COPY_TO) return; + if (myType == DType.SOURCE && operation == COPY_FROM) return; + if (myType == DType.CHANGED && operation == DELETE) return; + myOperation = operation; } From c13789d6c8d2baa2fd31a0f5a5951472fb4b70c8 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Sat, 11 Feb 2012 18:01:26 +0100 Subject: [PATCH 11/15] collect imports info via annotation processing API and feed it to dependency Mappings --- .../proto/javac_remote_proto.proto | 15 +- .../jps/incremental/java/JavaBuilder.java | 95 +-- .../jps/javac/DiagnosticOutputConsumer.java | 5 +- .../jetbrains/jps/javac/JavacASTAnalyser.java | 204 ++++-- .../org/jetbrains/jps/javac/JavacMain.java | 4 +- .../jetbrains/jps/javac/JavacProtoUtil.java | 17 +- .../jetbrains/jps/javac/JavacRemoteProto.java | 579 +++++++++++++++++- .../org/jetbrains/jps/javac/JavacServer.java | 6 + .../jps/javac/JavacServerResponseHandler.java | 13 +- .../ether/dependencyView/Callbacks.java | 4 +- .../ether/dependencyView/Mappings.java | 17 +- 11 files changed, 833 insertions(+), 126 deletions(-) diff --git a/jps/jps-builders/proto/javac_remote_proto.proto b/jps/jps-builders/proto/javac_remote_proto.proto index 1f280d6c9e92..c9991c036046 100644 --- a/jps/jps-builders/proto/javac_remote_proto.proto +++ b/jps/jps-builders/proto/javac_remote_proto.proto @@ -47,8 +47,9 @@ message Message { enum Type { BUILD_MESSAGE = 1; OUTPUT_OBJECT = 2; - BUILD_COMPLETED = 3; - REQUEST_ACK = 4; + CLASS_DATA = 3; + BUILD_COMPLETED = 4; + REQUEST_ACK = 5; } message CompileMessage { @@ -87,10 +88,18 @@ message Message { optional bytes content = 7; } + message ClassData { + required string class_name = 1; + repeated string import_statement = 2; + repeated string static_import = 3; + repeated string identifier = 4; + } + required Type response_type = 1; optional CompileMessage compile_message = 2; optional OutputObject output_object = 3; - optional bool completion_status = 4; + optional ClassData class_data = 4; + optional bool completion_status = 5; } required UUID session_id = 1; diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java index bfde575cf4d9..abcb48adad05 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java @@ -70,6 +70,8 @@ public class JavaBuilder extends ModuleLevelBuilder { private static final Key DELTA_MAPPINGS_CALLBACK_KEY = Key.create("_dependency_data_"); private final ExecutorService myTaskRunner; + private int myTasksInProgress = 0; + private final Object myCounterLock = new Object(); private final List myClassProcessors = new ArrayList(); public JavaBuilder(ExecutorService tasksExecutor) { @@ -375,10 +377,45 @@ public class JavaBuilder extends ModuleLevelBuilder { return rc; } finally { - classesConsumer.ensurePendingTasksCompleted(); + ensurePendingTasksCompleted(); } } + private void ensurePendingTasksCompleted() { + synchronized (myCounterLock) { + while (myTasksInProgress > 0) { + try { + myCounterLock.wait(); + } + catch (InterruptedException ignored) { + } + } + } + } + + private void submitAsyncTask(final Runnable taskRunnable) { + synchronized (myCounterLock) { + myTasksInProgress++; + } + myTaskRunner.submit(new Runnable() { + public void run() { + try { + taskRunnable.run(); + } + finally { + synchronized (myCounterLock) { + myTasksInProgress = Math.max(0, myTasksInProgress - 1); + if (myTasksInProgress == 0) { + myCounterLock.notifyAll(); + } + } + } + } + }); + } + + + private static JavacServerClient ensureJavacServerLaunched(CompileContext context) throws Exception { final ExternalJavacDescriptor descriptor = ExternalJavacDescriptor.KEY.get(context); if (descriptor != null) { @@ -736,7 +773,7 @@ public class JavaBuilder extends ModuleLevelBuilder { return version >= Opcodes.V1_6 && version != Opcodes.V1_1 ? ClassWriter.COMPUTE_FRAMES : ClassWriter.COMPUTE_MAXS; } - private static class DiagnosticSink implements DiagnosticOutputConsumer { + private class DiagnosticSink implements DiagnosticOutputConsumer { private final CompileContext myContext; private volatile int myErrorCount = 0; private volatile int myWarningCount = 0; @@ -745,6 +782,20 @@ public class JavaBuilder extends ModuleLevelBuilder { myContext = context; } + public void registerImports(final String className, final Collection imports, final Collection staticImports) { + submitAsyncTask(new Runnable() { + public void run() { + final Callbacks.Backend callback = DELTA_MAPPINGS_CALLBACK_KEY.get(myContext); + if (callback != null) { + final BuildDataManager dataManager = myContext.getDataManager(); + synchronized (dataManager.getMappings()) { + callback.registerImports(className, imports, staticImports); + } + } + } + }); + } + public void outputLineAvailable(String line) { if (!StringUtil.isEmpty(line)) { //if (line.startsWith("[") && line.endsWith("]")) { @@ -1068,8 +1119,6 @@ public class JavaBuilder extends ModuleLevelBuilder { private class ClassProcessingConsumer implements OutputFileConsumer { private final CompileContext myCompileContext; private final OutputFileConsumer myDelegateOutputFileSink; - private int myTasksInProgress = 0; - private final Object myCounterLock = new Object(); public ClassProcessingConsumer(CompileContext compileContext, OutputFileConsumer sink) { myCompileContext = compileContext; @@ -1081,8 +1130,7 @@ public class JavaBuilder extends ModuleLevelBuilder { } public void save(@NotNull final OutputFileObject fileObject) { - incTaskCount(); - myTaskRunner.submit(new Runnable() { + submitAsyncTask(new Runnable() { public void run() { try { for (ClassPostProcessor processor : myClassProcessors) { @@ -1090,43 +1138,10 @@ public class JavaBuilder extends ModuleLevelBuilder { } } finally { - try { - myDelegateOutputFileSink.save(fileObject); - } - finally { - decTaskCount(); - } + myDelegateOutputFileSink.save(fileObject); } } }); } - - private void decTaskCount() { - synchronized (myCounterLock) { - myTasksInProgress = Math.max(0, myTasksInProgress - 1); - if (myTasksInProgress == 0) { - myCounterLock.notifyAll(); - } - } - } - - private void incTaskCount() { - synchronized (myCounterLock) { - myTasksInProgress++; - } - } - - public void ensurePendingTasksCompleted() { - synchronized (myCounterLock) { - while (myTasksInProgress > 0) { - try { - myCounterLock.wait(); - } - catch (InterruptedException ignored) { - } - } - } - } - } } diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/DiagnosticOutputConsumer.java b/jps/jps-builders/src/org/jetbrains/jps/javac/DiagnosticOutputConsumer.java index 0230d254f7c1..f052f1e30653 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/javac/DiagnosticOutputConsumer.java +++ b/jps/jps-builders/src/org/jetbrains/jps/javac/DiagnosticOutputConsumer.java @@ -1,7 +1,7 @@ package org.jetbrains.jps.javac; -import javax.tools.DiagnosticListener; -import javax.tools.JavaFileObject; +import javax.tools.*; +import java.util.Collection; /** * @author Eugene Zhuravlev @@ -9,4 +9,5 @@ import javax.tools.JavaFileObject; */ public interface DiagnosticOutputConsumer extends DiagnosticListener { void outputLineAvailable(String line); + void registerImports(String className, Collection imports, Collection staticImports); } diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacASTAnalyser.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacASTAnalyser.java index 33d78d74661f..a76d5ccb104e 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacASTAnalyser.java +++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacASTAnalyser.java @@ -1,17 +1,16 @@ package org.jetbrains.jps.javac; -import com.sun.source.tree.*; +import com.sun.source.tree.ClassTree; +import com.sun.source.tree.ImportTree; +import com.sun.source.tree.Tree; import com.sun.source.util.TreeScanner; import com.sun.source.util.Trees; -import javax.annotation.processing.AbstractProcessor; -import javax.annotation.processing.ProcessingEnvironment; -import javax.annotation.processing.RoundEnvironment; -import javax.annotation.processing.SupportedAnnotationTypes; +import javax.annotation.processing.*; +import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; -import javax.lang.model.element.Modifier; -import javax.lang.model.element.Name; import javax.lang.model.element.TypeElement; +import java.util.HashSet; import java.util.Set; /** @@ -19,13 +18,15 @@ import java.util.Set; * Date: 2/1/12 * */ -//@SupportedSourceVersion(SourceVersion.RELEASE_7) +@SupportedSourceVersion(SourceVersion.RELEASE_7) @SupportedAnnotationTypes("*") public class JavacASTAnalyser extends AbstractProcessor{ private Trees myTrees; + private final DiagnosticOutputConsumer myOutputConsumer; private final boolean mySuppressOtherProcessors; - public JavacASTAnalyser(boolean suppressOtherProcessors) { + public JavacASTAnalyser(DiagnosticOutputConsumer outputConsumer, boolean suppressOtherProcessors) { + myOutputConsumer = outputConsumer; mySuppressOtherProcessors = suppressOtherProcessors; } @@ -37,65 +38,158 @@ public class JavacASTAnalyser extends AbstractProcessor{ @Override public boolean process(Set annotations, RoundEnvironment roundEnv) { - MyAnalyzer scaner = new MyAnalyzer(); - for (Element element : roundEnv.getRootElements()) { - final Tree tree = myTrees.getTree(element); - scaner.scan(tree, myTrees); - } + final Set elements = roundEnv.getRootElements(); + for (Element element : elements) { + if (!(element instanceof TypeElement)) { + continue; + } + final TypeElement typeElement = (TypeElement)element; + final ImportsCollector importsCollector = new ImportsCollector(); + importsCollector.scan(myTrees.getPath(typeElement).getParentPath().getLeaf(), myTrees); + + final Set imports = importsCollector.getImports(); + final Set staticImports = importsCollector.getStaticImports(); + + if (!imports.isEmpty() || !staticImports.isEmpty()) { + final String className = typeElement.getQualifiedName().toString(); + myOutputConsumer.registerImports(className, imports, staticImports); + } + break; + } return mySuppressOtherProcessors; } + private static class ImportsCollector extends TreeScanner { + private Set myImports = new HashSet(); + private Set myStaticImports = new HashSet(); + + public Set getImports() { + return myImports; + } + + public Set getStaticImports() { + return myStaticImports; + } - private static class MyAnalyzer extends TreeScanner { - @Override public Object visitImport(ImportTree node, Trees trees) { - return null/*super.visitImport(node, trees)*/; + final Tree identifier = node.getQualifiedIdentifier(); + final Set container = node.isStatic()? myStaticImports : myImports; + container.add(identifier.toString()); + return null; } - @Override public Object visitClass(ClassTree node, Trees trees) { - return scan(node.getMembers(), trees); - } - - @Override - public Object visitVariable(VariableTree node, Trees trees) { - final ModifiersTree modifiers = node.getModifiers(); - final Set flags = modifiers.getFlags(); - if (flags.contains(Modifier.STATIC) && flags.contains(Modifier.FINAL)) { - final Name variableName = node.getName(); - // todo register constant - final ConstantRefsFinder finder = new ConstantRefsFinder(); - finder.scan(node.getInitializer(), trees); - // todo: process found refs - } return null; } - @Override - public Object visitMethod(MethodTree node, Trees trees) { - final ConstantRefsFinder finder = new ConstantRefsFinder(); - finder.scan(node.getBody(), trees); - // todo: process found refs - return null; - } - } + //public void registerOverriddenMethod(TypeElement classElement, ExecutableElement method) { + // final Elements utils = myProcessingEnvironment.getElementUtils(); + // final String qName = utils.getBinaryName(classElement).toString(); + // List descriptors = myOverriddenMethods.get(qName); + // if (descriptors == null) { + // descriptors = new ArrayList(); + // myOverriddenMethods.put(qName, descriptors); + // } + // final StringBuilder buf = new StringBuilder(); + // buf.append("("); + // for (VariableElement param : method.getParameters()) { + // buf.append(getSignature(param.asType())); + // } + // buf.append(")").append(getSignature(method.getReturnType())); + // descriptors.add(new MethodDescriptor(method.getSimpleName().toString(), buf.toString())); + //} - private static class ConstantRefsFinder extends TreeScanner { - @Override - public Object visitMethodInvocation(MethodInvocationTree node, Trees trees) { - return scan(node.getArguments(), trees); - } - - @Override - public Object visitMemberSelect(MemberSelectTree node, Trees trees) { - return super.visitMemberSelect(node, trees); - } - - @Override - public Object visitIdentifier(IdentifierTree node, Trees trees) { - return super.visitIdentifier(node, trees); - } + //private static String getSignature(TypeMirror type) { + // switch (type.getKind()) { + // case BOOLEAN: return "Z"; + // case BYTE: return "B"; + // case CHAR: return "C"; + // case SHORT: return "S"; + // case INT: return "I"; + // case LONG: return "J"; + // case FLOAT: return "F"; + // case DOUBLE: return "D"; + // case VOID: return "V"; + // case ARRAY: + // final String signature = getSignature(((ArrayType)type).getComponentType()); + // return signature != null? "[" + signature : null; + // case DECLARED: + // final TypeElement typeElement = (TypeElement)((DeclaredType)type).asElement(); + // final String qName = typeElement.getQualifiedName().toString().replace(".", "/"); + // return "L" + qName + ";"; + // default: + // return null; + // } + //} } + //private static class IdentifiersCollector extends TreeScanner { + // private Set myIdentifiers = new HashSet(); + // private Set myImports = new HashSet(); + // private Set myStaticImports = new HashSet(); + // + // public Set getIdentifiers() { + // final HashSet result = new HashSet(); + // for (Name name : myIdentifiers) { + // result.add(name.toString()); + // } + // return result; + // } + // + // @Override + // public Object visitImport(ImportTree node, Trees trees) { + // final Tree identifier = node.getQualifiedIdentifier(); + // final Set container = node.isStatic()? myStaticImports : myImports; + // container.add(identifier.toString()); + // return null; + // } + // + // @Override + // public Object visitAnnotation(AnnotationTree node, Trees trees) { + // return scan(node.getArguments(), trees); + // } + // + // @Override + // public Object visitIdentifier(IdentifierTree node, Trees trees) { + // myIdentifiers.add(node.getName()); + // return super.visitIdentifier(node, trees); + // } + // + // @Override + // public Object visitMemberSelect(MemberSelectTree node, Trees trees) { + // myIdentifiers.add(node.getIdentifier()); + // return scan(node.getExpression(), trees); + // } + // + // @Override + // public Object visitClass(ClassTree node, Trees trees) { + // return scan(node.getMembers(), trees); + // } + // + // @Override + // public Object visitVariable(VariableTree node, Trees trees) { + // return scan(node.getInitializer(), trees); + // } + // + // @Override + // public Object visitMethod(MethodTree node, Trees trees) { + // return scan(node.getBody(), trees); + // } + // + // @Override + // public Object visitMethodInvocation(MethodInvocationTree node, Trees trees) { + // return scan(node.getArguments(), trees); + // } + // + // @Override + // public Object visitTypeCast(TypeCastTree node, Trees trees) { + // return scan(node.getExpression(), trees); + // } + // + // @Override + // public Object visitInstanceOf(InstanceOfTree node, Trees trees) { + // return scan(node.getExpression(), trees); + // } + //} } diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacMain.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacMain.java index f1db6c780dba..8aad8cffe136 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacMain.java +++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacMain.java @@ -68,8 +68,8 @@ public class JavacMain { final JavaCompiler.CompilationTask task = compiler.getTask( out, fileManager, outConsumer, filterOptionList(options), null, fileManager.toJavaFileObjects(sources) ); - //final JavacASTAnalyser analyzer = new JavacASTAnalyser(shouldSuppressAnnotationProcessing(options)); - //task.setProcessors(Collections.singleton(analyzer)); + final JavacASTAnalyser analyzer = new JavacASTAnalyser(outConsumer, shouldSuppressAnnotationProcessing(options)); + task.setProcessors(Collections.singleton(analyzer)); return task.call(); } finally { diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacProtoUtil.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacProtoUtil.java index dfda083e3fec..8f511c1650e8 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacProtoUtil.java +++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacProtoUtil.java @@ -4,8 +4,7 @@ import com.google.protobuf.ByteString; import com.intellij.openapi.util.io.FileUtil; import org.jetbrains.annotations.Nullable; -import javax.tools.Diagnostic; -import javax.tools.JavaFileObject; +import javax.tools.*; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.PrintStream; @@ -86,6 +85,20 @@ public class JavacProtoUtil { return builder.build(); } + public static JavacRemoteProto.Message.Response createClassDataResponse(String className, Collection imports, Collection staticImports) { + final JavacRemoteProto.Message.Response.ClassData.Builder msgBuilder = JavacRemoteProto.Message.Response.ClassData.newBuilder(); + msgBuilder.setClassName(className); + if (!imports.isEmpty()) { + msgBuilder.addAllImportStatement(imports); + } + if (!staticImports.isEmpty()) { + msgBuilder.addAllStaticImport(imports); + } + final JavacRemoteProto.Message.Response.Builder builder = JavacRemoteProto.Message.Response.newBuilder(); + builder.setResponseType(JavacRemoteProto.Message.Response.Type.CLASS_DATA).setClassData(msgBuilder.build()); + return builder.build(); + } + public static JavacRemoteProto.Message.Response createStdOutputResponse(String text) { final JavacRemoteProto.Message.Response.CompileMessage.Builder msgBuilder = JavacRemoteProto.Message.Response.CompileMessage.newBuilder(); msgBuilder.setKind(JavacRemoteProto.Message.Response.CompileMessage.Kind.STD_OUT); diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacRemoteProto.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacRemoteProto.java index 624e09be1800..9bb4156cf536 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacRemoteProto.java +++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacRemoteProto.java @@ -1831,8 +1831,9 @@ public final class JavacRemoteProto { implements com.google.protobuf.Internal.EnumLite { BUILD_MESSAGE(0, 1), OUTPUT_OBJECT(1, 2), - BUILD_COMPLETED(2, 3), - REQUEST_ACK(3, 4), + CLASS_DATA(2, 3), + BUILD_COMPLETED(3, 4), + REQUEST_ACK(4, 5), ; @@ -1842,8 +1843,9 @@ public final class JavacRemoteProto { switch (value) { case 1: return BUILD_MESSAGE; case 2: return OUTPUT_OBJECT; - case 3: return BUILD_COMPLETED; - case 4: return REQUEST_ACK; + case 3: return CLASS_DATA; + case 4: return BUILD_COMPLETED; + case 5: return REQUEST_ACK; default: return null; } } @@ -3014,6 +3016,496 @@ public final class JavacRemoteProto { // @@protoc_insertion_point(class_scope:org.jetbrains.javac.Message.Response.OutputObject) } + public static final class ClassData extends + com.google.protobuf.GeneratedMessageLite { + // Use ClassData.newBuilder() to construct. + private ClassData() { + initFields(); + } + private ClassData(boolean noInit) {} + + private static final ClassData defaultInstance; + public static ClassData getDefaultInstance() { + return defaultInstance; + } + + public ClassData getDefaultInstanceForType() { + return defaultInstance; + } + + // required string class_name = 1; + public static final int CLASS_NAME_FIELD_NUMBER = 1; + private boolean hasClassName; + private java.lang.String className_ = ""; + public boolean hasClassName() { return hasClassName; } + public java.lang.String getClassName() { return className_; } + + // repeated string import_statement = 2; + public static final int IMPORT_STATEMENT_FIELD_NUMBER = 2; + private java.util.List importStatement_ = + java.util.Collections.emptyList(); + public java.util.List getImportStatementList() { + return importStatement_; + } + public int getImportStatementCount() { return importStatement_.size(); } + public java.lang.String getImportStatement(int index) { + return importStatement_.get(index); + } + + // repeated string static_import = 3; + public static final int STATIC_IMPORT_FIELD_NUMBER = 3; + private java.util.List staticImport_ = + java.util.Collections.emptyList(); + public java.util.List getStaticImportList() { + return staticImport_; + } + public int getStaticImportCount() { return staticImport_.size(); } + public java.lang.String getStaticImport(int index) { + return staticImport_.get(index); + } + + // repeated string identifier = 4; + public static final int IDENTIFIER_FIELD_NUMBER = 4; + private java.util.List identifier_ = + java.util.Collections.emptyList(); + public java.util.List getIdentifierList() { + return identifier_; + } + public int getIdentifierCount() { return identifier_.size(); } + public java.lang.String getIdentifier(int index) { + return identifier_.get(index); + } + + private void initFields() { + } + public final boolean isInitialized() { + if (!hasClassName) return false; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasClassName()) { + output.writeString(1, getClassName()); + } + for (java.lang.String element : getImportStatementList()) { + output.writeString(2, element); + } + for (java.lang.String element : getStaticImportList()) { + output.writeString(3, element); + } + for (java.lang.String element : getIdentifierList()) { + output.writeString(4, element); + } + } + + private int memoizedSerializedSize = -1; + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasClassName()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(1, getClassName()); + } + { + int dataSize = 0; + for (java.lang.String element : getImportStatementList()) { + dataSize += com.google.protobuf.CodedOutputStream + .computeStringSizeNoTag(element); + } + size += dataSize; + size += 1 * getImportStatementList().size(); + } + { + int dataSize = 0; + for (java.lang.String element : getStaticImportList()) { + dataSize += com.google.protobuf.CodedOutputStream + .computeStringSizeNoTag(element); + } + size += dataSize; + size += 1 * getStaticImportList().size(); + } + { + int dataSize = 0; + for (java.lang.String element : getIdentifierList()) { + dataSize += com.google.protobuf.CodedOutputStream + .computeStringSizeNoTag(element); + } + size += dataSize; + size += 1 * getIdentifierList().size(); + } + memoizedSerializedSize = size; + return size; + } + + public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData prototype) { + return newBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessageLite.Builder< + org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData, Builder> { + private org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData result; + + // Construct using org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData(); + return builder; + } + + protected org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData internalGetResult() { + return result; + } + + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData(); + return this; + } + + public Builder clone() { + return create().mergeFrom(result); + } + + public org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData getDefaultInstanceForType() { + return org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData.getDefaultInstance(); + } + + public boolean isInitialized() { + return result.isInitialized(); + } + public org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + public org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + if (result.importStatement_ != java.util.Collections.EMPTY_LIST) { + result.importStatement_ = + java.util.Collections.unmodifiableList(result.importStatement_); + } + if (result.staticImport_ != java.util.Collections.EMPTY_LIST) { + result.staticImport_ = + java.util.Collections.unmodifiableList(result.staticImport_); + } + if (result.identifier_ != java.util.Collections.EMPTY_LIST) { + result.identifier_ = + java.util.Collections.unmodifiableList(result.identifier_); + } + org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData returnMe = result; + result = null; + return returnMe; + } + + public Builder mergeFrom(org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData other) { + if (other == org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData.getDefaultInstance()) return this; + if (other.hasClassName()) { + setClassName(other.getClassName()); + } + if (!other.importStatement_.isEmpty()) { + if (result.importStatement_.isEmpty()) { + result.importStatement_ = new java.util.ArrayList(); + } + result.importStatement_.addAll(other.importStatement_); + } + if (!other.staticImport_.isEmpty()) { + if (result.staticImport_.isEmpty()) { + result.staticImport_ = new java.util.ArrayList(); + } + result.staticImport_.addAll(other.staticImport_); + } + if (!other.identifier_.isEmpty()) { + if (result.identifier_.isEmpty()) { + result.identifier_ = new java.util.ArrayList(); + } + result.identifier_.addAll(other.identifier_); + } + return this; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + return this; + default: { + if (!parseUnknownField(input, extensionRegistry, tag)) { + return this; + } + break; + } + case 10: { + setClassName(input.readString()); + break; + } + case 18: { + addImportStatement(input.readString()); + break; + } + case 26: { + addStaticImport(input.readString()); + break; + } + case 34: { + addIdentifier(input.readString()); + break; + } + } + } + } + + + // required string class_name = 1; + public boolean hasClassName() { + return result.hasClassName(); + } + public java.lang.String getClassName() { + return result.getClassName(); + } + public Builder setClassName(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasClassName = true; + result.className_ = value; + return this; + } + public Builder clearClassName() { + result.hasClassName = false; + result.className_ = getDefaultInstance().getClassName(); + return this; + } + + // repeated string import_statement = 2; + public java.util.List getImportStatementList() { + return java.util.Collections.unmodifiableList(result.importStatement_); + } + public int getImportStatementCount() { + return result.getImportStatementCount(); + } + public java.lang.String getImportStatement(int index) { + return result.getImportStatement(index); + } + public Builder setImportStatement(int index, java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.importStatement_.set(index, value); + return this; + } + public Builder addImportStatement(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.importStatement_.isEmpty()) { + result.importStatement_ = new java.util.ArrayList(); + } + result.importStatement_.add(value); + return this; + } + public Builder addAllImportStatement( + java.lang.Iterable values) { + if (result.importStatement_.isEmpty()) { + result.importStatement_ = new java.util.ArrayList(); + } + super.addAll(values, result.importStatement_); + return this; + } + public Builder clearImportStatement() { + result.importStatement_ = java.util.Collections.emptyList(); + return this; + } + + // repeated string static_import = 3; + public java.util.List getStaticImportList() { + return java.util.Collections.unmodifiableList(result.staticImport_); + } + public int getStaticImportCount() { + return result.getStaticImportCount(); + } + public java.lang.String getStaticImport(int index) { + return result.getStaticImport(index); + } + public Builder setStaticImport(int index, java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.staticImport_.set(index, value); + return this; + } + public Builder addStaticImport(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.staticImport_.isEmpty()) { + result.staticImport_ = new java.util.ArrayList(); + } + result.staticImport_.add(value); + return this; + } + public Builder addAllStaticImport( + java.lang.Iterable values) { + if (result.staticImport_.isEmpty()) { + result.staticImport_ = new java.util.ArrayList(); + } + super.addAll(values, result.staticImport_); + return this; + } + public Builder clearStaticImport() { + result.staticImport_ = java.util.Collections.emptyList(); + return this; + } + + // repeated string identifier = 4; + public java.util.List getIdentifierList() { + return java.util.Collections.unmodifiableList(result.identifier_); + } + public int getIdentifierCount() { + return result.getIdentifierCount(); + } + public java.lang.String getIdentifier(int index) { + return result.getIdentifier(index); + } + public Builder setIdentifier(int index, java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.identifier_.set(index, value); + return this; + } + public Builder addIdentifier(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + if (result.identifier_.isEmpty()) { + result.identifier_ = new java.util.ArrayList(); + } + result.identifier_.add(value); + return this; + } + public Builder addAllIdentifier( + java.lang.Iterable values) { + if (result.identifier_.isEmpty()) { + result.identifier_ = new java.util.ArrayList(); + } + super.addAll(values, result.identifier_); + return this; + } + public Builder clearIdentifier() { + result.identifier_ = java.util.Collections.emptyList(); + return this; + } + + // @@protoc_insertion_point(builder_scope:org.jetbrains.javac.Message.Response.ClassData) + } + + static { + defaultInstance = new ClassData(true); + org.jetbrains.jps.javac.JavacRemoteProto.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:org.jetbrains.javac.Message.Response.ClassData) + } + // required .org.jetbrains.javac.Message.Response.Type response_type = 1; public static final int RESPONSE_TYPE_FIELD_NUMBER = 1; private boolean hasResponseType; @@ -3035,8 +3527,15 @@ public final class JavacRemoteProto { public boolean hasOutputObject() { return hasOutputObject; } public org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject getOutputObject() { return outputObject_; } - // optional bool completion_status = 4; - public static final int COMPLETION_STATUS_FIELD_NUMBER = 4; + // optional .org.jetbrains.javac.Message.Response.ClassData class_data = 4; + public static final int CLASS_DATA_FIELD_NUMBER = 4; + private boolean hasClassData; + private org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData classData_; + public boolean hasClassData() { return hasClassData; } + public org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData getClassData() { return classData_; } + + // optional bool completion_status = 5; + public static final int COMPLETION_STATUS_FIELD_NUMBER = 5; private boolean hasCompletionStatus; private boolean completionStatus_ = false; public boolean hasCompletionStatus() { return hasCompletionStatus; } @@ -3046,6 +3545,7 @@ public final class JavacRemoteProto { responseType_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.Type.BUILD_MESSAGE; compileMessage_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.CompileMessage.getDefaultInstance(); outputObject_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.OutputObject.getDefaultInstance(); + classData_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData.getDefaultInstance(); } public final boolean isInitialized() { if (!hasResponseType) return false; @@ -3055,6 +3555,9 @@ public final class JavacRemoteProto { if (hasOutputObject()) { if (!getOutputObject().isInitialized()) return false; } + if (hasClassData()) { + if (!getClassData().isInitialized()) return false; + } return true; } @@ -3070,8 +3573,11 @@ public final class JavacRemoteProto { if (hasOutputObject()) { output.writeMessage(3, getOutputObject()); } + if (hasClassData()) { + output.writeMessage(4, getClassData()); + } if (hasCompletionStatus()) { - output.writeBool(4, getCompletionStatus()); + output.writeBool(5, getCompletionStatus()); } } @@ -3093,9 +3599,13 @@ public final class JavacRemoteProto { size += com.google.protobuf.CodedOutputStream .computeMessageSize(3, getOutputObject()); } + if (hasClassData()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(4, getClassData()); + } if (hasCompletionStatus()) { size += com.google.protobuf.CodedOutputStream - .computeBoolSize(4, getCompletionStatus()); + .computeBoolSize(5, getCompletionStatus()); } memoizedSerializedSize = size; return size; @@ -3250,6 +3760,9 @@ public final class JavacRemoteProto { if (other.hasOutputObject()) { mergeOutputObject(other.getOutputObject()); } + if (other.hasClassData()) { + mergeClassData(other.getClassData()); + } if (other.hasCompletionStatus()) { setCompletionStatus(other.getCompletionStatus()); } @@ -3297,7 +3810,16 @@ public final class JavacRemoteProto { setOutputObject(subBuilder.buildPartial()); break; } - case 32: { + case 34: { + org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData.Builder subBuilder = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData.newBuilder(); + if (hasClassData()) { + subBuilder.mergeFrom(getClassData()); + } + input.readMessage(subBuilder, extensionRegistry); + setClassData(subBuilder.buildPartial()); + break; + } + case 40: { setCompletionStatus(input.readBool()); break; } @@ -3401,7 +3923,44 @@ public final class JavacRemoteProto { return this; } - // optional bool completion_status = 4; + // optional .org.jetbrains.javac.Message.Response.ClassData class_data = 4; + public boolean hasClassData() { + return result.hasClassData(); + } + public org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData getClassData() { + return result.getClassData(); + } + public Builder setClassData(org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasClassData = true; + result.classData_ = value; + return this; + } + public Builder setClassData(org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData.Builder builderForValue) { + result.hasClassData = true; + result.classData_ = builderForValue.build(); + return this; + } + public Builder mergeClassData(org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData value) { + if (result.hasClassData() && + result.classData_ != org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData.getDefaultInstance()) { + result.classData_ = + org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData.newBuilder(result.classData_).mergeFrom(value).buildPartial(); + } else { + result.classData_ = value; + } + result.hasClassData = true; + return this; + } + public Builder clearClassData() { + result.hasClassData = false; + result.classData_ = org.jetbrains.jps.javac.JavacRemoteProto.Message.Response.ClassData.getDefaultInstance(); + return this; + } + + // optional bool completion_status = 5; public boolean hasCompletionStatus() { return result.hasCompletionStatus(); } diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServer.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServer.java index 537cdf6a64e8..fd7ae5789180 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServer.java +++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServer.java @@ -122,6 +122,12 @@ public class JavacServer { final JavacRemoteProto.Message.Response response = JavacProtoUtil.createBuildMessageResponse(diagnostic); Channels.write(ctx.getChannel(), JavacProtoUtil.toMessage(sessionId, response)); } + + @Override + public void registerImports(String className, Collection imports, Collection staticImports) { + final JavacRemoteProto.Message.Response response = JavacProtoUtil.createClassDataResponse(className, imports, staticImports); + Channels.write(ctx.getChannel(), JavacProtoUtil.toMessage(sessionId, response)); + } }; final OutputFileConsumer outputSink = new OutputFileConsumer() { diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerResponseHandler.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerResponseHandler.java index f7232bec5968..00e3a08cc175 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerResponseHandler.java +++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerResponseHandler.java @@ -4,10 +4,10 @@ import com.google.protobuf.ByteString; import com.google.protobuf.MessageLite; import org.jetbrains.jps.client.ProtobufResponseHandler; -import javax.tools.Diagnostic; -import javax.tools.JavaFileObject; +import javax.tools.*; import java.io.File; import java.net.URI; +import java.util.Collection; import java.util.Locale; /** @@ -82,6 +82,15 @@ public class JavacServerResponseHandler implements ProtobufResponseHandler{ return false; } + if (responseType == JavacRemoteProto.Message.Response.Type.CLASS_DATA) { + final JavacRemoteProto.Message.Response.ClassData data = response.getClassData(); + final String className = data.getClassName(); + final Collection imports = data.getImportStatementList(); + final Collection staticImports = data.getStaticImportList(); + myDiagnosticSink.registerImports(className, imports, staticImports); + return false; + } + if (responseType == JavacRemoteProto.Message.Response.Type.BUILD_COMPLETED) { myTerminatedSuccessfully = response.getCompletionStatus(); return true; diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/Callbacks.java b/jps/model/src/org/jetbrains/ether/dependencyView/Callbacks.java index 51d644f2ec40..c4d7b133f4ed 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/Callbacks.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/Callbacks.java @@ -1,6 +1,7 @@ package org.jetbrains.ether.dependencyView; import org.objectweb.asm.ClassReader; + import java.util.Collection; /** @@ -26,8 +27,7 @@ public class Callbacks { public interface Backend { Collection getClassFiles(); void associate(String classFileName, SourceFileNameLookup sourceLookup, ClassReader cr); - void markOverride(String className, String methodName, String methodSignature); void registerConstantUsage(String className, String fieldName, String fieldOwner); - void registerImports(Collection imports, String rootClass); + void registerImports(String className, Collection imports, Collection staticImports); } } diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java b/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java index cc586037d2b9..530832021ad7 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java @@ -1732,23 +1732,24 @@ public class Mappings { } } - @Override - public void markOverride(final String className, final String methodName, final String methodSignature) { - //To change body of implemented methods use File | Settings | File Templates. - } - @Override public void registerConstantUsage(final String className, final String fieldName, final String fieldOwner) { //To change body of implemented methods use File | Settings | File Templates. } @Override - public void registerImports(final Collection imports, final String rootClass) { - final DependencyContext.S rootClassName = myContext.get(rootClass); + public void registerImports(final String className, final Collection imports, Collection staticImports) { + // todo: proces static imports as well + final DependencyContext.S rootClassName = myContext.get(className.replace(".", "/")); + + // todo: postpone processing until data collected is complete and myClassToSourceFile contains the mapping final DependencyContext.S fileName = myClassToSourceFile.get(rootClassName); for (final String i : imports) { - final DependencyContext.S iname = myContext.get(i); + if (i.endsWith("*")) { + continue; // filter out wildcard imports + } + final DependencyContext.S iname = myContext.get(i.replace(".", "/")); myClassToClassDependency.put(rootClassName, iname); From 7fec55778125a98f33ee65be6685456b76f84f0b Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Sat, 11 Feb 2012 18:14:58 +0100 Subject: [PATCH 12/15] comment 1.7 API usage --- .../src/org/jetbrains/jps/javac/JavacASTAnalyser.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacASTAnalyser.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacASTAnalyser.java index a76d5ccb104e..29f8155156f0 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacASTAnalyser.java +++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacASTAnalyser.java @@ -6,8 +6,10 @@ import com.sun.source.tree.Tree; import com.sun.source.util.TreeScanner; import com.sun.source.util.Trees; -import javax.annotation.processing.*; -import javax.lang.model.SourceVersion; +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.ProcessingEnvironment; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; import java.util.HashSet; @@ -18,7 +20,7 @@ import java.util.Set; * Date: 2/1/12 * */ -@SupportedSourceVersion(SourceVersion.RELEASE_7) +//@SupportedSourceVersion(SourceVersion.RELEASE_7) @SupportedAnnotationTypes("*") public class JavacASTAnalyser extends AbstractProcessor{ private Trees myTrees; From 88673888cbe5c861a47c1366ce7f9999429ca915 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Sat, 11 Feb 2012 19:43:43 +0100 Subject: [PATCH 13/15] suppress warnings and fix tests --- .../src/org/jetbrains/jps/javac/JavacASTAnalyser.java | 7 ++++++- .../src/org/jetbrains/jps/javac/JavacMain.java | 11 +++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacASTAnalyser.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacASTAnalyser.java index 29f8155156f0..a9e09d736bd9 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacASTAnalyser.java +++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacASTAnalyser.java @@ -10,6 +10,7 @@ import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.ProcessingEnvironment; import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedAnnotationTypes; +import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; import java.util.HashSet; @@ -20,7 +21,6 @@ import java.util.Set; * Date: 2/1/12 * */ -//@SupportedSourceVersion(SourceVersion.RELEASE_7) @SupportedAnnotationTypes("*") public class JavacASTAnalyser extends AbstractProcessor{ private Trees myTrees; @@ -32,6 +32,11 @@ public class JavacASTAnalyser extends AbstractProcessor{ mySuppressOtherProcessors = suppressOtherProcessors; } + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } + @Override public void init(ProcessingEnvironment processingEnv) { super.init(processingEnv); diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacMain.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacMain.java index 8aad8cffe136..5074b89b9d46 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacMain.java +++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacMain.java @@ -18,7 +18,7 @@ public class JavacMain { "-d", "-classpath", "-cp", "-bootclasspath" )); private static final Set FILTERED_SINGLE_OPTIONS = new HashSet(Arrays.asList( - "-verbose", "-proc:none" + "-verbose", "-proc:none", "-implicit:class", "-implicit:none" )); public static boolean compile(Collection options, @@ -65,8 +65,9 @@ public class JavacMain { }; try { + final Collection _options = prepareOptions(options); final JavaCompiler.CompilationTask task = compiler.getTask( - out, fileManager, outConsumer, filterOptionList(options), null, fileManager.toJavaFileObjects(sources) + out, fileManager, outConsumer, _options, null, fileManager.toJavaFileObjects(sources) ); final JavacASTAnalyser analyzer = new JavacASTAnalyser(outConsumer, shouldSuppressAnnotationProcessing(options)); task.setProcessors(Collections.singleton(analyzer)); @@ -86,11 +87,9 @@ public class JavacMain { return false; } - private static Collection filterOptionList(final Collection options) { - if (options.isEmpty()) { - return options; - } + private static Collection prepareOptions(final Collection options) { final List result = new ArrayList(); + result.add("-implicit:class"); boolean skip = false; for (String option : options) { if (FILTERED_OPTIONS.contains(option)) { From 4a11f8cdac6e42dcb8e21a58368f345860fde53b Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Sat, 11 Feb 2012 20:41:30 +0100 Subject: [PATCH 14/15] perform make iterations over all registered builders across categories, instead of iterating within each category --- .../jps/incremental/CompileContext.java | 5 +-- .../jetbrains/jps/incremental/FSState.java | 8 ++--- .../jps/incremental/IncProjectBuilder.java | 36 +++++++++---------- 3 files changed, 23 insertions(+), 26 deletions(-) diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/CompileContext.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/CompileContext.java index 90bd4e549c4e..a3593035e662 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/CompileContext.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/CompileContext.java @@ -178,16 +178,13 @@ public class CompileContext extends UserDataHolderBase implements MessageHandler myFsState.beforeNextRoundStart(); } - public void afterCompileRound() { - myFsState.clearContextRoundData(); - } - public void onChunkBuildStart(ModuleChunk chunk) { myFsState.setContextChunk(chunk); } void onChunkBuildComplete(@NotNull ModuleChunk chunk) throws IOException { myDataManager.flush(true); + myFsState.clearContextRoundData(); myFsState.clearContextChunk(); if (!myErrorsFound && !myCancelStatus.isCanceled()) { diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/FSState.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/FSState.java index 63874bc38d67..6b615f0afd70 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/FSState.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/FSState.java @@ -52,10 +52,6 @@ public class FSState { myContextModules.addAll(chunk.getModules()); } - public void clearContextChunk() { - myContextModules.clear(); - } - public void beforeNextRoundStart() { myLastRoundDelta = myCurrentRoundDelta; myCurrentRoundDelta = new FilesDelta(); @@ -66,6 +62,10 @@ public class FSState { myLastRoundDelta = null; } + public void clearContextChunk() { + myContextModules.clear(); + } + public void clearRecompile(RootDescriptor rd) { getDelta(rd.module).clearRecompile(rd.root, rd.isTestRoot); } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java index 5270a2c7c27a..97fc6b25399f 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java @@ -369,23 +369,23 @@ public class IncProjectBuilder { private void runModuleLevelBuilders(final CompileContext context, ModuleChunk chunk) throws ProjectBuildException { boolean rebuildFromScratchRequested = false; float stageCount = myTotalModuleLevelBuilderCount; + final int modulesInChunk = chunk.getModules().size(); + int buildersPassed = 0; + boolean nextPassRequired; + CHUNK_BUILD_START: - for (BuilderCategory category : BuilderCategory.values()) { - final List builders = myBuilderRegistry.getBuilders(category); - if (builders.isEmpty()) { - continue; + do { + nextPassRequired = false; + context.beforeCompileRound(chunk); + + if (!context.isProjectRebuild()) { + syncOutputFiles(context, chunk); } - final int modulesInChunk = chunk.getModules().size(); - int buildersPassed = 0; - - boolean nextPassRequired; - do { - nextPassRequired = false; - context.beforeCompileRound(chunk); - - if (!context.isProjectRebuild()) { - syncOutputFiles(context, chunk); + for (BuilderCategory category : BuilderCategory.values()) { + final List builders = myBuilderRegistry.getBuilders(category); + if (builders.isEmpty()) { + continue; } for (ModuleLevelBuilder builder : builders) { @@ -399,7 +399,7 @@ public class IncProjectBuilder { if (!nextPassRequired) { // recalculate basis myModulesProcessed -= (buildersPassed * modulesInChunk) / stageCount; - stageCount += builders.size(); + stageCount += myTotalModuleLevelBuilderCount; myModulesProcessed += (buildersPassed * modulesInChunk) / stageCount; } nextPassRequired = true; @@ -413,6 +413,8 @@ public class IncProjectBuilder { context.markDirty(chunk); // reverting to the beginning myModulesProcessed -= (buildersPassed * modulesInChunk) / stageCount; + stageCount = myTotalModuleLevelBuilderCount; + buildersPassed = 0; break CHUNK_BUILD_START; } catch (Exception e) { @@ -429,10 +431,8 @@ public class IncProjectBuilder { context.setDone(fraction); } } - while (nextPassRequired); - - context.afterCompileRound(); } + while (nextPassRequired); } private void runProjectLevelBuilders(CompileContext context) throws ProjectBuildException { From ba547218d6eb227d5012a08e743a01e372440b7c Mon Sep 17 00:00:00 2001 From: "kirill.safonov" Date: Sun, 12 Feb 2012 19:47:22 +0400 Subject: [PATCH 15/15] Flex project structure: correctly show and process shared libraries usages in build configurations --- .../GeneralProjectSettingsElement.java | 5 ++ .../ArtifactProjectStructureElement.java | 5 ++ .../BaseLibrariesConfigurable.java | 57 +++++++++---------- .../daemon/FacetProjectStructureElement.java | 5 ++ .../LibraryProjectStructureElement.java | 5 ++ .../daemon/ModuleProjectStructureElement.java | 5 ++ .../ProjectStructureDaemonAnalyzer.java | 8 ++- .../daemon/ProjectStructureElement.java | 2 + .../daemon/ProjectStructureValidator.java | 27 ++++++++- .../daemon/SdkProjectStructureElement.java | 5 ++ 10 files changed, 90 insertions(+), 34 deletions(-) diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/GeneralProjectSettingsElement.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/GeneralProjectSettingsElement.java index fa2945b3f49a..10bdcd813327 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/GeneralProjectSettingsElement.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/GeneralProjectSettingsElement.java @@ -42,6 +42,11 @@ public class GeneralProjectSettingsElement extends ProjectStructureElement { return "Project"; } + @Override + public String getTypeName() { + return "Project"; + } + @Override public void check(ProjectStructureProblemsHolder problemsHolder) { final Graph> graph = ModuleCompilerUtil.toChunkGraph( diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactProjectStructureElement.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactProjectStructureElement.java index 2d28cae26162..7d423413a2e8 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactProjectStructureElement.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactProjectStructureElement.java @@ -133,6 +133,11 @@ public class ArtifactProjectStructureElement extends ProjectStructureElement { return "Artifact '" + getActualArtifactName() + "'"; } + @Override + public String getTypeName() { + return "Artifact"; + } + @Override public String getId() { return "artifact:" + getActualArtifactName(); diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/BaseLibrariesConfigurable.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/BaseLibrariesConfigurable.java index 35f55193b22b..72fad056f245 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/BaseLibrariesConfigurable.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/BaseLibrariesConfigurable.java @@ -33,6 +33,8 @@ import com.intellij.openapi.roots.ui.configuration.libraryEditor.CreateNewLibrar import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.*; import com.intellij.openapi.ui.*; import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.containers.MultiMap; import com.intellij.util.ui.tree.TreeUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -250,42 +252,37 @@ public abstract class BaseLibrariesConfigurable extends BaseStructureConfigurabl if (table != null) { final Collection usages = myContext.getDaemonAnalyzer().getUsages(getSelectedElement()); if (usages.size() > 0) { - final List modules = new ArrayList(); - final List artifacts = new ArrayList(); + final MultiMap containerType2Usage = new MultiMap(); for (final ProjectStructureElementUsage usage : usages) { - if (usage instanceof UsageInModuleClasspath) { - modules.add(usage.getPresentableName()); - } else if (usage instanceof UsageInArtifact) { - artifacts.add(usage.getPresentableName()); - } else { - LOG.error("Unknown usage: " + usage.getClass().getName()); + containerType2Usage.putValue(usage.getContainingElement().getTypeName(), usage); + } + + List types = new ArrayList(containerType2Usage.keySet()); + Collections.sort(types); + + final StringBuilder sb = new StringBuilder("Library '"); + sb.append(library.getName()).append("' is used in "); + for (int i = 0; i < types.size(); i++) { + if (i == types.size() - 1) { + sb.append(" and in "); + } + else if (i > 0) { + sb.append(", in "); + } + String type = types.get(i); + Collection usagesOfType = containerType2Usage.get(type); + if (usagesOfType.size() > 1) { + sb.append(usagesOfType.size()).append(" ").append(StringUtil.decapitalize(StringUtil.pluralize(type))); + } + else { + sb.append(StringUtil.decapitalize(usagesOfType.iterator().next().getContainingElement().getPresentableName())); } } - final StringBuilder sb = new StringBuilder("Library \""); - sb.append(library.getName()).append("\" is used in "); - if (modules.size() > 0) { - if (modules.size() == 1) { - sb.append("module ").append("\"").append(modules.get(0)).append("\""); - } else { - sb.append(modules.size()).append(" modules"); - } - } - - if (artifacts.size() > 0) { - sb.append(modules.size() > 0 ? " and in " : ""); - - if (artifacts.size() == 1) { - sb.append("artifact ").append("\"").append(artifacts.get(0)).append("\"."); - } else { - sb.append(artifacts.size()).append(" artifacts."); - } - } - - sb.append("\n\nAre you sure you want to delete this library?"); + sb.append(".\n\nAre you sure you want to delete this library?"); if (DialogWrapper.OK_EXIT_CODE == Messages.showOkCancelDialog(myProject, sb.toString(), - "Confirm Library Deletion", Messages.getQuestionIcon())) { + "Delete Library", Messages.getQuestionIcon())) { final ModuleStructureConfigurable rootConfigurable = ModuleStructureConfigurable.getInstance(myProject); for (final ProjectStructureElementUsage usage : usages) { diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/FacetProjectStructureElement.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/FacetProjectStructureElement.java index 38b94f9e387c..3d8f41ec99bb 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/FacetProjectStructureElement.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/FacetProjectStructureElement.java @@ -48,6 +48,11 @@ public class FacetProjectStructureElement extends ProjectStructureElement { return "Facet '" + myFacet.getName() + "' in module '" + myFacet.getModule().getName() + "'"; } + @Override + public String getTypeName() { + return "Facet"; + } + @Override public String getId() { return "facet:" + FacetPointersManager.constructId(myFacet); diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/LibraryProjectStructureElement.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/LibraryProjectStructureElement.java index 92e4423e560e..3a07b8e6c312 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/LibraryProjectStructureElement.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/LibraryProjectStructureElement.java @@ -145,6 +145,11 @@ public class LibraryProjectStructureElement extends ProjectStructureElement { return "Library '" + myLibrary.getName() + "'"; } + @Override + public String getTypeName() { + return "Library"; + } + @Override public String getId() { return "library:" + myLibrary.getTable().getTableLevel() + ":" + myLibrary.getName(); diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ModuleProjectStructureElement.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ModuleProjectStructureElement.java index bd4dd49ce2f9..34899425c492 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ModuleProjectStructureElement.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ModuleProjectStructureElement.java @@ -140,6 +140,11 @@ public class ModuleProjectStructureElement extends ProjectStructureElement { return "Module '" + myModule.getName() + "'"; } + @Override + public String getTypeName() { + return "Module"; + } + @Override public String getId() { return "module:" + myModule.getName(); diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectStructureDaemonAnalyzer.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectStructureDaemonAnalyzer.java index a10dae160a8e..c2b693a2e245 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectStructureDaemonAnalyzer.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectStructureDaemonAnalyzer.java @@ -86,7 +86,7 @@ public class ProjectStructureDaemonAnalyzer implements Disposable { if (LOG.isDebugEnabled()) { LOG.debug("collecting usages in " + element); } - result.setResult(element.getUsagesInElement()); + result.setResult(getUsagesInElement(element)); } }.execute().getResultObject(); @@ -102,6 +102,10 @@ public class ProjectStructureDaemonAnalyzer implements Disposable { }); } + private static List getUsagesInElement(final ProjectStructureElement element) { + return ProjectStructureValidator.getUsagesInElement(element); + } + private void updateUsages(ProjectStructureElement element, List usages) { removeUsagesInElement(element); for (ProjectStructureElementUsage usage : usages) { @@ -233,7 +237,7 @@ public class ProjectStructureDaemonAnalyzer implements Disposable { public Collection getUsages(ProjectStructureElement selected) { ProjectStructureElement[] elements = myElementWithNotCalculatedUsages.toArray(new ProjectStructureElement[myElementWithNotCalculatedUsages.size()]); for (ProjectStructureElement element : elements) { - updateUsages(element, element.getUsagesInElement()); + updateUsages(element, getUsagesInElement(element)); } final Collection usages = mySourceElement2Usages.get(selected); return usages != null ? usages : Collections.emptyList(); diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectStructureElement.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectStructureElement.java index 76fec66e165c..f9e866962e79 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectStructureElement.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectStructureElement.java @@ -18,6 +18,8 @@ public abstract class ProjectStructureElement { public abstract String getPresentableName(); + public abstract String getTypeName(); + public abstract String getId(); public abstract void check(ProjectStructureProblemsHolder problemsHolder); diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectStructureValidator.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectStructureValidator.java index 45505a8645d1..79f1d7c0d5db 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectStructureValidator.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectStructureValidator.java @@ -16,6 +16,9 @@ package com.intellij.openapi.roots.ui.configuration.projectRoot.daemon; import com.intellij.openapi.extensions.ExtensionPointName; +import org.jetbrains.annotations.Nullable; + +import java.util.List; /** * User: ksafonov @@ -25,6 +28,16 @@ public abstract class ProjectStructureValidator { private static final ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.projectStructureValidator"); + public static List getUsagesInElement(final ProjectStructureElement element) { + for (ProjectStructureValidator validator : EP_NAME.getExtensions()) { + List usages = validator.getUsagesIn(element); + if (usages != null) { + return usages; + } + } + return element.getUsagesInElement(); + } + public static void check(ProjectStructureElement element, ProjectStructureProblemsHolder problemsHolder) { for (ProjectStructureValidator validator : EP_NAME.getExtensions()) { if (validator.checkElement(element, problemsHolder)) { @@ -33,9 +46,19 @@ public abstract class ProjectStructureValidator { } element.check(problemsHolder); } - + + /** + * @return true if it handled this element + */ protected boolean checkElement(ProjectStructureElement element, ProjectStructureProblemsHolder problemsHolder) { return false; } - + + /** + * @return list of usages or null when it does not handle such element + */ + @Nullable + protected List getUsagesIn(final ProjectStructureElement element) { + return null; + } } diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/SdkProjectStructureElement.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/SdkProjectStructureElement.java index 3e7e332355a1..b85fde871caf 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/SdkProjectStructureElement.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/SdkProjectStructureElement.java @@ -48,6 +48,11 @@ public class SdkProjectStructureElement extends ProjectStructureElement { return "SDK '" + mySdk.getName() + "'"; } + @Override + public String getTypeName() { + return "SDK"; + } + @Override public String getId() { return "sdk:" + mySdk.getName();