diff --git a/build/scripts/layouts.gant b/build/scripts/layouts.gant index 734760c5262c..e78e38697911 100644 --- a/build/scripts/layouts.gant +++ b/build/scripts/layouts.gant @@ -218,7 +218,7 @@ def layoutFull(String home, String targetDirectory, String patchedDescriptorDir public def layoutCommunityPlugins(String home) { dir("plugins") { - def simplePlugins = ["commander", "copyright", "properties", "java-i18n", "devkit", "eclipse", "hg4idea", "github"] + def simplePlugins = ["commander", "copyright", "properties", "java-i18n", "devkit", "eclipse", "hg4idea", "github", "ui-designer-new"] simplePlugins.each { layoutPlugin it @@ -392,6 +392,12 @@ public def layoutCommunityPlugins(String home) { jar("android-jps-plugin.jar") { module("android-jps-plugin") } } } + + layoutPlugin("android-designer") { + jar("android-designer.jar") { + module("android-designer") + } + } } } diff --git a/build/scripts/tests.gant b/build/scripts/tests.gant index ab0bbdf38c05..35b0b19f6314 100644 --- a/build/scripts/tests.gant +++ b/build/scripts/tests.gant @@ -1,10 +1,14 @@ -import static org.jetbrains.jps.idea.IdeaProjectLoader.* +import static org.jetbrains.jps.idea.IdeaProjectLoader.guessHome includeTargets << new File("${guessHome(this)}/build/scripts/common_tests.gant") setProperty("testcases", ["com.intellij.AllTests"]) -setProperty("jvm_args", [ - "-Xmx350m", - "-XX:MaxPermSize=320m", - ]) +def isMac = System.getProperty("os.name").toLowerCase().startsWith("mac") +def args = [ + "-Xmx350m", + "-XX:MaxPermSize=320m", +] +if (isMac) args << "-d32"; + +setProperty("jvm_args", args) diff --git a/java/compiler/impl/src/com/intellij/compiler/CompileServerManager.java b/java/compiler/impl/src/com/intellij/compiler/CompileServerManager.java index 9f1f7e80af35..fc7c7d7b7eb8 100644 --- a/java/compiler/impl/src/com/intellij/compiler/CompileServerManager.java +++ b/java/compiler/impl/src/com/intellij/compiler/CompileServerManager.java @@ -70,7 +70,8 @@ import org.jetbrains.jps.client.CompileServerClient; import org.jetbrains.jps.server.ClasspathBootstrap; import org.jetbrains.jps.server.Server; -import javax.tools.*; +import javax.tools.JavaCompiler; +import javax.tools.ToolProvider; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -611,7 +612,6 @@ public class CompileServerManager implements ApplicationComponent{ cmdLine.addParameter("-D"+ GlobalOptions.USE_EXTERNAL_JAVAC_OPTION + "=true"); } cmdLine.addParameter("-D"+ GlobalOptions.HOSTNAME_OPTION + "=" + NetUtils.getLocalHostString()); - cmdLine.addParameter("-D"+ GlobalOptions.VM_EXE_PATH_OPTION + "=" + FileUtil.toSystemIndependentName(vmExecutablePath)); // javac's VM should use the same default locale that IDEA uses in order for javac to print messages in 'correct' language final String lang = System.getProperty("user.language"); diff --git a/java/compiler/impl/src/com/intellij/compiler/make/Dependency.java b/java/compiler/impl/src/com/intellij/compiler/make/Dependency.java index cf50003bc0e4..bd2c5cf9017c 100644 --- a/java/compiler/impl/src/com/intellij/compiler/make/Dependency.java +++ b/java/compiler/impl/src/com/intellij/compiler/make/Dependency.java @@ -138,7 +138,7 @@ public class Dependency { private static String[] parseParameterDescriptors(String signature) { ArrayList list = new ArrayList(); String paramSignature = parseFieldType(signature); - while (paramSignature != null && !"".equals(paramSignature)) { + while (paramSignature != null && !paramSignature.isEmpty()) { list.add(paramSignature); signature = signature.substring(paramSignature.length()); paramSignature = parseFieldType(signature); @@ -147,39 +147,40 @@ public class Dependency { } private static String parseFieldType(@NonNls String signature) { - if (signature.length() == 0) { + if (signature.isEmpty()) { return null; } - if (signature.charAt(0) == 'B') { - return "B"; - } - if (signature.charAt(0) == 'C') { - return "C"; - } - if (signature.charAt(0) == 'D') { - return "D"; - } - if (signature.charAt(0) == 'F') { - return "F"; - } - if (signature.charAt(0) == 'I') { + char first = signature.charAt(0); + if (first == 'I') { return "I"; } - if (signature.charAt(0) == 'J') { + if (first == 'L') { + return signature.substring(0, signature.indexOf(';') + 1); + } + if (first == 'B') { + return "B"; + } + if (first == 'C') { + return "C"; + } + if (first == 'D') { + return "D"; + } + if (first == 'F') { + return "F"; + } + if (first == 'J') { return "J"; } - if (signature.charAt(0) == 'S') { + if (first == 'S') { return "S"; } - if (signature.charAt(0) == 'Z') { + if (first == 'Z') { return "Z"; } - if (signature.charAt(0) == 'L') { - return signature.substring(0, signature.indexOf(";") + 1); - } - if (signature.charAt(0) == '[') { + if (first == '[') { String s = parseFieldType(signature.substring(1)); - return (s != null)? ("[" + s) : null; + return s == null ? null : "[" + s; } return null; } diff --git a/java/compiler/openapi/src/com/intellij/compiler/ModuleCompilerUtil.java b/java/compiler/openapi/src/com/intellij/compiler/ModuleCompilerUtil.java index bf4cce63dc53..185648ac146e 100644 --- a/java/compiler/openapi/src/com/intellij/compiler/ModuleCompilerUtil.java +++ b/java/compiler/openapi/src/com/intellij/compiler/ModuleCompilerUtil.java @@ -24,6 +24,7 @@ import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.openapi.roots.ModuleRootModel; import com.intellij.openapi.util.Pair; import com.intellij.util.Chunk; import com.intellij.util.containers.ContainerUtil; @@ -106,15 +107,16 @@ public final class ModuleCompilerUtil { } } - public static GraphGenerator createGraphGenerator(final Map models) { - return GraphGenerator.create(CachingSemiGraph.create(new GraphGenerator.SemiGraph() { - public Collection getNodes() { + + public static GraphGenerator createGraphGenerator(final Map models) { + return GraphGenerator.create(CachingSemiGraph.create(new GraphGenerator.SemiGraph() { + public Collection getNodes() { return models.values(); } - public Iterator getIn(final ModifiableRootModel model) { + public Iterator getIn(final ModuleRootModel model) { final Module[] modules = model.getModuleDependencies(); - final List dependencies = new ArrayList(); + final List dependencies = new ArrayList(); for (Module module : modules) { dependencies.add(models.get(module)); } @@ -162,7 +164,7 @@ public final class ModuleCompilerUtil { return null; } - public static Collection> buildChunks(final Map models) { + public static Collection> buildChunks(final Map models) { return toChunkGraph(createGraphGenerator(models)).getNodes(); } } diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/ProjectFromSourcesBuilder.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/ProjectFromSourcesBuilder.java index 568311359726..fc28f8f6bf6d 100644 --- a/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/ProjectFromSourcesBuilder.java +++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/ProjectFromSourcesBuilder.java @@ -42,4 +42,6 @@ public interface ProjectFromSourcesBuilder { @NotNull WizardContext getContext(); + + boolean hasRootsFromOtherDetectors(ProjectStructureDetector thisDetector); } diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/impl/ProjectFromSourcesBuilderImpl.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/impl/ProjectFromSourcesBuilderImpl.java index 1ed00b0c054a..2980c4e25b09 100644 --- a/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/impl/ProjectFromSourcesBuilderImpl.java +++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/impl/ProjectFromSourcesBuilderImpl.java @@ -32,6 +32,7 @@ import com.intellij.ide.util.projectWizard.importSources.ProjectStructureDetecto import com.intellij.openapi.application.AccessToken; import com.intellij.openapi.application.WriteAction; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.module.*; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.project.Project; @@ -262,6 +263,15 @@ public class ProjectFromSourcesBuilderImpl extends ProjectBuilder implements Pro myUpdaters.add(updater); } + public boolean hasRootsFromOtherDetectors(ProjectStructureDetector thisDetector) { + for (ProjectStructureDetector projectStructureDetector : Extensions.getExtensions(ProjectStructureDetector.EP_NAME)) { + if (projectStructureDetector != thisDetector && !getProjectRoots(projectStructureDetector).isEmpty()) { + return true; + } + } + return false; + } + @NotNull private static Module createModule(ProjectDescriptor projectDescriptor, final ModuleDescriptor descriptor, final Map projectLibs, final ModifiableModuleModel moduleModel) diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ConfigurationErrorsComponent.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ConfigurationErrorsComponent.java index 9233ad1d8c88..fac049f3440d 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ConfigurationErrorsComponent.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ConfigurationErrorsComponent.java @@ -18,16 +18,15 @@ package com.intellij.openapi.roots.ui.configuration; import com.intellij.openapi.Disposable; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.MessageType; -import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.IconLoader; +import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.wm.impl.content.GraphicsConfig; import com.intellij.ui.awt.RelativePoint; import com.intellij.ui.components.JBList; import com.intellij.ui.components.JBScrollPane; import com.intellij.ui.components.labels.LinkLabel; import com.intellij.ui.components.labels.LinkListener; -import com.intellij.util.containers.ContainerUtil; import com.intellij.util.messages.MessageBusConnection; import com.intellij.util.ui.BaseButtonBehavior; import com.intellij.util.ui.TimedDeadzone; @@ -45,6 +44,7 @@ import java.awt.event.ComponentEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.geom.RoundRectangle2D; +import java.util.AbstractList; import java.util.ArrayList; import java.util.List; @@ -52,6 +52,7 @@ import java.util.List; * User: spLeaner */ public class ConfigurationErrorsComponent extends JPanel implements Disposable, ListDataListener { + private static final int MAX_ERRORS_TO_SHOW = SystemInfo.getIntProperty("idea.project.structure.max.errors.to.show", 100); private static final boolean ONE_LINE = true; private static final boolean MULTI_LINE = false; @@ -95,7 +96,7 @@ public class ConfigurationErrorsComponent extends JPanel implements Disposable, private void ensureCurrentViewIs(final boolean oneLine, @Nullable final Object data) { if (oneLine) { if (myCurrentView instanceof OneLineErrorComponent) return; - myConfigurationErrorsListModel.setFilter(null); + myConfigurationErrorsListModel.setFilter(true, true); OneLineErrorComponent c = new OneLineErrorComponent(myConfigurationErrorsListModel) { @Override public void onViewChange(Object data) { @@ -109,14 +110,9 @@ public class ConfigurationErrorsComponent extends JPanel implements Disposable, } myCurrentView = c; - } else { - Condition filter = data == null ? null : new Condition() { - @Override - public boolean value(ConfigurationError error) { - return data == null ? true : "Ignored".equals(data) ? error.isIgnored() : !error.isIgnored(); - } - }; - myConfigurationErrorsListModel.setFilter(filter); + } + else { + myConfigurationErrorsListModel.setFilter(data == null || !"Ignored".equals(data), data == null || "Ignored".equals(data)); if (myCurrentView instanceof MultiLineErrorComponent) return; MultiLineErrorComponent c = new MultiLineErrorComponent(myConfigurationErrorsListModel) { @Override @@ -568,13 +564,13 @@ public class ConfigurationErrorsComponent extends JPanel implements Disposable, if (errors.size() == 1) { mySingleErrorLabel.setText(myModel.getErrors().get(0).getPlainTextTitle()); } else { - myErrorsLabel.setText(String.format("%s errors found", errors.size())); + myErrorsLabel.setText(String.format("%s errors found", getErrorsCount(errors.size()))); } } final List ignoredErrors = myModel.getIgnoredErrors(); if (ignoredErrors.size() > 0) { - myIgnoredErrorsLabel.setText(String.format("%s ignored error%s", ignoredErrors.size(), ignoredErrors.size() == 1 ? "" : "s")); + myIgnoredErrorsLabel.setText(String.format("%s ignored error%s", getErrorsCount(ignoredErrors.size()), ignoredErrors.size() == 1 ? "" : "s")); } removeAll(); @@ -595,6 +591,10 @@ public class ConfigurationErrorsComponent extends JPanel implements Disposable, repaint(); } + private static String getErrorsCount(final int size) { + return size < MAX_ERRORS_TO_SHOW ? String.valueOf(size) : MAX_ERRORS_TO_SHOW + "+"; + } + private JComponent wrapLabel(@NotNull final JLabel label, @NotNull final ConfigurationError configurationError) { final JPanel result = new JPanel(new BorderLayout()); result.setBackground(label.getBackground()); @@ -653,7 +653,9 @@ public class ConfigurationErrorsComponent extends JPanel implements Disposable, public void onClick(MouseEvent e) { final Object o = myModel.getElementAt(0); if (o instanceof ConfigurationError) { - ((ConfigurationError)o).ignore(!((ConfigurationError)o).isIgnored()); + final ConfigurationError error = (ConfigurationError)o; + error.ignore(!error.isIgnored()); + myModel.update(error); updateView(); } } @@ -678,72 +680,92 @@ public class ConfigurationErrorsComponent extends JPanel implements Disposable, } } + //todo[nik] move to ContainerUtil after 11.1 + @NotNull + private static List concat(@NotNull final List list1, @NotNull final List list2) { + return new AbstractList() { + public T get(int index) { + if (index < list1.size()) { + return list1.get(index); + } + + return list2.get(index - list1.size()); + } + + public int size() { + return list1.size() + list2.size(); + } + }; + } + private static class ConfigurationErrorsListModel extends AbstractListModel implements ConfigurationErrors, Disposable { private MessageBusConnection myConnection; - private List myErrorsList = new ArrayList(); - private Condition myFilter; + private List myNotIgnoredErrors = new ArrayList(); + private List myAllErrors; + private List myIgnoredErrors = new ArrayList(); private ConfigurationErrorsListModel(@NotNull final Project project) { + setFilter(true, true); myConnection = project.getMessageBus().connect(); myConnection.subscribe(TOPIC, this); } - public void setFilter(Condition filter) { - myFilter = filter; + public void setFilter(boolean showNotIgnored, boolean showIgnored) { + if (showIgnored && showNotIgnored) { + myAllErrors = concat(myNotIgnoredErrors, myIgnoredErrors); + } + else if (showIgnored) { + myAllErrors = myIgnoredErrors; + } + else { + myAllErrors = myNotIgnoredErrors; + } } @Override public int getSize() { - return myFilter == null ? myErrorsList.size() : ContainerUtil.filter(myErrorsList, myFilter).size(); + return Math.min(myAllErrors.size(), MAX_ERRORS_TO_SHOW); } @Override public Object getElementAt(int index) { - return myFilter == null ? myErrorsList.get(index) : ContainerUtil.filter(myErrorsList, myFilter).get(index); + return myAllErrors.get(index); } - private boolean accept(ConfigurationError error) { - return myFilter == null || myFilter.value(error); - } - @Override public void addError(@NotNull ConfigurationError error) { - if (!myErrorsList.contains(error) && accept(error)) { - int ndx = 0; - if (error.isIgnored()) { - ndx = myErrorsList.size(); + if (!myAllErrors.contains(error)) { + List targetList = error.isIgnored() ? myIgnoredErrors : myNotIgnoredErrors; + if (targetList.size() < MAX_ERRORS_TO_SHOW) { + targetList.add(0, error); + } + else { + targetList.add(error); } - myErrorsList.add(ndx, error); - fireIntervalAdded(this, ndx, ndx); + int i = myAllErrors.indexOf(error); + if (i != -1 && i < MAX_ERRORS_TO_SHOW) { + fireIntervalAdded(this, i, i); + } } } @Override public void removeError(@NotNull ConfigurationError error) { - if (myErrorsList.contains(error)) { - final int ndx = myErrorsList.indexOf(error); - myErrorsList.remove(ndx); - fireIntervalRemoved(this, ndx, ndx); + final int i = myAllErrors.indexOf(error); + myIgnoredErrors.remove(error); + myNotIgnoredErrors.remove(error); + if (i != -1 && i < MAX_ERRORS_TO_SHOW) { + fireIntervalRemoved(this, i, i); } } public List getErrors() { - return ContainerUtil.filter(myErrorsList, new Condition() { - @Override - public boolean value(final ConfigurationError error) { - return !error.isIgnored(); - } - }); + return myNotIgnoredErrors; } public List getIgnoredErrors() { - return ContainerUtil.filter(myErrorsList, new Condition() { - @Override - public boolean value(final ConfigurationError error) { - return error.isIgnored(); - } - }); + return myIgnoredErrors; } @Override @@ -755,9 +777,30 @@ public class ConfigurationErrorsComponent extends JPanel implements Disposable, } public void update(final ConfigurationError error) { - final int ndx = myErrorsList.indexOf(error); - if (ndx >= 0) { - fireContentsChanged(this, ndx, ndx); + final int i0 = myAllErrors.indexOf(error); + if (error.isIgnored()) { + if (myNotIgnoredErrors.remove(error)) { + myIgnoredErrors.add(0, error); + } + } + else { + if (myIgnoredErrors.remove(error)) { + myNotIgnoredErrors.add(0, error); + } + } + final int i1 = myAllErrors.indexOf(error); + if (i0 == i1 && i0 != -1) { + if (i0 < MAX_ERRORS_TO_SHOW) { + fireContentsChanged(this, i0, i0); + } + } + else { + if (i0 != -1 && i0 < MAX_ERRORS_TO_SHOW) { + fireIntervalRemoved(this, i0, i0); + } + if (i1 != -1 && i1 < MAX_ERRORS_TO_SHOW) { + fireIntervalAdded(this, i1, i1); + } } } } 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 10bdcd813327..68688e1cbee0 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 @@ -18,7 +18,7 @@ package com.intellij.openapi.roots.ui.configuration; import com.intellij.compiler.ModuleCompilerUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectBundle; -import com.intellij.openapi.roots.ModifiableRootModel; +import com.intellij.openapi.roots.ModuleRootModel; import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext; import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.*; import com.intellij.openapi.util.text.StringUtil; @@ -49,14 +49,13 @@ public class GeneralProjectSettingsElement extends ProjectStructureElement { @Override public void check(ProjectStructureProblemsHolder problemsHolder) { - final Graph> graph = ModuleCompilerUtil.toChunkGraph( - myContext.getModulesConfigurator().createGraphGenerator()); - final Collection> chunks = graph.getNodes(); + final Graph> graph = ModuleCompilerUtil.toChunkGraph(myContext.getModulesConfigurator().createGraphGenerator()); + final Collection> chunks = graph.getNodes(); List cycles = new ArrayList(); - for (Chunk chunk : chunks) { - final Set modules = chunk.getNodes(); + for (Chunk chunk : chunks) { + final Set modules = chunk.getNodes(); List names = new ArrayList(); - for (ModifiableRootModel model : modules) { + for (ModuleRootModel model : modules) { names.add(model.getModule().getName()); } if (modules.size() > 1) { diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.java index 35fcf40f66f7..8f60ad874018 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.java @@ -213,10 +213,10 @@ public class ModulesConfigurator implements ModulesProvider, ModuleEditor.Change myAllModulesChangeListeners.add(listener); } - public GraphGenerator createGraphGenerator() { - final Map models = new HashMap(); + public GraphGenerator createGraphGenerator() { + final Map models = new HashMap(); for (ModuleEditor moduleEditor : myModuleEditors) { - models.put(moduleEditor.getModule(), moduleEditor.getModifiableRootModel()); + models.put(moduleEditor.getModule(), moduleEditor.getRootModel()); } return ModuleCompilerUtil.createGraphGenerator(models); } diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/JavaLangClassMemberReference.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/JavaLangClassMemberReference.java new file mode 100644 index 000000000000..8b93c386d07c --- /dev/null +++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/JavaLangClassMemberReference.java @@ -0,0 +1,164 @@ +/* + * 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.psi.impl.source.resolve.reference.impl; + +import com.intellij.codeInsight.completion.InsertHandler; +import com.intellij.codeInsight.completion.InsertionContext; +import com.intellij.codeInsight.completion.JavaLookupElementBuilder; +import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.codeInsight.lookup.LookupElementBuilder; +import com.intellij.psi.*; +import com.intellij.psi.codeStyle.JavaCodeStyleManager; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.PsiTypesUtil; +import com.intellij.psi.util.PsiUtilCore; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Konstantin Bulenkov + */ +public class JavaLangClassMemberReference extends PsiReferenceBase implements InsertHandler { + private final PsiClassObjectAccessExpression myContext; + + public JavaLangClassMemberReference(PsiLiteralExpression literal, PsiClassObjectAccessExpression context) { + super(literal); + myContext = context; + } + + @Override + public PsiElement resolve() { + final String name = (String)getElement().getValue(); + final Type type = getType(); + + if (type != null) { + final PsiClass psiClass = getPsiClass(); + if (psiClass != null) { + PsiMember member; + if (type == Type.FIELD || type == Type.DECLARED_FIELD) { + member = psiClass.findFieldByName(name, false); + } else { + final PsiMethod[] methods = psiClass.findMethodsByName(name, false); + member = methods.length == 0 ? null : methods[0]; + } + + return member; + } + } + + return null; + } + + @Nullable + private PsiClass getPsiClass() { + return PsiTypesUtil.getPsiClass(myContext.getOperand().getType()); + } + + @Nullable + private Type getType() { + boolean selfFound = false; + for (PsiElement child : myContext.getParent().getChildren()) { + if (!selfFound) { + if (child == myContext) { + selfFound = true; + } + continue; + } + + if (child instanceof PsiIdentifier) { + return Type.fromString(child.getText()); + } + } + return null; + } + + @NotNull + @Override + public Object[] getVariants() { + final Type type = getType(); + final PsiClass psiClass = getPsiClass(); + if (psiClass != null && type != null) { + if (type == Type.DECLARED_FIELD) { + return psiClass.getFields(); + } else if (type == Type.FIELD) { + final List fields = new ArrayList(); + for (PsiField field : psiClass.getFields()) { + if (isPublic(field)) { + fields.add(field); + } + } + return fields.toArray(); + } else if (type == Type.DECLARED_METHOD || type == Type.METHOD) { + final List elements = new ArrayList(); + for (PsiMethod method : psiClass.getMethods()) { + if (type == Type.DECLARED_METHOD || isPublic(method)) { + elements.add(JavaLookupElementBuilder.forMethod(method, PsiSubstitutor.EMPTY).setInsertHandler(this)); + } + } + return elements.toArray(); + } + } + return EMPTY_ARRAY; + } + + @Override + public void handleInsert(InsertionContext context, LookupElement item) { + final Object object = item.getObject(); + if (object instanceof PsiMethod) { + final PsiElement newElement = PsiUtilCore.getElementAtOffset(context.getFile(), context.getStartOffset()); + final int start = newElement.getTextRange().getEndOffset(); + final PsiElement params = newElement.getParent().getParent(); + final int end = params.getTextRange().getEndOffset() - 1; + final String types = getMethodTypes((PsiMethod)object); + context.getDocument().replaceString(start, end, types); + context.commitDocument(); + final PsiElement firstParam = PsiUtilCore.getElementAtOffset(context.getFile(), context.getStartOffset()); + final PsiMethodCallExpression methodCall = PsiTreeUtil.getParentOfType(firstParam, PsiMethodCallExpression.class); + if (methodCall != null) { + JavaCodeStyleManager.getInstance(context.getProject()).shortenClassReferences(methodCall); + } + } + } + + private static boolean isPublic(final PsiMember psiField) { + return psiField.hasModifierProperty(PsiModifier.PUBLIC); + } + + private static String getMethodTypes(PsiMethod method) { + final StringBuilder buf = new StringBuilder(); + for (PsiParameter parameter : method.getParameterList().getParameters()) { + buf.append(", ").append(parameter.getType().getCanonicalText()).append(".class"); + } + return buf.toString(); + } + + + enum Type { + FIELD, DECLARED_FIELD, METHOD, DECLARED_METHOD; + + @Nullable + static Type fromString(String s) { + if ("getField".equals(s)) return FIELD; + if ("getDeclaredField".equals(s)) return DECLARED_FIELD; + if ("getMethod".equals(s)) return METHOD; + if ("getDeclaredMethod".equals(s)) return DECLARED_METHOD; + return null; + } + } +} diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/JavaReflectionCompletionConfidence.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/JavaReflectionCompletionConfidence.java new file mode 100644 index 000000000000..6b77a6dcb752 --- /dev/null +++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/JavaReflectionCompletionConfidence.java @@ -0,0 +1,47 @@ +/* + * 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.psi.impl.source.resolve.reference.impl; + +import com.intellij.codeInsight.completion.CompletionConfidence; +import com.intellij.codeInsight.completion.CompletionParameters; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.util.ThreeState; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Konstantin Bulenkov + */ +public class JavaReflectionCompletionConfidence extends CompletionConfidence { + @NotNull + @Override + public ThreeState shouldFocusLookup(@NotNull CompletionParameters parameters) { + return ThreeState.UNSURE; + } + + @NotNull + @Override + public ThreeState shouldSkipAutopopup(@Nullable PsiElement contextElement, @NotNull PsiFile psiFile, int offset) { + if (contextElement != null) { + final PsiElement literal = contextElement.getParent(); + if (literal != null && JavaReflectionReferenceContributor.PATTERN.accepts(literal)) { + return ThreeState.NO; + } + } + return super.shouldSkipAutopopup(contextElement, psiFile, offset); + } +} diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/JavaReflectionReferenceContributor.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/JavaReflectionReferenceContributor.java new file mode 100644 index 000000000000..06e5d4a672f4 --- /dev/null +++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/JavaReflectionReferenceContributor.java @@ -0,0 +1,44 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.psi.impl.source.resolve.reference.impl; + +import com.intellij.patterns.PsiJavaElementPattern; +import com.intellij.psi.PsiLiteral; +import com.intellij.psi.PsiReferenceContributor; +import com.intellij.psi.PsiReferenceRegistrar; + +import static com.intellij.patterns.PsiJavaPatterns.psiExpression; +import static com.intellij.patterns.PsiJavaPatterns.psiLiteral; +import static com.intellij.patterns.PsiJavaPatterns.psiMethod; +import static com.intellij.patterns.StandardPatterns.string; +import static com.intellij.psi.CommonClassNames.JAVA_LANG_CLASS; + +/** + * @author Konstantin Bulenkov + */ +public class JavaReflectionReferenceContributor extends PsiReferenceContributor { + public static final PsiJavaElementPattern.Capture PATTERN = + psiLiteral().inside(psiExpression().methodCall(psiMethod().withName(string().oneOf("getDeclaredField", + "getField", + "getMethod", + "getDeclaredMethod")) + .definedInClass(JAVA_LANG_CLASS))); + + @Override + public void registerReferenceProviders(PsiReferenceRegistrar registrar) { + registrar.registerReferenceProvider(PATTERN, new JavaReflectionReferenceProvider()); + } +} diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/JavaReflectionReferenceProvider.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/JavaReflectionReferenceProvider.java new file mode 100644 index 000000000000..6a29dcb93197 --- /dev/null +++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/JavaReflectionReferenceProvider.java @@ -0,0 +1,50 @@ +/* + * 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.psi.impl.source.resolve.reference.impl; + +import com.intellij.psi.*; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.ProcessingContext; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Konstantin Bulenkov + */ +public class JavaReflectionReferenceProvider extends PsiReferenceProvider { + @NotNull + @Override + public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) { + if (element instanceof PsiLiteralExpression) { + String value = getValue(((PsiLiteralExpression)element)); + final PsiElement expressionList; + if (value != null && (expressionList = element.getParent()) instanceof PsiExpressionList) { + final PsiElement methodCall = expressionList.getParent(); + final PsiClassObjectAccessExpression classAccess; + if (methodCall != null && (classAccess = PsiTreeUtil.findChildOfType(methodCall, PsiClassObjectAccessExpression.class)) != null) { + return new PsiReference[]{new JavaLangClassMemberReference((PsiLiteralExpression)element, classAccess)}; + } + } + } + return PsiReference.EMPTY_ARRAY; + } + + @Nullable + private static String getValue(PsiLiteralExpression element) { + final Object value = element.getValue(); + return value instanceof String ? (String)value : null; + } +} diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDialog.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDialog.java index c5b5432c58ce..95ad17bdbe61 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDialog.java @@ -19,6 +19,7 @@ import com.intellij.codeInsight.completion.CompletionResultSet; import com.intellij.codeInsight.lookup.LookupElementBuilder; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CustomShortcutSet; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.colors.EditorFontType; @@ -29,6 +30,7 @@ import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.VerticalFlowLayout; +import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.text.StringUtil; @@ -558,7 +560,7 @@ public class JavaChangeSignatureDialog extends ChangeSignatureDialogBase item = parameterInfos.get(i); + final ParameterTableModelItemBase item = parameterInfos.get(i); if (!JavaPsiFacade.getInstance(manager.getProject()).getNameHelper().isIdentifier(item.parameter.getName())) { return RefactoringMessageUtil.getIncorrectIdentifierMessage(item.parameter.getName()); @@ -582,7 +584,12 @@ public class JavaChangeSignatureDialog extends ChangeSignatureDialogBase() { + @Override + public String compute() { + return JavaCodeStyleManager.getInstance(myProject).qualifyClassReferences(item.defaultValueCodeFragment).getText(); + } + }); String def = item.parameter.defaultValue; def = def.trim(); if (!(type instanceof PsiEllipsisType)) { diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java index a931ba654458..98c263f5103f 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java @@ -375,7 +375,7 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr else { newArg = factory.createExpressionFromText(info.getName(), list); } - list.add(newArg); + JavaCodeStyleManager.getInstance(list.getProject()).shortenClassReferences(list.add(newArg)); } } else { @@ -630,7 +630,7 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr else { actualArg = changeInfo.getValue(i, callExpression); } - callExpression.getArgumentList().add(actualArg); + JavaCodeStyleManager.getInstance(callExpression.getProject()).shortenClassReferences(callExpression.getArgumentList().add(actualArg)); } } diff --git a/java/java-impl/src/com/intellij/refactoring/introduceVariable/JavaVariableInplaceIntroducer.java b/java/java-impl/src/com/intellij/refactoring/introduceVariable/JavaVariableInplaceIntroducer.java index c9a9d826bd82..d9d0dc41135a 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceVariable/JavaVariableInplaceIntroducer.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceVariable/JavaVariableInplaceIntroducer.java @@ -28,6 +28,7 @@ import com.intellij.openapi.keymap.Keymap; import com.intellij.openapi.keymap.KeymapManager; import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Comparing; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.codeStyle.JavaCodeStyleManager; @@ -189,13 +190,15 @@ public class JavaVariableInplaceIntroducer extends InplaceVariableIntroducer"); } +} - public String getSerializedComponents() { - return mySerializedComponents; - } +class Test { + public int num; + public int num2; + int num3; } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/reflection/DeclaredField_after.java b/java/java-tests/testData/codeInsight/completion/reflection/DeclaredField_after.java new file mode 100644 index 000000000000..924c8f05deca --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/reflection/DeclaredField_after.java @@ -0,0 +1,26 @@ +/* + * 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. + */ +class DeclaredField { + void foo() { + Test.class.getDeclaredField("num2"); + } +} + +class Test { + public int num; + public int num2; + int num3; +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/reflection/DeclaredMethod.java b/java/java-tests/testData/codeInsight/completion/reflection/DeclaredMethod.java new file mode 100644 index 000000000000..5abc4c462133 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/reflection/DeclaredMethod.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. + */ +class DecalredMethod { + void foo() { + Test.class.getDeclaredMethod(""); + } +} + +class Test { + public void method(){} + public void method2(A a, B b){} + public void method3(){} +} + +class A {} +class B {} +class C {} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/reflection/DeclaredMethod2.java b/java/java-tests/testData/codeInsight/completion/reflection/DeclaredMethod2.java new file mode 100644 index 000000000000..7c63f9b3fb11 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/reflection/DeclaredMethod2.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. + */ +class DecalredMethod2 { + void foo() { + Test.class.getDeclaredMethod("m", A.class, B.class); + } +} + +class Test { + void method(){} + void method2(A a, B b){} + void method3(){} +} + +class A {} +class B {} +class C {} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/reflection/DeclaredMethod2_after.java b/java/java-tests/testData/codeInsight/completion/reflection/DeclaredMethod2_after.java new file mode 100644 index 000000000000..f9d56a003ff2 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/reflection/DeclaredMethod2_after.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. + */ +class DecalredMethod2 { + void foo() { + Test.class.getDeclaredMethod("method3"); + } +} + +class Test { + void method(){} + void method2(A a, B b){} + void method3(){} +} + +class A {} +class B {} +class C {} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/reflection/DeclaredMethod_after.java b/java/java-tests/testData/codeInsight/completion/reflection/DeclaredMethod_after.java new file mode 100644 index 000000000000..c6c0d5bce7d3 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/reflection/DeclaredMethod_after.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. + */ +class DecalredMethod { + void foo() { + Test.class.getDeclaredMethod("method2", A.class, B.class); + } +} + +class Test { + public void method(){} + public void method2(A a, B b){} + public void method3(){} +} + +class A {} +class B {} +class C {} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/reflection/Field.java b/java/java-tests/testData/codeInsight/completion/reflection/Field.java new file mode 100644 index 000000000000..1d39408e856d --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/reflection/Field.java @@ -0,0 +1,26 @@ +/* + * 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. + */ +class Field { + void foo() { + Test.class.getField(""); + } +} + +class Test { + public int num; + public int num2; + int num3; +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/reflection/Field_after.java b/java/java-tests/testData/codeInsight/completion/reflection/Field_after.java new file mode 100644 index 000000000000..352645d05ae8 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/reflection/Field_after.java @@ -0,0 +1,26 @@ +/* + * 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. + */ +class Field { + void foo() { + Test.class.getField("num2"); + } +} + +class Test { + public int num; + public int num2; + int num3; +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/reflection/Method.java b/java/java-tests/testData/codeInsight/completion/reflection/Method.java new file mode 100644 index 000000000000..d6e0b9625f6e --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/reflection/Method.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. + */ +class DecalredMethod { + void foo() { + Test.class.getMethod(""); + } +} + +class Test { + public void method(){} + public void method2(A a, B b){} + void method3(){} +} + +class A {} +class B {} +class C {} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/reflection/Method_after.java b/java/java-tests/testData/codeInsight/completion/reflection/Method_after.java new file mode 100644 index 000000000000..986c6e2078b6 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/reflection/Method_after.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. + */ +class DecalredMethod { + void foo() { + Test.class.getMethod("method2", A.class, B.class); + } +} + +class Test { + public void method(){} + public void method2(A a, B b){} + void method3(){} +} + +class A {} +class B {} +class C {} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaReflectionCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaReflectionCompletionTest.java new file mode 100644 index 000000000000..86351f99e964 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaReflectionCompletionTest.java @@ -0,0 +1,62 @@ +/* + * 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.codeInsight.completion; + +import com.intellij.JavaTestUtil; + +/** + * @author Konstantin Bulenkov + */ +public class JavaReflectionCompletionTest extends LightFixtureCompletionTestCase { + + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + @Override + protected String getBasePath() { + return JavaTestUtil.getRelativeJavaTestDataPath() + "/codeInsight/completion/reflection/"; + } + + public void testField() throws Exception { + doTest(1, "num", "num2"); + } + + public void testDeclaredField() throws Exception { + doTest(1, "num", "num2", "num3"); + } + + public void testDeclaredMethod() throws Exception { + doTest(1, "method", "method2", "method3"); + } + + public void testDeclaredMethod2() throws Exception { + doTest(2, "method", "method2", "method3"); + } + + public void testMethod() throws Exception { + doTest(1, "method", "method2"); + } + + + private void doTest(int index, String... expected) { + configureByFile(getTestName(false) + ".java"); + assertStringItems(expected); + selectItem(getLookup().getItems().get(index)); + myFixture.checkResultByFile(getTestName(false) + "_after.java"); + } +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/api/GlobalOptions.java b/jps/jps-builders/src/org/jetbrains/jps/api/GlobalOptions.java index 547f8135d93d..f2fdd71e4b0d 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/api/GlobalOptions.java +++ b/jps/jps-builders/src/org/jetbrains/jps/api/GlobalOptions.java @@ -5,10 +5,8 @@ package org.jetbrains.jps.api; * Date: 1/24/12 */ public interface GlobalOptions { - String USE_MEMORY_TEMP_CACHE_OPTION = "use.memory.temp.cache"; String USE_EXTERNAL_JAVAC_OPTION = "use.external.javac.process"; String HOSTNAME_OPTION = "localhost.name"; - String VM_EXE_PATH_OPTION = "vm.executable.path"; String PING_INTERVAL_MS_OPTION = "server.ping.interval"; } 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 b2b4b95ac98e..93613fbd9a0c 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/CompileContext.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/CompileContext.java @@ -13,6 +13,7 @@ import org.jetbrains.jps.incremental.messages.UptoDateFilesSavedEvent; import org.jetbrains.jps.incremental.storage.BuildDataManager; import org.jetbrains.jps.incremental.storage.SourceToOutputMapping; import org.jetbrains.jps.incremental.storage.TimestampStorage; +import org.jetbrains.jps.server.ProjectDescriptor; import java.io.File; import java.io.IOException; @@ -29,51 +30,40 @@ public class CompileContext extends UserDataHolderBase implements MessageHandler private final boolean myIsProjectRebuild; private final ProjectChunks myProductionChunks; private final ProjectChunks myTestChunks; - private final FSState myFsState; private final MessageHandler myDelegateMessageHandler; private volatile boolean myCompilingTests = false; - private final BuildDataManager myDataManager; - private final ModuleRootsIndex myRootsIndex; - private final Set> myNonIncrementalModules = new HashSet>(); private final ProjectPaths myProjectPaths; private volatile boolean myErrorsFound = false; private final long myCompilationStartStamp; + private final ProjectDescriptor myProjectDescriptor; private final TimestampStorage myTsStorage; - private final BuildLoggingManager myLoggingManager; private final Map myBuilderParams; private final CanceledStatus myCancelStatus; private float myDone = -1.0f; public CompileContext(CompileScope scope, - boolean isMake, + ProjectDescriptor pd, boolean isMake, boolean isProjectRebuild, ProjectChunks productionChunks, ProjectChunks testChunks, - FSState fsState, - final BuildDataManager dataManager, - TimestampStorage tsStorage, MessageHandler delegateMessageHandler, - final ModuleRootsIndex rootsIndex, - BuildLoggingManager loggingManager, Map builderParams, + Map builderParams, CanceledStatus cancelStatus) throws ProjectBuildException { - myTsStorage = tsStorage; - myLoggingManager = loggingManager; + myProjectDescriptor = pd; + myTsStorage = myProjectDescriptor.timestamps.getStorage(); myBuilderParams = Collections.unmodifiableMap(builderParams); myCancelStatus = cancelStatus; myCompilationStartStamp = System.currentTimeMillis(); myScope = scope; myIsProjectRebuild = isProjectRebuild; - myIsMake = isProjectRebuild? false : isMake; + myIsMake = !isProjectRebuild && isMake; myProductionChunks = productionChunks; myTestChunks = testChunks; - myFsState = fsState; myDelegateMessageHandler = delegateMessageHandler; - myDataManager = dataManager; final Project project = scope.getProject(); myProjectPaths = new ProjectPaths(project); - myRootsIndex = rootsIndex; } public Project getProject() { @@ -93,7 +83,7 @@ public class CompileContext extends UserDataHolderBase implements MessageHandler } public BuildLoggingManager getLoggingManager() { - return myLoggingManager; + return myProjectDescriptor.getLoggingManager(); } @Nullable @@ -104,26 +94,26 @@ public class CompileContext extends UserDataHolderBase implements MessageHandler public void markDirty(final File file) throws IOException { final RootDescriptor descriptor = getModuleAndRoot(file); if (descriptor != null) { - myFsState.markDirty(file, descriptor, myTsStorage); + myProjectDescriptor.fsState.markDirty(file, descriptor, myTsStorage); } } public void markDirtyIfNotDeleted(final File file) throws IOException { final RootDescriptor descriptor = getModuleAndRoot(file); if (descriptor != null) { - myFsState.markDirtyIfNotDeleted(file, descriptor, myTsStorage); + myProjectDescriptor.fsState.markDirtyIfNotDeleted(file, descriptor, myTsStorage); } } public void markDeleted(File file) throws IOException { final RootDescriptor descriptor = getModuleAndRoot(file); if (descriptor != null) { - myFsState.registerDeleted(descriptor.module, file, descriptor.isTestRoot, myTsStorage); + myProjectDescriptor.fsState.registerDeleted(descriptor.module, file, descriptor.isTestRoot, myTsStorage); } } public void markDirty(final ModuleChunk chunk) throws IOException { - myFsState.clearContextRoundData(); + myProjectDescriptor.fsState.clearContextRoundData(); final Set modules = chunk.getModules(); for (Module module : modules) { markDirtyFiles(module, myTsStorage, true, isCompilingTests()? DirtyMarkScope.TESTS : DirtyMarkScope.PRODUCTION, null); @@ -182,7 +172,7 @@ public class CompileContext extends UserDataHolderBase implements MessageHandler } public Mappings createDelta() { - return myDataManager.getMappings().createDelta(); + return getDataManager().getMappings().createDelta(); } public boolean isCompilingTests() { @@ -208,18 +198,18 @@ public class CompileContext extends UserDataHolderBase implements MessageHandler } void beforeCompileRound(@NotNull ModuleChunk chunk) { - myFsState.beforeNextRoundStart(); + myProjectDescriptor.fsState.beforeNextRoundStart(); } public void onChunkBuildStart(ModuleChunk chunk) { - myFsState.setContextChunk(chunk); + myProjectDescriptor.fsState.setContextChunk(chunk); } void onChunkBuildComplete(@NotNull ModuleChunk chunk) throws IOException { - myDataManager.closeSourceToOutputStorages(chunk, isCompilingTests()); - myDataManager.flush(true); - myFsState.clearContextRoundData(); - myFsState.clearContextChunk(); + getDataManager().closeSourceToOutputStorages(chunk, isCompilingTests()); + getDataManager().flush(true); + myProjectDescriptor.fsState.clearContextRoundData(); + myProjectDescriptor.fsState.clearContextChunk(); if (!myErrorsFound && !myCancelStatus.isCanceled()) { final boolean compilingTests = isCompilingTests(); @@ -231,12 +221,12 @@ public class CompileContext extends UserDataHolderBase implements MessageHandler myNonIncrementalModules.remove(new Pair(module, dirtyScope)); } if (isProjectRebuild()) { - myFsState.markInitialScanPerformed(module, compilingTests); + myProjectDescriptor.fsState.markInitialScanPerformed(module, compilingTests); } - final List roots = myRootsIndex.getModuleRoots(module); + final List roots = myProjectDescriptor.rootsIndex.getModuleRoots(module); for (RootDescriptor descriptor : roots) { if (compilingTests? descriptor.isTestRoot : !descriptor.isTestRoot) { - marked |= myFsState.markAllUpToDate(getScope(), descriptor, myTsStorage, myCompilationStartStamp); + marked |= myProjectDescriptor.fsState.markAllUpToDate(getScope(), descriptor, myTsStorage, myCompilationStartStamp); } } } @@ -251,7 +241,7 @@ public class CompileContext extends UserDataHolderBase implements MessageHandler } public BuildDataManager getDataManager() { - return myDataManager; + return myProjectDescriptor.dataManager; } public TimestampStorage getTimestampStorage() { @@ -274,7 +264,7 @@ public class CompileContext extends UserDataHolderBase implements MessageHandler public void processFilesToRecompile(ModuleChunk chunk, FileProcessor processor) throws IOException { for (Module module : chunk.getModules()) { - myFsState.processFilesToRecompile(this, module, processor); + myProjectDescriptor.fsState.processFilesToRecompile(this, module, processor); } } @@ -285,7 +275,7 @@ public class CompileContext extends UserDataHolderBase implements MessageHandler } else { if (isMake()) { - if (myFsState.markInitialScanPerformed(module, isCompilingTests())) { + if (myProjectDescriptor.fsState.markInitialScanPerformed(module, isCompilingTests())) { initModuleFSState(module); } } @@ -310,7 +300,7 @@ public class CompileContext extends UserDataHolderBase implements MessageHandler // can check if the file exists final File file = new File(path); if (!currentFiles.contains(file)) { - myFsState.registerDeleted(module, file, isCompilingTests(), myTsStorage); + myProjectDescriptor.fsState.registerDeleted(module, file, isCompilingTests(), myTsStorage); } } } @@ -322,16 +312,16 @@ public class CompileContext extends UserDataHolderBase implements MessageHandler @Nullable public RootDescriptor getModuleAndRoot(File file) { - return myRootsIndex.getModuleAndRoot(file); + return getRootsIndex().getModuleAndRoot(file); } @NotNull public List getModuleRoots(Module module) { - return myRootsIndex.getModuleRoots(module); + return getRootsIndex().getModuleRoots(module); } public ModuleRootsIndex getRootsIndex() { - return myRootsIndex; + return myProjectDescriptor.rootsIndex; } public void setDone(float done) { @@ -339,6 +329,10 @@ public class CompileContext extends UserDataHolderBase implements MessageHandler //processMessage(new ProgressMessage("", done)); } + public ProjectDescriptor getProjectDescriptor() { + return myProjectDescriptor; + } + public static enum DirtyMarkScope{ PRODUCTION, TESTS, BOTH } @@ -362,8 +356,8 @@ public class CompileContext extends UserDataHolderBase implements MessageHandler if (!rd.root.exists()) { continue; } - myFsState.clearRecompile(rd); - myFsState.clearDeletedPaths(module, isCompilingTests()); + myProjectDescriptor.fsState.clearRecompile(rd); + myProjectDescriptor.fsState.clearDeletedPaths(module, isCompilingTests()); traverseRecursively(rd, rd.root, excludes, tsStorage, forceMarkDirty, currentFiles); } } @@ -386,7 +380,7 @@ public class CompileContext extends UserDataHolderBase implements MessageHandler // if it is full project rebuild, all storages are already completely cleared; // so passing null because there is no need to access the storage to clear non-existing data final TimestampStorage _tsStorage = isProjectRebuild() ? null : tsStorage; - myFsState.markDirty(file, rd, _tsStorage); + myProjectDescriptor.fsState.markDirty(file, rd, _tsStorage); } if (currentFiles != null) { currentFiles.add(file); 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 5d1d585234df..f59e2c6a0da9 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java @@ -19,7 +19,6 @@ import org.jetbrains.jps.incremental.messages.ProgressMessage; import org.jetbrains.jps.incremental.storage.BuildDataManager; import org.jetbrains.jps.incremental.storage.SourceToFormMapping; import org.jetbrains.jps.incremental.storage.SourceToOutputMapping; -import org.jetbrains.jps.incremental.storage.TimestampStorage; import org.jetbrains.jps.server.ProjectDescriptor; import java.io.File; @@ -217,13 +216,9 @@ public class IncProjectBuilder { } private CompileContext createContext(CompileScope scope, boolean isMake, final boolean isProjectRebuild) throws ProjectBuildException { - final TimestampStorage tsStorage = myProjectDescriptor.timestamps.getStorage(); - final FSState fsState = myProjectDescriptor.fsState; - final ModuleRootsIndex rootsIndex = myProjectDescriptor.rootsIndex; - final BuildDataManager dataManager = myProjectDescriptor.dataManager; return new CompileContext( - scope, isMake, isProjectRebuild, myProductionChunks, myTestChunks, fsState, dataManager, tsStorage, myMessageDispatcher, rootsIndex, - myProjectDescriptor.getLoggingManager(), myBuilderParams, myCancelStatus + scope, myProjectDescriptor, isMake, isProjectRebuild, myProductionChunks, myTestChunks, myMessageDispatcher, + myBuilderParams, myCancelStatus ); } 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 2b58b2b00d05..7a9f8686f656 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 @@ -11,6 +11,7 @@ import com.intellij.uiDesigner.compiler.*; import com.intellij.uiDesigner.core.GridConstraints; import com.intellij.uiDesigner.lw.CompiledClassPropertiesProvider; import com.intellij.uiDesigner.lw.LwRootContainer; +import com.intellij.util.SystemProperties; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.ether.dependencyView.Callbacks; @@ -30,7 +31,8 @@ import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Opcodes; import org.objectweb.asm.commons.EmptyVisitor; -import javax.tools.*; +import javax.tools.Diagnostic; +import javax.tools.JavaFileObject; import java.io.*; import java.net.MalformedURLException; import java.net.ServerSocket; @@ -46,6 +48,7 @@ import java.util.concurrent.TimeUnit; */ public class JavaBuilder extends ModuleLevelBuilder { public static final String BUILDER_NAME = "java"; + private static final String FORMS_BUILDER_NAME = "forms"; private static final String JAVA_EXTENSION = ".java"; private static final String FORM_EXTENSION = ".form"; public static final boolean USE_EMBEDDED_JAVAC = System.getProperty(GlobalOptions.USE_EXTERNAL_JAVAC_OPTION) == null; @@ -421,21 +424,31 @@ public class JavaBuilder extends ModuleLevelBuilder { }); } - - private static JavacServerClient ensureJavacServerLaunched(CompileContext context) throws Exception { final ExternalJavacDescriptor descriptor = ExternalJavacDescriptor.KEY.get(context); if (descriptor != null) { return descriptor.client; } // start server here - final String vmExecPath = System.getProperty(GlobalOptions.VM_EXE_PATH_OPTION, System.getProperty("java.home") + "/bin/java"); final String hostString = System.getProperty(GlobalOptions.HOSTNAME_OPTION, "localhost"); final int port = findFreePort(); final int heapSize = getJavacServerHeapSize(context); + // defaulting to the same jdk that used to run the server + String javaHome = SystemProperties.getJavaHome(); + int javaVersion = convertToNumber(SystemProperties.getJavaVersion()); + + for (JavaSdk sdk : context.getProjectDescriptor().getProjectJavaSdks()) { + final String version = sdk.getVersion(); + final int ver = convertToNumber(version); + if (ver > javaVersion) { + javaVersion = ver; + javaHome = sdk.getHomePath(); + } + } + final BaseOSProcessHandler processHandler = JavacServerBootstrap.launchJavacServer( - vmExecPath, heapSize, port, Paths.getSystemRoot(), getCompilationVMOptions(context) + javaHome, heapSize, port, Paths.getSystemRoot(), getCompilationVMOptions(context) ); final JavacServerClient client = new JavacServerClient(); try { @@ -449,6 +462,26 @@ public class JavaBuilder extends ModuleLevelBuilder { return client; } + private static int convertToNumber(final String ver) { + final String prefix = "1."; + if (ver.startsWith(prefix)) { + final String versionNumberString; + final int dotIndex = ver.indexOf(".", prefix.length()); + if (dotIndex > 0) { + versionNumberString = ver.substring(prefix.length(), dotIndex); + } + else { + versionNumberString = ver.substring(prefix.length()); + } + try { + return Integer.parseInt(versionNumberString); + } + catch (NumberFormatException ignored) { + } + } + return 0; + } + private static int findFreePort() { try { final ServerSocket serverSocket = new ServerSocket(0); @@ -711,7 +744,7 @@ public class JavaBuilder extends ModuleLevelBuilder { if (alreadyProcessedForm != null) { context.processMessage( new CompilerMessage( - BUILDER_NAME, BuildMessage.Kind.WARNING, + FORMS_BUILDER_NAME, BuildMessage.Kind.WARNING, formFile.getAbsolutePath() + ": The form is bound to the class " + classToBind + ".\nAnother form " + alreadyProcessedForm.getAbsolutePath() + " is also bound to this class", formFile.getAbsolutePath()) ); @@ -737,7 +770,7 @@ public class JavaBuilder extends ModuleLevelBuilder { final FormErrorInfo[] warnings = codeGenerator.getWarnings(); for (final FormErrorInfo warning : warnings) { context.processMessage( - new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.WARNING, warning.getErrorMessage(), formFile.getAbsolutePath())); + new CompilerMessage(FORMS_BUILDER_NAME, BuildMessage.Kind.WARNING, warning.getErrorMessage(), formFile.getAbsolutePath())); } final FormErrorInfo[] errors = codeGenerator.getErrors(); @@ -750,7 +783,7 @@ public class JavaBuilder extends ModuleLevelBuilder { } message.append(formFile.getAbsolutePath()).append(": ").append(error.getErrorMessage()); } - context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, message.toString())); + context.processMessage(new CompilerMessage(FORMS_BUILDER_NAME, BuildMessage.Kind.ERROR, message.toString())); } else { final File sourceFile = outputClassFile.getSourceFile(); @@ -761,7 +794,7 @@ public class JavaBuilder extends ModuleLevelBuilder { } catch (Exception e) { success = false; - context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, "Forms instrumentation failed" + e.getMessage(), + context.processMessage(new CompilerMessage(FORMS_BUILDER_NAME, BuildMessage.Kind.ERROR, "Forms instrumentation failed" + e.getMessage(), formFile.getAbsolutePath())); } finally { diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerBootstrap.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerBootstrap.java index aece320b89a0..8452f1d9b1e6 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerBootstrap.java +++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServerBootstrap.java @@ -22,14 +22,9 @@ import java.util.List; */ public class JavacServerBootstrap { - public static BaseOSProcessHandler launchJavacServer(String vmExecutablePath, - int heapSize, - int port, - File workingDir, - List vmOptions) throws Exception { - + public static BaseOSProcessHandler launchJavacServer(String sdkHomePath, int heapSize, int port, File workingDir, List vmOptions) throws Exception { final List cmdLine = new ArrayList(); - appendParam(cmdLine, vmExecutablePath); + appendParam(cmdLine, getVMExecutablePath(sdkHomePath)); appendParam(cmdLine, "-server"); appendParam(cmdLine, "-XX:MaxPermSize=150m"); //appendParam(cmdLine, "-XX:ReservedCodeCacheSize=64m"); @@ -64,7 +59,7 @@ public class JavacServerBootstrap { appendParam(cmdLine, "-classpath"); - final List cp = ClasspathBootstrap.getJavacServerClasspath(); + final List cp = ClasspathBootstrap.getJavacServerClasspath(sdkHomePath); final StringBuilder classpath = new StringBuilder(); for (File file : cp) { if (classpath.length() > 0) { @@ -155,4 +150,8 @@ public class JavacServerBootstrap { } cmdLine.add(param); } + + public static String getVMExecutablePath(String sdkHome) { + return sdkHome + "/bin/java"; + } } diff --git a/jps/jps-builders/src/org/jetbrains/jps/server/ClasspathBootstrap.java b/jps/jps-builders/src/org/jetbrains/jps/server/ClasspathBootstrap.java index be4dec0b646a..45502bed0f72 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/server/ClasspathBootstrap.java +++ b/jps/jps-builders/src/org/jetbrains/jps/server/ClasspathBootstrap.java @@ -18,8 +18,11 @@ package org.jetbrains.jps.server; import com.google.protobuf.Message; import com.intellij.compiler.notNullVerification.NotNullVerifyingInstrumenter; import com.intellij.openapi.application.PathManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.io.FileUtil; import com.intellij.uiDesigner.compiler.AlienFormFileException; import com.intellij.uiDesigner.core.GridConstraints; +import com.intellij.util.SystemProperties; import com.jgoodies.forms.layout.CellConstraints; import net.n3.nanoxml.IXMLBuilder; import org.codehaus.groovy.GroovyException; @@ -30,16 +33,21 @@ import org.jetbrains.jps.javac.JavacServer; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.commons.EmptyVisitor; -import javax.tools.*; +import javax.tools.JavaCompiler; +import javax.tools.StandardJavaFileManager; +import javax.tools.ToolProvider; import java.io.File; -import java.util.*; +import java.util.ArrayList; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; /** * @author Eugene Zhuravlev * Date: 9/12/11 */ public class ClasspathBootstrap { - public static final String JPS_RUNTIME_PATH = "rt/jps-incremental"; + private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.server.ClasspathBootstrap"); private static class OptimizedFileManagerClassHolder { static final String CLASS_NAME = "org.jetbrains.jps.javac.OptimizedFileManager"; @@ -119,31 +127,47 @@ public class ClasspathBootstrap { return new ArrayList(cp); } - public static List getJavacServerClasspath() { + public static List getJavacServerClasspath(String sdkHome) { final Set cp = new LinkedHashSet(); - cp.add(getResourcePath(JavacServer.class)); - for (String path : PathManager.getUtilClassPath()) { cp.add(new File(path)); } // util + cp.add(getResourcePath(JavacServer.class)); // self + // util + for (String path : PathManager.getUtilClassPath()) { + cp.add(new File(path)); + } cp.add(getResourcePath(Message.class)); // protobuf cp.add(getResourcePath(Version.class)); // netty final Class optimizedFileManagerClass = getOptimizedFileManagerClass(); if (optimizedFileManagerClass != null) { - cp.add(getResourcePath(optimizedFileManagerClass)); // optimizedFileManager + cp.add(getResourcePath(optimizedFileManagerClass)); // optimizedFileManager, if applicable } try { final Class cmdLineWrapper = Class.forName("com.intellij.rt.execution.CommandLineWrapper"); cp.add(getResourcePath(cmdLineWrapper)); // idea_rt.jar } - catch (Throwable ignored) { + catch (Throwable th) { + LOG.info(th); } final JavaCompiler systemCompiler = ToolProvider.getSystemJavaCompiler(); if (systemCompiler != null) { try { - cp.add(getResourcePath(systemCompiler.getClass())); // tools.jar + final String localJarPath = FileUtil.toSystemIndependentName(getResourcePath(systemCompiler.getClass()).getPath()); + final String localJavaHome = SystemProperties.getJavaHome(); + String relPath = FileUtil.getRelativePath(FileUtil.toSystemIndependentName(localJavaHome), localJarPath, '/'); + if (relPath != null) { + if (relPath.contains("..")) { + relPath = FileUtil.getRelativePath(FileUtil.toSystemIndependentName(new File(localJavaHome).getParent()), localJarPath, '/'); + } + if (relPath != null) { + final File targetFile = new File(sdkHome +"/" +relPath); + cp.add(targetFile); // tools.jar + } + } } - catch (Throwable ignored) { + catch (Throwable th) { + LOG.info(th); } } diff --git a/jps/jps-builders/src/org/jetbrains/jps/server/ProjectDescriptor.java b/jps/jps-builders/src/org/jetbrains/jps/server/ProjectDescriptor.java index 456f57f4964e..c15821806570 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/server/ProjectDescriptor.java +++ b/jps/jps-builders/src/org/jetbrains/jps/server/ProjectDescriptor.java @@ -1,6 +1,9 @@ package org.jetbrains.jps.server; +import org.jetbrains.jps.JavaSdk; +import org.jetbrains.jps.Module; import org.jetbrains.jps.Project; +import org.jetbrains.jps.Sdk; import org.jetbrains.jps.incremental.BuildLoggingManager; import org.jetbrains.jps.incremental.FSState; import org.jetbrains.jps.incremental.ModuleRootsIndex; @@ -8,6 +11,8 @@ import org.jetbrains.jps.incremental.storage.BuildDataManager; import org.jetbrains.jps.incremental.storage.ProjectTimestamps; import java.io.IOException; +import java.util.HashSet; +import java.util.Set; /** * @author Eugene Zhuravlev @@ -21,6 +26,7 @@ public final class ProjectDescriptor { private final BuildLoggingManager myLoggingManager; public ModuleRootsIndex rootsIndex; private int myUseCounter = 1; + private Set myProjectJavaSdks; public ProjectDescriptor(Project project, FSState fsState, @@ -33,6 +39,20 @@ public final class ProjectDescriptor { this.dataManager = dataManager; myLoggingManager = loggingManager; this.rootsIndex = new ModuleRootsIndex(project); + myProjectJavaSdks = new HashSet(); + for (Module module : project.getModules().values()) { + final Sdk sdk = module.getSdk(); + if (sdk instanceof JavaSdk && !myProjectJavaSdks.contains(sdk)) { + final JavaSdk javaSdk = (JavaSdk)sdk; + if (javaSdk.getVersion() != null && javaSdk.getHomePath() != null) { + myProjectJavaSdks.add(javaSdk); + } + } + } + } + + public Set getProjectJavaSdks() { + return myProjectJavaSdks; } public BuildLoggingManager getLoggingManager() { diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/ClassfileAnalyzer.java b/jps/model/src/org/jetbrains/ether/dependencyView/ClassfileAnalyzer.java index 3968e164c634..8d898122d8d1 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/ClassfileAnalyzer.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/ClassfileAnalyzer.java @@ -365,7 +365,9 @@ class ClassfileAnalyzer { public FieldVisitor visitField(int access, String n, String desc, String signature, Object value) { processSignature(signature); - fields.add(new FieldRepr(context, access, context.get(n), context.get(desc), context.get(signature), value)); + if ((access & Opcodes.ACC_SYNTHETIC) == 0) { + fields.add(new FieldRepr(context, access, context.get(n), context.get(desc), context.get(signature), value)); + } return new EmptyVisitor() { @Override @@ -388,7 +390,9 @@ class ClassfileAnalyzer { return new EmptyVisitor() { @Override public void visitEnd() { - methods.add(new MethodRepr(context, access, context.get(n), context.get(signature), desc, exceptions, defaultValue.get())); + if ((access & Opcodes.ACC_SYNTHETIC) == 0 || (access & Opcodes.ACC_BRIDGE) > 0) { + methods.add(new MethodRepr(context, access, context.get(n), context.get(signature), desc, exceptions, defaultValue.get())); + } } @Override diff --git a/jps/model/src/org/jetbrains/jps/JavaSdk.groovy b/jps/model/src/org/jetbrains/jps/JavaSdk.groovy index 132d69a2c49d..d7496afcdac0 100644 --- a/jps/model/src/org/jetbrains/jps/JavaSdk.groovy +++ b/jps/model/src/org/jetbrains/jps/JavaSdk.groovy @@ -1,5 +1,7 @@ package org.jetbrains.jps +import org.jetbrains.annotations.Nullable + /** * @author Eugene.Kudelevsky */ @@ -12,7 +14,17 @@ public abstract class JavaSdk extends Sdk { super(project, name, initializer) } - abstract String getJavacExecutable(); + @Nullable + public String getHomePath() { + return null; + } - abstract String getJavaExecutable(); + @Nullable + public String getVersion() { + return null; + } + + public abstract String getJavacExecutable(); + + public abstract String getJavaExecutable(); } \ No newline at end of file diff --git a/jps/model/src/org/jetbrains/jps/JavaSdkImpl.groovy b/jps/model/src/org/jetbrains/jps/JavaSdkImpl.groovy index 0f220220bfc4..f6a37f44a8f5 100644 --- a/jps/model/src/org/jetbrains/jps/JavaSdkImpl.groovy +++ b/jps/model/src/org/jetbrains/jps/JavaSdkImpl.groovy @@ -15,11 +15,21 @@ class JavaSdkImpl extends JavaSdk { this.jdkPath = jdkPath } - String getJavacExecutable() { + @Override + public String getHomePath() { + return jdkPath; + } + + @Override + public String getVersion() { + return version; + } + + public String getJavacExecutable() { return jdkPath + File.separator + "bin" + File.separator + "javac"; } - String getJavaExecutable() { + public String getJavaExecutable() { return jdkPath + File.separator + "bin" + File.separator + "java"; } } diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/CharArray.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/CharArray.java index 437c4edac2a9..625acc8a0a93 100644 --- a/platform/core-impl/src/com/intellij/openapi/editor/impl/CharArray.java +++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/CharArray.java @@ -180,8 +180,6 @@ abstract class CharArray implements CharSequenceBackedByArray { } private void assertConsistency() { - if (!myDebug) return; - if (isDeferredChangeMode()) { assert myOriginalSequence == null; } @@ -194,6 +192,8 @@ abstract class CharArray implements CharSequenceBackedByArray { int count = myCount + myDeferredShift; assert count == origLen || origLen==-1; assert count == stringLen || stringLen==-1; + + if (!myDebug) return; final String stringFromCharArray; if (myArray != null) { diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java index efbace051a9c..437d7233a42c 100644 --- a/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java +++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java @@ -72,7 +72,7 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx { private int myCheckGuardedBlocks = 0; private boolean myGuardsSuppressed = false; private boolean myEventsHandling = false; - private final boolean myAssertWriteAccess; + private final boolean myAssertThreading; private volatile boolean myDoingBulkUpdate = false; private volatile boolean myAcceptSlashR = false; private boolean myChangeInProgress; @@ -90,7 +90,7 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx { myLineSet.documentCreated(this); setCyclicBufferSize(0); setModificationStamp(LocalTimeCounter.currentTime()); - myAssertWriteAccess = !forUseInNonAWTThread; + myAssertThreading = !forUseInNonAWTThread; } public boolean setAcceptSlashR(boolean accept) { @@ -424,7 +424,7 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx { } private void assertWriteAccess() { - if (myAssertWriteAccess) { + if (myAssertThreading) { final Application application = ApplicationManager.getApplication(); if (application != null) { application.assertWriteAccessAllowed(); @@ -826,14 +826,12 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx { @Override protected void assertReadAccess() { - DocumentImpl.assertReadAccess(); - } - } - - private static void assertReadAccess() { - final Application application = ApplicationManager.getApplication(); - if (application != null) { - application.assertReadAccessAllowed(); + if (myAssertThreading) { + final Application application = ApplicationManager.getApplication(); + if (application != null) { + application.assertReadAccessAllowed(); + } + } } } } diff --git a/platform/lang-api/src/com/intellij/openapi/roots/ModifiableRootModel.java b/platform/lang-api/src/com/intellij/openapi/roots/ModifiableRootModel.java index 4a355e58d60c..2277d4f19954 100644 --- a/platform/lang-api/src/com/intellij/openapi/roots/ModifiableRootModel.java +++ b/platform/lang-api/src/com/intellij/openapi/roots/ModifiableRootModel.java @@ -172,10 +172,6 @@ public interface ModifiableRootModel extends ModuleRootModel { void setExcludeExplodedDirectory(boolean excludeExplodedDir); - @NotNull Module[] getModuleDependencies(); - - @NotNull Module[] getModuleDependencies(boolean includeTests); - boolean isWritable(); void setRootUrls(OrderRootType orderRootType, String[] urls); diff --git a/platform/lang-api/src/com/intellij/openapi/roots/ModuleRootModel.java b/platform/lang-api/src/com/intellij/openapi/roots/ModuleRootModel.java index ba8b609dacad..70bc9e503190 100644 --- a/platform/lang-api/src/com/intellij/openapi/roots/ModuleRootModel.java +++ b/platform/lang-api/src/com/intellij/openapi/roots/ModuleRootModel.java @@ -193,4 +193,10 @@ public interface ModuleRootModel { @NotNull String[] getRootUrls(OrderRootType rootType); T getModuleExtension(Class klass); + + @NotNull + Module[] getModuleDependencies(); + + @NotNull + Module[] getModuleDependencies(boolean includeTests); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/TargetElementUtilBase.java b/platform/lang-impl/src/com/intellij/codeInsight/TargetElementUtilBase.java index 0d5a094c5e71..cd9ada8bbbae 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/TargetElementUtilBase.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/TargetElementUtilBase.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,6 +33,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.actions.EditorActionUtil; import com.intellij.openapi.editor.ex.util.EditorUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; @@ -82,7 +83,14 @@ public class TargetElementUtilBase { @Nullable public static PsiReference findReference(Editor editor) { - return findReference(editor, editor.getCaretModel().getOffset()); + PsiReference result = findReference(editor, editor.getCaretModel().getOffset()); + if (result == null) { + final Integer offset = editor.getUserData(EditorActionUtil.EXPECTED_CARET_OFFSET); + if (offset != null) { + result = findReference(editor, offset); + } + } + return result; } @Nullable @@ -124,7 +132,15 @@ public class TargetElementUtilBase { public static PsiElement findTargetElement(Editor editor, int flags) { ApplicationManager.getApplication().assertIsDispatchThread(); - return getInstance().findTargetElement(editor, flags, editor.getCaretModel().getOffset()); + final PsiElement result = getInstance().findTargetElement(editor, flags, editor.getCaretModel().getOffset()); + if (result != null) { + return result; + } + final Integer offset = editor.getUserData(EditorActionUtil.EXPECTED_CARET_OFFSET); + if (offset != null) { + return getInstance().findTargetElement(editor, flags, offset); + } + return result; } public static boolean inVirtualSpace(Editor editor, int offset) { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java index 85d351a90410..5126b9042f6c 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java @@ -32,6 +32,8 @@ import com.intellij.profile.codeInspection.InspectionProfileManager; import com.intellij.profile.codeInspection.InspectionProjectProfileManager; import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashMap; +import gnu.trove.TObjectIntHashMap; +import gnu.trove.TObjectIntProcedure; import org.jdom.Element; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -52,7 +54,7 @@ public class SeverityRegistrar implements JDOMExternalizable, Comparator ourRendererColors = new THashMap(); @NonNls private static final String COLOR = "color"; - private final JDOMExternalizableStringList myOrder = new JDOMExternalizableStringList(); + private final TObjectIntHashMap myOrder = new TObjectIntHashMap(); private JDOMExternalizableStringList myReadOrder; private static final Map STANDARD_SEVERITIES = new THashMap(); @@ -161,38 +163,51 @@ public class SeverityRegistrar implements JDOMExternalizable, Comparator knownSeverities = getDefaultOrder(); - myOrder.retainAll(knownSeverities); + myReadOrder.readExternal(element); + for (int i = 0; i < myReadOrder.size(); i++) { + String name = myReadOrder.get(i); + HighlightSeverity severity = getSeverity(name); + if (severity == null) continue; + myOrder.put(severity, i); + } + final List knownSeverities = getDefaultOrder(); + myOrder.retainEntries(new TObjectIntProcedure() { + @Override + public boolean execute(HighlightSeverity severity, int order) { + return knownSeverities.contains(severity); + } + }); if (myOrder.isEmpty()) { - myOrder.addAll(knownSeverities); + setFromList(knownSeverities); } //enforce include all known + List list = getOrderAsList(); for (int i = 0; i < knownSeverities.size(); i++) { - String stdSeverity = knownSeverities.get(i); - if (!myOrder.contains(stdSeverity)) { - for (int oIdx = 0; oIdx < myOrder.size(); oIdx++) { - final String orderSeverity = myOrder.get(oIdx); - final HighlightInfoType type = STANDARD_SEVERITIES.get(orderSeverity); - if (type != null && knownSeverities.indexOf(type.getSeverity(null).toString()) > i) { - myOrder.add(oIdx, stdSeverity); + HighlightSeverity stdSeverity = knownSeverities.get(i); + if (!list.contains(stdSeverity)) { + for (int oIdx = 0; oIdx < list.size(); oIdx++) { + HighlightSeverity orderSeverity = list.get(oIdx); + HighlightInfoType type = STANDARD_SEVERITIES.get(orderSeverity.toString()); + if (type != null && knownSeverities.indexOf(type.getSeverity(null)) > i) { + list.add(oIdx, stdSeverity); myReadOrder = null; break; } } } } + setFromList(list); } @Override public void writeExternal(Element element) throws WriteExternalException { - for (String severity : getOrder()) { + List list = getOrderAsList(); + for (HighlightSeverity s : list) { Element info = new Element(INFO); + String severity = s.toString(); final SeverityBasedTextAttributes infoType = ourMap.get(severity); if (infoType != null) { infoType.writeExternal(info); @@ -203,29 +218,57 @@ public class SeverityRegistrar implements JDOMExternalizable, Comparator() { + @Override + public boolean execute(HighlightSeverity orderSeverity, int oIdx) { + ext.set(oIdx, orderSeverity.toString()); + return true; + } + }); + ext.writeExternal(element); } } + @NotNull + private List getOrderAsList() { + List list = new ArrayList(); + for (Object o : getOrder().keys()) { + list.add((HighlightSeverity)o); + } + Collections.sort(list, this); + return list; + } + public int getSeveritiesCount() { return createCurrentSeverities().size(); } public HighlightSeverity getSeverityByIndex(final int i) { - return getSeverity(getOrder().get(i)); + final HighlightSeverity[] found = new HighlightSeverity[1]; + getOrder().forEachEntry(new TObjectIntProcedure() { + @Override + public boolean execute(HighlightSeverity severity, int order) { + if (order == i) { + found[0] = severity; + return false; + } + return true; + } + }); + return found[0]; } public int getSeverityMaxIndex() { return getOrder().size(); } - public HighlightSeverity getSeverity(final String name) { + public HighlightSeverity getSeverity(@NotNull String name) { final HighlightInfoType type = STANDARD_SEVERITIES.get(name); if (type != null) return type.getSeverity(null); final SeverityBasedTextAttributes attributes = ourMap.get(name); @@ -233,6 +276,7 @@ public class SeverityRegistrar implements JDOMExternalizable, Comparator createCurrentSeverities() { List list = new ArrayList(); list.addAll(STANDARD_SEVERITIES.keySet()); @@ -241,7 +285,7 @@ public class SeverityRegistrar implements JDOMExternalizable, Comparator order = getOrder(); + return order.get(s1) - order.get(s2); } - private JDOMExternalizableStringList getOrder() { + + @NotNull + private TObjectIntHashMap getOrder() { if (myOrder.isEmpty()) { - myOrder.addAll(getDefaultOrder()); + List order = getDefaultOrder(); + setFromList(order); } return myOrder; } - private List getDefaultOrder() { + private void setFromList(@NotNull List order) { + myOrder.clear(); + for (int i = 0; i < order.size(); i++) { + HighlightSeverity severity = order.get(i); + myOrder.put(severity, i); + } + } + + @NotNull + private List getDefaultOrder() { Collection values = ourMap.values(); List order = new ArrayList(STANDARD_SEVERITIES.size() + values.size()); for (HighlightInfoType type : STANDARD_SEVERITIES.values()) { @@ -277,29 +334,23 @@ public class SeverityRegistrar implements JDOMExternalizable, Comparator result = new ArrayList(order.size()); - for (HighlightSeverity severity : order) { - result.add(severity.toString()); - } - return result; + return order; } - public void setOrder(List order) { - myOrder.clear(); - myOrder.addAll(order); - + public void setOrder(@NotNull List order) { + setFromList(order); myReadOrder = null; } public int getSeverityIdx(@NotNull HighlightSeverity severity) { - return getOrder().indexOf(severity.toString()); + return getOrder().get(severity); } - public boolean isDefaultSeverity(HighlightSeverity severity) { + public boolean isDefaultSeverity(@NotNull HighlightSeverity severity) { return STANDARD_SEVERITIES.containsKey(severity.myName); } - public static boolean isGotoBySeverityEnabled(HighlightSeverity minSeverity) { + public static boolean isGotoBySeverityEnabled(@NotNull HighlightSeverity minSeverity) { for (SeveritiesProvider provider : Extensions.getExtensions(SeveritiesProvider.EP_NAME)) { if (provider.isGotoBySeverityEnabled(minSeverity)) return true; } diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/SeverityEditorDialog.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/SeverityEditorDialog.java index d2542b5a7def..97e0745594d3 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/SeverityEditorDialog.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/SeverityEditorDialog.java @@ -80,6 +80,7 @@ public class SeverityEditorDialog extends DialogWrapper { super(parent, true); mySeverityRegistrar = severityRegistrar; myOptionsList.setCellRenderer(new DefaultListCellRenderer() { + @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { final Component rendererComponent = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); if (value instanceof SeverityBasedTextAttributes) { @@ -89,6 +90,7 @@ public class SeverityEditorDialog extends DialogWrapper { } }); myOptionsList.addListSelectionListener(new ListSelectionListener() { + @Override public void valueChanged(ListSelectionEvent e) { if (myCurrentSelection != null) { apply(myCurrentSelection); @@ -110,6 +112,7 @@ public class SeverityEditorDialog extends DialogWrapper { InspectionsBundle.message("highlight.severity.create.dialog.title"), Messages.getQuestionIcon(), "", new InputValidator() { + @Override public boolean checkInput(final String inputString) { final ListModel listModel = myOptionsList.getModel(); for (int i = 0; i < listModel.getSize(); i++) { @@ -119,6 +122,7 @@ public class SeverityEditorDialog extends DialogWrapper { return true; } + @Override public boolean canClose(final String inputString) { return checkInput(inputString); } @@ -201,6 +205,7 @@ public class SeverityEditorDialog extends DialogWrapper { final JPanel disabled = new JPanel(new GridBagLayout()); final JButton button = new JButton(InspectionsBundle.message("severities.default.settings.message")); button.addActionListener(new ActionListener() { + @Override public void actionPerformed(final ActionEvent e) { editColorsAndFonts(); } @@ -230,6 +235,7 @@ public class SeverityEditorDialog extends DialogWrapper { final SearchableConfigurable javaPage = colorAndFontOptions.findSubConfigurable(InspectionColorSettingsPage.class); LOG.assertTrue(javaPage != null); optionsEditor.select(javaPage).doWhenDone(new Runnable() { + @Override public void run() { final Runnable runnable = javaPage.enableSearch(toConfigure); if (runnable != null) { @@ -261,6 +267,7 @@ public class SeverityEditorDialog extends DialogWrapper { final List infoTypes = new ArrayList(); infoTypes.addAll(mySeverityRegistrar.getRegisteredHighlightingInfoTypes()); Collections.sort(infoTypes, new Comparator() { + @Override public int compare(SeverityBasedTextAttributes attributes1, SeverityBasedTextAttributes attributes2) { return -mySeverityRegistrar.compare(attributes1.getSeverity(), attributes2.getSeverity()); @@ -306,16 +313,17 @@ public class SeverityEditorDialog extends DialogWrapper { myOptionsPanel.reset(description); } + @Override protected void doOKAction() { apply((SeverityBasedTextAttributes)myOptionsList.getSelectedValue()); final Collection infoTypes = new HashSet(mySeverityRegistrar.getRegisteredHighlightingInfoTypes()); final ListModel listModel = myOptionsList.getModel(); - final List order = new ArrayList(); + final List order = new ArrayList(); for (int i = listModel.getSize() - 1; i >= 0; i--) { final SeverityBasedTextAttributes info = (SeverityBasedTextAttributes)listModel.getElementAt(i); - order.add(info.getSeverity().myName); + order.add(info.getSeverity()); if (!mySeverityRegistrar.isDefaultSeverity(info.getSeverity())) { infoTypes.remove(info); final Color stripeColor = info.getAttributes().getErrorStripeColor(); @@ -329,6 +337,7 @@ public class SeverityEditorDialog extends DialogWrapper { super.doOKAction(); } + @Override @Nullable protected JComponent createCenterPanel() { return myPanel; @@ -349,15 +358,18 @@ public class SeverityEditorDialog extends DialogWrapper { super(name, group, attributes, type, null, null, null); } + @Override public void apply(EditorColorsScheme scheme) { } + @Override public boolean isErrorStripeEnabled() { return true; } + @Override public TextAttributes getTextAttributes() { return super.getTextAttributes(); } diff --git a/platform/lang-impl/src/com/intellij/ide/actions/CopyReferenceAction.java b/platform/lang-impl/src/com/intellij/ide/actions/CopyReferenceAction.java index 72e144cffe77..9627f6444924 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/CopyReferenceAction.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/CopyReferenceAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,6 +26,7 @@ import com.intellij.ide.IdeBundle; import com.intellij.ide.dnd.FileCopyPasteUtil; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.actions.EditorActionUtil; import com.intellij.openapi.editor.colors.EditorColors; import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.markup.TextAttributes; @@ -109,7 +110,7 @@ public class CopyReferenceAction extends AnAction { private static PsiElement getElementToCopy(final Editor editor, final DataContext dataContext) { PsiElement element = null; if (editor != null) { - PsiReference reference = TargetElementUtilBase.findReference(editor, editor.getCaretModel().getOffset()); + PsiReference reference = TargetElementUtilBase.findReference(editor); if (reference != null) { element = reference.getElement(); } diff --git a/platform/lang-impl/src/com/intellij/ide/fileTemplates/FileTemplateUtil.java b/platform/lang-impl/src/com/intellij/ide/fileTemplates/FileTemplateUtil.java index 0d0ec3f10408..747312d7ee40 100644 --- a/platform/lang-impl/src/com/intellij/ide/fileTemplates/FileTemplateUtil.java +++ b/platform/lang-impl/src/com/intellij/ide/fileTemplates/FileTemplateUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +22,7 @@ import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileTypes.FileType; +import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.fileTypes.FileTypes; import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.fileTypes.ex.FileTypeManagerEx; @@ -55,6 +56,7 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.swing.*; import java.io.*; import java.util.*; @@ -351,4 +353,9 @@ public class FileTemplateUtil{ CreateFromTemplateHandler handler = findHandler(template); return handler.canCreate(dirs); } + + @Nullable + public static Icon getIcon(@NotNull FileTemplate fileTemplate) { + return FileTypeManager.getInstance().getFileTypeByExtension(fileTemplate.getExtension()).getIcon(); + } } diff --git a/platform/lang-impl/src/com/intellij/ide/fileTemplates/actions/CreateFromTemplateAction.java b/platform/lang-impl/src/com/intellij/ide/fileTemplates/actions/CreateFromTemplateAction.java index c3108ade53d3..6f02e0f73e20 100644 --- a/platform/lang-impl/src/com/intellij/ide/fileTemplates/actions/CreateFromTemplateAction.java +++ b/platform/lang-impl/src/com/intellij/ide/fileTemplates/actions/CreateFromTemplateAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,10 +17,10 @@ package com.intellij.ide.fileTemplates.actions; import com.intellij.ide.fileTemplates.FileTemplate; +import com.intellij.ide.fileTemplates.FileTemplateUtil; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.Presentation; -import com.intellij.openapi.fileTypes.ex.FileTypeManagerEx; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiDirectory; import org.jetbrains.annotations.Nullable; @@ -30,7 +30,7 @@ public class CreateFromTemplateAction extends CreateFromTemplateActionBase { private final FileTemplate myTemplate; public CreateFromTemplateAction(FileTemplate template){ - super(template.getName(), null, FileTypeManagerEx.getInstanceEx().getFileTypeByExtension(template.getExtension()).getIcon()); + super(template.getName(), null, FileTemplateUtil.getIcon(template)); myTemplate = template; } diff --git a/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FileTemplateTabAsList.java b/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FileTemplateTabAsList.java index c548fba03d92..0ba5720650ba 100644 --- a/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FileTemplateTabAsList.java +++ b/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FileTemplateTabAsList.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,7 @@ package com.intellij.ide.fileTemplates.impl; import com.intellij.ide.fileTemplates.FileTemplate; -import com.intellij.openapi.fileTypes.FileTypeManager; +import com.intellij.ide.fileTemplates.FileTemplateUtil; import com.intellij.ui.components.JBList; import org.jetbrains.annotations.NotNull; @@ -52,7 +52,7 @@ abstract class FileTemplateTabAsList extends FileTemplateTab { Icon icon = null; if (value instanceof FileTemplate) { FileTemplate template = (FileTemplate) value; - icon = FileTypeManager.getInstance().getFileTypeByExtension(template.getExtension()).getIcon(); + icon = FileTemplateUtil.getIcon(template); final boolean internalTemplate = AllFileTemplatesConfigurable.isInternalTemplate(template.getName(), getTitle()); if (internalTemplate) { setFont(getFont().deriveFont(Font.BOLD)); diff --git a/platform/lang-impl/src/com/intellij/ide/fileTemplates/ui/SelectTemplateDialog.java b/platform/lang-impl/src/com/intellij/ide/fileTemplates/ui/SelectTemplateDialog.java index 1ad5a2cf2b9a..c29e101e0216 100644 --- a/platform/lang-impl/src/com/intellij/ide/fileTemplates/ui/SelectTemplateDialog.java +++ b/platform/lang-impl/src/com/intellij/ide/fileTemplates/ui/SelectTemplateDialog.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,10 +16,11 @@ package com.intellij.ide.fileTemplates.ui; +import com.intellij.ide.IdeBundle; import com.intellij.ide.fileTemplates.FileTemplate; import com.intellij.ide.fileTemplates.FileTemplateManager; import com.intellij.ide.fileTemplates.FileTemplateUtil; -import com.intellij.ide.IdeBundle; +import com.intellij.ide.ui.ListCellRendererWrapper; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.FixedSizeButton; @@ -80,6 +81,15 @@ public class SelectTemplateDialog extends DialogWrapper{ } if(myCbxTemplates == null){ myCbxTemplates = new JComboBox(model); + myCbxTemplates.setRenderer(new ListCellRendererWrapper(myCbxTemplates.getRenderer()) { + @Override + public void customize(JList list, FileTemplate fileTemplate, int index, boolean selected, boolean hasFocus) { + if (fileTemplate != null) { + setIcon(FileTemplateUtil.getIcon(fileTemplate)); + setText(fileTemplate.getName()); + } + } + }); } else{ Object selected = myCbxTemplates.getSelectedItem(); diff --git a/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeTreeViewPanel.java b/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeTreeViewPanel.java index 3abc03715a52..e5dfd6c99b84 100644 --- a/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeTreeViewPanel.java +++ b/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeTreeViewPanel.java @@ -210,6 +210,10 @@ public class ScopeTreeViewPanel extends JPanel implements Disposable { }); } }; + doWhenDone(runnable); + } + + private void doWhenDone(Runnable runnable) { if (myActionCallback == null || ApplicationManager.getApplication().isUnitTestMode()) { runnable.run(); } @@ -646,7 +650,7 @@ public class ScopeTreeViewPanel extends JPanel implements Disposable { }, false); } else if (propertyName.equals(PsiTreeChangeEvent.PROP_DIRECTORY_NAME)) { - queueRefreshScope(scope); + queueRefreshScope(scope, (PsiDirectory)element); } } } @@ -665,7 +669,7 @@ public class ScopeTreeViewPanel extends JPanel implements Disposable { } } else if (element instanceof PsiDirectory && element.isValid()) { - queueRefreshScope(scope); + queueRefreshScope(scope, (PsiDirectory)element); } } @@ -673,11 +677,22 @@ public class ScopeTreeViewPanel extends JPanel implements Disposable { return InjectedLanguageManager.getInstance(myProject).isInjectedFragment(psiFile); } - private void queueRefreshScope(final NamedScope scope) { + private void queueRefreshScope(final NamedScope scope, final PsiDirectory dir) { myUpdateQueue.cancelAllUpdates(); queueUpdate(new Runnable() { public void run() { + myTreeExpansionMonitor.freeze(); refreshScope(scope); + doWhenDone(new Runnable() { + @Override + public void run() { + myTreeExpansionMonitor.restore(); + final PackageDependenciesNode dirNode = myBuilder.findNode(dir, dir); + if (dirNode != null) { + TreeUtil.selectPath(myTree, new TreePath(dirNode.getPath())); + } + } + }); } }, false); } diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java index 356016c1dc16..87b750510819 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java @@ -31,6 +31,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.LayeredIcon; +import com.intellij.ui.LightColors; import com.intellij.ui.components.JBLabel; import com.intellij.util.ArrayUtil; import com.intellij.util.ui.EmptyIcon; @@ -156,6 +157,9 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C label.setIcon(EMPTY_ICON); panel.add(label, BorderLayout.WEST); panel.add(new JBLabel("Settings"), BorderLayout.EAST); + if (!isSelected) { + panel.setBackground(LightColors.SLIGHTLY_GRAY); + } } else if (value instanceof String) { final JBLabel label = new JBLabel((String)value); label.setIcon(EMPTY_ICON); diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/ModuleRootManagerImpl.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/ModuleRootManagerImpl.java index de4ec3acdf7a..18f6aa3d2a02 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/ModuleRootManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/ModuleRootManagerImpl.java @@ -267,6 +267,18 @@ public class ModuleRootManagerImpl extends ModuleRootManager implements ModuleCo return myRootModel.getModuleDependencies(includeTests); } + @NotNull + @Override + public Module[] getModuleDependencies() { + return myRootModel.getModuleDependencies(); + } + + @NotNull + @Override + public Module[] getModuleDependencies(boolean includeTests) { + return myRootModel.getModuleDependencies(includeTests); + } + public boolean isDependsOn(Module module) { return myRootModel.isDependsOn(module); } diff --git a/platform/lang-impl/src/com/intellij/psi/formatter/FormatterUtil.java b/platform/lang-impl/src/com/intellij/psi/formatter/FormatterUtil.java index 6b321f41f16c..c40a94360506 100644 --- a/platform/lang-impl/src/com/intellij/psi/formatter/FormatterUtil.java +++ b/platform/lang-impl/src/com/intellij/psi/formatter/FormatterUtil.java @@ -203,11 +203,11 @@ public class FormatterUtil { if (isWhitespaceOrEmpty(node)) return true; for (WhiteSpaceFormattingStrategy strategy : WhiteSpaceFormattingStrategyFactory.getAllStrategies()) { - if (!strategy.containsWhitespacesOnly(node)) { - return false; + if (strategy.containsWhitespacesOnly(node)) { + return true; } } - return true; + return false; } public static void replaceWhiteSpace(final String whiteSpace, diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/LeafPatcher.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/LeafPatcher.java index d58e5ac4aeff..c4f5e014907f 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/LeafPatcher.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/LeafPatcher.java @@ -39,6 +39,7 @@ class LeafPatcher extends RecursiveTreeElementWalkingVisitor { private String prevElementTail; private int shredNo; private String hostText; + private TextRange rangeInHost; private final Place myShreds; private final List> myEscapers; final Map newTexts = new THashMap(); @@ -74,7 +75,11 @@ class LeafPatcher extends RecursiveTreeElementWalkingVisitor { private StringBuilder constructTextFromHostPSI(int startOffset, int endOffset) { PsiLanguageInjectionHost.Shred current = myShreds.get(shredNo); - if (hostText == null) hostText = current.getHost().getText(); + if (hostText == null) { + hostText = current.getHost().getText(); + rangeInHost = current.getRangeInsideHost(); + } + StringBuilder text = new StringBuilder(endOffset-startOffset); while (startOffset < endOffset) { TextRange shredRange = current.getRange(); @@ -82,6 +87,7 @@ class LeafPatcher extends RecursiveTreeElementWalkingVisitor { if (startOffset >= shredRange.getEndOffset()) { current = myShreds.get(++shredNo); hostText = current.getHost().getText(); + rangeInHost = current.getRangeInsideHost(); continue; } assert startOffset >= shredRange.getStartOffset(); @@ -96,9 +102,11 @@ class LeafPatcher extends RecursiveTreeElementWalkingVisitor { String suffix = current.getSuffix(); if (startOffset < shredRange.getEndOffset() - suffix.length()) { // inside host body, cut out from the host text - int startOffsetInHost = myEscapers.get(shredNo).getOffsetInHost(startOffset - shredRange.getStartOffset() - prefix.length(), current.getRangeInsideHost()); + int startOffsetInHost = myEscapers.get(shredNo).getOffsetInHost( + startOffset - shredRange.getStartOffset() - prefix.length(), rangeInHost); int endOffsetCut = Math.min(endOffset, shredRange.getEndOffset() - suffix.length()); - int endOffsetInHost = myEscapers.get(shredNo).getOffsetInHost(endOffsetCut - shredRange.getStartOffset() - prefix.length(), current.getRangeInsideHost()); + int endOffsetInHost = myEscapers.get(shredNo).getOffsetInHost( + endOffsetCut - shredRange.getStartOffset() - prefix.length(), rangeInHost); if (endOffsetInHost != -1) { text.append(hostText, startOffsetInHost, endOffsetInHost); startOffset = endOffsetCut; diff --git a/platform/lvcs-impl/src/com/intellij/history/integration/IdeaGateway.java b/platform/lvcs-impl/src/com/intellij/history/integration/IdeaGateway.java index 26c99517ea82..4b13d2a3929c 100644 --- a/platform/lvcs-impl/src/com/intellij/history/integration/IdeaGateway.java +++ b/platform/lvcs-impl/src/com/intellij/history/integration/IdeaGateway.java @@ -50,43 +50,44 @@ public class IdeaGateway { private static final Key SAVED_DOCUMENT_CONTENT_AND_STAMP_KEY = Key.create("LocalHistory.SAVED_DOCUMENT_CONTENT_AND_STAMP_KEY"); - public boolean isVersioned(VirtualFile f) { + public boolean isVersioned(@NotNull VirtualFile f) { if (!f.isInLocalFileSystem()) return false; String fileName = f.getName(); if (!f.isDirectory() && fileName.endsWith(".class")) return false; - for (Project each : ProjectManager.getInstance().getOpenProjects()) { + Project[] openProjects = ProjectManager.getInstance().getOpenProjects(); + for (Project each : openProjects) { if (each.isDefault()) continue; if (!each.isInitialized()) continue; if (each.getWorkspaceFile() == f) return false; if (ProjectRootManager.getInstance(each).getFileIndex().isIgnored(f)) return false; } - return !FileTypeManager.getInstance().isFileIgnored(f); + // optimisation: FileTypeManager.isFileIgnored(f) already checked inside ProjectFileIndex.isIgnored() + return openProjects.length != 0 || !FileTypeManager.getInstance().isFileIgnored(f); } - public boolean areContentChangesVersioned(VirtualFile f) { - if (!isVersioned(f) || f.isDirectory()) return false; - return areContentChangesVersioned(f.getName()); + public boolean areContentChangesVersioned(@NotNull VirtualFile f) { + return isVersioned(f) && !f.isDirectory() && areContentChangesVersioned(f.getName()); } - public boolean areContentChangesVersioned(String fileName) { + public boolean areContentChangesVersioned(@NotNull String fileName) { return !FileTypeManager.getInstance().getFileTypeByFileName(fileName).isBinary(); } - public boolean ensureFilesAreWritable(Project p, List ff) { + public boolean ensureFilesAreWritable(@NotNull Project p, @NotNull List ff) { ReadonlyStatusHandler h = ReadonlyStatusHandler.getInstance(p); return !h.ensureFilesWritable(VfsUtil.toVirtualFileArray(ff)).hasReadonlyFiles(); } @Nullable - public VirtualFile findVirtualFile(String path) { + public VirtualFile findVirtualFile(@NotNull String path) { return LocalFileSystem.getInstance().findFileByPath(path); } @NotNull - public VirtualFile findOrCreateFileSafely(VirtualFile parent, String name, boolean isDirectory) throws IOException { + public VirtualFile findOrCreateFileSafely(@NotNull VirtualFile parent, @NotNull String name, boolean isDirectory) throws IOException { VirtualFile f = parent.findChild(name); if (f != null && f.isDirectory() != isDirectory) { f.delete(this); @@ -101,7 +102,7 @@ public class IdeaGateway { } @NotNull - public VirtualFile findOrCreateFileSafely(String path, boolean isDirectory) throws IOException { + public VirtualFile findOrCreateFileSafely(@NotNull String path, boolean isDirectory) throws IOException { VirtualFile f = findVirtualFile(path); if (f != null && f.isDirectory() != isDirectory) { f.delete(this); @@ -117,13 +118,14 @@ public class IdeaGateway { return f; } - public List getAllFilesFrom(String path) { + public List getAllFilesFrom(@NotNull String path) { VirtualFile f = findVirtualFile(path); if (f == null) return Collections.emptyList(); return collectFiles(f, new ArrayList()); } - private List collectFiles(VirtualFile f, List result) { + @NotNull + private static List collectFiles(@NotNull VirtualFile f, @NotNull List result) { if (f.isDirectory()) { for (VirtualFile child : iterateDBChildren(f)) { collectFiles(child, result); @@ -135,12 +137,14 @@ public class IdeaGateway { return result; } + @NotNull public static Collection iterateDBChildren(VirtualFile f) { if (!(f instanceof NewVirtualFile)) return Collections.emptyList(); NewVirtualFile nf = (NewVirtualFile)f; return nf.getCachedChildren(); } + @NotNull public RootEntry createTransientRootEntry() { ApplicationManager.getApplication().assertReadAccessAllowed(); RootEntry root = new RootEntry(); @@ -149,19 +153,19 @@ public class IdeaGateway { } @Nullable - public Entry createTransientEntry(VirtualFile file) { + public Entry createTransientEntry(@NotNull VirtualFile file) { ApplicationManager.getApplication().assertReadAccessAllowed(); return doCreateEntry(file, false); } @Nullable - public Entry createEntryForDeletion(VirtualFile file) { + public Entry createEntryForDeletion(@NotNull VirtualFile file) { ApplicationManager.getApplication().assertReadAccessAllowed(); return doCreateEntry(file, true); } @Nullable - private Entry doCreateEntry(VirtualFile file, boolean forDeletion) { + private Entry doCreateEntry(@NotNull VirtualFile file, boolean forDeletion) { if (!file.isDirectory()) { if (!isVersioned(file)) return null; @@ -182,18 +186,19 @@ public class IdeaGateway { return newDir; } - private void doCreateChildren(DirectoryEntry parent, Collection children, final boolean forDeletion) { + private void doCreateChildren(@NotNull DirectoryEntry parent, Collection children, final boolean forDeletion) { List entries = ContainerUtil.mapNotNull(children, new NullableFunction() { @Override - public Entry fun(VirtualFile each) { + public Entry fun(@NotNull VirtualFile each) { return doCreateEntry(each, forDeletion); } }); parent.addChildren(entries); } - public void registerUnsavedDocuments(final LocalHistoryFacade vcs) { + public void registerUnsavedDocuments(@NotNull final LocalHistoryFacade vcs) { ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override public void run() { vcs.beginChangeSet(); for (Document d : FileDocumentManager.getInstance().getUnsavedDocuments()) { @@ -206,12 +211,11 @@ public class IdeaGateway { }); } - private boolean shouldRegisterDocument(VirtualFile f) { - if (f == null || !f.isValid()) return false; - return areContentChangesVersioned(f); + private boolean shouldRegisterDocument(@Nullable VirtualFile f) { + return f != null && f.isValid() && areContentChangesVersioned(f); } - private void registerDocumentContents(LocalHistoryFacade vcs, VirtualFile f, Document d) { + private void registerDocumentContents(@NotNull LocalHistoryFacade vcs, @NotNull VirtualFile f, Document d) { Pair contentAndStamp = acquireAndUpdateActualContent(f, d); if (contentAndStamp != null) { vcs.contentChanged(f.getPath(), contentAndStamp.first, contentAndStamp.second); @@ -220,7 +224,7 @@ public class IdeaGateway { // returns null is content has not been changes since last time @Nullable - public Pair acquireAndUpdateActualContent(VirtualFile f, @Nullable Document d) { + public Pair acquireAndUpdateActualContent(@NotNull VirtualFile f, @Nullable Document d) { ContentAndTimestamps contentAndStamp = f.getUserData(SAVED_DOCUMENT_CONTENT_AND_STAMP_KEY); if (contentAndStamp == null) { if (d != null) saveDocumentContent(f, d); @@ -241,7 +245,7 @@ public class IdeaGateway { return Pair.create(contentAndStamp.content, contentAndStamp.registeredTimestamp); } - private void saveDocumentContent(VirtualFile f, Document d) { + private static void saveDocumentContent(@NotNull VirtualFile f, @NotNull Document d) { f.putUserData(SAVED_DOCUMENT_CONTENT_AND_STAMP_KEY, new ContentAndTimestamps(Clock.getTime(), StoredContent.acquireContent(bytesFromDocument(d)), @@ -249,7 +253,7 @@ public class IdeaGateway { } @NotNull - public Pair acquireAndClearCurrentContent(VirtualFile f, @Nullable Document d) { + public Pair acquireAndClearCurrentContent(@NotNull VirtualFile f, @Nullable Document d) { ContentAndTimestamps contentAndStamp = f.getUserData(SAVED_DOCUMENT_CONTENT_AND_STAMP_KEY); f.putUserData(SAVED_DOCUMENT_CONTENT_AND_STAMP_KEY, null); @@ -274,7 +278,7 @@ public class IdeaGateway { } @NotNull - private Pair getActualContentNoAcquire(VirtualFile f) { + private static Pair getActualContentNoAcquire(@NotNull VirtualFile f) { ContentAndTimestamps result = f.getUserData(SAVED_DOCUMENT_CONTENT_AND_STAMP_KEY); if (result == null) { return Pair.create(StoredContent.transientContent(f), f.getTimeStamp()); @@ -282,7 +286,7 @@ public class IdeaGateway { return Pair.create(result.content, result.registeredTimestamp); } - private byte[] bytesFromDocument(Document d) { + private static byte[] bytesFromDocument(@NotNull Document d) { try { return d.getText().getBytes(getFile(d).getCharset().name()); } @@ -291,7 +295,7 @@ public class IdeaGateway { } } - public String stringFromBytes(byte[] bytes, String path) { + public String stringFromBytes(@NotNull byte[] bytes, @NotNull String path) { try { VirtualFile file = findVirtualFile(path); if (file == null) { @@ -308,15 +312,18 @@ public class IdeaGateway { FileDocumentManager.getInstance().saveAllDocuments(); } - private VirtualFile getFile(Document d) { + @Nullable + private static VirtualFile getFile(@NotNull Document d) { return FileDocumentManager.getInstance().getFile(d); } - public Document getDocument(String path) { + @Nullable + public Document getDocument(@NotNull String path) { return FileDocumentManager.getInstance().getDocument(findVirtualFile(path)); } - public FileType getFileType(String fileName) { + @NotNull + public FileType getFileType(@NotNull String fileName) { return FileTypeManager.getInstance().getFileTypeByFileName(fileName); } diff --git a/platform/platform-api/src/com/intellij/lang/annotation/HighlightSeverity.java b/platform/platform-api/src/com/intellij/lang/annotation/HighlightSeverity.java index e3c3026e9e8a..3553925ff9a3 100644 --- a/platform/platform-api/src/com/intellij/lang/annotation/HighlightSeverity.java +++ b/platform/platform-api/src/com/intellij/lang/annotation/HighlightSeverity.java @@ -92,14 +92,17 @@ public class HighlightSeverity implements Comparable, JDOMExt return myName; } + @Override public int compareTo(final HighlightSeverity highlightSeverity) { return myVal - highlightSeverity.myVal; } + @Override public void readExternal(Element element) throws InvalidDataException { DefaultJDOMExternalizer.readExternal(this, element); } + @Override public void writeExternal(final Element element) throws WriteExternalException { DefaultJDOMExternalizer.writeExternal(this, element); } @@ -111,9 +114,7 @@ public class HighlightSeverity implements Comparable, JDOMExt final HighlightSeverity that = (HighlightSeverity)o; - if (!myName.equals(that.myName)) return false; - - return true; + return myName.equals(that.myName); } public int hashCode() { diff --git a/platform/platform-api/src/com/intellij/openapi/editor/event/EditorMouseListener.java b/platform/platform-api/src/com/intellij/openapi/editor/event/EditorMouseListener.java index 7aa1d8f8dc78..0e0eba4c0d87 100644 --- a/platform/platform-api/src/com/intellij/openapi/editor/event/EditorMouseListener.java +++ b/platform/platform-api/src/com/intellij/openapi/editor/event/EditorMouseListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,8 +25,12 @@ import java.util.EventListener; * @see EditorMouseMotionListener */ public interface EditorMouseListener extends EventListener { + /** * Called when a mouse button is pressed over the editor. + *

+ * Note: this callback is assumed to be at the very start of 'mouse press' processing, i.e. common actions + * like 'caret position change', 'selection change' etc implied by the 'mouse press' have not been performed yet. * * @param e the event containing information about the mouse press. */ diff --git a/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/NewVirtualFile.java b/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/NewVirtualFile.java index da635f475b1a..8c1807ce7904 100644 --- a/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/NewVirtualFile.java +++ b/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/NewVirtualFile.java @@ -34,36 +34,43 @@ import java.util.Collection; public abstract class NewVirtualFile extends VirtualFile implements VirtualFileWithId { private volatile long myModificationStamp = LocalTimeCounter.currentTime(); + @Override public boolean isValid() { ApplicationManager.getApplication().assertReadAccessAllowed(); return exists(); } + @Override @NotNull public byte[] contentsToByteArray() throws IOException { throw new IOException("not applicable to the "+this); } + @Override @NotNull public abstract NewVirtualFileSystem getFileSystem(); + @Override public abstract NewVirtualFile getParent(); + @Override @Nullable public abstract NewVirtualFile getCanonicalFile(); + @Override @Nullable public abstract NewVirtualFile findChild(@NotNull @NonNls final String name); @Nullable - public abstract NewVirtualFile refreshAndFindChild(final String name); + public abstract NewVirtualFile refreshAndFindChild(@NotNull String name); @Nullable - public abstract NewVirtualFile findChildIfCached(final String name); + public abstract NewVirtualFile findChildIfCached(@NotNull String name); public abstract void setTimeStamp(final long time) throws IOException; + @Override public abstract int getId(); @Nullable @@ -72,10 +79,12 @@ public abstract class NewVirtualFile extends VirtualFile implements VirtualFileW @Nullable public abstract NewVirtualFile findChildByIdIfCached(int id); + @Override public void refresh(final boolean asynchronous, final boolean recursive, final Runnable postRunnable) { RefreshQueue.getInstance().refresh(asynchronous, recursive, postRunnable, this); } + @Override public long getModificationStamp() { return myModificationStamp; } @@ -94,6 +103,7 @@ public abstract class NewVirtualFile extends VirtualFile implements VirtualFileW public abstract void markClean(); + @Override public void move(final Object requestor, @NotNull final VirtualFile newParent) throws IOException { if (!exists()) { throw new IOException("File to move does not exist: " + getPath()); @@ -113,6 +123,7 @@ public abstract class NewVirtualFile extends VirtualFile implements VirtualFileW } EncodingRegistry.doActionAndRestoreEncoding(this, new ThrowableComputable() { + @Override public VirtualFile compute() throws IOException { getFileSystem().moveFile(requestor, NewVirtualFile.this, newParent); return NewVirtualFile.this; @@ -120,8 +131,10 @@ public abstract class NewVirtualFile extends VirtualFile implements VirtualFileW }); } + @NotNull public abstract Collection getCachedChildren(); + @NotNull /** iterated children will NOT contain NullVirtualFile.INSTANCE */ public abstract Iterable iterInDbChildren(); diff --git a/platform/platform-impl/src/com/intellij/help/impl/IdeaHelpBroker.java b/platform/platform-impl/src/com/intellij/help/impl/IdeaHelpBroker.java index a7555f94361f..5df8dd779802 100644 --- a/platform/platform-impl/src/com/intellij/help/impl/IdeaHelpBroker.java +++ b/platform/platform-impl/src/com/intellij/help/impl/IdeaHelpBroker.java @@ -15,7 +15,10 @@ */ package com.intellij.help.impl; +import com.intellij.openapi.wm.IdeFocusManager; +import com.intellij.openapi.wm.impl.IdeFocusManagerHeadless; import com.intellij.ui.AppUIUtil; +import com.intellij.util.Alarm; import org.jetbrains.annotations.NotNull; import javax.help.*; @@ -207,6 +210,9 @@ class IdeaHelpBroker extends DefaultHelpBroker implements KeyListener{ //myFrame.setLocationRelativeTo(null); myFrame.setVisible(visible); myFrame.setState(JFrame.NORMAL); + IdeFocusManager focusManager = IdeFocusManager.findInstance(); + JComponent target = focusManager.getFocusTargetFor(myFrame.getRootPane()); + focusManager.requestFocus(target != null ? target : myFrame, true); } } @@ -671,8 +677,9 @@ class IdeaHelpBroker extends DefaultHelpBroker implements KeyListener{ if(myDialog.isShowing()){ myDialog.hide(); } - if(myOwnerWindow!=null) + if (myOwnerWindow != null) { myOwnerWindow.removeWindowListener(dl); + } myOwnerWindow=null; modalDeactivated=true; } @@ -694,22 +701,24 @@ class IdeaHelpBroker extends DefaultHelpBroker implements KeyListener{ } } } else{ - if(myFrame==null){ - myFrame=new JFrame(helpTitle); + if (myFrame == null) { + myFrame = new JFrame(helpTitle); resize = true; AppUIUtil.updateFrameIcon(myFrame); - WindowListener l=new WindowAdapter(){ - public void windowClosing(WindowEvent e){ + WindowListener l = new WindowAdapter() { + public void windowClosing(WindowEvent e) { myFrame.setVisible(false); } - public void windowClosed(WindowEvent e){ + public void windowClosed(WindowEvent e) { myFrame.setVisible(false); } }; myFrame.addWindowListener(l); - } else + } + else { pos = myFrame.getLocation(); + } if(myDialog!=null){ pos=myDialog.getLocation(); size=myDialog.getSize(); diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java index d8574f77d5eb..5a516066e7b7 100644 --- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java +++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java @@ -25,7 +25,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.SystemInfo; -import com.intellij.util.ui.UIUtil; +import com.intellij.util.WaitForProgressToShow; import java.io.UnsupportedEncodingException; import java.util.HashMap; @@ -182,7 +182,7 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider { } if (key.get() == null) { final Ref ex = new Ref(); - UIUtil.invokeAndWaitIfNeeded(new Runnable() { + WaitForProgressToShow.runOrInvokeAndWaitAboveProgress(new Runnable() { public void run() { if (key.get() == null) { try { diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterPasswordDialog.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterPasswordDialog.java index ce19098caa15..c93a98dfa242 100644 --- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterPasswordDialog.java +++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterPasswordDialog.java @@ -104,6 +104,11 @@ public class MasterPasswordDialog extends DialogWrapper { * @throws PasswordSafeException if the master password is not provided. */ public static void askPassword(Project project, MasterKeyPasswordSafe safe) throws PasswordSafeException { + // trying empty password: people who have set up empty password, don't want to get disturbed by the prompt. + if (safe.setMasterPassword("")) { + return; + } + String error = null; retries: for (int count = 0; count < NUMBER_OF_RETRIES; count++) { diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/ActionInstallPlugin.java b/platform/platform-impl/src/com/intellij/ide/plugins/ActionInstallPlugin.java index 5bcda3846d13..f1399ec5e82b 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/ActionInstallPlugin.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/ActionInstallPlugin.java @@ -103,10 +103,13 @@ public class ActionInstallPlugin extends AnAction implements DumbAware { pluginNode = (PluginNode)descr; } else if (descr instanceof IdeaPluginDescriptorImpl) { - pluginNode = new PluginNode(descr.getPluginId()); + final PluginId pluginId = descr.getPluginId(); + pluginNode = new PluginNode(pluginId); pluginNode.setName(descr.getName()); pluginNode.setDepends(Arrays.asList(descr.getDependentPluginIds()), descr.getOptionalDependentPluginIds()); pluginNode.setSize("-1"); + pluginNode.setRepositoryName(((InstalledPluginsTableModel)host.getPluginsModel()) + .getPluginHostUrl(pluginId.getIdString())); } if (pluginNode != null) { @@ -119,7 +122,6 @@ public class ActionInstallPlugin extends AnAction implements DumbAware { @Override public void run() { installedPluginsToModel(list); - installed.setRequireShutdown(true); if (!installed.isDisposed()) { getPluginTable().updateUI(); final InstalledPluginsTableModel pluginsModel = (InstalledPluginsTableModel)installed.getPluginsModel(); @@ -140,10 +142,23 @@ public class ActionInstallPlugin extends AnAction implements DumbAware { } } } - suggestToEnableInstalledPlugins(pluginsModel, disabled, disabledDependants, list); + if (suggestToEnableInstalledPlugins(pluginsModel, disabled, disabledDependants, list)) { + installed.setRequireShutdown(true); + } } else { - notifyPluginsWereInstalled(); + boolean needToRestart = false; + for (PluginNode node : list) { + final IdeaPluginDescriptor pluginDescriptor = PluginManager.getPlugin(node.getPluginId()); + if (pluginDescriptor == null || pluginDescriptor.isEnabled()) { + needToRestart = true; + break; + } + } + + if (needToRestart) { + notifyPluginsWereInstalled(); + } } } }; @@ -162,7 +177,7 @@ public class ActionInstallPlugin extends AnAction implements DumbAware { } } - private static void suggestToEnableInstalledPlugins(final InstalledPluginsTableModel pluginsModel, + private static boolean suggestToEnableInstalledPlugins(final InstalledPluginsTableModel pluginsModel, final Set disabled, final Set disabledDependants, final ArrayList list) { @@ -201,6 +216,7 @@ public class ActionInstallPlugin extends AnAction implements DumbAware { Messages.showYesNoCancelDialog(message + "", CommonBundle.getWarningTitle(), "Enable all", "Enable updated plugin" + (disabled.size() > 1 ? "s" : ""), CommonBundle.getCancelButtonText(), Messages.getQuestionIcon()); + if (result == DialogWrapper.NEXT_USER_EXIT_CODE) return false; } else { message += "
Would you like to enable "; if (!disabled.isEmpty()) { @@ -211,6 +227,7 @@ public class ActionInstallPlugin extends AnAction implements DumbAware { } message += "?"; result = Messages.showOkCancelDialog(message, CommonBundle.getWarningTitle(), Messages.getQuestionIcon()); + if (result == DialogWrapper.CANCEL_EXIT_CODE) return false; } if (result == DialogWrapper.OK_EXIT_CODE) { @@ -220,6 +237,7 @@ public class ActionInstallPlugin extends AnAction implements DumbAware { pluginsModel.enableRows(disabled.toArray(new IdeaPluginDescriptor[disabled.size()]), true); } } + return true; } private void installedPluginsToModel(ArrayList list) { diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsTableModel.java b/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsTableModel.java index 58c70ea71f84..3a9a4121ea82 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsTableModel.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsTableModel.java @@ -103,6 +103,10 @@ public class InstalledPluginsTableModel extends PluginTableModel { } } + public String getPluginHostUrl(String idString) { + return myPlugin2host.get(idString); + } + public static int getCheckboxColumn() { return 0; } diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java index 29bd4cc0e189..08cc5c2d995f 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java @@ -24,6 +24,8 @@ import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.updateSettings.impl.PluginDownloader; +import com.intellij.openapi.updateSettings.impl.UpdateChecker; +import com.intellij.openapi.util.Comparing; import com.intellij.ui.GuiUtils; import com.intellij.util.ArrayUtil; @@ -156,7 +158,28 @@ public class PluginInstaller { } synchronized (PluginManager.lock) { - final PluginDownloader downloader = PluginDownloader.createDownloader(pluginNode); + PluginDownloader downloader = null; + final String repositoryName = pluginNode.getRepositoryName(); + if (repositoryName != null) { + try { + final ArrayList downloaders = new ArrayList(); + if (!UpdateChecker.checkPluginsHost(repositoryName, downloaders)) { + return false; + } + for (PluginDownloader pluginDownloader : downloaders) { + if (Comparing.strEqual(pluginDownloader.getPluginId(), pluginNode.getPluginId().getIdString())) { + downloader = pluginDownloader; + break; + } + } + if (downloader == null) return false; + } + catch (Exception e) { + return false; + } + } else { + downloader = PluginDownloader.createDownloader(pluginNode); + } if (downloader.prepareToInstall(ProgressManager.getInstance().getProgressIndicator())) { downloader.install(); pluginNode.setStatus(PluginNode.STATUS_DOWNLOADED); diff --git a/platform/platform-impl/src/com/intellij/notification/impl/actions/NotificationTestAction.java b/platform/platform-impl/src/com/intellij/notification/impl/actions/NotificationTestAction.java index a1e9e584c843..a8a6054a8898 100644 --- a/platform/platform-impl/src/com/intellij/notification/impl/actions/NotificationTestAction.java +++ b/platform/platform-impl/src/com/intellij/notification/impl/actions/NotificationTestAction.java @@ -64,6 +64,13 @@ public class NotificationTestAction extends AnAction implements DumbAware { "You can
close this very

very very very long notification by clicking this link. Long long long long. It should be long. Very long. Too long. And even longer.", type, listener); - messageBus.syncPublisher(Notifications.TOPIC).notify(notification); + ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { + @Override + public void run() { + //DebugUtil.sleep(1000); + messageBus.syncPublisher(Notifications.TOPIC).notify(notification); + } + }); + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultProjectStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultProjectStoreImpl.java index 7c807f5ffed9..587d9e5b8f89 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultProjectStoreImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultProjectStoreImpl.java @@ -71,15 +71,18 @@ public class DefaultProjectStoreImpl extends ProjectStoreImpl { final XmlElementStorage storage = new XmlElementStorage(pathMacroManager.createTrackingSubstitutor(), componentManager, ROOT_TAG_NAME, StreamProvider.DEFAULT, "", ComponentRoamingManager.getInstance(), ComponentVersionProvider.EMPTY) { + @Override @Nullable protected Document loadDocument() throws StateStorageException { return document; } + @Override protected MySaveSession createSaveSession(final MyExternalizationSession externalizationSession) { return new DefaultSaveSession(externalizationSession); } + @Override @NotNull protected StorageData createStorageData() { return new BaseStorageData(ROOT_TAG_NAME); @@ -90,14 +93,17 @@ public class DefaultProjectStoreImpl extends ProjectStoreImpl { super(externalizationSession); } + @Override protected void doSave() throws StateStorageException { myProjectManager.setDefaultProjectRootElement(getDocumentToSave().getRootElement()); } + @Override public Collection getStorageFilesToSave() throws StateStorageException { return Collections.emptyList(); } + @Override public List getAllStorageFiles() { return Collections.emptyList(); } @@ -105,75 +111,92 @@ public class DefaultProjectStoreImpl extends ProjectStoreImpl { }; return new StateStorageManager() { + @Override public void addMacro(String macro, String expansion) { throw new UnsupportedOperationException("Method addMacro not implemented in " + getClass()); } + @Override @Nullable public TrackingPathMacroSubstitutor getMacroSubstitutor() { return null; } + @Override @Nullable public StateStorage getStateStorage(@NotNull Storage storageSpec) throws StateStorageException { return storage; } + @Override @Nullable public StateStorage getFileStateStorage(String fileName) { return storage; } + @Override public void clearStateStorage(@NotNull String file) { } + @Override public ExternalizationSession startExternalization() { return new MyExternalizationSession(storage); } + @Override public SaveSession startSave(final ExternalizationSession externalizationSession) { return new MySaveSession(storage, externalizationSession); } + @Override public void finishSave(SaveSession saveSession) { storage.finishSave(((MySaveSession)saveSession).saveSession); } + @Override public String expandMacroses(final String file) { throw new UnsupportedOperationException("Method expandMacroses not implemented in " + getClass()); } + @Override @Nullable public StateStorage getOldStorage(Object component, final String componentName, final StateStorageOperation operation) throws StateStorageException { return storage; } + @Override public void registerStreamProvider(final StreamProvider streamProvider, final RoamingType type) { throw new UnsupportedOperationException("Method registerStreamProvider not implemented in " + getClass()); } + @Override public void unregisterStreamProvider(final StreamProvider streamProvider, final RoamingType roamingType) { throw new UnsupportedOperationException("Method unregisterStreamProvider not implemented in " + getClass()); } + @Override public StreamProvider[] getStreamProviders(final RoamingType roamingType) { throw new UnsupportedOperationException("Method getStreamProviders not implemented in " + getClass()); } + @Override public Collection getStorageFileNames() { throw new UnsupportedOperationException("Method getStorageFileNames not implemented in " + getClass()); } + @Override public void reset() { } }; } + @Override public String getLocation() { throw new UnsupportedOperationException("Method getLocation not implemented in " + getClass()); } + @Override public void load() throws IOException, StateStorageException { if (myElement == null) return; super.load(); @@ -186,11 +209,13 @@ public class DefaultProjectStoreImpl extends ProjectStoreImpl { externalizationSession = storage.startExternalization(); } + @Override public void setState(@NotNull final Storage[] storageSpecs, final Object component, final String componentName, final Object state) throws StateStorageException { externalizationSession.setState(component, componentName, state, null); } + @Override public void setStateInOldStorage(final Object component, final String componentName, final Object state) throws StateStorageException { externalizationSession.setState(component, componentName, state, null); } @@ -204,19 +229,23 @@ public class DefaultProjectStoreImpl extends ProjectStoreImpl { } //returns set of component which were changed, null if changes are much more than just component state. + @Override @Nullable public Set analyzeExternalChanges(Set> files) { throw new UnsupportedOperationException("Method analyzeExternalChanges not implemented in " + getClass()); } + @Override public List getAllStorageFilesToSave() throws StateStorageException { return Collections.emptyList(); } + @Override public List getAllStorageFiles() { return Collections.emptyList(); } + @Override public void save() throws StateStorageException { saveSession.save(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/FileBasedStorage.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/FileBasedStorage.java index 356244d76a30..e0493ce493cc 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/FileBasedStorage.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/FileBasedStorage.java @@ -28,17 +28,16 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.options.StreamProvider; import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.LocalFileSystem; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.vfs.VirtualFileAdapter; -import com.intellij.openapi.vfs.VirtualFileEvent; +import com.intellij.openapi.vfs.*; import com.intellij.openapi.vfs.newvfs.NewVirtualFile; import com.intellij.openapi.vfs.tracker.VirtualFileTracker; +import com.intellij.util.io.fs.FileSystem; import com.intellij.util.io.fs.IFile; import com.intellij.util.messages.MessageBus; import org.jdom.Document; import org.jdom.Element; import org.jdom.JDOMException; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.picocontainer.PicoContainer; @@ -50,8 +49,6 @@ import java.util.Collection; import java.util.Collections; import java.util.List; -import static com.intellij.util.io.fs.FileSystem.FILE_SYSTEM; - public class FileBasedStorage extends XmlElementStorage { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.components.impl.stores.FileBasedStorage"); @@ -60,6 +57,7 @@ public class FileBasedStorage extends XmlElementStorage { protected final String myRootElementName; private static boolean myConfigDirectoryRefreshed = false; + private volatile VirtualFile myCachedVirtualFile; public FileBasedStorage(@Nullable TrackingPathMacroSubstitutor pathMacroManager, StreamProvider streamProvider, @@ -84,7 +82,7 @@ public class FileBasedStorage extends XmlElementStorage { myRootElementName = rootElementName; myFilePath = filePath; - myFile = FILE_SYSTEM.createFile(myFilePath); + myFile = FileSystem.FILE_SYSTEM.createFile(myFilePath); VirtualFileTracker virtualFileTracker = (VirtualFileTracker)picoContainer.getComponentInstanceOfType(VirtualFileTracker.class); MessageBus messageBus = (MessageBus)picoContainer.getComponentInstanceOfType(MessageBus.class); @@ -96,8 +94,21 @@ public class FileBasedStorage extends XmlElementStorage { final Listener listener = messageBus.syncPublisher(STORAGE_TOPIC); virtualFileTracker.addTracker(fileUrl, new VirtualFileAdapter() { + @Override + public void fileMoved(VirtualFileMoveEvent event) { + myCachedVirtualFile = null; + } + + @Override + public void fileDeleted(VirtualFileEvent event) { + myCachedVirtualFile = null; + } + + @Override public void contentsChanged(final VirtualFileEvent event) { - if (!isDisposed()) listener.storageFileChanged(event, FileBasedStorage.this); + if (!isDisposed()) { + listener.storageFileChanged(event, FileBasedStorage.this); + } } }, false, this); } @@ -125,6 +136,7 @@ public class FileBasedStorage extends XmlElementStorage { } } + @Override protected MySaveSession createSaveSession(final MyExternalizationSession externalizationSession) { return new FileSaveSession(externalizationSession); } @@ -135,7 +147,7 @@ public class FileBasedStorage extends XmlElementStorage { } - protected class FileSaveSession extends MySaveSession { + private class FileSaveSession extends MySaveSession { protected FileSaveSession(MyExternalizationSession externalizationSession) { super(externalizationSession); } @@ -156,16 +168,19 @@ public class FileBasedStorage extends XmlElementStorage { return hash; } + @Override protected void doSave() throws StateStorageException { - if (!myBlockSavingTheContent) { - if (ApplicationManager.getApplication().isUnitTestMode() && myFile != null && StringUtil.startsWithChar(myFile.getPath(), '$')) { - throw new StateStorageException("It seems like some macros were not expanded for path: " + myFile.getPath()); - } - - StorageUtil.save(myFile, getDocumentToSave(), this); + if (myBlockSavingTheContent) { + return; } + if (ApplicationManager.getApplication().isUnitTestMode() && myFile != null && StringUtil.startsWithChar(myFile.getPath(), '$')) { + throw new StateStorageException("It seems like some macros were not expanded for path: " + myFile.getPath()); + } + + myCachedVirtualFile = StorageUtil.save(myFile, getDocumentToSave(), this); } + @Override public Collection getStorageFilesToSave() throws StateStorageException { boolean needsSave = needsSave(); if (needsSave) { @@ -179,18 +194,21 @@ public class FileBasedStorage extends XmlElementStorage { } } + @Override public List getAllStorageFiles() { return Collections.singletonList(myFile); } } + @Override protected void loadState(final StorageData result, final Element element) throws StateStorageException { ((FileStorageData)result).myFileName = myFile.getAbsolutePath(); ((FileStorageData)result).myFilePath = myFile.getAbsolutePath(); super.loadState(result, element); } + @Override @NotNull protected StorageData createStorageData() { return new FileStorageData(myRootElementName); @@ -210,10 +228,12 @@ public class FileBasedStorage extends XmlElementStorage { myFilePath = storageData.myFilePath; } + @Override public StorageData clone() { return new FileStorageData(this); } + @NonNls public String toString() { return "FileStorageData[" + myFileName + "]"; } @@ -221,13 +241,18 @@ public class FileBasedStorage extends XmlElementStorage { @Nullable public VirtualFile getVirtualFile() { - return StorageUtil.getVirtualFile(myFile); + VirtualFile virtualFile = myCachedVirtualFile; + if (virtualFile == null) { + myCachedVirtualFile = virtualFile = StorageUtil.getVirtualFile(myFile); + } + return virtualFile; } public File getFile() { return new File(myFile.getPath()); } + @Override @Nullable protected Document loadDocument() throws StateStorageException { myBlockSavingTheContent = false; @@ -289,14 +314,14 @@ public class FileBasedStorage extends XmlElementStorage { return myFilePath; } + @Override public void setDefaultState(final Element element) { element.setName(myRootElementName); super.setDefaultState(element); } protected boolean physicalContentNeedsSave(final Document doc) { - if (!myFile.exists()) return true; - return !StorageUtil.contentEquals(doc, myFile); + return !myFile.exists() || !StorageUtil.contentEquals(doc, myFile); } @Nullable @@ -307,7 +332,6 @@ public class FileBasedStorage extends XmlElementStorage { File file = new File(myFile.getAbsolutePath()); JDOMUtil.writeDocument(document, file, "\n"); return file; - } return null; diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StorageUtil.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StorageUtil.java index b6624845f61f..6db45036ca44 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StorageUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StorageUtil.java @@ -90,7 +90,8 @@ public class StorageUtil { } } - static void save(final IFile file, final Parent element, final Object requestor) throws StateStorageException { + static VirtualFile save(final IFile file, final Parent element, final Object requestor) throws StateStorageException { + final VirtualFile[] result = new VirtualFile[1]; final String filePath = file.getCanonicalPath(); try { final Ref refIOException = Ref.create(null); @@ -98,7 +99,7 @@ public class StorageUtil { final Pair pair = loadFile(file); final byte[] text = JDOMUtil.writeParent(element, pair.second).getBytes(CharsetToolkit.UTF8); if (file.exists()) { - if (new String(text).equals(pair.first)) return; + if (new String(text).equals(pair.first)) return null; IFile backupFile = deleteBackup(filePath); file.renameTo(backupFile); } @@ -114,6 +115,7 @@ public class StorageUtil { final VirtualFile virtualFile = getOrCreateVirtualFile(requestor, file); virtualFile.setBinaryContent(text, -1, -1, requestor); + result[0] = virtualFile; } catch (IOException e) { refIOException.set(e); @@ -129,6 +131,7 @@ public class StorageUtil { catch (IOException e) { throw new StateStorageException(e); } + return result[0]; } static IFile deleteBackup(final String path) { diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/XmlElementStorage.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/XmlElementStorage.java index b439c3e212dc..64d4a01d6682 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/XmlElementStorage.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/XmlElementStorage.java @@ -72,6 +72,7 @@ public abstract class XmlElementStorage implements StateStorage, Disposable { protected Map myProviderVersions = null; protected ComponentVersionListener myListener = new ComponentVersionListener(){ + @Override public void componentStateChanged(String componentName) { myLocalVersionProvider.changeVersion(componentName, System.currentTimeMillis()); } @@ -97,6 +98,7 @@ public abstract class XmlElementStorage implements StateStorage, Disposable { myLocalVersionProvider = localComponentVersionsProvider; myRemoteVersionProvider = new ComponentVersionProvider(){ + @Override public long getVersion(String name) { if (myProviderVersions == null) { loadProviderVersions(); @@ -106,6 +108,7 @@ public abstract class XmlElementStorage implements StateStorage, Disposable { } + @Override public void changeVersion(String name, long version) { if (myProviderVersions == null) { loadProviderVersions(); @@ -138,11 +141,13 @@ public abstract class XmlElementStorage implements StateStorage, Disposable { return state; } + @Override public boolean hasState(final Object component, final String componentName, final Class aClass, final boolean reloadData) throws StateStorageException { final StorageData storageData = getStorageData(reloadData); return storageData.hasState(componentName); } + @Override @Nullable public T getState(final Object component, final String componentName, Class stateClass, @Nullable T mergeInto) throws StateStorageException { final Element element = getState(componentName); @@ -229,6 +234,7 @@ public abstract class XmlElementStorage implements StateStorage, Disposable { } } + @Override @NotNull public ExternalizationSession startExternalization() { try { @@ -242,6 +248,7 @@ public abstract class XmlElementStorage implements StateStorage, Disposable { } } + @Override @NotNull public SaveSession startSave(final ExternalizationSession externalizationSession) { assert mySession == externalizationSession; @@ -253,18 +260,22 @@ public abstract class XmlElementStorage implements StateStorage, Disposable { private SaveSession createNullSession() { return new SaveSession(){ + @Override public void save() throws StateStorageException { } + @Override public Set analyzeExternalChanges(final Set> changedFiles) { return Collections.emptySet(); } + @Override public Collection getStorageFilesToSave() throws StateStorageException { return Collections.emptySet(); } + @Override public List getAllStorageFiles() { return Collections.emptyList(); } @@ -273,6 +284,7 @@ public abstract class XmlElementStorage implements StateStorage, Disposable { protected abstract MySaveSession createSaveSession(final MyExternalizationSession externalizationSession); + @Override public void finishSave(final SaveSession saveSession) { try { LOG.assertTrue(mySession == saveSession, "mySession=" + mySession + " saveSession=" + saveSession); @@ -294,6 +306,7 @@ public abstract class XmlElementStorage implements StateStorage, Disposable { myListener = listener; } + @Override public void setState(final Object component, final String componentName, final Object state, final Storage storageSpec) throws StateStorageException { assert mySession == this; @@ -401,6 +414,7 @@ public abstract class XmlElementStorage implements StateStorage, Disposable { return null; } + @Override public final void save() throws StateStorageException { assert mySession == this; @@ -483,6 +497,7 @@ public abstract class XmlElementStorage implements StateStorage, Disposable { return myStorageData; } + @Override @Nullable public Set analyzeExternalChanges(final Set> changedFiles) { try { @@ -532,6 +547,7 @@ public abstract class XmlElementStorage implements StateStorage, Disposable { return result; } + @Override public void dispose() { myDisposed = true; } @@ -647,6 +663,7 @@ public abstract class XmlElementStorage implements StateStorage, Disposable { clearHash(); } + @Override public StorageData clone() { return new StorageData(this); } @@ -724,6 +741,7 @@ public abstract class XmlElementStorage implements StateStorage, Disposable { myLoadedData = null; } + @Override public void reload(@NotNull final Set changedComponents) throws StateStorageException { final StorageData storageData = loadData(false, myListener); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/EditorActionUtil.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/EditorActionUtil.java index 04582bc98034..7371f18b4a69 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/EditorActionUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/EditorActionUtil.java @@ -33,6 +33,7 @@ import com.intellij.openapi.actionSystem.ActionPopupMenu; import com.intellij.openapi.editor.*; import com.intellij.openapi.editor.event.EditorMouseEvent; import com.intellij.openapi.editor.event.EditorMouseEventArea; +import com.intellij.openapi.editor.event.EditorMouseListener; import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.editor.ex.util.EditorUtil; import com.intellij.openapi.editor.impl.EditorImpl; @@ -49,6 +50,21 @@ import java.awt.event.MouseEvent; import java.util.List; public class EditorActionUtil { + + /** + * Editor actions may be invoked multiple ways - programmatically, via keyboard/mouse shortcut, main/context menu etc. + * Action processing may also interfere with standard editor behavior (caret position change, selection change etc). + *

+ * E.g. consider a situation when context menu is shown on right mouse click - + * {@link EditorMouseListener#mousePressed(EditorMouseEvent) the contract says} that no common actions have been performed yet. + * However, some actions may operate on an 'active element' (an element under caret), hence, they would incorrectly because the + * caret position has not been changed yet. + *

+ * We address that problem by providing a special key that is intended to hold 'expected caret offset', i.e. offset where we + * expect the caret to be located at the near future. + */ + public static final Key EXPECTED_CARET_OFFSET = Key.create("expectedEditorOffset"); + protected static final Object EDIT_COMMAND_GROUP = Key.create("EditGroup"); public static final Object DELETE_COMMAND_GROUP = Key.create("DeleteGroup"); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index b44e8d539581..9179a8ce4f7d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -41,6 +41,7 @@ import com.intellij.openapi.command.UndoConfirmationPolicy; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.*; import com.intellij.openapi.editor.actionSystem.*; +import com.intellij.openapi.editor.actions.EditorActionUtil; import com.intellij.openapi.editor.colors.*; import com.intellij.openapi.editor.colors.impl.DelegateColorScheme; import com.intellij.openapi.editor.event.*; @@ -5078,6 +5079,10 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi TooltipController.getInstance().cancelTooltip(FOLDING_TOOLTIP_GROUP, e, true); } private void runMousePressedCommand(@NotNull final MouseEvent e) { + + final int clickOffset = logicalPositionToOffset(xyToLogicalPosition(e.getPoint())); + putUserData(EditorActionUtil.EXPECTED_CARET_OFFSET, clickOffset); + mySelectionTweaked = false; myMousePressedEvent = e; EditorMouseEvent event = new EditorMouseEvent(EditorImpl.this, e, getMouseEventArea(e)); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java index 6e7232d25313..cb0947dbdcf6 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java @@ -629,7 +629,7 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi int[] starts = getBlockSelectionStarts(); int[] ends = getBlockSelectionEnds(); int width = Math.abs(myBlockEnd.column - myBlockStart.column); - final StringBuffer buf = new StringBuffer(); + final StringBuilder buf = new StringBuilder(); for (int i = 0; i < starts.length; i++) { if (i > 0) buf.append('\n'); final int len = ends[i] - starts[i]; @@ -644,7 +644,7 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi return text.subSequence(selectionStart, selectionEnd).toString(); } - private static void appendCharSequence(@NotNull StringBuffer buf, @NotNull CharSequence s, int srcOffset, int len) { + private static void appendCharSequence(@NotNull StringBuilder buf, @NotNull CharSequence s, int srcOffset, int len) { if (srcOffset < 0 || len < 0 || srcOffset > s.length() - len) { throw new IndexOutOfBoundsException("srcOffset " + srcOffset + ", len " + len + ", s.length() " + s.length()); } diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java index 1682512f118e..f0813ecb738b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java @@ -47,7 +47,7 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{ private static volatile int ourLockedCheckCounter = 0; @NonNls private static final String NAME = "Progress Cancel Checker"; - private static final boolean DISABLED = Comparing.equal(System.getProperty(PROCESS_CANCELED_EXCEPTION), "disabled"); + private static final boolean DISABLED = "disabled".equals(System.getProperty(PROCESS_CANCELED_EXCEPTION)); private volatile boolean enabled = true; diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarFileSystemImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarFileSystemImpl.java index c7b85297e3f1..3ee71c67efc1 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarFileSystemImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarFileSystemImpl.java @@ -29,6 +29,7 @@ import com.intellij.openapi.vfs.newvfs.*; import com.intellij.openapi.vfs.newvfs.events.VFileEvent; import com.intellij.util.containers.ConcurrentHashSet; import com.intellij.util.messages.MessageBus; +import com.intellij.util.text.CaseInsensitiveStringHashingStrategy; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -41,7 +42,10 @@ import java.util.*; import java.util.zip.ZipFile; public class JarFileSystemImpl extends JarFileSystem implements ApplicationComponent { - private final Set myNoCopyJarPaths = new ConcurrentHashSet(); + private final Set myNoCopyJarPaths = SystemInfo.isFileSystemCaseSensitive ? + new ConcurrentHashSet() : + new ConcurrentHashSet(CaseInsensitiveStringHashingStrategy.INSTANCE); + @NonNls private static final String IDEA_JARS_NOCOPY = "idea.jars.nocopy"; private File myNoCopyJarDir; @@ -149,9 +153,6 @@ public class JarFileSystemImpl extends JarFileSystem implements ApplicationCompo if (index < 0) return; String path = pathInJar.substring(0, index); path = path.replace('/', File.separatorChar); - if (!SystemInfo.isFileSystemCaseSensitive) { - path = path.toLowerCase(); - } myNoCopyJarPaths.add(path); } @@ -268,12 +269,7 @@ public class JarFileSystemImpl extends JarFileSystem implements ApplicationCompo String property = System.getProperty(IDEA_JARS_NOCOPY); if (Boolean.TRUE.toString().equalsIgnoreCase(property)) return false; - String path = originalJar.getPath(); - if (!SystemInfo.isFileSystemCaseSensitive) { - path = path.toLowerCase(); - } - - if (myNoCopyJarPaths.contains(path)) return false; + if (myNoCopyJarPaths.contains(originalJar.getPath())) return false; if (myNoCopyJarDir!=null && FileUtil.isAncestor(myNoCopyJarDir, originalJar, false)) return false; return true; diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualFileImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualFileImpl.java index 326902eab68d..74ead49b63c6 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualFileImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualFileImpl.java @@ -45,11 +45,13 @@ public class VirtualFileImpl extends VirtualFileSystemEntry { return null; } + @NotNull @Override public Collection getCachedChildren() { return Collections.emptyList(); } + @NotNull @Override public Iterable iterInDbChildren() { return ContainerUtil.emptyIterable(); @@ -65,13 +67,13 @@ public class VirtualFileImpl extends VirtualFileSystemEntry { @Override @Nullable - public NewVirtualFile refreshAndFindChild(final String name) { + public NewVirtualFile refreshAndFindChild(@NotNull final String name) { return null; } @Override @Nullable - public NewVirtualFile findChildIfCached(final String name) { + public NewVirtualFile findChildIfCached(@NotNull final String name) { return null; } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeGlassPaneImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeGlassPaneImpl.java index 407129c27df1..6ae6c1041c14 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeGlassPaneImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeGlassPaneImpl.java @@ -131,7 +131,7 @@ public class IdeGlassPaneImpl extends JPanel implements IdeGlassPaneEx, IdeEvent } int button1 = MouseEvent.BUTTON1_MASK | MouseEvent.BUTTON1_DOWN_MASK; final boolean pureMouse1Event = (me.getModifiersEx() | button1) == button1; - if (pureMouse1Event && me.getClickCount() == 1 && !me.isPopupTrigger()) { + if (pureMouse1Event && me.getClickCount() <= 1 && !me.isPopupTrigger()) { final Point point = SwingUtilities.convertPoint(meComponent, me.getPoint(), myRootPane.getContentPane()); if (myRootPane.getMenuBar() != null && myRootPane.getMenuBar().isVisible()) { 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 8f3336f59026..018f663200d2 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 @@ -1333,7 +1333,14 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements FrameStateManager.getInstance().getApplicationActive().doWhenDone(new Runnable() { @Override public void run() { - ((BalloonImpl)balloon).setHideOnClickOutside(true); + final Alarm alarm = new Alarm(); + alarm.addRequest(new Runnable() { + @Override + public void run() { + ((BalloonImpl)balloon).setHideOnClickOutside(true); + Disposer.dispose(alarm); + } + }, 100); } }); listenerWrapper.myBalloon = balloon; diff --git a/platform/platform-resources-en/src/messages/ApplicationBundle.properties b/platform/platform-resources-en/src/messages/ApplicationBundle.properties index 1783df737381..0d597d8fdfa0 100644 --- a/platform/platform-resources-en/src/messages/ApplicationBundle.properties +++ b/platform/platform-resources-en/src/messages/ApplicationBundle.properties @@ -338,7 +338,7 @@ checkbox.mark.modified.tabs.with.asterisk=Mark modified tabs with asterisk group.code.folding=Code Folding checkbox.collapse.xml.tags=XML tags checkbox.collapse.anonymous.classes=Anonymous classes -checkbox.collapse.closures=Closures +checkbox.collapse.closures="Closures" (anonymous classes implementing one method) checkbox.collapse.generic.constructor.parameters=Generic constructor and method parameters checkbox.collapse.i18n.messages=I18n Strings checkbox.collapse.annotations=Annotations diff --git a/platform/platform-tests/testSrc/com/intellij/history/integration/revertion/SelectionReverterTest.java b/platform/platform-tests/testSrc/com/intellij/history/integration/revertion/SelectionReverterTest.java index 3ed82848a13b..7cff8dfa5e49 100644 --- a/platform/platform-tests/testSrc/com/intellij/history/integration/revertion/SelectionReverterTest.java +++ b/platform/platform-tests/testSrc/com/intellij/history/integration/revertion/SelectionReverterTest.java @@ -25,6 +25,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Clock; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.text.DateFormatUtil; +import org.jetbrains.annotations.NotNull; import java.io.IOException; import java.util.ArrayList; @@ -91,7 +92,7 @@ public class SelectionReverterTest extends IntegrationTestCase { final List files = new ArrayList(); myGateway = new IdeaGateway() { @Override - public boolean ensureFilesAreWritable(Project p, List ff) { + public boolean ensureFilesAreWritable(@NotNull Project p, @NotNull List ff) { files.addAll(ff); return true; } diff --git a/platform/platform-tests/testSrc/com/intellij/history/integration/ui/models/SelectionCalculatorTest.java b/platform/platform-tests/testSrc/com/intellij/history/integration/ui/models/SelectionCalculatorTest.java index b87a187f54c4..c56c80608df2 100644 --- a/platform/platform-tests/testSrc/com/intellij/history/integration/ui/models/SelectionCalculatorTest.java +++ b/platform/platform-tests/testSrc/com/intellij/history/integration/ui/models/SelectionCalculatorTest.java @@ -24,6 +24,7 @@ import com.intellij.history.core.revisions.Revision; import com.intellij.history.core.tree.RootEntry; import com.intellij.history.integration.IdeaGateway; import com.intellij.util.diff.FilesTooBigForDiffException; +import org.jetbrains.annotations.NotNull; import org.junit.Test; import java.util.List; @@ -133,7 +134,7 @@ public class SelectionCalculatorTest extends LocalHistoryTestCase { private static class MyIdeaGateway extends IdeaGateway { @Override - public String stringFromBytes(byte[] bytes, String path) { + public String stringFromBytes(@NotNull byte[] bytes, @NotNull String path) { return new String(bytes); } } diff --git a/platform/platform-tests/testSrc/com/intellij/psi/util/NameUtilTest.java b/platform/platform-tests/testSrc/com/intellij/psi/util/NameUtilTest.java index 1a27747841da..184e051fe81e 100644 --- a/platform/platform-tests/testSrc/com/intellij/psi/util/NameUtilTest.java +++ b/platform/platform-tests/testSrc/com/intellij/psi/util/NameUtilTest.java @@ -289,6 +289,13 @@ public class NameUtilTest extends UsefulTestCase { TextRange.from(0, 2)); } + public void testPreferCapsMatching() { + String sample = "getCurrentUser"; + // 0 4 10 + assertOrderedEquals(new NameUtil.MinusculeMatcher("getCU", NameUtil.MatchingCaseSensitivity.NONE).matchingFragments(sample), + TextRange.from(0, 4), TextRange.from(10, 1)); + } + public void testMatchingDegree() { assertPreference("OCO", "OneCoolObject", "OCObject"); assertPreference("MUp", "MavenUmlProvider", "MarkUp"); @@ -296,6 +303,7 @@ public class NameUtilTest extends UsefulTestCase { assertPreference("CertificateExce", "CertificateEncodingException", "CertificateException"); assertPreference("boo", "Boolean", "boolean", NameUtil.MatchingCaseSensitivity.NONE); assertPreference("Boo", "boolean", "Boolean", NameUtil.MatchingCaseSensitivity.NONE); + assertPreference("getCU", "getCurrentSomething", "getCurrentUser"); } private static void assertPreference(@NonNls String pattern, diff --git a/platform/util/src/com/intellij/openapi/util/JDOMExternalizableStringList.java b/platform/util/src/com/intellij/openapi/util/JDOMExternalizableStringList.java index b98c0a1dd0a1..9f754b895819 100644 --- a/platform/util/src/com/intellij/openapi/util/JDOMExternalizableStringList.java +++ b/platform/util/src/com/intellij/openapi/util/JDOMExternalizableStringList.java @@ -17,9 +17,11 @@ package com.intellij.openapi.util; import com.intellij.openapi.diagnostic.Logger; import org.jdom.Element; +import org.jetbrains.annotations.NotNull; import sun.reflect.Reflection; import java.util.ArrayList; +import java.util.Collection; @SuppressWarnings({"HardCodedStringLiteral"}) public class JDOMExternalizableStringList extends ArrayList implements JDOMExternalizable { @@ -32,6 +34,17 @@ public class JDOMExternalizableStringList extends ArrayList implements J private static final String ATTR_CLASS = "class"; private static final String ATTR_VALUE = "itemvalue"; + public JDOMExternalizableStringList(int initialCapacity) { + super(initialCapacity); + } + + public JDOMExternalizableStringList() { + } + + public JDOMExternalizableStringList(@NotNull Collection c) { + super(c); + } + public void readExternal(Element element) throws InvalidDataException { clear(); diff --git a/platform/util/src/com/intellij/psi/codeStyle/NameUtil.java b/platform/util/src/com/intellij/psi/codeStyle/NameUtil.java index 8c61b6c90e1d..db3833081524 100644 --- a/platform/util/src/com/intellij/psi/codeStyle/NameUtil.java +++ b/platform/util/src/com/intellij/psi/codeStyle/NameUtil.java @@ -423,6 +423,9 @@ public class NameUtil { if (patternIndex == myPattern.length) { return FList.emptyList(); } + if ('*' == myPattern[patternIndex]) { + return skipChars(name, patternIndex, nameIndex, true); + } if (nameIndex == name.length()) { return null; } @@ -430,9 +433,6 @@ public class NameUtil { if ('.' == myPattern[patternIndex] && name.charAt(nameIndex) != '.') { return skipChars(name, patternIndex, nameIndex, false); } - if ('*' == myPattern[patternIndex]) { - return skipChars(name, patternIndex, nameIndex, true); - } if (patternIndex == 0 && myOptions != MatchingCaseSensitivity.NONE && name.charAt(nameIndex) != myPattern[0]) { return null; @@ -455,26 +455,22 @@ public class NameUtil { int nextStart = NameUtil.nextWord(name, nameIndex); - boolean uppers = isWordStart(myPattern[patternIndex]); + int lastUpper = isWordStart(myPattern[patternIndex]) ? 0 : -1; int i = 1; while (true) { - if (patternIndex + i == myPattern.length) { - //end of pattern reached, the last word matches - return FList.emptyList().prepend(TextRange.from(nameIndex, i)); - } - if (i + nameIndex == nextStart) { - //whole word match + if (patternIndex + i == myPattern.length || i + nameIndex == nextStart) { break; } char p = myPattern[patternIndex + i]; - if (uppers && isWordStart(p) && myOptions != MatchingCaseSensitivity.ALL) { + char w = name.charAt(i + nameIndex); + if (lastUpper == i - 1 && isWordStart(p) && myOptions != MatchingCaseSensitivity.ALL) { + if (p == w) { + lastUpper = i; + } p = StringUtil.toLowerCase(p); - } else { - uppers = false; } - char w = name.charAt(i + nameIndex); if (myOptions != MatchingCaseSensitivity.ALL) { w = StringUtil.toLowerCase(w); } @@ -484,29 +480,38 @@ public class NameUtil { i++; } - if (myPattern[patternIndex + i] == '*') { - nextStart = nameIndex + i; + if (isFinalSpaceMatch(name, patternIndex, nameIndex, nextStart, i)) { + return FList.emptyList().prepend(TextRange.from(nameIndex, i)); } - // there's more in the pattern, but no more words - if (nextStart == name.length()) { - if (patternIndex + i == myPattern.length - 1) { - char last = myPattern[patternIndex + i]; - if (' ' == last && (i == 1 && isWordStart(myPattern[patternIndex]) || i + nameIndex == name.length()) || - '*' == last) { - return FList.emptyList().prepend(TextRange.from(nameIndex, i)); + return matchAfterFragment(name, patternIndex, nameIndex, nextStart, lastUpper, i); + } + + private boolean isFinalSpaceMatch(String name, int patternIndex, int nameIndex, int nextStart, int i) { + return nextStart == name.length() && + patternIndex + i == myPattern.length - 1 && + ' ' == myPattern[patternIndex + i] && + (i == 1 && isWordStart(myPattern[patternIndex]) || i + nameIndex == name.length()); + } + + @Nullable + private FList matchAfterFragment(String name, int patternIndex, int nameIndex, int nextStart, int lastUpper, int matchLen) { + int star = patternIndex + matchLen < myPattern.length && myPattern[patternIndex + matchLen] == '*' ? matchLen : -1; + if (lastUpper >= 0) { + FList ranges = matchName(name, patternIndex + lastUpper + 1, lastUpper == star ? nameIndex + lastUpper : nextStart); + if (ranges != null) { + return prependRange(ranges, nameIndex, lastUpper + 1); + } + } + + while (matchLen > 0) { + if (matchLen != lastUpper) { + FList ranges = matchName(name, patternIndex + matchLen, matchLen == star ? matchLen + lastUpper : nextStart); + if (ranges != null) { + return prependRange(ranges, nameIndex, matchLen); } } - - return null; - } - - while (i > 0) { - FList ranges = matchName(name, patternIndex + i, nextStart); - if (ranges != null) { - return prependRange(ranges, nameIndex, i); - } - i--; + matchLen--; } return null; } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ShortDiffDetails.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ShortDiffDetails.java index b65831f7b667..5c30d2039e35 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ShortDiffDetails.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ShortDiffDetails.java @@ -19,7 +19,6 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Getter; -import com.intellij.openapi.util.Pair; import com.intellij.openapi.vcs.Details; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.FilePathImpl; @@ -27,7 +26,6 @@ import com.intellij.openapi.vcs.GenericDetailsLoader; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Consumer; import com.intellij.util.PairConsumer; -import com.intellij.util.ThreeState; import com.intellij.util.containers.SLRUMap; import com.intellij.vcsUtil.UIVcsUtil; import org.jetbrains.annotations.Nullable; @@ -198,9 +196,11 @@ public class ShortDiffDetails implements RefreshablePanel, Disposable { @Override public void dispose() { if (myDetailsLoader != null) { - myDetailsLoader.dispose(); + Disposer.dispose(myDetailsLoader); + } + if (myDetailsPanel != null) { + myDetailsPanel.clear(); } - myDetailsPanel.clear(); myDetailsCache.clear(); } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitChangeListDialog.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitChangeListDialog.java index 67cd4033659b..9089fe523273 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitChangeListDialog.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitChangeListDialog.java @@ -236,7 +236,7 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj throw new IllegalArgumentException("nothing found to execute commit with"); } - myAllOfDefaultChangeListChangesIncluded = changes.containsAll(defaultChangeList.getChanges()); + myAllOfDefaultChangeListChangesIncluded = new HashSet(changes).containsAll(new HashSet(defaultChangeList.getChanges())); myIsAlien = isAlien; if (isAlien) { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitHelper.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitHelper.java index 8c6817faa73d..436b293b1f29 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitHelper.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitHelper.java @@ -42,12 +42,12 @@ import com.intellij.openapi.vcs.update.RefreshVFsSynchronously; import com.intellij.util.Consumer; import com.intellij.util.NullableFunction; import com.intellij.util.WaitForProgressToShow; -import com.intellij.util.containers.hash.HashSet; import com.intellij.util.ui.ConfirmationDialog; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.Collection; +import java.util.HashSet; import java.util.List; public class CommitHelper { @@ -326,7 +326,7 @@ public class CommitHelper { myAfterVcsRefreshModification = ChangeListsModificationAfterCommit.NOTHING; if (myChangeList instanceof LocalChangeList) { final LocalChangeList localList = (LocalChangeList) myChangeList; - final boolean containsAll = myIncludedChanges.containsAll(myChangeList.getChanges()); + final boolean containsAll = new HashSet(myIncludedChanges).containsAll(new HashSet(myChangeList.getChanges())); if (containsAll && !localList.isDefault() && !localList.isReadOnly()) { myAfterVcsRefreshModification = ChangeListsModificationAfterCommit.DELETE_LIST; } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTracker.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTracker.java index 7f45bdc8aa32..a9ef16c50e68 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTracker.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTracker.java @@ -87,7 +87,9 @@ public class LineStatusTracker { myUpToDateDocument.putUserData(UndoConstants.DONT_RECORD_UNDO, Boolean.TRUE); myProject = project; myBaseLoaded = BaseLoadState.LOADING; - myRanges = new ArrayList(); + synchronized (myLock) { + myRanges = new ArrayList(); + } myAnathemaThrown = false; myFileEditorManager = FileEditorManager.getInstance(myProject); } @@ -205,7 +207,6 @@ public class LineStatusTracker { } removeAnathema(); removeHighlightersFromMarkupModel(); - myRanges.clear(); myReleased = true; } } @@ -238,7 +239,6 @@ public class LineStatusTracker { myBulkUpdate = true; removeAnathema(); removeHighlightersFromMarkupModel(); - myRanges.clear(); } } @@ -249,6 +249,7 @@ public class LineStatusTracker { range.getHighlighter().dispose(); } } + myRanges.clear(); } } @@ -279,9 +280,7 @@ public class LineStatusTracker { myUpToDateDocument.setReadOnly(true); removeAnathema(); removeHighlightersFromMarkupModel(); - myRanges.clear(); myBaseLoaded = BaseLoadState.LOADING; - return; } } @@ -299,7 +298,7 @@ public class LineStatusTracker { synchronized (myLock) { if (myReleased) return; - if (myBulkUpdate || myAnathemaThrown || (BaseLoadState.LOADED != myBaseLoaded)) return; + if (myBulkUpdate || myAnathemaThrown || BaseLoadState.LOADED != myBaseLoaded) return; try { myFirstChangedLine = myDocument.getLineNumber(e.getOffset()); myLastChangedLine = myDocument.getLineNumber(e.getOffset() + e.getOldLength()); @@ -317,7 +316,7 @@ public class LineStatusTracker { myUpToDateFirstLine = firstChangedRange.getUOffset1(); } else { - myUpToDateFirstLine = firstChangedRange.getUOffset2() + (myFirstChangedLine - firstChangedRange.getOffset2()); + myUpToDateFirstLine = firstChangedRange.getUOffset2() + myFirstChangedLine - firstChangedRange.getOffset2(); } Range myLastChangedRange = getLastRangeBeforeLine(myLastChangedLine); @@ -330,7 +329,7 @@ public class LineStatusTracker { myLastChangedLine = myLastChangedRange.getOffset2(); } else { - myUpToDateLastLine = myLastChangedRange.getUOffset2() + (myLastChangedLine - myLastChangedRange.getOffset2()); + myUpToDateLastLine = myLastChangedRange.getUOffset2() + myLastChangedLine - myLastChangedRange.getOffset2(); } } catch (ProcessCanceledException ignore) { } @@ -353,7 +352,7 @@ public class LineStatusTracker { synchronized (myLock) { if (myReleased) return; - if (myBulkUpdate || myAnathemaThrown || (BaseLoadState.LOADED != myBaseLoaded)) return; + if (myBulkUpdate || myAnathemaThrown || BaseLoadState.LOADED != myBaseLoaded) return; try { int line = myDocument.getLineNumber(e.getOffset() + e.getNewLength()); @@ -415,7 +414,6 @@ public class LineStatusTracker { } catch (FilesTooBigForDiffException e1) { installAnathema(); removeHighlightersFromMarkupModel(); - myRanges.clear(); } } } diff --git a/plugins/android/src/org/jetbrains/android/logcat/AndroidLogcatColorPage.java b/plugins/android/src/org/jetbrains/android/logcat/AndroidLogcatColorPage.java index 19720c5477cc..27bf9aeae10d 100644 --- a/plugins/android/src/org/jetbrains/android/logcat/AndroidLogcatColorPage.java +++ b/plugins/android/src/org/jetbrains/android/logcat/AndroidLogcatColorPage.java @@ -48,12 +48,12 @@ public class AndroidLogcatColorPage implements ColorSettingsPage { "08-04 16:24:11.166: ASSERT/Assertion(4687): Expected true but was false"; static { - ADDITIONAL_HIGHLIGHT_DESCRIPTORS.put("verbose.level.title", AndroidLogcatConstants.VERBOSE_OUTPUT_KEY); - ADDITIONAL_HIGHLIGHT_DESCRIPTORS.put("debug.level.title", AndroidLogcatConstants.DEBUG_OUTPUT_KEY); - ADDITIONAL_HIGHLIGHT_DESCRIPTORS.put("info.level.title", AndroidLogcatConstants.INFO_OUTPUT_KEY); - ADDITIONAL_HIGHLIGHT_DESCRIPTORS.put("warning.level.title", AndroidLogcatConstants.WARNING_OUTPUT_KEY); - ADDITIONAL_HIGHLIGHT_DESCRIPTORS.put("error.level.title", AndroidLogcatConstants.ERROR_OUTPUT_KEY); - ADDITIONAL_HIGHLIGHT_DESCRIPTORS.put("assert.level.title", AndroidLogcatConstants.ASSERT_OUTPUT_KEY); + ADDITIONAL_HIGHLIGHT_DESCRIPTORS.put("verbose", AndroidLogcatConstants.VERBOSE_OUTPUT_KEY); + ADDITIONAL_HIGHLIGHT_DESCRIPTORS.put("debug", AndroidLogcatConstants.DEBUG_OUTPUT_KEY); + ADDITIONAL_HIGHLIGHT_DESCRIPTORS.put("info", AndroidLogcatConstants.INFO_OUTPUT_KEY); + ADDITIONAL_HIGHLIGHT_DESCRIPTORS.put("warning", AndroidLogcatConstants.WARNING_OUTPUT_KEY); + ADDITIONAL_HIGHLIGHT_DESCRIPTORS.put("error", AndroidLogcatConstants.ERROR_OUTPUT_KEY); + ADDITIONAL_HIGHLIGHT_DESCRIPTORS.put("assert", AndroidLogcatConstants.ASSERT_OUTPUT_KEY); } private static final AttributesDescriptor[] ATTRIBUTES_DESCRIPTORS = diff --git a/plugins/git4idea/src/git4idea/GitVcs.java b/plugins/git4idea/src/git4idea/GitVcs.java index 8bee54c341f3..7dd147df97cb 100644 --- a/plugins/git4idea/src/git4idea/GitVcs.java +++ b/plugins/git4idea/src/git4idea/GitVcs.java @@ -135,6 +135,7 @@ public class GitVcs extends AbstractVcs { private GitBranchWidget myBranchWidget; private GitVersion myVersion = GitVersion.NULL; // version of Git which this plugin uses. + private static final int MAX_CONSOLE_OUTPUT_SIZE = 10000; @Nullable public static GitVcs getInstance(Project project) { @@ -409,6 +410,9 @@ public class GitVcs extends AbstractVcs { * @param style a style to use */ private void showMessage(@NotNull String message, final TextAttributes style) { + if (message.length() > MAX_CONSOLE_OUTPUT_SIZE) { + message = message.substring(0, MAX_CONSOLE_OUTPUT_SIZE); + } myVcsManager.addMessageToConsoleWindow(message, style); } diff --git a/plugins/git4idea/src/git4idea/commands/GitHandler.java b/plugins/git4idea/src/git4idea/commands/GitHandler.java index 201606677a34..a71aa65e5030 100644 --- a/plugins/git4idea/src/git4idea/commands/GitHandler.java +++ b/plugins/git4idea/src/git4idea/commands/GitHandler.java @@ -621,10 +621,8 @@ public abstract class GitHandler { boolean suspendable = false; switch (myCommand.lockingPolicy()) { case META: - // do nothing no locks are taken for metadata - break; case READ: - vcs.getCommandLock().readLock().lock(); + // need to lock only write operations: reads can be performed even when a write operation is going on break; case WRITE_SUSPENDABLE: suspendable = true; @@ -716,10 +714,7 @@ public abstract class GitHandler { finally { switch (myCommand.lockingPolicy()) { case META: - // do nothing no locks are taken for metadata - break; case READ: - vcs.getCommandLock().readLock().unlock(); break; case WRITE_SUSPENDABLE: case WRITE: diff --git a/plugins/git4idea/src/git4idea/push/GitPushResult.java b/plugins/git4idea/src/git4idea/push/GitPushResult.java index 4a0226c846c4..e8ac07d4f6e1 100644 --- a/plugins/git4idea/src/git4idea/push/GitPushResult.java +++ b/plugins/git4idea/src/git4idea/push/GitPushResult.java @@ -277,7 +277,7 @@ class GitPushResult { sb.append(successReport); if (!updatedFiles.isEmpty()) { - sb.append("View files updated during the push"); + sb.append("View files updated during the push"); } NotificationListener viewUpdateFilesListener = new ViewUpdatedFilesNotificationListener(updatedFiles); diff --git a/plugins/gradle/src/META-INF/plugin.xml b/plugins/gradle/src/META-INF/plugin.xml index 7afc8950dde5..46b953b6956c 100644 --- a/plugins/gradle/src/META-INF/plugin.xml +++ b/plugins/gradle/src/META-INF/plugin.xml @@ -53,7 +53,6 @@ - org.jetbrains.plugins.gradle.notification.GradleConfigNotificationManager + + org.jetbrains.plugins.gradle.task.GradleTaskManager + diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/action/GradleRefreshProjectAction.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/action/GradleRefreshProjectAction.java index 52007519dc49..e47bc21333b3 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/action/GradleRefreshProjectAction.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/action/GradleRefreshProjectAction.java @@ -2,7 +2,6 @@ package org.jetbrains.plugins.gradle.action; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.Presentation; -import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; @@ -32,7 +31,7 @@ public class GradleRefreshProjectAction extends AbstractGradleLinkedProjectActio @Override protected void doUpdate(@NotNull Presentation presentation, @NotNull Project project, @NotNull String linkedProjectPath) { boolean enabled = false; - final GradleTaskManager taskManager = ServiceManager.getService(GradleTaskManager.class); + final GradleTaskManager taskManager = project.getComponent(GradleTaskManager.class); if (taskManager != null) { enabled = !taskManager.hasTaskOfTypeInProgress(GradleTaskType.RESOLVE_PROJECT); } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleConfigurable.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleConfigurable.java index 5c42b3763ba2..7416ae2ec650 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleConfigurable.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleConfigurable.java @@ -37,6 +37,8 @@ import javax.swing.*; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import java.awt.*; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.io.File; import java.util.concurrent.TimeUnit; @@ -117,6 +119,22 @@ public class GradleConfigurable implements SearchableConfigurable, Configurable. } } }; + myComponent.addPropertyChangeListener(new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (!"ancestor".equals(evt.getPropertyName())) { + return; + } + + // Configure the balloon to show on initial configurable drawing. + myShowBalloonIfNecessary = evt.getNewValue() != null && evt.getOldValue() == null; + + if (evt.getNewValue() == null && evt.getOldValue() != null) { + // Cancel delayed balloons when the configurable is hidden. + myAlarm.cancelAllRequests(); + } + } + }); GridBagConstraints constraints = new GridBagConstraints(); constraints.gridwidth = GridBagConstraints.REMAINDER; constraints.weightx = 1; @@ -151,7 +169,6 @@ public class GradleConfigurable implements SearchableConfigurable, Configurable. @Override public boolean isModified() { - myShowBalloonIfNecessary = true; if (!myPathManuallyModified) { return false; } @@ -169,17 +186,25 @@ public class GradleConfigurable implements SearchableConfigurable, Configurable. useNormalColorForPath(); String path = myGradleHomeComponent.getPath(); GradleSettings.applyGradleHome(path, myProject); - - // There is a possible case that user defines gradle home for particular open project. We want to apply that value - // to the default project as well if it's still non-defined. - Project defaultProject = ProjectManager.getInstance().getDefaultProject(); - if (defaultProject == myProject) { + + if (isValidGradleHome(path)) { + myGradleHomeSettingType = GradleHomeSettingType.EXPLICIT_CORRECT; + // There is a possible case that user defines gradle home for particular open project. We want to apply that value + // to the default project as well if it's still non-defined. + Project defaultProject = ProjectManager.getInstance().getDefaultProject(); + if (defaultProject != myProject && !isValidGradleHome(GradleSettings.getInstance(defaultProject).getGradleHome())) { + GradleSettings.applyGradleHome(path, defaultProject); + } return; } - if (isValidGradleHome(path) && !isValidGradleHome(GradleSettings.getInstance(defaultProject).getGradleHome())) { - GradleSettings.applyGradleHome(path, defaultProject); - } + if (StringUtil.isEmpty(path)) { + myGradleHomeSettingType = GradleHomeSettingType.UNKNOWN; + } + else { + myGradleHomeSettingType = GradleHomeSettingType.EXPLICIT_INCORRECT; + new DelayedBalloonInfo(MessageType.ERROR, myGradleHomeSettingType, 0).run(); + } } private boolean isValidGradleHome(@Nullable String path) { @@ -203,7 +228,7 @@ public class GradleConfigurable implements SearchableConfigurable, Configurable. GradleHomeSettingType.EXPLICIT_CORRECT : GradleHomeSettingType.EXPLICIT_INCORRECT; if (myGradleHomeSettingType == GradleHomeSettingType.EXPLICIT_INCORRECT) { - new DelayedBalloonInfo(MessageType.ERROR, myGradleHomeSettingType).run(); + new DelayedBalloonInfo(MessageType.ERROR, myGradleHomeSettingType, 0).run(); } else { myAlarm.cancelAllRequests(); @@ -283,9 +308,13 @@ public class GradleConfigurable implements SearchableConfigurable, Configurable. private final long myTriggerTime; DelayedBalloonInfo(@NotNull MessageType messageType, @NotNull GradleHomeSettingType settingType) { + this(messageType, settingType, BALLOON_DELAY_MILLIS); + } + + DelayedBalloonInfo(@NotNull MessageType messageType, @NotNull GradleHomeSettingType settingType, long delayMillis) { myMessageType = messageType; myText = settingType.getDescription(); - myTriggerTime = System.currentTimeMillis() + BALLOON_DELAY_MILLIS; + myTriggerTime = System.currentTimeMillis() + delayMillis; } @Override @@ -296,11 +325,15 @@ public class GradleConfigurable implements SearchableConfigurable, Configurable. myAlarm.addRequest(this, diff); return; } - if (myGradleHomeComponent == null || !myGradleHomeComponent.getPathComponent().isShowing()) { + if (myGradleHomeComponent == null) { myAlarm.cancelAllRequests(); myAlarm.addRequest(this, 200); return; } + if (!myGradleHomeComponent.getPathComponent().isShowing()) { + // Don't schedule the balloon if the configurable is hidden. + return; + } GradleUtil.showBalloon(myGradleHomeComponent.getPathComponent(), myMessageType, myText); } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleModulesImporter.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleModulesImporter.java index 1c192c1cef84..edc0ea2d1184 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleModulesImporter.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleModulesImporter.java @@ -338,7 +338,7 @@ public class GradleModulesImporter { public void run(@NotNull final ProgressIndicator indicator) { GradleResolveProjectTask task = new GradleResolveProjectTask(intellijProject, gradleProjectPath, true); task.execute(indicator); - GradleProject projectWithResolvedLibraries = task.getProject(); + GradleProject projectWithResolvedLibraries = task.getGradleProject(); gradleProjectRef.set(projectWithResolvedLibraries); ApplicationManager.getApplication().invokeLater(setupExternalDependenciesTask, ModalityState.NON_MODAL); } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/GradleApiFacadeManager.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/GradleApiFacadeManager.java index beafc16f69e6..a54979f44b8d 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/GradleApiFacadeManager.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/GradleApiFacadeManager.java @@ -14,11 +14,15 @@ import com.intellij.execution.process.ProcessTerminatedListener; import com.intellij.execution.rmi.RemoteProcessSupport; import com.intellij.execution.runners.ProgramRunner; import com.intellij.ide.actions.OpenProjectFileChooserDescriptor; +import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.projectRoots.*; import com.intellij.openapi.roots.DependencyScope; +import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.ShutDownTracker; import com.intellij.openapi.util.text.StringUtil; @@ -27,8 +31,10 @@ import com.intellij.psi.PsiBundle; import com.intellij.util.Alarm; import com.intellij.util.PathUtil; import com.intellij.util.SystemProperties; +import com.intellij.util.containers.ConcurrentWeakHashMap; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.gradle.notification.GradleProgressNotificationManager; import org.jetbrains.plugins.gradle.notification.GradleProgressNotificationManagerImpl; import org.jetbrains.plugins.gradle.remote.impl.GradleApiFacadeImpl; @@ -49,8 +55,8 @@ import java.rmi.server.UnicastRemoteObject; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.concurrent.ConcurrentMap; import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; /** * Entry point to work with remote {@link GradleApiFacade}. @@ -62,15 +68,19 @@ import java.util.concurrent.atomic.AtomicReference; */ public class GradleApiFacadeManager { + private static final Pair NULL_VALUE = Pair.empty(); + private static final String REMOTE_PROCESS_TTL_IN_MS_KEY = "gradle.remote.process.ttl.ms"; private static final String MAIN_CLASS_NAME = GradleApiFacadeImpl.class.getName(); private static final int REMOTE_FAIL_RECOVERY_ATTEMPTS_NUMBER = 3; - private final AtomicReference> myFacade - = new AtomicReference>(); - private final AtomicReference myExportedProgressManager - = new AtomicReference(); + private final ConcurrentMap myFacadeWrappers + = new ConcurrentWeakHashMap(); + private final ConcurrentMap myRemoteNotificationManagers + = new ConcurrentWeakHashMap(); + private final ConcurrentMap> myRemoteFacades + = new ConcurrentWeakHashMap>(); @NotNull private final GradleLibraryManager myGradleLibraryManager; @NotNull private final GradleProgressNotificationManagerImpl myProgressManager; @@ -78,13 +88,12 @@ public class GradleApiFacadeManager { // Please note that we don't use RemoteGradleProcessSettings as the 'Configuration' type parameter here because we need // to apply the settings to the newly created process. I.e. every time new process is created we need to call // 'GradleApiFacade.applySettings()'. So, we need to hold reference to the last returned 'GradleApiFacade' stub anyway. - private final RemoteProcessSupport mySupport; - private final GradleApiFacade myApiFacade; + private final RemoteProcessSupport mySupport; public GradleApiFacadeManager(@NotNull GradleLibraryManager gradleLibraryManager, @NotNull GradleProgressNotificationManager manager) { myGradleLibraryManager = gradleLibraryManager; myProgressManager = (GradleProgressNotificationManagerImpl)manager; - mySupport = new RemoteProcessSupport(GradleApiFacade.class) { + mySupport = new RemoteProcessSupport(GradleApiFacade.class) { @Override protected void fireModificationCountChanged() { } @@ -95,13 +104,10 @@ public class GradleApiFacadeManager { } @Override - protected RunProfileState getRunProfileState(Object o, Object configuration, Executor executor) throws ExecutionException { - return createRunProfileState(); + protected RunProfileState getRunProfileState(Object o, String configuration, Executor executor) throws ExecutionException { + return createRunProfileState(findProjectByName(configuration)); } }; - myApiFacade = (GradleApiFacade)Proxy.newProxyInstance( - GradleApiFacadeManager.class.getClassLoader(), new Class[]{GradleApiFacade.class}, new MyHandler() - ); ShutDownTracker.getInstance().registerShutdownTask(new Runnable() { public void run() { @@ -110,10 +116,21 @@ public class GradleApiFacadeManager { }); } - private RunProfileState createRunProfileState() { + @NotNull + private static Project findProjectByName(@NotNull String name) { + final ProjectManager projectManager = ProjectManager.getInstance(); + for (Project project : projectManager.getOpenProjects()) { + if (name.equals(project.getName())) { + return project; + } + } + return projectManager.getDefaultProject(); + } + + private RunProfileState createRunProfileState(@Nullable final Project project) { return new CommandLineState(null) { private SimpleJavaParameters createJavaParameters() throws ExecutionException { - Collection gradleLibraries = myGradleLibraryManager.getAllLibraries(); + Collection gradleLibraries = myGradleLibraryManager.getAllLibraries(project); GradleLog.LOG.assertTrue(gradleLibraries != null, GradleBundle.message("gradle.generic.text.error.sdk.undefined")); if (gradleLibraries == null) { throw new ExecutionException("Can't find gradle libraries"); @@ -193,19 +210,29 @@ public class GradleApiFacadeManager { * @throws Exception in case of inability to return the facade */ @NotNull - public GradleApiFacade getFacade() throws Exception { - return myApiFacade; + public GradleApiFacade getFacade(@Nullable Project project) throws Exception { + if (project == null) { + project = ProjectManager.getInstance().getDefaultProject(); + } + final GradleApiFacade facade = myFacadeWrappers.get(project.getName()); + if (facade == null) { + final GradleApiFacade newFacade = (GradleApiFacade)Proxy.newProxyInstance( + GradleApiFacadeManager.class.getClassLoader(), new Class[]{GradleApiFacade.class}, new MyHandler(project) + ); + myFacadeWrappers.putIfAbsent(project.getName(), newFacade); + } + return myFacadeWrappers.get(project.getName()); } - public Object doInvoke(Method method, Object[] args, int invocationNumber) throws Throwable { - GradleApiFacade facade = doGetFacade(); + public Object doInvoke(@NotNull Project project, Method method, Object[] args, int invocationNumber) throws Throwable { + GradleApiFacade facade = doGetFacade(project); try { return method.invoke(facade, args); } catch (InvocationTargetException e) { if (e.getTargetException() instanceof RemoteException && invocationNumber > 0) { Thread.sleep(1000); - return doInvoke(method, args, invocationNumber - 1); + return doInvoke(project, method, args, invocationNumber - 1); } else { throw e; @@ -213,43 +240,57 @@ public class GradleApiFacadeManager { } } + @SuppressWarnings("ConstantConditions") @NotNull - private GradleApiFacade doGetFacade() throws Exception { - if (!GradleUtil.isGradleAvailable()) { + private GradleApiFacade doGetFacade(@NotNull Project project) throws Exception { + if (project.isDisposed() || !GradleUtil.isGradleAvailable(project)) { return GradleApiFacade.NULL_OBJECT; } - Pair pair = myFacade.get(); + Pair pair = myRemoteFacades.get(project.getName()); if (pair != null) { - if (isValid(pair)) { + if (isValid(pair, project)) { return pair.first; } mySupport.stopAll(true); - myFacade.compareAndSet(pair, null); + myFacadeWrappers.clear(); + myRemoteFacades.clear(); + final Pair p = myRemoteFacades.putIfAbsent(project.getName(), NULL_VALUE); + if (p != null && p != NULL_VALUE) { + return p.first; + } } - final GradleApiFacade facade = mySupport.acquire(this, ""); + final GradleApiFacade facade = mySupport.acquire(this, project.getName()); if (facade == null) { - throw new IllegalStateException("Can't obtain facade to working with gradle api at the remote process"); + throw new IllegalStateException("Can't obtain facade to working with gradle api at the remote process. Project: " + project); } + Disposer.register(project, new Disposable() { + @Override + public void dispose() { + mySupport.stopAll(true); + myFacadeWrappers.clear(); + myRemoteFacades.clear(); + } + }); final GradleApiFacade result = new GradleApiFacadeWrapper(facade, myProgressManager); Pair newPair - = new Pair(result, getRemoteSettings()); - if (!myFacade.compareAndSet(null, newPair)) { - GradleLog.LOG.warn("Detected unexpected duplicate tooling api facade instance creation"); - return myFacade.get().first; + = new Pair(result, getRemoteSettings(project)); + if (myRemoteFacades.putIfAbsent(project.getName(), newPair) != null && !myRemoteFacades.replace(project.getName(), NULL_VALUE, newPair)) { + GradleLog.LOG.warn("Detected unexpected duplicate tooling api facade instance creation. Project: " + project); + return myRemoteFacades.get(project.getName()).first; } if (!StringUtil.isEmpty(newPair.second.getJavaHome())) { GradleLog.LOG.info("Instructing gradle to use java from " + newPair.second.getJavaHome()); } result.applySettings(newPair.second); - RemoteGradleProgressNotificationManager exported = myExportedProgressManager.get(); + RemoteGradleProgressNotificationManager exported = myRemoteNotificationManagers.get(project.getName()); if (exported == null) { try { exported = (RemoteGradleProgressNotificationManager)UnicastRemoteObject.exportObject(myProgressManager, 0); - myExportedProgressManager.set(exported); + myRemoteNotificationManagers.putIfAbsent(project.getName(), exported); } catch (RemoteException e) { - exported = myExportedProgressManager.get(); + exported = myRemoteNotificationManagers.get(project.getName()); } } if (exported == null) { @@ -261,7 +302,11 @@ public class GradleApiFacadeManager { return result; } - private boolean isValid(@NotNull Pair pair) { + private boolean isValid(@NotNull Pair pair, @Nullable Project project) { + if (pair == NULL_VALUE) { + return false; + } + // Check remote process is alive. try { pair.first.getResolver(); @@ -272,8 +317,8 @@ public class GradleApiFacadeManager { // Check that significant settings are not changed RemoteGradleProcessSettings oldSettings = pair.second; - RemoteGradleProcessSettings currentSettings = getRemoteSettings(); - + RemoteGradleProcessSettings currentSettings = getRemoteSettings(project); + // We restart the slave process because there is a possible case that it was started with the incorrect classpath. // For example, it could be started with gradle milestone-3 and that means that its classpath doesn't contain BasicIdeaProject.class. // So, even if the user defines gradle milestone-7 to use, the slave process still is unable to operate because its classpath @@ -285,8 +330,8 @@ public class GradleApiFacadeManager { } @NotNull - private RemoteGradleProcessSettings getRemoteSettings() { - File gradleHome = myGradleLibraryManager.getGradleHome(); + private RemoteGradleProcessSettings getRemoteSettings(@Nullable Project project) { + File gradleHome = myGradleLibraryManager.getGradleHome(project); RemoteGradleProcessSettings result = new RemoteGradleProcessSettings(gradleHome.getAbsolutePath()); String ttlAsString = System.getProperty(REMOTE_PROCESS_TTL_IN_MS_KEY); if (ttlAsString != null) { @@ -304,9 +349,16 @@ public class GradleApiFacadeManager { } private class MyHandler implements InvocationHandler { + + @NotNull private final String myProjectName; + + MyHandler(@NotNull Project project) { + myProjectName = project.getName(); + } + @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - return doInvoke(method, args, REMOTE_FAIL_RECOVERY_ATTEMPTS_NUMBER); + return doInvoke(findProjectByName(myProjectName), method, args, REMOTE_FAIL_RECOVERY_ATTEMPTS_NUMBER); } } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/task/AbstractGradleTask.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/task/AbstractGradleTask.java index 535ab6660ea1..0d848c744f29 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/task/AbstractGradleTask.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/task/AbstractGradleTask.java @@ -3,7 +3,9 @@ package org.jetbrains.plugins.gradle.task; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.gradle.notification.GradleProgressNotificationManager; import org.jetbrains.plugins.gradle.notification.GradleTaskNotificationEvent; import org.jetbrains.plugins.gradle.notification.GradleTaskNotificationListener; @@ -28,9 +30,11 @@ public abstract class AbstractGradleTask implements GradleTask { private final AtomicReference myState = new AtomicReference(GradleTaskState.NOT_STARTED); private final AtomicReference myError = new AtomicReference(); - private final GradleTaskId myId; + @Nullable transient private final Project myIntellijProject; + @NotNull private final GradleTaskId myId; - protected AbstractGradleTask(@NotNull GradleTaskType type) { + protected AbstractGradleTask(Project project, @NotNull GradleTaskType type) { + myIntellijProject = project; myId = GradleTaskId.create(type); } @@ -53,13 +57,18 @@ public abstract class AbstractGradleTask implements GradleTask { return myError.get(); } + @Nullable + public Project getIntellijProject() { + return myIntellijProject; + } + public void refreshState() { if (getState() != GradleTaskState.IN_PROGRESS) { return; } final GradleApiFacadeManager manager = ServiceManager.getService(GradleApiFacadeManager.class); try { - final GradleApiFacade facade = manager.getFacade(); + final GradleApiFacade facade = manager.getFacade(myIntellijProject); setState(facade.isTaskInProgress(getId()) ? GradleTaskState.IN_PROGRESS : GradleTaskState.FAILED); } catch (Throwable e) { diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/task/GradleResolveProjectTask.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/task/GradleResolveProjectTask.java index 8cc02d6d86fa..476ed753861d 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/task/GradleResolveProjectTask.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/task/GradleResolveProjectTask.java @@ -21,20 +21,19 @@ public class GradleResolveProjectTask extends AbstractGradleTask { private final AtomicReference myGradleProject = new AtomicReference(); - private final Project myIntellijProject; + private final String myProjectPath; private final boolean myResolveLibraries; public GradleResolveProjectTask(@Nullable Project project, @NotNull String projectPath, boolean resolveLibraries) { - super(GradleTaskType.RESOLVE_PROJECT); - myIntellijProject = project; + super(project, GradleTaskType.RESOLVE_PROJECT); myProjectPath = projectPath; myResolveLibraries = resolveLibraries; } protected void doExecute() throws Exception { final GradleApiFacadeManager manager = ServiceManager.getService(GradleApiFacadeManager.class); - GradleProjectResolver resolver = manager.getFacade().getResolver(); + GradleProjectResolver resolver = manager.getFacade(getIntellijProject()).getResolver(); setState(GradleTaskState.IN_PROGRESS); final GradleProject project = resolver.resolveProjectInfo(getId(), myProjectPath, myResolveLibraries); if (project == null) { @@ -42,10 +41,11 @@ public class GradleResolveProjectTask extends AbstractGradleTask { } myGradleProject.set(project); setState(GradleTaskState.FINISHED); - if (myIntellijProject == null || myIntellijProject.isDisposed()) { + final Project intellijProject = getIntellijProject(); + if (intellijProject == null || intellijProject.isDisposed()) { return; } - final GradleProjectStructureChangesModel model = myIntellijProject.getComponent(GradleProjectStructureChangesModel.class); + final GradleProjectStructureChangesModel model = intellijProject.getComponent(GradleProjectStructureChangesModel.class); if (model != null) { // This task may be called during the 'import from gradle' processing, hence, no project-level IoC is up. // Model update is necessary for the correct tool window project structure diff showing but we don't have @@ -55,7 +55,7 @@ public class GradleResolveProjectTask extends AbstractGradleTask { } @Nullable - public GradleProject getProject() { + public GradleProject getGradleProject() { return myGradleProject.get(); } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/task/GradleTaskManager.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/task/GradleTaskManager.java index 86ae3f72762d..9f4acf10fec4 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/task/GradleTaskManager.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/task/GradleTaskManager.java @@ -1,5 +1,8 @@ package org.jetbrains.plugins.gradle.task; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.components.AbstractProjectComponent; +import com.intellij.openapi.project.Project; import com.intellij.util.Alarm; import com.intellij.util.containers.ConcurrentHashMap; import org.jetbrains.annotations.NotNull; @@ -23,7 +26,7 @@ import java.util.concurrent.TimeUnit; * @author Denis Zhdanov * @since 2/8/12 1:52 PM */ -public class GradleTaskManager implements GradleTaskNotificationListener { +public class GradleTaskManager extends AbstractProjectComponent implements GradleTaskNotificationListener { /** * We receive information about the tasks being enqueued to the slave gradle projects here. However, there is a possible @@ -45,9 +48,19 @@ public class GradleTaskManager implements GradleTaskNotificationListener { @NotNull private final Alarm myAlarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD); @NotNull private final GradleApiFacadeManager myFacadeManager; + @NotNull private final GradleProgressNotificationManager myProgressNotificationManager; - public GradleTaskManager(@NotNull GradleApiFacadeManager facadeManager, @NotNull GradleProgressNotificationManager notificationManager) { + public GradleTaskManager(@NotNull Project project, + @NotNull GradleApiFacadeManager facadeManager, + @NotNull GradleProgressNotificationManager notificationManager) + { + super(project); myFacadeManager = facadeManager; + myProgressNotificationManager = notificationManager; + if (ApplicationManager.getApplication().isUnitTestMode()) { + return; + } + notificationManager.addNotificationListener(this); myAlarm.addRequest(new Runnable() { @Override @@ -67,7 +80,12 @@ public class GradleTaskManager implements GradleTaskNotificationListener { } }, DETECT_HANGED_TASKS_FREQUENCY_MILLIS); } - + + @Override + public void disposeComponent() { + myProgressNotificationManager.removeNotificationListener(this); + } + /** * Allows to check if any task of the given type is being executed at the moment. * @@ -106,7 +124,7 @@ public class GradleTaskManager implements GradleTaskNotificationListener { public void update() { try { - final Map> currentState = myFacadeManager.getFacade().getTasksInProgress(); + final Map> currentState = myFacadeManager.getFacade(myProject).getTasksInProgress(); myTasksInProgress.clear(); for (Set ids : currentState.values()) { for (GradleTaskId id : ids) { diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleLibraryManager.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleLibraryManager.java index 864978764d17..b07a24120186 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleLibraryManager.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleLibraryManager.java @@ -44,15 +44,6 @@ public class GradleLibraryManager { GRADLE_ENV_PROPERTY_NAME = System.getProperty("gradle.home.env.key", "GRADLE_HOME"); } - @Nullable - public Collection getAllLibraries() { - final Project[] projects = ProjectManager.getInstance().getOpenProjects(); - if (projects.length == 1) { - return getAllLibraries(projects[0]); - } - return getAllLibraries(null); - } - /** * Allows to get file handles for the gradle binaries to use. * diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleUtil.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleUtil.java index 0f346153bb13..892958e6fd22 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleUtil.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleUtil.java @@ -208,7 +208,7 @@ public class GradleUtil { public void execute(@NotNull ProgressIndicator indicator) { GradleResolveProjectTask task = new GradleResolveProjectTask(project, gradleProjectPath, resolveLibraries); task.execute(indicator); - gradleProject.set(task.getProject()); + gradleProject.set(task.getGradleProject()); final Throwable error = task.getError(); if (error == null) { return; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPropertyResolver.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPropertyResolver.java index e42b84800af2..fe4b96434501 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPropertyResolver.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPropertyResolver.java @@ -216,10 +216,17 @@ public class MavenPropertyResolver { MavenId parentId = selectedProject.getParentId(); if (parentId == null) return null; + unprefixed = unprefixed.substring("parent.".length()); + + if (unprefixed.equals("groupId")) { + return parentId.getGroupId(); + } + if (unprefixed.equals("artifactId")) { + return parentId.getArtifactId(); + } + selectedProject = projectsManager.findProject(parentId); if (selectedProject == null) return null; - - unprefixed = unprefixed.substring("parent.".length()); } if (unprefixed.equals("basedir") || (hasPrefix && mavenProject == selectedProject && unprefixed.equals("baseUri"))) { @@ -243,28 +250,6 @@ public class MavenPropertyResolver { result = mavenProject.getProperties().getProperty(propName); if (result != null) return result; - if (unprefixed.equals("groupId")) { - return selectedProject.getMavenId().getGroupId(); - } - if (unprefixed.equals("artifactId")) { - return selectedProject.getMavenId().getArtifactId(); - } - if (unprefixed.equals("version")) { - return selectedProject.getMavenId().getVersion(); - } - if (unprefixed.equals("buildDirectory")) { - return selectedProject.getBuildDirectory(); - } - if (unprefixed.equals("finalName")) { - return selectedProject.getFinalName(); - } - if (unprefixed.equals("outputDirectory")) { - return selectedProject.getOutputDirectory(); - } - if (unprefixed.equals("testOutputDirectory")) { - return selectedProject.getTestOutputDirectory(); - } - return null; } } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java index 258972e1bb52..5f3f6e99157a 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java @@ -31,7 +31,6 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.SmartList; import com.intellij.util.containers.CollectionFactory; import com.intellij.util.containers.ContainerUtil; -import gnu.trove.THashMap; import gnu.trove.THashSet; import org.jdom.Element; import org.jetbrains.annotations.NotNull; @@ -737,7 +736,13 @@ public class MavenProject { @Nullable public MavenPlugin findPlugin(@Nullable String groupId, @Nullable String artifactId) { - for (MavenPlugin each : getPlugins()) { + return findPlugin(groupId, artifactId, false); + } + + @Nullable + public MavenPlugin findPlugin(@Nullable String groupId, @Nullable String artifactId, final boolean explicitlyDeclaredOnly) { + final List plugins = explicitlyDeclaredOnly ? getDeclaredPlugins() : getPlugins(); + for (MavenPlugin each : plugins) { if (each.getMavenId().equals(groupId, artifactId)) return each; } return null; diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReader.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReader.java index 5612282b46b0..cc9fdd942cb0 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReader.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReader.java @@ -56,8 +56,17 @@ public class MavenProjectReader { File basedir = getBaseDir(file); MavenModel model = MavenServerManager.getInstance().interpolateAndAlignModel(readResult.first.model, basedir); + Map modelMap = new HashMap(); + modelMap.put("groupId", model.getMavenId().getGroupId()); + modelMap.put("artifactId", model.getMavenId().getArtifactId()); + modelMap.put("version", model.getMavenId().getVersion()); + modelMap.put("build.outputDirectory", model.getBuild().getOutputDirectory()); + modelMap.put("build.testOutputDirectory", model.getBuild().getTestOutputDirectory()); + modelMap.put("build.finalName", model.getBuild().getFinalName()); + modelMap.put("build.directory", model.getBuild().getDirectory()); + return new MavenProjectReaderResult(model, - Collections.emptyMap(), + modelMap, readResult.second, null, readResult.first.problems, @@ -162,7 +171,7 @@ public class MavenProjectReader { } } - private List collectResources(List xmlResources) { + private static List collectResources(List xmlResources) { List result = new ArrayList(); for (Element each : xmlResources) { result.add(new MavenResource(MavenJDOMUtil.findChildValueByPath(each, "directory"), diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenPackagingCompletionTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenPackagingCompletionTest.java index e98eb0fc34e0..b495e61b5c9b 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenPackagingCompletionTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenPackagingCompletionTest.java @@ -27,7 +27,7 @@ public class MavenPackagingCompletionTest extends MavenDomTestCase { ""); - assertCompletionVariants(myProjectPom, "jar", "pom", "war", "ejb", "ejb-client", "ear", "bundle"); + assertCompletionVariants(myProjectPom, "jar", "pom", "war", "ejb", "ejb-client", "ear", "bundle", "maven-plugin"); } public void testDoNotHighlightUnknownPackagingTypes() throws Throwable { diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenPropertyResolverTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenPropertyResolverTest.java index 378866fdd985..e9d469bc0f17 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenPropertyResolverTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenPropertyResolverTest.java @@ -123,10 +123,10 @@ public class MavenPropertyResolverTest extends MavenImportingTestCase { assertEquals("parent.value", resolve("${parentProp}", f)); assertEquals("module.value", resolve("${moduleProp}", f)); - assertEquals("parent.value", resolve("${project.parentProp}", f)); - assertEquals("parent.value", resolve("${pom.parentProp}", f)); - assertEquals("module.value", resolve("${project.moduleProp}", f)); - assertEquals("module.value", resolve("${pom.moduleProp}", f)); + assertEquals("${project.parentProp}", resolve("${project.parentProp}", f)); + assertEquals("${pom.parentProp}", resolve("${pom.parentProp}", f)); + assertEquals("${project.moduleProp}", resolve("${project.moduleProp}", f)); + assertEquals("${pom.moduleProp}", resolve("${pom.moduleProp}", f)); } public void testProjectPropertiesRecursively() throws Exception { diff --git a/plugins/tasks/jira-connector/src/main/java/com/intellij/tasks/jira/JiraTask.java b/plugins/tasks/jira-connector/src/main/java/com/intellij/tasks/jira/JiraTask.java index c7df1e689fd2..b9ef96425f32 100644 --- a/plugins/tasks/jira-connector/src/main/java/com/intellij/tasks/jira/JiraTask.java +++ b/plugins/tasks/jira-connector/src/main/java/com/intellij/tasks/jira/JiraTask.java @@ -144,9 +144,4 @@ class JiraTask extends Task { public String getIssueUrl() { return myJiraIssue.getIssueUrl(); } - - @Override - public String getCustomIcon() { - return null; - } } diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/Task.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/Task.java index 3cec728645c5..e946785b0ebd 100644 --- a/plugins/tasks/tasks-api/src/com/intellij/tasks/Task.java +++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/Task.java @@ -64,7 +64,9 @@ public abstract class Task { public abstract boolean isClosed(); @Nullable - public abstract String getCustomIcon(); + public String getCustomIcon() { + return null; + } /** * @return true if bugtracking issue is associated diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/github/GitHubRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/github/GitHubRepository.java index 2e2050ba5129..f09fa7dd790a 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/github/GitHubRepository.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/github/GitHubRepository.java @@ -224,11 +224,6 @@ public class GitHubRepository extends BaseRepositoryImpl { public String getPresentableName() { return getId() + ": " + getSummary(); } - - @Override - public String getCustomIcon() { - return null; - } }; } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/lighthouse/LighthouseRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/lighthouse/LighthouseRepository.java index c0b09fc4720d..c8492cb88007 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/lighthouse/LighthouseRepository.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/lighthouse/LighthouseRepository.java @@ -198,11 +198,6 @@ public class LighthouseRepository extends BaseRepositoryImpl { public String getPresentableName() { return getId() + ": " + getSummary(); } - - @Override - public String getCustomIcon() { - return null; - } }; } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/redmine/RedmineRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/redmine/RedmineRepository.java index 934bba605fa1..646265f8991c 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/redmine/RedmineRepository.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/redmine/RedmineRepository.java @@ -165,11 +165,6 @@ public class RedmineRepository extends BaseRepositoryImpl { public String getPresentableName() { return getId() + ": " + getSummary(); } - - @Override - public String getCustomIcon() { - return null; - } }; } diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/TaskVcsTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/TaskVcsTest.java index 67415fd57c86..52d955f914c9 100644 --- a/plugins/tasks/tasks-tests/test/com/intellij/tasks/TaskVcsTest.java +++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/TaskVcsTest.java @@ -144,11 +144,6 @@ public class TaskVcsTest extends TaskManagerTestCase { return false; } - @Override - public String getCustomIcon() { - return null; - } - @Override public boolean isIssue() { return false; diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/actions/CommonEditActionsProvider.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/actions/CommonEditActionsProvider.java index b0d8928027d1..927ae68ee52f 100644 --- a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/actions/CommonEditActionsProvider.java +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/actions/CommonEditActionsProvider.java @@ -16,7 +16,7 @@ package com.intellij.designer.actions; import com.intellij.designer.DesignerBundle; -import com.intellij.designer.clipboard.SerializedComponentData; +import com.intellij.uiDesigner.SerializedComponentData; import com.intellij.designer.clipboard.SimpleTransferable; import com.intellij.designer.designSurface.DesignerEditorPanel; import com.intellij.designer.designSurface.EditableArea; @@ -142,21 +142,24 @@ public class CommonEditActionsProvider implements DeleteProvider, CopyProvider, } private boolean doCopy() { - return myDesigner.getToolProvider().execute(new ThrowableRunnable() { - @Override - public void run() throws Exception { - Element root = new Element("designer"); - root.setAttribute("target", myDesigner.getPlatformTarget()); + try { + Element root = new Element("designer"); + root.setAttribute("target", myDesigner.getPlatformTarget()); - List components = RadComponent.getPureSelection(myDesigner.getActionsArea().getSelection()); - for (RadComponent component : components) { - component.copyTo(root); - } - - SerializedComponentData data = new SerializedComponentData(new XMLOutputter().outputString(root)); - CopyPasteManager.getInstance().setContents(new SimpleTransferable(data, DATA_FLAVOR)); + List components = RadComponent.getPureSelection(myDesigner.getActionsArea().getSelection()); + for (RadComponent component : components) { + component.copyTo(root); } - }); + + SerializedComponentData data = new SerializedComponentData(new XMLOutputter().outputString(root)); + CopyPasteManager.getInstance().setContents(new SimpleTransferable(data, DATA_FLAVOR)); + + return true; + } + catch (Throwable e) { + myDesigner.showError("Copy error:", e); + return false; + } } ////////////////////////////////////////////////////////////////////////////////////////// // diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/model/MetaModel.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/model/MetaModel.java index add10d839504..399439f46fc9 100644 --- a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/model/MetaModel.java +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/model/MetaModel.java @@ -84,7 +84,7 @@ public class MetaModel { if (myIconPath == null) { return myPaletteItem.getIcon(); } - myIcon = IconLoader.getIcon(myIconPath); + myIcon = IconLoader.findIcon(myIconPath, myModel); } return myIcon; } diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/palette/Item.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/palette/Item.java index 5da043ce8e45..3794bb28fb49 100644 --- a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/palette/Item.java +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/palette/Item.java @@ -19,7 +19,6 @@ import com.intellij.designer.model.MetaModel; import com.intellij.ide.dnd.DnDDragStartBean; import com.intellij.ide.palette.PaletteItem; import com.intellij.openapi.actionSystem.ActionGroup; -import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.IconLoader; import com.intellij.ui.ColoredListCellRenderer; @@ -50,7 +49,7 @@ public final class Item implements PaletteItem { public Icon getIcon() { if (myIcon == null) { - myIcon = IconLoader.getIcon(myIconPath); + myIcon = IconLoader.findIcon(myIconPath, myMetaModel.getModel()); } return myIcon; } diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index 11c8763e1679..e30a42bfee3b 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -211,6 +211,7 @@ + + + diff --git a/xml/impl/src/com/intellij/psi/formatter/xml/AbstractXmlBlock.java b/xml/impl/src/com/intellij/psi/formatter/xml/AbstractXmlBlock.java index e5eeab72f3cf..c64b5e032af8 100644 --- a/xml/impl/src/com/intellij/psi/formatter/xml/AbstractXmlBlock.java +++ b/xml/impl/src/com/intellij/psi/formatter/xml/AbstractXmlBlock.java @@ -22,7 +22,8 @@ import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleSettings; -import com.intellij.psi.formatter.FormatterUtil; +import com.intellij.psi.formatter.WhiteSpaceFormattingStrategy; +import com.intellij.psi.formatter.WhiteSpaceFormattingStrategyFactory; import com.intellij.psi.formatter.common.AbstractBlock; import com.intellij.psi.impl.source.SourceTreeToPsiMap; import com.intellij.psi.impl.source.tree.LeafElement; @@ -273,7 +274,7 @@ public abstract class AbstractXmlBlock extends AbstractBlock { ASTNode resultNode = child; ASTNode currentChild = child.getTreeNext(); while (currentChild != null && currentChild.getElementType() != XmlElementType.XML_END_TAG_START) { - if (!FormatterUtil.containsWhiteSpacesOnly(currentChild)) { + if (!containsWhiteSpacesOnly(currentChild)) { currentChild = processChild(result, currentChild, wrap, alignment, indent); resultNode = currentChild; } @@ -466,4 +467,11 @@ public abstract class AbstractXmlBlock extends AbstractBlock { return myNode.getElementType() == XmlElementType.XML_CDATA_END; } + public static boolean containsWhiteSpacesOnly(ASTNode node) { + WhiteSpaceFormattingStrategy strategy = WhiteSpaceFormattingStrategyFactory.getStrategy(node.getPsi().getLanguage()); + String nodeText = node.getText(); + int length = nodeText.length(); + return strategy.check(nodeText, 0, length) >= length; + } + } diff --git a/xml/impl/src/com/intellij/psi/formatter/xml/XmlBlock.java b/xml/impl/src/com/intellij/psi/formatter/xml/XmlBlock.java index 29068c340968..2886be8ed06e 100644 --- a/xml/impl/src/com/intellij/psi/formatter/xml/XmlBlock.java +++ b/xml/impl/src/com/intellij/psi/formatter/xml/XmlBlock.java @@ -23,7 +23,6 @@ import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiWhiteSpace; import com.intellij.psi.TokenType; -import com.intellij.psi.formatter.FormatterUtil; import com.intellij.psi.formatter.common.AbstractBlock; import com.intellij.psi.impl.source.SourceTreeToPsiMap; import com.intellij.psi.templateLanguages.OuterLanguageElement; @@ -112,7 +111,7 @@ public class XmlBlock extends AbstractXmlBlock { final ArrayList result = new ArrayList(5); ASTNode child = myNode.getFirstChildNode(); while (child != null) { - if (!FormatterUtil.containsWhiteSpacesOnly(child) && child.getTextLength() > 0) { + if (!containsWhiteSpacesOnly(child) && child.getTextLength() > 0) { child = processChild(result, child, getDefaultWrap(child), null, getChildDefaultIndent()); } if (child != null) { @@ -127,6 +126,7 @@ public class XmlBlock extends AbstractXmlBlock { } } + private List splitAttribute(ASTNode node, XmlFormattingPolicy formattingPolicy) { final ArrayList result = new ArrayList(3); ASTNode child = node.getFirstChildNode(); diff --git a/xml/impl/src/com/intellij/psi/formatter/xml/XmlTagBlock.java b/xml/impl/src/com/intellij/psi/formatter/xml/XmlTagBlock.java index 3d0d78fa4601..2e2ead783bea 100644 --- a/xml/impl/src/com/intellij/psi/formatter/xml/XmlTagBlock.java +++ b/xml/impl/src/com/intellij/psi/formatter/xml/XmlTagBlock.java @@ -18,8 +18,6 @@ package com.intellij.psi.formatter.xml; import com.intellij.formatting.*; import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElement; -import com.intellij.psi.codeStyle.CodeStyleSettings; -import com.intellij.psi.formatter.FormatterUtil; import com.intellij.psi.tree.IElementType; import com.intellij.psi.xml.XmlElementType; import com.intellij.psi.xml.XmlTag; @@ -64,7 +62,7 @@ public class XmlTagBlock extends AbstractXmlBlock{ boolean insideTag = true; while (child != null) { - if (!FormatterUtil.containsWhiteSpacesOnly(child) && child.getTextLength() > 0){ + if (!containsWhiteSpacesOnly(child) && child.getTextLength() > 0){ Wrap wrap = chooseWrap(child, tagBeginWrap, attrWrap, textWrap); Alignment alignment = chooseAlignment(child, attrAlignment, textAlignment); @@ -176,7 +174,7 @@ public class XmlTagBlock extends AbstractXmlBlock{ final Alignment alignment ) { while (child != null) { - if (!FormatterUtil.containsWhiteSpacesOnly(child) && child.getTextLength() > 0){ + if (!XmlBlock.containsWhiteSpacesOnly(child) && child.getTextLength() > 0){ final Indent indent = getChildrenIndent(); child = processChild(list,child, wrap, alignment, indent); if (child == null) return child; diff --git a/xml/impl/src/com/intellij/psi/impl/source/tree/injected/XmlTextLiteralEscaper.java b/xml/impl/src/com/intellij/psi/impl/source/tree/injected/XmlTextLiteralEscaper.java index 3182a969f016..ca6154728968 100644 --- a/xml/impl/src/com/intellij/psi/impl/source/tree/injected/XmlTextLiteralEscaper.java +++ b/xml/impl/src/com/intellij/psi/impl/source/tree/injected/XmlTextLiteralEscaper.java @@ -38,11 +38,13 @@ public class XmlTextLiteralEscaper extends LiteralTextEscaper { } public int getOffsetInHost(final int offsetInDecoded, @NotNull final TextRange rangeInsideHost) { - int displayStart = myHost.physicalToDisplay(rangeInsideHost.getStartOffset()); + final int rangeInsideHostStartOffset = rangeInsideHost.getStartOffset(); + int displayStart = myHost.physicalToDisplay(rangeInsideHostStartOffset); int i = myHost.displayToPhysical(offsetInDecoded + displayStart); - if (i < rangeInsideHost.getStartOffset()) i = rangeInsideHost.getStartOffset(); - if (i > rangeInsideHost.getEndOffset()) i = rangeInsideHost.getEndOffset(); + if (i < rangeInsideHostStartOffset) i = rangeInsideHostStartOffset; + final int rangeInsideHostEndOffset = rangeInsideHost.getEndOffset(); + if (i > rangeInsideHostEndOffset) i = rangeInsideHostEndOffset; return i; } diff --git a/xml/impl/src/com/intellij/xml/actions/ValidateXmlActionHandler.java b/xml/impl/src/com/intellij/xml/actions/ValidateXmlActionHandler.java index 638bbf5e63ce..2275976cd61a 100644 --- a/xml/impl/src/com/intellij/xml/actions/ValidateXmlActionHandler.java +++ b/xml/impl/src/com/intellij/xml/actions/ValidateXmlActionHandler.java @@ -32,6 +32,9 @@ import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; import com.intellij.psi.xml.*; import com.intellij.ui.content.*; +import com.intellij.util.ArrayUtil; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.ErrorTreeView; import com.intellij.util.ui.MessageCategory; import com.intellij.xml.XmlBundle; @@ -56,10 +59,7 @@ import javax.xml.parsers.SAXParserFactory; import java.io.FileNotFoundException; import java.io.StringReader; import java.net.*; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; import java.util.concurrent.Future; /** @@ -70,9 +70,11 @@ public class ValidateXmlActionHandler { private static final Key KEY = Key.create("ValidateXmlAction.KEY"); @NonNls private static final String SCHEMA_FULL_CHECKING_FEATURE_ID = "http://apache.org/xml/features/validation/schema-full-checking"; private static final String GRAMMAR_FEATURE_ID = Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY; + private static final Key GRAMMAR_POOL_KEY = Key.create("GrammarPoolKey"); private static final Key GRAMMAR_POOL_TIME_STAMP_KEY = Key.create("GrammarPoolTimeStampKey"); private static final Key DEPENDENT_FILES_KEY = Key.create("GrammarPoolFilesKey"); + private static final Key KNOWN_NAMESPACES_KEY = Key.create("KnownNamespacesKey"); private Project myProject; private XmlFile myFile; @@ -418,6 +420,7 @@ public class ValidateXmlActionHandler { myFile.putUserData(DEPENDENT_FILES_KEY, files); myFile.putUserData(GRAMMAR_POOL_TIME_STAMP_KEY, new Long(calculateTimeStamp(files, myProject))); } + myFile.putUserData(KNOWN_NAMESPACES_KEY, getNamespaces(myFile)); } catch (SAXException e) { LOG.debug(e); @@ -490,9 +493,7 @@ public class ValidateXmlActionHandler { XMLGrammarPool grammarPool = null; // check if the pool is valid - if (!forceChecking && - !isValidationDependentFilesOutOfDate(file) - ) { + if (!forceChecking && !isValidationDependentFilesOutOfDate(file)) { grammarPool = previousGrammarPool; } @@ -511,10 +512,13 @@ public class ValidateXmlActionHandler { public static boolean isValidationDependentFilesOutOfDate(XmlFile myFile) { final VirtualFile[] files = myFile.getUserData(DEPENDENT_FILES_KEY); final Long grammarPoolTimeStamp = myFile.getUserData(GRAMMAR_POOL_TIME_STAMP_KEY); + String[] ns = myFile.getUserData(KNOWN_NAMESPACES_KEY); - if (grammarPoolTimeStamp != null && - files != null - ) { + if (!Arrays.equals(ns, getNamespaces(myFile))) { + return true; + } + + if (grammarPoolTimeStamp != null && files != null) { long dependentFilesTimestamp = calculateTimeStamp(files,myFile.getProject()); if (dependentFilesTimestamp == grammarPoolTimeStamp.longValue()) { @@ -525,6 +529,17 @@ public class ValidateXmlActionHandler { return true; } + private static String[] getNamespaces(XmlFile file) { + XmlTag rootTag = file.getRootTag(); + if (rootTag == null) return ArrayUtil.EMPTY_STRING_ARRAY; + return ContainerUtil.mapNotNull(rootTag.getAttributes(), new Function() { + @Override + public String fun(XmlAttribute attribute) { + return attribute.getValue(); + } + }, ArrayUtil.EMPTY_STRING_ARRAY); + } + private static long calculateTimeStamp(final VirtualFile[] files, Project myProject) { long timestamp = 0; diff --git a/xml/impl/src/com/intellij/xml/util/CheckXmlFileWithXercesValidatorInspection.java b/xml/impl/src/com/intellij/xml/util/CheckXmlFileWithXercesValidatorInspection.java index 900ae8ed9455..8a664c544030 100644 --- a/xml/impl/src/com/intellij/xml/util/CheckXmlFileWithXercesValidatorInspection.java +++ b/xml/impl/src/com/intellij/xml/util/CheckXmlFileWithXercesValidatorInspection.java @@ -26,6 +26,7 @@ import org.jetbrains.annotations.NotNull; /** * @author Maxim Mossienko + * @see com.intellij.xml.impl.ExternalDocumentValidator */ public class CheckXmlFileWithXercesValidatorInspection extends XmlSuppressableInspectionTool implements UnfairLocalInspectionTool { public static final @NonNls String SHORT_NAME = "CheckXmlFileWithXercesValidator";