diff --git a/java/compiler/impl/src/com/intellij/compiler/CompilerEncodingService.java b/java/compiler/impl/src/com/intellij/compiler/CompilerEncodingService.java new file mode 100644 index 000000000000..104173a09fca --- /dev/null +++ b/java/compiler/impl/src/com/intellij/compiler/CompilerEncodingService.java @@ -0,0 +1,40 @@ +/* + * 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.compiler; + +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.nio.charset.Charset; +import java.util.Collection; + +/** + * @author nik + */ +public abstract class CompilerEncodingService { + public static CompilerEncodingService getInstance(@NotNull Project project) { + return ServiceManager.getService(project, CompilerEncodingService.class); + } + + @Nullable + public abstract Charset getPreferredModuleEncoding(@NotNull Module module); + + @NotNull + public abstract Collection getAllModuleEncodings(@NotNull Module module); +} diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/CompilerEncodingServiceImpl.java b/java/compiler/impl/src/com/intellij/compiler/impl/CompilerEncodingServiceImpl.java new file mode 100644 index 000000000000..2257176c5e02 --- /dev/null +++ b/java/compiler/impl/src/com/intellij/compiler/impl/CompilerEncodingServiceImpl.java @@ -0,0 +1,118 @@ +/* + * 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.compiler.impl; + +import com.intellij.compiler.CompilerEncodingService; +import com.intellij.openapi.compiler.CompilerManager; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.ProjectFileIndex; +import com.intellij.openapi.roots.ProjectRootManager; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.encoding.EncodingProjectManager; +import com.intellij.openapi.vfs.encoding.EncodingProjectManagerImpl; +import com.intellij.psi.util.CachedValue; +import com.intellij.psi.util.CachedValueProvider; +import com.intellij.psi.util.CachedValuesManager; +import com.intellij.util.containers.ContainerUtil; +import gnu.trove.THashMap; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.nio.charset.Charset; +import java.util.Collection; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; + +/** + * @author nik + */ +public class CompilerEncodingServiceImpl extends CompilerEncodingService { + @NotNull private final Project myProject; + private final CachedValue>> myModuleFileEncodings; + + public CompilerEncodingServiceImpl(@NotNull Project project) { + myProject = project; + myModuleFileEncodings = CachedValuesManager.getManager(project).createCachedValue(new CachedValueProvider>>() { + @Override + public Result>> compute() { + Map> result = computeModuleCharsetMap(); + return Result.create(result, ProjectRootManager.getInstance(myProject), + ((EncodingProjectManagerImpl)EncodingProjectManager.getInstance(myProject)).getModificationTracker()); + } + }, false); + } + + private Map> computeModuleCharsetMap() { + final Map> map = new THashMap>(); + final Map mappings = EncodingProjectManager.getInstance(myProject).getAllMappings(); + ProjectFileIndex index = ProjectRootManager.getInstance(myProject).getFileIndex(); + final CompilerManager compilerManager = CompilerManager.getInstance(myProject); + for (Map.Entry entry : mappings.entrySet()) { + final VirtualFile file = entry.getKey(); + final Charset charset = entry.getValue(); + if (file == null || charset == null || !compilerManager.isCompilableFileType(file.getFileType()) + || !index.isInSourceContent(file)) continue; + + final Module module = index.getModuleForFile(file); + if (module == null) continue; + + Set set = map.get(module); + if (set == null) { + set = new LinkedHashSet(); + map.put(module, set); + + final VirtualFile sourceRoot = index.getSourceRootForFile(file); + VirtualFile current = file.getParent(); + Charset parentCharset = null; + while (current != null) { + final Charset currentCharset = mappings.get(current); + if (currentCharset != null) { + parentCharset = currentCharset; + } + if (current.equals(sourceRoot)) { + break; + } + current = current.getParent(); + } + if (parentCharset != null) { + set.add(parentCharset); + } + } + set.add(charset); + } + + return map; + } + + @Override + @Nullable + public Charset getPreferredModuleEncoding(@NotNull Module module) { + final Set encodings = myModuleFileEncodings.getValue().get(module); + return ContainerUtil.getFirstItem(encodings, EncodingProjectManager.getInstance(myProject).getDefaultCharset()); + } + + @NotNull + @Override + public Collection getAllModuleEncodings(@NotNull Module module) { + final Set encodings = myModuleFileEncodings.getValue().get(module); + if (encodings != null) { + return encodings; + } + return ContainerUtil.createMaybeSingletonList(EncodingProjectManager.getInstance(myProject).getDefaultCharset()); + } +} 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/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ModuleStructureConfigurable.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ModuleStructureConfigurable.java index 41546503f757..4fc52aea677a 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ModuleStructureConfigurable.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ModuleStructureConfigurable.java @@ -770,10 +770,16 @@ public class ModuleStructureConfigurable extends BaseStructureConfigurable imple return null; } }; + + Collection actionsFromExtensions = new ArrayList(); for (final ModuleStructureExtension extension : ModuleStructureExtension.EP_NAME.getExtensions()) { - result.addAll(extension.createAddActions(selectedNodeRetriever, TREE_UPDATER, myProject, myRoot)); + actionsFromExtensions.addAll(extension.createAddActions(selectedNodeRetriever, TREE_UPDATER, myProject, myRoot)); } + if (!actionsFromExtensions.isEmpty() && !result.isEmpty()) { + result.add(new Separator()); + } + result.addAll(actionsFromExtensions); return result.toArray(new AnAction[result.size()]); } }; diff --git a/java/java-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspection.java b/java/java-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspection.java index ec028e11c50e..06583b409c77 100644 --- a/java/java-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspection.java @@ -26,6 +26,7 @@ import com.intellij.codeInspection.*; import com.intellij.codeInspection.ex.BaseLocalInspectionTool; import com.intellij.ide.DataManager; import com.intellij.openapi.actionSystem.PlatformDataKeys; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.util.text.StringUtil; @@ -60,6 +61,8 @@ public class NullableStuffInspection extends BaseLocalInspectionTool { @Deprecated @SuppressWarnings({"WeakerAccess"}) public boolean REPORT_NOT_ANNOTATED_SETTER_PARAMETER = true; @Deprecated @SuppressWarnings({"WeakerAccess"}) public boolean REPORT_ANNOTATION_NOT_PROPAGATED_TO_OVERRIDERS = true; // remains for test @SuppressWarnings({"WeakerAccess"}) public boolean REPORT_NULLS_PASSED_TO_NON_ANNOTATED_METHOD = true; + + private static final Logger LOG = Logger.getInstance("#" + NullableStuffInspection.class.getName()); @NotNull public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) { @@ -144,10 +147,10 @@ public class NullableStuffInspection extends BaseLocalInspectionTool { final PsiParameter[] parameters = setter.getParameterList().getParameters(); assert parameters.length == 1 : setter.getText(); final PsiParameter parameter = parameters[0]; - assert parameter != null : setter.getText(); + LOG.assertTrue(parameter != null, setter.getText()); if (REPORT_NOT_ANNOTATED_GETTER && !AnnotationUtil.isAnnotated(parameter, manager.getAllAnnotations()) && !TypeConversionUtil.isPrimitiveAndNotNull(parameter.getType())) { final PsiIdentifier nameIdentifier1 = parameter.getNameIdentifier(); - assert nameIdentifier1 != null : parameter; + assertValidElement(setter, parameter, nameIdentifier1); holder.registerProblem(nameIdentifier1, InspectionsBundle.message("inspection.nullable.problems.annotated.field.setter.parameter.not.annotated", StringUtil.getShortName(anno)), @@ -157,7 +160,7 @@ public class NullableStuffInspection extends BaseLocalInspectionTool { if (PropertyUtils.isSimpleSetter(setter)) { if (annotated.isDeclaredNotNull && manager.isNullable(parameter, false)) { final PsiIdentifier nameIdentifier1 = parameter.getNameIdentifier(); - assert nameIdentifier1 != null : parameter; + assertValidElement(setter, parameter, nameIdentifier1); holder.registerProblem(nameIdentifier1, InspectionsBundle.message( "inspection.nullable.problems.annotated.field.setter.parameter.conflict", StringUtil.getShortName(anno), nullableSimpleName), @@ -166,7 +169,7 @@ public class NullableStuffInspection extends BaseLocalInspectionTool { } else if (annotated.isDeclaredNullable && manager.isNotNull(parameter, false)) { final PsiIdentifier nameIdentifier1 = parameter.getNameIdentifier(); - assert nameIdentifier1 != null : parameter; + assertValidElement(setter, parameter, nameIdentifier1); holder.registerProblem(nameIdentifier1, InspectionsBundle.message( "inspection.nullable.problems.annotated.field.setter.parameter.conflict", StringUtil.getShortName(anno), notNullSimpleName), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, @@ -241,6 +244,11 @@ public class NullableStuffInspection extends BaseLocalInspectionTool { } } + private void assertValidElement(PsiMethod setter, PsiParameter parameter, PsiIdentifier nameIdentifier1) { + LOG.assertTrue(nameIdentifier1 != null, setter.getText()); + LOG.assertTrue(parameter.isPhysical(), setter.getText()); + } + public PsiAssignmentExpression getAssignmentExpressionIfOnAssignmentLefthand(PsiExpression expression) { PsiElement parent = PsiTreeUtil.skipParentsOfType(expression, PsiParenthesizedExpression.class); if (!(parent instanceof PsiAssignmentExpression)) { 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 index 8b93c386d07c..af68ee1a409b 100644 --- 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 @@ -20,11 +20,11 @@ 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.openapi.project.Project; 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 com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.util.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -35,9 +35,9 @@ import java.util.List; * @author Konstantin Bulenkov */ public class JavaLangClassMemberReference extends PsiReferenceBase implements InsertHandler { - private final PsiClassObjectAccessExpression myContext; + private final PsiExpression myContext; - public JavaLangClassMemberReference(PsiLiteralExpression literal, PsiClassObjectAccessExpression context) { + public JavaLangClassMemberReference(PsiLiteralExpression literal, PsiExpression context) { super(literal); myContext = context; } @@ -67,7 +67,26 @@ public class JavaLangClassMemberReference extends PsiReferenceBase EP_NAME = ExtensionPointName.create("com.intellij.psi.clsDecompiledFileProvider"); + + /** + * Returns decompiled PSI associated with this classfile + * + * @param clsFile instance of ClsFile + * @return decompiled PSI file + */ + @Nullable + PsiFile getDecompiledPsiFile(@NotNull PsiJavaFile clsFile); +} diff --git a/java/java-psi-impl/java-psi-impl.iml b/java/java-psi-impl/java-psi-impl.iml index 6c15172b7e3d..ccd2d51410f9 100644 --- a/java/java-psi-impl/java-psi-impl.iml +++ b/java/java-psi-impl/java-psi-impl.iml @@ -12,7 +12,6 @@ - diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java index 1de25cafa001..631c86dd3a50 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java @@ -26,8 +26,6 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileEditor.FileDocumentManager; -import com.intellij.openapi.fileTypes.ContentBasedClassFileProcessor; -import com.intellij.openapi.fileTypes.ContentBasedFileSubstitutor; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.progress.NonCancelableSection; import com.intellij.openapi.progress.ProgressIndicatorProvider; @@ -327,12 +325,10 @@ public class ClsFileImpl extends ClsRepositoryPsiElement @Override public PsiFile getDecompiledPsiFile() { - for (ContentBasedFileSubstitutor processor : Extensions.getExtensions(ContentBasedFileSubstitutor.EP_NAME)) { - if (processor instanceof ContentBasedClassFileProcessor && processor.isApplicable(getProject(), getVirtualFile())) { - PsiFile decompiledPsiFile = ((ContentBasedClassFileProcessor)processor).getDecompiledPsiFile(this); - if (decompiledPsiFile != null) { - return decompiledPsiFile; - } + for (ClsFileDecompiledPsiFileProvider provider : Extensions.getExtensions(ClsFileDecompiledPsiFileProvider.EP_NAME)) { + PsiFile decompiledPsiFile = provider.getDecompiledPsiFile(this); + if (decompiledPsiFile != null) { + return decompiledPsiFile; } } return (PsiFile) getMirror(); diff --git a/java/java-tests/testData/codeInsight/completion/reflection/ForNameDeclaredField.java b/java/java-tests/testData/codeInsight/completion/reflection/ForNameDeclaredField.java new file mode 100644 index 000000000000..b8111aba4c72 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/reflection/ForNameDeclaredField.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 ForNameDeclaredField { + void foo() { + Class.forName("Test").getDeclaredField(""); + } +} + +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/ForNameDeclaredField_after.java b/java/java-tests/testData/codeInsight/completion/reflection/ForNameDeclaredField_after.java new file mode 100644 index 000000000000..b6224c1fbb4c --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/reflection/ForNameDeclaredField_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 ForNameDeclaredField { + void foo() { + Class.forName("Test").getDeclaredField("num3"); + } +} + +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/ForNameDeclaredMethod.java b/java/java-tests/testData/codeInsight/completion/reflection/ForNameDeclaredMethod.java new file mode 100644 index 000000000000..9f2d2aeec438 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/reflection/ForNameDeclaredMethod.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 ForNameDeclaredMethod { + void foo() { + Class.forName("Test").getDeclaredMethod(""); + } +} + +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/ForNameDeclaredMethod_after.java b/java/java-tests/testData/codeInsight/completion/reflection/ForNameDeclaredMethod_after.java new file mode 100644 index 000000000000..ff165cfc6ac4 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/reflection/ForNameDeclaredMethod_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 ForNameDeclaredMethod { + void foo() { + Class.forName("Test").getDeclaredMethod("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/testData/codeInsight/completion/reflection/ForNameField.java b/java/java-tests/testData/codeInsight/completion/reflection/ForNameField.java new file mode 100644 index 000000000000..ace6e481b3a4 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/reflection/ForNameField.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 ForNameField { + void foo() { + Class.forName("Test").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/ForNameField_after.java b/java/java-tests/testData/codeInsight/completion/reflection/ForNameField_after.java new file mode 100644 index 000000000000..c8c6d5ed4923 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/reflection/ForNameField_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 ForNameField { + void foo() { + Class.forName("Test").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/ForNameMethod.java b/java/java-tests/testData/codeInsight/completion/reflection/ForNameMethod.java new file mode 100644 index 000000000000..9789073801f9 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/reflection/ForNameMethod.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 ForNameMethod { + void foo() { + Class.forName("Test").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/ForNameMethod_after.java b/java/java-tests/testData/codeInsight/completion/reflection/ForNameMethod_after.java new file mode 100644 index 000000000000..8a1412ec4895 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/reflection/ForNameMethod_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 ForNameMethod { + void foo() { + Class.forName("Test").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/JavaAutoPopupTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy index 4e4700b484ca..4aabe47f124f 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy @@ -1240,4 +1240,16 @@ class Foo {{ assert myFixture.lookupElementStrings.containsAll(['too', 'command.toString']) } + public void testUnfinishedString() { + myFixture.configureByText 'a.java', ''' +// Date +class Foo { + String s = " + String s2 = s; +} +''' + type 'D' + assert !lookup + } + } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaReflectionCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaReflectionCompletionTest.java index 86351f99e964..5d5a4dc178f3 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaReflectionCompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaReflectionCompletionTest.java @@ -52,6 +52,21 @@ public class JavaReflectionCompletionTest extends LightFixtureCompletionTestCase doTest(1, "method", "method2"); } + public void testForNameDeclaredMethod() throws Exception { + doTest(1, "method", "method2", "method3"); + } + + public void testForNameMethod() throws Exception { + doTest(1, "method", "method2"); + } + + public void testForNameField() throws Exception { + doTest(1, "num", "num2"); + } + + public void testForNameDeclaredField() throws Exception { + doTest(2, "num", "num2", "num3"); + } private void doTest(int index, String... expected) { configureByFile(getTestName(false) + ".java"); diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/IntervalTreeImpl.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/IntervalTreeImpl.java index 54ab504d2a94..bdf9b68045fc 100644 --- a/platform/core-impl/src/com/intellij/openapi/editor/impl/IntervalTreeImpl.java +++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/IntervalTreeImpl.java @@ -65,7 +65,7 @@ public abstract class IntervalTreeImpl extends RedBla private final IntervalTreeImpl myIntervalTree; - public IntervalNode(IntervalTreeImpl intervalTree, @NotNull E key, int start, int end) { + public IntervalNode(@NotNull IntervalTreeImpl intervalTree, @NotNull E key, int start, int end) { // maxEnd == 0 so to not disrupt existing maxes myIntervalTree = intervalTree; myStart = start; diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerImpl.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerImpl.java index 72180cd2ec84..7d1343e5ad70 100644 --- a/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerImpl.java +++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerImpl.java @@ -28,7 +28,7 @@ public class RangeMarkerImpl extends UserDataHolderBase implements RangeMarkerEx private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.impl.RangeMarkerImpl"); protected final DocumentEx myDocument; - protected RangeMarkerTree.RMNode myNode; + protected RangeMarkerTree.RMNode myNode; private final long myId; private static final StripedIDGenerator counter = new StripedIDGenerator(); @@ -91,7 +91,7 @@ public class RangeMarkerImpl extends UserDataHolderBase implements RangeMarkerEx public void invalidate(final DocumentEvent e) { setValid(false); - RangeMarkerTree.RMNode node = myNode; + RangeMarkerTree.RMNode node = myNode; if (node != null) { node.processAliveKeys(new Processor() { diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerTree.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerTree.java index bd320dfc7462..6fc5bb1d8830 100644 --- a/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerTree.java +++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerTree.java @@ -88,10 +88,10 @@ public class RangeMarkerTree extends IntervalTreeImpl.RMNode addInterval(@NotNull T interval, int start, int end, boolean greedyToLeft, boolean greedyToRight, int layer) { + public RMNode addInterval(@NotNull T interval, int start, int end, boolean greedyToLeft, boolean greedyToRight, int layer) { RangeMarkerImpl marker = (RangeMarkerImpl)interval; marker.setValid(true); - RangeMarkerTree.RMNode node = (RMNode)super.addInterval(interval, start, end, greedyToLeft, greedyToRight, layer); + RMNode node = (RMNode)super.addInterval(interval, start, end, greedyToLeft, greedyToRight, layer); if (DEBUG && node.intervals.size() > DUPLICATE_LIMIT) { l.readLock().lock(); @@ -113,7 +113,7 @@ public class RangeMarkerTree extends IntervalTreeImpl node) { @NonNls final StringBuilder msg = new StringBuilder(); final AtomicInteger alive = new AtomicInteger(); node.processAliveKeys(new Processor() { @@ -135,8 +135,8 @@ public class RangeMarkerTree extends IntervalTreeImpl createNewNode(@NotNull T key, int start, int end, boolean greedyToLeft, boolean greedyToRight, int layer) { + return new RMNode(this, key, start, end, greedyToLeft, greedyToRight); } @Override @@ -146,21 +146,26 @@ public class RangeMarkerTree extends IntervalTreeImpl.RMNode lookupNode(@NotNull T key) { - return (RMNode)((RangeMarkerImpl)key).myNode; + protected RMNode lookupNode(@NotNull T key) { + return (RMNode)((RangeMarkerImpl)key).myNode; } @Override protected void setNode(@NotNull T key, IntervalNode intervalNode) { - ((RangeMarkerImpl)key).myNode = (RangeMarkerTree.RMNode)intervalNode; + ((RangeMarkerImpl)key).myNode = (RMNode)intervalNode; } - public class RMNode extends IntervalTreeImpl.IntervalNode { + static class RMNode extends IntervalTreeImpl.IntervalNode { private final boolean isExpandToLeft; private final boolean isExpandToRight; - public RMNode(@NotNull T key, int start, int end, boolean greedyToLeft, boolean greedyToRight) { - super(RangeMarkerTree.this, key, start, end); + public RMNode(@NotNull RangeMarkerTree rangeMarkerTree, + @NotNull T key, + int start, + int end, + boolean greedyToLeft, + boolean greedyToRight) { + super(rangeMarkerTree, key, start, end); isExpandToLeft = greedyToLeft; isExpandToRight = greedyToRight; } @@ -227,7 +232,7 @@ public class RangeMarkerTree extends IntervalTreeImpl insertedNode = (RMNode)findOrInsert(node); // can change if two range become the one if (insertedNode != node) { // merge happened diff --git a/platform/lang-api/src/com/intellij/codeInsight/completion/SkipAutopopupInStrings.java b/platform/lang-api/src/com/intellij/codeInsight/completion/SkipAutopopupInStrings.java index e6eab89815c8..699667024930 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/completion/SkipAutopopupInStrings.java +++ b/platform/lang-api/src/com/intellij/codeInsight/completion/SkipAutopopupInStrings.java @@ -17,10 +17,11 @@ package com.intellij.codeInsight.completion; import com.intellij.lang.LanguageParserDefinitions; import com.intellij.lang.ParserDefinition; -import com.intellij.patterns.ElementPattern; import com.intellij.patterns.PlatformPatterns; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiErrorElement; import com.intellij.psi.PsiFile; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtilBase; import com.intellij.util.ThreeState; import org.jetbrains.annotations.NotNull; @@ -42,13 +43,26 @@ public class SkipAutopopupInStrings extends CompletionConfidence { if (contextElement != null) { ParserDefinition definition = LanguageParserDefinitions.INSTANCE.forLanguage(PsiUtilBase.getLanguageAtOffset(psiFile, offset)); if (definition != null) { - ElementPattern pattern = PlatformPatterns.psiElement().withElementType(definition.getStringLiteralElements()); - if (pattern.accepts(contextElement) || pattern.accepts(contextElement.getParent())) { + if (isStringLiteral(contextElement, definition) || isStringLiteral(contextElement.getParent(), definition)) { return ThreeState.YES; } + if (offset > 0) { + PsiElement prev = psiFile.findElementAt(offset - 1); + if (prev != null && (isStringLiteralWithError(prev, definition) || isStringLiteralWithError(prev.getParent(), definition))) { + return ThreeState.YES; + } + } } } return ThreeState.UNSURE; } + + private static boolean isStringLiteral(PsiElement element, ParserDefinition definition) { + return PlatformPatterns.psiElement().withElementType(definition.getStringLiteralElements()).accepts(element); + } + + private static boolean isStringLiteralWithError(PsiElement element, ParserDefinition definition) { + return isStringLiteral(element, definition) && PsiTreeUtil.nextLeaf(element) instanceof PsiErrorElement; + } } 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/codeInspection/ex/ProblemDescriptorImpl.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/ProblemDescriptorImpl.java index ff171fa13760..e80cbf8e61b8 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/ProblemDescriptorImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/ProblemDescriptorImpl.java @@ -87,7 +87,11 @@ public class ProblemDescriptorImpl extends CommonProblemDescriptorImpl implement assertPhysical(startElement); if (startElement != endElement) assertPhysical(endElement); - if (startElement.getTextRange().getStartOffset() >= endElement.getTextRange().getEndOffset()) { + final TextRange startElementRange = startElement.getTextRange(); + LOG.assertTrue(startElementRange != null, startElement); + final TextRange endElementRange = endElement.getTextRange(); + LOG.assertTrue(endElementRange != null, endElement); + if (startElementRange.getStartOffset() >= endElementRange.getEndOffset()) { if (!(startElement instanceof PsiFile && endElement instanceof PsiFile)) { LOG.error("Empty PSI elements should not be passed to createDescriptor. Start: " + startElement + ", end: " + endElement); } diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsViewComparator.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsViewComparator.java index b0b76948bf27..7fac178a6060 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsViewComparator.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsViewComparator.java @@ -141,7 +141,11 @@ public class InspectionResultsViewComparator implements Comparator { private static int compareEntity(final RefEntity entity, final PsiElement element) { if (entity instanceof RefElement) { - return PsiUtilCore.compareElementsByPosition(((RefElement)entity).getElement(), element); + final PsiElement psiElement = ((RefElement)entity).getElement(); + if (psiElement != null && element != null) { + return PsiUtilCore.compareElementsByPosition(psiElement, element); + } + if (element == null) return psiElement == null ? 0 : 1; } if (element instanceof PsiQualifiedNamedElement) { return StringUtil.compare(entity.getQualifiedName(), ((PsiQualifiedNamedElement)element).getQualifiedName(), true); 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/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/openapi/vcs/checkin/BeforeCheckinHandlerUtil.java b/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/BeforeCheckinHandlerUtil.java index 5a2c3d785530..6c88ae099f46 100644 --- a/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/BeforeCheckinHandlerUtil.java +++ b/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/BeforeCheckinHandlerUtil.java @@ -16,6 +16,7 @@ package com.intellij.openapi.vcs.checkin; import com.intellij.openapi.components.StorageScheme; +import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ex.ProjectEx; import com.intellij.openapi.roots.ProjectFileIndex; @@ -70,6 +71,10 @@ public class BeforeCheckinHandlerUtil { private static boolean isFileUnderSourceRoot(@NotNull Project project, @NotNull VirtualFile file) { ProjectFileIndex index = ProjectRootManager.getInstance(project).getFileIndex(); - return index.isInSource(file) && !index.isInLibrarySource(file); + if (StdFileTypes.JAVA == file.getFileType()) { + return index.isInSource(file) && !index.isInLibrarySource(file); + } else { + return index.isInContent(file) && !index.isInLibrarySource(file) ; + } } } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/DocumentCommitThread.java b/platform/lang-impl/src/com/intellij/psi/impl/DocumentCommitThread.java index 8ffa8b89fd4e..db88fb00b106 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/DocumentCommitThread.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/DocumentCommitThread.java @@ -31,6 +31,7 @@ import com.intellij.openapi.progress.util.ProgressIndicatorBase; import com.intellij.openapi.project.Project; import com.intellij.openapi.startup.StartupManager; import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.ex.ProgressIndicatorEx; import com.intellij.pom.PomManager; @@ -407,6 +408,12 @@ public class DocumentCommitThread implements Runnable, Disposable { catch (Exception e) { s += e; } + try { + Disposer.dispose(project); + } + catch (Throwable ignored) { + // do not fill log with endless exceptions + } throw new RuntimeException(s); } 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/fileTypes/ContentBasedClassFileProcessor.java b/platform/platform-api/src/com/intellij/openapi/fileTypes/ContentBasedClassFileProcessor.java index 595f3dc87d10..dee22ce81b6a 100644 --- a/platform/platform-api/src/com/intellij/openapi/fileTypes/ContentBasedClassFileProcessor.java +++ b/platform/platform-api/src/com/intellij/openapi/fileTypes/ContentBasedClassFileProcessor.java @@ -34,13 +34,4 @@ public interface ContentBasedClassFileProcessor extends ContentBasedFileSubstitu */ @NotNull SyntaxHighlighter createHighlighter(Project project, VirtualFile vFile); - - /** - * Returns decompiled PSI associated with this classfile - * - * @param clsFile instance of ClsFile - * @return decompiled PSI file - */ - @Nullable - PsiFile getDecompiledPsiFile(PsiFile clsFile); } diff --git a/platform/platform-api/src/com/intellij/ui/NonFocusableCheckBox.java b/platform/platform-api/src/com/intellij/ui/NonFocusableCheckBox.java index cd0bea52063d..34d40667e010 100644 --- a/platform/platform-api/src/com/intellij/ui/NonFocusableCheckBox.java +++ b/platform/platform-api/src/com/intellij/ui/NonFocusableCheckBox.java @@ -34,7 +34,7 @@ public class NonFocusableCheckBox extends JCheckBox { } private void initFocusability() { - if (!UISettings.getInstance().DISABLE_MNEMONICS_IN_CONTROLS) { // Or that won't be keyboard accessible at all + if (!UISettings.getShadowInstance().DISABLE_MNEMONICS_IN_CONTROLS) { // Or that won't be keyboard accessible at all setFocusable(false); } } diff --git a/platform/platform-api/src/com/intellij/util/ui/DialogUtil.java b/platform/platform-api/src/com/intellij/util/ui/DialogUtil.java index ea7670d384b2..27f0ac706660 100644 --- a/platform/platform-api/src/com/intellij/util/ui/DialogUtil.java +++ b/platform/platform-api/src/com/intellij/util/ui/DialogUtil.java @@ -53,7 +53,7 @@ public class DialogUtil{ } if (mnemonic != '\0') { button.setText(realText.toString()); - if (UISettings.getInstance().DISABLE_MNEMONICS_IN_CONTROLS) { + if (UISettings.getShadowInstance().DISABLE_MNEMONICS_IN_CONTROLS) { button.setMnemonic(0); button.setDisplayedMnemonicIndex(-1); button.setFocusable(true); @@ -93,7 +93,7 @@ public class DialogUtil{ } if (mnemonic != '\0') { label.setText(realText.toString()); - if (UISettings.getInstance().DISABLE_MNEMONICS_IN_CONTROLS) { + if (UISettings.getShadowInstance().DISABLE_MNEMONICS_IN_CONTROLS) { label.setDisplayedMnemonic(0); label.setDisplayedMnemonicIndex(-1); } 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/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/CaretModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java index 607b043b00b8..b297fd94ce71 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java @@ -110,7 +110,7 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener, DocumentBulkUpdateListener bulkUpdateListener = new DocumentBulkUpdateListener() { @Override public void updateStarted(@NotNull Document doc) { - if (doc != myEditor.getDocument() && myOffset >= doc.getTextLength()) return; + if (doc != myEditor.getDocument() && myOffset >= doc.getTextLength() || savedBeforeBulkCaretMarker != null) return; savedBeforeBulkCaretMarker = doc.createRangeMarker(myOffset, myOffset); } @Override @@ -237,7 +237,7 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener, } public void setIgnoreWrongMoves(boolean ignoreWrongMoves) { - this.myIgnoreWrongMoves = ignoreWrongMoves; + myIgnoreWrongMoves = ignoreWrongMoves; } @Override @@ -695,9 +695,8 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener, moveToOffset(newLength, performSoftWrapAdjustment); } else { - final int line; try { - line = event.translateLineViaDiff(myLogicalCaret.line); + final int line = event.translateLineViaDiff(myLogicalCaret.line); moveToLogicalPosition(new LogicalPosition(line, myLogicalCaret.column), performSoftWrapAdjustment, null, false); } catch (FilesTooBigForDiffException e1) { 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/RangeHighlighterTree.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/RangeHighlighterTree.java index 8a191e1b86bd..cd0947bc871f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/RangeHighlighterTree.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/RangeHighlighterTree.java @@ -44,19 +44,20 @@ public class RangeHighlighterTree extends RangeMarkerTree { @NotNull @Override protected RHNode createNewNode(@NotNull RangeHighlighterEx key, int start, int end, boolean greedyToLeft, boolean greedyToRight, int layer) { - return new RHNode(key, start, end, greedyToLeft, greedyToRight,layer); + return new RHNode(this, key, start, end, greedyToLeft, greedyToRight,layer); } - class RHNode extends RangeMarkerTree.RMNode { + static class RHNode extends RMNode { final int myLayer; - public RHNode(@NotNull final RangeHighlighterEx key, + public RHNode(@NotNull RangeHighlighterTree rangeMarkerTree, + @NotNull final RangeHighlighterEx key, int start, int end, boolean greedyToLeft, boolean greedyToRight, int layer) { - super(key, start, end, greedyToLeft, greedyToRight); + super(rangeMarkerTree, key, start, end, greedyToLeft, greedyToRight); myLayer = layer; } diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/encoding/EncodingProjectManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/encoding/EncodingProjectManagerImpl.java index 5e6b834c77ed..0d27f0cebe4e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/encoding/EncodingProjectManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/encoding/EncodingProjectManagerImpl.java @@ -36,6 +36,7 @@ import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.ModificationTracker; import com.intellij.openapi.vfs.*; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; @@ -65,6 +66,13 @@ public class EncodingProjectManagerImpl extends EncodingProjectManager { private boolean myUseUTFGuessing = true; private boolean myNative2AsciiForPropertiesFiles; private Charset myDefaultCharsetForPropertiesFiles; + private long myModificationCount; + private final ModificationTracker myModificationTracker = new ModificationTracker() { + @Override + public long getModificationCount() { + return myModificationCount; + } + }; public EncodingProjectManagerImpl(Project project, GeneralSettings generalSettings, EditorSettingsExternalizable editorSettings, PsiDocumentManager documentManager) { myProject = project; @@ -138,6 +146,7 @@ public class EncodingProjectManagerImpl extends EncodingProjectManager { myEditorSettings.migrateCharsetSettingsTo(defaultManager); } } + myModificationCount++; } @Override @@ -180,6 +189,10 @@ public class EncodingProjectManagerImpl extends EncodingProjectManager { return null; } + public ModificationTracker getModificationTracker() { + return myModificationTracker; + } + @Override public void setEncoding(@Nullable VirtualFile virtualFileOrDir, @Nullable Charset charset) { if (charset == null) { @@ -188,6 +201,7 @@ public class EncodingProjectManagerImpl extends EncodingProjectManager { else { myMapping.put(virtualFileOrDir, charset); } + myModificationCount++; setAndSaveOrReload(virtualFileOrDir, charset); } @@ -252,6 +266,7 @@ public class EncodingProjectManagerImpl extends EncodingProjectManager { } } } + myModificationCount++; } //retrieves encoding for the Project node diff --git a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml index 04707cc5ddfa..8c33091ef480 100644 --- a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml +++ b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml @@ -532,6 +532,8 @@ + diff --git a/platform/util/src/com/intellij/psi/codeStyle/NameUtil.java b/platform/util/src/com/intellij/psi/codeStyle/NameUtil.java index db3833081524..3993118425a1 100644 --- a/platform/util/src/com/intellij/psi/codeStyle/NameUtil.java +++ b/platform/util/src/com/intellij/psi/codeStyle/NameUtil.java @@ -264,8 +264,8 @@ public class NameUtil { continue; } - answer.add(compoundSuggestion(prefix, upperCaseStyle, words, wordCount, startWord, c, isArray, true) + suffix); answer.add(compoundSuggestion(prefix, upperCaseStyle, words, wordCount, startWord, c, isArray, false) + suffix); + answer.add(compoundSuggestion(prefix, upperCaseStyle, words, wordCount, startWord, c, isArray, true) + suffix); } return answer; } diff --git a/platform/util/src/com/intellij/util/io/PersistentHashMap.java b/platform/util/src/com/intellij/util/io/PersistentHashMap.java index 3b33caea1ed9..161c173ba62c 100644 --- a/platform/util/src/com/intellij/util/io/PersistentHashMap.java +++ b/platform/util/src/com/intellij/util/io/PersistentHashMap.java @@ -222,6 +222,9 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< if (fileSize > 5 * megabyte) { // file is longer than 5MB and (more than 50% of keys is garbage or approximate benefit larger than 100M) int liveKeys = (int)(myLiveAndGarbageKeysCounter / LIVE_KEY_MASK); int deadKeys = (int)(myLiveAndGarbageKeysCounter & 0xFFFFFFFF); + + if (deadKeys < 50) return false; + final int benefitSize = 100 * megabyte; final long avgValueSize = fileSize / (liveKeys + deadKeys); diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/CommittedChangesProvider.java b/platform/vcs-api/src/com/intellij/openapi/vcs/CommittedChangesProvider.java index 4a035ad82c81..5a5d11d9d8fd 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/CommittedChangesProvider.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/CommittedChangesProvider.java @@ -64,4 +64,6 @@ public interface CommittedChangesProvider getOneList(final VirtualFile file, final VcsRevisionNumber number) throws VcsException; + + RepositoryLocation getForNonLocal(final VirtualFile file); } diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/annotate/ShowAllAffectedGenericAction.java b/platform/vcs-api/src/com/intellij/openapi/vcs/annotate/ShowAllAffectedGenericAction.java index f8ae000b3b93..804a5b1ce008 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/annotate/ShowAllAffectedGenericAction.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/annotate/ShowAllAffectedGenericAction.java @@ -34,6 +34,8 @@ import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; +import java.util.List; + /** * @author irengrig * Date: 3/16/11 @@ -60,6 +62,7 @@ public class ShowAllAffectedGenericAction extends AnAction { public static void showSubmittedFiles(final Project project, final VcsRevisionNumber revision, final VirtualFile virtualFile, final VcsKey vcsKey) { final AbstractVcs vcs = ProjectLevelVcsManager.getInstance(project).findVcsByName(vcsKey.getName()); if (vcs == null) return; + if (! isInLocalFSHack(virtualFile) && ! canPresentNonLocal(project, vcsKey, virtualFile)) return; final String title = VcsBundle.message("paths.affected.in.revision", revision instanceof ShortVcsRevisionNumber @@ -71,9 +74,20 @@ public class ShowAllAffectedGenericAction extends AnAction { @Override public void run(@NotNull ProgressIndicator indicator) { try { - final Pair pair = vcs.getCommittedChangesProvider().getOneList(virtualFile, revision); - if (pair != null) { - list[0] = pair.getFirst(); + final CommittedChangesProvider provider = vcs.getCommittedChangesProvider(); + if (isInLocalFSHack(virtualFile)) { + final Pair pair = provider.getOneList(virtualFile, revision); + if (pair != null) { + list[0] = pair.getFirst(); + } + } else { + final RepositoryLocation local = provider.getForNonLocal(virtualFile); + if (local != null) { + final List changes = provider.getCommittedChanges(provider.createDefaultSettings(), local, 1); + if (changes != null && changes.size() == 1) { + list[0] = changes.get(0); + } + } } } catch (VcsException e) { @@ -95,6 +109,12 @@ public class ShowAllAffectedGenericAction extends AnAction { }); } + private static boolean isInLocalFSHack(final VirtualFile vf) { + if (vf.isInLocalFileSystem()) return true; + final String url = vf.getPresentableUrl(); + return ! url.contains("://") && ! url.contains(":\\\\"); + } + private static String failedText(VirtualFile virtualFile, VcsRevisionNumber revision) { return "Show all affected files for " + virtualFile.getPath() + " at " + revision.asString() + " failed"; } @@ -108,6 +128,16 @@ public class ShowAllAffectedGenericAction extends AnAction { return; } final VirtualFile revisionVirtualFile = e.getData(VcsDataKeys.VCS_VIRTUAL_FILE); - e.getPresentation().setEnabled((e.getData(VcsDataKeys.VCS_FILE_REVISION) != null) && (revisionVirtualFile != null)); + boolean enabled = (e.getData(VcsDataKeys.VCS_FILE_REVISION) != null) && (revisionVirtualFile != null); + enabled = enabled && (isInLocalFSHack(revisionVirtualFile) || canPresentNonLocal(project, vcsKey, revisionVirtualFile)); + e.getPresentation().setEnabled(enabled); + } + + private static boolean canPresentNonLocal(Project project, VcsKey key, final VirtualFile file) { + final AbstractVcs vcs = ProjectLevelVcsManager.getInstance(project).findVcsByName(key.getName()); + if (vcs == null) return false; + final CommittedChangesProvider provider = vcs.getCommittedChangesProvider(); + if (provider == null) return false; + return provider.getForNonLocal(file) != null; } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CompositeCommittedChangesProvider.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CompositeCommittedChangesProvider.java index 7f7702a55834..b6a7370ff14f 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CompositeCommittedChangesProvider.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CompositeCommittedChangesProvider.java @@ -161,6 +161,11 @@ public class CompositeCommittedChangesProvider implements CommittedChangesProvid throw new UnsupportedOperationException(); } + @Override + public RepositoryLocation getForNonLocal(VirtualFile file) { + throw new UnsupportedOperationException(); + } + public static class CompositeChangeBrowserSettings extends ChangeBrowserSettings { private final Map myMap; private final Set myEnabledVcs = new HashSet(); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesTreeList.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesTreeList.java index 92ab2a6c428d..9afdb600452b 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesTreeList.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesTreeList.java @@ -299,6 +299,7 @@ public abstract class ChangesTreeList extends JPanel { } }); + final Set wasSelected = new HashSet(Arrays.asList(myList.getSelectedValues())); myList.setModel(new AbstractListModel() { @Override public int getSize() { @@ -310,6 +311,12 @@ public abstract class ChangesTreeList extends JPanel { return sortedChanges.get(index); } }); + for (int i = 0; i < sortedChanges.size(); i++) { + T t = sortedChanges.get(i); + if (wasSelected.contains(t)) { + myList.setSelectedIndex(i); + } + } final DefaultTreeModel model = buildTreeModel(changes, myChangeDecorator); TreeState state = null; diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/history/FileHistoryPanelImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/history/FileHistoryPanelImpl.java index 008a1ad75491..5b7f7eea5286 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/history/FileHistoryPanelImpl.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/history/FileHistoryPanelImpl.java @@ -642,6 +642,7 @@ public class FileHistoryPanelImpl extends PanelWithActionsAndCloseButton { VcsHistoryUtil.showDiff(project, myFilePath, left, right, leftTitle, rightTitle); } catch (final VcsException e) { + LOG.info(e); WaitForProgressToShow.runOrInvokeLaterAboveProgress(new Runnable() { public void run() { Messages.showErrorDialog(VcsBundle.message("message.text.cannot.show.differences", e.getLocalizedMessage()), @@ -650,7 +651,7 @@ public class FileHistoryPanelImpl extends PanelWithActionsAndCloseButton { }, null, project); } catch (IOException e) { - LOG.error(e); + LOG.info(e); } catch (ProcessCanceledException ex) { LOG.info(ex); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XFramesView.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XFramesView.java index 91f31c4a3886..866eb1a4bee9 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XFramesView.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XFramesView.java @@ -92,7 +92,6 @@ public class XFramesView extends XDebugViewBase { CustomLineBorder border = new CustomLineBorder(CaptionPanel.CNT_ACTIVE_COLOR, 0, 0, 1, 0); myThreadsPanel.setBorder(border); myThreadsPanel.add(myToolbar.getComponent(), BorderLayout.EAST); - myThreadsPanel.add(myThreadComboBox, BorderLayout.CENTER); myMainPanel.add(myThreadsPanel, BorderLayout.NORTH); rebuildView(SessionEvent.RESUMED); @@ -155,12 +154,10 @@ public class XFramesView extends XDebugViewBase { } XExecutionStack activeExecutionStack = suspendContext.getActiveExecutionStack(); myThreadComboBox.setSelectedItem(activeExecutionStack); - final boolean invisible = executionStacks.length == 1 && StringUtil.isEmpty(executionStacks[0].getDisplayName()); myThreadsPanel.removeAll(); - if (invisible) { - myThreadsPanel.add(myToolbar.getComponent(), BorderLayout.WEST); - } else { - myThreadsPanel.add(myToolbar.getComponent(), BorderLayout.EAST); + myThreadsPanel.add(myToolbar.getComponent(), BorderLayout.EAST); + final boolean invisible = executionStacks.length == 1 && StringUtil.isEmpty(executionStacks[0].getDisplayName()); + if (!invisible) { myThreadsPanel.add(myThreadComboBox, BorderLayout.CENTER); } myToolbar.setAddSeparatorFirst(!invisible); diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnqualifiedFieldAccessInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnqualifiedFieldAccessInspection.java index e89e21c45978..0de37c8ed3df 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnqualifiedFieldAccessInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnqualifiedFieldAccessInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2011 Bas Leijdekkers + * Copyright 2006-201@ Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -73,6 +73,10 @@ public class UnqualifiedFieldAccessInspection extends BaseInspection { if (field.hasModifierProperty(PsiModifier.STATIC)) { return; } + final PsiClass containingClass = field.getContainingClass(); + if (containingClass instanceof PsiAnonymousClass) { + return; + } registerError(expression); } } diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnqualifiedMethodAccessInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnqualifiedMethodAccessInspection.java index 12ceb5425306..2d54bc48f77f 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnqualifiedMethodAccessInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnqualifiedMethodAccessInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2011 Bas Leijdekkers + * Copyright 2006-2012 Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -68,6 +68,10 @@ public class UnqualifiedMethodAccessInspection extends BaseInspection { if (method.isConstructor() || method.hasModifierProperty(PsiModifier.STATIC)) { return; } + final PsiClass containingClass = method.getContainingClass(); + if (containingClass instanceof PsiAnonymousClass) { + return; + } registerError(expression); } } diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unqualified_field_access/UnqualifiedFieldAccess.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unqualified_field_access/UnqualifiedFieldAccess.java index c74a6852d584..6c7518d8d83b 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unqualified_field_access/UnqualifiedFieldAccess.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unqualified_field_access/UnqualifiedFieldAccess.java @@ -9,4 +9,17 @@ public class UnqualifiedFieldAccess { final String s = String.valueOf(field.hashCode()); System.out.println(s); } + + void foo() { + new Object() { + int i; + void foo() { + new Object() { + void foo() { + i = 0; + } + }; + } + }; + } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unqualified_method_access/UnqualifiedMethodAccess.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unqualified_method_access/UnqualifiedMethodAccess.java index 0e3b456c86c5..0e626f3fe31d 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unqualified_method_access/UnqualifiedMethodAccess.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unqualified_method_access/UnqualifiedMethodAccess.java @@ -15,4 +15,16 @@ public class UnqualifiedMethodAccess extends JPanel { void foo(String s) { this.foo(); } + + void anonymous() { + new Object() { + void bar() { + new Object() { + void foo() { + bar(); + } + }; + } + }; + } } diff --git a/plugins/android-designer/android-designer.iml b/plugins/android-designer/android-designer.iml index a6cb9856732d..dc07d072b1ba 100644 --- a/plugins/android-designer/android-designer.iml +++ b/plugins/android-designer/android-designer.iml @@ -24,6 +24,7 @@ + diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/AndroidDesignerEditorPanel.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/AndroidDesignerEditorPanel.java index 37a1ba1643e7..216709a18dc3 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/designSurface/AndroidDesignerEditorPanel.java +++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/AndroidDesignerEditorPanel.java @@ -40,6 +40,7 @@ import com.intellij.openapi.module.Module; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Condition; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiErrorElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; import com.intellij.psi.xml.XmlFile; @@ -56,7 +57,6 @@ import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; -import java.awt.image.BufferedImage; import java.util.List; /** @@ -137,6 +137,8 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel { parser.updateRootComponent(mySession, rootView); RadViewComponent newRootComponent = parser.getRootComponent(); + newRootComponent.setClientProperty(ModelParser.XML_FILE_KEY, myXmlFile); + PropertyParser propertyParser = new PropertyParser(myModule, myProfileAction.getProfileManager().getSelectedTarget()); newRootComponent.setClientProperty(PropertyParser.KEY, propertyParser); propertyParser.loadRecursive(newRootComponent); @@ -158,7 +160,10 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel { final String layoutXmlText = ApplicationManager.getApplication().runReadAction(new Computable() { @Override public String compute() { - return myXmlFile.getText(); + if (ModelParser.checkTag(myXmlFile.getRootTag())) { + return myXmlFile.getText(); + } + return ModelParser.NO_ROOT_CONTENT; } }); createRenderer(layoutXmlText, new ThrowableRunnable() { @@ -387,27 +392,4 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel { myPSIChangeListener.start(); } } - - private static class RootView extends JComponent { - private int myX; - private int myY; - private BufferedImage myImage; - - public RootView(BufferedImage image, int x, int y) { - myX = x; - myY = y; - setImage(image); - } - - public void setImage(BufferedImage image) { - myImage = image; - setBounds(myX, myY, image.getWidth(), image.getHeight()); - } - - @Override - public void paintComponent(Graphics g) { - super.paintComponent(g); - g.drawImage(myImage, 0, 0, null); - } - } } \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/DropToOperation.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/DropToOperation.java new file mode 100644 index 000000000000..3ccb4f968921 --- /dev/null +++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/DropToOperation.java @@ -0,0 +1,88 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.android.designer.designSurface; + +import com.intellij.android.designer.model.ModelParser; +import com.intellij.android.designer.model.RadViewComponent; +import com.intellij.designer.designSurface.EditOperation; +import com.intellij.designer.designSurface.FeedbackLayer; +import com.intellij.designer.designSurface.OperationContext; +import com.intellij.designer.designSurface.feedbacks.AlphaComponent; +import com.intellij.designer.model.RadComponent; + +import javax.swing.*; +import java.awt.*; +import java.util.Collections; +import java.util.List; + +/** + * @author Alexander Lobas + */ +public class DropToOperation implements EditOperation { + private final RadViewComponent myContainer; + private final OperationContext myContext; + private List myComponents; + private JComponent myFeedback; + + public DropToOperation(RadViewComponent container, OperationContext context) { + myContainer = container; + myContext = context; + } + + @Override + public void setComponent(RadComponent component) { + myComponents = Collections.singletonList(component); + } + + @Override + public void setComponents(List components) { + myComponents = components; + } + + @Override + public void showFeedback() { + FeedbackLayer layer = myContext.getArea().getFeedbackLayer(); + + if (myFeedback == null) { + myFeedback = new AlphaComponent(Color.green); + layer.add(myFeedback); + myFeedback.setBounds(myContainer.getBounds(layer)); + layer.repaint(); + } + } + + @Override + public void eraseFeedback() { + if (myFeedback != null) { + FeedbackLayer layer = myContext.getArea().getFeedbackLayer(); + layer.remove(myFeedback); + layer.repaint(); + myFeedback = null; + } + } + + @Override + public boolean canExecute() { + return true; + } + + @Override + public void execute() throws Exception { + for (RadComponent component : myComponents) { + ModelParser.addComponent(myContainer, (RadViewComponent)component, null); + } + } +} \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/RootView.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/RootView.java new file mode 100644 index 000000000000..acc95d5610da --- /dev/null +++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/RootView.java @@ -0,0 +1,75 @@ +/* + * 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.android.designer.designSurface; + +import javax.swing.*; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Alexander Lobas + */ +public class RootView extends JComponent { + private int myX; + private int myY; + private BufferedImage myImage; + private List myEmptyRegions; + + public RootView(BufferedImage image, int x, int y) { + myX = x; + myY = y; + setImage(image); + } + + public void setImage(BufferedImage image) { + myImage = image; + myEmptyRegions = new ArrayList(); + setBounds(myX, myY, image.getWidth(), image.getHeight()); + } + + public void addEmptyRegion(int x, int y, int width, int height) { + if (new Rectangle(0, 0, myImage.getWidth(), myImage.getHeight()).contains(x, y)) { + EmptyRegion r = new EmptyRegion(); + r.myX = x; + r.myY = y; + r.myWidth = width; + r.myHeight = height; + r.myColor = new Color(~myImage.getRGB(x, y)); + myEmptyRegions.add(r); + } + } + + @Override + public void paintComponent(Graphics g) { + super.paintComponent(g); + g.drawImage(myImage, 0, 0, null); + + for (EmptyRegion r : myEmptyRegions) { + g.setColor(r.myColor); + g.fillRect(r.myX, r.myY, r.myWidth, r.myHeight); + } + } + + private static class EmptyRegion { + public Color myColor; + public int myX; + public int myY; + public int myWidth; + public int myHeight; + } +} \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/designSurface/TreeDropToOperation.java b/plugins/android-designer/src/com/intellij/android/designer/designSurface/TreeDropToOperation.java new file mode 100644 index 000000000000..80fd38068843 --- /dev/null +++ b/plugins/android-designer/src/com/intellij/android/designer/designSurface/TreeDropToOperation.java @@ -0,0 +1,36 @@ +/* + * 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.android.designer.designSurface; + +import com.intellij.android.designer.model.ModelParser; +import com.intellij.android.designer.model.RadViewComponent; +import com.intellij.designer.componentTree.TreeEditOperation; +import com.intellij.designer.designSurface.OperationContext; +import com.intellij.designer.model.RadComponent; + +/** + * @author Alexander Lobas + */ +public class TreeDropToOperation extends TreeEditOperation { + public TreeDropToOperation(RadComponent host, OperationContext context) { + super(host, context); + } + + @Override + protected void execute(RadComponent insertBefore) throws Exception { + ModelParser.addComponent((RadViewComponent)myHost, (RadViewComponent)myComponents.get(0), (RadViewComponent)insertBefore); + } +} \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/ModelParser.java b/plugins/android-designer/src/com/intellij/android/designer/model/ModelParser.java index fa4a6a9692a5..020a3f689bdd 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/model/ModelParser.java +++ b/plugins/android-designer/src/com/intellij/android/designer/model/ModelParser.java @@ -17,6 +17,7 @@ package com.intellij.android.designer.model; import com.android.ide.common.rendering.api.RenderSession; import com.android.ide.common.rendering.api.ViewInfo; +import com.intellij.android.designer.designSurface.RootView; import com.intellij.designer.model.MetaManager; import com.intellij.designer.model.MetaModel; import com.intellij.designer.model.RadComponent; @@ -26,10 +27,14 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiErrorElement; import com.intellij.psi.XmlElementFactory; import com.intellij.psi.XmlRecursiveElementVisitor; import com.intellij.psi.xml.XmlFile; import com.intellij.psi.xml.XmlTag; +import com.intellij.xml.util.XmlUtil; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.util.List; @@ -38,6 +43,13 @@ import java.util.List; * @author Alexander Lobas */ public class ModelParser extends XmlRecursiveElementVisitor { + public static final String NO_ROOT_CONTENT = + ""; + + public static final String XML_FILE_KEY = "XML_FILE"; + + private static final int EMPTY_COMPONENT_SIZE = 5; + private final MetaManager myMetaManager; private final XmlFile myXmlFile; private RadViewComponent myRootComponent; @@ -61,11 +73,11 @@ public class ModelParser extends XmlRecursiveElementVisitor { @Override public String compute() { XmlTag root = myXmlFile.getRootTag(); - if (root != null) { + if (checkTag(root)) { root.accept(ModelParser.this); + return myXmlFile.getText(); } - - return myXmlFile.getText(); + return NO_ROOT_CONTENT; } }); } @@ -111,19 +123,58 @@ public class ModelParser extends XmlRecursiveElementVisitor { return component; } + public static void addComponent(RadViewComponent container, RadViewComponent newComponent, @Nullable RadViewComponent insertBefore) + throws Exception { + newComponent.setParent(container); + + List children = container.getChildren(); + if (insertBefore == null) { + children.add(newComponent); + } + else { + children.add(children.indexOf(insertBefore), newComponent); + } + + setComponentTag(container.getTag(), newComponent, insertBefore == null ? null : insertBefore.getTag()); + + PropertyParser propertyParser = container.getRoot().getClientProperty(PropertyParser.KEY); + propertyParser.load(newComponent); + } + public static void setComponentTag(final XmlTag parentTag, final RadViewComponent component, final XmlTag nextTag) { ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override public void run() { - Language language = StdFileTypes.XML.getLanguage(); - XmlTag xmlTag = - XmlElementFactory.getInstance(parentTag.getProject()).createTagFromText(component.getMetaModel().getCreation(), language); + Project project; + RadViewComponent root = null; + XmlFile xmlFile = null; - if (nextTag == null) { - xmlTag = parentTag.addSubTag(xmlTag, false); + if (!checkTag(parentTag) && component.getParent() == component.getRoot()) { + root = (RadViewComponent)component.getParent(); + xmlFile = root.getClientProperty(XML_FILE_KEY); + project = xmlFile.getProject(); } else { - xmlTag = (XmlTag)parentTag.addBefore(xmlTag, nextTag); + project = parentTag.getProject(); + } + + Language language = StdFileTypes.XML.getLanguage(); + XmlTag xmlTag = + XmlElementFactory.getInstance(project).createTagFromText("\n" + component.getMetaModel().getCreation(), language); + + if (checkTag(parentTag)) { + if (nextTag == null) { + xmlTag = parentTag.addSubTag(xmlTag, false); + } + else { + xmlTag = (XmlTag)parentTag.addBefore(xmlTag, nextTag); + } + } + else { + xmlTag.setAttribute("xmlns:android", "http://schemas.android.com/apk/res/android"); + xmlTag = (XmlTag)xmlFile.getDocument().add(xmlTag); + root.setTag(xmlFile.getDocument().getRootTag()); + XmlUtil.expandTag(xmlTag); } component.setTag(xmlTag); @@ -131,6 +182,15 @@ public class ModelParser extends XmlRecursiveElementVisitor { }); } + public static boolean checkTag(XmlTag tag) { + try { + return tag != null && tag.getFirstChild() != null && !(tag.getFirstChild() instanceof PsiErrorElement) && tag.getProject() != null; + } + catch (Throwable e) { + return false; + } + } + ////////////////////////////////////////////////////////////////////////////////////////// // // @@ -145,27 +205,26 @@ public class ModelParser extends XmlRecursiveElementVisitor { return myLayoutXmlText; } - public void updateRootComponent(RenderSession session, JComponent nativeComponent) throws Exception { - RadViewComponent rootComponent = myRootComponent; - - if (session.getRootViews().size() == 1) { - RadViewComponent newRootComponent = createComponent(myXmlFile.getRootTag(), myMetaManager.getModelByTag("")); - - rootComponent.setParent(newRootComponent); - newRootComponent.getChildren().add(rootComponent); - - myRootComponent = rootComponent = newRootComponent; + public void updateRootComponent(RenderSession session, RootView nativeComponent) throws Exception { + if (myRootComponent == null) { + myRootComponent = createComponent(myXmlFile.getRootTag(), myMetaManager.getModelByTag("")); + } + else if (session.getRootViews().size() == 1) { + RadViewComponent rootComponent = myRootComponent; + myRootComponent = createComponent(myXmlFile.getRootTag(), myMetaManager.getModelByTag("")); + myRootComponent.getChildren().add(rootComponent); + rootComponent.setParent(myRootComponent); } - updateRootComponent(rootComponent, session, nativeComponent); + updateRootComponent(myRootComponent, session, nativeComponent); } public static void updateRootComponent(RadViewComponent rootComponent, RenderSession session, - JComponent nativeComponent) { + RootView nativeComponent) { List views = session.getRootViews(); - int size = views.size(); List children = rootComponent.getChildren(); + int size = children.size(); for (int i = 0; i < size; i++) { updateComponent((RadViewComponent)children.get(i), views.get(i), nativeComponent, 0, 0); } @@ -176,7 +235,7 @@ public class ModelParser extends XmlRecursiveElementVisitor { private static void updateComponent(RadViewComponent component, ViewInfo view, - JComponent nativeComponent, + RootView nativeComponent, int parentX, int parentY) { component.setViewInfo(view); @@ -184,11 +243,18 @@ public class ModelParser extends XmlRecursiveElementVisitor { int left = parentX + view.getLeft(); int top = parentY + view.getTop(); - component.setBounds(left, top, view.getRight() - view.getLeft(), view.getBottom() - view.getTop()); + int width = view.getRight() - view.getLeft(); + int height = view.getBottom() - view.getTop(); + + if (width < EMPTY_COMPONENT_SIZE && height < EMPTY_COMPONENT_SIZE) { + nativeComponent.addEmptyRegion(left, top, EMPTY_COMPONENT_SIZE, EMPTY_COMPONENT_SIZE); + } + + component.setBounds(left, top, Math.max(width, EMPTY_COMPONENT_SIZE), Math.max(height, EMPTY_COMPONENT_SIZE)); List views = view.getChildren(); List children = component.getChildren(); - int size = views.size(); + int size = children.size(); for (int i = 0; i < size; i++) { updateComponent((RadViewComponent)children.get(i), views.get(i), nativeComponent, left, top); diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/RadLinearLayout.java b/plugins/android-designer/src/com/intellij/android/designer/model/RadLinearLayout.java index 7edb1f0b4213..e6cbf4533c44 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/model/RadLinearLayout.java +++ b/plugins/android-designer/src/com/intellij/android/designer/model/RadLinearLayout.java @@ -40,22 +40,7 @@ public class RadLinearLayout extends RadViewLayout { } private void addNewComponent(RadViewComponent newComponent, @Nullable RadViewComponent insertBefore) throws Exception { - RadViewComponent container = (RadViewComponent)myContainer; - newComponent.setParent(container); - - List children = container.getChildren(); - if (insertBefore == null) { - children.add(newComponent); - } - else { - children.add(children.indexOf(insertBefore), newComponent); - } - - ModelParser - .setComponentTag(container.getTag(), newComponent, insertBefore == null ? null : insertBefore.getTag()); - - PropertyParser propertyParser = container.getRoot().getClientProperty(PropertyParser.KEY); - propertyParser.load(newComponent); + ModelParser.addComponent((RadViewComponent)myContainer, newComponent, insertBefore); } private class TreeCreateOperation extends TreeEditOperation { diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/RadRootViewLayout.java b/plugins/android-designer/src/com/intellij/android/designer/model/RadRootViewLayout.java new file mode 100644 index 000000000000..58cb437d055a --- /dev/null +++ b/plugins/android-designer/src/com/intellij/android/designer/model/RadRootViewLayout.java @@ -0,0 +1,38 @@ +/* + * 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.android.designer.model; + +import com.intellij.android.designer.designSurface.DropToOperation; +import com.intellij.android.designer.designSurface.TreeDropToOperation; +import com.intellij.designer.designSurface.EditOperation; +import com.intellij.designer.designSurface.OperationContext; + +/** + * @author Alexander Lobas + */ +public class RadRootViewLayout extends RadViewLayout { + @Override + public EditOperation processChildOperation(OperationContext context) { + if (myContainer.getChildren().isEmpty() && (context.isCreate() || context.isPaste()) && context.getComponents().size() == 1) { + if (context.isTree()) { + return new TreeDropToOperation(myContainer, context); + } + return new DropToOperation((RadViewComponent)myContainer, context); + } + + return null; + } +} \ No newline at end of file diff --git a/plugins/android-designer/src/com/intellij/android/designer/model/views-meta-model.xml b/plugins/android-designer/src/com/intellij/android/designer/model/views-meta-model.xml index 7918b73cf229..8cdf52ed49a1 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/model/views-meta-model.xml +++ b/plugins/android-designer/src/com/intellij/android/designer/model/views-meta-model.xml @@ -5,15 +5,17 @@ + layout="com.intellij.android.designer.model.RadRootViewLayout" + tag="<root>" + delete="false"> + tag="merge" + delete="false"> diff --git a/plugins/android-designer/src/com/intellij/android/designer/propertyTable/editors/ResourceDialog.java b/plugins/android-designer/src/com/intellij/android/designer/propertyTable/editors/ResourceDialog.java index af914b52de7a..350ca69a65e1 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/propertyTable/editors/ResourceDialog.java +++ b/plugins/android-designer/src/com/intellij/android/designer/propertyTable/editors/ResourceDialog.java @@ -83,6 +83,9 @@ public class ResourceDialog extends DialogWrapper implements TreeSelectionListen myContentPanel.addTab("Project", myProjectPanel.myComponent); myContentPanel.addTab("System", mySystemPanel.myComponent); + myProjectPanel.myTreeBuilder.expandAll(null); + mySystemPanel.myTreeBuilder.expandAll(null); + myContentPanel.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/changeBrowser/CvsCommittedChangesProvider.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/changeBrowser/CvsCommittedChangesProvider.java index 7a7904a04683..d5eaf4db6a21 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/changeBrowser/CvsCommittedChangesProvider.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/changeBrowser/CvsCommittedChangesProvider.java @@ -207,6 +207,11 @@ public class CvsCommittedChangesProvider implements CachingCommittedChangesProvi return new Pair(result.get(), filePath); } + @Override + public RepositoryLocation getForNonLocal(VirtualFile file) { + return null; + } + public List getCommittedChanges(ChangeBrowserSettings settings, RepositoryLocation location, final int maxCount) throws VcsException { final CvsRepositoryLocation cvsLocation = (CvsRepositoryLocation) location; diff --git a/plugins/git4idea/src/git4idea/changes/GitCommittedChangeListProvider.java b/plugins/git4idea/src/git4idea/changes/GitCommittedChangeListProvider.java index 439afdf1fa62..a6ce3954f6cb 100644 --- a/plugins/git4idea/src/git4idea/changes/GitCommittedChangeListProvider.java +++ b/plugins/git4idea/src/git4idea/changes/GitCommittedChangeListProvider.java @@ -266,6 +266,11 @@ public class GitCommittedChangeListProvider implements CommittedChangesProvider< return new Pair(commit, ((GitFileRevision) history.get(history.size() - 1)).getPath()); } + @Override + public RepositoryLocation getForNonLocal(VirtualFile file) { + return null; + } + public int getFormatVersion() { return 0; } 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/hg4idea/src/org/zmlx/hg4idea/provider/HgCachingCommitedChangesProvider.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCachingCommitedChangesProvider.java index 2356f8afd93f..2a16ca883658 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCachingCommitedChangesProvider.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCachingCommitedChangesProvider.java @@ -286,4 +286,9 @@ public class HgCachingCommitedChangesProvider } return null; } + + @Override + public RepositoryLocation getForNonLocal(VirtualFile file) { + return null; + } } 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 8fd863215ef6..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"))) { 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/wizards/MavenAddArchetypeDialog.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenAddArchetypeDialog.java index 8dc80a92e6f5..66d35185a88e 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenAddArchetypeDialog.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenAddArchetypeDialog.java @@ -35,7 +35,7 @@ public class MavenAddArchetypeDialog extends DialogWrapper { public MavenAddArchetypeDialog(Component parent) { super(parent, false); - setTitle("Add archetype"); + setTitle("Add Archetype"); init(); 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/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java index 3e25901512c5..50f35abf515b 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java @@ -556,17 +556,22 @@ public class SvnVcs extends AbstractVcs { } private void createPool() { + if (myPool != null) return; final String property = System.getProperty(KEEP_CONNECTIONS_KEY); final boolean keep; if (StringUtil.isEmptyOrSpaces(property)) { - keep = ! ApplicationManager.getApplication().isUnitTestMode(); // default + keep = !ApplicationManager.getApplication().isUnitTestMode(); // default } else { keep = Boolean.getBoolean(KEEP_CONNECTIONS_KEY); } myPool = new DefaultSVNRepositoryPool(myConfiguration.getAuthenticationManager(this), myConfiguration.getOptions(myProject), 60*1000, keep); } + @NotNull private ISVNRepositoryPool getPool() { + if (myPool == null) { + createPool(); + } return myPool; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CopiesPanel.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CopiesPanel.java index 1255ace19796..fd7c1b22761f 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CopiesPanel.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CopiesPanel.java @@ -86,18 +86,22 @@ public class CopiesPanel { myCurrentInfoList = null; final Runnable focus = new Runnable() { + @Override public void run() { IdeFocusManager.getInstance(myProject).requestFocus(myRefreshLabel, true); } }; final Runnable refreshView = new Runnable() { + @Override public void run() { final List infoList = myVcs.getAllWcInfos(); Runnable runnable = new Runnable() { + @Override public void run() { if (myCurrentInfoList != null) { final List> newList = ObjectsConvertor.convert(infoList, new Convertor>() { + @Override public OverrideEqualsWrapper convert(WCInfo o) { return new OverrideEqualsWrapper(InfoEqualityPolicy.getInstance(), o); } @@ -119,8 +123,14 @@ public class CopiesPanel { } }; final Runnable refreshOnPooled = new Runnable() { + @Override public void run() { - ApplicationManager.getApplication().executeOnPooledThread(refreshView); + if (ApplicationManager.getApplication().isUnitTestMode()) { + refreshView.run(); + } + else { + ApplicationManager.getApplication().executeOnPooledThread(refreshView); + } } }; myConnection.subscribe(SvnVcs.ROOTS_RELOADED, refreshOnPooled); @@ -133,6 +143,7 @@ public class CopiesPanel { panel.add(myPanel, BorderLayout.NORTH); holderPanel.add(panel, BorderLayout.WEST); myRefreshLabel = new MyLinkLabel(myTextHeight, "Refresh", new LinkListener() { + @Override public void linkSelected(LinkLabel aSource, Object aLinkData) { if (myRefreshLabel.isEnabled()) { myVcs.invokeRefreshSvnRoots(true); @@ -280,6 +291,7 @@ public class CopiesPanel { private void mergeFrom(final WCInfo wcInfo, final VirtualFile root, final Component mergeLabel) { SelectBranchPopup.showForBranchRoot(myProject, root, new SelectBranchPopup.BranchSelectedCallback() { + @Override public void branchSelected(Project project, SvnBranchConfigurationNew configuration, String url, long revision) { new QuickMerge(project, url, wcInfo, SVNPathUtil.tail(url), root).execute(); } @@ -393,6 +405,7 @@ public class CopiesPanel { } } + @Override public int getHashCode(WCInfo value) { final HashCodeBuilder builder = new HashCodeBuilder(); builder.append(value.getPath()); @@ -404,6 +417,7 @@ public class CopiesPanel { return builder.getCode(); } + @Override public boolean isEqual(WCInfo val1, WCInfo val2) { if (val1 == val2) return true; if (val1 == null || val2 == null || val1.getClass() != val2.getClass()) return false; @@ -425,6 +439,7 @@ public class CopiesPanel { return ourComparator; } + @Override public int compare(WCInfo o1, WCInfo o2) { return o1.getPath().compareTo(o2.getPath()); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java index b69913b752db..f1165d66d5e2 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java @@ -25,6 +25,7 @@ import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vcs.*; import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vcs.changes.ContentRevision; @@ -33,6 +34,7 @@ import com.intellij.openapi.vcs.history.VcsRevisionNumber; import com.intellij.openapi.vcs.versionBrowser.ChangeBrowserSettings; import com.intellij.openapi.vcs.versionBrowser.ChangesBrowserSettingsEditor; import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList; +import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.AsynchConsumer; import com.intellij.util.Consumer; @@ -563,6 +565,12 @@ public class SvnCommittedChangesProvider implements CachingCommittedChangesProvi return new Pair(result[0], new FilePathImpl(file)); } + @Override + public RepositoryLocation getForNonLocal(VirtualFile file) { + final String url = file.getPresentableUrl(); + return new SvnRepositoryLocation(FileUtil.toSystemIndependentName(url)); + } + private static class RenameContext { @NotNull private String myCurrentPath; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java index 85e799818441..ae4d715969ea 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java @@ -619,10 +619,10 @@ public class SvnHistoryProvider implements VcsHistoryProvider, VcsCacheableHisto super(vcs, url, pegRevision, lastPath, result, repoRootURL, null); } - @Override + /*@Override protected SvnFileRevision createRevision(final SVNLogEntry logEntry, final String copyPath) { return new SvnFileRevision(myVcs, SVNRevision.UNDEFINED, logEntry, myUrl, copyPath, null); - } + }*/ } private class MergeSourceColumnInfo extends ColumnInfo { diff --git a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGRunnableState.java b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGRunnableState.java index 314b5729fa97..8a64a074f259 100644 --- a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGRunnableState.java +++ b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGRunnableState.java @@ -246,9 +246,10 @@ public class TestNGRunnableState extends JavaCommandLineState { LOG.info("Language level is " + effectiveLanguageLevel.toString()); LOG.info("is15 is " + is15); final String pathToBundledJar = PathUtil.getJarPathForClass(AfterClass.class); - final String incompatibilityMessage = TestNGVersionChecker - .getVersionIncompatibilityMessage(project, config.getPersistantData().getScope().getSourceScope(config).getLibrariesScope(), - pathToBundledJar); + final SourceScope sourceScope = config.getPersistantData().getScope().getSourceScope(config); + final String incompatibilityMessage = sourceScope != null ? + TestNGVersionChecker.getVersionIncompatibilityMessage(project, sourceScope.getLibrariesScope(), pathToBundledJar) : + null; if (incompatibilityMessage != null) { javaParameters.getClassPath().add(pathToBundledJar); } diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/model/MetaManager.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/model/MetaManager.java index 95e6a6ec50fe..345eb76b2663 100644 --- a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/model/MetaManager.java +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/model/MetaManager.java @@ -92,6 +92,11 @@ public abstract class MetaManager { meta.setLayout((Class)classLoader.loadClass(layout)); } + String delete = element.getAttributeValue("delete"); + if (delete != null) { + meta.setDelete(Boolean.parseBoolean(delete)); + } + Element presentation = element.getChild("presentation"); if (presentation != null) { meta.setPresentation(presentation.getAttributeValue("title"), presentation.getAttributeValue("icon")); 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 399439f46fc9..8fea8ebad914 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 @@ -36,6 +36,7 @@ public class MetaModel { private String myIconPath; private Icon myIcon; private String myCreation; + private boolean myDelete = true; private List myNormalProperties = Collections.emptyList(); private List myImportantProperties = Collections.emptyList(); private List myExpertProperties = Collections.emptyList(); @@ -75,6 +76,14 @@ public class MetaModel { myCreation = creation; } + public boolean canDelete() { + return myDelete; + } + + public void setDelete(boolean delete) { + myDelete = delete; + } + public String getTitle() { return myTitle; } diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/model/RadComponent.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/model/RadComponent.java index c84a5b97aa3c..05ed077f0b91 100644 --- a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/model/RadComponent.java +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/model/RadComponent.java @@ -175,7 +175,7 @@ public abstract class RadComponent { ////////////////////////////////////////////////////////////////////////////////////////// public boolean canDelete() { - return true; + return myMetaModel == null || myMetaModel.canDelete(); } public void delete() throws Exception { diff --git a/resources/src/idea/RichPlatformPlugin.xml b/resources/src/idea/RichPlatformPlugin.xml index 7ebbc00918b9..950b924e7452 100644 --- a/resources/src/idea/RichPlatformPlugin.xml +++ b/resources/src/idea/RichPlatformPlugin.xml @@ -187,6 +187,8 @@ serviceImplementation="com.intellij.openapi.roots.impl.CompilerProjectExtensionImpl"/> + 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";